1 <?php
2 /**
3 * Admin Page Framework
4 *
5 * http://en.michaeluno.jp/admin-page-framework/
6 * Copyright (c) 2013-2014 Michael Uno; Licensed MIT
7 *
8 */
9 if ( ! class_exists( 'AdminPageFramework_PostType' ) ) :
10 /**
11 * Provides methods for registering custom post types.
12 *
13 * <h2>Hooks</h2>
14 * <p>The class automatically creates WordPress action and filter hooks associated with the class methods.
15 * The class methods corresponding to the name of the below actions and filters can be extended to modify the page output. Those methods are the callbacks of the filters and actions.</p>
16 * <h3>Methods and Action Hooks</h3>
17 * <ul>
18 * <li><strong>start_ + extended class name</strong> – triggered at the end of the class constructor.</li>
19 * </ul>
20 * <h3>Methods and Filter Hooks</h3>
21 * <ul>
22 * <li><strong>cell_{post type slug}_{column key}</strong> – receives the output string for the listing table of the custom post type's post. The first parameter: output string. The second parameter: the post ID.</li>
23 * <li><strong>columns_{post type slug}</strong> – receives the array containing the header columns for the listing table of the custom post type's post. The first parameter: the header columns container array.</li>
24 * <li><strong>sortable_columns_{post type slug}</strong> – receives the array containing the sortable header column array for the listing table of the custom post type's post. The first parameter: the sortable header columns container array.</li>
25 * </ul>
26 * <h3>Remarks</h3>
27 * <p>The slugs must not contain a dot(.) or a hyphen(-) since it is used in the callback method name.</p>
28 *
29 * @abstract
30 * @since 2.0.0
31 * @package AdminPageFramework
32 * @subpackage PostType
33 */
34 abstract class AdminPageFramework_PostType {
35
36 // Objects
37 /**
38 * @since 2.0.0
39 * @internal
40 */
41 protected $oUtil;
42 /**
43 * @since 2.0.0
44 * @internal
45 */
46 protected $oLink;
47
48 /**
49 * The constructor of the class object.
50 *
51 * Registers necessary hooks and sets up internal properties.
52 *
53 * <h4>Example</h4>
54 * <code>new APF_PostType(
55 * 'apf_posts', // post type slug
56 * array( // argument - for the array structure, refer to http://codex.wordpress.org/Function_Reference/register_post_type#Arguments
57 * 'labels' => array(
58 * 'name' => 'Admin Page Framework',
59 * 'singular_name' => 'Admin Page Framework',
60 * 'add_new' => 'Add New',
61 * 'add_new_item' => 'Add New APF Post',
62 * 'edit' => 'Edit',
63 * 'edit_item' => 'Edit APF Post',
64 * 'new_item' => 'New APF Post',
65 * 'view' => 'View',
66 * 'view_item' => 'View APF Post',
67 * 'search_items' => 'Search APF Post',
68 * 'not_found' => 'No APF Post found',
69 * 'not_found_in_trash' => 'No APF Post found in Trash',
70 * 'parent' => 'Parent APF Post'
71 * ),
72 * 'public' => true,
73 * 'menu_position' => 110,
74 * 'supports' => array( 'title' ),
75 * 'taxonomies' => array( '' ),
76 * 'menu_icon' => null,
77 * 'has_archive' => true,
78 * 'show_admin_column' => true, // for custom taxonomies
79 * )
80 * );</code>
81 * @since 2.0.0
82 * @since 2.1.6 Added the $sTextDomain parameter.
83 * @see http://codex.wordpress.org/Function_Reference/register_post_type#Arguments
84 * @param string The post type slug.
85 * @param array The <a href="http://codex.wordpress.org/Function_Reference/register_post_type#Arguments">argument array</a> passed to register_post_type().
86 * @param string The path of the caller script. This is used to retrieve the script information to insert it into the footer. If not set, the framework tries to detect it.
87 * @param string The text domain of the caller script.
88 * @return void
89 */
90 public function __construct( $sPostType, $aArgs=array(), $sCallerPath=null, $sTextDomain='admin-page-framework' ) {
91
92 // Objects
93 $this->oUtil = new AdminPageFramework_WPUtility;
94 $this->oProp = new AdminPageFramework_Property_PostType(
95 $this,
96 $sCallerPath ? trim( $sCallerPath ) : AdminPageFramework_Utility::getCallerScriptPath( __FILE__ ), // this is important to attempt to find the caller script path here when separating the library into multiple files.
97 get_class( $this ) // class name
98 );
99 $this->oMsg = AdminPageFramework_Message::instantiate( $sTextDomain );
100 $this->oHeadTag = new AdminPageFramework_HeadTag_PostType( $this->oProp );
101 $this->oPageLoadInfo = AdminPageFramework_PageLoadInfo_PostType::instantiate( $this->oProp, $this->oMsg );
102 $this->oDebug = new AdminPageFramework_Debug;
103
104 // Properties
105 $this->oProp->sPostType = $this->oUtil->sanitizeSlug( $sPostType );
106 $this->oProp->aPostTypeArgs = $aArgs; // for the argument array structure, refer to http://codex.wordpress.org/Function_Reference/register_post_type#Arguments
107 $this->oProp->aColumnHeaders = array(
108 'cb' => '<input type="checkbox" />', // Checkbox for bulk actions.
109 'title' => $this->oMsg->__( 'title' ), // Post title. Includes "edit", "quick edit", "trash" and "view" links. If $mode (set from $_REQUEST['mode']) is 'excerpt', a post excerpt is included between the title and links.
110 'author' => $this->oMsg->__( 'author' ), // Post author.
111 // 'categories' => $this->oMsg->__( 'categories' ), // Categories the post belongs to.
112 // 'tags' => $this->oMsg->__( 'tags' ), // Tags for the post.
113 'comments' => '<div class="comment-grey-bubble"></div>', // Number of pending comments.
114 'date' => $this->oMsg->__( 'date' ), // The date and publish status of the post.
115 );
116
117 add_action( 'init', array( $this, '_replyToRegisterPostType' ), 999 ); // this is loaded in the front-end as well so should not be admin_init. Also "if ( is_admin() )" should not be used either.
118
119 if ( $this->oProp->sPostType != '' && $this->oProp->bIsAdmin ) {
120
121 add_action( 'admin_enqueue_scripts', array( $this, '_replyToDisableAutoSave' ) );
122
123 // For table columns
124 add_filter( "manage_{$this->oProp->sPostType}_posts_columns", array( $this, '_replyToSetColumnHeader' ) );
125 add_filter( "manage_edit-{$this->oProp->sPostType}_sortable_columns", array( $this, '_replyToSetSortableColumns' ) );
126 add_action( "manage_{$this->oProp->sPostType}_posts_custom_column", array( $this, '_replyToSetColumnCell' ), 10, 2 );
127
128 // For filters
129 add_action( 'restrict_manage_posts', array( $this, '_replyToAddAuthorTableFilter' ) );
130 add_action( 'restrict_manage_posts', array( $this, '_replyToAddTaxonomyTableFilter' ) );
131 add_filter( 'parse_query', array( $this, '_replyToSetTableFilterQuery' ) );
132
133 // Style
134 add_action( 'admin_head', array( $this, '_replyToAddStyle' ) );
135
136 // Links
137 $this->oLink = new AdminPageFramework_Link_PostType( $this->oProp, $this->oMsg );
138
139 add_action( 'wp_loaded', array( $this, 'setUp' ) );
140 }
141
142 $this->oUtil->addAndDoAction( $this, "start_{$this->oProp->sClassName}" );
143
144 }
145
146 /*
147 * Extensible methods
148 */
149
150 /**
151 * The method for all necessary set-ups.
152 *
153 * <h4>Example</h4>
154 * <code>public function setUp() {
155 * $this->setAutoSave( false );
156 * $this->setAuthorTableFilter( true );
157 * $this->addTaxonomy(
158 * 'sample_taxonomy', // taxonomy slug
159 * array( // argument - for the argument array keys, refer to : http://codex.wordpress.org/Function_Reference/register_taxonomy#Arguments
160 * 'labels' => array(
161 * 'name' => 'Genre',
162 * 'add_new_item' => 'Add New Genre',
163 * 'new_item_name' => "New Genre"
164 * ),
165 * 'show_ui' => true,
166 * 'show_tagcloud' => false,
167 * 'hierarchical' => true,
168 * 'show_admin_column' => true,
169 * 'show_in_nav_menus' => true,
170 * 'show_table_filter' => true, // framework specific key
171 * 'show_in_sidebar_menus' => false, // framework specific key
172 * )
173 * );
174 * }</code>
175 *
176 * @abstract
177 * @since 2.0.0
178 * @remark The user should override this method in their class definition.
179 * @remark A callback for the <em>wp_loaded</em> hook.
180 */
181 public function setUp() {}
182
183 /*
184 * Head Tag Methods
185 */
186 /**
187 * Enqueues styles by page slug and tab slug.
188 *
189 * @since 3.0.0
190 * @return array An array holding the handle IDs of queued items.
191 */
192 public function enqueueStyles( $aSRCs, $aCustomArgs=array() ) {
193 return $this->oHeadTag->_enqueueStyles( $aSRCs, array( $this->oProp->sPostType ), $aCustomArgs );
194 }
195 /**
196 * Enqueues a style by page slug and tab slug.
197 *
198 * @since 3.0.0
199 * @see http://codex.wordpress.org/Function_Reference/wp_enqueue_style
200 * @param string The URL of the stylesheet to enqueue, the absolute file path, or the relative path to the root directory of WordPress. Example: '/css/mystyle.css'.
201 * @param array (optional) The argument array for more advanced parameters.
202 * <h4>Custom Argument Array</h4>
203 * <ul>
204 * <li><strong>handle_id</strong> - ( optional, string ) The handle ID of the stylesheet.</li>
205 * <li><strong>dependencies</strong> - ( optional, array ) The dependency array. For more information, see <a href="http://codex.wordpress.org/Function_Reference/wp_enqueue_style">codex</a>.</li>
206 * <li><strong>version</strong> - ( optional, string ) The stylesheet version number.</li>
207 * <li><strong>media</strong> - ( optional, string ) the description of the field which is inserted into after the input field tag.</li>
208 * </ul>
209 * @return string The script handle ID. If the passed url is not a valid url string, an empty string will be returned.
210 */
211 public function enqueueStyle( $sSRC, $aCustomArgs=array() ) {
212 return $this->oHeadTag->_enqueueStyle( $sSRC, array( $this->oProp->sPostType ), $aCustomArgs );
213 }
214 /**
215 * Enqueues scripts by page slug and tab slug.
216 *
217 * @since 3.0.0
218 * @return array An array holding the handle IDs of queued items.
219 */
220 public function enqueueScripts( $aSRCs, $aCustomArgs=array() ) {
221 return $this->oHeadTag->_enqueueScripts( $aSRCs, array( $this->oProp->sPostType ), $aCustomArgs );
222 }
223 /**
224 * Enqueues a script by page slug and tab slug.
225 *
226 * <h4>Example</h4>
227 * <code>$this->enqueueScript(
228 * plugins_url( 'asset/js/test.js' , __FILE__ ), // source url or path
229 * array(
230 * 'handle_id' => 'my_script', // this handle ID also is used as the object name for the translation array below.
231 * 'translation' => array(
232 * 'a' => 'hello world!',
233 * 'style_handle_id' => $sStyleHandle, // check the enqueued style handle ID here.
234 * ),
235 * )
236 * );</code>
237 *
238 * @since 3.0.0
239 * @see http://codex.wordpress.org/Function_Reference/wp_enqueue_script
240 * @param string The URL of the stylesheet to enqueue, the absolute file path, or the relative path to the root directory of WordPress. Example: '/js/myscript.js'.
241 * @param array (optional) The argument array for more advanced parameters.
242 * <h4>Custom Argument Array</h4>
243 * <ul>
244 * <li><strong>handle_id</strong> - ( optional, string ) The handle ID of the script.</li>
245 * <li><strong>dependencies</strong> - ( optional, array ) The dependency array. For more information, see <a href="http://codex.wordpress.org/Function_Reference/wp_enqueue_script">codex</a>.</li>
246 * <li><strong>version</strong> - ( optional, string ) The stylesheet version number.</li>
247 * <li><strong>translation</strong> - ( optional, array ) The translation array. The handle ID will be used for the object name.</li>
248 * <li><strong>in_footer</strong> - ( optional, boolean ) Whether to enqueue the script before <code></head ></code> or before <code></body></code> Default: <em>false</em>.</li>
249 * </ul>
250 * @return string The script handle ID. If the passed url is not a valid url string, an empty string will be returned.
251 */
252 public function enqueueScript( $sSRC, $aCustomArgs=array() ) {
253 return $this->oHeadTag->_enqueueScript( $sSRC, array( $this->oProp->sPostType ), $aCustomArgs );
254 }
255
256 /*
257 * Front-end methods
258 */
259 /**
260 * Enables or disables the auto-save feature in the custom post type's post submission page.
261 *
262 * <h4>Example</h4>
263 * <code>$this->setAutoSave( false );
264 * </code>
265 *
266 * @since 2.0.0
267 * @param boolean If true, it enables the auto-save; otherwise, it disables it.
268 * return void
269 */
270 protected function setAutoSave( $bEnableAutoSave=True ) {
271 $this->oProp->bEnableAutoSave = $bEnableAutoSave;
272 }
273
274 /**
275 * Adds a custom taxonomy to the class post type.
276 * <h4>Example</h4>
277 * <code>$this->addTaxonomy(
278 * 'sample_taxonomy', // taxonomy slug
279 * array( // argument
280 * 'labels' => array(
281 * 'name' => 'Genre',
282 * 'add_new_item' => 'Add New Genre',
283 * 'new_item_name' => "New Genre"
284 * ),
285 * 'show_ui' => true,
286 * 'show_tagcloud' => false,
287 * 'hierarchical' => true,
288 * 'show_admin_column' => true,
289 * 'show_in_nav_menus' => true,
290 * 'show_table_filter' => true, // framework specific key
291 * 'show_in_sidebar_menus' => false, // framework specific key
292 * )
293 * );</code>
294 *
295 * @see http://codex.wordpress.org/Function_Reference/register_taxonomy#Arguments
296 * @since 2.0.0
297 * @param string The taxonomy slug.
298 * @param array The taxonomy argument array passed to the second parameter of the <a href="http://codex.wordpress.org/Function_Reference/register_taxonomy#Arguments">register_taxonomy()</a> function.
299 * @return void
300 */
301 protected function addTaxonomy( $sTaxonomySlug, $aArgs ) {
302
303 $sTaxonomySlug = $this->oUtil->sanitizeSlug( $sTaxonomySlug );
304 $this->oProp->aTaxonomies[ $sTaxonomySlug ] = $aArgs;
305 if ( isset( $aArgs['show_table_filter'] ) && $aArgs['show_table_filter'] )
306 $this->oProp->aTaxonomyTableFilters[] = $sTaxonomySlug;
307 if ( isset( $aArgs['show_in_sidebar_menus'] ) && ! $aArgs['show_in_sidebar_menus'] )
308 $this->oProp->aTaxonomyRemoveSubmenuPages[ "edit-tags.php?taxonomy={$sTaxonomySlug}&post_type={$this->oProp->sPostType}" ] = "edit.php?post_type={$this->oProp->sPostType}";
309
310 if ( count( $this->oProp->aTaxonomyTableFilters ) == 1 )
311 add_action( 'init', array( $this, '_replyToRegisterTaxonomies' ) ); // the hook should not be admin_init because taxonomies need to be accessed in regular pages.
312 if ( count( $this->oProp->aTaxonomyRemoveSubmenuPages ) == 1 )
313 add_action( 'admin_menu', array( $this, '_replyToRemoveTexonomySubmenuPages' ), 999 );
314
315 }
316
317 /**
318 * Sets whether the author drop-down filter is enabled/disabled in the post type post list table.
319 *
320 * <h4>Example</h4>
321 * <code>$this->setAuthorTableFilter( true );
322 * </code>
323 *
324 * @since 2.0.0
325 * @param boolean If true, it enables the author filter; otherwise, it disables it.
326 * @return void
327 */
328 protected function setAuthorTableFilter( $bEnableAuthorTableFileter=false ) {
329 $this->oProp->bEnableAuthorTableFileter = $bEnableAuthorTableFileter;
330 }
331
332 /**
333 * Sets the post type arguments.
334 *
335 * This is only necessary if it is not set in the constructor.
336 *
337 * @since 2.0.0
338 * @see http://codex.wordpress.org/Function_Reference/register_post_type#Arguments
339 * @param array The <a href="http://codex.wordpress.org/Function_Reference/register_post_type#Arguments">array of arguments</a> to be passed to the second parameter of the <em>register_post_type()</em> function.
340 * @return void
341 */
342 protected function setPostTypeArgs( $aArgs ) {
343 $this->oProp->aPostTypeArgs = $aArgs;
344 }
345
346 /**
347 * Sets the given HTML text into the footer on the left hand side.
348 *
349 * <h4>Example</h4>
350 * <code>$this->setFooterInfoLeft( '<br />Custom Text on the left hand side.' );
351 * </code>
352 *
353 * @since 2.0.0
354 * @param string The HTML code to insert.
355 * @param boolean If true, the text will be appended; otherwise, it will replace the default text.
356 * @return void
357 */
358 protected function setFooterInfoLeft( $sHTML, $bAppend=true ) {
359 if ( isset( $this->oLink ) ) // check if the object is set to ensure it won't trigger a warning message in non-admin pages.
360 $this->oLink->aFooterInfo['sLeft'] = $bAppend
361 ? $this->oLink->aFooterInfo['sLeft'] . $sHTML
362 : $sHTML;
363 }
364
365 /**
366 * Sets the given HTML text into the footer on the right hand side.
367 *
368 * <h4>Example</h4>
369 * <code>$this->setFooterInfoRight( '<br />Custom Text on the right hand side.' );
370 * </code>
371 *
372 * @since 2.0.0
373 * @param string The HTML code to insert.
374 * @param boolean If true, the text will be appended; otherwise, it will replace the default text.
375 * @return void
376 */
377 protected function setFooterInfoRight( $sHTML, $bAppend=true ) {
378 if ( isset( $this->oLink ) ) // check if the object is set to ensure it won't trigger a warning message in non-admin pages.
379 $this->oLink->aFooterInfo['sRight'] = $bAppend
380 ? $this->oLink->aFooterInfo['sRight'] . $sHTML
381 : $sHTML;
382 }
383
384 /**
385 * Sets the given screen icon to the post type screen icon.
386 *
387 * @since 2.1.3
388 * @since 2.1.6 The $sSRC parameter can accept file path.
389 */
390 private function getStylesForPostTypeScreenIcon( $sSRC ) {
391
392 $sNone = 'none';
393
394 $sSRC = $this->oUtil->resolveSRC( $sSRC );
395
396 return "#post-body-content {
397 margin-bottom: 10px;
398 }
399 #edit-slug-box {
400 display: {$sNone};
401 }
402 #icon-edit.icon32.icon32-posts-" . $this->oProp->sPostType . " {
403 background: url('" . $sSRC . "') no-repeat;
404 background-size: 32px 32px;
405 }
406 ";
407
408 }
409
410 /*
411 * Callback functions
412 */
413
414 /**
415 * Defines the column header items in the custom post listing table.
416 *
417 * This method should be overridden by the user in their extended class.
418 *
419 * @since 2.0.0
420 * @remark A callback for the <em>manage_{post type}_post)_columns</em> hook.
421 * @return void
422 * @internal
423 */
424 public function _replyToSetColumnHeader( $aHeaderColumns ) {
425 return $this->oUtil->addAndApplyFilter( $this, "columns_{$this->oProp->sPostType}", $aHeaderColumns );
426 }
427
428 /**
429 * Defines the sortable column items in the custom post listing table.
430 *
431 * This method should be overridden by the user in their extended class.
432 *
433 * @since 2.0.0
434 * @remark A callback for the <em>manage_edit-{post type}_sortable_columns</em> hook.
435 * @internal
436 */
437 public function _replyToSetSortableColumns( $aColumns ) {
438 return $this->oUtil->addAndApplyFilter( $this, "sortable_columns_{$this->oProp->sPostType}", $aColumns );
439 }
440
441 /**
442 * Adds the script.
443 * @internal
444 */
445 public function _replyToAddStyle() {
446
447 if ( ! isset( $_GET['post_type'] ) || $_GET['post_type'] != $this->oProp->sPostType )
448 return;
449
450 // If the screen icon url is specified
451 if ( isset( $this->oProp->aPostTypeArgs['screen_icon'] ) && $this->oProp->aPostTypeArgs['screen_icon'] )
452 $this->oProp->sStyle .= $this->getStylesForPostTypeScreenIcon( $this->oProp->aPostTypeArgs['screen_icon'] );
453
454 $this->oProp->sStyle = $this->oUtil->addAndApplyFilters( $this, "style_{$this->oProp->sClassName}", $this->oProp->sStyle );
455
456 // Print out the filtered styles.
457 if ( ! empty( $this->oProp->sStyle ) )
458 echo "<style type='text/css' id='admin-page-framework-style-post-type'>"
459 . $this->oProp->sStyle
460 . "</style>";
461
462 }
463
464 /**
465 * Registers the post type passed to the constructor.
466 *
467 * @internal
468 */
469 public function _replyToRegisterPostType() {
470
471 register_post_type( $this->oProp->sPostType, $this->oProp->aPostTypeArgs );
472
473 $bIsPostTypeSet = get_option( "post_type_rules_flased_{$this->oProp->sPostType}" );
474 if ( $bIsPostTypeSet !== true ) {
475 flush_rewrite_rules( false );
476 update_option( "post_type_rules_flased_{$this->oProp->sPostType}", true );
477 }
478
479 }
480
481 /**
482 * Registerd the set custom taxonomies.
483 *
484 * @internal
485 */
486 public function _replyToRegisterTaxonomies() {
487
488 foreach( $this->oProp->aTaxonomies as $sTaxonomySlug => $aArgs )
489 register_taxonomy(
490 $sTaxonomySlug,
491 $this->oProp->sPostType,
492 $aArgs // for the argument array keys, refer to: http://codex.wordpress.org/Function_Reference/register_taxonomy#Arguments
493 );
494
495 }
496
497 /**
498 * Removes taxonomy menu items from the sidebar menu.
499 *
500 * @internal
501 */
502 public function _replyToRemoveTexonomySubmenuPages() {
503
504 foreach( $this->oProp->aTaxonomyRemoveSubmenuPages as $sSubmenuPageSlug => $sTopLevelPageSlug )
505 remove_submenu_page( $sTopLevelPageSlug, $sSubmenuPageSlug );
506
507 }
508
509 /**
510 * Disables the WordPress's built-in auto-save functionality.
511 *
512 * @internal
513 */
514 public function _replyToDisableAutoSave() {
515
516 if ( $this->oProp->bEnableAutoSave ) return;
517 if ( $this->oProp->sPostType != get_post_type() ) return;
518 wp_dequeue_script( 'autosave' );
519
520 }
521
522 /**
523 * Adds a drop-down list to filter posts by author, placed above the post type listing table.
524 *
525 * @internal
526 */
527 public function _replyToAddAuthorTableFilter() {
528
529 if ( ! $this->oProp->bEnableAuthorTableFileter ) return;
530
531 if ( ! ( isset( $_GET['post_type'] ) && post_type_exists( $_GET['post_type'] )
532 && in_array( strtolower( $_GET['post_type'] ), array( $this->oProp->sPostType ) ) ) )
533 return;
534
535 wp_dropdown_users( array(
536 'show_option_all' => 'Show all Authors',
537 'show_option_none' => false,
538 'name' => 'author',
539 'selected' => ! empty( $_GET['author'] ) ? $_GET['author'] : 0,
540 'include_selected' => false
541 ));
542
543 }
544
545 /**
546 * Adds drop-down lists to filter posts by added taxonomies, placed above the post type listing table.
547 *
548 * @internal
549 */
550 public function _replyToAddTaxonomyTableFilter() {
551
552 if ( $GLOBALS['typenow'] != $this->oProp->sPostType ) return;
553
554 // If there is no post added to the post type, do nothing.
555 $oPostCount = wp_count_posts( $this->oProp->sPostType );
556 if ( $oPostCount->publish + $oPostCount->future + $oPostCount->draft + $oPostCount->pending + $oPostCount->private + $oPostCount->trash == 0 )
557 return;
558
559 foreach ( get_object_taxonomies( $GLOBALS['typenow'] ) as $sTaxonomySulg ) {
560
561 if ( ! in_array( $sTaxonomySulg, $this->oProp->aTaxonomyTableFilters ) ) continue;
562
563 $oTaxonomy = get_taxonomy( $sTaxonomySulg );
564
565 // If there is no added term, skip.
566 if ( wp_count_terms( $oTaxonomy->name ) == 0 ) continue;
567
568 // This function will echo the drop down list based on the passed array argument.
569 wp_dropdown_categories( array(
570 'show_option_all' => $this->oMsg->__( 'show_all' ) . ' ' . $oTaxonomy->label,
571 'taxonomy' => $sTaxonomySulg,
572 'name' => $oTaxonomy->name,
573 'orderby' => 'name',
574 'selected' => intval( isset( $_GET[ $sTaxonomySulg ] ) ),
575 'hierarchical' => $oTaxonomy->hierarchical,
576 'show_count' => true,
577 'hide_empty' => false,
578 'hide_if_empty' => false,
579 'echo' => true, // this make the function print the output
580 ) );
581
582 }
583 }
584
585 /**
586 *
587 *
588 * @internal
589 */
590 public function _replyToSetTableFilterQuery( $oQuery=null ) {
591
592 if ( 'edit.php' != $GLOBALS['pagenow'] ) return $oQuery;
593
594 if ( ! isset( $GLOBALS['typenow'] ) ) return $oQuery;
595
596 foreach ( get_object_taxonomies( $GLOBALS['typenow'] ) as $sTaxonomySlug ) {
597
598 if ( ! in_array( $sTaxonomySlug, $this->oProp->aTaxonomyTableFilters ) ) continue;
599
600 $sVar = &$oQuery->query_vars[ $sTaxonomySlug ];
601 if ( ! isset( $sVar ) ) continue;
602
603 $oTerm = get_term_by( 'id', $sVar, $sTaxonomySlug );
604 if ( is_object( $oTerm ) )
605 $sVar = $oTerm->slug;
606
607 }
608 return $oQuery;
609
610 }
611
612 /**
613 *
614 * @internal
615 */
616 public function _replyToSetColumnCell( $sColumnTitle, $iPostID ) {
617
618 // cell_{post type}_{custom column key}
619 echo $this->oUtil->addAndApplyFilter( $this, "cell_{$this->oProp->sPostType}_{$sColumnTitle}", $sCell='', $iPostID );
620
621 }
622
623 /**
624 * Redirects undefined callback methods or to the appropriate methods.
625 *
626 * @internal
627 */
628 public function __call( $sMethodName, $aArgs=null ) {
629 if ( substr( $sMethodName, 0, strlen( "cell_" ) ) == "cell_" ) return $aArgs[0];
630 if ( substr( $sMethodName, 0, strlen( "sortable_columns_" ) ) == "sortable_columns_" ) return $aArgs[0];
631 if ( substr( $sMethodName, 0, strlen( "columns_" ) ) == "columns_" ) return $aArgs[0];
632 if ( substr( $sMethodName, 0, strlen( "style_ie_common_" ) )== "style_ie_common_" ) return $aArgs[0];
633 if ( substr( $sMethodName, 0, strlen( "style_common_" ) )== "style_common_" ) return $aArgs[0];
634 if ( substr( $sMethodName, 0, strlen( "style_ie_" ) )== "style_ie_" ) return $aArgs[0];
635 if ( substr( $sMethodName, 0, strlen( "style_" ) )== "style_" ) return $aArgs[0];
636 }
637
638 }
639 endif;