PageRenderTime 40ms CodeModel.GetById 1ms RepoModel.GetById 1ms app.codeStats 0ms

/wp-content/plugins/posts-to-posts/scb/AdminPage.php

https://gitlab.com/blueprintmrk/bladencountyrecords
PHP | 444 lines | 275 code | 108 blank | 61 comment | 42 complexity | 65a5da925329e21056f44a5d5683f436 MD5 | raw file
  1. <?php
  2. // Administration page base class
  3. abstract class scbAdminPage {
  4. /** Page args
  5. * $page_title string (mandatory)
  6. * $parent (string) (default: options-general.php)
  7. * $capability (string) (default: 'manage_options')
  8. * $menu_title (string) (default: $page_title)
  9. * $page_slug (string) (default: sanitized $page_title)
  10. * $toplevel (string) If not empty, will create a new top level menu (for expected values see http://codex.wordpress.org/Administration_Menus#Using_add_submenu_page)
  11. * - $icon_url (string) URL to an icon for the top level menu
  12. * - $position (int) Position of the toplevel menu (caution!)
  13. * $screen_icon (string) The icon type to use in the screen header
  14. * $nonce string (default: $page_slug)
  15. * $action_link (string|bool) Text of the action link on the Plugins page (default: 'Settings')
  16. * $admin_action_priority int The priority that the admin_menu action should be executed at (default: 10)
  17. */
  18. protected $args;
  19. // URL to the current plugin directory.
  20. // Useful for adding css and js files
  21. protected $plugin_url;
  22. // Created at page init
  23. protected $pagehook;
  24. // scbOptions object holder
  25. // Normally, it's used for storing formdata
  26. protected $options;
  27. protected $option_name;
  28. // l10n
  29. protected $textdomain;
  30. // ____________REGISTRATION COMPONENT____________
  31. private static $registered = array();
  32. static function register( $class, $file, $options = null ) {
  33. if ( isset( self::$registered[$class] ) )
  34. return false;
  35. self::$registered[$class] = array( $file, $options );
  36. add_action( '_admin_menu', array( __CLASS__, '_pages_init' ) );
  37. return true;
  38. }
  39. static function replace( $old_class, $new_class ) {
  40. if ( ! isset( self::$registered[$old_class] ) )
  41. return false;
  42. self::$registered[$new_class] = self::$registered[$old_class];
  43. unset( self::$registered[$old_class] );
  44. return true;
  45. }
  46. static function remove( $class ) {
  47. if ( ! isset( self::$registered[$class] ) )
  48. return false;
  49. unset( self::$registered[$class] );
  50. return true;
  51. }
  52. static function _pages_init() {
  53. foreach ( self::$registered as $class => $args )
  54. new $class( $args[0], $args[1] );
  55. }
  56. // ____________MAIN METHODS____________
  57. // Constructor
  58. function __construct( $file = false, $options = null ) {
  59. if ( is_a( $options, 'scbOptions' ) )
  60. $this->options = $options;
  61. $this->setup();
  62. $this->check_args();
  63. if ( isset( $this->option_name ) ) {
  64. add_action( 'admin_init', array( $this, 'option_init' ) );
  65. if ( function_exists( 'settings_errors' ) )
  66. add_action( 'admin_notices', 'settings_errors' );
  67. }
  68. add_action( 'admin_menu', array( $this, 'page_init' ), $this->args['admin_action_priority'] );
  69. add_filter( 'contextual_help', array( $this, '_contextual_help' ), 10, 2 );
  70. if ( $file ) {
  71. $this->file = $file;
  72. $this->plugin_url = plugin_dir_url( $file );
  73. if ( $this->args['action_link'] )
  74. add_filter( 'plugin_action_links_' . plugin_basename( $file ), array( $this, '_action_link' ) );
  75. }
  76. }
  77. // This is where all the page args can be set
  78. function setup(){}
  79. // This is where the css and js go
  80. // Both wp_enqueue_*() and inline code can be added
  81. function page_head(){}
  82. // This is where the contextual help goes
  83. // @return string
  84. function page_help(){}
  85. // A generic page header
  86. function page_header() {
  87. echo "<div class='wrap'>\n";
  88. screen_icon( $this->args['screen_icon'] );
  89. echo "<h2>" . $this->args['page_title'] . "</h2>\n";
  90. }
  91. // This is where the page content goes
  92. abstract function page_content();
  93. // A generic page footer
  94. function page_footer() {
  95. echo "</div>\n";
  96. }
  97. // This is where the form data should be validated
  98. function validate( $new_data, $old_data ) {
  99. return $new_data;
  100. }
  101. // Manually handle option saving ( use Settings API instead )
  102. function form_handler() {
  103. if ( empty( $_POST['action'] ) )
  104. return false;
  105. check_admin_referer( $this->nonce );
  106. if ( !isset($this->options) ) {
  107. trigger_error('options handler not set', E_USER_WARNING);
  108. return false;
  109. }
  110. $new_data = wp_array_slice_assoc( $_POST, array_keys( $this->options->get_defaults() ) );
  111. $new_data = stripslashes_deep( $new_data );
  112. $new_data = $this->validate( $new_data, $this->options->get() );
  113. $this->options->set( $new_data );
  114. $this->admin_msg();
  115. }
  116. // Manually generate a standard admin notice ( use Settings API instead )
  117. function admin_msg( $msg = '', $class = "updated" ) {
  118. if ( empty( $msg ) )
  119. $msg = __( 'Settings <strong>saved</strong>.', $this->textdomain );
  120. echo scb_admin_notice( $msg, $class );
  121. }
  122. // ____________UTILITIES____________
  123. // Generates a form submit button
  124. function submit_button( $value = '', $action = 'action', $class = "button" ) {
  125. if ( is_array( $value ) ) {
  126. extract( wp_parse_args( $value, array(
  127. 'value' => __( 'Save Changes', $this->textdomain ),
  128. 'action' => 'action',
  129. 'class' => 'button',
  130. 'ajax' => true
  131. ) ) );
  132. if ( ! $ajax )
  133. $class .= ' no-ajax';
  134. }
  135. else {
  136. if ( empty( $value ) )
  137. $value = __( 'Save Changes', $this->textdomain );
  138. }
  139. $input_args = array(
  140. 'type' => 'submit',
  141. 'name' => $action,
  142. 'value' => $value,
  143. 'extra' => '',
  144. 'desc' => false,
  145. 'wrap' => html( 'p class="submit"', scbForms::TOKEN )
  146. );
  147. if ( ! empty( $class ) )
  148. $input_args['extra'] = compact( 'class' );
  149. return scbForms::input( $input_args );
  150. }
  151. /*
  152. Mimics scbForms::form_wrap()
  153. $this->form_wrap( $content ); // generates a form with a default submit button
  154. $this->form_wrap( $content, false ); // generates a form with no submit button
  155. // the second argument is sent to submit_button()
  156. $this->form_wrap( $content, array( 'text' => 'Save changes',
  157. 'name' => 'action',
  158. 'ajax' => true,
  159. ) );
  160. */
  161. function form_wrap( $content, $submit_button = true ) {
  162. if ( is_array( $submit_button ) ) {
  163. $content .= $this->submit_button( $submit_button );
  164. } elseif ( true === $submit_button ) {
  165. $content .= $this->submit_button();
  166. } elseif ( false !== strpos( $submit_button, '<input' ) ) {
  167. $content .= $submit_button;
  168. } elseif ( false !== $submit_button ) {
  169. $button_args = array_slice( func_get_args(), 1 );
  170. $content .= call_user_func_array( array( $this, 'submit_button' ), $button_args );
  171. }
  172. return scbForms::form_wrap( $content, $this->nonce );
  173. }
  174. // Generates a table wrapped in a form
  175. function form_table( $rows, $formdata = false ) {
  176. $output = '';
  177. foreach ( $rows as $row )
  178. $output .= $this->table_row( $row, $formdata );
  179. $output = $this->form_table_wrap( $output );
  180. return $output;
  181. }
  182. // Wraps the given content in a <form><table>
  183. function form_table_wrap( $content ) {
  184. $output = $this->table_wrap( $content );
  185. $output = $this->form_wrap( $output );
  186. return $output;
  187. }
  188. // Generates a form table
  189. function table( $rows, $formdata = false ) {
  190. $output = '';
  191. foreach ( $rows as $row )
  192. $output .= $this->table_row( $row, $formdata );
  193. $output = $this->table_wrap( $output );
  194. return $output;
  195. }
  196. // Generates a table row
  197. function table_row( $args, $formdata = false ) {
  198. return $this->row_wrap( $args['title'], $this->input( $args, $formdata ) );
  199. }
  200. // Wraps the given content in a <table>
  201. function table_wrap( $content ) {
  202. return
  203. html( 'table class="form-table"', $content );
  204. }
  205. // Wraps the given content in a <tr><td>
  206. function row_wrap( $title, $content ) {
  207. return
  208. html( 'tr',
  209. html( 'th scope="row"', $title )
  210. .html( 'td', $content ) );
  211. }
  212. // Mimic scbForms inheritance
  213. function __call( $method, $args ) {
  214. if ( in_array( $method, array( 'input', 'form' ) ) ) {
  215. if ( empty( $args[1] ) && isset( $this->options ) )
  216. $args[1] = $this->options->get();
  217. if ( 'form' == $method )
  218. $args[2] = $this->nonce;
  219. }
  220. return call_user_func_array( array( 'scbForms', $method ), $args );
  221. }
  222. // Wraps a string in a <script> tag
  223. function js_wrap( $string ) {
  224. return "\n<script type='text/javascript'>\n" . $string . "\n</script>\n";
  225. }
  226. // Wraps a string in a <style> tag
  227. function css_wrap( $string ) {
  228. return "\n<style type='text/css'>\n" . $string . "\n</style>\n";
  229. }
  230. // ____________INTERNAL METHODS____________
  231. // Registers a page
  232. function page_init() {
  233. extract( $this->args );
  234. if ( ! $toplevel ) {
  235. $this->pagehook = add_submenu_page( $parent, $page_title, $menu_title, $capability, $page_slug, array( $this, '_page_content_hook' ) );
  236. } else {
  237. $func = 'add_' . $toplevel . '_page';
  238. $this->pagehook = $func( $page_title, $menu_title, $capability, $page_slug, array( $this, '_page_content_hook' ), $icon_url, $position );
  239. }
  240. if ( ! $this->pagehook )
  241. return;
  242. if ( $ajax_submit ) {
  243. $this->ajax_response();
  244. add_action( 'admin_footer', array( $this, 'ajax_submit' ), 20 );
  245. }
  246. add_action( 'admin_print_styles-' . $this->pagehook, array( $this, 'page_head' ) );
  247. }
  248. function option_init() {
  249. register_setting( $this->option_name, $this->option_name, array( $this, 'validate' ) );
  250. }
  251. private function check_args() {
  252. if ( empty( $this->args['page_title'] ) )
  253. trigger_error( 'Page title cannot be empty', E_USER_WARNING );
  254. $this->args = wp_parse_args( $this->args, array(
  255. 'toplevel' => '',
  256. 'position' => null,
  257. 'icon_url' => '',
  258. 'screen_icon' => '',
  259. 'parent' => 'options-general.php',
  260. 'capability' => 'manage_options',
  261. 'menu_title' => $this->args['page_title'],
  262. 'page_slug' => '',
  263. 'nonce' => '',
  264. 'action_link' => __( 'Settings', $this->textdomain ),
  265. 'ajax_submit' => false,
  266. 'admin_action_priority' => 10,
  267. ) );
  268. if ( empty( $this->args['page_slug'] ) )
  269. $this->args['page_slug'] = sanitize_title_with_dashes( $this->args['menu_title'] );
  270. if ( empty( $this->args['nonce'] ) )
  271. $this->nonce = $this->args['page_slug'];
  272. }
  273. function _contextual_help( $help, $screen ) {
  274. if ( is_object( $screen ) )
  275. $screen = $screen->id;
  276. $actual_help = $this->page_help();
  277. if ( $screen == $this->pagehook && $actual_help )
  278. return $actual_help;
  279. return $help;
  280. }
  281. function ajax_response() {
  282. if ( ! isset( $_POST['_ajax_submit'] ) || $_POST['_ajax_submit'] != $this->pagehook )
  283. return;
  284. $this->form_handler();
  285. die;
  286. }
  287. function ajax_submit() {
  288. global $page_hook;
  289. if ( $page_hook != $this->pagehook )
  290. return;
  291. ?>
  292. <script type="text/javascript">
  293. jQuery( document ).ready( function( $ ){
  294. var $spinner = $( new Image() ).attr( 'src', '<?php echo admin_url( "images/wpspin_light.gif" ); ?>' );
  295. $( ':submit' ).click( function( ev ){
  296. var $submit = $( this );
  297. var $form = $submit.parents( 'form' );
  298. if ( $submit.hasClass( 'no-ajax' ) || $form.attr( 'method' ).toLowerCase() != 'post' )
  299. return true;
  300. var $this_spinner = $spinner.clone();
  301. $submit.before( $this_spinner ).hide();
  302. var data = $form.serializeArray();
  303. data.push( {name: $submit.attr( 'name' ), value: $submit.val()} );
  304. data.push( {name: '_ajax_submit', value: '<?php echo $this->pagehook; ?>'} );
  305. $.post( location.href, data, function( response ){
  306. var $prev = $( '.wrap > .updated, .wrap > .error' );
  307. var $msg = $( response ).hide().insertAfter( $( '.wrap h2' ) );
  308. if ( $prev.length > 0 )
  309. $prev.fadeOut( 'slow', function(){ $msg.fadeIn( 'slow' ); } );
  310. else
  311. $msg.fadeIn( 'slow' );
  312. $this_spinner.hide();
  313. $submit.show();
  314. } );
  315. ev.stopPropagation();
  316. ev.preventDefault();
  317. } );
  318. } );
  319. </script>
  320. <?php
  321. }
  322. function _page_content_hook() {
  323. $this->form_handler();
  324. $this->page_header();
  325. $this->page_content();
  326. $this->page_footer();
  327. }
  328. function _action_link( $links ) {
  329. $url = add_query_arg( 'page', $this->args['page_slug'], admin_url( $this->args['parent'] ) );
  330. $links[] = html_link( $url, $this->args['action_link'] );
  331. return $links;
  332. }
  333. }