PageRenderTime 50ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/classes/PodsComponents.php

https://github.com/ElmsPark/pods
PHP | 660 lines | 544 code | 57 blank | 59 comment | 75 complexity | 5b710a3ae7dc5301c14c0c8be1a19ec0 MD5 | raw file
Possible License(s): AGPL-1.0
  1. <?php
  2. /**
  3. * Component managing class
  4. *
  5. * @package Pods
  6. */
  7. class PodsComponents {
  8. /**
  9. * Root of Components directory
  10. *
  11. * @var string
  12. *
  13. * @private
  14. * @since 2.0.0
  15. */
  16. private $components_dir = null;
  17. /**
  18. * Available components
  19. *
  20. * @var string
  21. *
  22. * @since 2.0.0
  23. */
  24. public $components = array();
  25. /**
  26. * Components settings
  27. *
  28. * @var string
  29. *
  30. * @since 2.0.0
  31. */
  32. public $settings = array();
  33. /**
  34. * Setup actions and get options
  35. *
  36. * @since 2.0.0
  37. */
  38. public function __construct () {
  39. $this->components_dir = realpath( apply_filters( 'pods_components_dir', PODS_DIR . 'components' ) ) . '/';
  40. $settings = get_option( 'pods_component_settings', '' );
  41. if ( !empty( $settings ) )
  42. $this->settings = (array) json_decode( $settings, true );
  43. if ( !isset( $this->settings[ 'components' ] ) )
  44. $this->settings[ 'components' ] = array();
  45. // Get components (give it access to theme)
  46. add_action( 'setup_theme', array( $this, 'get_components' ), 11 );
  47. // Load in components
  48. add_action( 'setup_theme', array( $this, 'load' ), 12 );
  49. // AJAX handling
  50. if ( is_admin() ) {
  51. add_action( 'wp_ajax_pods_admin_components', array( $this, 'admin_ajax' ) );
  52. add_action( 'wp_ajax_nopriv_pods_admin_components', array( $this, 'admin_ajax' ) );
  53. // Add the Pods Components capabilities
  54. add_filter( 'members_get_capabilities', array( $this, 'admin_capabilities' ) );
  55. }
  56. }
  57. /**
  58. * Add menu item
  59. *
  60. * @param string $parent The parent slug.
  61. *
  62. * @since 2.0.0
  63. *
  64. * @uses add_submenu_page
  65. */
  66. public function menu ( $parent ) {
  67. global $submenu;
  68. $custom_component_menus = array();
  69. foreach ( $this->components as $component => $component_data ) {
  70. if ( empty( $component_data[ 'MustUse' ] ) && ( !isset( $this->settings[ 'components' ][ $component ] ) || 0 == $this->settings[ 'components' ][ $component ] ) )
  71. continue;
  72. if ( !empty( $component_data[ 'Hide' ] ) )
  73. continue;
  74. if ( !empty( $component_data[ 'DeveloperMode' ] ) && !pods_developer() )
  75. continue;
  76. if ( empty( $component_data[ 'MenuPage' ] ) ) {
  77. if ( !isset( $component_data[ 'object' ] ) )
  78. continue;
  79. elseif ( !method_exists( $component_data[ 'object' ], 'admin' ) && !method_exists( $component_data[ 'object' ], 'options' ) )
  80. continue;
  81. }
  82. if ( false === $component_data[ 'External' ] )
  83. $component_data[ 'File' ] = realpath( $this->components_dir . $component_data[ 'File' ] );
  84. if ( !file_exists( $component_data[ 'File' ] ) ) {
  85. pods_message( 'Pods Component not found: ' . $component_data[ 'File' ] );
  86. pods_transient_clear( 'pods_components' );
  87. continue;
  88. }
  89. $capability = 'pods_component_' . str_replace( '-', '_', sanitize_title( $component ) );
  90. if ( 0 < strlen( $component_data[ 'Capability' ] ) )
  91. $capability = $component_data[ 'Capability' ];
  92. if ( !is_super_admin() && !current_user_can( 'delete_users' ) && !current_user_can( 'pods' ) && !current_user_can( 'pods_components' ) && !current_user_can( $capability ) )
  93. continue;
  94. $menu_page = 'pods-component-' . $component;
  95. if ( !empty( $component_data[ 'MenuPage' ] ) )
  96. $custom_component_menus[ $menu_page ] = $component_data;
  97. $page = add_submenu_page(
  98. $parent,
  99. strip_tags( $component_data[ 'Name' ] ),
  100. '- ' . strip_tags( $component_data[ 'MenuName' ] ),
  101. 'read',
  102. $menu_page,
  103. array( $this, 'admin_handler' )
  104. );
  105. if ( isset( $component_data[ 'object' ] ) && method_exists( $component_data[ 'object' ], 'admin_assets' ) )
  106. add_action( 'admin_print_styles-' . $page, array( $component_data[ 'object' ], 'admin_assets' ) );
  107. }
  108. if ( !empty( $custom_component_menus ) ) {
  109. foreach ( $custom_component_menus as $menu_page => $component_data ) {
  110. if ( isset( $submenu[ $parent ] ) ) {
  111. foreach ( $submenu[ $parent ] as $sub => &$menu ) {
  112. if ( $menu[ 2 ] == $menu_page ) {
  113. $menu_page = $component_data[ 'MenuPage' ];
  114. /*if ( !empty( $component_data[ 'MenuAddPage' ] ) ) {
  115. if ( false !== strpos( $_SERVER[ 'REQUEST_URI' ], $component_data[ 'MenuAddPage' ] ) )
  116. $menu_page = $component_data[ 'MenuAddPage' ];
  117. }*/
  118. $menu[ 2 ] = $menu_page;
  119. $page = current( explode( '?', $menu[ 2 ] ) );
  120. if ( isset( $component_data[ 'object' ] ) && method_exists( $component_data[ 'object' ], 'admin_assets' ) )
  121. add_action( 'admin_print_styles-' . $page, array( $component_data[ 'object' ], 'admin_assets' ) );
  122. break;
  123. }
  124. }
  125. }
  126. }
  127. }
  128. }
  129. /**
  130. * Load activated components and init component
  131. *
  132. * @since 2.0.0
  133. */
  134. public function load () {
  135. do_action( 'pods_components_load' );
  136. foreach ( (array) $this->components as $component => $component_data ) {
  137. if ( false === $component_data[ 'MustUse' ] && ( !isset( $this->settings[ 'components' ][ $component ] ) || 0 == $this->settings[ 'components' ][ $component ] ) )
  138. continue;
  139. if ( !empty( $component_data[ 'PluginDependency' ] ) ) {
  140. $dependency = explode( '|', $component_data[ 'PluginDependency' ] );
  141. if ( !pods_is_plugin_active( $dependency[ 1 ] ) )
  142. continue;
  143. }
  144. if ( !empty( $component_data[ 'ThemeDependency' ] ) ) {
  145. $dependency = explode( '|', $component_data[ 'ThemeDependency' ] );
  146. if ( strtolower( $dependency[ 1 ] ) != strtolower( get_template() ) && strtolower( $dependency[ 1 ] ) != strtolower( get_stylesheet() ) )
  147. continue;
  148. }
  149. if ( false === $component_data[ 'External' ] )
  150. $component_data[ 'File' ] = realpath( $this->components_dir . $component_data[ 'File' ] );
  151. if ( empty( $component_data[ 'File' ] ) ) {
  152. pods_transient_clear( 'pods_components' );
  153. continue;
  154. }
  155. if ( !file_exists( $component_data[ 'File' ] ) ) {
  156. pods_message( 'Pods Component not found: ' . $component_data[ 'File' ] );
  157. pods_transient_clear( 'pods_components' );
  158. continue;
  159. }
  160. include_once $component_data[ 'File' ];
  161. if ( ( !empty( $component_data[ 'Class' ] ) && class_exists( $component_data[ 'Class' ] ) ) || isset( $component_data[ 'object' ] ) ) {
  162. if ( !isset( $this->components[ $component ][ 'object' ] ) )
  163. $this->components[ $component ][ 'object' ] = new $component_data[ 'Class' ];
  164. if ( method_exists( $this->components[ $component ][ 'object' ], 'options' ) ) {
  165. if ( isset( $this->settings[ 'components' ][ $component ] ) )
  166. $this->components[ $component ][ 'options' ] = $this->components[ $component ][ 'object' ]->options( $this->settings[ 'components' ][ $component ] );
  167. else
  168. $this->components[ $component ][ 'options' ] = $this->components[ $component ][ 'object' ]->options( array() );
  169. $this->options( $component, $this->components[ $component ][ 'options' ] );
  170. }
  171. else
  172. $this->options( $component, array() );
  173. if ( method_exists( $this->components[ $component ][ 'object' ], 'handler' ) )
  174. $this->components[ $component ][ 'object' ]->handler( $this->settings[ 'components' ][ $component ] );
  175. }
  176. }
  177. }
  178. /**
  179. * Get list of components available
  180. *
  181. * @since 2.0.0
  182. */
  183. public function get_components () {
  184. $components = pods_transient_get( 'pods_components' );
  185. if ( 1 == pods_var( 'pods_debug_components', 'get', 0 ) && is_user_logged_in() && ( is_super_admin() || current_user_can( 'delete_users' ) || current_user_can( 'pods' ) ) )
  186. $components = array();
  187. if ( PodsInit::$version != PODS_VERSION || !is_array( $components ) || empty( $components ) || ( is_admin() && isset( $_GET[ 'page' ] ) && 'pods-components' == $_GET[ 'page' ] && 1 !== pods_transient_get( 'pods_components_refresh' ) ) ) {
  188. do_action( 'pods_components_get' );
  189. $component_dir = @opendir( untrailingslashit( $this->components_dir ) );
  190. $component_files = array();
  191. if ( false !== $component_dir ) {
  192. while ( false !== ( $file = readdir( $component_dir ) ) ) {
  193. if ( '.' == substr( $file, 0, 1 ) )
  194. continue;
  195. elseif ( is_dir( $this->components_dir . $file ) ) {
  196. $component_subdir = @opendir( $this->components_dir . $file );
  197. if ( $component_subdir ) {
  198. while ( false !== ( $subfile = readdir( $component_subdir ) ) ) {
  199. if ( '.' == substr( $subfile, 0, 1 ) )
  200. continue;
  201. elseif ( '.php' == substr( $subfile, -4 ) )
  202. $component_files[] = str_replace( '\\', '/', $file . '/' . $subfile );
  203. }
  204. closedir( $component_subdir );
  205. }
  206. }
  207. elseif ( '.php' == substr( $file, -4 ) )
  208. $component_files[] = $file;
  209. }
  210. closedir( $component_dir );
  211. }
  212. $default_headers = array(
  213. 'ID' => 'ID',
  214. 'Name' => 'Name',
  215. 'ShortName' => 'Short Name',
  216. 'PluginName' => 'Plugin Name',
  217. 'ComponentName' => 'Component Name',
  218. 'URI' => 'URI',
  219. 'MenuName' => 'Menu Name',
  220. 'MenuPage' => 'Menu Page',
  221. 'MenuAddPage' => 'Menu Add Page',
  222. 'MustUse' => 'Must Use',
  223. 'Description' => 'Description',
  224. 'Version' => 'Version',
  225. 'Category' => 'Category',
  226. 'Author' => 'Author',
  227. 'AuthorURI' => 'Author URI',
  228. 'Class' => 'Class',
  229. 'Hide' => 'Hide',
  230. 'PluginDependency' => 'Plugin Dependency',
  231. 'ThemeDependency' => 'Theme Dependency',
  232. 'DeveloperMode' => 'Developer Mode',
  233. 'Capability' => 'Capability'
  234. );
  235. $component_files = apply_filters( 'pods_components_register', $component_files );
  236. $components = array();
  237. foreach ( $component_files as $component_file ) {
  238. $external = false;
  239. if ( is_array( $component_file ) && isset( $component_file[ 'File' ] ) ) {
  240. $component = $component_file = $component_file[ 'File' ];
  241. $external = true;
  242. }
  243. else
  244. $component = $this->components_dir . $component_file;
  245. if ( !is_readable( $component ) )
  246. continue;
  247. $component_data = get_file_data( $component, $default_headers, 'pods_component' );
  248. if ( ( empty( $component_data[ 'Name' ] ) && empty( $component_data[ 'ComponentName' ] ) && empty( $component_data[ 'PluginName' ] ) ) || 'yes' == $component_data[ 'Hide' ] )
  249. continue;
  250. if ( empty( $component_data[ 'Name' ] ) ) {
  251. if ( !empty( $component_data[ 'ComponentName' ] ) )
  252. $component_data[ 'Name' ] = $component_data[ 'ComponentName' ];
  253. elseif ( !empty( $component_data[ 'PluginName' ] ) )
  254. $component_data[ 'Name' ] = $component_data[ 'PluginName' ];
  255. }
  256. if ( empty( $component_data[ 'ShortName' ] ) )
  257. $component_data[ 'ShortName' ] = $component_data[ 'Name' ];
  258. if ( empty( $component_data[ 'MenuName' ] ) )
  259. $component_data[ 'MenuName' ] = $component_data[ 'Name' ];
  260. if ( empty( $component_data[ 'Class' ] ) )
  261. $component_data[ 'Class' ] = 'Pods_' . pods_clean_name( basename( $component, '.php' ), false );
  262. if ( empty( $component_data[ 'ID' ] ) )
  263. $component_data[ 'ID' ] = sanitize_title( $component_data[ 'Name' ] );
  264. if ( 'on' == strtolower( $component_data[ 'DeveloperMode' ] ) || 1 == $component_data[ 'DeveloperMode' ] )
  265. $component_data[ 'DeveloperMode' ] = true;
  266. else
  267. $component_data[ 'DeveloperMode' ] = false;
  268. $component_data[ 'External' ] = (boolean) $external;
  269. if ( 'on' == strtolower($component_data[ 'MustUse' ] ) || '1' == $component_data[ 'MustUse' ] )
  270. $component_data[ 'MustUse' ] = true;
  271. elseif ( 'off' == strtolower($component_data[ 'MustUse' ] ) || '0' == $component_data[ 'MustUse' ] )
  272. $component_data[ 'MustUse' ] = false;
  273. else
  274. $component_data[ 'MustUse' ] = $component_data[ 'External' ];
  275. $component_data[ 'File' ] = $component_file;
  276. $components[ $component_data[ 'ID' ] ] = $component_data;
  277. }
  278. ksort( $components );
  279. pods_transient_set( 'pods_components_refresh', 1, ( 60 * 60 * 12 ) );
  280. pods_transient_set( 'pods_components', $components );
  281. }
  282. if ( 1 == pods_var( 'pods_debug_components', 'get', 0 ) && is_user_logged_in() && ( is_super_admin() || current_user_can( 'delete_users' ) || current_user_can( 'pods' ) ) )
  283. pods_debug( $components );
  284. $this->components = $components;
  285. return $this->components;
  286. }
  287. /**
  288. * Set component options
  289. *
  290. * @param $component
  291. * @param $options
  292. *
  293. * @since 2.0.0
  294. */
  295. public function options ( $component, $options ) {
  296. if ( !isset( $this->settings[ 'components' ][ $component ] ) || !is_array( $this->settings[ 'components' ][ $component ] ) )
  297. $this->settings[ 'components' ][ $component ] = array();
  298. foreach ( $options as $option => $data ) {
  299. if ( !isset( $this->settings[ 'components' ][ $component ][ $option ] ) && isset( $data[ 'default' ] ) )
  300. $this->settings[ 'components' ][ $component ][ $option ] = $data[ 'default' ];
  301. }
  302. }
  303. /**
  304. * Call component specific admin functions
  305. *
  306. * @since 2.0.0
  307. */
  308. public function admin_handler () {
  309. $component = str_replace( 'pods-component-', '', $_GET[ 'page' ] );
  310. if ( isset( $this->components[ $component ] ) && isset( $this->components[ $component ][ 'object' ] ) && is_object( $this->components[ $component ][ 'object' ] ) ) {
  311. if ( method_exists( $this->components[ $component ][ 'object' ], 'admin' ) )
  312. $this->components[ $component ][ 'object' ]->admin( $this->settings[ 'components' ][ $component ], $component );
  313. elseif ( method_exists( $this->components[ $component ][ 'object' ], 'options' ) )
  314. $this->admin( $this->components[ $component ][ 'object' ]->options( $this->settings[ 'components' ][ $component ] ), $this->settings[ 'components' ][ $component ], $component );
  315. }
  316. }
  317. public function admin ( $options, $settings, $component ) {
  318. if ( !isset( $this->components[ $component ] ) )
  319. wp_die( 'Invalid Component' );
  320. $component_label = $this->components[ $component ][ 'Name' ];
  321. include PODS_DIR . 'ui/admin/components-admin.php';
  322. }
  323. /**
  324. * Toggle a component on or off
  325. *
  326. * @param string $component The component name to toggle
  327. *
  328. * @return bool
  329. *
  330. * @since 2.0.0
  331. */
  332. public function toggle ( $component ) {
  333. $toggle = null;
  334. if ( isset( $this->components[ $component ] ) ) {
  335. if ( 1 == pods_var( 'toggle', 'get' ) && ( !isset( $this->settings[ 'components' ][ $component ] ) || 0 == $this->settings[ 'components' ][ $component ] ) ) {
  336. $this->settings[ 'components' ][ $component ] = array();
  337. $toggle = true;
  338. }
  339. elseif ( 0 == pods_var( 'toggle', 'get' ) ) {
  340. $this->settings[ 'components' ][ $component ] = 0;
  341. $toggle = false;
  342. }
  343. }
  344. $settings = version_compare( PHP_VERSION, '5.4.0', '>=' ) ? json_encode( $this->settings, JSON_UNESCAPED_UNICODE ) : json_encode( $this->settings );
  345. update_option( 'pods_component_settings', $settings );
  346. return $toggle;
  347. }
  348. /**
  349. * Add pods specific capabilities.
  350. *
  351. * @param $capabilities List of extra capabilities to add
  352. *
  353. * @return array
  354. */
  355. public function admin_capabilities ( $capabilities ) {
  356. foreach ( $this->components as $component => $component_data ) {
  357. if ( !empty( $component_data[ 'Hide' ] ) )
  358. continue;
  359. if ( true === (boolean) pods_var( 'DeveloperMode', $component_data, false ) && ( !pods_developer() ) )
  360. continue;
  361. if ( empty( $component_data[ 'MenuPage' ] ) && ( !isset( $component_data[ 'object' ] ) || !method_exists( $component_data[ 'object' ], 'admin' ) ) )
  362. continue;
  363. $capability = 'pods_component_' . str_replace( '-', '_', sanitize_title( str_replace( ' and ', ' ', strip_tags( $component_data[ 'Name' ] ) ) ) );
  364. if ( 0 < strlen ( $component_data[ 'Capability' ] ) )
  365. $capability = $component_data[ 'Capability' ];
  366. if ( !in_array( $capability, $capabilities ) )
  367. $capabilities[] = $capability;
  368. }
  369. return $capabilities;
  370. }
  371. /**
  372. * Handle admin ajax
  373. *
  374. * @since 2.0.0
  375. */
  376. public function admin_ajax () {
  377. if ( false === headers_sent() ) {
  378. if ( '' == session_id() )
  379. @session_start();
  380. header( 'Content-Type: text/html; charset=' . get_bloginfo( 'charset' ) );
  381. }
  382. // Sanitize input
  383. $params = stripslashes_deep( (array) $_POST );
  384. foreach ( $params as $key => $value ) {
  385. if ( 'action' == $key )
  386. continue;
  387. unset( $params[ $key ] );
  388. $params[ str_replace( '_podsfix_', '', $key ) ] = $value;
  389. }
  390. $params = (object) $params;
  391. $component = $params->component;
  392. $method = $params->method;
  393. if ( !isset( $component ) || !isset( $this->components[ $component ] ) || !isset( $this->settings[ 'components' ][ $component ] ) )
  394. pods_error( 'Invalid AJAX request', $this );
  395. if ( !isset( $params->_wpnonce ) || false === wp_verify_nonce( $params->_wpnonce, 'pods-component-' . $component . '-' . $method ) )
  396. pods_error( 'Unauthorized request', $this );
  397. // Cleaning up $params
  398. unset( $params->action );
  399. unset( $params->component );
  400. unset( $params->method );
  401. unset( $params->_wpnonce );
  402. $params = (object) apply_filters( 'pods_component_ajax_' . $component . '_' . $method, $params, $component, $method );
  403. $output = false;
  404. // Handle internal methods
  405. if ( isset( $this->components[ $component ][ 'object' ] ) && !method_exists( $this->components[ $component ][ 'object' ], 'ajax_' . $method ) && method_exists( $this, 'admin_ajax_' . $method ) )
  406. $output = call_user_func( array( $this, 'admin_ajax_' . $method ), $component, $params );
  407. // Make sure method exists
  408. elseif ( !isset( $this->components[ $component ][ 'object' ] ) || !method_exists( $this->components[ $component ][ 'object' ], 'ajax_' . $method ) )
  409. pods_error( 'API method does not exist', $this );
  410. // Dynamically call the component method
  411. else
  412. $output = call_user_func( array( $this->components[ $component ][ 'object' ], 'ajax_' . $method ), $params );
  413. if ( !is_bool( $output ) )
  414. echo $output;
  415. die(); // KBAI!
  416. }
  417. public function admin_ajax_settings ( $component, $params ) {
  418. if ( !isset( $this->components[ $component ] ) )
  419. wp_die( 'Invalid Component' );
  420. elseif ( !method_exists( $this->components[ $component ][ 'object' ], 'options' ) )
  421. pods_error( 'Component options method does not exist', $this );
  422. $options = $this->components[ $component ][ 'object' ]->options( $this->settings[ 'components' ][ $component ] );
  423. if ( empty( $this->settings[ 'components' ][ $component ] ) )
  424. $this->settings[ 'components' ][ $component ] = array();
  425. foreach ( $options as $field_name => $field_option ) {
  426. $field_option = PodsForm::field_setup( $field_option, null, $field_option[ 'type' ] );
  427. if ( !is_array( $field_option[ 'group' ] ) ) {
  428. $field_value = pods_var_raw( 'pods_setting_' . $field_name, $params );
  429. $this->settings[ 'components' ][ $component ][ $field_name ] = $field_value;
  430. }
  431. else {
  432. foreach ( $field_option[ 'group' ] as $field_group_name => $field_group_option ) {
  433. $field_value = pods_var_raw( 'pods_setting_' . $field_group_name, $params );
  434. $this->settings[ 'components' ][ $component ][ $field_group_name ] = $field_value;
  435. }
  436. }
  437. }
  438. $settings = version_compare( PHP_VERSION, '5.4.0', '>=' ) ? json_encode( $this->settings, JSON_UNESCAPED_UNICODE ) : json_encode( $this->settings );
  439. update_option( 'pods_component_settings', $settings );
  440. return '1';
  441. }
  442. }
  443. /**
  444. * The base component class, all components should extend this.
  445. *
  446. * @package Pods
  447. */
  448. class PodsComponent {
  449. /**
  450. * Do things like register/enqueue scripts and stylesheets
  451. *
  452. * @since 2.0.0
  453. */
  454. public function __construct () {
  455. }
  456. /**
  457. * Add options and set defaults for component settings, shows in admin area
  458. *
  459. * @return array $options
  460. *
  461. * @since 2.0.0
  462. public function options () {
  463. $options = array(
  464. 'option_name' => array(
  465. 'label' => 'Option Label',
  466. 'depends-on' => array( 'another_option' => 'specific-value' ),
  467. 'default' => 'default-value',
  468. 'type' => 'field_type',
  469. 'data' => array(
  470. 'value1' => 'Label 1',
  471. // Group your options together
  472. 'Option Group' => array(
  473. 'gvalue1' => 'Option Label 1',
  474. 'gvalue2' => 'Option Label 2'
  475. ),
  476. // below is only if the option_name above is the "{$fieldtype}_format_type"
  477. 'value2' => array(
  478. 'label' => 'Label 2',
  479. 'regex' => '[a-zA-Z]' // Uses JS regex validation for the value saved if this option selected
  480. )
  481. ),
  482. // below is only for a boolean group
  483. 'group' => array(
  484. 'option_boolean1' => array(
  485. 'label' => 'Option boolean 1?',
  486. 'default' => 1,
  487. 'type' => 'boolean'
  488. ),
  489. 'option_boolean2' => array(
  490. 'label' => 'Option boolean 2?',
  491. 'default' => 0,
  492. 'type' => 'boolean'
  493. )
  494. )
  495. )
  496. );
  497. return $options;
  498. }
  499. */
  500. /**
  501. * Handler to run code based on $options
  502. *
  503. * @param $options
  504. *
  505. * @since 2.0.0
  506. */
  507. public function handler ( $options ) {
  508. // run code based on $options set
  509. }
  510. /**
  511. * Build admin area
  512. *
  513. * @param $options
  514. *
  515. * @since 2.0.0
  516. public function admin ( $options ) {
  517. // run code based on $options set
  518. }
  519. */
  520. }