PageRenderTime 47ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/blog/wp-content/plugins/redirection/plugin.php

https://github.com/kennethreitz-archive/wordpress-skeleton
PHP | 625 lines | 286 code | 72 blank | 267 comment | 57 complexity | 676b53652c4d497e70a0e42cbb9c93ae MD5 | raw file
  1. <?php
  2. // ======================================================================================
  3. // This library is free software; you can redistribute it and/or
  4. // modify it under the terms of the GNU Lesser General Public
  5. // License as published by the Free Software Foundation; either
  6. // version 2.1 of the License, or(at your option) any later version.
  7. //
  8. // This library is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. // Lesser General Public License for more details.
  12. // ======================================================================================
  13. // @author John Godley(http://urbangiraffe.com)
  14. // @version 0.2.7
  15. // @copyright Copyright &copy; 2009 John Godley, All Rights Reserved
  16. // ======================================================================================
  17. // 0.1.6 - Corrected WP locale functions
  18. // 0.1.7 - Add phpdoc comments
  19. // 0.1.8 - Support for Admin SSL
  20. // 0.1.9 - URL encoding, defer localization until init
  21. // 0.1.10 - Better URL encoding
  22. // 0.1.11 - Make work in WP 2.0, fix HTTPS issue on IIS
  23. // 0.1.12 - Activation/deactivation actions that take into account the directory
  24. // 0.1.13 - Add realpath function
  25. // 0.1.14 - Add select/checked functions, fix locale loader
  26. // 0.1.15 - Remove dependency on prototype
  27. // 0.1.16 - Add support for homedir in realpath
  28. // 0.1.17 - Added widget class
  29. // 0.1.18 - Expand checked function
  30. // 0.1.19 - Make url() cope with sites with no trailing slash
  31. // 0.1.20 - Change init function to prevent overloading
  32. // 0.1.21 - Make widget work for WP 2.1
  33. // 0.1.22 - Make select work with option groups, RSS compatability fix
  34. // 0.1.23 - Make widget count work better, fix widgets in K2
  35. // 0.1.24 - Make realpath better
  36. // 0.1.25 - Support for new WP2.6 config location
  37. // 0.1.26 - Add description to widget class
  38. // 0.1.27 - Realpath on windows again
  39. // 0.1.28 - Plugin version information
  40. // 0.1.29 - Plugin version for older WP
  41. // 0.1.30 - Add htmlspecialchars for non-support charsets
  42. // 0.2 - WP Coding style
  43. // 0.2.1 - Better HTTPS detection
  44. // 0.2.2 - Plugin settings, base function
  45. // 0.2.3 - More HTTPS
  46. // 0.2.4 - Ajax helper, more compatability functions
  47. // 0.2.5 - _n helper
  48. // 0.2.6 - Compatability functions js_esc
  49. // 0.2.7 - Allow multiple hooks in add_action/add_filter
  50. // ======================================================================================
  51. /**
  52. * Wraps up several useful functions for WordPress plugins and provides a method to separate
  53. * display HTML from PHP code.
  54. *
  55. * <h4>Display Rendering</h4>
  56. * The class uses a similar technique to Ruby On Rails views, whereby the display HTML is kept
  57. * in a separate directory and file from the main code. A display is 'rendered'(sent to the browser)
  58. * or 'captured'(returned to the calling function).
  59. *
  60. * Template files are separated into two areas: admin and user. Admin templates are only for display in
  61. * the WordPress admin interface, while user templates are typically for display on the site(although neither
  62. * of these are enforced). All templates are PHP code, but are referred to without .php extension.
  63. *
  64. * The reason for this separation is that one golden rule of plugin creation is that someone will always want to change
  65. * the formatting and style of your output. Rather than forcing them to modify the plugin(bad), or modify files within
  66. * the plugin(equally bad), the class allows user templates to be overridden with files contained within the theme.
  67. *
  68. * An additional benefit is that it leads to code re-use, especially with regards to Ajax(i.e. your display code can be called from
  69. * many locations)
  70. *
  71. * Template files are located within the 'view' subdirectory of the plugins base(specified when registering the plugin):
  72. *
  73. * <pre>myplugin/view/admin
  74. * myplugin/view/myplugin</pre>
  75. *
  76. * Admin templates are contained within 'admin', and user templates are contained within a directory of the same name as the plugin.
  77. *
  78. * User files can be overridden within the theme by creating a similar directory structure:
  79. *
  80. * <pre>/themes/mytheme/view/myplugin</pre>
  81. *
  82. * The class will first look in the theme and then defaults to the plugin. A plugin should always provide default templates.
  83. *
  84. * <h4>Display Parameters</h4>
  85. * Also similar to Ruby On Rails, when you display a template you must supply the parameters that the template has access to. This tries
  86. * to ensure a very clean separation between code and display. Parameters are supplied as an associative array mapping variable name to variable value.
  87. *
  88. * For example,
  89. *
  90. * array( 'message' => 'Your data was processed', 'items' => 103);
  91. *
  92. * <h4>How it works in practice</h4>
  93. * You create a template file to display how many items have been processed. You store this in 'view/admin/processed.php':
  94. *
  95. * <pre>&lt;p&gt;You processed &lt;?php echo $items ?&gt; items&lt;/p&gt;</pre>
  96. *
  97. * When you want to display this in your plugin you use:
  98. *
  99. * <pre> $this->render_admin( 'processed', array( 'items' => 100));</pre>
  100. *
  101. * @package WordPress base library
  102. * @author John Godley
  103. * @copyright Copyright(C) John Godley
  104. **/
  105. class Redirection_Plugin {
  106. /**
  107. * Plugin name
  108. * @var string
  109. **/
  110. var $plugin_name;
  111. /**
  112. * Plugin 'view' directory
  113. * @var string Directory
  114. **/
  115. var $plugin_base;
  116. /**
  117. * Version URL(if enabled)
  118. * @var string URL
  119. **/
  120. var $version_url;
  121. /**
  122. * Register your plugin with a name and base directory. This <strong>must</strong> be called once.
  123. *
  124. * @param string $name Name of your plugin. Is used to determine the plugin locale domain
  125. * @param string $base Directory containing the plugin's 'view' files.
  126. * @return void
  127. **/
  128. function register_plugin( $name, $base ) {
  129. $this->plugin_base = rtrim( dirname( $base ), '/' );
  130. $this->plugin_name = $name;
  131. $this->add_action( 'init', 'load_locale' );
  132. global $wp_version;
  133. if ( version_compare( $wp_version, '2.8', '<' ) )
  134. $this->add_action( 'admin_menu', 'compatibility_28' );
  135. if ( version_compare( $wp_version, '2.7', '<' ) )
  136. $this->add_action( 'admin_menu', 'compatibility_27' );
  137. if ( version_compare( $wp_version, '2.6', '<' ) )
  138. $this->add_action( 'admin_menu', 'compatibility_26' );
  139. if ( version_compare( $wp_version, '2.5', '<' ) ) {
  140. $this->add_action( 'admin_menu', 'compatibility_25' );
  141. if ( !function_exists( 'is_front_page' ) ) {
  142. function is_front_page ( ) {
  143. return is_home ();
  144. }
  145. }
  146. }
  147. }
  148. function compatibility_28() {
  149. if ( !function_exists( 'esc_js' ) ) {
  150. function esc_js( $text ) {
  151. $safe_text = wp_specialchars( $safe_text, ENT_COMPAT );
  152. $safe_text = preg_replace( '/&#(x)?0*(?(1)27|39);?/i', "'", stripslashes( $safe_text ) );
  153. $safe_text = preg_replace( "/\r?\n/", "\\n", addslashes( $safe_text ) );
  154. return apply_filters( 'js_escape', $safe_text, $text );
  155. }
  156. }
  157. }
  158. function compatibility_25() {
  159. if ( !function_exists( 'check_ajax_referer' ) ) {
  160. function check_ajax_referer( $action = -1, $query_arg = false, $die = true ) {
  161. if ( $query_arg )
  162. $nonce = $_REQUEST[$query_arg];
  163. else
  164. $nonce = $_REQUEST['_ajax_nonce'] ? $_REQUEST['_ajax_nonce'] : $_REQUEST['_wpnonce'];
  165. $result = wp_verify_nonce( $nonce, $action );
  166. if ( $die && false == $result )
  167. die('-1');
  168. do_action('check_ajax_referer', $action, $result);
  169. return $result;
  170. }
  171. }
  172. }
  173. function compatibility_26() {
  174. if ( !function_exists( 'admin_url' ) ) {
  175. function admin_url() {
  176. $url = site_url('wp-admin/', 'admin');
  177. if ( !empty($path) && is_string($path) && strpos($path, '..') === false )
  178. $url .= ltrim($path, '/');
  179. return $url;
  180. }
  181. }
  182. if ( !function_exists( 'is_ssl' ) ) {
  183. function is_ssl() {
  184. if ( isset($_SERVER['HTTPS']) ) {
  185. if ( 'on' == strtolower($_SERVER['HTTPS']) )
  186. return true;
  187. if ( '1' == $_SERVER['HTTPS'] )
  188. return true;
  189. } elseif ( isset($_SERVER['SERVER_PORT']) && ( '443' == $_SERVER['SERVER_PORT'] ) ) {
  190. return true;
  191. }
  192. return false;
  193. }
  194. }
  195. if ( !function_exists( 'site_url' ) ) {
  196. function site_url($path = '', $scheme = null) {
  197. $scheme = ( is_ssl() ? 'https' : 'http' );
  198. $url = str_replace( 'http://', "{$scheme}://", get_option('siteurl') );
  199. if ( !empty($path) && is_string($path) && strpos($path, '..') === false )
  200. $url .= '/' . ltrim($path, '/');
  201. return apply_filters('site_url', $url, $path, $orig_scheme);
  202. }
  203. }
  204. }
  205. /**
  206. * Backwards compatible admin functions
  207. * @return void
  208. **/
  209. function compatibility_27() {
  210. if ( !function_exists( 'screen_icon' ) ) {
  211. function screen_icon() {
  212. }
  213. }
  214. if ( !function_exists( 'add_meta_box' ) ) {
  215. function add_meta_box ( $id, $title, $callback, $page, $context = 'advanced', $priority = 'default', $callback_args=null ) {
  216. add_action( 'dbx_post_advanced', $callback );
  217. }
  218. }
  219. }
  220. /**
  221. * Hook called to change the locale directory
  222. * @return void
  223. **/
  224. function load_locale() {
  225. // Here we manually fudge the plugin locale as WP doesnt allow many options
  226. $locale = get_locale();
  227. if( empty( $locale ) )
  228. $locale = 'en_US';
  229. $mofile = dirname( __FILE__ )."/locale/$locale.mo";
  230. load_textdomain( $this->plugin_name, $mofile );
  231. }
  232. /**
  233. * Register a WordPress action and map it back to the calling object
  234. *
  235. * @param mixed $action Name of the action (single string or array of strings)
  236. * @param string $function Function name (optional, if an array is given for $action then first $action is used as function name)
  237. * @param int $priority WordPress priority(optional)
  238. * @param int $accepted_args Number of arguments the function accepts(optional)
  239. * @return void
  240. **/
  241. function add_action( $actions, $function = '', $priority = 10, $accepted_args = 1 ) {
  242. if ( !is_array( $actions ) )
  243. $actions = array( $actions );
  244. foreach ( $actions AS $action ) {
  245. add_action( $action, array( &$this, $function == '' ? $actions[0] : $function ), $priority, $accepted_args );
  246. }
  247. }
  248. /**
  249. * Register a WordPress filter and map it back to the calling object
  250. *
  251. * @param mixed $action Name of the action (single string or array of strings)
  252. * @param string $function Function name (optional, if an array is given for $action then first $action is used as function name)
  253. * @param int $priority WordPress priority(optional)
  254. * @param int $accepted_args Number of arguments the function accepts(optional)
  255. * @return void
  256. **/
  257. function add_filter( $filters, $function = '', $priority = 10, $accepted_args = 1 ) {
  258. if ( !is_array( $filters ) )
  259. $filters = array( $filters );
  260. foreach ( $filters AS $filter ) {
  261. add_filter( $filter, array( &$this, $function == '' ? $filters[0] : $function ), $priority, $accepted_args );
  262. }
  263. }
  264. /**
  265. * Special activation function that takes into account the plugin directory
  266. *
  267. * @param string $pluginfile The plugin file location(i.e. __FILE__)
  268. * @param string $function Optional function name, or default to 'activate'
  269. * @return void
  270. **/
  271. function register_activation( $pluginfile, $function = '' ) {
  272. add_action( 'activate_'.basename( dirname( $pluginfile ) ).'/'.basename( $pluginfile ), array( &$this, $function == '' ? 'activate' : $function ) );
  273. }
  274. function register_ajax( $action, $function = '', $priority = 10 ) {
  275. add_action( 'wp_ajax_'.$action, array( &$this, $function == '' ? $action : $function ), $priority );
  276. }
  277. /**
  278. * Special deactivation function that takes into account the plugin directory
  279. *
  280. * @param string $pluginfile The plugin file location(i.e. __FILE__)
  281. * @param string $function Optional function name, or default to 'deactivate'
  282. * @return void
  283. **/
  284. function register_deactivation( $pluginfile, $function = '' ) {
  285. add_action( 'deactivate_'.basename( dirname( $pluginfile ) ).'/'.basename( $pluginfile ), array( &$this, $function == '' ? 'deactivate' : $function ) );
  286. }
  287. function register_plugin_settings( $pluginfile, $function = '' ) {
  288. add_action( 'plugin_action_links_'.basename( dirname( $pluginfile ) ).'/'.basename( $pluginfile ), array( &$this, $function == '' ? 'plugin_settings' : $function ), 10, 4 );
  289. }
  290. /**
  291. * Renders an admin section of display code
  292. *
  293. * @param string $ug_name Name of the admin file(without extension)
  294. * @param string $array Array of variable name=>value that is available to the display code(optional)
  295. * @return void
  296. **/
  297. function render_admin( $ug_name, $ug_vars = array() ) {
  298. global $plugin_base;
  299. foreach ( $ug_vars AS $key => $val ) {
  300. $$key = $val;
  301. }
  302. if ( file_exists( "{$this->plugin_base}/view/admin/$ug_name.php" ) )
  303. include "{$this->plugin_base}/view/admin/$ug_name.php";
  304. else
  305. echo "<p>Rendering of admin template {$this->plugin_base}/view/admin/$ug_name.php failed</p>";
  306. }
  307. /**
  308. * Renders a section of user display code. The code is first checked for in the current theme display directory
  309. * before defaulting to the plugin
  310. *
  311. * @param string $ug_name Name of the admin file(without extension)
  312. * @param string $array Array of variable name=>value that is available to the display code(optional)
  313. * @return void
  314. **/
  315. function render( $ug_name, $ug_vars = array() ) {
  316. foreach ( $ug_vars AS $key => $val ) {
  317. $$key = $val;
  318. }
  319. if ( file_exists( TEMPLATEPATH."/view/{$this->plugin_name}/$ug_name.php" ) )
  320. include TEMPLATEPATH."/view/{$this->plugin_name}/$ug_name.php";
  321. elseif ( file_exists( "{$this->plugin_base}/view/{$this->plugin_name}/$ug_name.php" ) )
  322. include "{$this->plugin_base}/view/{$this->plugin_name}/$ug_name.php";
  323. else
  324. echo "<p>Rendering of template $ug_name.php failed</p>";
  325. }
  326. /**
  327. * Renders a section of user display code. The code is first checked for in the current theme display directory
  328. * before defaulting to the plugin
  329. *
  330. * @param string $ug_name Name of the admin file(without extension)
  331. * @param string $array Array of variable name=>value that is available to the display code(optional)
  332. * @return void
  333. **/
  334. function capture( $ug_name, $ug_vars = array() ) {
  335. ob_start();
  336. $this->render( $ug_name, $ug_vars );
  337. $output = ob_get_contents();
  338. ob_end_clean();
  339. return $output;
  340. }
  341. /**
  342. * Captures an admin section of display code
  343. *
  344. * @param string $ug_name Name of the admin file(without extension)
  345. * @param string $array Array of variable name=>value that is available to the display code(optional)
  346. * @return string Captured code
  347. **/
  348. function capture_admin( $ug_name, $ug_vars = array() ) {
  349. ob_start();
  350. $this->render_admin( $ug_name, $ug_vars );
  351. $output = ob_get_contents();
  352. ob_end_clean();
  353. return $output;
  354. }
  355. /**
  356. * Display a standard error message(using CSS ID 'message' and classes 'fade' and 'error)
  357. *
  358. * @param string $message Message to display
  359. * @return void
  360. **/
  361. function render_error( $message ) {
  362. ?>
  363. <div class="fade error" id="message">
  364. <p><?php echo $message ?></p>
  365. </div>
  366. <?php
  367. }
  368. /**
  369. * Display a standard notice(using CSS ID 'message' and class 'updated' ).
  370. * Note that the notice can be made to automatically disappear, and can be removed
  371. * by clicking on it.
  372. *
  373. * @param string $message Message to display
  374. * @param int $timeout Number of seconds to automatically remove the message(optional)
  375. * @return void
  376. **/
  377. function render_message( $message, $timeout = 0 ) {
  378. ?>
  379. <div class="updated" id="message" onclick="this.parentNode.removeChild(this)">
  380. <p><?php echo $message ?></p>
  381. </div>
  382. <?php
  383. }
  384. /**
  385. * Get the plugin's base directory
  386. *
  387. * @return string Base directory
  388. **/
  389. function dir() {
  390. return $this->plugin_base;
  391. }
  392. function base () {
  393. $parts = explode( '?', basename( $_SERVER['REQUEST_URI'] ) );
  394. return $parts[0];
  395. }
  396. /**
  397. * Get a URL to the plugin. Useful for specifying JS and CSS files
  398. *
  399. * For example, <img src="<?php echo $this->url() ?>/myimage.png"/>
  400. *
  401. * @return string URL
  402. **/
  403. function url( $url = '' ) {
  404. if ( $url )
  405. return str_replace( '\\', urlencode( '\\' ), str_replace( '&amp;amp', '&amp;', str_replace( '&', '&amp;', $url ) ) );
  406. $root = ABSPATH;
  407. if ( defined( 'WP_PLUGIN_DIR' ) )
  408. $root = WP_PLUGIN_DIR;
  409. $url = substr( $this->plugin_base, strlen( $this->realpath( $root ) ) );
  410. if ( DIRECTORY_SEPARATOR != '/' )
  411. $url = str_replace( DIRECTORY_SEPARATOR, '/', $url );
  412. if ( defined( 'WP_PLUGIN_URL' ) )
  413. $url = WP_PLUGIN_URL.'/'.ltrim( $url, '/' );
  414. else
  415. $url = get_bloginfo( 'wpurl' ).'/'.ltrim( $url, '/' );
  416. // Do an SSL check - only works on Apache
  417. global $is_IIS;
  418. if ( isset( $_SERVER['HTTPS'] ) && strtolower( $_SERVER['HTTPS'] ) == 'on' && $is_IIS === false )
  419. $url = str_replace( 'http://', 'https://', $url );
  420. return $url;
  421. }
  422. /**
  423. * Version of realpath that will work on systems without realpath
  424. *
  425. * @param string $path The path to canonicalize
  426. * @return string Canonicalized path
  427. **/
  428. function realpath( $path ) {
  429. if ( function_exists( 'realpath' ) && DIRECTORY_SEPARATOR == '/' )
  430. return realpath( $path );
  431. elseif ( DIRECTORY_SEPARATOR == '/' )
  432. {
  433. $path = preg_replace( '/^~/', $_SERVER['DOCUMENT_ROOT'], $path );
  434. // canonicalize
  435. $path = explode( DIRECTORY_SEPARATOR, $path );
  436. $newpath = array();
  437. for ( $i = 0; $i < count( $path ); $i++ ) {
  438. if ( $path[$i] === '' || $path[$i] === '.' )
  439. continue;
  440. if ( $path[$i] === '..' ) {
  441. array_pop( $newpath );
  442. continue;
  443. }
  444. array_push( $newpath, $path[$i] );
  445. }
  446. return DIRECTORY_SEPARATOR.implode( DIRECTORY_SEPARATOR, $newpath );
  447. }
  448. return $path;
  449. }
  450. /**
  451. * Helper function to check a checkbox if the item has been checked
  452. *
  453. * @param mixed $item Checkbox value, or array of checkbox values: field => value
  454. * @param string $field Fieldname, if array is given for $item
  455. * @return void
  456. **/
  457. function checked( $item, $field = '' ) {
  458. if ( $field && is_array( $item ) ) {
  459. if ( isset( $item[$field] ) && $item[$field] )
  460. echo ' checked="checked"';
  461. }
  462. elseif ( !empty( $item ) )
  463. echo ' checked="checked"';
  464. }
  465. /**
  466. * Helper function to display a dropdown select box
  467. *
  468. * @param array $items Associative array of: fieldname => label
  469. * @param string $default Default fieldname to select
  470. * @return void
  471. **/
  472. function select( $items, $default = '' ) {
  473. if ( count( $items ) > 0 ) {
  474. foreach ( $items AS $key => $value ) {
  475. if ( is_array( $value ) ) {
  476. echo '<optgroup label="'.$key.'">';
  477. foreach ( $value AS $sub => $subvalue ) {
  478. echo '<option value="'.$sub.'"'.( $sub == $default ? ' selected="selected"' : '' ).'>'.$subvalue.'</option>';
  479. }
  480. echo '</optgroup>';
  481. }
  482. else
  483. echo '<option value="'.$key.'"'.( $key == $default ? ' selected="selected"' : '' ).'>'.$value.'</option>';
  484. }
  485. }
  486. }
  487. /**
  488. * Expanded version of htmlspecialchars which detects the blog encoding and runs iconv on any encoding that is not supported by htmlspecialchars
  489. *
  490. * @param string $text Text to run htmlspecialchars on
  491. * @return void
  492. **/
  493. function specialchars( $text ) {
  494. $charset = get_option( 'blog_charset' );
  495. if ( $charset != 'UTF-8' && function_exists( 'iconv' ) && !in_array( $charset, array( 'ISO-8859-1', 'ISO-8859-15', 'cp1251', 'cp1252', 'KOI8-R', 'BIG5', 'GB2312', 'Shift_JIS', 'EUC-JP' ) ) )
  496. return iconv( 'UTF-8//IGNORE', $charset, htmlspecialchars( iconv( $charset, 'UTF-8//IGNORE', $text ) ) );
  497. return htmlspecialchars( $text, ENT_COMPAT, $charset );
  498. }
  499. /**
  500. * Special version of strlen that runs mb_strlen if blog encoding is not UTF-8
  501. *
  502. * @param string $name Name of your plugin. Is used to determine the plugin locale domain
  503. * @param string $base Directory containing the plugin's 'view' files.
  504. * @return void
  505. **/
  506. function strlen( $text ) {
  507. $charset = get_option( 'blog_charset' );
  508. if ( $charset != 'UTF-8' && function_exists( 'mb_strlen' ) )
  509. return mb_strlen( $text );
  510. return strlen( $text );
  511. }
  512. /**
  513. * Returns version of plugin
  514. *
  515. * @return string Version
  516. **/
  517. function version() {
  518. $plugin_data = implode( '', file( $this->plugin_base ) );
  519. if ( preg_match( '|Version:(.*)|i', $plugin_data, $version ) )
  520. return trim( $version[1] );
  521. return '';
  522. }
  523. }
  524. /**
  525. * Debug helper, borrowed from CakePHP, that displays a print_r inside <pre></pre> tags
  526. *
  527. * @param string $name Name of your plugin. Is used to determine the plugin locale domain
  528. * @param string $base Directory containing the plugin's 'view' files.
  529. * @return void
  530. **/
  531. if ( !function_exists( 'pr' ) ) {
  532. function pr( $thing ) {
  533. echo '<pre>';
  534. print_r( $thing );
  535. echo '</pre>';
  536. }
  537. }
  538. if ( !function_exists( '_n' ) ) {
  539. function _n($single, $plural, $number, $domain = 'default') {
  540. return __ngettext($single, $plural, $number, $domain = 'default');
  541. }
  542. }