PageRenderTime 72ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 1ms

/admin/class-apl-admin.php

https://github.com/Advanced-Post-List/advanced-post-list
PHP | 2227 lines | 1214 code | 266 blank | 747 comment | 121 complexity | dc05c4f4aa7d94e9ee2d9c74bcd7f0e1 MD5 | raw file
  1. <?php
  2. /**
  3. * APL Admin API: APL_Admin Class
  4. *
  5. * Admin core object to Advanced Post List
  6. *
  7. * @link https://github.com/Advanced-Post-List/advanced-post-list/
  8. *
  9. * @package advanced-post-list\APL_Core
  10. * @since 0.4.0
  11. */
  12. /**
  13. * APL Admin
  14. *
  15. * Admin core class.
  16. *
  17. * @since 0.4.0
  18. */
  19. class APL_Admin {
  20. /**
  21. * Singleton Instance
  22. *
  23. * @since 0.4.0
  24. * @access private
  25. * @var null $instance Singleton Class Instance.
  26. */
  27. protected static $instance = null;
  28. /**
  29. * Get Singleton Instance
  30. *
  31. * Singleton Get Instance.
  32. *
  33. * @since 0.4.0
  34. * @access private
  35. *
  36. * @return object
  37. */
  38. public static function get_instance() {
  39. if ( null === static::$instance ) {
  40. static::$instance = new static();
  41. // TODO - Catch WP Error.
  42. }
  43. return static::$instance;
  44. }
  45. /**
  46. * Throws error on object clone
  47. *
  48. * The whole idea of the singleton design pattern is that there is a single
  49. * object therefore, we don't want the object to be cloned.
  50. *
  51. * @ignore
  52. * @since 0.4.0
  53. * @access private
  54. */
  55. private function __clone() {
  56. // Cloning instances of the class is forbidden.
  57. _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin\' huh?', 'advanced-post-list' ), APL_VERSION );
  58. }
  59. /**
  60. * Disable unserializing of the class
  61. *
  62. * @ignore
  63. * @since 0.4.0
  64. * @access protected
  65. */
  66. private function __wakeup() {
  67. // Unserializing instances of the class is forbidden.
  68. _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin\' huh?', 'advanced-post-list' ), APL_VERSION );
  69. }
  70. /**
  71. * Constructor
  72. *
  73. * Private Singleton Constructor.
  74. *
  75. * @ignore
  76. * @since 0.4.0
  77. * @access private
  78. *
  79. * @todo Complete Admin Encapsulation. Concept linked.
  80. * @link https://florianbrinkmann.com/en/3815/wordpress-backend-request/
  81. */
  82. private function __construct() {
  83. // Exit if Non-Admins access this object. Also wrapped in APL_Core.
  84. if ( ! is_admin() ) {
  85. return new WP_Error( 'apl_admin', esc_html__( 'You do not have admin capabilities in APL_Admin.', 'advanced-post-list' ) );
  86. }
  87. // Initialize Core Class functions.
  88. $this->_requires();
  89. apl_notice_set_activation_review_plugin( false, false );
  90. // Settings Data.
  91. add_action( 'admin_post_apl_save_general_settings', array( $this, 'save_general_settings' ) );
  92. // AJAX.
  93. add_action( 'admin_init', array( $this, 'add_settings_ajax_hooks' ) );
  94. // Check if wp-admin.php is loaded, and WP_Screen is defined.
  95. // is_admin_bar_showing().
  96. if ( defined( 'WP_ADMIN' ) && WP_ADMIN && is_blog_admin() ) {
  97. // Menu & Scripts.
  98. add_action( 'admin_menu', array( $this, 'admin_menu' ) );
  99. add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue' ) );
  100. // Admin Screens for Modular Screen Execution.
  101. // NOTE: Settings Page needs to hook sooner (in constructor/here).
  102. add_action( 'current_screen', array( $this, 'current_screen_hooks' ) );
  103. // Hook into WP to customize Screens.
  104. add_action( 'admin_head', array( $this, 'disable_screen_boxes' ) );
  105. add_action( 'load-edit.php', array( $this, 'post_list_screen_options_all' ) );
  106. add_action( 'load-post-new.php', array( $this, 'post_list_screen_options_add_new' ) );
  107. add_action( 'manage_apl_post_list_posts_columns', array( $this, 'post_list_posts_columns' ) );
  108. add_action( 'manage_apl_post_list_posts_custom_column', array( $this, 'post_list_posts_custom_column' ), 10, 2 );
  109. add_action( 'manage_edit-apl_post_list_sortable_columns', array( $this, 'post_list_sortable_columns' ) );
  110. // Editor Meta Boxes.
  111. add_action( 'add_meta_boxes', array( $this, 'post_list_meta_boxes' ) );
  112. add_action( 'add_meta_boxes', array( $this, 'settings_meta_boxes' ) );
  113. if ( defined( 'ICL_SITEPRESS_VERSION' ) || defined( 'APLP_VERSION' ) ) {
  114. add_action( 'add_meta_boxes', array( $this, 'design_meta_boxes' ) );
  115. }
  116. add_filter( 'mce_external_plugins', array( $this, 'mce_external_plugins' ) );
  117. add_filter( 'mce_buttons', array( $this, 'mce_buttons' ) );
  118. add_action( 'admin_head', array( $this, 'tinymce_extra_vars' ) );
  119. }
  120. }
  121. /**
  122. * Requires Files
  123. *
  124. * Files that this class object needs to load.
  125. *
  126. * @ignore
  127. * @since 0.4.0
  128. * @access private
  129. */
  130. private function _requires() {
  131. // Example.
  132. // 'require_once( APL_DIR . 'includes/example.php' )'.
  133. require_once APL_DIR . 'admin/functions-admin.php';
  134. require_once APL_DIR . 'admin/export.php';
  135. require_once APL_DIR . 'admin/import.php';
  136. require_once APL_DIR . 'admin/class-apl-notices.php';
  137. }
  138. /**
  139. * Current Admin Screen Hooks
  140. *
  141. * Adds hooks according to the admin screen in use.
  142. *
  143. * @since 0.4.0
  144. *
  145. * @param WP_Screen $current_screen Current WP_Screen object.
  146. */
  147. public function current_screen_hooks( $current_screen ) {
  148. if ( 'apl_post_list' === $current_screen->id || 'edit-apl_post_list' === $current_screen->id ) {
  149. // Post Data.
  150. add_action( 'draft_apl_post_list', array( $this, 'draft_post_list' ), 10, 2 );
  151. add_action( 'private_apl_post_list', array( $this, 'save_post_list' ), 10, 2 );
  152. add_action( 'publish_apl_post_list', array( $this, 'save_post_list' ), 10, 2 );
  153. add_action( 'pending_apl_post_list', array( $this, 'save_post_list' ), 10, 2 );
  154. add_action( 'future_apl_post_list', array( $this, 'save_post_list' ), 10, 2 );
  155. // //add_action( 'trash_apl_post_list', array( $this, 'trash_post_list' ), 10, 3 );
  156. add_action( 'wp_trash_post', array( $this, 'action_wp_trash_post_apl_post_list' ) );
  157. add_action( 'untrash_post', array( $this, 'action_untrash_post_apl_post_list' ) );
  158. add_action( 'before_delete_post', array( $this, 'action_before_delete_post_apl_post_list' ) );
  159. // //if ( 'apl_post_list' === $current_screen->id ) {
  160. // // $current_screen->add_help_tab( array(
  161. // // 'id' => 'apl_post_list_help', //unique id for the tab.
  162. // // 'title' => 'Testing Help Tab', //unique visible title for the tab.
  163. // // 'content' => 'Hello World', //actual help text.
  164. // // //'callback' => $callback //optional function to callback.
  165. // // ) );
  166. // //}
  167. } elseif ( 'apl_design' === $current_screen->id || 'edit-apl_design' === $current_screen->id ) {
  168. // Post Data.
  169. add_action( 'draft_apl_design', array( $this, 'draft_design' ), 10, 2 );
  170. add_action( 'private_apl_design', array( $this, 'save_design' ), 10, 2 );
  171. add_action( 'publish_apl_design', array( $this, 'save_design' ), 10, 2 );
  172. add_action( 'pending_apl_design', array( $this, 'save_design' ), 10, 2 );
  173. add_action( 'future_apl_design', array( $this, 'save_design' ), 10, 2 );
  174. // //add_action( 'trash_apl_post_list', array( $this, 'trash_design' ), 10, 3 );
  175. // //add_action( 'wp_trash_post', array( $this, 'action_wp_trash_post_apl_design' ) );
  176. // //add_action( 'untrash_post', array( $this, 'action_untrash_post_apl_design' ) );
  177. // //add_action( 'before_delete_post', array( $this, 'action_before_delete_post_apl_design' ) );
  178. } elseif ( 'adv-post-list_page_apl_settings' === $current_screen->id ) {
  179. // SETTINGS (Page).
  180. // DOES NOT always work as intended. Use self::_constructor().
  181. } else {
  182. // //add_filter( 'mce_external_plugins', array( $this, 'mce_external_plugins' ) );
  183. // //add_filter( 'mce_buttons', array( $this, 'mce_register_buttons' ) );
  184. }// End if().
  185. }
  186. /**
  187. * APL Admin Menu
  188. *
  189. * Adds the Admin Menu and Scripts for APL.
  190. *
  191. * @since 0.4.0
  192. *
  193. * @see 'admin_menu' hook
  194. * @see wp-admin/admin-header.php
  195. * @link https://developer.wordpress.org/reference/functions/add_menu_page/
  196. * @link https://developer.wordpress.org/reference/functions/add_submenu_page/
  197. */
  198. public function admin_menu() {
  199. add_menu_page(
  200. __( 'Advanced Post List', 'advanced-post-list' ),
  201. __( 'Adv. Post List', 'advanced-post-list' ),
  202. 'administrator',
  203. 'advanced_post_list',
  204. 'edit.php?post_type=apl_post_list', // Callback function if dashboard is added.
  205. 'dashicons-welcome-widgets-menus',
  206. 58
  207. );
  208. // TODO Add APL Dashboard.
  209. // All Post Lists (Submenu) - Submenu setting is added during CPT registration.
  210. // Add New (Submenu).
  211. add_submenu_page(
  212. 'advanced_post_list',
  213. __( 'Add New Post List', 'advanced-post-list' ),
  214. __( '- New Post List', 'advanced-post-list' ),
  215. 'administrator',
  216. 'post-new.php?post_type=apl_post_list'
  217. );
  218. // Settings (Submenu).
  219. add_submenu_page(
  220. 'advanced_post_list',
  221. // // edit.php?post_type=apl_post_list',
  222. __( 'APL Settings', 'advanced-post-list' ),
  223. __( 'Settings', 'advanced-post-list' ),
  224. 'administrator',
  225. 'apl_settings',
  226. array( $this, 'submenu_settings_page' )
  227. );
  228. add_action( 'admin_init', array( $this, 'settings_register_settings' ) );
  229. // TODO - Add Help API.
  230. // EXTENSIONS.
  231. do_action( 'apl_admin_menu_ext' );
  232. }
  233. /**
  234. * Submenu Callback for Settings Page
  235. *
  236. * @since 0.4.0
  237. */
  238. public function submenu_settings_page() {
  239. apl_get_template( 'admin/settings-page.php' );
  240. }
  241. /**
  242. * Registers Input Settings for Settings Page
  243. *
  244. * @since 0.4.0
  245. */
  246. public function settings_register_settings() {
  247. register_setting( 'apl_settings_general', 'apl_delete_on_deactivation', 'strval' );
  248. register_setting( 'apl_settings_general', 'apl_default_empty_enable', 'strval' );
  249. register_setting( 'apl_settings_general', 'apl_default_empty_message', 'strval' );
  250. // //register_setting( 'apl_settings_import_export', 'apl_export_file_name', 'strval' );
  251. // //register_setting( 'apl_settings_import_export', 'apl_import_opt', 'strval' );
  252. // //register_setting( 'apl_settings_import_export', 'apl_import_file', 'strval' );
  253. // //register_setting( 'apl_settings_import_export', 'apl_restore_database', 'strval' );
  254. }
  255. /**
  256. * APL Admin Enqueue Scripts & Styles
  257. *
  258. * Loads APL scripts and styles. If not in APL Admin Pages, then remove.
  259. *
  260. * @since 0.4.0
  261. *
  262. * @see wp-admin/admin-header.php
  263. * @link https://developer.wordpress.org/reference/hooks/admin_enqueue_scripts/
  264. *
  265. * @param string $hook_suffix The suffix for the current Admin page.
  266. */
  267. public function admin_enqueue( $hook_suffix ) {
  268. $screen = get_current_screen();
  269. /*
  270. * ************** REMOVE SCRIPTS & STYLES *********************
  271. */
  272. // STEP 1 - By default, remove any scripts & styles.
  273. wp_deregister_script( 'apl-admin-js' );
  274. wp_deregister_script( 'apl-admin-ui-js' );
  275. wp_deregister_script( 'apl-admin-ui-multiselect-js' );
  276. wp_deregister_script( 'apl-admin-ui-multiselect-filter-js' );
  277. wp_deregister_style( 'apl-admin-css' );
  278. wp_deregister_style( 'apl-admin-ui-multiselect-css' );
  279. wp_deregister_style( 'apl-admin-ui-multiselect-filter-css' );
  280. wp_deregister_style( 'apl-admin-settings-css' );
  281. if ( 'apl_post_list' === $screen->id || 'edit-apl_post_list' === $screen->id || 'apl_design' === $screen->id || 'edit-apl_design' === $screen->id ) {
  282. /*
  283. * ************** AJAX ACTION HOOKS ***************************
  284. */
  285. // TODO - Add meta box to side to load different presets from 'edit.php'.
  286. // //add_action( 'wp_ajax_apl_load_preset', array( $this, 'hook_ajax_load_preset' ) );
  287. /*
  288. * ************** REGISTER SCRIPTS ****************************
  289. */
  290. // Step 2 - Register scripts to be enqueued.
  291. wp_register_script(
  292. 'apl-admin-js',
  293. APL_URL . 'admin/js/admin.js',
  294. array(
  295. 'jquery',
  296. ),
  297. APL_VERSION,
  298. false
  299. );
  300. wp_register_script(
  301. 'apl-admin-ui-js',
  302. APL_URL . 'admin/js/admin-ui.js',
  303. array(
  304. 'jquery',
  305. 'jquery-ui-core',
  306. 'jquery-ui-widget',
  307. 'jquery-ui-tabs',
  308. 'jquery-ui-spinner',
  309. 'jquery-ui-slider',
  310. 'jquery-ui-button',
  311. 'jquery-ui-dialog',
  312. 'jquery-ui-selectmenu',
  313. 'jquery-ui-position',
  314. 'jquery-ui-tooltip',
  315. ),
  316. APL_VERSION,
  317. true
  318. );
  319. wp_register_script(
  320. 'apl-admin-ui-multiselect-js',
  321. APL_URL . 'admin/js/jquery-multiselect/jquery.multiselect.min.js',
  322. array(
  323. 'jquery',
  324. 'jquery-ui-core',
  325. 'jquery-ui-widget',
  326. 'jquery-ui-selectmenu',
  327. ),
  328. APL_VERSION,
  329. false
  330. );
  331. wp_register_script(
  332. 'apl-admin-ui-multiselect-filter-js',
  333. APL_URL . 'admin/js/jquery-multiselect/jquery.multiselect.filter.min.js',
  334. array(
  335. 'jquery',
  336. 'jquery-ui-core',
  337. 'jquery-ui-widget',
  338. ),
  339. APL_VERSION,
  340. false
  341. );
  342. global $wp_version;
  343. if ( version_compare( $wp_version, '4.9', '>' ) && ( 'apl_post_list' === $screen->id || 'apl_design' === $screen->id ) ) {
  344. // Enqueue code editor and settings for manipulating HTML.
  345. // https://developer.wordpress.org/reference/functions/wp_enqueue_code_editor/
  346. $args = array( 'type' => 'application/x-httpd-php' );
  347. $settings = wp_enqueue_code_editor( $args );
  348. if ( false !== $settings ) {
  349. wp_add_inline_script(
  350. 'code-editor',
  351. sprintf(
  352. 'jQuery( function() { wp.codeEditor.initialize( "apl_textarea_before", %s ); } );',
  353. wp_json_encode( $settings )
  354. )
  355. );
  356. wp_add_inline_script(
  357. 'code-editor',
  358. sprintf(
  359. 'jQuery( function() { wp.codeEditor.initialize( "apl_textarea_content", %s ); } );',
  360. wp_json_encode( $settings )
  361. )
  362. );
  363. wp_add_inline_script(
  364. 'code-editor',
  365. sprintf(
  366. 'jQuery( function() { wp.codeEditor.initialize( "apl_textarea_after", %s ); } );',
  367. wp_json_encode( $settings )
  368. )
  369. );
  370. // Empty is disabled for now, but will need to be hidden when checkbox is unchecked.
  371. // Hold off until 5.0.
  372. }
  373. }
  374. // STEP 3 - Enqueue scripts.
  375. wp_enqueue_script( 'apl-admin-js' );
  376. wp_enqueue_script( 'apl-admin-ui-js' );
  377. wp_enqueue_script( 'apl-admin-ui-multiselect-js' );
  378. wp_enqueue_script( 'apl-admin-ui-multiselect-filter-js' );
  379. /*
  380. * ************** REGISTER STYLES *****************************
  381. */
  382. // Step 4 - (Register) Enqueue styles.
  383. wp_enqueue_style(
  384. 'apl-admin-css',
  385. APL_URL . 'admin/css/admin.css',
  386. false,
  387. APL_VERSION,
  388. false
  389. );
  390. $wp_scripts = wp_scripts();
  391. wp_enqueue_style(
  392. 'apl-admin-ui-css',
  393. APL_URL . 'admin/css/jquery-ui/jquery-ui.min.css',
  394. false,
  395. APL_VERSION,
  396. false
  397. );
  398. wp_enqueue_style(
  399. 'apl-admin-ui-multiselect-css',
  400. APL_URL . 'admin/css/jquery-multiselect/jquery.multiselect.css',
  401. false,
  402. APL_VERSION,
  403. false
  404. );
  405. wp_enqueue_style(
  406. 'apl-admin-ui-multiselect-filter-css',
  407. APL_URL . 'admin/css/jquery-multiselect/jquery.multiselect.filter.css',
  408. false,
  409. APL_VERSION,
  410. false
  411. );
  412. // Get values for variables to localize into JS files.
  413. // POST => TAXONOMIES.
  414. $data_post_tax = apl_get_post_tax();
  415. // TAXONOMIES => TERMS.
  416. $data_tax_terms = apl_get_tax_terms();
  417. $data_ui_trans = array(
  418. 'tax_noneSelectedText' => esc_html__( 'Select Taxonomy', 'advanced-post-list' ),
  419. 'tax_selectedText' => esc_html__( '# of # taxonomies selected', 'advanced-post-list' ),
  420. 'author_ids_noneSelectedText' => esc_html__( '- None -', 'advanced-post-list' ),
  421. 'author_ids_selectedText' => esc_html__( '# Selected', 'advanced-post-list' ),
  422. 'post_status_1_noneSelectedText' => esc_html__( 'Select Status', 'advanced-post-list' ),
  423. 'post_status_1_selectedText' => esc_html__( 'Both', 'advanced-post-list' ),
  424. 'post_status_2_noneSelectedText' => esc_html__( 'Published', 'advanced-post-list' ),
  425. 'post_status_2_selectedText' => esc_html__( '# Selected', 'advanced-post-list' ),
  426. );
  427. $admin_localize = array();
  428. $admin_ui_localize = array(
  429. 'post_tax' => $data_post_tax,
  430. 'tax_terms' => $data_tax_terms,
  431. 'trans' => $data_ui_trans,
  432. );
  433. // Add variables to JS files.
  434. // '../admin/js/admin.js'.
  435. // '../admin/js/admin-ui.js'.
  436. wp_localize_script( 'apl-admin-js', 'apl_admin_local', $admin_localize );
  437. wp_localize_script( 'apl-admin-ui-js', 'apl_admin_ui_local', $admin_ui_localize );
  438. // //} elseif ( 'apl_design' === $screen->id || 'edit-apl_design' === $screen->id ) {
  439. // TODO Add handling APL Designs without extra code from APL_Post_Lists..
  440. } elseif ( 'adv-post-list_page_apl_settings' === $screen->id ) {
  441. // If we are not viewing APL Post List area, then return.
  442. // SETTINGS PAGE.
  443. // SCRIPTS.
  444. wp_register_script(
  445. 'apl-settings-js',
  446. APL_URL . 'admin/js/settings.js',
  447. array(
  448. 'jquery',
  449. 'jquery-ui-core',
  450. 'jquery-ui-widget',
  451. 'jquery-ui-button',
  452. 'jquery-ui-dialog',
  453. ),
  454. APL_VERSION,
  455. true
  456. );
  457. wp_register_script(
  458. 'apl-settings-ui-js',
  459. APL_URL . 'admin/js/settings-ui.js',
  460. array(
  461. 'jquery',
  462. 'jquery-ui-core',
  463. 'jquery-ui-widget',
  464. 'jquery-ui-dialog',
  465. 'jquery-ui-position',
  466. 'jquery-ui-tooltip',
  467. ),
  468. APL_VERSION,
  469. true
  470. );
  471. wp_enqueue_script( 'postbox' );
  472. wp_enqueue_script( 'apl-settings-js' );
  473. wp_enqueue_script( 'apl-settings-ui-js' );
  474. // STYLES.
  475. wp_enqueue_style(
  476. 'apl-admin-settings-css',
  477. APL_URL . 'admin/css/settings.css',
  478. false,
  479. APL_VERSION,
  480. false
  481. );
  482. wp_enqueue_style(
  483. 'apl-admin-ui-css',
  484. APL_URL . 'admin/css/jquery-ui/jquery-ui.css',
  485. false,
  486. APL_VERSION,
  487. false
  488. );
  489. $trans_arr = array(
  490. 'default_alert_title' => __( 'Alert', 'advanced-post-list' ),
  491. 'default_alert_message' => __( 'No Message to Display.', 'advanced-post-list' ),
  492. 'fileName_empty_alert_title' => __( 'Filename Required', 'advanced-post-list' ),
  493. 'fileName_empty_alert_message' => __( 'A filename doesn\'t exist. \n Please enter a filename before exporting.', 'advanced-post-list' ),
  494. 'import_no_file_message' => __( 'No file(s) selected. Please choose a JSON file to upload.', 'advanced-post-list' ),
  495. 'import_no_file_title' => __( 'No File', 'advanced-post-list' ),
  496. 'import_invalid_file_message' => __( 'Invalid file type. Please choose a JSON file to upload.', 'advanced-post-list' ),
  497. 'import_invalid_file_title' => __( 'Invalid File', 'advanced-post-list' ),
  498. 'import_success_message' => __( 'Data successfully imported.', 'advanced-post-list' ),
  499. 'import_success_title' => __( 'Complete', 'advanced-post-list' ),
  500. 'import_overwrite_dialog_title' => __( 'Overwrite Presets', 'advanced-post-list' ),
  501. 'fileName_char_alert_title' => __( 'Illegal Characters', 'advanced-post-list' ),
  502. 'fileName_char_alert_message1' => __( 'Cannot use (< > : " / \\ | , ? *).', 'advanced-post-list' ),
  503. 'fileName_char_alert_message2' => __( 'Please rename your filename.', 'advanced-post-list' ),
  504. );
  505. $trans_ui_arr = array(
  506. 'fileName_char_alert_title' => __( 'Illegal Characters', 'advanced-post-list' ),
  507. 'fileName_char_alert_message1' => __( 'Cannot use (< > : " / \\ | , ? *).', 'advanced-post-list' ),
  508. 'fileName_char_alert_message2' => __( 'Please rename your filename.', 'advanced-post-list' ),
  509. );
  510. $settings_localize = array(
  511. 'export_nonce' => wp_create_nonce( 'apl_settings_export' ),
  512. 'import_nonce' => wp_create_nonce( 'apl_settings_import' ),
  513. 'restoreDefaultsNonce' => wp_create_nonce( 'apl_settings_restore_defaults' ),
  514. 'trans' => $trans_arr,
  515. );
  516. $settings_ui_localize = array(
  517. 'trans' => $trans_ui_arr,
  518. );
  519. wp_localize_script( 'apl-settings-js', 'apl_settings_local', $settings_localize );
  520. wp_localize_script( 'apl-settings-ui-js', 'apl_settings_ui_local', $settings_ui_localize );
  521. global $post_type;
  522. do_action( 'add_meta_boxes', $hook_suffix, $post_type );
  523. $screen_args = array(
  524. 'max' => 2,
  525. 'default' => 2,
  526. );
  527. add_screen_option( 'layout_columns', $screen_args );
  528. } else {
  529. // REGISTER.
  530. // LOCALIZE.
  531. // ENQUEUE.
  532. wp_enqueue_style(
  533. 'apl-admin-wp-editor-css',
  534. APL_URL . 'admin/css/wp-editor.css',
  535. false,
  536. APL_VERSION,
  537. false
  538. );
  539. }// End if().
  540. }
  541. /**
  542. * Disables/Hides Screen Option Settings
  543. *
  544. * Disables / Hides the Screen Option's display Meta Boxes Settings. Basically
  545. * prevents certain Meta Boxes from being hidden, and forces the box to display.
  546. *
  547. * @since 0.4.0
  548. *
  549. * @see 'admin_head' hook.
  550. * @link https://wordpress.stackexchange.com/questions/149602/hiding-metabox-from-screen-options-pull-down
  551. */
  552. public function disable_screen_boxes() {
  553. echo '<style>label[for=apl-post-list-filter-hide] { display: none; }</style>';
  554. echo '<style>#apl-post-list-filter { display: block; }</style>';
  555. }
  556. /**
  557. * Screen Options for 'All Post List' page
  558. *
  559. * Hook 'load-edit.php', sets additional Screen Options.
  560. *
  561. * @see 'load-edit.php' hook.
  562. * @since 0.4.0
  563. */
  564. public function post_list_screen_options_all() {
  565. $screen = get_current_screen();
  566. // Get out of here if we are not on our settings page.
  567. if ( ! is_object( $screen ) || 'edit-apl_post_list' !== $screen->id ) {
  568. return;
  569. }
  570. $options = $screen->get_options();
  571. }
  572. /**
  573. * Screen Options for 'Add New' page
  574. *
  575. * Hook 'load-post-new.php', sets additional Screen Options.
  576. *
  577. * @see 'load-post-new.php' hook.
  578. * @since 0.4.0
  579. */
  580. public function post_list_screen_options_add_new() {
  581. $screen = get_current_screen();
  582. // Get out of here if we are not on our settings page.
  583. if ( ! is_object( $screen ) || 'apl_post_list' !== $screen->id ) {
  584. return;
  585. }
  586. $options = $screen->get_options();
  587. }
  588. /**
  589. * Post List All Posts Columns
  590. *
  591. * Adds additional columns to All Post Lists page.
  592. *
  593. * @since 0.4.0
  594. *
  595. * @see 'manage_apl_post_list_posts_columns'
  596. * @uses manage_${post_type}_posts_columns
  597. * @link https://codex.wordpress.org/Plugin_API/Filter_Reference/manage_$post_type_posts_columns
  598. *
  599. * @param array $columns Columns use in the 'All Post Lists' page.
  600. * @return array
  601. */
  602. public function post_list_posts_columns( $columns ) {
  603. $tmp_date = $columns['date'];
  604. unset( $columns['date'] );
  605. $columns['post_name'] = __( 'Slug', 'advanced-post-list' );
  606. $columns['apl_shortcode'] = __( 'Shortcode', 'advanced-post-list' );
  607. $columns['date'] = $tmp_date;
  608. return $columns;
  609. }
  610. /**
  611. * Post List Custom Column
  612. *
  613. * Adds content to custom column.
  614. *
  615. * @since 0.4.0
  616. *
  617. * @uses manage_${post_type}_posts_columns hook.
  618. * @link https://codex.wordpress.org/Plugin_API/Action_Reference/manage_$post_type_posts_custom_column
  619. *
  620. * @param array $column The name of the column to display. Default: None.
  621. * @param int $post_id The ID of the current post. Can also be taken from the global $post->ID. Default: None.
  622. */
  623. public function post_list_posts_custom_column( $column, $post_id ) {
  624. $args = array(
  625. 'post__in' => array( $post_id ),
  626. 'post_type' => 'apl_post_list',
  627. 'post_status' => array(
  628. 'draft',
  629. 'pending',
  630. 'publish',
  631. 'future',
  632. 'private',
  633. 'trash',
  634. ),
  635. );
  636. $post_lists = new WP_Query( $args );
  637. $post_list = $post_lists->post;
  638. switch ( $column ) {
  639. case 'post_name':
  640. echo esc_attr( $post_list->post_name );
  641. break;
  642. case 'apl_shortcode':
  643. echo '<input value="[post_list name=\'' . esc_attr( $post_list->post_name ) . '\']" type="text" size="32" onfocus="this.select();" onclick="this.select();" readonly="readonly" />';
  644. break;
  645. }
  646. }
  647. /**
  648. * Post List Sortable Columns
  649. *
  650. * Sets Custom Columns to be sortable.
  651. *
  652. * @link https://developer.wordpress.org/reference/hooks/manage_this-screen-id_sortable_columns/
  653. *
  654. * @param array $columns An array of sortable columns.
  655. * @return array
  656. */
  657. public function post_list_sortable_columns( $columns ) {
  658. $columns['post_name'] = 'post_name';
  659. return $columns;
  660. }
  661. /**
  662. * Post List Meta Boxes
  663. *
  664. * Hook 'add_meta_boxes', adds meta boxes used in post lists.
  665. *
  666. * @since 0.4.0
  667. *
  668. * @see $this->_construct Used by.
  669. * @see 'add_meta_boxes' hook.
  670. * @see wp-admin/includes/template.php
  671. * @link https://codex.wordpress.org/Plugin_API/Action_Reference/add_meta_boxes
  672. * @link https://developer.wordpress.org/reference/functions/add_meta_box/
  673. */
  674. public function post_list_meta_boxes() {
  675. add_meta_box(
  676. 'apl-post-list-filter',
  677. __( 'Filter Settings', 'advanced-post-list' ),
  678. array( $this, 'post_list_meta_box_filter' ),
  679. 'apl_post_list',
  680. // 'normal', 'advanced', 'side'.
  681. 'normal',
  682. // 'high', 'sorted', 'core', 'default', 'low'.
  683. 'high'
  684. );
  685. add_meta_box(
  686. 'apl-post-list-display',
  687. __( 'Display Settings', 'advanced-post-list' ),
  688. array( $this, 'post_list_meta_box_design' ),
  689. 'apl_post_list',
  690. 'normal',
  691. 'core'
  692. );
  693. }
  694. /**
  695. * Design Meta Boxes
  696. *
  697. * Hook 'add_meta_boxes', adds meta boxes used in designs.
  698. *
  699. * @since 0.4.0
  700. *
  701. * @see $this->_construct Used by.
  702. * @see 'add_meta_boxes' hook.
  703. * @see wp-admin/includes/template.php
  704. * @link https://codex.wordpress.org/Plugin_API/Action_Reference/add_meta_boxes
  705. * @link https://developer.wordpress.org/reference/functions/add_meta_box/
  706. */
  707. public function design_meta_boxes() {
  708. add_meta_box(
  709. 'apl-post-list-display',
  710. __( 'Display Settings', 'advanced-post-list' ),
  711. array( $this, 'design_meta_box_design' ),
  712. 'apl_design',
  713. 'normal',
  714. 'core'
  715. );
  716. }
  717. /**
  718. * Add Settings Page Meta Boxes
  719. *
  720. * @see $this->_construct Used by.
  721. * @see 'add_meta_boxes' hook.
  722. * @see add_meta_box();
  723. * @link https://codex.wordpress.org/Plugin_API/Action_Reference/add_meta_boxes
  724. * @link https://developer.wordpress.org/reference/functions/add_meta_box/
  725. */
  726. public function settings_meta_boxes() {
  727. add_meta_box(
  728. 'apl-info',
  729. __( 'About', 'advanced-post-list' ),
  730. array( $this, 'settings_meta_box_info' ),
  731. 'adv-post-list_page_apl_settings',
  732. // 'normal', 'advanced', 'side'.
  733. 'side',
  734. // 'high', 'sorted', 'core', 'default', 'low'.
  735. 'core'
  736. );
  737. // TODO - Add Documentation Link to Admin Page/Metabox documentation.
  738. // //$title = '<a id="info16" class="info_a_link" style="float:right;">Export/Import Info<span class="ui-icon ui-icon-info info-icon" style="float:right"></span></a>';
  739. add_meta_box(
  740. 'apl-general',
  741. // //$title . __( 'General Settings', 'advanced-post-list' ),
  742. __( 'General Settings', 'advanced-post-list' ),
  743. array( $this, 'settings_meta_box_general' ),
  744. 'adv-post-list_page_apl_settings',
  745. 'normal',
  746. 'high'
  747. );
  748. add_meta_box(
  749. 'apl-import-export',
  750. __( 'Import / Export', 'advanced-post-list' ),
  751. array( $this, 'settings_meta_box_import_export' ),
  752. 'adv-post-list_page_apl_settings',
  753. 'advanced',
  754. 'core'
  755. );
  756. }
  757. /**
  758. * Settings Info Meta Box
  759. *
  760. * @since 0.4.0
  761. *
  762. * @param WP_Post $post Current WP_Post object.
  763. * @param array $metabox With Meta Box id, title, callback, and args elements.
  764. */
  765. public function settings_meta_box_info( $post, $metabox ) {
  766. $args = array(
  767. 'post' => $post,
  768. 'metabox' => $metabox,
  769. );
  770. apl_get_template( 'admin/meta-box/settings-info.php', $args );
  771. }
  772. /**
  773. * Settings General Settings Meta Box
  774. *
  775. * @since 0.4.0
  776. *
  777. * @param WP_Post $post Current WP_Post object.
  778. * @param array $metabox With Meta Box id, title, callback, and args elements.
  779. */
  780. public function settings_meta_box_general( $post, $metabox ) {
  781. $args = array(
  782. 'post' => $post,
  783. 'metabox' => $metabox,
  784. );
  785. apl_get_template( 'admin/meta-box/settings-general.php', $args );
  786. }
  787. /**
  788. * Settings Import/Export Meta Box
  789. *
  790. * @since 0.4.0
  791. *
  792. * @param WP_Post $post Current WP_Post object.
  793. * @param array $metabox With Meta Box id, title, callback, and args elements.
  794. */
  795. public function settings_meta_box_import_export( $post, $metabox ) {
  796. $args = array(
  797. 'post' => $post,
  798. 'metabox' => $metabox,
  799. );
  800. apl_get_template( 'admin/meta-box/settings-import-export.php', $args );
  801. }
  802. /**
  803. * Post List Filter Meta box Template
  804. *
  805. * @since 0.4.0
  806. *
  807. * @param WP_Post $post Current WP_Post object.
  808. * @param array $metabox With Meta Box id, title, callback, and args elements.
  809. */
  810. public function post_list_meta_box_filter( $post, $metabox ) {
  811. $args = array(
  812. 'post' => $post,
  813. 'metabox' => $metabox,
  814. 'apl_post_tax' => apl_get_post_tax(),
  815. 'apl_tax_terms' => apl_get_tax_terms(),
  816. 'apl_display_post_types' => apl_get_display_post_types(),
  817. );
  818. apl_get_template( 'admin/meta-box/post-list-filter.php', $args );
  819. }
  820. /**
  821. * Post List Design Meta box Template
  822. *
  823. * Hook '$this->post_list_meta_boxes()', renders the Design Meta Box Template.
  824. *
  825. * @since 0.4.0
  826. *
  827. * @param WP_Post $post Current WP_Post object.
  828. * @param array $metabox With Meta Box id, title, callback, and args elements.
  829. */
  830. public function post_list_meta_box_design( $post, $metabox ) {
  831. $args = array(
  832. 'post' => $post,
  833. 'metabox' => $metabox,
  834. );
  835. apl_get_template( 'admin/meta-box/post-list-design.php', $args );
  836. }
  837. /**
  838. * Post List Design Meta box Template
  839. *
  840. * Renders the Design Meta Box Template.
  841. *
  842. * @see self::design_meta_boxes()
  843. * @since 0.4.0
  844. *
  845. * @param WP_Post $post Current WP_Post object.
  846. * @param array $metabox With Meta Box id, title, callback, and args elements.
  847. */
  848. public function design_meta_box_design( $post, $metabox ) {
  849. $args = array(
  850. 'post' => $post,
  851. 'metabox' => $metabox,
  852. );
  853. apl_get_template( 'admin/meta-box/design-design.php', $args );
  854. }
  855. /**
  856. * Draft Post List
  857. *
  858. * Hook for draft Post Transitions with Post Lists.
  859. *
  860. * @since 0.4.0
  861. *
  862. * @param int $post_id
  863. * @param WP_Post $post
  864. */
  865. public function draft_post_list( $post_id, $post ) {
  866. if ( isset( $_REQUEST['action'] ) ) {
  867. if ( 'untrash' === $_REQUEST['action'] ) {
  868. return;
  869. }
  870. }
  871. if ( empty( $post->post_name ) ) {
  872. if ( empty( $post->post_title ) ) {
  873. $post->post_title = 'APL-' . $post->ID;
  874. }
  875. remove_action( 'draft_apl_post_list', array( $this, 'draft_post_list' ) );
  876. $post->post_name = sanitize_title_with_dashes( $post->post_title );
  877. $post_arr = array(
  878. 'ID' => $post->ID,
  879. 'post_title' => $post->post_title,
  880. 'post_name' => $post->post_name,
  881. //'post_status' => $post->post_status,
  882. );
  883. wp_update_post( $post_arr );
  884. add_action( 'draft_apl_post_list', array( $this, 'draft_post_list' ), 10, 2 );
  885. }
  886. $this->post_list_process( $post_id, $post );
  887. }
  888. /**
  889. * Save Post List
  890. *
  891. * Hook for saving object during post transitions.
  892. *
  893. * @since 0.4.0
  894. *
  895. * @see self::current_screen_hooks() Used by.
  896. * @see private_apl_post_list hook.
  897. * @see publish_apl_post_list hook.
  898. * @see pending_apl_post_list hook.
  899. * @see future_apl_post_list hook.
  900. * @see {status}_{post_type} Hook Transitions.
  901. * @link https://codex.wordpress.org/Post_Status_Transitions
  902. *
  903. * @param int $post_id Old post ID.
  904. * @param WP_Post $post Current Post object.
  905. */
  906. public function save_post_list( $post_id, $post ) {
  907. // CHECK AJAX REFERENCE.
  908. // ACTION = editpost
  909. // Doesn't work if there is no action ( Add New )
  910. // //check_admin_referer( 'update-post_' . $post_id );
  911. // //add_action( 'private_apl_post_list', array( $this, 'save_post_list' ), 10, 2 );
  912. // //add_action( 'publish_apl_post_list', array( $this, 'save_post_list' ), 10, 2 );
  913. // //add_action( 'pending_apl_post_list', array( $this, 'save_post_list' ), 10, 2 );
  914. // //add_action( 'future_apl_post_list', array( $this, 'save_post_list' ), 10, 2 );
  915. $this->post_list_process( $post_id, $post );
  916. }
  917. /**
  918. * Draft Design
  919. *
  920. * Hook for draft Post Transitions with Designs.
  921. *
  922. * @since 0.4.0
  923. *
  924. * @param int $post_id Post ID.
  925. * @param WP_Post $post (New) Post Data content.
  926. */
  927. public function draft_design( $post_id, $post ) {
  928. if ( isset( $_REQUEST['action'] ) ) {
  929. if ( 'untrash' === $_REQUEST['action'] ) {
  930. return;
  931. }
  932. }
  933. if ( empty( $post->post_name ) ) {
  934. if ( empty( $post->post_title ) ) {
  935. $post->post_title = 'APL-' . $post->ID;
  936. }
  937. remove_action( 'draft_apl_design', array( $this, 'draft_design' ) );
  938. $post->post_name = sanitize_title_with_dashes( $post->post_title );
  939. $postarr = array(
  940. 'ID' => $post->ID,
  941. 'post_title' => $post->post_title,
  942. 'post_name' => $post->post_name,
  943. );
  944. wp_update_post( $postarr );
  945. add_action( 'draft_apl_design', array( $this, 'draft_design' ), 10, 2 );
  946. }
  947. $this->design_process( $post_id, $post );
  948. }
  949. /**
  950. * Save Design
  951. *
  952. * Hook for saving object during post transitions.
  953. *
  954. * @since 0.4.0
  955. *
  956. * @see self::current_screen_hooks() Used by.
  957. * @see private_apl_design hook.
  958. * @see publish_apl_design hook.
  959. * @see pending_apl_design hook.
  960. * @see future_apl_design hook.
  961. * @see {status}_{post_type} Hook Transitions.
  962. * @link https://codex.wordpress.org/Post_Status_Transitions
  963. *
  964. * @param int $post_id Old post ID.
  965. * @param WP_Post $post Current Post object.
  966. */
  967. public function save_design( $post_id, $post ) {
  968. $this->design_process( $post_id, $post );
  969. }
  970. /**
  971. * WP_Trash_Post APL Post List
  972. *
  973. * Host for trash post transitions with Post Lists.
  974. *
  975. * @since 0.4.0
  976. *
  977. * @link https://developer.wordpress.org/reference/functions/wp_trash_post/
  978. *
  979. * @param int $post_id Post ID. Default is ID of the global $post if EMPTY_TRASH_DAYS equals true.
  980. * @return boolean
  981. */
  982. public function action_wp_trash_post_apl_post_list( $post_id ) {
  983. $args = array(
  984. 'post__in' => array( $post_id ),
  985. 'post_type' => 'apl_post_list',
  986. //'post_status' => 'trash',
  987. );
  988. $post_lists = new WP_Query( $args );
  989. if ( 1 > $post_lists->post_count ) {
  990. return false;
  991. }
  992. $post_list = $post_lists->post;
  993. if ( 'apl_post_list' !== $post_list->post_type ) {
  994. return false;
  995. }
  996. $apl_post_list = new APL_Post_List( $post_list->post_name );
  997. $apl_design = new APL_Design( $apl_post_list->pl_apl_design );
  998. $new_post_list_slug = $post_list->post_name . '__trashed';
  999. $new_design_slug = '';
  1000. if ( ! empty( $post_list->post_name ) ) {
  1001. // //$slug_suffix = apply_filters( 'apl_design_slug_suffix', '-design' );
  1002. $design_slug = apply_filters( 'apl_design_trash_slug', $new_post_list_slug );
  1003. // //$new_design_slug = $design_slug . $slug_suffix;
  1004. $new_design_slug = $design_slug;
  1005. }
  1006. $apl_post_list->pl_apl_design = $new_design_slug;
  1007. $apl_design->slug = $new_design_slug;
  1008. $apl_design->save_design();
  1009. }
  1010. /**
  1011. * Un-Trash for Post List
  1012. *
  1013. * Hook for untrash Post Transition with Post Lists.
  1014. *
  1015. * @since 0.4.0
  1016. * @since 0.4.4 Added stricter APL_Design object referencing.
  1017. *
  1018. * @hook `untrash_post`
  1019. * @link https://codex.wordpress.org/Plugin_API/Action_Reference/untrash_post
  1020. *
  1021. * @param int $post_id ID of the post being untrashed.
  1022. * @return boolean
  1023. */
  1024. public function action_untrash_post_apl_post_list( $post_id ) {
  1025. $args = array(
  1026. 'post__in' => array( $post_id ),
  1027. 'post_type' => 'apl_post_list',
  1028. 'post_status' => 'trash',
  1029. );
  1030. $post_lists = new WP_Query( $args );
  1031. if ( 1 > $post_lists->post_count ) {
  1032. return false;
  1033. }
  1034. $post_list = $post_lists->post;
  1035. if ( 'apl_post_list' !== $post_list->post_type ) {
  1036. return false;
  1037. }
  1038. $apl_post_list = new APL_Post_List( $post_list->post_name );
  1039. $apl_design = new APL_Design( $apl_post_list->pl_apl_design_id );
  1040. $new_post_list_slug = str_replace( '__trashed', '', $post_list->post_name );
  1041. $new_design_slug = '';
  1042. if ( ! empty( $post_list->post_name ) ) {
  1043. // //$slug_suffix = apply_filters( 'apl_design_slug_suffix', '-design' );
  1044. $design_slug = apply_filters( 'apl_design_trash_slug', $new_post_list_slug );
  1045. // //$new_design_slug = $design_slug . $slug_suffix;
  1046. $new_design_slug = $design_slug;
  1047. }
  1048. $apl_post_list->pl_apl_design = $new_design_slug;
  1049. $apl_design->slug = $new_design_slug;
  1050. $apl_design->save_design();
  1051. }
  1052. /**
  1053. * WP_Delete_Post APL Post List
  1054. *
  1055. * Host for delete post transitions with Post Lists.
  1056. *
  1057. * @since 0.4.0
  1058. * @since 0.4.4 Added stricter APL_Design object referencing.
  1059. * @see https://codex.wordpress.org/Plugin_API/Action_Reference/before_delete_post
  1060. *
  1061. * @param int $post_id The post id that is being deleted.
  1062. * @return boolean
  1063. */
  1064. public function action_before_delete_post_apl_post_list( $post_id ) {
  1065. $args = array(
  1066. 'post__in' => array( $post_id ),
  1067. 'post_type' => 'apl_post_list',
  1068. 'post_status' => 'trash',
  1069. );
  1070. $post_lists = new WP_Query( $args );
  1071. if ( 1 > $post_lists->post_count ) {
  1072. return false;
  1073. }
  1074. $post_list = $post_lists->post;
  1075. if ( 'apl_post_list' !== $post_list->post_type ) {
  1076. return false;
  1077. }
  1078. $apl_post_list = new APL_Post_List( $post_list->post_name );
  1079. $apl_design = new APL_Design( $apl_post_list->pl_apl_design_id );
  1080. $apl_design->delete_design();
  1081. }
  1082. /**
  1083. * Save General Settings
  1084. *
  1085. * Uses a lazy REST API built into WP.
  1086. *
  1087. * @uses Hook 'admin_post_{SCREEN ID}' ex. 'admin_post_apl_save_general_settings'.
  1088. * @link https://developer.wordpress.org/reference/hooks/admin_post_action/
  1089. */
  1090. public function save_general_settings() {
  1091. if (
  1092. ! wp_verify_nonce( $_POST['apl_general_settings_nonce'], 'apl_settings_general_save' ) &&
  1093. ! current_user_can( 'administrator' )
  1094. ) {
  1095. wp_die();
  1096. }
  1097. $options = apl_options_load();
  1098. $tmp_ignore_pt = array();
  1099. $post_types = get_post_types( '', 'names' );
  1100. foreach ( $post_types as $post_type ) {
  1101. if ( isset( $_POST[ 'apl_ignore_pt_' . $post_type ] ) ) {
  1102. $input = filter_input( INPUT_POST, 'apl_ignore_pt_' . $post_type, FILTER_SANITIZE_STRING );
  1103. $tmp_ignore_pt[ $post_type ] = sanitize_key( $input );
  1104. }
  1105. }
  1106. $options['ignore_post_types'] = $tmp_ignore_pt;
  1107. if ( isset( $_POST['apl_delete_on_deactivate'] ) ) {
  1108. $input = filter_input( INPUT_POST, 'apl_delete_on_deactivate', FILTER_SANITIZE_STRING );
  1109. if ( 'yes' === $input ) {
  1110. $options['delete_core_db'] = true;
  1111. } elseif ( 'no' === $input ) {
  1112. $options['delete_core_db'] = false;
  1113. } else {
  1114. $options['delete_core_db'] = false;
  1115. }
  1116. }
  1117. if ( isset( $_POST['apl_default_empty_enable'] ) ) {
  1118. $input = filter_input( INPUT_POST, 'apl_delete_on_deactivate', FILTER_SANITIZE_STRING );
  1119. if ( 'yes' === $input ) {
  1120. $options['default_empty_enable'] = true;
  1121. } elseif ( 'no' === $input ) {
  1122. $options['default_empty_enable'] = false;
  1123. } else {
  1124. $options['default_empty_enable'] = true;
  1125. }
  1126. }
  1127. $options['default_empty_output'] = '';
  1128. if ( isset( $_POST['apl_default_empty_message'] ) ) {
  1129. // Sanitize with admins?
  1130. // TODO Possibly change to a WP_Post Object. Db update would be required.
  1131. $tmp_empty_messaage = filter_input( INPUT_POST, 'apl_default_empty_message', FILTER_UNSAFE_RAW );
  1132. $options['default_empty_output'] = $tmp_empty_messaage;
  1133. }
  1134. apl_options_save( $options );
  1135. wp_redirect( 'admin.php?page=apl_settings' );
  1136. //wp_die();
  1137. exit();
  1138. }
  1139. /**
  1140. * Settings Page AJAX Hooks
  1141. *
  1142. * Add AJAX hooks for Settings Page.
  1143. *
  1144. * @uses 'wp_ajax_{name}'
  1145. */
  1146. public function add_settings_ajax_hooks() {
  1147. add_action( 'wp_ajax_apl_settings_export', array( $this, 'ajax_settings_export' ) );
  1148. add_action( 'wp_ajax_apl_export', 'apl_export' );
  1149. add_action( 'wp_ajax_apl_settings_import', array( $this, 'ajax_settings_import' ) );
  1150. add_action( 'wp_ajax_apl_import', 'apl_import' );
  1151. add_action( 'wp_ajax_apl_settings_restore_defaults', array( $this, 'ajax__restore_defaults' ) );
  1152. }
  1153. /**
  1154. * MCE External Plugins
  1155. *
  1156. * @since 0.4.2
  1157. *
  1158. * @see 'mce_external_plugins' filter hook
  1159. * @link https://codex.wordpress.org/Plugin_API/Filter_Reference/mce_external_plugins
  1160. *
  1161. * @param array $plugin_array Other plugin's mce buttons.
  1162. * @return mixed
  1163. */
  1164. public function mce_external_plugins( $plugin_array ) {
  1165. $plugin_array['advanced_post_list'] = APL_URL . 'admin/js/wp-editor-mce.js';
  1166. return $plugin_array;
  1167. }
  1168. /**
  1169. * MCE Buttons
  1170. *
  1171. * @since 0.4.2
  1172. *
  1173. * @uses 'mce_buttons' filter hook
  1174. * @link https://codex.wordpress.org/Plugin_API/Filter_Reference/mce_buttons,_mce_buttons_2,_mce_buttons_3,_mce_buttons_4
  1175. *
  1176. * @param array $buttons Buttons for MCE Editor.
  1177. * @return mixed
  1178. */
  1179. public function mce_buttons( $buttons ) {
  1180. array_push( $buttons, 'apl_post_list' );
  1181. array_push( $buttons, 'dropcap', 'showrecent' );
  1182. return $buttons;
  1183. }
  1184. /**
  1185. * TinyMCE Extra Vars
  1186. *
  1187. * @since 0.4.0
  1188. */
  1189. public function tinymce_extra_vars() {
  1190. $args = array(
  1191. 'post_type' => 'apl_post_list',
  1192. 'post_status' => array(
  1193. 'draft',
  1194. 'pending',
  1195. 'publish',
  1196. 'future',
  1197. 'private',
  1198. 'trash',
  1199. ),
  1200. );
  1201. $pl_query = new WP_Query( $args );
  1202. $post_lists = array();
  1203. foreach ( $pl_query->posts as $apl_post ) {
  1204. $post_lists[ $apl_post->post_name ] = $apl_post->post_title;
  1205. }
  1206. $trans = array(
  1207. 'button_title' => __( 'APL Post List', 'advanced-post-list' ),
  1208. 'button_tooltip' => __( 'Insert APL Shortcode', 'advanced-post-list' ),
  1209. 'window_title' => __( 'APL Shortcode', 'advanced-post-list' ),
  1210. 'window_body_1_label' => __( 'Post List', 'advanced-post-list' ),
  1211. 'window_body_1_tooltip' => __( 'Select the Post List you want.', 'advanced-post-list' ),
  1212. );
  1213. $apl_tinymce_json = wp_json_encode(
  1214. array(
  1215. 'post_lists' => $post_lists,
  1216. 'trans' => $trans,
  1217. )
  1218. );
  1219. ?>
  1220. <script type="text/javascript">
  1221. var apl_tinyMCE = <?php echo $apl_tinymce_json; ?>;
  1222. </script>
  1223. <?php
  1224. }
  1225. /**
  1226. * AJAX Settings Page Export
  1227. *
  1228. * Handles the AJAX call for exporting data.
  1229. *
  1230. * @since 0.3
  1231. * @since 0.4.4 Added stricter APL_Design object referencing.
  1232. */
  1233. public function ajax_settings_export() {
  1234. check_ajax_referer( 'apl_settings_export' );
  1235. $rtn_data = array(
  1236. 'action' => 'apl_export',
  1237. '_ajax_nonce' => wp_create_nonce( 'apl_export' ),
  1238. );
  1239. $tmp_filename = 'file_export_name';
  1240. if ( isset( $_POST['filename'] ) ) {
  1241. $tmp_filename = filter_input( INPUT_POST, 'filename', FILTER_SANITIZE_STRING );
  1242. }
  1243. $rtn_data['filename'] = $tmp_filename;
  1244. $export_data = array(
  1245. 'version' => APL_VERSION,
  1246. 'apl_post_list_arr' => array(),
  1247. 'apl_design_arr' => array(),
  1248. );
  1249. $args = array(
  1250. 'post_type' => 'apl_post_list',
  1251. 'post_status' => 'publish',
  1252. 'posts_per_page' => -1,
  1253. );
  1254. $apl_post_lists = new WP_Query( $args );
  1255. foreach ( $apl_post_lists->posts as $post_obj ) {
  1256. $apl_post_list = new APL_Post_List( $post_obj->post_name );
  1257. $apl_design = new APL_Design( $apl_post_list->pl_apl_design_id );
  1258. $export_data['apl_post_list_arr'][] = $apl_post_list->slug;
  1259. $export_data['apl_design_arr'][] = $apl_design->slug;
  1260. }
  1261. update_option( 'apl_export_data', $export_data );
  1262. echo json_encode( $rtn_data );
  1263. wp_die();
  1264. }
  1265. /**
  1266. * AJAX Settings Import
  1267. *
  1268. * @since 0.4.0
  1269. * @since 0.4.4 Handle 0.3 and 0.4 database types separately, and stricter handling APL_Design with APL_Post_List.
  1270. *
  1271. * @uses add_settings_ajax_hooks().
  1272. * @uses wp_ajax_apl_settings_import.
  1273. */
  1274. public function ajax_settings_import() {
  1275. check_ajax_referer( 'apl_settings_import' );
  1276. $raw_content = array();
  1277. $i = 0;
  1278. while ( isset( $_FILES[ 'file_' . $i ] ) ) {
  1279. /**
  1280. * @type array $file_{$i} {
  1281. * @type int $error
  1282. * @type string $name
  1283. * @type int $size
  1284. * @type string $tmp_name
  1285. * @type string $type
  1286. * }
  1287. */
  1288. if ( isset( $_FILES[ 'file_' . $i ]['tmp_name'] ) && ! empty( $_FILES[ 'file_' . $i ]['tmp_name'] ) ) {
  1289. $file_error = ( isset( $_FILES[ 'file_' . $i ]['error'] ) ) ? intval( filter_var( $_FILES[ 'file_' . $i ]['error'], FILTER_SANITIZE_NUMBER_INT ) ) : 1;
  1290. $file_type = ( isset( $_FILES[ 'file_' . $i ]['type'] ) ) ? filter_var( $_FILES[ 'file_' . $i ]['type'], FILTER_SANITIZE_STRING ) : '';
  1291. $file_tmp = ( isset( $_FILES[ 'file_' . $i ]['type'] ) ) ? filter_var( $_FILES[ 'file_' . $i ]['tmp_name'], FILTER_SANITIZE_STRING ) : '';
  1292. // 2 = validate_file() - windows drive paths are needed for development purposes.
  1293. if ( ! $file_error && 'application/json' === $file_type && ! in_array( validate_file( $file_tmp ), array( 1, 3 ) ) ) {
  1294. $file_content = file_get_contents( $_FILES[ 'file_' . $i ]['tmp_name'] );
  1295. $raw_content[] = json_decode( $file_content );
  1296. }
  1297. }
  1298. $i++;
  1299. }
  1300. $imported_content = array();
  1301. foreach ( $raw_content as $v1_content ) {
  1302. $update_items = array();
  1303. if (
  1304. isset( $v1_content->version ) &&
  1305. preg_match( '/([0-9]+)\.([0-9]+)(?:\.([0-9]+))?(?:\.([0-9]|dev|a[1-9]|b[1-9]+))?/', $v1_content->version ) )
  1306. {
  1307. $version = $v1_content->version;
  1308. } else {
  1309. return new WP_Error( 'apl_admin', __( 'Version number is missing or invalid in imported file.', 'advanced-post-list' ) );
  1310. }
  1311. // 0.3 Database.
  1312. if ( version_compare( '0.3.0', $version, '<' ) && version_compare( '0.4.0', $version, '>' ) ) {
  1313. if ( isset( $v1_content->presetDbObj ) && $v1_content->presetDbObj instanceof APL_Preset_Db ) {
  1314. $update_items['preset_db'] = $v1_content->presetDbObj;
  1315. }
  1316. }
  1317. // 0.4+ Database.
  1318. elseif( version_compare( '0.4.0', $version, '<' ) ) {
  1319. if ( isset( $v1_content->apl_post_list_arr ) && $v1_content->apl_post_list_arr instanceof APL_Post_List ) {
  1320. $update_items['apl_post_list_arr'] = $v1_content->apl_post_list_arr;
  1321. }
  1322. if ( isset( $v1_content->apl_design_arr ) && $v1_content->apl_design_arr instanceof APL_Design ) {
  1323. $update_items['apl_design_arr'] = $v1_content->apl_design_arr;
  1324. }
  1325. }
  1326. $updater = new APL_Updater( $version, $update_items, 'OBJECT' );
  1327. $imported_content[] = array(
  1328. 'apl_post_list_arr' => $updater->apl_post_list_arr,
  1329. 'apl_design_arr' => $updater->apl_design_arr,
  1330. );
  1331. }
  1332. $overwrite_apl_post_list = array();
  1333. $overwrite_apl_design = array();
  1334. $data_overwrite_post_list = array();
  1335. $data_overwrite_design = array();
  1336. foreach ( $imported_content as $v1_content ) {
  1337. // POST LISTS.
  1338. foreach ( $v1_content['apl_post_list_arr'] as $v2_post_list ) {
  1339. $db_post_list = new APL_Post_List( $v2_post_list->slug );
  1340. // Check if Post List (ID) already exists.
  1341. if ( 0 !== $db_post_list->id ) {
  1342. $overwrite_apl_post_list[] = $v2_post_list;
  1343. $data_overwrite_post_list[] = $v2_post_list->slug;
  1344. // DESIGNS.
  1345. foreach ( $v1_content['apl_design_arr'] as $k3_design => $v3_design ) {
  1346. if ( $v3_design->slug === $v2_post_list->pl_apl_design ) {
  1347. $overwrite_apl_design[] = $v3_design;
  1348. $data_overwrite_design[] = $v3_design->slug;
  1349. unset( $v1_content['apl_design_arr'][ $k3_design ] );
  1350. break;
  1351. }
  1352. }
  1353. } else {
  1354. // DESIGNS.
  1355. foreach ( $v1_content['apl_design_arr'] as $k3_design => $v3_design ) {
  1356. if ( $v3_design->slug === $v2_post_list->pl_apl_design ) {
  1357. // Uses slug instead of ID.
  1358. $db_design = new APL_Design( $v3_design->slug );
  1359. if ( 0 !== $db_design->id ) {
  1360. // Add Variable to Database.
  1361. //$v2_post_list->pl_apl_design_id = $v3_design->id;
  1362. //$v2_post_list->pl_apl_design_slug = $v3_design->slug;
  1363. //$this->import_process_post_list( $v2_post_list );
  1364. $overwrite_apl_post_list[] = $v2_post_list;
  1365. $data_overwrite_post_list[] = $v2_post_list->slug;
  1366. $overwrite_apl_design[] = $v3_design;
  1367. $data_overwrite_design[] = $v3_design->slug;
  1368. } else {
  1369. // Add Variable to Database.
  1370. //$db_design = $this->import_process_design( $v3_design );
  1371. $db_design = $v3_design;
  1372. $this->import_process_post_list_design( $v2_post_list, $db_design );
  1373. }
  1374. unset( $v1_content['apl_design_arr'][ $k3_design ] );
  1375. break;
  1376. }
  1377. }
  1378. // Add Variable to Database.
  1379. //$this->import_process_post_list( $v2_post_list, $db_design );
  1380. }
  1381. }
  1382. // DESIGNS.
  1383. // Catch any remaining designs that may be left.
  1384. foreach ( $v1_content['apl_design_arr'] as $v2_design ) {
  1385. // Uses slug instead of ID.
  1386. $db_design = new APL_Design( $v2_design->slug );
  1387. if ( 0 !== $db_design->id ) {
  1388. $overwrite_apl_design[] = $v2_design;
  1389. $data_overwrite_design[] = $v2_design->slug;
  1390. } else {
  1391. // Add Variable to Database.
  1392. $this->import_process_design( $v2_design );
  1393. }
  1394. }
  1395. }
  1396. update_option( 'apl_import_overwrite_post_list', $overwrite_apl_post_list );
  1397. update_option( 'apl_import_overwrite_design', $overwrite_apl_design );
  1398. $rtn_data = array(
  1399. 'action' => 'apl_import',
  1400. '_ajax_nonce' => wp_create_nonce( 'apl_import' ),
  1401. 'overwrite_post_list' => $data_overwrite_post_list,
  1402. 'overwrite_design' => $data_overwrite_design,
  1403. );
  1404. echo json_encode( $rtn_data );
  1405. die();
  1406. }
  1407. /**
  1408. * AJAX - Restore Defaults
  1409. *
  1410. * @since 0.5
  1411. *
  1412. * @return void
  1413. */
  1414. public function ajax__restore_defaults() {
  1415. check_ajax_referer( 'apl_settings_restore_defaults' );
  1416. $this->restore_default_presets();
  1417. wp_send_json_success( 'Success' );
  1418. }
  1419. /**
  1420. * Restore Default Presets
  1421. *
  1422. * @since 0.5
  1423. */
  1424. public function restore_default_presets() {
  1425. include_once APL_DIR . 'admin/includes/default-presets.php';
  1426. $apl_post_list_default = apl_restore_post_list_default();
  1427. $apl_design_excerpt_divided = apl_restore_design_excerpt_divided();
  1428. $apl_design_page_content_divided = apl_restore_design_page_content_divided();
  1429. $apl_design_footer_list = apl_restore_design_footer_list();
  1430. $apl_post_list_default->title = 'Excerpt Divided';
  1431. $apl_post_list_default->slug = 'excerpt-divided';
  1432. $apl_post_list_default->pl_apl_design = 'excerpt-divided';
  1433. $this->import_process_post_list_design( $apl_post_list_default, $apl_design_excerpt_divided );
  1434. $apl_post_list_default->title = 'Page Content Divided';
  1435. $apl_post_list_default->slug = 'page-content-divided';
  1436. $apl_post_list_default->pl_apl_design = 'page-content-divided';
  1437. $this->import_process_post_list_design( $apl_post_list_default, $apl_design_page_content_divided );
  1438. $apl_post_list_default->title = 'Footer List';
  1439. $apl_post_list_default->slug = 'footer-list';
  1440. $apl_post_list_default->pl_apl_design = 'footer-list';
  1441. $this->import_process_post_list_design( $apl_post_list_default, $apl_design_footer_list );
  1442. }
  1443. /**
  1444. * Process Import for Post Lists
  1445. *
  1446. * @ignore
  1447. * @since 0.4.0
  1448. * @since 0.4.4 Added APL_Design ID, but disabled for future use.
  1449. *
  1450. * @param APL_Post_List $apl_post_list Current post list to import.
  1451. */
  1452. private function import_process_post_list( $apl_post_list ) {
  1453. $tmp_apl_post_list = new APL_Post_List( $apl_post_list->slug );
  1454. $tmp_apl_post_list->title = $apl_post_list->title ?: $tmp_apl_post_list->title;
  1455. $tmp_apl_post_list->post_type = $apl_post_list->post_type ? json_decode( json_encode( $apl_post_list->post_type ), true ) : $tmp_apl_post_list->post_type ;
  1456. $tmp_apl_post_list->tax_query = $apl_post_list->tax_query ? json_decode( json_encode( $apl_post_list->tax_query ), true ) : $tmp_apl_post_list->tax_query;
  1457. $tmp_apl_post_list->post_parent__in = $apl_post_list->post_parent__in ? json_decode( json_encode( $apl_post_list->post_parent__in ), true ) : $tmp_apl_post_list->post_parent__in;
  1458. $tmp_apl_post_list->post_parent_dynamic = $apl_post_list->post_parent_dynamic ? json_decode( json_encode( $apl_post_list->post_parent_dynamic ), true ) : $tmp_apl_post_list->post_parent_dynamic;
  1459. $tmp_apl_post_list->posts_per_page = $apl_post_list->posts_per_page ?: $tmp_apl_post_list->posts_per_page;
  1460. $tmp_apl_post_list->offset = $apl_post_list->offset ?: $tmp_apl_post_list->offset;
  1461. $tmp_apl_post_list->order_by = $apl_post_list->order_by ?: $tmp_apl_post_list->order_by;
  1462. $tmp_apl_post_list->order = $apl_post_list->order ?: $tmp_apl_post_list->order;
  1463. $tmp_apl_post_list->post_status = $apl_post_list->post_status ? json_decode( json_encode( $apl_post_list->post_status ), true ) : $tmp_apl_post_list->post_status;
  1464. $tmp_apl_post_list->perm = $apl_post_list->perm ?: $tmp_apl_post_list->perm;
  1465. $tmp_apl_post_list->author__bool = $apl_post_list->author__bool ?: $tmp_apl_post_list->author__bool;
  1466. $tmp_apl_post_list->author__in = $apl_post_list->author__in ?: $tmp_apl_post_list->author__in;
  1467. $tmp_apl_post_list->ignore_sticky_posts = $apl_post_list->ignore_sticky_posts ?: $tmp_apl_post_list->ignore_sticky_posts;
  1468. $tmp_apl_post_list->post__not_in = $apl_post_list->post__not_in ?: $tmp_apl_post_list->post__not_in;
  1469. $tmp_apl_post_list->pl_exclude_current = $apl_post_list->pl_exclude_current ?: $tmp_apl_post_list->pl_exclude_current;
  1470. $tmp_apl_post_list->pl_exclude_dupes = $apl_post_list->pl_exclude_dupes ?: $tmp_apl_post_list->pl_exclude_dupes;
  1471. $tmp_apl_post_list->pl_apl_design = $apl_post_list->pl_apl_design ?: $tmp_apl_post_list->pl_apl_design;
  1472. $tmp_apl_post_list->pl_apl_design_id = $apl_post_list->pl_apl_design_id ?: $tmp_apl_post_list->pl_apl_design_id;
  1473. $tmp_apl_post_list->pl_apl_design_slug = $apl_post_list->pl_apl_design_slug ?: $tmp_apl_post_list->pl_apl_design_slug;
  1474. $tmp_apl_post_list->save_post_list();
  1475. }
  1476. /**
  1477. * Process Import for Post List with Design
  1478. *
  1479. * @ignore
  1480. * @since 0.4.0
  1481. *
  1482. * @param APL_Post_List $apl_post_list
  1483. * @param APL_Design $apl_design
  1484. */
  1485. private function import_process_post_list_design( $apl_post_list, $apl_design ) {
  1486. $tmp_apl_post_list = new APL_Post_List( $apl_post_list->slug );
  1487. $tmp_apl_post_list->title = $apl_post_list->title ?: $tmp_apl_post_list->title;
  1488. $tmp_apl_post_list->post_type = $apl_post_list->post_type ? json_decode( json_encode( $apl_post_list->post_type ), true ) : $tmp_apl_post_list->post_type ;
  1489. $tmp_apl_post_list->tax_query = $apl_post_list->tax_query ? json_decode( json_encode( $apl_post_list->tax_query ), true ) : $tmp_apl_post_list->tax_query;
  1490. $tmp_apl_post_list->post_parent__in = $apl_post_list->post_parent__in ? json_decode( json_encode( $apl_post_list->post_parent__in ), true ) : $tmp_apl_post_list->post_parent__in;
  1491. $tmp_apl_post_list->post_parent_dynamic = $apl_post_list->post_parent_dynamic ? json_decode( json_encode( $apl_post_list->post_parent_dynamic ), true ) : $tmp_apl_post_list->post_parent_dynamic;
  1492. $tmp_apl_post_list->posts_per_page = $apl_post_list->posts_per_page ?: $tmp_apl_post_list->posts_per_page;
  1493. $tmp_apl_post_list->offset = $apl_post_list->offset ?: $tmp_apl_post_list->offset;
  1494. $tmp_apl_post_list->order_by = $apl_post_list->order_by ?: $tmp_apl_post_list->order_by;
  1495. $tmp_apl_post_list->order = $apl_post_list->order ?: $tmp_apl_post_list->order;
  1496. $tmp_apl_post_list->post_status = $apl_post_list->post_status ? json_decode( json_encode( $apl_post_list->post_status ), true ) : $tmp_apl_post_list->post_status;
  1497. $tmp_apl_post_list->perm = $apl_post_list->perm ?: $tmp_apl_post_list->perm;
  1498. $tmp_apl_post_list->author__bool = $apl_post_list->author__bool ?: $tmp_apl_post_list->author__bool;
  1499. $tmp_apl_post_list->author__in = $apl_post_list->author__in ?: $tmp_apl_post_list->author__in;
  1500. $tmp_apl_post_list->ignore_sticky_posts = $apl_post_list->ignore_sticky_posts ?: $tmp_apl_post_list->ignore_sticky_posts;
  1501. $tmp_apl_post_list->post__not_in = $apl_post_list->post__not_in ?: $tmp_apl_post_list->post__not_in;
  1502. $tmp_apl_post_list->pl_exclude_current = $apl_post_list->pl_exclude_current ?: $tmp_apl_post_list->pl_exclude_current;
  1503. $tmp_apl_post_list->pl_exclude_dupes = $apl_post_list->pl_exclude_dupes ?: $tmp_apl_post_list->pl_exclude_dupes;
  1504. $apl_design = $this->import_process_design( $apl_design );
  1505. $tmp_apl_post_list->pl_apl_design = $apl_post_list->pl_apl_design ?: $tmp_apl_post_list->pl_apl_design;
  1506. $tmp_apl_post_list->pl_apl_design_id = $apl_design->id ?: $tmp_apl_post_list->pl_apl_design_id;
  1507. $tmp_apl_post_list->pl_apl_design_slug = $apl_design->slug ?: $tmp_apl_post_list->pl_apl_design_slug;
  1508. $tmp_apl_post_list->save_post_list();
  1509. }
  1510. /**
  1511. * Process Import for Designs
  1512. *
  1513. * @ignore
  1514. * @since 0.4.0
  1515. *
  1516. * @param APL_Design $apl_design
  1517. * @return APL_Design
  1518. */
  1519. private function import_process_design( $apl_design ) {
  1520. $new_apl_design = new APL_Design( $apl_design->slug );
  1521. $new_apl_design->title = $apl_design->title ?: $new_apl_design->title;
  1522. $new_apl_design->before = $apl_design->before ?: $new_apl_design->before;
  1523. $new_apl_design->content = $apl_design->content ?: $new_apl_design->content;
  1524. $new_apl_design->after = $apl_design->after ?: $new_apl_design->after;
  1525. $new_apl_design->empty = $apl_design->empty ?: $new_apl_design->empty;
  1526. $new_apl_design->save_design();
  1527. return $new_apl_design;
  1528. }
  1529. /**
  1530. * Process Post List Form
  1531. *
  1532. * Gathers data from the Post List edit page.
  1533. *
  1534. * @ignore
  1535. * @since 0.4.0
  1536. * @since 0.4.4 Added stricter APL_Design object referencing.
  1537. * @access private
  1538. *
  1539. * @see $this->save_post_list()
  1540. *
  1541. * @param int $post_id Old post ID.
  1542. * @param WP_Post $post Current Post object.
  1543. */
  1544. private function post_list_process( $post_id, $post ) {
  1545. $old_post = get_post( $post_id );
  1546. $apl_post_list = new APL_Post_List( $old_post->post_name );
  1547. // post_type[0,1,2] = 'any' || 'none' || array(); CANNOT USE 'any' IN ARRAY.
  1548. // tax_query[pt1,pt2,pt3] = array( empty ) || array( query ).
  1549. // post_parent__in.
  1550. // post_parent_dynamic.
  1551. $tmp_post_type = array();
  1552. $tmp_tax_query = array();
  1553. $tmp_post_parent__in = array();
  1554. $tmp_post_parent_dynamic = array();
  1555. $post_type_names = apl_get_display_post_types();
  1556. $post_type_names = array_merge( array( 'any' => __( 'Any / All', 'advanced-post-list' ) ), $post_type_names );
  1557. foreach ( $post_type_names as $k_pt_slug => $v_pt_title ) {
  1558. // POST TYPES (ACTIVE).
  1559. if ( isset( $_POST[ 'apl_toggle-' . $k_pt_slug ] ) ) {
  1560. $tmp_tax_query[ $k_pt_slug ] = array();
  1561. // If 'Any / All' is toggled, then treat 'any' differently and skip the rest.
  1562. if ( 'any' === $k_pt_slug ) {
  1563. // 'any' TAXONOMY.
  1564. $tmp_post_type[] = 'any';
  1565. if ( isset( $_POST['apl_multiselect_taxonomies-any'] ) ) {
  1566. $tmp_tax_query[ $k_pt_slug ] = $this->post_list_process_tax_query( $k_pt_slug );
  1567. }
  1568. break;
  1569. } else {
  1570. // POST TYPE TAXONOMIES.
  1571. $tmp_post_type[] = array( $k_pt_slug );
  1572. if ( isset( $_POST[ 'apl_multiselect_taxonomies-' . $k_pt_slug ] ) ) {
  1573. $tmp_tax_query[ $k_pt_slug ] = $this->post_list_process_tax_query( $k_pt_slug );
  1574. }
  1575. // PAGE PARENTS.
  1576. if ( is_post_type_hierarchical( $k_pt_slug ) ) {
  1577. $tmp_post_parent_dynamic[ $k_pt_slug ] = false;
  1578. if ( isset( $_POST[ 'apl_page_parent_dynamic-' . $k_pt_slug ] ) ) {
  1579. $tmp_post_parent_dynamic[ $k_pt_slug ] = true;
  1580. }
  1581. $page_args = array(
  1582. 'post_type' => $k_pt_slug,
  1583. 'posts_per_page' => -1,
  1584. 'order' => 'DESC',
  1585. 'orderby' => 'id',
  1586. );
  1587. $page_query = new WP_Query( $page_args );
  1588. while ( $page_query->have_posts() ) {
  1589. $page_query->the_post();
  1590. if ( isset( $_POST[ 'apl_page_parent-' . $k_pt_slug . '-' . $page_query->post->ID ] ) ) {
  1591. if ( ! isset( $tmp_post_parent__in[ $k_pt_slug ] ) ) {
  1592. $tmp_post_parent__in[ $k_pt_slug ] = array();
  1593. }
  1594. $tmp_post_parent__in[ $k_pt_slug ][] = $page_query->post->ID;
  1595. }
  1596. }
  1597. wp_reset_postdata();
  1598. }
  1599. }// End if().
  1600. }// End if().
  1601. }// End foreach().
  1602. $apl_post_list->post_type = $tmp_post_type;
  1603. $apl_post_list->tax_query = $tmp_tax_query;
  1604. $apl_post_list->post_parent__in = $tmp_post_parent__in;
  1605. $apl_post_list->post_parent_dynamic = $tmp_post_parent_dynamic;
  1606. // posts_per_page.
  1607. $tmp_posts_per_page = 5;
  1608. if ( isset( $_POST['apl_posts_per_page'] ) ) {
  1609. $p_posts_per_page = filter_input( INPUT_POST, 'apl_posts_per_page', FILTER_SANITIZE_NUMBER_INT );
  1610. $tmp_posts_per_page = intval( $p_posts_per_page );
  1611. }
  1612. $apl_post_list->posts_per_page = $tmp_posts_per_page;
  1613. // offset.
  1614. $tmp_offset = 5;
  1615. if ( isset( $_POST['apl_offset'] ) ) {
  1616. $p_offset = filter_input( INPUT_POST, 'apl_offset', FILTER_SANITIZE_NUMBER_INT );
  1617. $tmp_offset = intval( $p_offset );
  1618. }
  1619. $apl_post_list->offset = $tmp_offset;
  1620. // order_by.
  1621. // order.
  1622. $tmp_order_by = 'none';
  1623. $tmp_order = 'DESC';
  1624. if ( isset( $_POST['apl_order_by'] ) ) {
  1625. $order_by = filter_input( INPUT_POST, 'apl_order_by', FILTER_SANITIZE_STRING );
  1626. $tmp_order_by = $order_by;
  1627. if ( 'none' !== $order_by && isset( $_POST['apl_order'] ) ) {
  1628. $order = filter_input( INPUT_POST, 'apl_order', FILTER_SANITIZE_STRING );
  1629. $tmp_order = $order;
  1630. }
  1631. }
  1632. $apl_post_list->order_by = $tmp_order_by;
  1633. $apl_post_list->order = $tmp_order;
  1634. // post_status = array ( 'public', 'publish' ).
  1635. $tmp_post_status = 'any';
  1636. if ( isset( $_POST['apl_post_status_1'] ) ) {
  1637. $p_post_status_1 = array_map( 'sanitize_key', $_POST['apl_post_status_1'] );
  1638. $p_post_status_2 = array();
  1639. if ( 'none' === $p_post_status_1[0] || 'any' === $p_post_status_1[0] ) {
  1640. $tmp_post_status = $p_post_status_1[0];
  1641. } else {
  1642. // add 'public' &| 'private'
  1643. if ( isset( $_POST['apl_post_status_2'] ) ) {
  1644. $p_post_status_2 = array_map( 'sanitize_key', $_POST['apl_post_status_2'] );
  1645. }
  1646. $tmp_post_status = array_merge( $p_post_status_1, $p_post_status_2 );
  1647. }
  1648. }
  1649. $apl_post_list->post_status = $tmp_post_status;
  1650. // perm.
  1651. $tmp_perm = 'none';
  1652. if ( isset( $_POST['apl_perm'] ) ) {
  1653. $tmp_perm = filter_input( INPUT_POST, 'apl_perm', FILTER_SANITIZE_STRING );
  1654. }
  1655. $apl_post_list->perm = $tmp_perm;
  1656. // author_in = (boolean).
  1657. // author = array( ).
  1658. $tmp_author__bool = 'none';
  1659. $tmp_author__in = array();
  1660. if ( isset( $_POST['apl_author__bool'] ) ) {
  1661. $tmp_author__bool = filter_input( INPUT_POST, 'apl_author__bool', FILTER_SANITIZE_STRING );
  1662. if ( 'none' !== $tmp_author__bool && isset( $_POST['apl_author__in'] ) ) {
  1663. $tmp_author__in = array_map( 'intval', $_POST['apl_author__in'] );
  1664. }
  1665. }
  1666. $apl_post_list->author__bool = $tmp_author__bool;
  1667. $apl_post_list->author__in = $tmp_author__in;
  1668. // post__not_in.
  1669. $tmp_post__not_in = array();
  1670. if ( isset( $_POST['apl_post__not_in'] ) ) {
  1671. $p_post__not_in = filter_input( INPUT_POST, 'apl_post__not_in', FILTER_SANITIZE_STRING );
  1672. if ( ! empty( $p_post__not_in ) ) {
  1673. $tmp_post__not_in = array_map( 'absint', explode( ',', $p_post__not_in ) );
  1674. }
  1675. }
  1676. $apl_post_list->post__not_in = $tmp_post__not_in;
  1677. // ignore_stick_posts.
  1678. $tmp_ignore_sticky_posts = true;
  1679. if ( isset( $_POST['apl_sticky_posts'] ) ) {
  1680. $p_ignore_sticky_posts = filter_input( INPUT_POST, 'apl_sticky_posts', FILTER_SANITIZE_STRING );
  1681. $tmp_ignore_sticky_posts = false;
  1682. }
  1683. $apl_post_list->ignore_sticky_posts = $tmp_ignore_sticky_posts;
  1684. // pl_exclude_current.
  1685. $tmp_pl_exclude_current = false;
  1686. if ( isset( $_POST['apl_pl_exclude_current'] ) ) {
  1687. $p_pl_exclude_current = filter_input( INPUT_POST, 'apl_pl_exclude_current', FILTER_SANITIZE_STRING );
  1688. $tmp_pl_exclude_current = true;
  1689. }
  1690. $apl_post_list->pl_exclude_current = $tmp_pl_exclude_current;
  1691. // pl_exclude_dupes.
  1692. $tmp_pl_exclude_dupes = false;
  1693. if ( isset( $_POST['apl_pl_exclude_dupes'] ) ) {
  1694. $p_pl_exclude_dupes = filter_input( INPUT_POST, 'apl_pl_exclude_dupes', FILTER_SANITIZE_STRING );
  1695. $tmp_pl_exclude_dupes = true;
  1696. }
  1697. $apl_post_list->pl_exclude_dupes = $tmp_pl_exclude_dupes;
  1698. $new_design_slug = '';
  1699. if ( ! empty( $post->post_name ) ) {
  1700. $new_design_slug = $post->post_name;
  1701. }
  1702. $tmp_apl_design = $this->post_list_process_apl_design( $apl_post_list->pl_apl_design, $new_design_slug );
  1703. $apl_post_list->pl_apl_design = $tmp_apl_design->slug;
  1704. $apl_post_list->pl_apl_design_id = $tmp_apl_design->id;
  1705. $apl_post_list->pl_apl_design_slug = $tmp_apl_design->slug;
  1706. }
  1707. /**
  1708. * Process Tax Query
  1709. *
  1710. * Processes the taxonomies and returns 'multiple arrays' simular to $args['tax_query'].
  1711. *
  1712. * @ignore
  1713. * @since 0.4.0
  1714. * @access private
  1715. *
  1716. * @see WP_Query Args
  1717. * @link https://gist.github.com/luetkemj/2023628
  1718. *
  1719. * @param string $post_type Post Type slug.
  1720. * @return array Tax_Query used in WP_Query Args.
  1721. */
  1722. private function post_list_process_tax_query( $post_type ) {
  1723. // Get the list of active taxonomies.
  1724. $p_taxonomies = array_map( 'sanitize_key', $_POST[ 'apl_multiselect_taxonomies-' . $post_type ] );
  1725. $tmp_tax_query = array();
  1726. $tmp_req_tax = 'OR';
  1727. foreach ( $p_taxonomies as $v1_taxonomy ) {
  1728. // Check 'require' as an active checkbox.
  1729. // Else process other checkboxes.
  1730. if ( 'require' === $v1_taxonomy ) {
  1731. $tmp_req_tax = 'AND';
  1732. } else {
  1733. // Check Require Terms.
  1734. $tmp_terms_req = 'IN';
  1735. if ( isset( $_POST[ 'apl_terms_req-' . $post_type . '-' . $v1_taxonomy ] ) ) {
  1736. $tmp_terms_req = 'AND';
  1737. }
  1738. // Check Dynamic Terms.
  1739. $tmp_terms_dynamic = false;
  1740. if ( isset( $_POST[ 'apl_terms_dynamic-' . $post_type . '-' . $v1_taxonomy ] ) ) {
  1741. $tmp_terms_dynamic = true;
  1742. }
  1743. // TERM LOOP.
  1744. $arg_terms = array(
  1745. 'taxonomy' => $v1_taxonomy,
  1746. 'hide_empty' => false,
  1747. );
  1748. $terms = get_terms( $arg_terms );
  1749. $tmp_terms = array();
  1750. $tmp_terms_slug = array();
  1751. foreach ( $terms as $v2_term_obj ) {
  1752. // Check 'any' term, and if set, skip other terms. break;
  1753. if ( isset( $_POST[ 'apl_term-' . $post_type . '-' . $v1_taxonomy . '-any' ] ) ) {
  1754. // No reason to have dynamic true with 'any'; fallback method.
  1755. $tmp_terms[] = 0;
  1756. $tmp_terms_dynamic = false;
  1757. break;
  1758. } elseif ( isset( $_POST[ 'apl_term-' . $post_type . '-' . $v1_taxonomy . '-' . $v2_term_obj->term_id ] ) ) {
  1759. $tmp_terms[] = $v2_term_obj->term_id;
  1760. $tmp_terms_slug[ $v2_term_obj->term_id ] = $v2_term_obj->slug;
  1761. }
  1762. }
  1763. $tmp_tax_query[] = array(
  1764. 'taxonomy' => $v1_taxonomy,
  1765. 'field' => 'id', // Or 'slug'.
  1766. 'terms' => $tmp_terms,
  1767. 'include_children' => false,
  1768. 'operator' => $tmp_terms_req, // 'IN' | 'AND' | --'NOT IN'--
  1769. //'apl_terms_req' = $tmp_terms_req;
  1770. 'apl_terms_slug' => $tmp_terms_slug,
  1771. 'apl_terms_dynamic' => $tmp_terms_dynamic,
  1772. );
  1773. }// End if().
  1774. } // End foreach().
  1775. $tmp_tax_query['relation'] = $tmp_req_tax;
  1776. return $tmp_tax_query;
  1777. }
  1778. /**
  1779. * Process Design Meta Box
  1780. *
  1781. * Processes the incoming data to APL Designs.
  1782. *
  1783. * @ignore
  1784. * @since 0.4.0
  1785. * @since 0.4.4 Added stricter APL_Design object referencing; Changed to return APL_Design.
  1786. * @access private
  1787. *
  1788. * @param string $apl_design_slug Current active slug.
  1789. * @param string $new_design_slug New slug relative to $this->pl_apl_design.
  1790. * @return APL_Design Slug used in $this->pl_apl_design.
  1791. */
  1792. private function post_list_process_apl_design( $apl_design_slug, $new_design_slug ) {
  1793. $apl_design = new APL_Design( $apl_design_slug );
  1794. // SLUG / KEY.
  1795. //if ( $new_design_slug !== $apl_design_slug && '-design' !== $new_design_slug ) {
  1796. if ( $new_design_slug !== $apl_design_slug ) {
  1797. $apl_design->title = $new_design_slug;
  1798. $apl_design->slug = sanitize_title_with_dashes( $new_design_slug );
  1799. }
  1800. // BEFORE.
  1801. $tmp_apl_design_before = '';
  1802. if ( isset( $_POST['apl_before'] ) ) {
  1803. $tmp_apl_design_before = filter_input( INPUT_POST, 'apl_before', FILTER_UNSAFE_RAW );
  1804. }
  1805. $apl_design->before = $tmp_apl_design_before;
  1806. // CONTENT.
  1807. $tmp_apl_design_content = '';
  1808. if ( isset( $_POST['apl_content'] ) ) {
  1809. $tmp_apl_design_content = filter_input( INPUT_POST, 'apl_content', FILTER_UNSAFE_RAW );
  1810. }
  1811. $apl_design->content = $tmp_apl_design_content;
  1812. // AFTER.
  1813. $tmp_apl_design_after = '';
  1814. if ( isset( $_POST['apl_after'] ) ) {
  1815. $tmp_apl_design_after = filter_input( INPUT_POST, 'apl_after', FILTER_UNSAFE_RAW );
  1816. }
  1817. $apl_design->after = $tmp_apl_design_after;
  1818. // EMPTY MESSAGE.
  1819. $tmp_apl_design_empty = '';
  1820. if ( isset( $_POST['apl_empty_enable'] ) && isset( $_POST['apl_empty_message'] ) ) {
  1821. $tmp_apl_design_empty = filter_input( INPUT_POST, 'apl_empty_message', FILTER_UNSAFE_RAW );
  1822. }
  1823. $apl_design->empty = $tmp_apl_design_empty;
  1824. // Save APL_Design.
  1825. $apl_design->save_design();
  1826. return $apl_design;
  1827. }
  1828. /**
  1829. * Process APL Design Class
  1830. *
  1831. * @since 0.4.0
  1832. * @since 0.4.4 Added stricter APL_Design object referencing.
  1833. * @access private
  1834. *
  1835. * @param int $post_id Contains the ID of the post type.
  1836. * @param WP_Post $post New Post Data content to save/update.
  1837. */
  1838. private function design_process( $post_id, $post ) {
  1839. $apl_design = new APL_Design( $post_id );
  1840. // BEFORE.
  1841. $tmp_apl_design_before = '';
  1842. if ( isset( $_POST['apl_before'] ) ) {
  1843. $tmp_apl_design_before = filter_input( INPUT_POST, 'apl_before', FILTER_UNSAFE_RAW );
  1844. }
  1845. $apl_design->before = $tmp_apl_design_before;
  1846. // CONTENT.
  1847. $tmp_apl_design_content = '';
  1848. if ( isset( $_POST['apl_content'] ) ) {
  1849. $tmp_apl_design_content = filter_input( INPUT_POST, 'apl_content', FILTER_UNSAFE_RAW );
  1850. }
  1851. $apl_design->content = $tmp_apl_design_content;
  1852. // AFTER.
  1853. $tmp_apl_design_after = '';
  1854. if ( isset( $_POST['apl_after'] ) ) {
  1855. $tmp_apl_design_after = filter_input( INPUT_POST, 'apl_after', FILTER_UNSAFE_RAW );
  1856. }
  1857. $apl_design->after = $tmp_apl_design_after;
  1858. // EMPTY MESSAGE.
  1859. $tmp_apl_design_empty = '';
  1860. if ( isset( $_POST['apl_empty_enable'] ) && isset( $_POST['apl_empty_message'] ) ) {
  1861. $tmp_apl_design_empty = filter_input( INPUT_POST, 'apl_empty_message', FILTER_UNSAFE_RAW );
  1862. }
  1863. $apl_design->empty = $tmp_apl_design_empty;
  1864. }
  1865. /*
  1866. * *************************************************************************
  1867. * **** PRIVATE FUNCTIONS **************************************************
  1868. * *************************************************************************
  1869. */
  1870. /**
  1871. * Get Post Type & Taxonomies
  1872. *
  1873. * Gets and returns an array of Post_Types => Taxonomies.
  1874. *
  1875. * @deprecated 0.4.4.1 Use apl_get_post_tax()
  1876. *
  1877. * @ignore
  1878. * @since 0.4.0
  1879. * @access private
  1880. *
  1881. * @return array Post_Type = > Name, Taxonomy Array.
  1882. */
  1883. private function get_post_tax() {
  1884. $rtn_post_tax = array();
  1885. $post_types = apl_get_display_post_types();
  1886. // Add to rtn {post_type} => {array( taxonomies )}.
  1887. $rtn_post_tax['any']['name'] = __( 'Any / All', 'advanced-post-list' );
  1888. $taxonomy_names = get_taxonomies( '', 'names' );
  1889. foreach ( $taxonomy_names as $name ) {
  1890. $rtn_post_tax['any']['tax_arr'][] = $name;
  1891. }
  1892. foreach ( $post_types as $k_slug => $v_name ) {
  1893. $rtn_post_tax[ $k_slug ]['name'] = $v_name;
  1894. $rtn_post_tax[ $k_slug ]['tax_arr'] = get_object_taxonomies( $k_slug, 'names' );
  1895. }
  1896. // Return Post_Tax.
  1897. return $rtn_post_tax;
  1898. }
  1899. /**
  1900. * Get Taxonomies & Terms
  1901. *
  1902. * Gets and returns an array of Taxonomies => Terms.
  1903. *
  1904. * @deprecated 0.4.4.1 Use apl_get_tax_terms().
  1905. *
  1906. * @see get_terms()
  1907. * @link https://developer.wordpress.org/reference/functions/get_terms/
  1908. *
  1909. * @ignore
  1910. * @since 0.4.0
  1911. * @access private
  1912. *
  1913. * @return array Taxonomy => Term.
  1914. */
  1915. private function get_tax_terms() {
  1916. $rtn_tax_terms = array();
  1917. // Get Taxonomy Names.
  1918. $taxonomy_names = get_taxonomies( '', 'names' );
  1919. // Loop foreach taxonomy. Get terms, and foreach term add to taxonomy.
  1920. foreach ( $taxonomy_names as $taxonomy ) {
  1921. $args = array(
  1922. 'taxonomy' => $taxonomy,
  1923. 'hide_empty' => false,
  1924. );
  1925. $terms = get_terms( $args );
  1926. // Set slug.
  1927. $rtn_tax_terms[ $taxonomy ] = array();
  1928. foreach ( $terms as $term ) {
  1929. $rtn_tax_terms[ $taxonomy ][] = $term->term_id;
  1930. }
  1931. }
  1932. // Return Tax_Terms.
  1933. return $rtn_tax_terms;
  1934. }
  1935. /**
  1936. * Get Post Types to Display
  1937. *
  1938. * Displays a *valid* list of post types that also aren't on the global ignore list.
  1939. *
  1940. * @ignore
  1941. * @since 0.4.0
  1942. * @access private
  1943. *
  1944. * @see $this->_ignore_post_types.
  1945. *
  1946. * @return array List of Post Types.
  1947. */
  1948. private function get_display_post_types() {
  1949. $rtn_post_types = array();
  1950. $post_type_objs = get_post_types( '', 'objects' );
  1951. // Remove ignored Post Types.
  1952. $ignore_post_types = apl_get_display_post_types();
  1953. foreach ( $ignore_post_types as $value ) {
  1954. unset( $post_type_objs[ $value ] );
  1955. }
  1956. foreach ( $post_type_objs as $key => $value ) {
  1957. $rtn_post_types[ $key ] = $value->labels->singular_name;
  1958. }
  1959. return $rtn_post_types;
  1960. }
  1961. }