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

/wp/wp-content/plugins/kc-settings/kc-settings.php

https://bitbucket.org/akeda/bmw-id-hris
PHP | 869 lines | 631 code | 149 blank | 89 comment | 140 complexity | 83e06414a25bee049bd102c6bc643841 MD5 | raw file
  1. <?php
  2. /**
  3. * @package KC_Settings
  4. * @version 2.8.5
  5. */
  6. /*
  7. Plugin name: KC Settings
  8. Plugin URI: http://kucrut.org/kc-settings/
  9. Description: Easily create plugin/theme settings page, custom fields metaboxes, term meta and user meta settings.
  10. Version: 2.8.5
  11. Author: Dzikri Aziz
  12. Author URI: http://kucrut.org/
  13. License: GPL v2
  14. Text Domain: kc-settings
  15. */
  16. final class kcSettings {
  17. const version = '2.8.5';
  18. protected static $data = array(
  19. 'paths' => '',
  20. 'pages' => array('media-upload-popup'),
  21. 'messages' => array(),
  22. 'notices' => array( 'updated' => array(), 'error' => array() ),
  23. 'settings' => array(),
  24. 'defaults' => array(),
  25. 'kcsb' => array(),
  26. 'kids' => array(),
  27. 'blacklist' => array(
  28. 'theme' => array(
  29. 'multiinput', 'multiselect', 'special', 'editor', 'checkbox',
  30. 'file', 'image', 'upload', 'media',
  31. 'date', 'datetime', 'datetime-local', 'week', 'month', 'time',
  32. ),
  33. 'menu_item' => array(
  34. 'multiinput', 'editor', 'file', 'image', 'upload', 'media',
  35. 'date', 'datetime', 'datetime-local', 'week', 'month', 'time',
  36. ),
  37. 'menu_nav' => array(
  38. 'editor', 'multiinput',
  39. ),
  40. ),
  41. 'is_kcs_page' => false,
  42. 'field_defaults' => array(),
  43. 'media_fields' => array(),
  44. );
  45. public static function setup() {
  46. $paths = self::_paths( __FILE__ );
  47. if ( !is_array($paths) )
  48. return false;
  49. self::$data['paths'] = $paths;
  50. self::$data['standalone'] = current_filter() == 'plugins_loaded';
  51. require_once "{$paths['inc']}/form.php";
  52. require_once "{$paths['inc']}/helper.php";
  53. # i18n
  54. $mo_file = $paths['inc'].'/languages/kc-settings-'.get_locale().'.mo';
  55. if ( is_readable($mo_file) )
  56. load_textdomain( 'kc-settings', $mo_file );
  57. self::_set_field_defaults();
  58. add_action( 'admin_notices', array(__CLASS__, '_admin_notices') );
  59. add_action( 'init', array(__CLASS__, 'init'), 99 );
  60. # Debug bar extension
  61. require_once "{$paths['inc']}/debug-bar-ext.php";
  62. add_filter( 'debug_bar_panels', array(__CLASS__, 'debug_bar_ext') );
  63. }
  64. private static function _set_field_defaults() {
  65. self::$data['field_defaults'] = array(
  66. 'media' => array(
  67. 'multiple' => false,
  68. 'mime_type' => '_all',
  69. 'frame_title' => __( 'Select', 'kc-settings' ), // Title of the media manager lightbox
  70. 'select_button' => __( 'Select', 'kc-settings' ), // Button text
  71. 'insert_button' => __( 'Select', 'kc-settings' ), // Button text
  72. 'preview_size' => 'thumbnail',
  73. 'animate' => 500,
  74. ),
  75. );
  76. }
  77. public static function init() {
  78. # Get children (plugins/themes that depend on KC Settings)
  79. self::$data['kids'] = apply_filters( 'kc_settings_kids', array() );
  80. # Setup termmeta table
  81. self::_setup_termmeta_table();
  82. # Register scripts n styles
  83. self::_sns_register();
  84. # Options helpers
  85. require_once self::$data['paths']['inc'] . '/options.php';
  86. kcSettings_options::init();
  87. # Include samples (for development)
  88. //self::_samples( array('01_plugin', '02_post', '03_term', '04_user', '05_theme', '06_attachment', '07_menu_item', '08_menu_nav') );
  89. # Get all settings
  90. self::_bootstrap_settings();
  91. # Backend-only stuff
  92. if ( is_admin() )
  93. self::_admin_init();
  94. # Theme customizer
  95. if ( isset(self::$data['settings']['theme']) && !empty(self::$data['settings']) )
  96. require_once self::$data['paths']['inc'] . '/theme.php';
  97. }
  98. public static function _admin_init() {
  99. # Register settings
  100. if ( self::$data['settings'] ) {
  101. foreach ( array_keys(self::$data['settings']) as $type ) {
  102. if ( $type === 'theme' )
  103. continue;
  104. require_once self::$data['paths']['inc']."/{$type}.php";
  105. if ( $type == 'plugin' ) {
  106. foreach ( self::$data['settings']['plugin'] as $group )
  107. new kcSettings_plugin( $group );
  108. # Lock
  109. add_filter( 'plugin_action_links', array(__CLASS__, '_lock'), 10, 4 );
  110. }
  111. else {
  112. call_user_func( array("kcSettings_{$type}", 'init') );
  113. }
  114. }
  115. }
  116. # Admin body class
  117. add_action( 'admin_body_class', array(__CLASS__, 'admin_body_class') );
  118. # Admin scripts n styles
  119. add_action( 'admin_enqueue_scripts', array(__CLASS__, '_sns_admin') );
  120. # Builder: only load if NOT bundled
  121. if ( self::$data['standalone'] ) {
  122. require_once( self::$data['paths']['inc'].'/builder.php' );
  123. kcSettings_builder::init();
  124. }
  125. add_action( 'wp_ajax_kc_get_image_url', 'kc_ajax_get_image_url' );
  126. }
  127. /**
  128. * Set plugin paths
  129. */
  130. public static function _paths( $file, $inc_suffix = '-inc' ) {
  131. if ( !file_exists($file) )
  132. return false;
  133. $file_info = pathinfo( $file );
  134. $file_info['parent'] = basename( $file_info['dirname'] );
  135. $locations = array(
  136. 'plugins' => array( WP_PLUGIN_DIR, plugins_url() ),
  137. 'mu-plugins' => array( WPMU_PLUGIN_DIR, WPMU_PLUGIN_URL ),
  138. 'themes' => array( get_theme_root(), get_theme_root_uri() )
  139. );
  140. $valid = false;
  141. foreach ( $locations as $key => $loc ) {
  142. $dir = $loc[0];
  143. if ( $file_info['parent'] != $key )
  144. $dir .= "/{$file_info['parent']}";
  145. if ( file_exists($dir) && is_dir( $dir ) ) {
  146. $valid = true;
  147. break;
  148. }
  149. }
  150. if ( !$valid )
  151. return false;
  152. $paths = array();
  153. $url = $locations[$key][1];
  154. if ( $file_info['parent'] != $key )
  155. $url .= "/{$file_info['parent']}";
  156. $inc_prefix = "{$file_info['filename']}{$inc_suffix}";
  157. $paths['file'] = $file;
  158. $paths['p_file'] = kc_plugin_file( $file );
  159. $paths['inc'] = "{$dir}/{$inc_prefix}";
  160. $paths['url'] = $url;
  161. $paths['scripts'] = "{$url}/{$inc_prefix}/scripts";
  162. $paths['styles'] = "{$url}/{$inc_prefix}/styles";
  163. return $paths;
  164. }
  165. /**
  166. * Get all settings
  167. */
  168. private static function _bootstrap_settings() {
  169. # Settings bootstrap error messages
  170. self::$data['messages']['bootstrap'] = array(
  171. 'no_prefix' => __( "One of your settings doesn't have <b>prefix</b> set.", 'kc-settings'),
  172. 'no_menu_title' => __( "One of your settings doesn't have <b>menu title</b> set.", 'kc-settings'),
  173. 'no_page_title' => __( "One of your settings doesn't have <b>page title</b> set.", 'kc-settings'),
  174. 'no_options' => __( "One of your settings doesn't have <b>options</b> set.", 'kc-settings'),
  175. 'section_no_cb' => __( "One of your section's callback is not callable.", 'kc-settings'),
  176. 'section_no_fields' => __( "One of your settings' section doesn't have <b>fields</b> set.", 'kc-settings'),
  177. 'section_no_id' => __( "One of your settings' sections doesn't have <b>ID</b> set.", 'kc-settings'),
  178. 'section_no_title' => __( "One of your settings' sections doesn't have <b>title</b> set.", 'kc-settings'),
  179. 'section_metabox_old' => __( 'One of your settings is still using the old format for metabox setting, please migrate it to the new one.', 'kc-settings'),
  180. 'field_no_id' => __( "One of your fields doesn't have <b>ID</b> set.", 'kc-settings'),
  181. 'field_no_title' => __( "One of your fields doesn't have <b>title</b> set.", 'kc-settings'),
  182. 'field_no_type' => __( "One of your fields doesn't have <b>type</b> set.", 'kc-settings'),
  183. 'field_no_opt' => __( "One of your fields doesn't have the required <b>options</b> set.", 'kc-settings'),
  184. 'field_no_cb' => __( "One of your fields doesn't have the required <b>callback</b> set, or is not callable.", 'kc-settings'),
  185. 'field_nested_multi' => __( 'multiinput fields cannot have a multiinput sub-field.', 'kc-settings')
  186. );
  187. $kcsb = array(
  188. 'settings' => get_option( 'kcsb' ),
  189. '_ids' => array(
  190. 'settings' => array(),
  191. 'sections' => array(),
  192. 'fields' => array()
  193. ),
  194. 'items' => array()
  195. );
  196. $settings = array(
  197. 'plugin' => array(),
  198. 'theme' => array(),
  199. 'post' => array(),
  200. 'term' => array(),
  201. 'user' => array(),
  202. 'menu_item' => array(),
  203. 'menu_nav' => array()
  204. );
  205. # Process settings from the builder
  206. if ( is_array($kcsb['settings']) && !empty($kcsb['settings']) ) {
  207. $pre_options = get_class_vars( 'kcSettings_options' );
  208. $pre_options_cb = get_class_methods( 'kcSettings_options_cb' );
  209. $pre_options_cb_args = array( 'tax', 'pt' );
  210. foreach ( $kcsb['settings'] as $setting ) {
  211. $sID = $setting['id'];
  212. $kcsb['_ids']['settings'][] = $sID;
  213. if ( isset($setting['status']) && !$setting['status'] )
  214. continue;
  215. $type = $setting['type'];
  216. $sections = array();
  217. foreach ( $setting['sections'] as $section ) {
  218. $kcsb['_ids']['sections'][] = $section['id'];
  219. $fields = array();
  220. foreach ( $section['fields'] as $field ) {
  221. $kcsb['_ids']['fields'][] = $field['id'];
  222. if ( in_array($field['type'], array('checkbox', 'radio', 'select', 'multiselect')) ) {
  223. # Predefined options
  224. if ( isset($field['option_type']) && $field['option_type'] == 'predefined' ) {
  225. if ( isset($pre_options[$field['option_predefined']]) ) {
  226. $field['options'] = $pre_options[$field['option_predefined']];
  227. }
  228. elseif ( in_array($field['option_predefined'], $pre_options_cb) ) {
  229. $field['options'] = array('kcSettings_options_cb', $field['option_predefined']);
  230. foreach ( $pre_options_cb_args as $_cb_arg )
  231. if ( isset($field["option_predefined_cb_{$_cb_arg}"]) )
  232. $field['args'] = $field["option_predefined_cb_{$_cb_arg}"];
  233. }
  234. unset( $field['option_type'] );
  235. unset( $field['option_predefined'] );
  236. unset( $field['option_predefined_cb'] );
  237. unset( $field['option_predefined_cb_pt'] );
  238. unset( $field['option_predefined_cb_tax'] );
  239. }
  240. # Custom options
  241. else {
  242. $options = array();
  243. foreach ( $field['options'] as $option ) {
  244. $options[$option['key']] = $option['label'];
  245. }
  246. $field['options'] = $options;
  247. }
  248. }
  249. elseif ( $field['type'] === 'editor' ) {
  250. if ( !isset($field['editor_settings']) )
  251. $field['editor_settings'] = array();
  252. $editor_settings = array();
  253. foreach ( array('media_buttons', 'tinymce', 'quicktags') as $key )
  254. $editor_settings[$key] = in_array($key, $field['editor_settings']);
  255. $field['editor_settings'] = $editor_settings;
  256. }
  257. $fields[$field['id']] = $field;
  258. }
  259. $section['fields'] = $fields;
  260. $sections[$section['id']] = $section;
  261. }
  262. $setting['options'] = $sections;
  263. unset ( $setting['sections'] );
  264. $kcsb['items'][$type][$sID] = $setting;
  265. if ( $type == 'plugin' ) {
  266. $settings[$type][$sID] = $setting;
  267. }
  268. elseif ( $type == 'user' ) {
  269. $settings[$type][$sID] = array( $setting['options'] );
  270. }
  271. else {
  272. $object = ( $type == 'post') ? $setting['post_type'] : $setting['taxonomy'];
  273. $settings[$type][$sID] = array($object => $setting['options']);
  274. }
  275. }
  276. self::$data['kcsb'] = $kcsb;
  277. }
  278. $settings = self::_validate_settings( $settings );
  279. if ( empty($settings) )
  280. return;
  281. self::$data['settings'] = $settings;
  282. }
  283. # Validate settings
  284. private static function _validate_settings( $settings ) {
  285. $nu = array();
  286. foreach ( $settings as $type => $groups ) {
  287. $groups = apply_filters( "kc_{$type}_settings", $settings[$type] );
  288. if ( empty($groups) ) {
  289. unset( $settings[$type] );
  290. continue;
  291. }
  292. foreach ( $groups as $g_idx => $group ) {
  293. if ( isset($group['status']) && !$group['status'] )
  294. continue;
  295. if ( !is_array($group) || empty($group) ) {
  296. trigger_error( self::$data['messages']['bootstrap']['no_options'] );
  297. unset( $groups[$g_idx] );
  298. continue;
  299. }
  300. if ( $type == 'plugin' ) {
  301. $g_idx = $group['prefix'];
  302. foreach ( array('prefix', 'menu_title', 'page_title', 'options') as $c ) {
  303. if ( !isset($group[$c]) || empty($group[$c]) || ($c == 'options' && !is_array($group[$c])) ) {
  304. trigger_error( self::$data['messages']['bootstrap']["no_{$c}"] );
  305. unset( $groups[$g_idx] );
  306. continue 2;
  307. }
  308. # Set page display type
  309. if ( !isset($group['display']) )
  310. $group['display'] = 'plain';
  311. # Set the location
  312. if ( !isset($group['menu_location']) )
  313. $group['menu_location'] = 'options-general.php';
  314. }
  315. $group['options'] = self::_validate_sections( $type, $group['options'], $group );
  316. if ( empty($group['options']) )
  317. $group = null;
  318. }
  319. elseif ( in_array($type, array('post', 'term', 'user')) ) {
  320. foreach ( $group as $obj => $sections ) {
  321. $group[$obj] = self::_validate_sections( $type, $sections );
  322. if ( empty($group[$obj]) )
  323. $group = null;
  324. }
  325. }
  326. elseif ( $type == 'theme' ) {
  327. $group['options'] = self::_validate_sections( $type, $group['options'], $group );
  328. if ( empty($group['options']) )
  329. $group = null;
  330. }
  331. elseif ( $type == 'menu_item' || $type == 'menu_nav' ) {
  332. $group = self::_validate_sections( $type, $group );
  333. if ( empty($group) )
  334. $group = null;
  335. }
  336. # Include this group only if it's valid
  337. if ( !empty($group) ) {
  338. # Plugin/themes only: Set page layout
  339. if ( isset($group['options']['has_sidebar']) ) {
  340. unset( $group['options']['has_sidebar'] );
  341. $group['has_sidebar'] = true;
  342. }
  343. $nu[$type][$g_idx] = $group;
  344. }
  345. }
  346. }
  347. # Merge Post, Term & User metadata
  348. foreach ( array('post', 'term', 'user') as $type ) {
  349. if ( isset($nu[$type]) )
  350. $nu[$type] = self::_bootstrap_meta( $nu[$type] );
  351. }
  352. # Merge nav menu item metadata
  353. foreach ( array('menu_item', 'menu_nav') as $_type ) {
  354. if ( isset($nu[$_type]) ) {
  355. $_temp = array();
  356. foreach ( $nu[$_type] as $group )
  357. $_temp = array_merge( $_temp, $group );
  358. $nu[$_type] = $_temp;
  359. }
  360. }
  361. return $nu;
  362. }
  363. # Validate each setting's section
  364. private static function _validate_sections( $type, $sections, $group = '' ) {
  365. $defaults = array();
  366. foreach ( $sections as $s_idx => $section ) {
  367. unset( $sections[$s_idx] );
  368. # Section check: id & title
  369. foreach ( array('id', 'title') as $c ) {
  370. if ( !isset($section[$c]) || empty($section[$c]) ) {
  371. trigger_error( self::$data['messages']['bootstrap']["section_no_{$c}"] );
  372. unset( $sections[$s_idx] );
  373. continue 2;
  374. }
  375. }
  376. # Custom callback for section?
  377. if ( $type == 'plugin' && isset($section['cb']) ) {
  378. if ( !is_callable($section['cb']) ) {
  379. trigger_error( self::$data['messages']['bootstrap']['section_no_cb'] );
  380. continue;
  381. }
  382. }
  383. else {
  384. if ( !isset($section['fields']) || !is_array($section['fields']) || empty($section['fields']) ) {
  385. trigger_error( self::$data['messages']['bootstrap']['section_no_fields'] );
  386. continue;
  387. }
  388. else {
  389. $fields = self::_validate_fields( $type, $section['fields'] );
  390. if ( empty($fields['fields']) )
  391. continue;
  392. $section['fields'] = $fields['fields'];
  393. if ( !empty($fields['defaults']) )
  394. $defaults[$type][$group['prefix']][$section['id']] = $fields['defaults'];
  395. }
  396. }
  397. # Plugin/theme/post only: Set metabox position & priority
  398. if ( $type == 'post' || ($type == 'plugin' && $group['display']) == 'metabox' ) {
  399. # TODO: remove in version 3.0
  400. if ( isset($section['priority']) ) {
  401. trigger_error( self::$data['messages']['bootstrap']['section_metabox_old'] );
  402. $metabox_priority = $section['priority'];
  403. unset( $section['priority'] );
  404. }
  405. $metabox_default = array(
  406. 'context' => 'normal',
  407. 'priority' => isset($metabox_priority) ? $metabox_priority : 'default',
  408. 'button_text' => __('Save Changes'),
  409. );
  410. $metabox = isset($section['metabox']) ? $section['metabox'] : array();
  411. $section['metabox'] = wp_parse_args( $metabox, $metabox_default );
  412. unset( $metabox_priority );
  413. }
  414. # Plugin/themes metabox position
  415. if ( $type == 'plugin' && $section['metabox']['context'] == 'side' )
  416. $sections['has_sidebar'] = true;
  417. $sections[$section['id']] = $section;
  418. }
  419. # Store default values
  420. if ( !empty($defaults) )
  421. self::$data['defaults'] = array_merge_recursive( self::$data['defaults'], $defaults );
  422. return $sections;
  423. }
  424. private static function _validate_fields( $type, $fields, $sub = false ) {
  425. $defaults = array();
  426. $need_options = array( 'select', 'radio', 'checkbox' );
  427. $file_modes = array('single', 'radio', 'checkbox');
  428. foreach ( $fields as $idx => $field ) {
  429. unset( $fields[$idx] );
  430. # Blacklisted field types
  431. if ( isset(self::$data['blacklist'][$type]) && in_array($field['type'], self::$data['blacklist'][$type]) )
  432. continue;
  433. # Field check: id, title & type
  434. foreach ( array('id', 'title', 'type') as $c ) {
  435. if ( !isset($field[$c]) || empty($field[$c]) ) {
  436. trigger_error( self::$data['messages']['bootstrap']["field_no_{$c}"] );
  437. continue 2;
  438. }
  439. }
  440. # Field check: need options
  441. if ( in_array($field['type'], $need_options) && !isset($field['options']) ) {
  442. trigger_error( self::$data['messages']['bootstrap']['field_no_opt'] );
  443. continue;
  444. }
  445. # Field check: file mode
  446. elseif ( $field['type'] == 'file' ) {
  447. if ( !isset($field['mode']) || !in_array($field['mode'], $file_modes) )
  448. $field['mode'] = 'radio';
  449. if ( empty($field['mime_type']) )
  450. $field['mime_type'] = 'all';
  451. }
  452. elseif ( $field['type'] == 'special' ) {
  453. if ( !isset($field['cb']) || !is_callable($field['cb']) ) {
  454. trigger_error( self::$data['messages']['bootstrap']['field_no_cb'] );
  455. continue;
  456. }
  457. }
  458. elseif ( $field['type'] == 'multiinput' ) {
  459. if ( $sub ) {
  460. trigger_error( self::$data['messages']['bootstrap']['field_nested_multi'] );
  461. continue;
  462. }
  463. $subfields = ( isset($field['subfields']) && !empty($field['subfields']) ) ? self::_validate_fields( $type, $field['subfields'], true ) : array( 'fields' => array() );
  464. if ( empty($subfields['fields']) ) {
  465. $field['subfields'] = array(
  466. array(
  467. 'id' => 'key',
  468. 'title' => __('Key', 'kc-settings'),
  469. 'type' => 'text',
  470. ),
  471. array(
  472. 'id' => 'value',
  473. 'title' => __('Value', 'kc-settings'),
  474. 'type' => 'textarea',
  475. ),
  476. );
  477. }
  478. else {
  479. $field['subfields'] = $subfields['fields'];
  480. }
  481. }
  482. elseif ( $field['type'] == 'media' ) {
  483. $field = wp_parse_args( $field, self::$data['field_defaults']['media'] );
  484. }
  485. # Has default value?
  486. if ( ($type == 'plugin' || $type == 'theme') && isset($field['default']) )
  487. $defaults[$field['id']] = $field['default'];
  488. $fields[$field['id']] = $field;
  489. }
  490. return array('fields' => $fields, 'defaults' => $defaults );
  491. }
  492. /**
  493. * Bootstrap Metadata
  494. *
  495. * Merge all the custom fields set by themes/plugins. Also rebuild the array.
  496. *
  497. * @param string $meta_type post|term|user Which meta?
  498. * @return array $nu Our valid post/term/user meta options array
  499. *
  500. */
  501. private static function _bootstrap_meta( $settings ) {
  502. $nu = array();
  503. foreach ( $settings as $group ) {
  504. foreach ( $group as $object => $sections ) {
  505. if ( isset($nu[$object]) )
  506. foreach ( $sections as $sk => $sv )
  507. $nu[$object][$sk] = $sv;
  508. else
  509. $nu[$object] = $sections;
  510. }
  511. }
  512. return $nu;
  513. }
  514. public static function _sns_register() {
  515. $path = self::$data['paths'];
  516. $admin_color = get_user_option( 'admin_color' );
  517. $suffix = ( defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ) ? '' : '.min';
  518. # Common
  519. wp_register_script( 'modernizr', "{$path['scripts']}/modernizr-2.6.2-20121030{$suffix}.js", false, '2.6.2-20121030', false );
  520. wp_register_script( 'kc-media-selector', "{$path['scripts']}/media-selector{$suffix}.js", array('jquery-ui-sortable'), self::version, true );
  521. wp_register_script( 'kc-settings-base', "{$path['scripts']}/kc-settings-base{$suffix}.js", array('jquery', 'modernizr', 'json2'), self::version, true );
  522. wp_register_script( 'kc-settings', "{$path['scripts']}/kc-settings{$suffix}.js", array('kc-settings-base', 'kc-media-selector'), self::version, true );
  523. wp_register_style( 'kc-settings', "{$path['styles']}/kc-settings{$suffix}.css", false, self::version );
  524. $jqui_theme = ( $admin_color == 'fresh' ) ? 'flick' : 'cupertino';
  525. wp_register_style( 'jquery-ui', "{$path['styles']}/jquery-ui/{$jqui_theme}/jquery-ui-1.9.2.custom{$suffix}.css", false, '1.8.23' );
  526. wp_register_script( 'chosen', "{$path['scripts']}/chosen.jquery{$suffix}.js", array('jquery'), '0.9.8', true );
  527. wp_register_style( 'chosen', "{$path['styles']}/chosen/chosen{$suffix}.css", false, '0.9.8' );
  528. # Builder
  529. wp_register_script( 'kc-settings-builder', "{$path['scripts']}/kc-settings-builder{$suffix}.js", array('kc-settings-base', 'jquery-ui-sortable'), self::version, true );
  530. # Uploader
  531. wp_register_script( 'kc-settings-upload', "{$path['scripts']}/upload{$suffix}.js", array('media-upload'), self::version, true );
  532. wp_register_script( 'kc-settings-upload-single', "{$path['scripts']}/upload-single{$suffix}.js", array('media-upload'), self::version, true );
  533. add_action( 'admin_print_footer_scripts', array(__CLASS__, '_sns_vars'), 9 );
  534. }
  535. public static function admin_body_class( $classes ) {
  536. if ( self::$data['is_kcs_page'] )
  537. $classes .= 'kc-settings-page';
  538. return $classes;
  539. }
  540. public static function _sns_admin( $hook_suffix ) {
  541. if ( !in_array($hook_suffix, self::$data['pages']) )
  542. return;
  543. self::$data['is_kcs_page'] = true;
  544. wp_enqueue_style( 'kc-settings' );
  545. wp_enqueue_script( 'kc-settings' );
  546. if ( $hook_suffix === 'media-upload-popup' ) {
  547. if ( (isset($_REQUEST['kcsfs']) && $_REQUEST['kcsfs']) || strpos( wp_get_referer(), 'kcsfs') !== false )
  548. wp_enqueue_script( 'kc-settings-upload-single' );
  549. elseif ( (isset($_REQUEST['kcsf']) && $_REQUEST['kcsf']) || strpos( wp_get_referer(), 'kcsf') !== false )
  550. wp_enqueue_script( 'kc-settings-upload' );
  551. }
  552. $media_args = ( 'post' === get_current_screen()->base ) ? array('post' => get_queried_object_id()) : '';
  553. wp_enqueue_media( $media_args );
  554. }
  555. public static function _sns_vars() {
  556. global $wp_scripts, $wp_locale;
  557. if ( !in_array('kc-settings-base', $wp_scripts->in_footer) )
  558. return;
  559. $vars = array(
  560. 'locale' => get_locale(),
  561. 'paths' => self::$data['paths'],
  562. 'js' => kc_get_sns( array('jquery-ui-datepicker', 'thickbox', 'jquery-ui-sortable', 'chosen', 'wp-color-picker', 'kc-media-selector'), 'js' ),
  563. 'css' => kc_get_sns( array('jquery-ui', 'thickbox', 'chosen', 'wp-color-picker'), 'css' ),
  564. 'upload' => array(
  565. 'text' => array(
  566. 'head' => 'KC Settings',
  567. 'empty' => __( 'Please upload some files and then go back to this tab.', 'kc-settings' ),
  568. 'checkAll' => __( 'Select all files', 'kc-settings' ),
  569. 'clear' => __( 'Clear selections', 'kc-settings' ),
  570. 'invert' => __( 'Invert selection', 'kc-settings' ),
  571. 'addFiles' => __( 'Add files to collection', 'kc-settings' ),
  572. 'info' => __( 'Click the "Media Library" tab to insert files that are already upload, or, upload your files and then go to the "Media Library" tab to insert the files you just uploaded.', 'kc-settings' ),
  573. 'selFile' => __( 'Select file', 'kc-settings' ),
  574. 'filenomatch' => __( "You can't select this because the file type doesn't match", 'kc-settings' ),
  575. ),
  576. ),
  577. 'texts' => array(
  578. 'show' => __('Show', 'kc-settings'),
  579. 'hide' => __('Hide', 'kc-settings'),
  580. 'now' => __('Now', 'kc-settings'),
  581. 'done' => __('Done', 'kc-settings'),
  582. 'time' => __('Time', 'kc-settings'),
  583. 'hour' => __('Hour', 'kc-settings'),
  584. 'minute' => __('Minute', 'kc-settings'),
  585. 'today' => __('Today', 'kc-settings'),
  586. 'prev' => __('Prev', 'kc-settings'),
  587. 'next' => __('Next', 'kc-settings'),
  588. 'chooseTime' => __('Choose time', 'kc-settings'),
  589. 'monthNames' => array(
  590. 'full' => $wp_locale->month,
  591. 'shrt' => $wp_locale->month_abbrev,
  592. ),
  593. 'dayNames' => array(
  594. 'full' => $wp_locale->weekday,
  595. 'shrt' => $wp_locale->weekday_abbrev,
  596. 'min' => array(
  597. _x('Su', 'day min name', 'kc-settings'),
  598. _x('Mo', 'day min name', 'kc-settings'),
  599. _x('Tu', 'day min name', 'kc-settings'),
  600. _x('We', 'day min name', 'kc-settings'),
  601. _x('Th', 'day min name', 'kc-settings'),
  602. _x('Fr', 'day min name', 'kc-settings'),
  603. _x('Sa', 'day min name', 'kc-settings'),
  604. ),
  605. ),
  606. 'weekNames' => array(
  607. 'full' => __('Week', 'kc-settings'),
  608. 'shrt' => _x('Wk', 'week short', 'kc-settings'),
  609. ),
  610. ),
  611. 'mediaFields' => self::$data['media_fields'],
  612. );
  613. ?>
  614. <script>
  615. var kcSettings = <?php echo json_encode( $vars ); ?>
  616. </script>
  617. <?php
  618. }
  619. private static function _samples( $types ) {
  620. foreach ( $types as $type )
  621. require_once self::$data['paths']['inc'] . "/doc/sample/{$type}.php";
  622. }
  623. /**
  624. * Create and/or set termmeta table
  625. *
  626. * @credit Simple Term Meta
  627. * @link http://www.cmurrayconsulting.com/software/wordpress-simple-term-meta/
  628. *
  629. */
  630. private static function _setup_termmeta_table() {
  631. global $wpdb;
  632. $table_name = $wpdb->prefix . 'termmeta';
  633. if ( $wpdb->get_var("SHOW TABLES LIKE '{$table_name}'") != $table_name ) {
  634. $sql = "CREATE TABLE {$table_name} (
  635. meta_id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  636. term_id bigint(20) unsigned NOT NULL DEFAULT '0',
  637. meta_key varchar(255) DEFAULT NULL,
  638. meta_value longtext,
  639. PRIMARY KEY (meta_id),
  640. KEY term_id (term_id),
  641. KEY meta_key (meta_key)
  642. );";
  643. require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
  644. dbDelta( $sql );
  645. }
  646. $wpdb->termmeta = $table_name;
  647. }
  648. /**
  649. * Lock plugin/prevent deactivation when there are other plugins/themes
  650. * that depend on it.
  651. */
  652. public static function _lock( $actions, $plugin_file, $plugin_data, $context ) {
  653. if ( $plugin_file == self::$data['paths']['p_file'] && !empty(self::$data['kids']) )
  654. unset( $actions['deactivate'] );
  655. return $actions;
  656. }
  657. public static function _admin_notices() {
  658. $notices = kc_array_remove_empty( self::$data['notices'] );
  659. if ( empty($notices) )
  660. return;
  661. foreach ( $notices as $type => $messages ) {
  662. foreach ( $messages as $message ) {
  663. if ( empty($message) )
  664. continue;
  665. ?>
  666. <div class="<?php echo esc_attr($type) ?>">
  667. <?php echo wpautop( $message ) // xss ok ?>
  668. </div>
  669. <?php
  670. }
  671. }
  672. }
  673. public static function get_data() {
  674. $data = self::$data;
  675. if ( !func_num_args() )
  676. return $data;
  677. $args = func_get_args();
  678. return kc_array_multi_get_value( $data, $args );
  679. }
  680. public static function add_page( $page ) {
  681. if ( !in_array($page, self::$data['pages']) )
  682. self::$data['pages'][] = $page;
  683. }
  684. public static function add_notice( $type, $message ) {
  685. if ( !in_array($type, array('updated', 'error')) )
  686. $type = 'updated';
  687. self::$data['notices'][$type][] = $message;
  688. }
  689. public static function add_media_field( $id, $args ) {
  690. self::$data['media_fields'][ $id ] = $args;
  691. }
  692. # Plugin activation tasks
  693. public static function _activate() {
  694. if ( version_compare( get_bloginfo('version'), '3.5', '<' ) )
  695. wp_die( 'Please upgrade your WordPress to version 3.5 before using this plugin.' );
  696. /**
  697. * Since 2.7.4
  698. * We're not saving any plugin status to the DB anymore so the plugin
  699. * can be bundled with a plugin/theme.
  700. */
  701. delete_option( 'kc_settings' );
  702. }
  703. public static function debug_bar_ext( $panels ) {
  704. $panels[] = new kcDebug;
  705. return $panels;
  706. }
  707. }
  708. add_action( 'plugins_loaded', array('kcSettings', 'setup'), 7 );
  709. # A hack for symlinks
  710. if ( !function_exists('kc_plugin_file') ) {
  711. function kc_plugin_file( $file ) {
  712. if ( !file_exists($file) )
  713. return $file;
  714. $file_info = pathinfo( $file );
  715. $parent = basename( $file_info['dirname'] );
  716. $file = ( $parent == $file_info['filename'] ) ? "{$parent}/{$file_info['basename']}" : $file_info['basename'];
  717. return $file;
  718. }
  719. }
  720. register_activation_hook( kc_plugin_file( __FILE__ ), array('kcSettings', '_activate') );