PageRenderTime 32ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 1ms

/plugins/bj-lazy-load/inc/scb/AdminPage.php

https://gitlab.com/mattswann/launch-housing
PHP | 519 lines | 230 code | 95 blank | 194 comment | 29 complexity | 90e61fdc432b0a6ce487be6c8051db08 MD5 | raw file
  1. <?php
  2. /**
  3. * Administration page base class
  4. */
  5. abstract class scbAdminPage {
  6. /** Page args
  7. * $page_title string (mandatory)
  8. * $parent (string) (default: options-general.php)
  9. * $capability (string) (default: 'manage_options')
  10. * $menu_title (string) (default: $page_title)
  11. * $submenu_title (string) (default: $menu_title)
  12. * $page_slug (string) (default: sanitized $page_title)
  13. * $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)
  14. * - $icon_url (string) URL to an icon for the top level menu
  15. * - $position (int) Position of the toplevel menu (caution!)
  16. * $screen_icon (string) The icon type to use in the screen header
  17. * $nonce string (default: $page_slug)
  18. * $action_link (string|bool) Text of the action link on the Plugins page (default: 'Settings')
  19. * $admin_action_priority int The priority that the admin_menu action should be executed at (default: 10)
  20. */
  21. protected $args;
  22. // URL to the current plugin directory.
  23. // Useful for adding css and js files
  24. protected $plugin_url;
  25. // Created at page init
  26. protected $pagehook;
  27. // scbOptions object holder
  28. // Normally, it's used for storing formdata
  29. protected $options;
  30. protected $option_name;
  31. // l10n
  32. protected $textdomain;
  33. // ____________REGISTRATION COMPONENT____________
  34. private static $registered = array();
  35. /**
  36. * @param string $class
  37. * @param string $file
  38. * @param scbOptions $options
  39. *
  40. * @return bool
  41. */
  42. static function register( $class, $file, $options = null ) {
  43. if ( isset( self::$registered[$class] ) )
  44. return false;
  45. self::$registered[$class] = array( $file, $options );
  46. add_action( '_admin_menu', array( __CLASS__, '_pages_init' ) );
  47. return true;
  48. }
  49. /**
  50. * @param string $old_class
  51. * @param string $new_class
  52. *
  53. * @return bool
  54. */
  55. static function replace( $old_class, $new_class ) {
  56. if ( ! isset( self::$registered[$old_class] ) )
  57. return false;
  58. self::$registered[$new_class] = self::$registered[$old_class];
  59. unset( self::$registered[$old_class] );
  60. return true;
  61. }
  62. /**
  63. * @param string $class
  64. *
  65. * @return bool
  66. */
  67. static function remove( $class ) {
  68. if ( ! isset( self::$registered[$class] ) )
  69. return false;
  70. unset( self::$registered[$class] );
  71. return true;
  72. }
  73. static function _pages_init() {
  74. foreach ( self::$registered as $class => $args )
  75. new $class( $args[0], $args[1] );
  76. }
  77. // ____________MAIN METHODS____________
  78. /**
  79. * Constructor
  80. *
  81. * @param string|bool $file
  82. * @param scbOptions $options
  83. */
  84. function __construct( $file = false, $options = null ) {
  85. if ( is_a( $options, 'scbOptions' ) )
  86. $this->options = $options;
  87. $this->setup();
  88. $this->check_args();
  89. if ( isset( $this->option_name ) ) {
  90. add_action( 'admin_init', array( $this, 'option_init' ) );
  91. if ( function_exists( 'settings_errors' ) )
  92. add_action( 'admin_notices', 'settings_errors' );
  93. }
  94. add_action( 'admin_menu', array( $this, 'page_init' ), $this->args['admin_action_priority'] );
  95. add_filter( 'contextual_help', array( $this, '_contextual_help' ), 10, 2 );
  96. if ( $file ) {
  97. $this->file = $file;
  98. $this->plugin_url = plugin_dir_url( $file );
  99. if ( $this->args['action_link'] )
  100. add_filter( 'plugin_action_links_' . plugin_basename( $file ), array( $this, '_action_link' ) );
  101. }
  102. }
  103. /**
  104. * This is where all the page args can be set
  105. */
  106. function setup(){}
  107. /**
  108. * Called when the page is loaded, but before any rendering.
  109. *
  110. * Useful for calling $screen->add_help_tab() etc.
  111. */
  112. function page_loaded() {}
  113. /**
  114. * This is where the css and js go
  115. * Both wp_enqueue_*() and inline code can be added
  116. */
  117. function page_head(){}
  118. /**
  119. * This is where the contextual help goes
  120. * @return string
  121. */
  122. function page_help(){}
  123. /**
  124. * A generic page header
  125. */
  126. function page_header() {
  127. echo "<div class='wrap'>\n";
  128. screen_icon( $this->args['screen_icon'] );
  129. echo html( 'h2', $this->args['page_title'] );
  130. }
  131. /**
  132. * This is where the page content goes
  133. */
  134. abstract function page_content();
  135. /**
  136. * A generic page footer
  137. */
  138. function page_footer() {
  139. echo "</div>\n";
  140. }
  141. /**
  142. * This is where the form data should be validated
  143. *
  144. * @param array $new_data
  145. * @param array $old_data
  146. *
  147. * @return array
  148. */
  149. function validate( $new_data, $old_data ) {
  150. return $new_data;
  151. }
  152. /**
  153. * Manually handle option saving ( use Settings API instead )
  154. *
  155. * @return bool
  156. */
  157. function form_handler() {
  158. if ( empty( $_POST['submit'] ) && empty( $_POST['action'] ) )
  159. return false;
  160. check_admin_referer( $this->nonce );
  161. if ( !isset($this->options) ) {
  162. trigger_error( 'options handler not set', E_USER_WARNING );
  163. return false;
  164. }
  165. $new_data = wp_array_slice_assoc( $_POST, array_keys( $this->options->get_defaults() ) );
  166. $new_data = stripslashes_deep( $new_data );
  167. $new_data = $this->validate( $new_data, $this->options->get() );
  168. $this->options->set( $new_data );
  169. $this->admin_msg();
  170. return true;
  171. }
  172. /**
  173. * Manually generate a standard admin notice ( use Settings API instead )
  174. *
  175. * @param string $msg
  176. * @param string $class
  177. */
  178. function admin_msg( $msg = '', $class = 'updated' ) {
  179. if ( empty( $msg ) )
  180. $msg = __( 'Settings <strong>saved</strong>.', $this->textdomain );
  181. echo scb_admin_notice( $msg, $class );
  182. }
  183. // ____________UTILITIES____________
  184. /**
  185. * Generates a form submit button
  186. *
  187. * @param string|array $value button text or array of arguments
  188. * @param string $action
  189. * @param string $class
  190. *
  191. * @return string
  192. */
  193. function submit_button( $value = '', $action = 'submit', $class = 'button' ) {
  194. $args = is_array( $value ) ? $value : compact( 'value', 'action', 'class' );
  195. $args = wp_parse_args( $args, array(
  196. 'value' => null,
  197. 'action' => $action,
  198. 'class' => $class,
  199. ) );
  200. return get_submit_button( $args['value'], $args['class'], $args['action'] );
  201. }
  202. /**
  203. * Mimics scbForms::form_wrap()
  204. *
  205. * $this->form_wrap( $content ); // generates a form with a default submit button
  206. *
  207. * $this->form_wrap( $content, false ); // generates a form with no submit button
  208. *
  209. * // the second argument is sent to submit_button()
  210. * $this->form_wrap( $content, array(
  211. * 'text' => 'Save changes',
  212. * 'name' => 'action',
  213. * ) );
  214. *
  215. * @see scbForms::form_wrap()
  216. *
  217. * @param string $content
  218. * @param boolean|string|array $submit_button
  219. *
  220. * @return string
  221. */
  222. function form_wrap( $content, $submit_button = true ) {
  223. if ( is_array( $submit_button ) ) {
  224. $content .= $this->submit_button( $submit_button );
  225. } elseif ( true === $submit_button ) {
  226. $content .= $this->submit_button();
  227. } elseif ( false !== strpos( $submit_button, '<input' ) ) {
  228. $content .= $submit_button;
  229. } elseif ( false !== strpos( $submit_button, '<button' ) ) {
  230. $content .= $submit_button;
  231. } elseif ( false !== $submit_button ) {
  232. $button_args = array_slice( func_get_args(), 1 );
  233. $content .= call_user_func_array( array( $this, 'submit_button' ), $button_args );
  234. }
  235. return scbForms::form_wrap( $content, $this->nonce );
  236. }
  237. /**
  238. * Generates a table wrapped in a form
  239. *
  240. * @param array $rows
  241. * @param array|boolean $formdata
  242. *
  243. * @return string
  244. */
  245. function form_table( $rows, $formdata = false ) {
  246. $output = '';
  247. foreach ( $rows as $row )
  248. $output .= $this->table_row( $row, $formdata );
  249. $output = $this->form_table_wrap( $output );
  250. return $output;
  251. }
  252. /**
  253. * Wraps the given content in a <form><table>
  254. *
  255. * @param string $content
  256. *
  257. * @return string
  258. */
  259. function form_table_wrap( $content ) {
  260. $output = $this->table_wrap( $content );
  261. $output = $this->form_wrap( $output );
  262. return $output;
  263. }
  264. /**
  265. * Generates a form table
  266. *
  267. * @param array $rows
  268. * @param array|boolean $formdata
  269. *
  270. * @return string
  271. */
  272. function table( $rows, $formdata = false ) {
  273. $output = '';
  274. foreach ( $rows as $row )
  275. $output .= $this->table_row( $row, $formdata );
  276. $output = $this->table_wrap( $output );
  277. return $output;
  278. }
  279. /**
  280. * Generates a table row
  281. *
  282. * @param array $args
  283. * @param array|boolean $formdata
  284. *
  285. * @return string
  286. */
  287. function table_row( $args, $formdata = false ) {
  288. return $this->row_wrap( $args['title'], $this->input( $args, $formdata ) );
  289. }
  290. /**
  291. * Mimic scbForms inheritance
  292. *
  293. * @see scbForms
  294. *
  295. * @param string $method
  296. * @param array $args
  297. *
  298. * @return mixed
  299. */
  300. function __call( $method, $args ) {
  301. if ( in_array( $method, array( 'input', 'form' ) ) ) {
  302. if ( empty( $args[1] ) && isset( $this->options ) )
  303. $args[1] = $this->options->get();
  304. if ( 'form' == $method )
  305. $args[2] = $this->nonce;
  306. }
  307. return call_user_func_array( array( 'scbForms', $method ), $args );
  308. }
  309. /**
  310. * Wraps a string in a <script> tag
  311. *
  312. * @param string $string
  313. *
  314. * @return string
  315. */
  316. function js_wrap( $string ) {
  317. return html( "script type='text/javascript'", $string );
  318. }
  319. /**
  320. * Wraps a string in a <style> tag
  321. *
  322. * @param string $string
  323. *
  324. * @return string
  325. */
  326. function css_wrap( $string ) {
  327. return html( "style type='text/css'", $string );
  328. }
  329. // ____________INTERNAL METHODS____________
  330. /**
  331. * Registers a page
  332. */
  333. function page_init() {
  334. if ( ! $this->args['toplevel'] ) {
  335. $this->pagehook = add_submenu_page(
  336. $this->args['parent'],
  337. $this->args['page_title'],
  338. $this->args['menu_title'],
  339. $this->args['capability'],
  340. $this->args['page_slug'],
  341. array( $this, '_page_content_hook' )
  342. );
  343. } else {
  344. $func = 'add_' . $this->args['toplevel'] . '_page';
  345. $this->pagehook = $func(
  346. $this->args['page_title'],
  347. $this->args['menu_title'],
  348. $this->args['capability'],
  349. $this->args['page_slug'],
  350. null,
  351. $this->args['icon_url'],
  352. $this->args['position']
  353. );
  354. add_submenu_page(
  355. $this->args['page_slug'],
  356. $this->args['page_title'],
  357. $this->args['submenu_title'],
  358. $this->args['capability'],
  359. $this->args['page_slug'],
  360. array( $this, '_page_content_hook' )
  361. );
  362. }
  363. if ( ! $this->pagehook )
  364. return;
  365. add_action( 'load-' . $this->pagehook, array( $this, 'page_loaded' ) );
  366. add_action( 'admin_print_styles-' . $this->pagehook, array( $this, 'page_head' ) );
  367. }
  368. function option_init() {
  369. register_setting( $this->option_name, $this->option_name, array( $this, 'validate' ) );
  370. }
  371. private function check_args() {
  372. if ( empty( $this->args['page_title'] ) )
  373. trigger_error( 'Page title cannot be empty', E_USER_WARNING );
  374. $this->args = wp_parse_args( $this->args, array(
  375. 'toplevel' => '',
  376. 'position' => null,
  377. 'icon_url' => '',
  378. 'screen_icon' => '',
  379. 'parent' => 'options-general.php',
  380. 'capability' => 'manage_options',
  381. 'menu_title' => $this->args['page_title'],
  382. 'page_slug' => '',
  383. 'nonce' => '',
  384. 'action_link' => __( 'Settings', $this->textdomain ),
  385. 'admin_action_priority' => 10,
  386. ) );
  387. if ( empty( $this->args['submenu_title'] ) )
  388. $this->args['submenu_title'] = $this->args['menu_title'];
  389. if ( empty( $this->args['page_slug'] ) )
  390. $this->args['page_slug'] = sanitize_title_with_dashes( $this->args['menu_title'] );
  391. if ( empty( $this->args['nonce'] ) )
  392. $this->nonce = $this->args['page_slug'];
  393. }
  394. /**
  395. * @param string $help
  396. * @param string|object $screen
  397. *
  398. * @return string
  399. */
  400. function _contextual_help( $help, $screen ) {
  401. if ( is_object( $screen ) )
  402. $screen = $screen->id;
  403. $actual_help = $this->page_help();
  404. if ( $screen == $this->pagehook && $actual_help )
  405. return $actual_help;
  406. return $help;
  407. }
  408. function _page_content_hook() {
  409. $this->form_handler();
  410. $this->page_header();
  411. $this->page_content();
  412. $this->page_footer();
  413. }
  414. /**
  415. * @param array $links
  416. *
  417. * @return array
  418. */
  419. function _action_link( $links ) {
  420. $url = add_query_arg( 'page', $this->args['page_slug'], admin_url( $this->args['parent'] ) );
  421. $links[] = html_link( $url, $this->args['action_link'] );
  422. return $links;
  423. }
  424. }