PageRenderTime 45ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/exclude-pages/exclude_pages.php

https://github.com/firebelly/Radio-Arte-Wordpress
PHP | 325 lines | 181 code | 31 blank | 113 comment | 29 complexity | 0e77ae4a7974134e47d717093fd586b4 MD5 | raw file
  1. <?php
  2. /*
  3. Plugin Name: Exclude Pages from Navigation
  4. Plugin URI: http://wordpress.org/extend/plugins/exclude-pages/
  5. Description: Provides a checkbox on the editing page which you can check to exclude pages from the primary navigation. IMPORTANT NOTE: This will remove the pages from any "consumer" side page listings, which may not be limited to your page navigation listings.
  6. Version: 1.6
  7. Author: Simon Wheatley
  8. Author URI: http://simonwheatley.co.uk/wordpress/
  9. Copyright 2007 Simon Wheatley
  10. This script is free software; you can redistribute it and/or modify
  11. it under the terms of the GNU General Public License as published by
  12. the Free Software Foundation; either version 3 of the License, or
  13. (at your option) any later version.
  14. This script is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. GNU General Public License for more details.
  18. You should have received a copy of the GNU General Public License
  19. along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. // Full filesystem path to this dir
  22. define('EP_PLUGIN_DIR', dirname(__FILE__));
  23. // Option name for exclusion data
  24. define('EP_OPTION_NAME', 'ep_exclude_pages');
  25. // Separator for the string of IDs stored in the option value
  26. define('EP_OPTION_SEP', ',');
  27. // Take the pages array, and return the pages array without the excluded pages
  28. // Doesn't do this when in the admin area
  29. function ep_exclude_pages( & $pages )
  30. {
  31. // If the URL includes "wp-admin", just return the unaltered list
  32. // This constant, WP_ADMIN, only came into WP on 2007-12-19 17:56:16 rev 6412, i.e. not something we can rely upon unfortunately.
  33. // May as well check it though.
  34. if ( defined( 'WP_ADMIN' ) && WP_ADMIN == true ) return $pages;
  35. // Fall back to checking the URL... let's hope they haven't got a page called wp-admin (probably not)
  36. // SWTODO: Actually, you can create a page with an address of wp-admin (which is then inaccessible), I consider this a bug in WordPress (which I may file a report for, and patch, another time).
  37. if ( strpos( $_SERVER[ 'PHP_SELF' ], 'wp-admin' ) !== false ) return $pages;
  38. $excluded_ids = ep_get_excluded_ids();
  39. $length = count($pages);
  40. // Ensure we catch all descendant pages, so that if a parent
  41. // is hidden, it's children are too.
  42. for ( $i=0; $i<$length; $i++ ) {
  43. $page = & $pages[$i];
  44. // If one of the ancestor pages is excluded, add it to our exclude array
  45. if ( ep_ancestor_excluded( $page, $excluded_ids, $pages ) ) {
  46. // Can't actually delete the pages at the moment,
  47. // it'll screw with our recursive search.
  48. // For the moment, just tag the ID onto our excluded IDs
  49. $excluded_ids[] = $page->ID;
  50. }
  51. }
  52. // Ensure the array only has unique values
  53. $delete_ids = array_unique( $excluded_ids );
  54. // Loop though the $pages array and actually unset/delete stuff
  55. for ( $i=0; $i<$length; $i++ ) {
  56. $page = & $pages[$i];
  57. // If one of the ancestor pages is excluded, add it to our exclude array
  58. if ( in_array( $page->ID, $delete_ids ) ) {
  59. // Finally, delete something(s)
  60. unset( $pages[$i] );
  61. }
  62. }
  63. // Reindex the array, for neatness
  64. // SWFIXME: Is reindexing the array going to create a memory optimisation problem for large arrays of WP post/page objects?
  65. if ( ! is_array( $pages ) ) $pages = (array) $pages;
  66. $pages = array_values( $pages );
  67. return $pages;
  68. }
  69. // Recurse down an ancestor chain, checking if one is excluded
  70. // Returns the ID of the "nearest" excluded ancestor
  71. function ep_ancestor_excluded( & $page, & $excluded_ids, & $pages )
  72. {
  73. $parent = & ep_get_page( $page->post_parent, $pages );
  74. // Is it excluded?
  75. if ( in_array( $parent->ID, $excluded_ids ) ) {
  76. return $parent->ID;
  77. }
  78. // Is it the homepage?
  79. if ( $parent->ID == 0 ) return false;
  80. // Otherwise we have another ancestor to check
  81. return ep_ancestor_excluded( $parent, $excluded_ids, $pages );
  82. }
  83. // Return the portion of the $pages array which refers to the ID passed as $page_id
  84. function ep_get_page( $page_id, & $pages )
  85. {
  86. // PHP 5 would be much nicer here, we could use foreach by reference, ah well.
  87. $length = count($pages);
  88. for ( $i=0; $i<$length; $i++ ) {
  89. $page = & $pages[$i];
  90. if ( $page->ID == $page_id ) return $page;
  91. }
  92. // Unusual.
  93. return false;
  94. }
  95. // Is this page we're editing (defined by global $post_ID var)
  96. // currently NOT excluded (i.e. included),
  97. // returns true if NOT excluded (i.e. included)
  98. // returns false is it IS excluded.
  99. // (Tricky this upside down flag business.)
  100. function ep_this_page_included()
  101. {
  102. global $post_ID;
  103. // New post? Must be included then.
  104. if ( ! $post_ID ) return true;
  105. $excluded_ids = ep_get_excluded_ids();
  106. // If there's no exclusion array, we can return true
  107. if ( empty($excluded_ids) ) return true;
  108. // Check if our page is in the exclusion array
  109. // The bang (!) reverses the polarity [1] of the boolean
  110. return ! in_array( $post_ID, $excluded_ids );
  111. // fn1. (of the neutron flow, ahem)
  112. }
  113. // Check the ancestors for the page we're editing (defined by
  114. // global $post_ID var), return the ID if the nearest one which
  115. // is excluded (if any);
  116. function ep_nearest_excluded_ancestor()
  117. {
  118. global $post_ID, $wpdb;
  119. // New post? No problem.
  120. if ( ! $post_ID ) return false;
  121. $excluded_ids = ep_get_excluded_ids();
  122. // Manually get all the pages, to avoid our own filter.
  123. $sql = "SELECT ID, post_parent FROM $wpdb->posts WHERE post_type = 'page'";
  124. $pages = $wpdb->get_results( $sql );
  125. // Start recursively checking the ancestors
  126. $parent = ep_get_page( $post_ID, $pages );
  127. return ep_ancestor_excluded( $parent, $excluded_ids, $pages );
  128. }
  129. function ep_get_excluded_ids()
  130. {
  131. $exclude_ids_str = get_option( EP_OPTION_NAME );
  132. // No excluded IDs? Return an empty array
  133. if ( empty($exclude_ids_str) ) return array();
  134. // Otherwise, explode the separated string into an array, and return that
  135. return explode( EP_OPTION_SEP, $exclude_ids_str );
  136. }
  137. // This function gets all the exclusions out of the options
  138. // table, updates them, and resaves them in the options table.
  139. // We're avoiding making this a postmeta (custom field) because we
  140. // don't want to have to retrieve meta for every page in order to
  141. // determine if it's to be excluded. Storing all the exclusions in
  142. // one row seems more sensible.
  143. function ep_update_exclusions( $post_ID )
  144. {
  145. // Bang (!) to reverse the polarity of the boolean, turning include into exclude
  146. $exclude_this_page = ! (bool) $_POST['ep_this_page_included'];
  147. // SWTODO: Also check for a hidden var, which confirms that this checkbox was present
  148. // If hidden var not present, then default to including the page in the nav (i.e. bomb out here rather
  149. // than add the page ID to the list of IDs to exclude)
  150. $ctrl_present = (bool) @ $_POST['ep_ctrl_present'];
  151. if ( ! $ctrl_present ) return;
  152. $excluded_ids = ep_get_excluded_ids();
  153. // If we need to EXCLUDE the page from the navigation...
  154. if ( $exclude_this_page ) {
  155. // Add the post ID to the array of excluded IDs
  156. array_push( $excluded_ids, $post_ID );
  157. // De-dupe the array, in case it was there already
  158. $excluded_ids = array_unique( $excluded_ids );
  159. }
  160. // If we need to INCLUDE the page in the navigation...
  161. if ( ! $exclude_this_page ) {
  162. // Find the post ID in the array of excluded IDs
  163. $index = array_search( $post_ID, $excluded_ids );
  164. // Delete any index found
  165. if ( $index !== false ) unset( $excluded_ids[$index] );
  166. }
  167. $excluded_ids_str = implode( EP_OPTION_SEP, $excluded_ids );
  168. ep_set_option( EP_OPTION_NAME, $excluded_ids_str, "Comma separated list of post and page IDs to exclude when returning pages from the get_pages function." );
  169. }
  170. // Take an option, delete it if it exists, then add it.
  171. function ep_set_option( $name, $value, $description )
  172. {
  173. // Delete option
  174. delete_option($name);
  175. // Insert option
  176. add_option($name, $value, $description);
  177. }
  178. // Pre WP2.5
  179. // Add some HTML for the DBX sidebar control into the edit page page
  180. function ep_admin_sidebar()
  181. {
  182. $nearest_excluded_ancestor = ep_nearest_excluded_ancestor();
  183. echo ' <fieldset id="excludepagediv" class="dbx-box">';
  184. echo ' <h3 class="dbx-handle">'.__('Navigation').'</h3>';
  185. echo ' <div class="dbx-content">';
  186. echo ' <label for="ep_this_page_included" class="selectit">';
  187. echo ' <input ';
  188. echo ' type="checkbox" ';
  189. echo ' name="ep_this_page_included" ';
  190. echo ' id="ep_this_page_included" ';
  191. if ( ep_this_page_included() ) echo 'checked="checked"';
  192. echo ' />';
  193. echo ' '.__('Include this page in menus').'</label>';
  194. echo ' <input type="hidden" name="ep_ctrl_present" value="1" />';
  195. if ( $nearest_excluded_ancestor !== false ) {
  196. echo '<div class="exclude_alert">';
  197. echo __('An ancestor of this page is excluded, so this page is too. ');
  198. echo '<a href="page.php?action=edit&amp;post='.$nearest_excluded_ancestor.'"';
  199. echo ' title="'.__('edit the excluded ancestor').'">'.__('Edit ancestor').'</a>.</div>';
  200. }
  201. echo ' </div></fieldset>';
  202. }
  203. // Post WP 2.5
  204. // Add some HTML below the submit box
  205. function ep_admin_sidebar_wp25()
  206. {
  207. $nearest_excluded_ancestor = ep_nearest_excluded_ancestor();
  208. echo ' <div id="excludepagediv" class="new-admin-wp25">';
  209. echo ' <div class="outer"><div class="inner">';
  210. echo ' <label for="ep_this_page_included" class="selectit">';
  211. echo ' <input ';
  212. echo ' type="checkbox" ';
  213. echo ' name="ep_this_page_included" ';
  214. echo ' id="ep_this_page_included" ';
  215. if ( ep_this_page_included() ) echo 'checked="checked"';
  216. echo ' />';
  217. echo ' '.__('Include this page in user menus').'</label>';
  218. echo ' <input type="hidden" name="ep_ctrl_present" value="1" />';
  219. if ( $nearest_excluded_ancestor !== false ) {
  220. echo '<div class="exclude_alert"><em>';
  221. echo __('N.B. An ancestor of this page is excluded, so this page is too. ');
  222. echo '<a href="page.php?action=edit&amp;post='.$nearest_excluded_ancestor.'"';
  223. echo ' title="'.__('edit the excluded ancestor').'">'.__('Edit ancestor').'</a>.</em></div>';
  224. }
  225. echo ' </div><!-- .inner --></div><!-- .outer -->';
  226. echo ' </div><!-- #excludepagediv -->';
  227. }
  228. // Add some CSS into the HEAD element of the admin area
  229. function ep_admin_css()
  230. {
  231. echo ' <style type="text/css" media="screen">';
  232. echo ' div.exclude_alert { font-size: 11px; }';
  233. echo ' .new-admin-wp25 { font-size: 11px; background-color: #fff; }';
  234. echo ' .new-admin-wp25 div.inner { padding: 8px 12px; background-color: #EAF3FA; border: 1px solid #EAF3FA; -moz-border-radius: 3px; -khtml-border-bottom-radius: 3px; -webkit-border-bottom-radius: 3px; border-bottom-radius: 3px; }';
  235. echo ' #ep_admin_meta_box div.inner { padding: inherit; background-color: transparent; border: none; }';
  236. echo ' #ep_admin_meta_box div.inner label { background-color: none; }';
  237. echo ' .new-admin-wp25 div.exclude_alert { padding-top: 5px; }';
  238. echo ' .new-admin-wp25 div.exclude_alert em { font-style: normal; }';
  239. echo ' </style>';
  240. }
  241. // Add our ctrl to the list of controls which AREN'T hidden
  242. function ep_hec_show_dbx( $to_show )
  243. {
  244. array_push( $to_show, 'excludepagediv' );
  245. return $to_show;
  246. }
  247. // PAUSE & RESUME FUNCTIONS
  248. function pause_exclude_pages()
  249. {
  250. remove_filter('get_pages','ep_exclude_pages');
  251. }
  252. function resume_exclude_pages()
  253. {
  254. add_filter('get_pages','ep_exclude_pages');
  255. }
  256. // INIT FUNCTIONS
  257. function ep_init()
  258. {
  259. // Call this function on the get_pages filter
  260. // (get_pages filter appears to only be called on the "consumer" side of WP,
  261. // the admin side must use another function to get the pages. So we're safe to
  262. // remove these pages every time.)
  263. add_filter('get_pages','ep_exclude_pages');
  264. }
  265. function ep_admin_init()
  266. {
  267. // Add panels into the editing sidebar(s)
  268. global $wp_version;
  269. if ( version_compare( $wp_version, '2.7-beta', '>=' ) ) {
  270. add_meta_box('ep_admin_meta_box', __('Exclude Pages'), 'ep_admin_sidebar_wp25', 'page', 'side', 'low');
  271. } else {
  272. add_action('dbx_page_sidebar', 'ep_admin_sidebar'); // Pre WP2.5
  273. add_action('submitpage_box', 'ep_admin_sidebar_wp25'); // Post WP 2.5, pre WP 2.7
  274. }
  275. // Set the exclusion when the post is saved
  276. add_action('save_post', 'ep_update_exclusions');
  277. // Add some CSS to the admin header
  278. add_action('admin_head', 'ep_admin_css');
  279. // Call this function on our very own hec_show_dbx filter
  280. // This filter is harmless to add, even if we don't have the
  281. // Hide Editor Clutter plugin installed as it's using a custom filter
  282. // which won't be called except by the HEC plugin.
  283. // Uncomment to show the control by default
  284. // add_filter('hec_show_dbx','ep_hec_show_dbx');
  285. }
  286. // HOOK IT UP TO WORDPRESS
  287. add_action( 'init', 'ep_init' );
  288. add_action( 'admin_init', 'ep_admin_init' )
  289. ?>