ReduxFramework

Main ReduxFramework class.

Defined (1)

The class is defined in the following location(s).

/inc/ReduxFramework/ReduxCore/framework.php  
  1. class ReduxFramework { 
  2.  
  3. // ATTENTION DEVS 
  4. // Please update the build number with each push, no matter how small. 
  5. // This will make for easier support when we ask users what version they are using. 
  6. public static $_version = '3.3.9.30'; 
  7. public static $_dir;  
  8. public static $_url; 
  9. public static $_upload_dir; 
  10. public static $_upload_url; 
  11. public static $wp_content_url; 
  12. public static $base_wp_content_url; 
  13. public static $_is_plugin = true; 
  14. public static $_as_plugin = false; 
  15.  
  16. public static function init() { 
  17. $dir = Redux_Helpers::cleanFilePath( dirname( __FILE__ ) ); 
  18.  
  19. // Windows-proof constants: replace backward by forward slashes. Thanks to: @peterbouwmeester 
  20. self::$_dir = trailingslashit( $dir ); 
  21. self::$wp_content_url = trailingslashit( Redux_Helpers::cleanFilePath( ( is_ssl() ? str_replace( 'http://', 'https://', WP_CONTENT_URL ) : WP_CONTENT_URL ) ) ); 
  22.  
  23. // See if Redux is a plugin or not 
  24. if ( strpos( Redux_Helpers::cleanFilePath( __FILE__ ), Redux_Helpers::cleanFilePath( get_stylesheet_directory() ) ) !== false || strpos( Redux_Helpers::cleanFilePath( __FILE__ ), Redux_Helpers::cleanFilePath( get_template_directory_uri() ) ) !== false || strpos( Redux_Helpers::cleanFilePath( __FILE__ ), Redux_Helpers::cleanFilePath( WP_CONTENT_DIR . '/themes/' ) ) !== false ) { 
  25. self::$_is_plugin = false; 
  26. } else { 
  27. // Check if plugin is a symbolic link, see if it's a plugin. If embedded, we can't do a thing. 
  28. if ( strpos( self::$_dir, ABSPATH ) === false ) { 
  29. if ( ! function_exists( 'get_plugins' ) ) { 
  30. require_once ABSPATH . 'wp-admin/includes/plugin.php'; 
  31.  
  32. $is_plugin = false; 
  33. foreach ( get_plugins() as $key => $value ) { 
  34. if ( strpos( $key, 'redux-framework.php' ) !== false ) { 
  35. self::$_dir = trailingslashit( Redux_Helpers::cleanFilePath( WP_CONTENT_DIR . '/plugins/' . plugin_dir_path( $key ) . 'ReduxCore/' ) ); 
  36. $is_plugin = true; 
  37. if ( ! $is_plugin ) { 
  38. self::$_is_plugin = false; 
  39.  
  40. if ( self::$_is_plugin == true || self::$_as_plugin == true ) { 
  41. self::$_url = plugin_dir_url( __FILE__ ); 
  42. } else { 
  43. if ( strpos( Redux_Helpers::cleanFilePath( __FILE__ ), Redux_Helpers::cleanFilePath( get_template_directory() ) ) !== false ) { 
  44. $relative_url = str_replace( Redux_Helpers::cleanFilePath( get_template_directory() ), '', self::$_dir ); 
  45. self::$_url = trailingslashit( get_template_directory_uri() . $relative_url ); 
  46. } else if ( strpos( Redux_Helpers::cleanFilePath( __FILE__ ), Redux_Helpers::cleanFilePath( get_stylesheet_directory() ) ) !== false ) { 
  47. $relative_url = str_replace( Redux_Helpers::cleanFilePath( get_stylesheet_directory() ), '', self::$_dir ); 
  48. self::$_url = trailingslashit( get_stylesheet_directory_uri() . $relative_url ); 
  49. } else { 
  50. $wp_content_dir = trailingslashit( Redux_Helpers::cleanFilePath( WP_CONTENT_DIR ) ); 
  51. $wp_content_dir = trailingslashit( str_replace( '//', '/', $wp_content_dir ) ); 
  52. $relative_url = str_replace( $wp_content_dir, '', self::$_dir ); 
  53. self::$_url = trailingslashit( self::$wp_content_url . $relative_url ); 
  54.  
  55. self::$_url = apply_filters( "redux/_url", self::$_url ); 
  56. self::$_dir = apply_filters( "redux/_dir", self::$_dir ); 
  57. self::$_is_plugin = apply_filters( "redux/_is_plugin", self::$_is_plugin ); 
  58.  
  59.  
  60. // ::init() 
  61.  
  62. public $framework_url = 'http://www.reduxframework.com/'; 
  63. public static $instance = null; 
  64. public $admin_notices = array(); 
  65. public $page = ''; 
  66. public $saved = false; 
  67. public $fields = array(); // Fields by type used in the panel 
  68. public $current_tab = ''; // Current section to display, cookies 
  69. public $extensions = array(); // Extensions by type used in the panel 
  70. public $sections = array(); // Sections and fields 
  71. public $errors = array(); // Errors 
  72. public $warnings = array(); // Warnings 
  73. public $options = array(); // Option values 
  74. public $options_defaults = null; // Option defaults 
  75. public $notices = array(); // Option defaults 
  76. public $compiler_fields = array(); // Fields that trigger the compiler hook 
  77. public $required = array(); // Information that needs to be localized 
  78. public $required_child = array(); // Information that needs to be localized 
  79. public $localize_data = array(); // Information that needs to be localized 
  80. public $fonts = array(); // Information that needs to be localized 
  81. public $folds = array(); // The itms that need to fold. 
  82. public $path = ''; 
  83. public $changed_values = array(); // Values that have been changed on save. Orig values. 
  84. public $output = array(); // Fields with CSS output selectors 
  85. public $outputCSS = null; // CSS that get auto-appended to the header 
  86. public $compilerCSS = null; // CSS that get sent to the compiler hook 
  87. public $customizerCSS = null; // CSS that goes to the customizer 
  88. public $fieldsValues = array(); //all fields values in an id=>value array so we can check dependencies 
  89. public $fieldsHidden = array(); //all fields that didn't pass the dependency test and are hidden 
  90. public $toHide = array(); // Values to hide on page load 
  91. public $typography = null; //values to generate google font CSS 
  92. public $import_export = null; 
  93. public $debug = null; 
  94. public $no_panel = array(); // Fields that are not visible in the panel 
  95. private $show_hints = false; 
  96. private $hidden_perm_fields = array(); // Hidden fields specified by 'permissions' arg. 
  97. private $hidden_perm_sections = array(); // Hidden sections specified by 'permissions' arg. 
  98. public $typography_preview = array(); 
  99. public $args = array(); 
  100. public $filesystem = null; 
  101.  
  102. /** 
  103. * Class Constructor. Defines the args for the theme options class 
  104. * @since 1.0.0 
  105. * @param array $sections Panel sections. 
  106. * @param array $args Class constructor arguments. 
  107. * @param array $extra_tabs Extra panel tabs. // REMOVE 
  108. * @return \ReduxFramework 
  109. */ 
  110. public function __construct( $sections = array(), $args = array(), $extra_tabs = array() ) { 
  111.  
  112. // Disregard WP AJAX 'heartbeat'call. Why waste resources? 
  113. if ( isset( $_POST ) && isset( $_POST['action'] ) && $_POST['action'] == 'heartbeat' ) { 
  114.  
  115. // Hook, for purists. 
  116. if ( ! has_action( 'redux/ajax/heartbeat' ) ) { 
  117. do_action( 'redux/ajax/heartbeat', $this ); 
  118.  
  119. // Buh bye! 
  120. return; 
  121.  
  122. // Pass parent pointer to function helper. 
  123. Redux_Functions::$_parent = $this; 
  124.  
  125. $this->filesystem = new Redux_Filesystem( $this ); 
  126.  
  127. //set redux upload folder 
  128. $this->set_redux_content(); 
  129.  
  130. // Set values 
  131. $this->set_default_args(); 
  132. $this->args = wp_parse_args( $args, $this->args ); 
  133.  
  134. if ( empty( $this->args['transient_time'] ) ) { 
  135. $this->args['transient_time'] = 60 * MINUTE_IN_SECONDS; 
  136.  
  137. if ( empty( $this->args['footer_credit'] ) ) { 
  138. $this->args['footer_credit'] = '<span id="footer-thankyou">' . sprintf( __( 'Options panel created using %1$s', 'redux-framework' ), '<a href="' . esc_url( $this->framework_url ) . '" target="_blank">' . __( 'Redux Framework', 'redux-framework' ) . '</a> v' . self::$_version ) . '</span>'; 
  139.  
  140. if ( empty( $this->args['menu_title'] ) ) { 
  141. $this->args['menu_title'] = __( 'Options', 'redux-framework' ); 
  142.  
  143. if ( empty( $this->args['page_title'] ) ) { 
  144. $this->args['page_title'] = __( 'Options', 'redux-framework' ); 
  145.  
  146. /** 
  147. * filter 'redux/args/{opt_name}' 
  148. * @param array $args ReduxFramework configuration 
  149. */ 
  150. $this->args = apply_filters( "redux/args/{$this->args['opt_name']}", $this->args ); 
  151.  
  152. /** 
  153. * filter 'redux/options/{opt_name}/args' 
  154. * @param array $args ReduxFramework configuration 
  155. */ 
  156. $this->args = apply_filters( "redux/options/{$this->args['opt_name']}/args", $this->args ); 
  157.  
  158. if ( ! empty( $this->args['opt_name'] ) ) { 
  159. /** 
  160. * SHIM SECTION 
  161. * Old variables and ways of doing things that need correcting. ;) 
  162. **/ 
  163. // Variable name change 
  164. if ( ! empty( $this->args['page_cap'] ) ) { 
  165. $this->args['page_permissions'] = $this->args['page_cap']; 
  166. unset( $this->args['page_cap'] ); 
  167.  
  168. if ( ! empty( $this->args['page_position'] ) ) { 
  169. $this->args['page_priority'] = $this->args['page_position']; 
  170. unset( $this->args['page_position'] ); 
  171.  
  172. if ( ! empty( $this->args['page_type'] ) ) { 
  173. $this->args['menu_type'] = $this->args['page_type']; 
  174. unset( $this->args['page_type'] ); 
  175.  
  176. // Get rid of extra_tabs! Not needed. 
  177. if ( is_array( $extra_tabs ) && ! empty( $extra_tabs ) ) { 
  178. foreach ( $extra_tabs as $tab ) { 
  179. array_push( $this->sections, $tab ); 
  180.  
  181. // Move to the first loop area! 
  182. /** 
  183. * filter 'redux-sections' 
  184. * @deprecated 
  185. * @param array $sections field option sections 
  186. */ 
  187. $this->sections = apply_filters( 'redux-sections', $sections ); // REMOVE LATER 
  188. /** 
  189. * filter 'redux-sections-{opt_name}' 
  190. * @deprecated 
  191. * @param array $sections field option sections 
  192. */ 
  193. $this->sections = apply_filters( "redux-sections-{$this->args['opt_name']}", $this->sections ); // REMOVE LATER 
  194. /** 
  195. * filter 'redux/options/{opt_name}/sections' 
  196. * @param array $sections field option sections 
  197. */ 
  198. $this->sections = apply_filters( "redux/options/{$this->args['opt_name']}/sections", $this->sections ); 
  199.  
  200. /** 
  201. * Construct hook 
  202. * action 'redux/construct' 
  203. * @param object $this ReduxFramework 
  204. */ 
  205. do_action( 'redux/construct', $this ); 
  206.  
  207. //$this->filesystem = new Redux_Filesystem( $this ); 
  208.  
  209. //set redux upload folder 
  210. //$this->set_redux_content(); 
  211.  
  212. // Set the default values 
  213. $this->_default_cleanup(); 
  214.  
  215. // Internataionalization 
  216. $this->_internationalization(); 
  217.  
  218. // Register extra extensions 
  219. $this->_register_extensions(); 
  220.  
  221. // Grab database values 
  222. $this->get_options(); 
  223.  
  224. // Tracking 
  225. if ( true != Redux_Helpers::isTheme( __FILE__ ) || ( true == Redux_Helpers::isTheme( __FILE__ ) && !$this->args['disable_tracking'] ) ) { 
  226. $this->_tracking(); 
  227.  
  228. // Set option with defaults 
  229. //add_action( 'init', array( &$this, '_set_default_options' ), 101 ); 
  230.  
  231. //logconsole('post', $_GET['page']); 
  232.  
  233. //DOVY!! HERE!!! 
  234. // Getting started page 
  235. // if ( is_admin () && $this->args['dev_mode'] ) { 
  236. // 
  237. // if ( isset($_GET['page']) && ($_GET['page'] == 'redux-about' || $_GET['page'] == 'redux-getting-started' || $_GET['page'] == 'redux-credits' || $_GET['page'] == 'redux-changelog' )) { 
  238. // //logconsole('inc'); 
  239. // require_once( dirname( __FILE__ ) . '/inc/welcome.php' ); 
  240. // } else { 
  241. // //logconsole('compare'); 
  242. // if (isset($_GET['page']) && $_GET['page'] == $this->args['page_slug']) { 
  243. // $saveVer = get_option('redux_version_upgraded_from'); 
  244. // $curVer = self::$_version; 
  245. // 
  246. // if (empty($saveVer)) { 
  247. // //logconsole('redir'); 
  248. // wp_safe_redirect ( admin_url ( 'index.php?page=redux-getting-started' ) ); 
  249. // exit; 
  250. // } else if (version_compare($curVer, $saveVer, '>')) { 
  251. // wp_safe_redirect ( admin_url ( 'index.php?page=redux-about' ) ); 
  252. // exit; 
  253. // } 
  254. // } 
  255. // } 
  256. // } 
  257.  
  258. // Options page 
  259. add_action( 'admin_menu', array( $this, '_options_page' ) ); 
  260.  
  261. // Add a network menu 
  262. if ( $this->args['database'] == "network" && $this->args['network_admin'] ) { 
  263. add_action( 'network_admin_menu', array( $this, '_options_page' ) ); 
  264.  
  265. // Admin Bar menu 
  266. add_action( 'admin_bar_menu', array( 
  267. $this,  
  268. '_admin_bar_menu' 
  269. ), $this->args['admin_bar_priority'] ); 
  270.  
  271. // Register setting 
  272. add_action( 'admin_init', array( $this, '_register_settings' ) ); 
  273.  
  274. // Display admin notices in dev_mode 
  275. if ( true == $this->args['dev_mode'] ) { 
  276. require_once( self::$_dir . 'inc/debug.php' ); 
  277. $this->debug = new ReduxDebugObject( $this ); 
  278.  
  279. if ( true == $this->args['update_notice'] ) { 
  280. add_action( 'admin_init', array( $this, '_update_check' ) ); 
  281.  
  282. // Display admin notices 
  283. add_action( 'admin_notices', array( $this, '_admin_notices' ) ); 
  284.  
  285. // Check for dismissed admin notices. 
  286. add_action( 'admin_init', array( $this, '_dismiss_admin_notice' ), 9 ); 
  287.  
  288. // Enqueue the admin page CSS and JS 
  289. if ( isset( $_GET['page'] ) && $_GET['page'] == $this->args['page_slug'] ) { 
  290. add_action( 'admin_enqueue_scripts', array( $this, '_enqueue' ), 1 ); 
  291.  
  292. // Output dynamic CSS 
  293. // Frontend: Maybe enqueue dynamic CSS and Google fonts 
  294. if ( empty( $this->args['output_location'] ) || in_array( 'frontend', $this->args['output_location'] ) ) { 
  295. add_action( 'wp_head', array( &$this, '_output_css' ), 150 ); 
  296. add_action( 'wp_enqueue_scripts', array( &$this, '_enqueue_output' ), 150 ); 
  297.  
  298. // Login page: Maybe enqueue dynamic CSS and Google fonts 
  299. if ( in_array( 'login', $this->args['output_location'] ) ) { 
  300. add_action( 'login_head', array( &$this, '_output_css' ), 150 ); 
  301. add_action( 'login_enqueue_scripts', array( &$this, '_enqueue_output' ), 150 ); 
  302.  
  303. // Admin area: Maybe enqueue dynamic CSS and Google fonts 
  304. if ( in_array( 'admin', $this->args['output_location'] ) ) { 
  305. add_action( 'admin_head', array( &$this, '_output_css' ), 150 ); 
  306. add_action( 'admin_enqueue_scripts', array( &$this, '_enqueue_output' ), 150 ); 
  307.  
  308.  
  309. add_action( 'wp_print_scripts', array( $this, 'vc_fixes' ), 100 ); 
  310. add_action( 'admin_enqueue_scripts', array( $this, 'vc_fixes' ), 100 ); 
  311.  
  312. require_once( self::$_dir . 'inc/import_export.php' ); 
  313. $this->import_export = new Redux_import_export( $this ); 
  314.  
  315. if ( $this->args['database'] == "network" && $this->args['network_admin'] ) { 
  316. add_action( 'network_admin_edit_redux_' . $this->args['opt_name'], array( 
  317. $this,  
  318. 'save_network_page' 
  319. ), 10, 0 ); 
  320. add_action( 'admin_bar_menu', array( $this, 'network_admin_bar' ), 999 ); 
  321.  
  322.  
  323.  
  324. /** 
  325. * Loaded hook 
  326. * action 'redux/loaded' 
  327. * @param object $this ReduxFramework 
  328. */ 
  329. do_action( 'redux/loaded', $this ); 
  330.  
  331. } // __construct() 
  332.  
  333. private function set_redux_content() { 
  334. $upload_dir = wp_upload_dir(); 
  335. self::$_upload_dir = $upload_dir['basedir'] . '/redux/'; 
  336. self::$_upload_url = $upload_dir['baseurl'] . '/redux/'; 
  337.  
  338. if ( ! is_dir( self::$_upload_dir ) ) { 
  339. $this->filesystem->execute( 'mkdir', self::$_upload_dir ); 
  340.  
  341. private function set_default_args() { 
  342. $this->args = array( 
  343. 'opt_name' => '',  
  344. // Must be defined by theme/plugin 
  345. 'google_api_key' => '',  
  346. // Must be defined to update the google fonts cache for the typography module 
  347. 'google_update_weekly' => false,  
  348. // Set to keep your google fonts updated weekly 
  349. 'last_tab' => '',  
  350. // force a specific tab to always show on reload 
  351. 'menu_icon' => '',  
  352. // menu icon 
  353. 'menu_title' => '',  
  354. // menu title/text 
  355. 'page_title' => '',  
  356. // option page title 
  357. 'page_slug' => '_options',  
  358. 'page_permissions' => 'manage_options',  
  359. 'menu_type' => 'menu',  
  360. // ('menu'|'submenu') 
  361. 'page_parent' => 'themes.php',  
  362. // requires menu_type = 'submenu 
  363. 'page_priority' => null,  
  364. 'allow_sub_menu' => true,  
  365. // allow submenus to be added if menu_type == menu 
  366. 'save_defaults' => true,  
  367. // Save defaults to the DB on it if empty 
  368. 'footer_credit' => '',  
  369. 'async_typography' => false,  
  370. 'disable_google_fonts_link' => false,  
  371. 'class' => '',  
  372. // Class that gets appended to all redux-containers 
  373. 'admin_bar' => true,  
  374. 'admin_bar_priority' => 999,  
  375. // Show the panel pages on the admin bar 
  376. 'admin_bar_icon' => '',  
  377. // admin bar icon 
  378. 'help_tabs' => array(),  
  379. 'help_sidebar' => '',  
  380. 'database' => '',  
  381. // possible: options, theme_mods, theme_mods_expanded, transient, network 
  382. 'customizer' => false,  
  383. // setting to true forces get_theme_mod_expanded 
  384. 'global_variable' => '',  
  385. // Changes global variable from $GLOBALS['YOUR_OPT_NAME'] to whatever you set here. false disables the global variable 
  386. 'output' => true,  
  387. // Dynamically generate CSS 
  388. 'compiler' => true,  
  389. // Initiate the compiler hook 
  390. 'output_tag' => true,  
  391. // Print Output Tag 
  392. 'output_location' => array( 'frontend' ),  
  393. // Where the dynamic CSS will be added. Can be any combination from: 'frontend', 'login', 'admin' 
  394. 'transient_time' => '',  
  395. 'default_show' => false,  
  396. // If true, it shows the default value 
  397. 'default_mark' => '',  
  398. // What to print by the field's title if the value shown is default 
  399. 'update_notice' => true,  
  400. // Recieve an update notice of new commits when in dev mode 
  401. 'disable_save_warn' => false,  
  402. // Disable the save warn 
  403. 'open_expanded' => false,  
  404. 'hide_expand' => false,  
  405. // Start the panel fully expanded to start with 
  406. 'network_admin' => false,  
  407. // Enable network admin when using network database mode 
  408. 'network_sites' => true,  
  409. // Enable sites as well as admin when using network database mode 
  410. 'hide_reset' => false,  
  411. 'hints' => array( 
  412. 'icon' => 'icon-question-sign',  
  413. 'icon_position' => 'right',  
  414. 'icon_color' => 'lightgray',  
  415. 'icon_size' => 'normal',  
  416. 'tip_style' => array( 
  417. 'color' => 'light',  
  418. 'shadow' => true,  
  419. 'rounded' => false,  
  420. 'style' => '',  
  421. ),  
  422. 'tip_position' => array( 
  423. 'my' => 'top_left',  
  424. 'at' => 'bottom_right',  
  425. ),  
  426. 'tip_effect' => array( 
  427. 'show' => array( 
  428. 'effect' => 'slide',  
  429. 'duration' => '500',  
  430. 'event' => 'mouseover',  
  431. ),  
  432. 'hide' => array( 
  433. 'effect' => 'fade',  
  434. 'duration' => '500',  
  435. 'event' => 'click mouseleave',  
  436. ),  
  437. ),  
  438. ),  
  439. 'show_import_export' => true,  
  440. 'dev_mode' => true,  
  441. 'system_info' => false,  
  442. 'disable_tracking' => false,  
  443. 'sass' => array( 
  444. 'enabled' => true,  
  445. 'page_output' => true,  
  446. ); 
  447.  
  448. // Fix conflicts with Visual Composer. 
  449. public function vc_fixes() { 
  450. if ( redux_helpers::isFieldInUse( $this, 'ace_editor' ) ) { 
  451. wp_dequeue_script( 'wpb_ace' ); 
  452. wp_deregister_script( 'wpb_ace' ); 
  453.  
  454. public function network_admin_bar( $wp_admin_bar ) { 
  455.  
  456. $args = array( 
  457. 'id' => $this->args['opt_name'] . '_network_admin',  
  458. 'title' => $this->args['menu_title'],  
  459. 'parent' => 'network-admin',  
  460. 'href' => network_admin_url( 'settings.php' ) . '?page=' . $this->args['page_slug'],  
  461. 'meta' => array( 'class' => 'redux-network-admin' ) 
  462. ); 
  463. $wp_admin_bar->add_node( $args ); 
  464.  
  465.  
  466. private function stripslashes_deep( $value ) { 
  467. $value = is_array( $value ) ? 
  468. array_map( 'stripslashes_deep', $value ) : 
  469. stripslashes( $value ); 
  470.  
  471. return $value; 
  472.  
  473. public function save_network_page() { 
  474.  
  475. $data = $this->_validate_options( $_POST[ $this->args['opt_name'] ] ); 
  476.  
  477. if ( ! empty( $data ) ) { 
  478. $this->set_options( $data ); 
  479.  
  480. wp_redirect( add_query_arg( array( 
  481. 'page' => $this->args['page_slug'],  
  482. 'updated' => 'true' 
  483. ), network_admin_url( 'settings.php' ) ) ); 
  484. exit(); 
  485.  
  486. public function _update_check() { 
  487. // Only one notice per instance please 
  488. if ( ! isset( $GLOBALS['redux_update_check'] ) ) { 
  489. Redux_Functions::updateCheck( self::$_version ); 
  490. $GLOBALS['redux_update_check'] = 1; 
  491.  
  492. public function _admin_notices() { 
  493. Redux_Functions::adminNotices(); 
  494.  
  495. public function _dismiss_admin_notice() { 
  496. Redux_Functions::dismissAdminNotice(); 
  497.  
  498. /** 
  499. * Load the plugin text domain for translation. 
  500. * @since 3.0.5 
  501. */ 
  502. private function _internationalization() { 
  503.  
  504. /** 
  505. * Locale for text domain 
  506. * filter 'redux/textdomain/{opt_name}' 
  507. * @param string The locale of the blog or from the 'locale' hook 
  508. * @param string 'redux-framework' text domain 
  509. */ 
  510. $locale = apply_filters( "redux/textdomain/{$this->args['opt_name']}", get_locale(), 'redux-framework' ); 
  511.  
  512. if ( strpos( $locale, '_' ) === false ) { 
  513. if ( file_exists( self::$_dir . 'languages/' . strtolower( $locale ) . '_' . strtoupper( $locale ) . '.mo' ) ) { 
  514. $locale = strtolower( $locale ) . '_' . strtoupper( $locale ); 
  515. load_textdomain( 'redux-framework', self::$_dir . 'languages/' . $locale . '.mo' ); 
  516. } // _internationalization() 
  517.  
  518. /** 
  519. * @return ReduxFramework 
  520. */ 
  521. public function get_instance() { 
  522. //self::$_instance = $this; 
  523. return self::$instance; 
  524. } // get_instance() 
  525.  
  526. private function _tracking() { 
  527. require_once( dirname( __FILE__ ) . '/inc/tracking.php' ); 
  528. $tracking = Redux_Tracking::get_instance(); 
  529. $tracking->load( $this ); 
  530. } // _tracking() 
  531.  
  532. /** 
  533. * ->_get_default(); This is used to return the default value if default_show is set 
  534. * @since 1.0.1 
  535. * @access public 
  536. * @param string $opt_name The option name to return 
  537. * @param mixed $default (null) The value to return if default not set 
  538. * @return mixed $default 
  539. */ 
  540. public function _get_default( $opt_name, $default = null ) { 
  541. if ( $this->args['default_show'] == true ) { 
  542.  
  543. if ( empty( $this->options_defaults ) ) { 
  544. $this->_default_values(); // fill cache 
  545.  
  546. $default = array_key_exists( $opt_name, $this->options_defaults ) ? $this->options_defaults[ $opt_name ] : $default; 
  547.  
  548. return $default; 
  549. } // _get_default() 
  550.  
  551. /** 
  552. * ->get(); This is used to return and option value from the options array 
  553. * @since 1.0.0 
  554. * @access public 
  555. * @param string $opt_name The option name to return 
  556. * @param mixed $default (null) The value to return if option not set 
  557. * @return mixed 
  558. */ 
  559. public function get( $opt_name, $default = null ) { 
  560. return ( ! empty( $this->options[ $opt_name ] ) ) ? $this->options[ $opt_name ] : $this->_get_default( $opt_name, $default ); 
  561. } // get() 
  562.  
  563. /** 
  564. * ->set(); This is used to set an arbitrary option in the options array 
  565. * @since 1.0.0 
  566. * @access public 
  567. * @param string $opt_name The name of the option being added 
  568. * @param mixed $value The value of the option being added 
  569. * @return void 
  570. */ 
  571. public function set( $opt_name = '', $value = '' ) { 
  572. if ( $opt_name != '' ) { 
  573. $this->options[ $opt_name ] = $value; 
  574. $this->set_options( $this->options ); 
  575. } // set() 
  576.  
  577. /** 
  578. * Set a global variable by the global_variable argument 
  579. * @since 3.1.5 
  580. * @return bool (global was set) 
  581. */ 
  582. private function set_global_variable() { 
  583. if ( $this->args['global_variable'] ) { 
  584. $option_global = $this->args['global_variable']; 
  585. /** 
  586. * filter 'redux/options/{opt_name}/global_variable' 
  587. * @param array $value option value to set global_variable with 
  588. */ 
  589.  
  590. $GLOBALS[ $this->args['global_variable'] ] = apply_filters( "redux/options/{$this->args['opt_name']}/global_variable", $this->options ); 
  591. if ( isset( $this->transients['last_save'] ) ) { 
  592. // Deprecated 
  593. $GLOBALS[ $this->args['global_variable'] ]['REDUX_last_saved'] = $this->transients['last_save']; 
  594. // Last save key 
  595. $GLOBALS[ $this->args['global_variable'] ]['REDUX_LAST_SAVE'] = $this->transients['last_save']; 
  596. if ( isset( $this->transients['last_compiler'] ) ) { 
  597. // Deprecated 
  598. $GLOBALS[ $this->args['global_variable'] ]['REDUX_COMPILER'] = $this->transients['last_compiler']; 
  599. // Last compiler hook key 
  600. $GLOBALS[ $this->args['global_variable'] ]['REDUX_LAST_COMPILER'] = $this->transients['last_compiler']; 
  601.  
  602. return true; 
  603.  
  604. return false; 
  605. } // set_global_variable() 
  606.  
  607.  
  608. /** 
  609. * ->set_options(); This is used to set an arbitrary option in the options array 
  610. * @since ReduxFramework 3.0.0 
  611. * @param mixed $value the value of the option being added 
  612. */ 
  613. public function set_options( $value = '' ) { 
  614.  
  615. $this->transients['last_save'] = time(); 
  616.  
  617. if ( ! empty( $value ) ) { 
  618. $this->options = $value; 
  619.  
  620. if ( $this->args['database'] === 'transient' ) { 
  621. set_transient( $this->args['opt_name'] . '-transient', $value, $this->args['transient_time'] ); 
  622. } else if ( $this->args['database'] === 'theme_mods' ) { 
  623. set_theme_mod( $this->args['opt_name'] . '-mods', $value ); 
  624. } else if ( $this->args['database'] === 'theme_mods_expanded' ) { 
  625. foreach ( $value as $k => $v ) { 
  626. set_theme_mod( $k, $v ); 
  627. } else if ( $this->args['database'] === 'network' ) { 
  628. // Strip those slashes! 
  629. $value = json_decode( stripslashes( json_encode( $value ) ), true ); 
  630. update_site_option( $this->args['opt_name'], $value ); 
  631. } else { 
  632. update_option( $this->args['opt_name'], $value ); 
  633.  
  634. // Store the changed values in the transient 
  635. if ( $value != $this->options ) { 
  636. foreach ( $value as $k => $v ) { 
  637. if ( ! isset( $this->options[ $k ] ) ) { 
  638. $this->options[ $k ] = ""; 
  639. } else if ( $v == $this->options[ $k ] ) { 
  640. unset( $this->options[ $k ] ); 
  641. $this->transients['changed_values'] = $this->options; 
  642.  
  643. $this->options = $value; 
  644.  
  645. // Set a global variable by the global_variable argument. 
  646. $this->set_global_variable(); 
  647.  
  648. // Saving the transient values 
  649. $this->set_transients(); 
  650.  
  651. //do_action( "redux-saved-{$this->args['opt_name']}", $value ); // REMOVE 
  652. //do_action( "redux/options/{$this->args['opt_name']}/saved", $value, $this->transients['changed_values'] ); 
  653.  
  654. } // set_options() 
  655.  
  656. /** 
  657. * ->get_options(); This is used to get options from the database 
  658. * @since ReduxFramework 3.0.0 
  659. */ 
  660. public function get_options() { 
  661. $defaults = false; 
  662.  
  663. if ( ! empty( $this->defaults ) ) { 
  664. $defaults = $this->defaults; 
  665.  
  666. if ( $this->args['database'] === "transient" ) { 
  667. $result = get_transient( $this->args['opt_name'] . '-transient' ); 
  668. } else if ( $this->args['database'] === "theme_mods" ) { 
  669. $result = get_theme_mod( $this->args['opt_name'] . '-mods' ); 
  670. } else if ( $this->args['database'] === 'theme_mods_expanded' ) { 
  671. $result = get_theme_mods(); 
  672. } else if ( $this->args['database'] === 'network' ) { 
  673. $result = get_site_option( $this->args['opt_name'], array() ); 
  674. $result = json_decode( stripslashes( json_encode( $result ) ), true ); 
  675. } else { 
  676. $result = get_option( $this->args['opt_name'], array() ); 
  677.  
  678. if ( empty( $result ) && ! empty( $defaults ) ) { 
  679. $results = $defaults; 
  680. $this->set_options( $results ); 
  681. } else { 
  682. $this->options = $result; 
  683.  
  684. /** 
  685. * action 'redux/options/{opt_name}/options' 
  686. * @param mixed $value option values 
  687. */ 
  688. $this->options = apply_filters( "redux/options/{$this->args['opt_name']}/options", $this->options ); 
  689.  
  690. // Get transient values 
  691. $this->get_transients(); 
  692.  
  693. // Set a global variable by the global_variable argument. 
  694. $this->set_global_variable(); 
  695. } // get_options() 
  696.  
  697. /** 
  698. * ->get_wordpress_date() - Get Wordpress specific data from the DB and return in a usable array 
  699. * @since ReduxFramework 3.0.0 
  700. */ 
  701. public function get_wordpress_data( $type = false, $args = array() ) { 
  702. $data = ""; 
  703.  
  704. /** 
  705. * filter 'redux/options/{opt_name}/wordpress_data/{type}/' 
  706. * @deprecated 
  707. * @param string $data 
  708. */ 
  709. $data = apply_filters( "redux/options/{$this->args['opt_name']}/wordpress_data/$type/", $data ); // REMOVE LATER 
  710.  
  711. /** 
  712. * filter 'redux/options/{opt_name}/data/{type}' 
  713. * @param string $data 
  714. */ 
  715. $data = apply_filters( "redux/options/{$this->args['opt_name']}/data/$type", $data ); 
  716.  
  717. $argsKey = ""; 
  718. foreach ( $args as $key => $value ) { 
  719. if ( ! is_array( $value ) ) { 
  720. $argsKey .= $value . "-"; 
  721. } else { 
  722. $argsKey .= implode( "-", $value ); 
  723.  
  724. if ( empty( $data ) && isset( $this->wp_data[ $type . $argsKey ] ) ) { 
  725. $data = $this->wp_data[ $type . $argsKey ]; 
  726.  
  727. if ( empty( $data ) && ! empty( $type ) ) { 
  728.  
  729. /** 
  730. * Use data from Wordpress to populate options array 
  731. **/ 
  732. if ( ! empty( $type ) && empty( $data ) ) { 
  733. if ( empty( $args ) ) { 
  734. $args = array(); 
  735.  
  736. $data = array(); 
  737. $args = wp_parse_args( $args, array() ); 
  738.  
  739. if ( $type == "categories" || $type == "category" ) { 
  740. $cats = get_categories( $args ); 
  741. if ( ! empty( $cats ) ) { 
  742. foreach ( $cats as $cat ) { 
  743. $data[ $cat->term_id ] = $cat->name; 
  744. //foreach 
  745. } // If 
  746. } else if ( $type == "menus" || $type == "menu" ) { 
  747. $menus = wp_get_nav_menus( $args ); 
  748. if ( ! empty( $menus ) ) { 
  749. foreach ( $menus as $item ) { 
  750. $data[ $item->term_id ] = $item->name; 
  751. //foreach 
  752. //if 
  753. } else if ( $type == "pages" || $type == "page" ) { 
  754. if ( ! isset( $args['posts_per_page'] ) ) { 
  755. $args['posts_per_page'] = 20; 
  756. $pages = get_pages( $args ); 
  757. if ( ! empty( $pages ) ) { 
  758. foreach ( $pages as $page ) { 
  759. $data[ $page->ID ] = $page->post_title; 
  760. //foreach 
  761. //if 
  762. } else if ( $type == "terms" || $type == "term" ) { 
  763. $taxonomies = $args['taxonomies']; 
  764. unset( $args['taxonomies'] ); 
  765. $terms = get_terms( $taxonomies, $args ); // this will get nothing 
  766. if ( ! empty( $terms ) ) { 
  767. foreach ( $terms as $term ) { 
  768. $data[ $term->term_id ] = $term->name; 
  769. //foreach 
  770. } // If 
  771. } else if ( $type == "taxonomy" || $type == "taxonomies" ) { 
  772. $taxonomies = get_taxonomies( $args ); 
  773. if ( ! empty( $taxonomies ) ) { 
  774. foreach ( $taxonomies as $key => $taxonomy ) { 
  775. $data[ $key ] = $taxonomy; 
  776. //foreach 
  777. } // If 
  778. } else if ( $type == "posts" || $type == "post" ) { 
  779. $posts = get_posts( $args ); 
  780. if ( ! empty( $posts ) ) { 
  781. foreach ( $posts as $post ) { 
  782. $data[ $post->ID ] = $post->post_title; 
  783. //foreach 
  784. //if 
  785. } else if ( $type == "post_type" || $type == "post_types" ) { 
  786. global $wp_post_types; 
  787.  
  788. $defaults = array( 
  789. 'public' => true,  
  790. 'exclude_from_search' => false,  
  791. ); 
  792. $args = wp_parse_args( $args, $defaults ); 
  793. $output = 'names'; 
  794. $operator = 'and'; 
  795. $post_types = get_post_types( $args, $output, $operator ); 
  796.  
  797. ksort( $post_types ); 
  798.  
  799. foreach ( $post_types as $name => $title ) { 
  800. if ( isset( $wp_post_types[ $name ]->labels->menu_name ) ) { 
  801. $data[ $name ] = $wp_post_types[ $name ]->labels->menu_name; 
  802. } else { 
  803. $data[ $name ] = ucfirst( $name ); 
  804. } else if ( $type == "tags" || $type == "tag" ) { // NOT WORKING! 
  805. $tags = get_tags( $args ); 
  806. if ( ! empty( $tags ) ) { 
  807. foreach ( $tags as $tag ) { 
  808. $data[ $tag->term_id ] = $tag->name; 
  809. //foreach 
  810. //if 
  811. } else if ( $type == "menu_location" || $type == "menu_locations" ) { 
  812. global $_wp_registered_nav_menus; 
  813.  
  814. foreach ( $_wp_registered_nav_menus as $k => $v ) { 
  815. $data[ $k ] = $v; 
  816. } else if ( $type == "image_size" || $type == "image_sizes" ) { 
  817. global $_wp_additional_image_sizes; 
  818.  
  819. foreach ( $_wp_additional_image_sizes as $size_name => $size_attrs ) { 
  820. $data[ $size_name ] = $size_name . ' - ' . $size_attrs['width'] . ' x ' . $size_attrs['height']; 
  821. } else if ( $type == "elusive-icons" || $type == "elusive-icon" || $type == "elusive" || 
  822. $type == "font-icon" || $type == "font-icons" || $type == "icons" 
  823. ) { 
  824.  
  825. /** 
  826. * filter 'redux-font-icons' 
  827. * @deprecated 
  828. * @param array $font_icons array of elusive icon classes 
  829. */ 
  830. $font_icons = apply_filters( 'redux-font-icons', array() ); // REMOVE LATER 
  831.  
  832. /** 
  833. * filter 'redux/font-icons' 
  834. * @deprecated 
  835. * @param array $font_icons array of elusive icon classes 
  836. */ 
  837. $font_icons = apply_filters( 'redux/font-icons', $font_icons ); 
  838.  
  839. /** 
  840. * filter 'redux/{opt_name}/field/font/icons' 
  841. * @deprecated 
  842. * @param array $font_icons array of elusive icon classes 
  843. */ 
  844. $font_icons = apply_filters( "redux/{$this->args['opt_name']}/field/font/icons", $font_icons ); 
  845.  
  846. foreach ( $font_icons as $k ) { 
  847. $data[ $k ] = $k; 
  848. } else if ( $type == "roles" ) { 
  849. /** @global WP_Roles $wp_roles */ 
  850. global $wp_roles; 
  851.  
  852. $data = $wp_roles->get_names(); 
  853. } else if ( $type == "sidebars" || $type == "sidebar" ) { 
  854. /** @global array $wp_registered_sidebars */ 
  855. global $wp_registered_sidebars; 
  856.  
  857. foreach ( $wp_registered_sidebars as $key => $value ) { 
  858. $data[ $key ] = $value['name']; 
  859. } else if ( $type == "capabilities" ) { 
  860. /** @global WP_Roles $wp_roles */ 
  861. global $wp_roles; 
  862.  
  863. foreach ( $wp_roles->roles as $role ) { 
  864. foreach ( $role['capabilities'] as $key => $cap ) { 
  865. $data[ $key ] = ucwords( str_replace( '_', ' ', $key ) ); 
  866. } else if ( $type == "callback" ) { 
  867. if ( ! is_array( $args ) ) { 
  868. $args = array( $args ); 
  869. $data = call_user_func( $args[0] ); 
  870. //if 
  871. //if 
  872.  
  873. $this->wp_data[ $type . $argsKey ] = $data; 
  874.  
  875. //if 
  876.  
  877. return $data; 
  878. } // get_wordpress_data() 
  879.  
  880. /** 
  881. * ->show(); This is used to echo and option value from the options array 
  882. * @since 1.0.0 
  883. * @access public 
  884. * @param string $opt_name The name of the option being shown 
  885. * @param mixed $default The value to show if $opt_name isn't set 
  886. * @return void 
  887. */ 
  888. public function show( $opt_name, $default = '' ) { 
  889. $option = $this->get( $opt_name ); 
  890. if ( ! is_array( $option ) && $option != '' ) { 
  891. echo $option; 
  892. } elseif ( $default != '' ) { 
  893. echo $this->_get_default( $opt_name, $default ); 
  894. } // show() 
  895.  
  896. /** 
  897. * Get the default value for an option 
  898. * @since 3.3.6 
  899. * @access public 
  900. * @param string $key The option's ID 
  901. * @param string $array_key The key of the default's array 
  902. * @return mixed 
  903. */ 
  904. public function get_default_value( $key, $array_key = false ) { 
  905. if ( empty( $this->options_defaults ) ) { 
  906. $this->options_defaults = $this->_default_values(); 
  907.  
  908. $defaults = $this->options_defaults; 
  909. $value = ''; 
  910.  
  911. if ( isset( $defaults[ $key ] ) ) { 
  912. if ( $array_key !== false && isset( $defaults[ $key ][ $array_key ] ) ) { 
  913. $value = $defaults[ $key ][ $array_key ]; 
  914. } else { 
  915. $value = $defaults[ $key ]; 
  916.  
  917. return $value; 
  918.  
  919.  
  920. /** 
  921. * Get default options into an array suitable for the settings API 
  922. * @since 1.0.0 
  923. * @access public 
  924. * @return array $this->options_defaults 
  925. */ 
  926. public function _default_values() { 
  927. if ( ! is_null( $this->sections ) && is_null( $this->options_defaults ) ) { 
  928.  
  929. // fill the cache 
  930. foreach ( $this->sections as $sk => $section ) { 
  931. if ( ! isset( $section['id'] ) ) { 
  932. if ( ! is_numeric( $sk ) || ! isset( $section['title'] ) ) { 
  933. $section['id'] = $sk; 
  934. } else { 
  935. $section['id'] = sanitize_title( $section['title'], $sk ); 
  936. $this->sections[ $sk ] = $section; 
  937. if ( isset( $section['fields'] ) ) { 
  938. foreach ( $section['fields'] as $k => $field ) { 
  939. if ( empty( $field['id'] ) && empty( $field['type'] ) ) { 
  940. continue; 
  941.  
  942. if ( in_array( $field['type'], array( 'ace_editor' ) ) && isset( $field['options'] ) ) { 
  943. $this->sections[ $sk ]['fields'][ $k ]['args'] = $field['options']; 
  944. unset( $this->sections[ $sk ]['fields'][ $k ]['options'] ); 
  945.  
  946. if ( $field['type'] == "section" && isset( $field['indent'] ) && $field['indent'] == "true" ) { 
  947. $field['class'] = isset( $field['class'] ) ? $field['class'] : ''; 
  948. $field['class'] .= "redux-section-indent-start"; 
  949. $this->sections[ $sk ]['fields'][ $k ] = $field; 
  950. // Detect what field types are being used 
  951. if ( ! isset( $this->fields[ $field['type'] ][ $field['id'] ] ) ) { 
  952. $this->fields[ $field['type'] ][ $field['id'] ] = 1; 
  953. } else { 
  954. $this->fields[ $field['type'] ] = array( $field['id'] => 1 ); 
  955. if ( isset( $field['default'] ) ) { 
  956. $this->options_defaults[ $field['id'] ] = $field['default']; 
  957. } elseif ( isset( $field['options'] ) && ( $field['type'] != "ace_editor" ) ) { 
  958. // Sorter data filter 
  959.  
  960. if ( $field['type'] == "sorter" && isset( $field['data'] ) && ! empty( $field['data'] ) && is_array( $field['data'] ) ) { 
  961. if ( ! isset( $field['args'] ) ) { 
  962. $field['args'] = array(); 
  963. foreach ( $field['data'] as $key => $data ) { 
  964. if ( ! isset( $field['args'][ $key ] ) ) { 
  965. $field['args'][ $key ] = array(); 
  966. $field['options'][ $key ] = $this->get_wordpress_data( $data, $field['args'][ $key ] ); 
  967.  
  968. if ( $field['type'] == "sortable" ) { 
  969. $this->options_defaults[ $field['id'] ] = array(); 
  970. } elseif ( $field['type'] == "image_select" ) { 
  971. $this->options_defaults[ $field['id'] ] = ''; 
  972. } elseif ( $field['type'] == "select" ) { 
  973. $this->options_defaults[ $field['id'] ] = ''; 
  974. } else { 
  975. $this->options_defaults[ $field['id'] ] = $field['options']; 
  976.  
  977. /** 
  978. * filter 'redux/options/{opt_name}/defaults' 
  979. * @param array $defaults option default values 
  980. */ 
  981. $this->transients['changed_values'] = isset( $this->transients['changed_values'] ) ? $this->transients['changed_values'] : array(); 
  982. $this->options_defaults = apply_filters( "redux/options/{$this->args['opt_name']}/defaults", $this->options_defaults, $this->transients['changed_values'] ); 
  983.  
  984. return $this->options_defaults; 
  985.  
  986. /** 
  987. * Set default options on admin_init if option doesn't exist 
  988. * @since 1.0.0 
  989. * @access public 
  990. * @return void 
  991. */ 
  992. private function _default_cleanup() { 
  993.  
  994. // Fix the global variable name 
  995. if ( $this->args['global_variable'] == "" && $this->args['global_variable'] !== false ) { 
  996. $this->args['global_variable'] = str_replace( '-', '_', $this->args['opt_name'] ); 
  997.  
  998. /** 
  999. * Class Add Sub Menu Function, creates options submenu in Wordpress admin area. 
  1000. * @since 3.1.9 
  1001. * @access private 
  1002. * @return void 
  1003. */ 
  1004. private function add_submenu( $page_parent, $page_title, $menu_title, $page_permissions, $page_slug ) { 
  1005. global $submenu; 
  1006.  
  1007. // Just in case. One never knows. 
  1008. $page_parent = strtolower( $page_parent ); 
  1009.  
  1010. $test = array( 
  1011. 'index.php' => 'dashboard',  
  1012. 'edit.php' => 'posts',  
  1013. 'upload.php' => 'media',  
  1014. 'link-manager.php' => 'links',  
  1015. 'edit.php?post_type=page' => 'pages',  
  1016. 'edit-comments.php' => 'comments',  
  1017. 'themes.php' => 'theme',  
  1018. 'plugins.php' => 'plugins',  
  1019. 'users.php' => 'users',  
  1020. 'tools.php' => 'management',  
  1021. 'options-general.php' => 'options',  
  1022. ); 
  1023.  
  1024. if ( isset( $test[ $page_parent ] ) ) { 
  1025. $function = 'add_' . $test[ $page_parent ] . '_page'; 
  1026. $this->page = $function( 
  1027. $page_title, $menu_title, $page_permissions, $page_slug, array( $this, '_options_page_html' ) 
  1028. ); 
  1029. } else { 
  1030. // Network settings and Post type menus. These do not have 
  1031. // wrappers and need to be appened to using add_submenu_page. 
  1032. // Okay, since we've left the post type menu appending 
  1033. // as default, we need to validate it, so anything that 
  1034. // isn't post_type=<post_type> doesn't get through and mess 
  1035. // things up. 
  1036. $addMenu = false; 
  1037. if ( 'settings.php' != $page_parent ) { 
  1038. // Establish the needle 
  1039. $needle = '?post_type='; 
  1040.  
  1041. // Check if it exists in the page_parent (how I miss instr) 
  1042. $needlePos = strrpos( $page_parent, $needle ); 
  1043.  
  1044. // It's there, so... 
  1045. if ( $needlePos > 0 ) { 
  1046.  
  1047. // Get the post type. 
  1048. $postType = substr( $page_parent, $needlePos + strlen( $needle ) ); 
  1049.  
  1050. // Ensure it exists. 
  1051. if ( post_type_exists( $postType ) ) { 
  1052. // Set flag to add the menu page 
  1053. $addMenu = true; 
  1054. // custom menu 
  1055. } elseif ( isset( $submenu[ $this->args['page_parent'] ] ) ) { 
  1056. $addMenu = true; 
  1057.  
  1058. } else { 
  1059. // The page_parent was settings.php, so set menu add 
  1060. // flag to true. 
  1061. $addMenu = true; 
  1062. // Add the submenu if it's permitted. 
  1063. if ( true == $addMenu ) { 
  1064. $this->page = add_submenu_page( 
  1065. $page_parent, $page_title, $menu_title, $page_permissions, $page_slug, array( 
  1066. &$this,  
  1067. '_options_page_html' 
  1068. ); 
  1069.  
  1070. /** 
  1071. * Class Options Page Function, creates main options page. 
  1072. * @since 1.0.0 
  1073. * @access public 
  1074. * @return void 
  1075. */ 
  1076. public function _options_page() { 
  1077. $this->import_export->in_field(); 
  1078.  
  1079. if ( $this->args['menu_type'] == 'hidden' ) { 
  1080.  
  1081. // No menu to add! 
  1082.  
  1083. } else if ( $this->args['menu_type'] == 'submenu' ) { 
  1084. $this->add_submenu( 
  1085. $this->args['page_parent'],  
  1086. $this->args['page_title'],  
  1087. $this->args['menu_title'],  
  1088. $this->args['page_permissions'],  
  1089. $this->args['page_slug'] 
  1090. ); 
  1091.  
  1092. } else { 
  1093. $this->page = add_menu_page( 
  1094. $this->args['page_title'],  
  1095. $this->args['menu_title'],  
  1096. $this->args['page_permissions'],  
  1097. $this->args['page_slug'],  
  1098. array( &$this, '_options_page_html' ),  
  1099. $this->args['menu_icon'],  
  1100. $this->args['page_priority'] 
  1101. ); 
  1102.  
  1103. if ( true === $this->args['allow_sub_menu'] ) { 
  1104. if ( ! isset( $section['type'] ) || $section['type'] != 'divide' ) { 
  1105. foreach ( $this->sections as $k => $section ) { 
  1106. $canBeSubSection = ( $k > 0 && ( ! isset( $this->sections[ ( $k ) ]['type'] ) || $this->sections[ ( $k ) ]['type'] != "divide" ) ) ? true : false; 
  1107.  
  1108. if ( ! isset( $section['title'] ) || ( $canBeSubSection && ( isset( $section['subsection'] ) && $section['subsection'] == true ) ) ) { 
  1109. continue; 
  1110.  
  1111. if ( isset( $section['submenu'] ) && $section['submenu'] == false ) { 
  1112. continue; 
  1113.  
  1114. if ( isset( $section['customizer_only'] ) && $section['customizer_only'] == true ) { 
  1115. continue; 
  1116.  
  1117. add_submenu_page( 
  1118. $this->args['page_slug'],  
  1119. $section['title'],  
  1120. $section['title'],  
  1121. $this->args['page_permissions'],  
  1122. $this->args['page_slug'] . '&tab=' . $k,  
  1123. //create_function( '$a', "return null;" ) 
  1124. '__return_null' 
  1125. ); 
  1126.  
  1127. // Remove parent submenu item instead of adding null item. 
  1128. remove_submenu_page( $this->args['page_slug'], $this->args['page_slug'] ); 
  1129.  
  1130. if ( true == $this->args['show_import_export'] && false == $this->import_export->is_field ) { 
  1131. $this->import_export->add_submenu(); 
  1132.  
  1133. if ( true == $this->args['dev_mode'] ) { 
  1134. $this->debug->add_submenu(); 
  1135.  
  1136. if ( true == $this->args['system_info'] ) { 
  1137. add_submenu_page( 
  1138. $this->args['page_slug'],  
  1139. __( 'System Info', 'redux-framework' ),  
  1140. __( 'System Info', 'redux-framework' ),  
  1141. $this->args['page_permissions'],  
  1142. $this->args['page_slug'] . '&tab=system_info_default',  
  1143. '__return_null' 
  1144. ); 
  1145.  
  1146. add_action( "load-{$this->page}", array( &$this, '_load_page' ) ); 
  1147. } // _options_page() 
  1148.  
  1149. /** 
  1150. * Add admin bar menu 
  1151. * @since 3.1.5.16 
  1152. * @access public 
  1153. * @global $menu , $submenu, $wp_admin_bar 
  1154. * @return void 
  1155. */ 
  1156. public function _admin_bar_menu() { 
  1157. global $menu, $submenu, $wp_admin_bar; 
  1158.  
  1159. $ct = wp_get_theme(); 
  1160. $theme_data = $ct; 
  1161.  
  1162. if ( ! is_super_admin() || ! is_admin_bar_showing() || ! $this->args['admin_bar'] || $this->args['menu_type'] == 'hidden' ) { 
  1163. return; 
  1164.  
  1165. if ( $menu ) { 
  1166. foreach ( $menu as $menu_item ) { 
  1167. if ( isset( $menu_item[2] ) && $menu_item[2] === $this->args["page_slug"] ) { 
  1168.  
  1169. // Fetch the title 
  1170. $title = empty( $this->args['admin_bar_icon'] ) ? $menu_item[0] : '<span class="ab-icon ' . $this->args['admin_bar_icon'] . '"></span>' . $menu_item[0]; 
  1171.  
  1172. $nodeargs = array( 
  1173. 'id' => $menu_item[2],  
  1174. 'title' => $title,  
  1175. 'href' => admin_url( 'admin.php?page=' . $menu_item[2] ),  
  1176. 'meta' => array() 
  1177. ); 
  1178. $wp_admin_bar->add_node( $nodeargs ); 
  1179.  
  1180. break; 
  1181.  
  1182. if ( isset( $submenu[ $this->args["page_slug"] ] ) && is_array( $submenu[ $this->args["page_slug"] ] ) ) { 
  1183. foreach ( $submenu[ $this->args["page_slug"] ] as $index => $redux_options_submenu ) { 
  1184. $subnodeargs = array( 
  1185. 'id' => $this->args["page_slug"] . '_' . $index,  
  1186. 'title' => $redux_options_submenu[0],  
  1187. 'parent' => $this->args["page_slug"],  
  1188. 'href' => admin_url( 'admin.php?page=' . $redux_options_submenu[2] ),  
  1189. ); 
  1190.  
  1191. $wp_admin_bar->add_node( $subnodeargs ); 
  1192.  
  1193. // Let's deal with external links 
  1194. if ( isset( $this->args['admin_bar_links'] ) ) { 
  1195.  
  1196. // Group for Main Root Menu (External Group) 
  1197. $wp_admin_bar->add_node( array( 
  1198. 'id' => $this->args["page_slug"] . '-external',  
  1199. 'parent' => $this->args["page_slug"],  
  1200. 'group' => true,  
  1201. 'meta' => array( 'class' => 'ab-sub-secondary' ) 
  1202. ) ); 
  1203.  
  1204. // Add Child Menus to External Group Menu 
  1205. foreach ( $this->args['admin_bar_links'] as $link ) { 
  1206. if ( ! isset( $link['id'] ) ) { 
  1207. $link['id'] = $this->args["page_slug"] . '-sub-' . sanitize_html_class( $link['title'] ); 
  1208. $externalnodeargs = array( 
  1209. 'id' => $link['id'],  
  1210. 'title' => $link['title'],  
  1211. 'parent' => $this->args["page_slug"] . '-external',  
  1212. 'href' => $link['href'],  
  1213. 'meta' => array( 'target' => '_blank' ) 
  1214. ); 
  1215.  
  1216. $wp_admin_bar->add_node( $externalnodeargs ); 
  1217. } else { 
  1218. // Fetch the title 
  1219. $title = empty( $this->args['admin_bar_icon'] ) ? $this->args['menu_title'] : '<span class="ab-icon ' . $this->args['admin_bar_icon'] . '"></span>' . $this->args['menu_title']; 
  1220.  
  1221. $nodeargs = array( 
  1222. 'id' => $this->args["page_slug"],  
  1223. 'title' => $title,  
  1224. // $theme_data->get( 'Name' ) . " " . __( 'Options', 'redux-framework-demo' ),  
  1225. 'href' => admin_url( 'admin.php?page=' . $this->args["page_slug"] ),  
  1226. 'meta' => array() 
  1227. ); 
  1228.  
  1229. $wp_admin_bar->add_node( $nodeargs ); 
  1230. } // _admin_bar_menu() 
  1231.  
  1232. /** 
  1233. * Output dynamic CSS at bottom of HEAD 
  1234. * @since 3.2.8 
  1235. * @access public 
  1236. * @return void 
  1237. */ 
  1238. public function _output_css() { 
  1239. if ( $this->args['output'] == false && $this->args['compiler'] == false ) { 
  1240. return; 
  1241.  
  1242. if ( isset( $this->no_output ) ) { 
  1243. return; 
  1244.  
  1245. if ( ! empty( $this->outputCSS ) && ( $this->args['output_tag'] == true || ( isset( $_POST['customized'] ) ) ) ) { 
  1246. echo '<style type="text/css" title="dynamic-css" class="options-output">' . $this->outputCSS . '</style>'; 
  1247.  
  1248. /** 
  1249. * Enqueue CSS and Google fonts for front end 
  1250. * @since 1.0.0 
  1251. * @access public 
  1252. * @return void 
  1253. */ 
  1254. public function _enqueue_output() { 
  1255. if ( $this->args['output'] == false && $this->args['compiler'] == false ) { 
  1256. return; 
  1257.  
  1258. /** @noinspection PhpUnusedLocalVariableInspection */ 
  1259. foreach ( $this->sections as $k => $section ) { 
  1260. if ( isset( $section['type'] ) && ( $section['type'] == 'divide' ) ) { 
  1261. continue; 
  1262.  
  1263. if ( isset( $section['fields'] ) ) { 
  1264. /** @noinspection PhpUnusedLocalVariableInspection */ 
  1265. foreach ( $section['fields'] as $fieldk => $field ) { 
  1266. if ( isset( $field['type'] ) && $field['type'] != "callback" ) { 
  1267. $field_class = "ReduxFramework_{$field['type']}"; 
  1268. if ( ! class_exists( $field_class ) ) { 
  1269.  
  1270. if ( ! isset( $field['compiler'] ) ) { 
  1271. $field['compiler'] = ""; 
  1272.  
  1273. /** 
  1274. * Field class file 
  1275. * filter 'redux/{opt_name}/field/class/{field.type} 
  1276. * @param string field class file 
  1277. * @param array $field field config data 
  1278. */ 
  1279. $class_file = apply_filters( "redux/{$this->args['opt_name']}/field/class/{$field['type']}", self::$_dir . "inc/fields/{$field['type']}/field_{$field['type']}.php", $field ); 
  1280.  
  1281. if ( $class_file && file_exists( $class_file ) && ! class_exists( $field_class ) ) { 
  1282. /** @noinspection PhpIncludeInspection */ 
  1283. require_once( $class_file ); 
  1284.  
  1285. if ( ! empty( $this->options[ $field['id'] ] ) && class_exists( $field_class ) && method_exists( $field_class, 'output' ) && $this->_can_output_css( $field ) ) { 
  1286. $field = apply_filters( "redux/field/{$this->args['opt_name']}/output_css", $field ); 
  1287.  
  1288. if ( ! empty( $field['output'] ) && ! is_array( $field['output'] ) ) { 
  1289. $field['output'] = array( $field['output'] ); 
  1290.  
  1291. $value = isset( $this->options[ $field['id'] ] ) ? $this->options[ $field['id'] ] : ''; 
  1292. $enqueue = new $field_class( $field, $value, $this ); 
  1293.  
  1294. if ( ( ( isset( $field['output'] ) && ! empty( $field['output'] ) ) || ( isset( $field['compiler'] ) && ! empty( $field['compiler'] ) ) || $field['type'] == "typography" || $field['type'] == "icon_select" ) ) { 
  1295. $enqueue->output(); 
  1296.  
  1297. // For use like in the customizer. Stops the output, but passes the CSS in the variable for the compiler 
  1298. if ( isset( $this->no_output ) ) { 
  1299. return; 
  1300.  
  1301. if ( ! empty( $this->typography ) && ! empty( $this->typography ) && filter_var( $this->args['output'], FILTER_VALIDATE_BOOLEAN ) ) { 
  1302. $version = ! empty( $this->transients['last_save'] ) ? $this->transients['last_save'] : ''; 
  1303. $typography = new ReduxFramework_typography( null, null, $this ); 
  1304.  
  1305. if ( $this->args['async_typography'] && ! empty( $this->typography ) ) { 
  1306. $families = array(); 
  1307. foreach ( $this->typography as $key => $value ) { 
  1308. $families[] = $key; 
  1309.  
  1310. ?> 
  1311. <script> 
  1312. /* You can add more configuration options to webfontloader by previously defining the WebFontConfig with your options */ 
  1313. if ( typeof WebFontConfig === "undefined" ) { 
  1314. WebFontConfig = new Object(); 
  1315. WebFontConfig['google'] = {families: [<?php echo $typography->makeGoogleWebfontString( $this->typography )?>]}; 
  1316.  
  1317. (function() { 
  1318. var wf = document.createElement( 'script' ); 
  1319. wf.src = 'https://ajax.googleapis.com/ajax/libs/webfont/1.5.3/webfont.js'; 
  1320. wf.type = 'text/javascript'; 
  1321. wf.async = 'true'; 
  1322. var s = document.getElementsByTagName( 'script' )[0]; 
  1323. s.parentNode.insertBefore( wf, s ); 
  1324. })(); 
  1325. </script> 
  1326. <?php 
  1327. } elseif ( ! $this->args['disable_google_fonts_link'] ) { 
  1328. $protocol = ( ! empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443 ) ? "https:" : "http:"; 
  1329.  
  1330. //echo '<link rel="stylesheet" id="options-google-fonts" title="" href="'.$protocol.$typography->makeGoogleWebfontLink( $this->typography ).'&v='.$version.'" type="text/css" media="all" />'; 
  1331. wp_register_style( 'redux-google-fonts', $protocol . $typography->makeGoogleWebfontLink( $this->typography ), '', $version ); 
  1332. wp_enqueue_style( 'redux-google-fonts' ); 
  1333.  
  1334. } // _enqueue_output() 
  1335.  
  1336. /** 
  1337. * Enqueue CSS/JS for options page 
  1338. * @since 1.0.0 
  1339. * @access public 
  1340. * @global $wp_styles 
  1341. * @return void 
  1342. */ 
  1343. public function _enqueue() { 
  1344. global $wp_styles; 
  1345.  
  1346. Redux_Functions::$_parent = $this; 
  1347. $min = Redux_Functions::isMin(); 
  1348.  
  1349. // Select2 business. Fields: Background, Border, Dimensions, Select, Slider, Typography 
  1350. $field_arr = array( 
  1351. 'background',  
  1352. 'border',  
  1353. 'dimensions',  
  1354. 'select',  
  1355. 'select_image',  
  1356. 'slider',  
  1357. 'spacing',  
  1358. 'typography',  
  1359. 'color_scheme',  
  1360. 'css_layout' 
  1361. ); 
  1362.  
  1363. if ( Redux_Helpers::isFieldInUseByType( $this->fields, $field_arr ) ) { 
  1364.  
  1365. // select2 CSS 
  1366. wp_register_style( 
  1367. 'select2-css',  
  1368. self::$_url . 'assets/js/vendor/select2/select2.css',  
  1369. array(),  
  1370. filemtime( self::$_dir . 'assets/js/vendor/select2/select2.css' ),  
  1371. 'all' 
  1372. ); 
  1373.  
  1374. wp_enqueue_style( 'select2-css' ); 
  1375.  
  1376. // JS 
  1377. wp_register_script( 
  1378. 'redux-select2-sortable-js',  
  1379. self::$_url . 'assets/js/vendor/redux.select2.sortable' . $min . '.js',  
  1380. array( 'jquery' ),  
  1381. filemtime( self::$_dir . 'assets/js/vendor/redux.select2.sortable' . $min . '.js' ),  
  1382. true 
  1383. ); 
  1384.  
  1385. wp_register_script( 
  1386. 'select2-js',  
  1387. self::$_url . 'assets/js/vendor/select2/select2.min.js',  
  1388. array( 'jquery', 'redux-select2-sortable-js' ),  
  1389. filemtime( self::$_dir . 'assets/js/vendor/select2/select2.min.js' ),  
  1390. true 
  1391. ); 
  1392.  
  1393. wp_enqueue_script( 'select2-js' ); 
  1394.  
  1395. redux_enqueue_style( 
  1396. $this,  
  1397. 'redux-admin-css',  
  1398. self::$_url . 'assets/css/redux-admin.css',  
  1399. self::$_dir . 'assets/css/',  
  1400. array( 'farbtastic' ),  
  1401. time(),  
  1402. 'all' 
  1403. );  
  1404.  
  1405. // wp_enqueue_style( 
  1406. // 'redux-css',  
  1407. // self::$_url . 'assets/css/redux.css',  
  1408. // array( 'farbtastic' ),  
  1409. // filemtime( self::$_dir . 'assets/css/redux.css' ),  
  1410. // 'all' 
  1411. // ); 
  1412. // 
  1413. // wp_register_style( 
  1414. // 'admin-css',  
  1415. // self::$_url . 'assets/css/admin.css',  
  1416. // array( 'farbtastic' ),  
  1417. // filemtime( self::$_dir . 'assets/css/admin.css' ),  
  1418. // 'all' 
  1419. // ); 
  1420.  
  1421. wp_register_style( 
  1422. 'redux-elusive-icon',  
  1423. self::$_url . 'assets/css/vendor/elusive-icons/elusive-webfont.css',  
  1424. array(),  
  1425. filemtime( self::$_dir . 'assets/css/vendor/elusive-icons/elusive-webfont.css' ),  
  1426. 'all' 
  1427. ); 
  1428.  
  1429. wp_register_style( 
  1430. 'redux-elusive-icon-ie7',  
  1431. self::$_url . 'assets/css/vendor/elusive-icons/elusive-webfont-ie7.css',  
  1432. array(),  
  1433. filemtime( self::$_dir . 'assets/css/vendor/elusive-icons/elusive-webfont-ie7.css' ),  
  1434. 'all' 
  1435. ); 
  1436.  
  1437. wp_register_style( 
  1438. 'qtip-css',  
  1439. self::$_url . 'assets/css/vendor/qtip/jquery.qtip.css',  
  1440. array(),  
  1441. filemtime( self::$_dir . 'assets/css/vendor/qtip/jquery.qtip.css' ),  
  1442. 'all' 
  1443. ); 
  1444.  
  1445. $wp_styles->add_data( 'redux-elusive-icon-ie7', 'conditional', 'lte IE 7' ); 
  1446.  
  1447. /** 
  1448. * jQuery UI stylesheet src 
  1449. * filter 'redux/page/{opt_name}/enqueue/jquery-ui-css' 
  1450. * @param string bundled stylesheet src 
  1451. */ 
  1452. wp_register_style( 
  1453. 'jquery-ui-css',  
  1454. apply_filters( "redux/page/{$this->args['opt_name']}/enqueue/jquery-ui-css", self::$_url . 'assets/css/vendor/jquery-ui-bootstrap/jquery-ui-1.10.0.custom.css' ),  
  1455. '',  
  1456. filemtime( self::$_dir . 'assets/css/vendor/jquery-ui-bootstrap/jquery-ui-1.10.0.custom.css' ), // todo - version should be based on above post-filter src 
  1457. 'all' 
  1458. ); 
  1459.  
  1460. wp_enqueue_style( 'jquery-ui-css' ); 
  1461. wp_enqueue_style( 'redux-lte-ie8' ); 
  1462. wp_enqueue_style( 'qtip-css' ); 
  1463. wp_enqueue_style( 'redux-elusive-icon' ); 
  1464. wp_enqueue_style( 'redux-elusive-icon-ie7' ); 
  1465.  
  1466. if ( is_rtl() ) { 
  1467. wp_register_style( 
  1468. 'redux-rtl-css',  
  1469. self::$_url . 'assets/css/rtl.css',  
  1470. array('redux-css'),  
  1471. filemtime( self::$_dir . 'assets/css/rtl.css' ),  
  1472. 'all' 
  1473. ); 
  1474. wp_enqueue_style( 'redux-rtl-css' ); 
  1475.  
  1476. wp_enqueue_script( 'jquery' ); 
  1477. wp_enqueue_script( 'jquery-ui-core' ); 
  1478. wp_enqueue_script( 'jquery-ui-dialog' ); 
  1479.  
  1480. // Load jQuery sortable for slides, sorter, sortable and group 
  1481. if ( Redux_Helpers::isFieldInUseByType( $this->fields, array( 
  1482. 'slides',  
  1483. 'sorter',  
  1484. 'sortable',  
  1485. 'group' 
  1486. ) ) 
  1487. ) { 
  1488. wp_enqueue_script( 'jquery-ui-sortable' ); 
  1489. wp_enqueue_style( 'jquery-ui-sortable' ); 
  1490.  
  1491. // Load jQuery UI Datepicker for date 
  1492. if ( Redux_Helpers::isFieldInUseByType( $this->fields, array( 'date', 'datetime' ) ) ) { 
  1493. wp_enqueue_script( 'jquery-ui-datepicker' ); 
  1494.  
  1495. // Load jQuery UI Accordion for slides and group 
  1496. if ( Redux_Helpers::isFieldInUseByType( $this->fields, array( 'slides', 'group' ) ) ) { 
  1497. wp_enqueue_script( 'jquery-ui-accordion' ); 
  1498.  
  1499. // Load wp-color-picker for color, color_gradient, link_color, border, background and typography 
  1500. if ( Redux_Helpers::isFieldInUseByType( $this->fields, array( 
  1501. 'background',  
  1502. 'color',  
  1503. 'color_gradient',  
  1504. 'link_color',  
  1505. 'border',  
  1506. 'typography',  
  1507. 'css_layout' 
  1508. ) ) 
  1509. ) { 
  1510.  
  1511. redux_enqueue_style( 
  1512. $this,  
  1513. 'redux-color-picker-css',  
  1514. ReduxFramework::$_url . 'assets/css/color-picker/color-picker.css',  
  1515. ReduxFramework::$_dir . 'assets/css/color-picker',  
  1516. array(),  
  1517. time(),  
  1518. false 
  1519. );  
  1520.  
  1521. // wp_enqueue_style( 
  1522. // 'redux-color-picker-css',  
  1523. // self::$_url . 'assets/css/color-picker/color-picker.css',  
  1524. // array( 'wp-color-picker' ),  
  1525. // filemtime( self::$_dir . 'assets/css/color-picker/color-picker.css' ),  
  1526. // 'all' 
  1527. // ); 
  1528.  
  1529. wp_enqueue_style( 'color-picker-css' ); 
  1530.  
  1531.  
  1532. wp_enqueue_script( 'wp-color-picker' ); 
  1533. wp_enqueue_style( 'wp-color-picker' ); 
  1534.  
  1535. if ( function_exists( 'wp_enqueue_media' ) ) { 
  1536. wp_enqueue_media(); 
  1537. } else { 
  1538. wp_enqueue_script( 'media-upload' ); 
  1539.  
  1540. add_thickbox(); 
  1541.  
  1542. wp_register_script( 
  1543. 'qtip-js',  
  1544. self::$_url . 'assets/js/vendor/qtip/jquery.qtip.js',  
  1545. array( 'jquery' ),  
  1546. '2.2.0',  
  1547. true 
  1548. ); 
  1549.  
  1550. wp_register_script( 
  1551. 'serializeForm-js',  
  1552. self::$_url . 'assets/js/vendor/jquery.serializeForm.js',  
  1553. array( 'jquery' ),  
  1554. '1.0.0',  
  1555. true 
  1556. ); 
  1557.  
  1558. // Embed the compress version unless in dev mode 
  1559. // dev_mode = true 
  1560. if ( isset( $this->args['dev_mode'] ) && $this->args['dev_mode'] == true ) { 
  1561. //wp_enqueue_style( 'admin-css' ); 
  1562. wp_register_script( 
  1563. 'redux-vendor',  
  1564. self::$_url . 'assets/js/vendor.min.js',  
  1565. array( 'jquery' ),  
  1566. filemtime( self::$_dir . 'assets/js/vendor.min.js' ),  
  1567. true 
  1568. ); 
  1569.  
  1570. // dev_mode - false 
  1571. } else { 
  1572. //wp_enqueue_style( 'redux-css' ); 
  1573.  
  1574. $depArray = array( 'jquery', 'qtip-js', 'serializeForm-js', ); 
  1575.  
  1576. if ( true == $this->args['dev_mode'] ) { 
  1577. array_push( $depArray, 'redux-vendor' ); 
  1578.  
  1579. wp_register_script( 
  1580. 'redux-js',  
  1581. self::$_url . 'assets/js/redux' . $min . '.js',  
  1582. $depArray,  
  1583. filemtime( self::$_dir . 'assets/js/redux' . $min . '.js' ),  
  1584. true 
  1585. ); 
  1586.  
  1587. foreach ( $this->sections as $section ) { 
  1588. if ( isset( $section['fields'] ) ) { 
  1589. foreach ( $section['fields'] as $field ) { 
  1590. // TODO AFTER GROUP WORKS - Revert IF below 
  1591. // if( isset( $field['type'] ) && $field['type'] != 'callback' ) { 
  1592. if ( isset( $field['type'] ) && $field['type'] != 'callback' ) { 
  1593.  
  1594. $field_class = 'ReduxFramework_' . $field['type']; 
  1595.  
  1596. /** 
  1597. * Field class file 
  1598. * filter 'redux/{opt_name}/field/class/{field.type} 
  1599. * @param string field class file path 
  1600. * @param array $field field config data 
  1601. */ 
  1602. $class_file = apply_filters( "redux/{$this->args['opt_name']}/field/class/{$field['type']}", self::$_dir . "inc/fields/{$field['type']}/field_{$field['type']}.php", $field ); 
  1603. if ( $class_file ) { 
  1604. if ( ! class_exists( $field_class ) ) { 
  1605. if ( file_exists( $class_file ) ) { 
  1606. require_once( $class_file ); 
  1607.  
  1608. if ( ( method_exists( $field_class, 'enqueue' ) ) || method_exists( $field_class, 'localize' ) ) { 
  1609. if ( ! isset( $this->options[ $field['id'] ] ) ) { 
  1610. $this->options[ $field['id'] ] = ""; 
  1611. $theField = new $field_class( $field, $this->options[ $field['id'] ], $this ); 
  1612.  
  1613. // Move dev_mode check to a new if/then block 
  1614. if ( ! wp_script_is( 'redux-field-' . $field['type'] . '-js', 'enqueued' ) && class_exists( $field_class ) && method_exists( $field_class, 'enqueue' ) ) { 
  1615.  
  1616. // Checking for extension field AND dev_mode = false OR dev_mode = true 
  1617. // Since extension fields use 'extension_dir' exclusively, we can detect them here. 
  1618. // Also checking for dev_mode = true doesn't mess up the JS combinine. 
  1619. //if ( /*$this->args['dev_mode'] === false && */ isset($theField->extension_dir) && (!'' == $theField->extension_dir) /* || ($this->args['dev_mode'] === true) */) { 
  1620. $theField->enqueue(); 
  1621. //print_r($field['type']); 
  1622. //} 
  1623.  
  1624. if ( method_exists( $field_class, 'localize' ) ) { 
  1625. $params = $theField->localize( $field ); 
  1626. if ( ! isset( $this->localize_data[ $field['type'] ] ) ) { 
  1627. $this->localize_data[ $field['type'] ] = array(); 
  1628. $this->localize_data[ $field['type'] ][ $field['id'] ] = $theField->localize( $field ); 
  1629.  
  1630. unset( $theField ); 
  1631.  
  1632. if ($this->args['sass']['enabled']) { 
  1633. reduxSassCompiler::compile_sass($this); 
  1634.  
  1635. if (!$this->args['sass']['page_output']) { 
  1636. wp_enqueue_style( 
  1637. 'redux-css',  
  1638. ReduxFramework::$_upload_url . $this->args['opt_name'] . '-redux.css',  
  1639. array(),  
  1640. time(),  
  1641. 'all' 
  1642. ); 
  1643.  
  1644. $this->localize_data['required'] = $this->required; 
  1645. $this->localize_data['fonts'] = $this->fonts; 
  1646. $this->localize_data['required_child'] = $this->required_child; 
  1647. $this->localize_data['fields'] = $this->fields; 
  1648.  
  1649. if ( isset( $this->font_groups['google'] ) ) { 
  1650. $this->localize_data['googlefonts'] = $this->font_groups['google']; 
  1651.  
  1652. if ( isset( $this->font_groups['std'] ) ) { 
  1653. $this->localize_data['stdfonts'] = $this->font_groups['std']; 
  1654.  
  1655. if ( isset( $this->font_groups['customfonts'] ) ) { 
  1656. $this->localize_data['customfonts'] = $this->font_groups['customfonts']; 
  1657.  
  1658. $this->localize_data['folds'] = $this->folds; 
  1659.  
  1660. // Make sure the children are all hidden properly. 
  1661. foreach ( $this->fields as $key => $value ) { 
  1662. if ( in_array( $key, $this->fieldsHidden ) ) { 
  1663. foreach ( $value as $k => $v ) { 
  1664. if ( ! in_array( $k, $this->fieldsHidden ) ) { 
  1665. $this->fieldsHidden[] = $k; 
  1666. $this->folds[ $k ] = "hide"; 
  1667.  
  1668. if ( isset( $this->args['dev_mode'] ) && $this->args['dev_mode'] == true ) { 
  1669.  
  1670. $base = admin_url( 'admin-ajax.php' ) . '?action=redux_p&url='; 
  1671. $url = $base . urlencode( 'http://ads.reduxframework.com/api/index.php?js&g&1&v=2' ) . '&proxy=' . urlencode( $base ); 
  1672. $this->localize_data['rAds'] = '<span data-id="1" class="mgv1_1"><script type="text/javascript">(function() {if (mysa_mgv1_1) return; var ma = document.createElement("script"); ma.type = "text/javascript"; ma.async = true; ma.src = "' . $url . '"; var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(ma, s) })();var mysa_mgv1_1=true;</script></span>'; 
  1673.  
  1674. $this->localize_data['fieldsHidden'] = $this->fieldsHidden; 
  1675. $this->localize_data['options'] = $this->options; 
  1676. $this->localize_data['defaults'] = $this->options_defaults; 
  1677.  
  1678. /** 
  1679. * Save pending string 
  1680. * filter 'redux/{opt_name}/localize/save_pending 
  1681. * @param string save_pending string 
  1682. */ 
  1683. $save_pending = apply_filters( "redux/{$this->args['opt_name']}/localize/save_pending", __( 'You have changes that are not saved. Would you like to save them now?', 'redux-framework' ) ); 
  1684.  
  1685. /** 
  1686. * Reset all string 
  1687. * filter 'redux/{opt_name}/localize/reset 
  1688. * @param string reset all string 
  1689. */ 
  1690. $reset_all = apply_filters( "redux/{$this->args['opt_name']}/localize/reset", __( 'Are you sure? Resetting will lose all custom values.', 'redux-framework' ) ); 
  1691.  
  1692. /** 
  1693. * Reset section string 
  1694. * filter 'redux/{opt_name}/localize/reset_section 
  1695. * @param string reset section string 
  1696. */ 
  1697. $reset_section = apply_filters( "redux/{$this->args['opt_name']}/localize/reset_section", __( 'Are you sure? Resetting will lose all custom values in this section.', 'redux-framework' ) ); 
  1698.  
  1699. /** 
  1700. * Preset confirm string 
  1701. * filter 'redux/{opt_name}/localize/preset 
  1702. * @param string preset confirm string 
  1703. */ 
  1704. $preset_confirm = apply_filters( "redux/{$this->args['opt_name']}/localize/preset", __( 'Your current options will be replaced with the values of this preset. Would you like to proceed?', 'redux-framework' ) ); 
  1705. global $pagenow; 
  1706. $this->localize_data['args'] = array( 
  1707. 'save_pending' => $save_pending,  
  1708. 'reset_confirm' => $reset_all,  
  1709. 'reset_section_confirm' => $reset_section,  
  1710. 'preset_confirm' => $preset_confirm,  
  1711. 'please_wait' => __( 'Please Wait', 'redux-framework' ),  
  1712. 'opt_name' => $this->args['opt_name'],  
  1713. 'slug' => $this->args['page_slug'],  
  1714. 'hints' => $this->args['hints'],  
  1715. 'disable_save_warn' => $this->args['disable_save_warn'],  
  1716. 'class' => $this->args['class'],  
  1717. 'menu_search' => $pagenow . '?page=' . $this->args['page_slug'] . "&tab=" 
  1718. ); 
  1719.  
  1720. // Construct the errors array. 
  1721. if ( isset( $this->transients['last_save_mode'] ) && ! empty( $this->transients['notices']['errors'] ) ) { 
  1722. $theTotal = 0; 
  1723. $theErrors = array(); 
  1724.  
  1725. foreach ( $this->transients['notices']['errors'] as $error ) { 
  1726. $theErrors[ $error['section_id'] ]['errors'][] = $error; 
  1727.  
  1728. if ( ! isset( $theErrors[ $error['section_id'] ]['total'] ) ) { 
  1729. $theErrors[ $error['section_id'] ]['total'] = 0; 
  1730.  
  1731. $theErrors[ $error['section_id'] ]['total'] ++; 
  1732. $theTotal ++; 
  1733.  
  1734. $this->localize_data['errors'] = array( 'total' => $theTotal, 'errors' => $theErrors ); 
  1735. unset( $this->transients['notices']['errors'] ); 
  1736.  
  1737. // Construct the warnings array. 
  1738. if ( isset( $this->transients['last_save_mode'] ) && ! empty( $this->transients['notices']['warnings'] ) ) { 
  1739. $theTotal = 0; 
  1740. $theWarnings = array(); 
  1741.  
  1742. foreach ( $this->transients['notices']['warnings'] as $warning ) { 
  1743. $theWarnings[ $warning['section_id'] ]['warnings'][] = $warning; 
  1744.  
  1745. if ( ! isset( $theWarnings[ $warning['section_id'] ]['total'] ) ) { 
  1746. $theWarnings[ $warning['section_id'] ]['total'] = 0; 
  1747.  
  1748. $theWarnings[ $warning['section_id'] ]['total'] ++; 
  1749. $theTotal ++; 
  1750.  
  1751. unset( $this->transients['notices']['warnings'] ); 
  1752. $this->localize_data['warnings'] = array( 'total' => $theTotal, 'warnings' => $theWarnings ); 
  1753.  
  1754. if ( empty( $this->transients['notices'] ) ) { 
  1755. unset( $this->transients['notices'] ); 
  1756.  
  1757. // Values used by the javascript 
  1758. wp_localize_script( 
  1759. 'redux-js',  
  1760. 'redux',  
  1761. $this->localize_data 
  1762. ); 
  1763.  
  1764. wp_enqueue_script( 'redux-js' ); // Enque the JS now 
  1765.  
  1766. wp_enqueue_script( 
  1767. 'webfontloader',  
  1768. 'https://ajax.googleapis.com/ajax/libs/webfont/1.5.0/webfont.js',  
  1769. array( 'jquery' ),  
  1770. '1.5.0',  
  1771. true 
  1772. ); 
  1773.  
  1774. /** 
  1775. * action 'redux-enqueue-{opt_name}' 
  1776. * @deprecated 
  1777. * @param object $this ReduxFramework 
  1778. */ 
  1779. do_action( "redux-enqueue-{$this->args['opt_name']}", $this ); // REMOVE 
  1780.  
  1781. /** 
  1782. * action 'redux/page/{opt_name}/enqueue' 
  1783. */ 
  1784. do_action( "redux/page/{$this->args['opt_name']}/enqueue" ); 
  1785. } // _enqueue() 
  1786.  
  1787. /** 
  1788. * Show page help 
  1789. * @since 1.0.0 
  1790. * @access public 
  1791. * @return void 
  1792. */ 
  1793. public function _load_page() { 
  1794.  
  1795. // Do admin head action for this page 
  1796. add_action( 'admin_head', array( &$this, 'admin_head' ) ); 
  1797.  
  1798. // Do admin footer text hook 
  1799. add_filter( 'admin_footer_text', array( &$this, 'admin_footer_text' ) ); 
  1800.  
  1801. $screen = get_current_screen(); 
  1802.  
  1803. if ( is_array( $this->args['help_tabs'] ) ) { 
  1804. foreach ( $this->args['help_tabs'] as $tab ) { 
  1805. $screen->add_help_tab( $tab ); 
  1806.  
  1807. // If hint argument is set, display hint tab 
  1808. if ( true == $this->show_hints ) { 
  1809. global $current_user; 
  1810.  
  1811. // Users enable/disable hint choice 
  1812. $hint_status = get_user_meta( $current_user->ID, 'ignore_hints' ) ? get_user_meta( $current_user->ID, 'ignore_hints', true ) : 'true'; 
  1813.  
  1814. // current page parameters 
  1815. $curPage = $_GET['page']; 
  1816.  
  1817. $curTab = '0'; 
  1818. if ( isset( $_GET['tab'] ) ) { 
  1819. $curTab = $_GET['tab']; 
  1820.  
  1821. // Default url values for enabling hints. 
  1822. $dismiss = 'true'; 
  1823. $s = __( 'Enable', 'redux-framework' ); 
  1824.  
  1825. // Values for disabling hints. 
  1826. if ( 'true' == $hint_status ) { 
  1827. $dismiss = 'false'; 
  1828. $s = __( 'Disable', 'redux-framework' ); 
  1829.  
  1830. // Make URL 
  1831. $url = '<a class="redux_hint_status" href="?dismiss=' . $dismiss . '&id=hints&page=' . $curPage . '&tab=' . $curTab . '">' . $s . ' hints</a>'; 
  1832.  
  1833. $event = __( 'moving the mouse over', 'redux-framework' ); 
  1834. if ( 'click' == $this->args['hints']['tip_effect']['show']['event'] ) { 
  1835. $event = __( 'clicking', 'redux-framework' ); 
  1836.  
  1837. // Construct message 
  1838. $msg = sprintf( __( 'Hints are tooltips that popup when %d the hint icon, offering addition information about the field in which they appear. They can be %d d by using the link below.', 'redux-framework' ), $event, strtolower( $s ) ) . '<br/><br/>' . $url; 
  1839.  
  1840. // Construct hint tab 
  1841. $tab = array( 
  1842. 'id' => 'redux-hint-tab',  
  1843. 'title' => __( 'Hints', 'redux-framework' ),  
  1844. 'content' => '<p>' . $msg . '</p>' 
  1845. ); 
  1846.  
  1847. $screen->add_help_tab( $tab ); 
  1848.  
  1849. // Sidebar text 
  1850. if ( $this->args['help_sidebar'] != '' ) { 
  1851.  
  1852. // Specify users text from arguments 
  1853. $screen->set_help_sidebar( $this->args['help_sidebar'] ); 
  1854. } else { 
  1855.  
  1856. // If sidebar text is empty and hints are active, display text 
  1857. // about hints. 
  1858. if ( true == $this->show_hints ) { 
  1859. $screen->set_help_sidebar( '<p><strong>Redux Framework</strong><br/><br/>Hint Tooltip Preferences</p>' ); 
  1860.  
  1861. /** 
  1862. * action 'redux-load-page-{opt_name}' 
  1863. * @deprecated 
  1864. * @param object $screen WP_Screen 
  1865. */ 
  1866. do_action( "redux-load-page-{$this->args['opt_name']}", $screen ); // REMOVE 
  1867.  
  1868. /** 
  1869. * action 'redux/page/{opt_name}/load' 
  1870. * @param object $screen WP_Screen 
  1871. */ 
  1872. do_action( "redux/page/{$this->args['opt_name']}/load", $screen ); 
  1873.  
  1874. } // _load_page() 
  1875.  
  1876. /** 
  1877. * Do action redux-admin-head for options page 
  1878. * @since 1.0.0 
  1879. * @access public 
  1880. * @return void 
  1881. */ 
  1882. public function admin_head() { 
  1883. /** 
  1884. * action 'redux-admin-head-{opt_name}' 
  1885. * @deprecated 
  1886. * @param object $this ReduxFramework 
  1887. */ 
  1888. do_action( "redux-admin-head-{$this->args['opt_name']}", $this ); // REMOVE 
  1889.  
  1890. /** 
  1891. * action 'redux/page/{opt_name}/header' 
  1892. * @param object $this ReduxFramework 
  1893. */ 
  1894. do_action( "redux/page/{$this->args['opt_name']}/header", $this ); 
  1895. } // admin_head() 
  1896.  
  1897. /** 
  1898. * Return footer text 
  1899. * @since 2.0.0 
  1900. * @access public 
  1901. * @return string $this->args['footer_credit'] 
  1902. */ 
  1903. public function admin_footer_text() { 
  1904. return $this->args['footer_credit']; 
  1905. } // admin_footer_text() 
  1906.  
  1907. /** 
  1908. * Return default output string for use in panel 
  1909. * @since 3.1.5 
  1910. * @access public 
  1911. * @return string default_output 
  1912. */ 
  1913. private function get_default_output_string( $field ) { 
  1914. $default_output = ""; 
  1915.  
  1916. if ( ! isset( $field['default'] ) ) { 
  1917. $field['default'] = ""; 
  1918.  
  1919. if ( ! is_array( $field['default'] ) ) { 
  1920. if ( ! empty( $field['options'][ $field['default'] ] ) ) { 
  1921. if ( ! empty( $field['options'][ $field['default'] ]['alt'] ) ) { 
  1922. $default_output .= $field['options'][ $field['default'] ]['alt'] . ', '; 
  1923. } else { 
  1924. // TODO: This serialize fix may not be the best solution. Look into it. PHP 5.4 error without serialize 
  1925. if ( ! is_array( $field['options'][ $field['default'] ] ) ) { 
  1926. $default_output .= $field['options'][ $field['default'] ] . ", "; 
  1927. } else { 
  1928. $default_output .= serialize( $field['options'][ $field['default'] ] ) . ", "; 
  1929. } else if ( ! empty( $field['options'][ $field['default'] ] ) ) { 
  1930. $default_output .= $field['options'][ $field['default'] ] . ", "; 
  1931. } else if ( ! empty( $field['default'] ) ) { 
  1932. if ( $field['type'] == 'switch' && isset( $field['on'] ) && isset( $field['off'] ) ) { 
  1933. $default_output .= ( $field['default'] == 1 ? $field['on'] : $field['off'] ) . ', '; 
  1934. } else { 
  1935. $default_output .= $field['default'] . ', '; 
  1936. } else { 
  1937. foreach ( $field['default'] as $defaultk => $defaultv ) { 
  1938. if ( ! empty( $field['options'][ $defaultv ]['alt'] ) ) { 
  1939. $default_output .= $field['options'][ $defaultv ]['alt'] . ', '; 
  1940. } else if ( ! empty( $field['options'][ $defaultv ] ) ) { 
  1941. $default_output .= $field['options'][ $defaultv ] . ", "; 
  1942. } else if ( ! empty( $field['options'][ $defaultk ] ) ) { 
  1943. $default_output .= $field['options'][ $defaultk ] . ", "; 
  1944. } else if ( ! empty( $defaultv ) ) { 
  1945. $default_output .= $defaultv . ', '; 
  1946.  
  1947. if ( ! empty( $default_output ) ) { 
  1948. $default_output = __( 'Default', 'redux-framework' ) . ": " . substr( $default_output, 0, - 2 ); 
  1949.  
  1950. if ( ! empty( $default_output ) ) { 
  1951. $default_output = '<span class="showDefaults">' . $default_output . '</span><br class="default_br" />'; 
  1952.  
  1953. return $default_output; 
  1954. } // get_default_output_string() 
  1955.  
  1956. public function get_header_html( $field ) { 
  1957. global $current_user; 
  1958.  
  1959. // Set to empty string to avoid wanrings. 
  1960. $hint = ''; 
  1961. $th = ""; 
  1962.  
  1963. if ( isset( $field['title'] ) && isset( $field['type'] ) && $field['type'] !== "info" && $field['type'] !== "section" ) { 
  1964. $default_mark = ( ! empty( $field['default'] ) && isset( $this->options[ $field['id'] ] ) && $this->options[ $field['id'] ] == $field['default'] && ! empty( $this->args['default_mark'] ) && isset( $field['default'] ) ) ? $this->args['default_mark'] : ''; 
  1965.  
  1966. // If a hint is specified in the field, process it. 
  1967. if ( isset( $field['hint'] ) && ! '' == $field['hint'] ) { 
  1968.  
  1969. // Set show_hints flag to true, so helptab will be displayed. 
  1970. $this->show_hints = true; 
  1971.  
  1972. // Get user pref for displaying hints. 
  1973. $metaVal = get_user_meta( $current_user->ID, 'ignore_hints', true ); 
  1974. if ( 'true' == $metaVal || empty( $metaVal ) ) { 
  1975.  
  1976. // Set hand cursor for clickable hints 
  1977. $pointer = ''; 
  1978. if ( isset( $this->args['hints']['tip_effect']['show']['event'] ) && 'click' == $this->args['hints']['tip_effect']['show']['event'] ) { 
  1979. $pointer = 'pointer'; 
  1980.  
  1981. $size = '16px'; 
  1982. if ( 'large' == $this->args['hints']['icon_size'] ) { 
  1983. $size = '18px'; 
  1984.  
  1985. // In case docs are ignored. 
  1986. $titleParam = isset( $field['hint']['title'] ) ? $field['hint']['title'] : ''; 
  1987. $contentParam = isset( $field['hint']['content'] ) ? $field['hint']['content'] : ''; 
  1988.  
  1989. $hint_color = isset( $this->args['hints']['icon_color'] ) ? $this->args['hints']['icon_color'] : '#d3d3d3'; 
  1990.  
  1991. // Set hint html with appropriate position css 
  1992. $hint = '<div class="redux-hint-qtip" style="float:' . $this->args['hints']['icon_position'] . '; font-size: ' . $size . '; color:' . $hint_color . '; cursor: ' . $pointer . ';" qtip-title="' . $titleParam . '" qtip-content="' . $contentParam . '"><i class="el-' . $this->args['hints']['icon'] . '"></i>  </div>'; 
  1993.  
  1994. if ( ! empty( $field['title'] ) ) { 
  1995. if ( 'left' == $this->args['hints']['icon_position'] ) { 
  1996. $th = $hint . $field['title'] . $default_mark . ""; 
  1997. } else { 
  1998. $th = $field['title'] . $default_mark . "" . $hint; 
  1999.  
  2000. if ( isset( $field['subtitle'] ) ) { 
  2001. $th .= '<span class="description">' . $field['subtitle'] . '</span>'; 
  2002.  
  2003. if ( ! empty( $th ) ) { 
  2004. $th = '<div class="redux_field_th">' . $th . '</div>'; 
  2005.  
  2006. if ( $this->args['default_show'] === true && isset( $field['default'] ) && isset( $this->options[ $field['id'] ] ) && $this->options[ $field['id'] ] != $field['default'] && $field['type'] !== "info" && $field['type'] !== "group" && $field['type'] !== "section" && $field['type'] !== "editor" && $field['type'] !== "ace_editor" ) { 
  2007. $th .= $this->get_default_output_string( $field ); 
  2008.  
  2009. return $th; 
  2010.  
  2011.  
  2012. /** 
  2013. * Register Option for use 
  2014. * @since 1.0.0 
  2015. * @access public 
  2016. * @return void 
  2017. */ 
  2018. public function _register_settings() { 
  2019.  
  2020. // TODO - REMOVE 
  2021. // Not used by new sample-config, but in here for legacy builds 
  2022. // This is bad and can break things. Hehe. 
  2023. if ( ! function_exists( 'wp_get_current_user' ) ) { 
  2024. include( ABSPATH . "wp-includes/pluggable.php" ); 
  2025.  
  2026. register_setting( $this->args['opt_name'] . '_group', $this->args['opt_name'], array( 
  2027. $this,  
  2028. '_validate_options' 
  2029. ) ); 
  2030.  
  2031. if ( is_null( $this->sections ) ) { 
  2032. return; 
  2033.  
  2034. $this->options_defaults = $this->_default_values(); 
  2035.  
  2036. $runUpdate = false; 
  2037.  
  2038. foreach ( $this->sections as $k => $section ) { 
  2039. if ( isset( $section['type'] ) && $section['type'] == 'divide' ) { 
  2040. continue; 
  2041.  
  2042. $display = true; 
  2043.  
  2044. if ( isset( $_GET['page'] ) && $_GET['page'] == $this->args['page_slug'] ) { 
  2045. if ( isset( $section['panel'] ) && $section['panel'] == false ) { 
  2046. $display = false; 
  2047.  
  2048.  
  2049. // DOVY! Replace $k with $section['id'] when ready 
  2050. /** 
  2051. * filter 'redux-section-{index}-modifier-{opt_name}' 
  2052. * @param array $section section configuration 
  2053. */ 
  2054. $section = apply_filters( "redux-section-{$k}-modifier-{$this->args['opt_name']}", $section ); 
  2055.  
  2056. /** 
  2057. * filter 'redux/options/{opt_name}/section/{section.id}' 
  2058. * @param array $section section configuration 
  2059. */ 
  2060. if ( isset( $section['id'] ) ) { 
  2061. $section = apply_filters( "redux/options/{$this->args['opt_name']}/section/{$section['id']}", $section ); 
  2062.  
  2063. if ( ! isset( $section['title'] ) ) { 
  2064. $section['title'] = ""; 
  2065.  
  2066. $heading = isset( $section['heading'] ) ? $section['heading'] : $section['title']; 
  2067.  
  2068. if ( isset( $section['permissions'] ) ) { 
  2069. if ( ! current_user_can( $section['permissions'] ) ) { 
  2070. $this->hidden_perm_sections[] = $section['title']; 
  2071.  
  2072. foreach ( $section['fields'] as $num => $field_data ) { 
  2073. $field_type = $field_data['type']; 
  2074.  
  2075. if ( $field_type != 'section' || $field_type != 'divide' || $field_type != 'info' || $field_type != 'raw' ) { 
  2076. $field_id = $field_data['id']; 
  2077. $default = isset( $this->options_defaults[ $field_id ] ) ? $this->options_defaults[ $field_id ] : ''; 
  2078. $data = isset( $this->options[ $field_id ] ) ? $this->options[ $field_id ] : $default; 
  2079.  
  2080. $this->hidden_perm_fields[ $field_id ] = $data; 
  2081.  
  2082. continue; 
  2083.  
  2084. if ( ! $display ) { 
  2085. $this->no_panel_section[ $k ] = $section; 
  2086. } else { 
  2087. add_settings_section( $this->args['opt_name'] . $k . '_section', $heading, array( 
  2088. &$this,  
  2089. '_section_desc' 
  2090. ), $this->args['opt_name'] . $k . '_section_group' ); 
  2091.  
  2092. $sectionIndent = false; 
  2093. if ( isset( $section['fields'] ) ) { 
  2094. foreach ( $section['fields'] as $fieldk => $field ) { 
  2095. if ( ! isset( $field['type'] ) ) { 
  2096. continue; // You need a type! 
  2097.  
  2098. /** 
  2099. * filter 'redux/options/{opt_name}/field/{field.id}' 
  2100. * @param array $field field config 
  2101. */ 
  2102. $field = apply_filters( "redux/options/{$this->args['opt_name']}/field/{$field['id']}/register", $field ); 
  2103.  
  2104. $display = true; 
  2105.  
  2106. if ( isset( $_GET['page'] ) && $_GET['page'] == $this->args['page_slug'] ) { 
  2107. if ( isset( $field['panel'] ) && $field['panel'] == false ) { 
  2108. $display = false; 
  2109. if ( isset( $field['customizer_only'] ) && $field['customizer_only'] == true ) { 
  2110. //$display = false; 
  2111.  
  2112.  
  2113. // TODO AFTER GROUP WORKS - Remove IF statement 
  2114. // if ( $field['type'] == "group" && isset( $_GET['page'] ) && $_GET['page'] == $this->args['page_slug'] ) { 
  2115. // if ( $this->args['dev_mode'] ) { 
  2116. // $this->admin_notices[] = array( 
  2117. // 'type' => 'error',  
  2118. // 'msg' => 'The <strong>group field</strong> has been <strong>removed</strong> while we retool it for improved performance.',  
  2119. // 'id' => 'group_err',  
  2120. // 'dismiss' => true,  
  2121. // ); 
  2122. // } 
  2123. // continue; // Disabled for now 
  2124. // } 
  2125.  
  2126.  
  2127. if ( isset( $field['permissions'] ) ) { 
  2128.  
  2129. if ( ! current_user_can( $field['permissions'] ) ) { 
  2130. $data = isset( $this->options[ $field['id'] ] ) ? $this->options[ $field['id'] ] : $this->options_defaults[ $field['id'] ]; 
  2131.  
  2132. $this->hidden_perm_fields[ $field['id'] ] = $data; 
  2133.  
  2134. continue; 
  2135.  
  2136. if ( ! isset( $field['id'] ) ) { 
  2137. echo '<br /><h3>No field ID is set.</h3><pre>'; 
  2138. print_r( $field ); 
  2139. echo "</pre><br />"; 
  2140. continue; 
  2141.  
  2142. if ( isset( $field['type'] ) && $field['type'] == "section" ) { 
  2143. if ( isset( $field['indent'] ) && $field['indent'] == true ) { 
  2144. $sectionIndent = true; 
  2145. } else { 
  2146. $sectionIndent = false; 
  2147.  
  2148. if ( isset( $field['type'] ) && $field['type'] == "info" && $sectionIndent ) { 
  2149. $field['indent'] = $sectionIndent; 
  2150.  
  2151. $th = $this->get_header_html( $field ); 
  2152.  
  2153. $field['name'] = $this->args['opt_name'] . '[' . $field['id'] . ']'; 
  2154.  
  2155. // Set the default value if present 
  2156. $this->options_defaults[ $field['id'] ] = isset( $this->options_defaults[ $field['id'] ] ) ? $this->options_defaults[ $field['id'] ] : ''; 
  2157.  
  2158. // Set the defaults to the value if not present 
  2159. $doUpdate = false; 
  2160.  
  2161. // Check fields for values in the default parameter 
  2162. if ( ! isset( $this->options[ $field['id'] ] ) && isset( $field['default'] ) ) { 
  2163. $this->options_defaults[ $field['id'] ] = $this->options[ $field['id'] ] = $field['default']; 
  2164. $doUpdate = true; 
  2165.  
  2166. // Check fields that hae no default value, but an options value with settings to 
  2167. // be saved by default 
  2168. } elseif ( ! isset( $this->options[ $field['id'] ] ) && isset( $field['options'] ) ) { 
  2169.  
  2170. // If sorter field, check for options as save them as defaults 
  2171. if ( $field['type'] == 'sorter' || $field['type'] == 'sortable' ) { 
  2172. $this->options_defaults[ $field['id'] ] = $this->options[ $field['id'] ] = $field['options']; 
  2173. $doUpdate = true; 
  2174.  
  2175. // CORRECT URLS if media URLs are wrong, but attachment IDs are present. 
  2176. if ( $field['type'] == "media" ) { 
  2177. if ( isset( $this->options[ $field['id'] ]['id'] ) && isset( $this->options[ $field['id'] ]['url'] ) && ! empty( $this->options[ $field['id'] ]['url'] ) && strpos( $this->options[ $field['id'] ]['url'], str_replace( 'http://', '', WP_CONTENT_URL ) ) === false ) { 
  2178. $data = wp_get_attachment_url( $this->options[ $field['id'] ]['id'] ); 
  2179.  
  2180. if ( isset( $data ) && ! empty( $data ) ) { 
  2181. $this->options[ $field['id'] ]['url'] = $data; 
  2182. $data = wp_get_attachment_image_src( $this->options[ $field['id'] ]['id'], array( 
  2183. 150,  
  2184. 150 
  2185. ) ); 
  2186. $this->options[ $field['id'] ]['thumbnail'] = $data[0]; 
  2187. $doUpdate = true; 
  2188.  
  2189. if ( $field['type'] == "background" ) { 
  2190. if ( isset( $this->options[ $field['id'] ]['media']['id'] ) && isset( $this->options[ $field['id'] ]['background-image'] ) && ! empty( $this->options[ $field['id'] ]['background-image'] ) && strpos( $this->options[ $field['id'] ]['background-image'], str_replace( 'http://', '', WP_CONTENT_URL ) ) === false ) { 
  2191. $data = wp_get_attachment_url( $this->options[ $field['id'] ]['media']['id'] ); 
  2192.  
  2193. if ( isset( $data ) && ! empty( $data ) ) { 
  2194. $this->options[ $field['id'] ]['background-image'] = $data; 
  2195. $data = wp_get_attachment_image_src( $this->options[ $field['id'] ]['media']['id'], array( 
  2196. 150,  
  2197. 150 
  2198. ) ); 
  2199. $this->options[ $field['id'] ]['media']['thumbnail'] = $data[0]; 
  2200. $doUpdate = true; 
  2201.  
  2202. if ( $field['type'] == "slides" ) { 
  2203. if ( isset( $this->options[ $field['id'] ][0]['attachment_id'] ) && isset( $this->options[ $field['id'] ][0]['image'] ) && ! empty( $this->options[ $field['id'] ][0]['image'] ) && strpos( $this->options[ $field['id'] ][0]['image'], str_replace( 'http://', '', WP_CONTENT_URL ) ) === false ) { 
  2204. foreach ( $this->options[ $field['id'] ] as $k => $v ) { 
  2205. $data = wp_get_attachment_url( $v['attachment_id'] ); 
  2206.  
  2207. if ( isset( $data ) && ! empty( $data ) ) { 
  2208. $this->options[ $field['id'] ][ $k ]['image'] = $data; 
  2209. $data = wp_get_attachment_image_src( $v['attachment_id'], array( 
  2210. 150,  
  2211. 150 
  2212. ) ); 
  2213. $this->options[ $field['id'] ][ $k ]['thumb'] = $data[0]; 
  2214. $doUpdate = true; 
  2215. // END -> CORRECT URLS if media URLs are wrong, but attachment IDs are present. 
  2216.  
  2217. if ( true == $doUpdate && ! isset( $this->never_save_to_db ) ) { 
  2218. if ( $this->args['save_defaults'] ) { // Only save that to the DB if allowed to 
  2219. $runUpdate = true; 
  2220. // elseif($this->saved != '' && $this->saved != false) { 
  2221. // $runUpdate = true; 
  2222. //} 
  2223.  
  2224. if ( ! isset( $field['class'] ) ) { // No errors please 
  2225. $field['class'] = ""; 
  2226. $id = $field['id']; 
  2227.  
  2228. /** 
  2229. * filter 'redux-field-{field.id}modifier-{opt_name}' 
  2230. * @deprecated 
  2231. * @param array $field field config 
  2232. */ 
  2233. $field = apply_filters( "redux-field-{$field['id']}modifier-{$this->args['opt_name']}", $field ); // REMOVE LATER 
  2234.  
  2235. /** 
  2236. * filter 'redux/options/{opt_name}/field/{field.id}' 
  2237. * @param array $field field config 
  2238. */ 
  2239. $field = apply_filters( "redux/options/{$this->args['opt_name']}/field/{$field['id']}", $field ); 
  2240.  
  2241. if ( empty( $field ) || ! $field || $field == false ) { 
  2242. unset( $this->sections[ $k ]['fields'][ $fieldk ] ); 
  2243. continue; 
  2244.  
  2245. if ( ! empty( $this->folds[ $field['id'] ]['parent'] ) ) { // This has some fold items, hide it by default 
  2246. $field['class'] .= " fold"; 
  2247.  
  2248. if ( ! empty( $this->folds[ $field['id'] ]['children'] ) ) { // Sets the values you shoe fold children on 
  2249. $field['class'] .= " foldParent"; 
  2250.  
  2251. if ( ! empty( $field['compiler'] ) ) { 
  2252. $field['class'] .= " compiler"; 
  2253. $this->compiler_fields[ $field['id'] ] = 1; 
  2254.  
  2255. if ( isset( $field['unit'] ) && ! isset( $field['units'] ) ) { 
  2256. $field['units'] = $field['unit']; 
  2257. unset( $field['unit'] ); 
  2258.  
  2259. $this->sections[ $k ]['fields'][ $fieldk ] = $field; 
  2260.  
  2261. if ( isset( $this->args['display_source'] ) ) { 
  2262. $th .= '<div id="' . $field['id'] . '-settings" style="display:none;"><pre>' . var_export( $this->sections[ $k ]['fields'][ $fieldk ], true ) . '</pre></div>'; 
  2263. $th .= '<br /><a href="#TB_inline?width=600&height=800&inlineId=' . $field['id'] . '-settings" class="thickbox"><small>View Source</small></a>'; 
  2264.  
  2265. /** 
  2266. * action 'redux/options/{opt_name}/field/field.type}/register' 
  2267. */ 
  2268. do_action( "redux/options/{$this->args['opt_name']}/field/{$field['type']}/register", $field ); 
  2269.  
  2270. $this->check_dependencies( $field ); 
  2271.  
  2272. if ( ! $display || isset( $this->no_panel_section[ $k ] ) ) { 
  2273. $this->no_panel[] = $field['id']; 
  2274. } else { 
  2275. if (isset($field['hidden']) && $field['hidden']) { 
  2276. $field['label_for'] = 'redux_hide_field'; 
  2277.  
  2278. add_settings_field( 
  2279. "{$fieldk}_field",  
  2280. $th,  
  2281. array( &$this, '_field_input' ),  
  2282. "{$this->args['opt_name']}{$k}_section_group",  
  2283. "{$this->args['opt_name']}{$k}_section",  
  2284. $field 
  2285. ); // checkbox 
  2286.  
  2287. /** 
  2288. * action 'redux-register-settings-{opt_name}' 
  2289. * @deprecated 
  2290. */ 
  2291. do_action( "redux-register-settings-{$this->args['opt_name']}" ); // REMOVE 
  2292.  
  2293. /** 
  2294. * action 'redux/options/{opt_name}/register' 
  2295. * @param array option sections 
  2296. */ 
  2297. do_action( "redux/options/{$this->args['opt_name']}/register", $this->sections ); 
  2298.  
  2299. if ( $runUpdate && ! isset( $this->never_save_to_db ) ) { // Always update the DB with new fields 
  2300. $this->set_options( $this->options ); 
  2301.  
  2302. if ( isset( $this->transients['run_compiler'] ) && $this->transients['run_compiler'] ) { 
  2303.  
  2304. $this->no_output = true; 
  2305. $this->_enqueue_output(); 
  2306.  
  2307.  
  2308. /** 
  2309. * action 'redux-compiler-{opt_name}' 
  2310. * @deprecated 
  2311. * @param array options 
  2312. * @param string CSS that get sent to the compiler hook 
  2313. */ 
  2314. do_action( "redux-compiler-{$this->args['opt_name']}", $this->options, $this->compilerCSS, $this->transients['changed_values'] ); // REMOVE 
  2315.  
  2316. /** 
  2317. * action 'redux/options/{opt_name}/compiler' 
  2318. * @param array options 
  2319. * @param string CSS that get sent to the compiler hook 
  2320. */ 
  2321. do_action( "redux/options/{$this->args['opt_name']}/compiler", $this->options, $this->compilerCSS, $this->transients['changed_values'] ); 
  2322.  
  2323. /** 
  2324. * action 'redux/options/{opt_name}/compiler/advanced' 
  2325. * @param array options 
  2326. * @param string CSS that get sent to the compiler hook, which sends the full Redux object 
  2327. */ 
  2328. do_action( "redux/options/{$this->args['opt_name']}/compiler/advanced", $this ); 
  2329.  
  2330. unset( $this->transients['run_compiler'] ); 
  2331. $this->set_transients(); 
  2332. } // _register_settings() 
  2333.  
  2334. /** 
  2335. * Register Extensions for use 
  2336. * @since 3.0.0 
  2337. * @access public 
  2338. * @return void 
  2339. */ 
  2340. private function _register_extensions() { 
  2341. $path = dirname( __FILE__ ) . '/extensions/'; 
  2342. $folders = scandir( $path, 1 ); 
  2343.  
  2344. /** 
  2345. * action 'redux/extensions/{opt_name}/before' 
  2346. * @param object $this ReduxFramework 
  2347. */ 
  2348. do_action( "redux/extensions/{$this->args['opt_name']}/before", $this ); 
  2349.  
  2350. foreach ( $folders as $folder ) { 
  2351. if ( $folder === '.' || $folder === '..' || ! is_dir( $path . $folder ) || substr( $folder, 0, 1 ) === '.' || substr( $folder, 0, 1 ) === '@' || substr( $folder, 0, 4 ) === '_vti' ) { 
  2352. continue; 
  2353.  
  2354. $extension_class = 'ReduxFramework_Extension_' . $folder; 
  2355.  
  2356. /** 
  2357. * filter 'redux-extensionclass-load' 
  2358. * @deprecated 
  2359. * @param string extension class file path 
  2360. * @param string $extension_class extension class name 
  2361. */ 
  2362. $class_file = apply_filters( "redux-extensionclass-load", "$path/$folder/extension_{$folder}.php", $extension_class ); // REMOVE LATER 
  2363.  
  2364. /** 
  2365. * filter 'redux/extension/{opt_name}/{folder}' 
  2366. * @param string extension class file path 
  2367. * @param string $extension_class extension class name 
  2368. */ 
  2369. $class_file = apply_filters( "redux/extension/{$this->args['opt_name']}/$folder", "$path/$folder/extension_{$folder}.php", $class_file ); 
  2370.  
  2371. if ( $class_file ) { 
  2372. if ( file_exists( $class_file ) ) { 
  2373. require_once( $class_file ); 
  2374.  
  2375. $this->extensions[ $folder ] = new $extension_class( $this ); 
  2376.  
  2377.  
  2378. /** 
  2379. * action 'redux-register-extensions-{opt_name}' 
  2380. * @deprecated 
  2381. * @param object $this ReduxFramework 
  2382. */ 
  2383. do_action( "redux-register-extensions-{$this->args['opt_name']}", $this ); // REMOVE 
  2384.  
  2385. /** 
  2386. * action 'redux/extensions/{opt_name}' 
  2387. * @param object $this ReduxFramework 
  2388. */ 
  2389. do_action( "redux/extensions/{$this->args['opt_name']}", $this ); 
  2390.  
  2391. private function get_transients() { 
  2392. if ( ! isset( $this->transients ) ) { 
  2393. $this->transients = get_option( $this->args['opt_name'] . '-transients', array() ); 
  2394. $this->transients_check = $this->transients; 
  2395.  
  2396. private function set_transients() { 
  2397. if ( ! isset( $this->transients ) || ! isset( $this->transients_check ) || $this->transients != $this->transients_check ) { 
  2398. update_option( $this->args['opt_name'] . '-transients', $this->transients ); 
  2399. $this->transients_check = $this->transients; 
  2400.  
  2401. /** 
  2402. * Validate the Options options before insertion 
  2403. * @since 3.0.0 
  2404. * @access public 
  2405. * @param array $plugin_options The options array 
  2406. * @return array|mixed|string|void 
  2407. */ 
  2408. public function _validate_options( $plugin_options ) { 
  2409.  
  2410. // Save the values not in the panel 
  2411. if ( isset( $plugin_options['redux-no_panel'] ) ) { 
  2412. $keys = explode( '|', $plugin_options['redux-no_panel'] ); 
  2413. foreach ( $keys as $key ) { 
  2414. $plugin_options[ $key ] = $this->options[ $key ]; 
  2415. if ( isset( $plugin_options['redux-no_panel'] ) ) { 
  2416. unset( $plugin_options['redux-no_panel'] ); 
  2417.  
  2418. if ( ! empty( $this->hidden_perm_fields ) && is_array( $this->hidden_perm_fields ) ) { 
  2419. foreach ( $this->hidden_perm_fields as $id => $data ) { 
  2420. $plugin_options[ $id ] = $data; 
  2421.  
  2422. if ( $plugin_options == $this->options ) { 
  2423. return $plugin_options; 
  2424.  
  2425. $time = time(); 
  2426.  
  2427. // Sets last saved time 
  2428. $this->transients['last_save'] = $time; 
  2429.  
  2430. // Import 
  2431. if ( ! empty( $plugin_options['import'] ) ) { 
  2432. $this->transients['last_save_mode'] = "import"; // Last save mode 
  2433. $this->transients['last_compiler'] = $time; 
  2434. $this->transients['last_import'] = $time; 
  2435. $this->transients['run_compiler'] = 1; 
  2436.  
  2437. if ( $plugin_options['import_code'] != '' ) { 
  2438. $import = $plugin_options['import_code']; 
  2439. } elseif ( $plugin_options['import_link'] != '' ) { 
  2440. $import = wp_remote_retrieve_body( wp_remote_get( $plugin_options['import_link'] ) ); 
  2441.  
  2442. if ( ! empty( $import ) ) { 
  2443. $imported_options = json_decode( $import, true ); 
  2444.  
  2445. if ( ! empty( $imported_options ) && is_array( $imported_options ) && isset( $imported_options['redux-backup'] ) && $imported_options['redux-backup'] == '1' ) { 
  2446.  
  2447. $this->transients['changed_values'] = array(); 
  2448. foreach ( $plugin_options as $key => $value ) { 
  2449. if ( isset( $imported_options[ $key ] ) && $imported_options[ $key ] != $value ) { 
  2450. $this->transients['changed_values'][ $key ] = $value; 
  2451. $plugin_options[ $key ] = $value; 
  2452.  
  2453. /** 
  2454. * action 'redux/options/{opt_name}/import' 
  2455. * @param &array [&$plugin_options, redux_options] 
  2456. */ 
  2457. do_action_ref_array( "redux/options/{$this->args['opt_name']}/import", array( 
  2458. &$plugin_options,  
  2459. $imported_options,  
  2460. $this->transients['changed_values'] 
  2461. ) ); 
  2462.  
  2463. // Remove the import/export tab cookie. 
  2464. if ( $_COOKIE['redux_current_tab'] == 'import_export_default' ) { 
  2465. setcookie( 'redux_current_tab', '', 1, '/' ); 
  2466. $_COOKIE['redux_current_tab'] = 1; 
  2467.  
  2468. setcookie( 'redux_current_tab', '', 1, '/', $time + 1000, "/" ); 
  2469. $_COOKIE['redux_current_tab'] = 1; 
  2470.  
  2471. unset( $plugin_options['defaults'], $plugin_options['compiler'], $plugin_options['import'], $plugin_options['import_code'] ); 
  2472. if ( $this->args['database'] == 'transient' || $this->args['database'] == 'theme_mods' || $this->args['database'] == 'theme_mods_expanded' || $this->args['database'] == 'network' ) { 
  2473. $this->set_options( $plugin_options ); 
  2474.  
  2475. return; 
  2476.  
  2477. $plugin_options = wp_parse_args( $imported_options, $plugin_options ); 
  2478. $this->set_transients(); // Update the transients 
  2479.  
  2480. return $plugin_options; 
  2481.  
  2482. // Reset all to defaults 
  2483. if ( ! empty( $plugin_options['defaults'] ) ) { 
  2484. if ( empty( $this->options_defaults ) ) { 
  2485. $this->options_defaults = $this->_default_values(); 
  2486.  
  2487. // Section reset 
  2488. //setcookie('redux-compiler-' . $this->args['opt_name'], 1, time() + 3000, '/'); 
  2489. $plugin_options = $this->options_defaults; 
  2490.  
  2491. $this->transients['changed_values'] = array(); 
  2492.  
  2493. if ( empty( $this->options ) ) { 
  2494. $this->options = $this->options_defaults; 
  2495.  
  2496. foreach ( $this->options as $key => $value ) { 
  2497. if ( isset( $plugin_options[ $key ] ) && $value != $plugin_options[ $key ] ) { 
  2498. $this->transients['changed_values'][ $key ] = $value; 
  2499.  
  2500. $this->transients['run_compiler'] = 1; 
  2501. $this->transients['last_save_mode'] = "defaults"; // Last save mode 
  2502.  
  2503. //setcookie('redux-compiler-' . $this->args['opt_name'], 1, time() + 1000, "/"); 
  2504. //setcookie("redux-saved-{$this->args['opt_name']}", 'defaults', time() + 1000, "/"); 
  2505.  
  2506. $this->set_transients(); // Update the transients 
  2507.  
  2508. return $plugin_options; 
  2509.  
  2510. // Section reset to defaults 
  2511. if ( ! empty( $plugin_options['defaults-section'] ) ) { 
  2512. if ( isset( $plugin_options['redux-section'] ) && isset( $this->sections[ $plugin_options['redux-section'] ]['fields'] ) ) { 
  2513. foreach ( $this->sections[ $plugin_options['redux-section'] ]['fields'] as $field ) { 
  2514. if ( isset( $this->options_defaults[ $field['id'] ] ) ) { 
  2515. $plugin_options[ $field['id'] ] = $this->options_defaults[ $field['id'] ]; 
  2516. } else { 
  2517. $plugin_options[ $field['id'] ] = ""; 
  2518.  
  2519. if ( isset( $field['compiler'] ) ) { 
  2520. $compiler = true; 
  2521.  
  2522. $this->transients['changed_values'] = array(); 
  2523. foreach ( $this->options as $key => $value ) { 
  2524. if ( isset( $plugin_options[ $key ] ) && $value != $plugin_options[ $key ] ) { 
  2525. $this->transients['changed_values'][ $key ] = $value; 
  2526.  
  2527. if ( isset( $compiler ) ) { 
  2528. //$this->run_compiler = true; 
  2529. //setcookie('redux-compiler-' . $this->args['opt_name'], 1, time()+1000, '/'); 
  2530. //$plugin_options['REDUX_COMPILER'] = time(); 
  2531. $this->transients['last_compiler'] = $time; 
  2532. $this->transients['run_compiler'] = 1; 
  2533.  
  2534. $this->transients['last_save_mode'] = "defaults_section"; // Last save mode 
  2535.  
  2536. //setcookie("redux-saved-{$this->args['opt_name']}", 'defaults_section', time() + 1000, "/"); 
  2537. unset( $plugin_options['defaults'], $plugin_options['defaults_section'], $plugin_options['import'], $plugin_options['import_code'], $plugin_options['import_link'], $plugin_options['compiler'], $plugin_options['redux-section'] ); 
  2538.  
  2539. $this->set_transients(); 
  2540.  
  2541. return $plugin_options; 
  2542.  
  2543. // if ($this->transients['last_save_mode'] != 'remove') { 
  2544. $this->transients['last_save_mode'] = "normal"; // Last save mode 
  2545. // } else { 
  2546. // $this->transients['last_save_mode'] = ''; 
  2547. // } 
  2548.  
  2549.  
  2550. // Validate fields (if needed) 
  2551. $plugin_options = $this->_validate_values( $plugin_options, $this->options, $this->sections ); 
  2552.  
  2553. if ( ! empty( $this->errors ) || ! empty( $this->warnings ) ) { 
  2554. $this->transients['notices'] = array( 'errors' => $this->errors, 'warnings' => $this->warnings ); 
  2555.  
  2556. /** 
  2557. * action 'redux-validate-{opt_name}' 
  2558. * @deprecated 
  2559. * @param &array [&$plugin_options, redux_options] 
  2560. */ 
  2561. do_action_ref_array( "redux-validate-{$this->args['opt_name']}", array( 
  2562. &$plugin_options,  
  2563. $this->options 
  2564. ) ); // REMOVE 
  2565.  
  2566. /** 
  2567. * action 'redux/options/{opt_name}/validate' 
  2568. * @param &array [&$plugin_options, redux_options] 
  2569. */ 
  2570. do_action_ref_array( "redux/options/{$this->args['opt_name']}/validate", array( 
  2571. &$plugin_options,  
  2572. $this->options,  
  2573. $this->transients['changed_values'] 
  2574. ) ); 
  2575.  
  2576. if ( ! empty( $plugin_options['compiler'] ) ) { 
  2577. unset( $plugin_options['compiler'] ); 
  2578.  
  2579. $this->transients['last_compiler'] = $time; 
  2580. $this->transients['run_compiler'] = 1; 
  2581.  
  2582. $this->transients['changed_values'] = array(); // Changed values since last save 
  2583. foreach ( $this->options as $key => $value ) { 
  2584. if ( isset( $plugin_options[ $key ] ) && $value != $plugin_options[ $key ] ) { 
  2585. $this->transients['changed_values'][ $key ] = $value; 
  2586.  
  2587. unset( $plugin_options['defaults'], $plugin_options['defaults_section'], $plugin_options['import'], $plugin_options['import_code'], $plugin_options['import_link'], $plugin_options['compiler'], $plugin_options['redux-section'] ); 
  2588. if ( $this->args['database'] == 'transient' || $this->args['database'] == 'theme_mods' || $this->args['database'] == 'theme_mods_expanded' ) { 
  2589. $this->set_options( $plugin_options ); 
  2590.  
  2591. return; 
  2592.  
  2593. if ( defined( 'WP_CACHE' ) && WP_CACHE && class_exists( 'W3_ObjectCache' ) ) { 
  2594. //echo "here"; 
  2595. $w3 = W3_ObjectCache::instance(); 
  2596. $key = $w3->_get_cache_key( $this->args['opt_name'] . '-transients', 'transient' ); 
  2597. //echo $key; 
  2598. $w3->delete( $key, 'transient', true ); 
  2599. //set_transient($this->args['opt_name'].'-transients', $this->transients); 
  2600. //exit(); 
  2601.  
  2602. $this->set_transients( $this->transients ); 
  2603.  
  2604. return $plugin_options; 
  2605.  
  2606. /** 
  2607. * Validate values from options form (used in settings api validate function) 
  2608. * calls the custom validation class for the field so authors can override with custom classes 
  2609. * @since 1.0.0 
  2610. * @access public 
  2611. * @param array $plugin_options 
  2612. * @param array $options 
  2613. * @return array $plugin_options 
  2614. */ 
  2615. public function _validate_values( $plugin_options, $options, $sections ) { 
  2616. foreach ( $sections as $k => $section ) { 
  2617. if ( isset( $section['fields'] ) ) { 
  2618. foreach ( $section['fields'] as $fkey => $field ) { 
  2619.  
  2620. if( is_array( $field ) ) { 
  2621. $field['section_id'] = $k; 
  2622.  
  2623. if ( isset( $field['type'] ) && ( $field['type'] == 'checkbox' || $field['type'] == 'checkbox_hide_below' || $field['type'] == 'checkbox_hide_all' ) ) { 
  2624. if ( ! isset( $plugin_options[ $field['id'] ] ) ) { 
  2625. $plugin_options[ $field['id'] ] = 0; 
  2626.  
  2627. // Default 'not_empty 'flag to false. 
  2628. $isNotEmpty = false; 
  2629.  
  2630. // Make sure 'validate' field is set. 
  2631. if ( isset( $field['validate'] ) ) { 
  2632.  
  2633. // Make sure 'validate field' is set to 'not_empty' or 'email_not_empty' 
  2634. if ( $field['validate'] == 'not_empty' || $field['validate'] == 'email_not_empty' || $field['validate'] == 'numeric_not_empty' ) { 
  2635.  
  2636. // Set the flag. 
  2637. $isNotEmpty = true; 
  2638.  
  2639. // Check for empty id value 
  2640.  
  2641. if ( ! isset( $field['id'] ) || ! isset( $plugin_options[ $field['id'] ] ) || ( isset( $plugin_options[ $field['id'] ] ) && $plugin_options[ $field['id'] ] == '' ) ) { 
  2642.  
  2643. // If we are looking for an empty value, in the case of 'not_empty' 
  2644. // then we need to keep processing. 
  2645. if ( ! $isNotEmpty ) { 
  2646.  
  2647. // Empty id and not checking for 'not_empty. Bail out... 
  2648. continue; 
  2649.  
  2650. // Force validate of custom field types 
  2651. if ( isset( $field['type'] ) && ! isset( $field['validate'] ) ) { 
  2652. if ( $field['type'] == 'color' || $field['type'] == 'color_gradient' ) { 
  2653. $field['validate'] = 'color'; 
  2654. } elseif ( $field['type'] == 'date' ) { 
  2655. $field['validate'] = 'date'; 
  2656.  
  2657. if ( isset( $field['validate'] ) ) { 
  2658. $validate = 'Redux_Validation_' . $field['validate']; 
  2659.  
  2660. if ( ! class_exists( $validate ) ) { 
  2661. /** 
  2662. * filter 'redux-validateclass-load' 
  2663. * @deprecated 
  2664. * @param string validation class file path 
  2665. * @param string $validate validation class name 
  2666. */ 
  2667. $class_file = apply_filters( "redux-validateclass-load", self::$_dir . "inc/validation/{$field['validate']}/validation_{$field['validate']}.php", $validate ); // REMOVE LATER 
  2668.  
  2669. /** 
  2670. * filter 'redux/validate/{opt_name}/class/{field.validate}' 
  2671. * @param string validation class file path 
  2672. * @param string $class_file validation class file path 
  2673. */ 
  2674. $class_file = apply_filters( "redux/validate/{$this->args['opt_name']}/class/{$field['validate']}", self::$_dir . "inc/validation/{$field['validate']}/validation_{$field['validate']}.php", $class_file ); 
  2675.  
  2676. if ( $class_file ) { 
  2677. if ( file_exists( $class_file ) ) { 
  2678. require_once( $class_file ); 
  2679.  
  2680. if ( class_exists( $validate ) ) { 
  2681.  
  2682. //!DOVY - DB saving stuff. Is this right? 
  2683. if ( empty ( $options[ $field['id'] ] ) ) { 
  2684. $options[ $field['id'] ] = ''; 
  2685.  
  2686. if ( isset( $plugin_options[ $field['id'] ] ) && is_array( $plugin_options[ $field['id'] ] ) && ! empty( $plugin_options[ $field['id'] ] ) ) { 
  2687. foreach ( $plugin_options[ $field['id'] ] as $key => $value ) { 
  2688. $before = $after = null; 
  2689. if ( isset( $plugin_options[ $field['id'] ][ $key ] ) && ! empty( $plugin_options[ $field['id'] ][ $key ] ) ) { 
  2690. if ( is_array( $plugin_options[ $field['id'] ][ $key ] ) ) { 
  2691. $before = $plugin_options[ $field['id'] ][ $key ]; 
  2692. } else { 
  2693. $before = trim( $plugin_options[ $field['id'] ][ $key ] ); 
  2694.  
  2695. if ( isset( $options[ $field['id'] ][ $key ] ) && ! empty( $options[ $field['id'] ][ $key ] ) ) { 
  2696. $after = $options[ $field['id'] ][ $key ]; 
  2697.  
  2698. $validation = new $validate( $this, $field, $before, $after ); 
  2699. if ( ! empty( $validation->value ) ) { 
  2700. $plugin_options[ $field['id'] ][ $key ] = $validation->value; 
  2701. } else { 
  2702. unset( $plugin_options[ $field['id'] ][ $key ] ); 
  2703.  
  2704. if ( isset( $validation->error ) ) { 
  2705. $this->errors[] = $validation->error; 
  2706.  
  2707. if ( isset( $validation->warning ) ) { 
  2708. $this->warnings[] = $validation->warning; 
  2709. } else { 
  2710. if ( is_array( $plugin_options[ $field['id'] ] ) ) { 
  2711. $pofi = $plugin_options[ $field['id'] ]; 
  2712. } else { 
  2713. $pofi = trim( $plugin_options[ $field['id'] ] ); 
  2714.  
  2715. $validation = new $validate( $this, $field, $pofi, $options[ $field['id'] ] ); 
  2716. $plugin_options[ $field['id'] ] = $validation->value; 
  2717.  
  2718. if ( isset( $validation->error ) ) { 
  2719. $this->errors[] = $validation->error; 
  2720.  
  2721. if ( isset( $validation->warning ) ) { 
  2722. $this->warnings[] = $validation->warning; 
  2723.  
  2724. continue; 
  2725. if ( isset( $field['validate_callback'] ) && ( is_callable( $field['validate_callback'] ) || ( is_string( $field['validate_callback'] ) && function_exists( $field['validate_callback'] ) ) ) ) { 
  2726. $callback = $field['validate_callback']; 
  2727. unset( $field['validate_callback'] ); 
  2728.  
  2729. $callbackvalues = call_user_func( $callback, $field, $plugin_options[ $field['id'] ], $options[ $field['id'] ] ); 
  2730. $plugin_options[ $field['id'] ] = $callbackvalues['value']; 
  2731.  
  2732. if ( isset( $callbackvalues['error'] ) ) { 
  2733. $this->errors[] = $callbackvalues['error']; 
  2734. // TODO - This warning message is failing. Hmm. 
  2735. if ( isset( $callbackvalues['warning'] ) ) { 
  2736. $this->warnings[] = $callbackvalues['warning']; 
  2737.  
  2738. return $plugin_options; 
  2739.  
  2740. /** 
  2741. * Return Section Menu HTML 
  2742. * @since 3.1.5 
  2743. * @access public 
  2744. * @return void 
  2745. */ 
  2746. public function section_menu( $k, $section, $suffix = "", $sections = array() ) { 
  2747. $display = true; 
  2748.  
  2749. $section['class'] = isset( $section['class'] ) ? ' ' . $section['class'] : ''; 
  2750.  
  2751. if ( isset( $_GET['page'] ) && $_GET['page'] == $this->args['page_slug'] ) { 
  2752. if ( isset( $section['panel'] ) && $section['panel'] == false ) { 
  2753. $display = false; 
  2754.  
  2755. if ( ! $display ) { 
  2756. return ""; 
  2757.  
  2758. if ( empty( $sections ) ) { 
  2759. $sections = $this->sections; 
  2760.  
  2761. $string = ""; 
  2762. if ( ( isset( $this->args['icon_type'] ) && $this->args['icon_type'] == 'image' ) || ( isset( $section['icon_type'] ) && $section['icon_type'] == 'image' ) ) { 
  2763. //if( !empty( $this->args['icon_type'] ) && $this->args['icon_type'] == 'image' ) { 
  2764. $icon = ( ! isset( $section['icon'] ) ) ? '' : '<img class="image_icon_type" src="' . $section['icon'] . '" /> '; 
  2765. } else { 
  2766. if ( ! empty( $section['icon_class'] ) ) { 
  2767. $icon_class = ' ' . $section['icon_class']; 
  2768. } elseif ( ! empty( $this->args['default_icon_class'] ) ) { 
  2769. $icon_class = ' ' . $this->args['default_icon_class']; 
  2770. } else { 
  2771. $icon_class = ''; 
  2772. $icon = ( ! isset( $section['icon'] ) ) ? '<i class="el-icon-cog' . $icon_class . '"></i> ' : '<i class="' . $section['icon'] . $icon_class . '"></i> '; 
  2773.  
  2774. $hide_section = ''; 
  2775. if (isset($section['hidden'])) { 
  2776. $hide_section = ($section['hidden'] == true) ? ' hidden ' : ''; 
  2777.  
  2778. $canBeSubSection = ( $k > 0 && ( ! isset( $sections[ ( $k ) ]['type'] ) || $sections[ ( $k ) ]['type'] != "divide" ) ) ? true : false; 
  2779.  
  2780. if ( ! $canBeSubSection && isset( $section['subsection'] ) && $section['subsection'] == true ) { 
  2781. unset( $section['subsection'] ); 
  2782.  
  2783. if ( isset( $section['type'] ) && $section['type'] == "divide" ) { 
  2784. $string .= '<li class="divide' . $section['class'] . '"> </li>'; 
  2785. } else if ( ! isset( $section['subsection'] ) || $section['subsection'] != true ) { 
  2786.  
  2787. // DOVY! REPLACE $k with $section['ID'] when used properly. 
  2788. //$active = ( ( is_numeric($this->current_tab) && $this->current_tab == $k ) || ( !is_numeric($this->current_tab) && $this->current_tab === $k ) ) ? ' active' : ''; 
  2789. $subsections = ( isset( $sections[ ( $k + 1 ) ] ) && isset( $sections[ ( $k + 1 ) ]['subsection'] ) && $sections[ ( $k + 1 ) ]['subsection'] == true ) ? true : false; 
  2790. $subsectionsClass = $subsections ? ' hasSubSections' : ''; 
  2791. $subsectionsClass .= ( ! isset( $section['fields'] ) || empty( $section['fields'] ) ) ? ' empty_section' : ''; 
  2792. $extra_icon = $subsections ? '<span class="extraIconSubsections"><i class="el el-icon-chevron-down"> </i></span>' : ''; 
  2793. $string .= '<li id="' . $k . $suffix . '_section_group_li" class="redux-group-tab-link-li' . $hide_section . $section['class'] . $subsectionsClass . '">'; 
  2794. $string .= '<a href="javascript:void(0);" id="' . $k . $suffix . '_section_group_li_a" class="redux-group-tab-link-a" data-key="' . $k . '" data-rel="' . $k . $suffix . '">' . $extra_icon . $icon . '<span class="group_title">' . $section['title'] . '</span></a>'; 
  2795. $nextK = $k; 
  2796.  
  2797. // Make sure you can make this a subsection 
  2798. if ( $subsections ) { 
  2799. $string .= '<ul id="' . $nextK . $suffix . '_section_group_li_subsections" class="subsection">'; 
  2800. $doLoop = true; 
  2801.  
  2802. while ( $doLoop ) { 
  2803. $nextK += 1; 
  2804. $display = true; 
  2805.  
  2806. if ( isset( $_GET['page'] ) && $_GET['page'] == $this->args['page_slug'] ) { 
  2807. if ( isset( $sections[ $nextK ]['panel'] ) && $sections[ $nextK ]['panel'] == false ) { 
  2808. $display = false; 
  2809.  
  2810. if ( count( $sections ) < $nextK || ! isset( $sections[ $nextK ] ) || ! isset( $sections[ $nextK ]['subsection'] ) || $sections[ $nextK ]['subsection'] != true ) { 
  2811. $doLoop = false; 
  2812. } else { 
  2813. if ( ! $display ) { 
  2814. continue; 
  2815.  
  2816. $hide_sub = ''; 
  2817. if (isset($sections[ $nextK ]['hidden'])) { 
  2818. $hide_sub = ($sections[ $nextK ]['hidden'] == true) ? ' hidden ' : ''; 
  2819.  
  2820. if ( ( isset( $this->args['icon_type'] ) && $this->args['icon_type'] == 'image' ) || ( isset( $sections[ $nextK ]['icon_type'] ) && $sections[ $nextK ]['icon_type'] == 'image' ) ) { 
  2821. //if( !empty( $this->args['icon_type'] ) && $this->args['icon_type'] == 'image' ) { 
  2822. $icon = ( ! isset( $sections[ $nextK ]['icon'] ) ) ? '' : '<img class="image_icon_type" src="' . $sections[ $nextK ]['icon'] . '" /> '; 
  2823. } else { 
  2824. if ( ! empty( $sections[ $nextK ]['icon_class'] ) ) { 
  2825. $icon_class = ' ' . $sections[ $nextK ]['icon_class']; 
  2826. } elseif ( ! empty( $this->args['default_icon_class'] ) ) { 
  2827. $icon_class = ' ' . $this->args['default_icon_class']; 
  2828. } else { 
  2829. $icon_class = ''; 
  2830. $icon = ( ! isset( $sections[ $nextK ]['icon'] ) ) ? '' : '<i class="' . $sections[ $nextK ]['icon'] . $icon_class . '"></i> '; 
  2831. $section[ $nextK ]['class'] = isset( $section[ $nextK ]['class'] ) ? $section[ $nextK ]['class'] : ''; 
  2832. $string .= '<li id="' . $nextK . $suffix . '_section_group_li" class="redux-group-tab-link-li ' . $hide_sub . $section[ $nextK ]['class'] . ( $icon ? ' hasIcon' : '' ) . '">'; 
  2833. $string .= '<a href="javascript:void(0);" id="' . $nextK . $suffix . '_section_group_li_a" class="redux-group-tab-link-a" data-key="' . $nextK . '" data-rel="' . $nextK . $suffix . '">' . $icon . '<span class="group_title">' . $sections[ $nextK ]['title'] . '</span></a>'; 
  2834. $string .= '</li>'; 
  2835.  
  2836. $string .= '</ul>'; 
  2837.  
  2838. $string .= '</li>'; 
  2839.  
  2840. return $string; 
  2841.  
  2842. } // section_menu() 
  2843.  
  2844.  
  2845. /** 
  2846. * HTML OUTPUT. 
  2847. * @since 1.0.0 
  2848. * @access public 
  2849. * @return void 
  2850. */ 
  2851. public function _options_page_html() { 
  2852. echo '<div class="wrap"><h2></h2></div>'; // Stupid hack for Wordpress alerts and warnings 
  2853.  
  2854. echo '<div class="clear"></div>'; 
  2855. echo '<div class="wrap">'; 
  2856.  
  2857. // Do we support JS? 
  2858. echo '<noscript><div class="no-js">' . __( 'Warning- This options panel will not work properly without javascript!', 'redux-framework' ) . '</div></noscript>'; 
  2859.  
  2860. // Security is vital! 
  2861. echo '<input type="hidden" id="ajaxsecurity" name="security" value="' . wp_create_nonce( 'redux_ajax_nonce' ) . '" />'; 
  2862.  
  2863. /** 
  2864. * action 'redux-page-before-form-{opt_name}' 
  2865. * @deprecated 
  2866. */ 
  2867. do_action( "redux-page-before-form-{$this->args['opt_name']}" ); // Remove 
  2868.  
  2869. /** 
  2870. * action 'redux/page/{opt_name}/form/before' 
  2871. * @param object $this ReduxFramework 
  2872. */ 
  2873. do_action( "redux/page/{$this->args['opt_name']}/form/before", $this ); 
  2874.  
  2875. // Main container 
  2876. $expanded = ( $this->args['open_expanded'] ) ? ' fully-expanded' : ''; 
  2877.  
  2878. echo '<div class="redux-container' . $expanded . ( ! empty( $this->args['class'] ) ? ' ' . $this->args['class'] : '' ) . '">'; 
  2879. $url = './options.php'; 
  2880. if ( $this->args['database'] == "network" && $this->args['network_admin'] ) { 
  2881. if ( is_network_admin() ) { 
  2882. $url = './edit.php?action=redux_' . $this->args['opt_name']; 
  2883. echo '<form method="post" action="' . $url . '" enctype="multipart/form-data" id="redux-form-wrapper">'; 
  2884. echo '<input type="hidden" id="redux-compiler-hook" name="' . $this->args['opt_name'] . '[compiler]" value="" />'; 
  2885. echo '<input type="hidden" id="currentSection" name="' . $this->args['opt_name'] . '[redux-section]" value="" />'; 
  2886. if ( ! empty( $this->no_panel ) ) { 
  2887. echo '<input type="hidden" name="' . $this->args['opt_name'] . '[redux-no_panel]" value="' . implode( '|', $this->no_panel ) . '" />'; 
  2888.  
  2889.  
  2890. settings_fields( "{$this->args['opt_name']}_group" ); 
  2891.  
  2892. // Last tab? 
  2893. $this->options['last_tab'] = ( isset( $_GET['tab'] ) && ! isset( $this->transients['last_save_mode'] ) ) ? $_GET['tab'] : ''; 
  2894.  
  2895. echo '<input type="hidden" id="last_tab" name="' . $this->args['opt_name'] . '[last_tab]" value="' . $this->options['last_tab'] . '" />'; 
  2896.  
  2897. // Header area 
  2898. echo '<div id="redux-header">'; 
  2899.  
  2900. if ( ! empty( $this->args['display_name'] ) ) { 
  2901. echo '<div class="display_header">'; 
  2902.  
  2903. if ( isset( $this->args['dev_mode'] ) && $this->args['dev_mode'] ) { 
  2904. echo '<span class="redux-dev-mode-notice">' . __( 'Developer Mode Enabled', 'redux-framework' ) . '</span>'; 
  2905.  
  2906. echo '<h2>' . $this->args['display_name'] . '</h2>'; 
  2907.  
  2908. if ( ! empty( $this->args['display_version'] ) ) { 
  2909. echo '<span>' . $this->args['display_version'] . '</span>'; 
  2910.  
  2911. echo '</div>'; 
  2912.  
  2913. echo '<div class="clear"></div>'; 
  2914. echo '</div>'; 
  2915.  
  2916. // Intro text 
  2917. if ( isset( $this->args['intro_text'] ) ) { 
  2918. echo '<div id="redux-intro-text">'; 
  2919. echo $this->args['intro_text']; 
  2920. echo '</div>'; 
  2921.  
  2922. // Stickybar 
  2923. echo '<div id="redux-sticky">'; 
  2924. echo '<div id="info_bar">'; 
  2925.  
  2926. $expanded = ( $this->args['open_expanded'] ) ? ' expanded' : ''; 
  2927. $hide_expand = $this->args['hide_expand'] ? ' style="display: none;"' : ''; 
  2928.  
  2929. echo '<a href="javascript:void(0);" class="expand_options' . $expanded . '"' . $hide_expand . '>' . __( 'Expand', 'redux-framework' ) . '</a>'; 
  2930. echo '<div class="redux-action_bar">'; 
  2931. submit_button( __( 'Save Changes', 'redux-framework' ), 'primary', 'redux_save', false ); 
  2932.  
  2933. if ( false === $this->args['hide_reset'] ) { 
  2934. echo ' '; 
  2935. submit_button( __( 'Reset Section', 'redux-framework' ), 'secondary', $this->args['opt_name'] . '[defaults-section]', false ); 
  2936. echo ' '; 
  2937. submit_button( __( 'Reset All', 'redux-framework' ), 'secondary', $this->args['opt_name'] . '[defaults]', false ); 
  2938.  
  2939. echo '</div>'; 
  2940.  
  2941. echo '<div class="redux-ajax-loading" alt="' . __( 'Working...', 'redux-framework' ) . '"> </div>'; 
  2942. echo '<div class="clear"></div>'; 
  2943. echo '</div>'; 
  2944.  
  2945. // Warning bar 
  2946. if ( isset( $this->transients['last_save_mode'] ) ) { 
  2947.  
  2948. if ( $this->transients['last_save_mode'] == "import" ) { 
  2949. /** 
  2950. * action 'redux/options/{opt_name}/import' 
  2951. * @param object $this ReduxFramework 
  2952. */ 
  2953. do_action( "redux/options/{$this->args['opt_name']}/import", $this, $this->transients['changed_values'] ); 
  2954.  
  2955. /** 
  2956. * filter 'redux-imported-text-{opt_name}' 
  2957. * @param string translated "settings imported" text 
  2958. */ 
  2959. echo '<div class="admin-notice notice-blue saved_notice"><strong>' . apply_filters( "redux-imported-text-{$this->args['opt_name']}", __( 'Settings Imported!', 'redux-framework' ) ) . '</strong></div>'; 
  2960. //exit(); 
  2961. } else if ( $this->transients['last_save_mode'] == "defaults" ) { 
  2962. /** 
  2963. * action 'redux/options/{opt_name}/reset' 
  2964. * @param object $this ReduxFramework 
  2965. */ 
  2966. do_action( "redux/options/{$this->args['opt_name']}/reset", $this ); 
  2967.  
  2968. /** 
  2969. * filter 'redux-defaults-text-{opt_name}' 
  2970. * @param string translated "settings imported" text 
  2971. */ 
  2972. echo '<div class="saved_notice admin-notice notice-yellow"><strong>' . apply_filters( "redux-defaults-text-{$this->args['opt_name']}", __( 'All Defaults Restored!', 'redux-framework' ) ) . '</strong></div>'; 
  2973. } else if ( $this->transients['last_save_mode'] == "defaults_section" ) { 
  2974. /** 
  2975. * action 'redux/options/{opt_name}/section/reset' 
  2976. * @param object $this ReduxFramework 
  2977. */ 
  2978. do_action( "redux/options/{$this->args['opt_name']}/section/reset", $this ); 
  2979.  
  2980. /** 
  2981. * filter 'redux-defaults-section-text-{opt_name}' 
  2982. * @param string translated "settings imported" text 
  2983. */ 
  2984. echo '<div class="saved_notice admin-notice notice-yellow"><strong>' . apply_filters( "redux-defaults-section-text-{$this->args['opt_name']}", __( 'Section Defaults Restored!', 'redux-framework' ) ) . '</strong></div>'; 
  2985. } else if ( $this->transients['last_save_mode'] == "normal") { 
  2986. /** 
  2987. * action 'redux/options/{opt_name}/saved' 
  2988. * @param mixed $value set/saved option value 
  2989. */ 
  2990. do_action( "redux/options/{$this->args['opt_name']}/saved", $this->options, $this->transients['changed_values'] ); 
  2991.  
  2992. /** 
  2993. * filter 'redux-saved-text-{opt_name}' 
  2994. * @param string translated "settings saved" text 
  2995. */ 
  2996. echo '<div class="saved_notice admin-notice notice-green"><strong>' . apply_filters( "redux-saved-text-{$this->args['opt_name']}", __( 'Settings Saved!', 'redux-framework' ) ) . '</strong></div>'; 
  2997.  
  2998. unset( $this->transients['last_save_mode'] ); 
  2999. //$this->transients['last_save_mode'] = 'remove'; 
  3000. $this->set_transients(); 
  3001.  
  3002. /** 
  3003. * action 'redux/options/{opt_name}/settings/changes' 
  3004. * @param mixed $value set/saved option value 
  3005. */ 
  3006. do_action( "redux/options/{$this->args['opt_name']}/settings/change", $this->options, $this->transients['changed_values'] ); 
  3007.  
  3008. /** 
  3009. * filter 'redux-changed-text-{opt_name}' 
  3010. * @param string translated "settings have changed" text 
  3011. */ 
  3012. echo '<div class="redux-save-warn notice-yellow"><strong>' . apply_filters( "redux-changed-text-{$this->args['opt_name']}", __( 'Settings have changed, you should save them!', 'redux-framework' ) ) . '</strong></div>'; 
  3013.  
  3014. /** 
  3015. * action 'redux/options/{opt_name}/errors' 
  3016. * @param array $this ->errors error information 
  3017. */ 
  3018. do_action( "redux/options/{$this->args['opt_name']}/errors", $this->errors ); 
  3019. echo '<div class="redux-field-errors notice-red"><strong><span></span> ' . __( 'error(s) were found!', 'redux-framework' ) . '</strong></div>'; 
  3020.  
  3021. /** 
  3022. * action 'redux/options/{opt_name}/warnings' 
  3023. * @param array $this ->warnings warning information 
  3024. */ 
  3025. do_action( "redux/options/{$this->args['opt_name']}/warnings", $this->warnings ); 
  3026. echo '<div class="redux-field-warnings notice-yellow"><strong><span></span> ' . __( 'warning(s) were found!', 'redux-framework' ) . '</strong></div>'; 
  3027.  
  3028. echo '</div>'; 
  3029.  
  3030. echo '<div class="clear"></div>'; 
  3031.  
  3032. // Sidebar 
  3033. echo '<div class="redux-sidebar">'; 
  3034. echo '<ul class="redux-group-menu">'; 
  3035.  
  3036. foreach ( $this->sections as $k => $section ) { 
  3037. $title = isset( $section['title'] ) ? $section['title'] : ''; 
  3038.  
  3039. $skip_sec = false; 
  3040. foreach ( $this->hidden_perm_sections as $num => $section_title ) { 
  3041. if ( $section_title == $title ) { 
  3042. $skip_sec = true; 
  3043.  
  3044. if ( isset( $section['customizer_only'] ) && $section['customizer_only'] == true ) { 
  3045. continue; 
  3046.  
  3047. if ( false == $skip_sec ) { 
  3048. echo $this->section_menu( $k, $section ); 
  3049. $skip_sec = false; 
  3050.  
  3051. /** 
  3052. * action 'redux-page-after-sections-menu-{opt_name}' 
  3053. * @param object $this ReduxFramework 
  3054. */ 
  3055. do_action( "redux-page-after-sections-menu-{$this->args['opt_name']}", $this ); 
  3056.  
  3057. /** 
  3058. * action 'redux/page/{opt_name}/menu/after' 
  3059. * @param object $this ReduxFramework 
  3060. */ 
  3061. do_action( "redux/page/{$this->args['opt_name']}/menu/after", $this ); 
  3062.  
  3063. // Import / Export tab 
  3064. if ( true == $this->args['show_import_export'] && false == $this->import_export->is_field ) { 
  3065. $this->import_export->render_tab(); 
  3066.  
  3067. // Debug tab 
  3068. if ( $this->args['dev_mode'] == true ) { 
  3069. $this->debug->render_tab(); 
  3070.  
  3071. if ( $this->args['system_info'] === true ) { 
  3072. echo '<li id="system_info_default_section_group_li" class="redux-group-tab-link-li">'; 
  3073.  
  3074. if ( ! empty( $this->args['icon_type'] ) && $this->args['icon_type'] == 'image' ) { 
  3075. $icon = ( ! isset( $this->args['system_info_icon'] ) ) ? '' : '<img src="' . $this->args['system_info_icon'] . '" /> '; 
  3076. } else { 
  3077. $icon_class = ( ! isset( $this->args['system_info_icon_class'] ) ) ? '' : ' ' . $this->args['system_info_icon_class']; 
  3078. $icon = ( ! isset( $this->args['system_info_icon'] ) ) ? '<i class="el-icon-info-sign' . $icon_class . '"></i>' : '<i class="icon-' . $this->args['system_info_icon'] . $icon_class . '"></i> '; 
  3079.  
  3080. echo '<a href="javascript:void(0);" id="system_info_default_section_group_li_a" class="redux-group-tab-link-a custom-tab" data-rel="system_info_default">' . $icon . ' <span class="group_title">' . __( 'System Info', 'redux-framework' ) . '</span></a>'; 
  3081. echo '</li>'; 
  3082.  
  3083. echo '</ul>'; 
  3084. echo '</div>'; 
  3085.  
  3086. echo '<div class="redux-main">'; 
  3087.  
  3088. foreach ( $this->sections as $k => $section ) { 
  3089. if ( isset( $section['customizer_only'] ) && $section['customizer_only'] == true ) { 
  3090. continue; 
  3091.  
  3092. //$active = ( ( is_numeric($this->current_tab) && $this->current_tab == $k ) || ( !is_numeric($this->current_tab) && $this->current_tab === $k ) ) ? ' style="display: block;"' : ''; 
  3093. $section['class'] = isset( $section['class'] ) ? ' ' . $section['class'] : ''; 
  3094. echo '<div id="' . $k . '_section_group' . '" class="redux-group-tab' . $section['class'] . '" data-rel="' . $k . '">'; 
  3095. //echo '<div id="' . $k . '_nav-bar' . '"'; 
  3096. /** 
  3097. if ( !empty( $section['tab'] ) ) { 
  3098.   
  3099. echo '<div id="' . $k . '_section_tabs' . '" class="redux-section-tabs">'; 
  3100.   
  3101. echo '<ul>'; 
  3102.   
  3103. foreach ($section['tab'] as $subkey => $subsection) { 
  3104. //echo '-=' . $subkey . '=-'; 
  3105. echo '<li style="display:inline;"><a href="#' . $k . '_section-tab-' . $subkey . '">' . $subsection['title'] . '</a></li>'; 
  3106.   
  3107. echo '</ul>'; 
  3108. foreach ($section['tab'] as $subkey => $subsection) { 
  3109. echo '<div id="' . $k .'sub-'.$subkey. '_section_group' . '" class="redux-group-tab" style="display:block;">'; 
  3110. echo '<div id="' . $k . '_section-tab-' . $subkey . '">'; 
  3111. echo "hello ".$subkey; 
  3112. do_settings_sections( $this->args['opt_name'] . $k . '_tab_' . $subkey . '_section_group' ); 
  3113. echo "</div>"; 
  3114. echo "</div>"; 
  3115. echo "</div>"; 
  3116. } else { 
  3117. */ 
  3118.  
  3119. // Don't display in the 
  3120. $display = true; 
  3121. if ( isset( $_GET['page'] ) && $_GET['page'] == $this->args['page_slug'] ) { 
  3122. if ( isset( $section['panel'] ) && $section['panel'] == "false" ) { 
  3123. $display = false; 
  3124.  
  3125. if ( $display ) { 
  3126. do_settings_sections( $this->args['opt_name'] . $k . '_section_group' ); 
  3127. //} 
  3128. echo "</div>"; 
  3129. //echo '</div>'; 
  3130.  
  3131. // Import / Export output 
  3132. if ( true == $this->args['show_import_export'] && false == $this->import_export->is_field ) { 
  3133. $this->import_export->enqueue(); 
  3134.  
  3135. echo '<fieldset id="' . $this->args['opt_name'] . '-import_export_core" class="redux-field-container redux-field redux-field-init redux-container-import_export" data-id="import_export_core" data-type="import_export">'; 
  3136. $this->import_export->render(); 
  3137. echo '</fieldset>'; 
  3138.  
  3139.  
  3140. // Debug object output 
  3141. if ( $this->args['dev_mode'] == true ) { 
  3142. $this->debug->render(); 
  3143.  
  3144. if ( $this->args['system_info'] === true ) { 
  3145. require_once 'inc/sysinfo.php'; 
  3146. $system_info = new Simple_System_Info(); 
  3147.  
  3148. echo '<div id="system_info_default_section_group' . '" class="redux-group-tab">'; 
  3149. echo '<h3>' . __( 'System Info', 'redux-framework' ) . '</h3>'; 
  3150.  
  3151. echo '<div id="redux-system-info">'; 
  3152. echo $system_info->get( true ); 
  3153. echo '</div>'; 
  3154.  
  3155. echo '</div>'; 
  3156.  
  3157. /** 
  3158. * action 'redux/page-after-sections-{opt_name}' 
  3159. * @deprecated 
  3160. * @param object $this ReduxFramework 
  3161. */ 
  3162. do_action( "redux/page-after-sections-{$this->args['opt_name']}", $this ); // REMOVE LATER 
  3163.  
  3164. /** 
  3165. * action 'redux/page/{opt_name}/sections/after' 
  3166. * @param object $this ReduxFramework 
  3167. */ 
  3168. do_action( "redux/page/{$this->args['opt_name']}/sections/after", $this ); 
  3169.  
  3170. echo '<div class="clear"></div>'; 
  3171. echo '</div>'; 
  3172. echo '<div class="clear"></div>'; 
  3173.  
  3174. echo '<div id="redux-sticky-padder" style="display: none;"> </div>'; 
  3175. echo '<div id="redux-footer-sticky"><div id="redux-footer">'; 
  3176.  
  3177. if ( isset( $this->args['share_icons'] ) ) { 
  3178. echo '<div id="redux-share">'; 
  3179.  
  3180. foreach ( $this->args['share_icons'] as $link ) { 
  3181. // SHIM, use URL now 
  3182. if ( isset( $link['link'] ) && ! empty( $link['link'] ) ) { 
  3183. $link['url'] = $link['link']; 
  3184. unset( $link['link'] ); 
  3185.  
  3186. echo '<a href="' . $link['url'] . '" title="' . $link['title'] . '" target="_blank">'; 
  3187.  
  3188. if ( isset( $link['icon'] ) && ! empty( $link['icon'] ) ) { 
  3189. echo '<i class="' . $link['icon'] . '"></i>'; 
  3190. } else { 
  3191. echo '<img src="' . $link['img'] . '"/>'; 
  3192.  
  3193. echo '</a>'; 
  3194.  
  3195. echo '</div>'; 
  3196.  
  3197. echo '<div class="redux-action_bar">'; 
  3198. submit_button( __( 'Save Changes', 'redux-framework' ), 'primary', 'redux_save', false ); 
  3199.  
  3200. if ( false === $this->args['hide_reset'] ) { 
  3201. echo ' '; 
  3202. submit_button( __( 'Reset Section', 'redux-framework' ), 'secondary', $this->args['opt_name'] . '[defaults-section]', false ); 
  3203. echo ' '; 
  3204. submit_button( __( 'Reset All', 'redux-framework' ), 'secondary', $this->args['opt_name'] . '[defaults]', false ); 
  3205.  
  3206. echo '</div>'; 
  3207.  
  3208. echo '<div class="redux-ajax-loading" alt="' . __( 'Working...', 'redux-framework' ) . '"> </div>'; 
  3209. echo '<div class="clear"></div>'; 
  3210.  
  3211. echo '</div>'; 
  3212. echo '</form>'; 
  3213. echo '</div></div>'; 
  3214.  
  3215. echo ( isset( $this->args['footer_text'] ) ) ? '<div id="redux-sub-footer">' . $this->args['footer_text'] . '</div>' : ''; 
  3216.  
  3217. /** 
  3218. * action 'redux-page-after-form-{opt_name}' 
  3219. * @deprecated 
  3220. */ 
  3221. do_action( "redux-page-after-form-{$this->args['opt_name']}" ); // REMOVE 
  3222.  
  3223. /** 
  3224. * action 'redux/page/{opt_name}/form/after' 
  3225. * @param object $this ReduxFramework 
  3226. */ 
  3227. do_action( "redux/page/{$this->args['opt_name']}/form/after", $this ); 
  3228.  
  3229. echo '<div class="clear"></div>'; 
  3230. echo '</div><!--wrap-->'; 
  3231.  
  3232. if ( $this->args['dev_mode'] == true ) { 
  3233. if ( current_user_can( 'administrator' ) ) { 
  3234. global $wpdb; 
  3235. echo "<br /><pre>"; 
  3236. print_r( $wpdb->queries ); 
  3237. echo "</pre>"; 
  3238.  
  3239. echo '<br /><div class="redux-timer">' . get_num_queries() . ' queries in ' . timer_stop( 0 ) . ' seconds<br/>Redux is currently set to developer mode.</div>'; 
  3240.  
  3241. $this->set_transients(); 
  3242.  
  3243. /** 
  3244. * Section HTML OUTPUT. 
  3245. * @since 1.0.0 
  3246. * @access public 
  3247. * @param array $section 
  3248. * @return void 
  3249. */ 
  3250. public function _section_desc( $section ) { 
  3251. $id = trim( rtrim( $section['id'], '_section' ), $this->args['opt_name'] ); 
  3252.  
  3253. if ( isset( $this->sections[ $id ]['desc'] ) && ! empty( $this->sections[ $id ]['desc'] ) ) { 
  3254. echo '<div class="redux-section-desc">' . $this->sections[ $id ]['desc'] . '</div>'; 
  3255.  
  3256. /** 
  3257. * Field HTML OUTPUT. 
  3258. * Gets option from options array, then calls the specific field type class - allows extending by other devs 
  3259. * @since 1.0.0 
  3260. * @param array $field 
  3261. * @param string $v 
  3262. * @return void 
  3263. */ 
  3264. public function _field_input( $field, $v = null ) { 
  3265.  
  3266. if ( isset( $field['callback'] ) && ( is_callable( $field['callback'] ) || ( is_string( $field['callback'] ) && function_exists( $field['callback'] ) ) ) ) { 
  3267.  
  3268. $value = ( isset( $this->options[ $field['id'] ] ) ) ? $this->options[ $field['id'] ] : ''; 
  3269.  
  3270. /** 
  3271. * action 'redux-before-field-{opt_name}' 
  3272. * @deprecated 
  3273. * @param array $field field data 
  3274. * @param string $value field.id 
  3275. */ 
  3276. do_action( "redux-before-field-{$this->args['opt_name']}", $field, $value ); // REMOVE 
  3277.  
  3278. /** 
  3279. * action 'redux/field/{opt_name}/{field.type}/callback/before' 
  3280. * @param array $field field data 
  3281. * @param string $value field.id 
  3282. */ 
  3283. do_action( "redux/field/{$this->args['opt_name']}/{$field['type']}/callback/before", $field, $value ); 
  3284.  
  3285. /** 
  3286. * action 'redux/field/{opt_name}/callback/before' 
  3287. * @param array $field field data 
  3288. * @param string $value field.id 
  3289. */ 
  3290. do_action( "redux/field/{$this->args['opt_name']}/callback/before", $field, $value ); 
  3291.  
  3292. call_user_func( $field['callback'], $field, $value ); 
  3293.  
  3294.  
  3295. /** 
  3296. * action 'redux-after-field-{opt_name}' 
  3297. * @deprecated 
  3298. * @param array $field field data 
  3299. * @param string $value field.id 
  3300. */ 
  3301. do_action( "redux-after-field-{$this->args['opt_name']}", $field, $value ); // REMOVE 
  3302.  
  3303. /** 
  3304. * action 'redux/field/{opt_name}/{field.type}/callback/after' 
  3305. * @param array $field field data 
  3306. * @param string $value field.id 
  3307. */ 
  3308. do_action( "redux/field/{$this->args['opt_name']}/{$field['type']}/callback/after", $field, $value ); 
  3309.  
  3310. /** 
  3311. * action 'redux/field/{opt_name}/callback/after' 
  3312. * @param array $field field data 
  3313. * @param string $value field.id 
  3314. */ 
  3315. do_action( "redux/field/{$this->args['opt_name']}/callback/after", $field, $value ); 
  3316.  
  3317. return; 
  3318.  
  3319. if ( isset( $field['type'] ) ) { 
  3320.  
  3321. // If the field is set not to display in the panel 
  3322. $display = true; 
  3323. if ( isset( $_GET['page'] ) && $_GET['page'] == $this->args['page_slug'] ) { 
  3324. if ( isset( $field['panel'] ) && $field['panel'] == false ) { 
  3325. $display = false; 
  3326.  
  3327. if ( ! $display ) { 
  3328. return; 
  3329.  
  3330. $field_class = "ReduxFramework_{$field['type']}"; 
  3331.  
  3332. if ( ! class_exists( $field_class ) ) { 
  3333. // $class_file = apply_filters( 'redux/field/class/'.$field['type'], self::$_dir . 'inc/fields/' . $field['type'] . '/field_' . $field['type'] . '.php', $field ); // REMOVE 
  3334. /** 
  3335. * filter 'redux/{opt_name}/field/class/{field.type}' 
  3336. * @param string field class file path 
  3337. * @param array $field field data 
  3338. */ 
  3339. $class_file = apply_filters( "redux/{$this->args['opt_name']}/field/class/{$field['type']}", self::$_dir . "inc/fields/{$field['type']}/field_{$field['type']}.php", $field ); 
  3340.  
  3341. if ( $class_file ) { 
  3342. if ( file_exists( $class_file ) ) { 
  3343. require_once( $class_file ); 
  3344.  
  3345.  
  3346. if ( class_exists( $field_class ) ) { 
  3347. $value = isset( $this->options[ $field['id'] ] ) ? $this->options[ $field['id'] ] : ''; 
  3348.  
  3349. if ( $v !== null ) { 
  3350. $value = $v; 
  3351.  
  3352. /** 
  3353. * action 'redux-before-field-{opt_name}' 
  3354. * @deprecated 
  3355. * @param array $field field data 
  3356. * @param string $value field id 
  3357. */ 
  3358. do_action( "redux-before-field-{$this->args['opt_name']}", $field, $value ); // REMOVE 
  3359.  
  3360. /** 
  3361. * action 'redux/field/{opt_name}/{field.type}/render/before' 
  3362. * @param array $field field data 
  3363. * @param string $value field id 
  3364. */ 
  3365. do_action( "redux/field/{$this->args['opt_name']}/{$field['type']}/render/before", $field, $value ); 
  3366.  
  3367. /** 
  3368. * action 'redux/field/{$this->args['opt_name']}/render/before' 
  3369. * @param array $field field data 
  3370. * @param string $value field id 
  3371. */ 
  3372. do_action( "redux/field/{$this->args['opt_name']}/render/before", $field, $value ); 
  3373.  
  3374. if ( ! isset( $field['name_suffix'] ) ) { 
  3375. $field['name_suffix'] = ""; 
  3376.  
  3377. $render = new $field_class( $field, $value, $this ); 
  3378. ob_start(); 
  3379.  
  3380. $render->render(); 
  3381.  
  3382. /** 
  3383.   
  3384. echo "<pre>"; 
  3385. print_r($value); 
  3386. echo "</pre>"; 
  3387. */ 
  3388.  
  3389. /** 
  3390. * filter 'redux-field-{opt_name}' 
  3391. * @deprecated 
  3392. * @param string rendered field markup 
  3393. * @param array $field field data 
  3394. */ 
  3395. $_render = apply_filters( "redux-field-{$this->args['opt_name']}", ob_get_contents(), $field ); // REMOVE 
  3396.  
  3397. /** 
  3398. * filter 'redux/field/{opt_name}/{field.type}/render/after' 
  3399. * @param string rendered field markup 
  3400. * @param array $field field data 
  3401. */ 
  3402. $_render = apply_filters( "redux/field/{$this->args['opt_name']}/{$field['type']}/render/after", $_render, $field ); 
  3403.  
  3404. /** 
  3405. * filter 'redux/field/{opt_name}/render/after' 
  3406. * @param string rendered field markup 
  3407. * @param array $field field data 
  3408. */ 
  3409. $_render = apply_filters( "redux/field/{$this->args['opt_name']}/render/after", $_render, $field ); 
  3410.  
  3411. ob_end_clean(); 
  3412.  
  3413. //save the values into a unique array in case we need it for dependencies 
  3414. $this->fieldsValues[ $field['id'] ] = ( isset( $value['url'] ) && is_array( $value ) ) ? $value['url'] : $value; 
  3415.  
  3416. //create default data und class string and checks the dependencies of an object 
  3417. $class_string = ''; 
  3418. $data_string = ''; 
  3419.  
  3420. $this->check_dependencies( $field ); 
  3421.  
  3422. /** 
  3423. * action 'redux/field/{opt_name}/{field.type}/fieldset/before/{opt_name}' 
  3424. * @param array $field field data 
  3425. * @param string $value field id 
  3426. */ 
  3427. do_action( "redux/field/{$this->args['opt_name']}/{$field['type']}/fieldset/before/{$this->args['opt_name']}", $field, $value ); 
  3428.  
  3429. /** 
  3430. * action 'redux/field/{opt_name}/fieldset/before/{opt_name}' 
  3431. * @param array $field field data 
  3432. * @param string $value field id 
  3433. */ 
  3434. do_action( "redux/field/{$this->args['opt_name']}/fieldset/before/{$this->args['opt_name']}", $field, $value ); 
  3435.  
  3436. if ( ! isset( $field['fields'] ) || empty( $field['fields'] ) ) { 
  3437. echo '<fieldset id="' . $this->args['opt_name'] . '-' . $field['id'] . '" class="redux-field-container redux-field redux-field-init redux-container-' . $field['type'] . ' ' . $class_string . '" data-id="' . $field['id'] . '" ' . $data_string . ' data-type="' . $field['type'] . '">'; 
  3438.  
  3439. echo $_render; 
  3440.  
  3441. if ( ! empty( $field['desc'] ) ) { 
  3442. $field['description'] = $field['desc']; 
  3443.  
  3444. echo ( isset( $field['description'] ) && $field['type'] != "info" && $field['type'] !== "section" && ! empty( $field['description'] ) ) ? '<div class="description field-desc">' . $field['description'] . '</div>' : ''; 
  3445.  
  3446. if ( ! isset( $field['fields'] ) || empty( $field['fields'] ) ) { 
  3447. echo '</fieldset>'; 
  3448.  
  3449. /** 
  3450. * action 'redux-after-field-{opt_name}' 
  3451. * @deprecated 
  3452. * @param array $field field data 
  3453. * @param string $value field id 
  3454. */ 
  3455. do_action( "redux-after-field-{$this->args['opt_name']}", $field, $value ); // REMOVE 
  3456.  
  3457. /** 
  3458. * action 'redux/field/{opt_name}/{field.type}/fieldset/after/{opt_name}' 
  3459. * @param array $field field data 
  3460. * @param string $value field id 
  3461. */ 
  3462. do_action( "redux/field/{$this->args['opt_name']}/{$field['type']}/fieldset/after/{$this->args['opt_name']}", $field, $value ); 
  3463.  
  3464. /** 
  3465. * action 'redux/field/{opt_name}/fieldset/after/{opt_name}' 
  3466. * @param array $field field data 
  3467. * @param string $value field id 
  3468. */ 
  3469. do_action( "redux/field/{$this->args['opt_name']}/fieldset/after/{$this->args['opt_name']}", $field, $value ); 
  3470. } // _field_input() 
  3471.  
  3472. /** 
  3473. * Can Output CSS 
  3474. * Check if a field meets its requirements before outputting to CSS 
  3475. * @param $field 
  3476. * @return bool 
  3477. */ 
  3478. public function _can_output_css( $field ) { 
  3479. $return = true; 
  3480.  
  3481. $field = apply_filters( "redux/field/{$this->args['opt_name']}/_can_output_css", $field ); 
  3482. if ( isset( $field['force_output'] ) && $field['force_output'] == true ) { 
  3483. return $return; 
  3484.  
  3485. if ( ! empty( $field['required'] ) ) { 
  3486. if ( isset( $field['required'][0] ) ) { 
  3487. if ( ! is_array( $field['required'][0] ) && count( $field['required'] ) == 3 ) { 
  3488. $parentValue = $GLOBALS[ $this->args['global_variable'] ][ $field['required'][0] ]; 
  3489. $checkValue = $field['required'][2]; 
  3490. $operation = $field['required'][1]; 
  3491. $return = $this->compareValueDependencies( $parentValue, $checkValue, $operation ); 
  3492. } else if ( is_array( $field['required'][0] ) ) { 
  3493. foreach ( $field['required'] as $required ) { 
  3494. if ( ! is_array( $required[0] ) && count( $required ) == 3 ) { 
  3495. $parentValue = $GLOBALS[ $this->args['global_variable'] ][ $required[0] ]; 
  3496. $checkValue = $required[2]; 
  3497. $operation = $required[1]; 
  3498. $return = $this->compareValueDependencies( $parentValue, $checkValue, $operation ); 
  3499. if ( ! $return ) { 
  3500. return $return; 
  3501.  
  3502. return $return; 
  3503. } // _can_output_css 
  3504.  
  3505. /** 
  3506. * Checks dependencies between objects based on the $field['required'] array 
  3507. * If the array is set it needs to have exactly 3 entries. 
  3508. * The first entry describes which field should be monitored by the current field. eg: "content" 
  3509. * The second entry describes the comparison parameter. eg: "equals, not, is_larger, is_smaller , contains" 
  3510. * The third entry describes the value that we are comparing against. 
  3511. * Example: if the required array is set to array('content', 'equals', 'Hello World'); then the current 
  3512. * field will only be displayed if the field with id "content" has exactly the value "Hello World" 
  3513. * @param array $field 
  3514. * @return array $params 
  3515. */ 
  3516. public function check_dependencies( $field ) { 
  3517. //$params = array('data_string' => "", 'class_string' => ""); 
  3518.  
  3519. if ( ! empty( $field['required'] ) ) { 
  3520.  
  3521. //$this->folds[$field['id']] = $this->folds[$field['id']] ? $this->folds[$field['id']] : array(); 
  3522. if ( ! isset( $this->required_child[ $field['id'] ] ) ) { 
  3523. $this->required_child[ $field['id'] ] = array(); 
  3524.  
  3525. if ( ! isset( $this->required[ $field['id'] ] ) ) { 
  3526. $this->required[ $field['id'] ] = array(); 
  3527.  
  3528. if ( is_array( $field['required'][0] ) ) { 
  3529. foreach ( $field['required'] as $value ) { 
  3530. if ( is_array( $value ) && count( $value ) == 3 ) { 
  3531. $data = array(); 
  3532. $data['parent'] = $value[0]; 
  3533. $data['operation'] = $value[1]; 
  3534. $data['checkValue'] = $value[2]; 
  3535.  
  3536. $this->required[ $data['parent'] ][ $field['id'] ][] = $data; 
  3537.  
  3538. if ( ! in_array( $data['parent'], $this->required_child[ $field['id'] ] ) ) { 
  3539. $this->required_child[ $field['id'] ][] = $data; 
  3540.  
  3541. $this->checkRequiredDependencies( $field, $data ); 
  3542. } else { 
  3543. $data = array(); 
  3544. $data['parent'] = $field['required'][0]; 
  3545. $data['operation'] = $field['required'][1]; 
  3546. $data['checkValue'] = $field['required'][2]; 
  3547.  
  3548. $this->required[ $data['parent'] ][ $field['id'] ][] = $data; 
  3549.  
  3550. if ( ! in_array( $data['parent'], $this->required_child[ $field['id'] ] ) ) { 
  3551. $this->required_child[ $field['id'] ][] = $data; 
  3552.  
  3553. $this->checkRequiredDependencies( $field, $data ); 
  3554.  
  3555. //return $params; 
  3556.  
  3557. // Compare data for required field 
  3558. private function compareValueDependencies( $parentValue, $checkValue, $operation ) { 
  3559. $return = false; 
  3560. switch ( $operation ) { 
  3561. case '=': 
  3562. case 'equals': 
  3563. $data['operation'] = "="; 
  3564.  
  3565. if (is_array($parentValue)) { 
  3566. foreach($parentValue as $idx => $val) { 
  3567. if (is_array($checkValue)) { 
  3568. foreach($checkValue as $i => $v) { 
  3569. if ($val == $v) { 
  3570. $return = true; 
  3571. } else { 
  3572. if ($val == $checkValue) { 
  3573. $return = true; 
  3574. } else { 
  3575. if (is_array($checkValue)) { 
  3576. foreach($checkValue as $i => $v) { 
  3577. if ($parentValue == $v) { 
  3578. $return = true; 
  3579. } else { 
  3580. if ($parentValue == $checkValue) { 
  3581. $return = true; 
  3582. break; 
  3583.  
  3584. case '!=': 
  3585. case 'not': 
  3586. $data['operation'] = "!=="; 
  3587. if (is_array($parentValue)) { 
  3588. foreach($parentValue as $idx => $val) { 
  3589. if (is_array($checkValue)) { 
  3590. foreach($checkValue as $i => $v) { 
  3591. if ($val != $v) { 
  3592. $return = true; 
  3593. } else { 
  3594. if ($val != $checkValue) { 
  3595. $return = true; 
  3596. } else { 
  3597. if (is_array($checkValue)) { 
  3598. foreach($checkValue as $i => $v) { 
  3599. if ($parentValue != $v) { 
  3600. $return = true; 
  3601. } else { 
  3602. if ($parentValue != $checkValue) { 
  3603. $return = true; 
  3604.  
  3605. // if ( is_array( $checkValue ) ) { 
  3606. // if ( ! in_array( $parentValue, $checkValue ) ) { 
  3607. // $return = true; 
  3608. // } 
  3609. // } else { 
  3610. // if ( $parentValue != $checkValue ) { 
  3611. // $return = true; 
  3612. // } else if ( is_array( $parentValue ) ) { 
  3613. // if ( ! in_array( $checkValue, $parentValue ) ) { 
  3614. // $return = true; 
  3615. // } 
  3616. // } 
  3617. // } 
  3618. break; 
  3619. case '>': 
  3620. case 'greater': 
  3621. case 'is_larger': 
  3622. $data['operation'] = ">"; 
  3623. if ( $parentValue > $checkValue ) { 
  3624. $return = true; 
  3625. break; 
  3626. case '>=': 
  3627. case 'greater_equal': 
  3628. case 'is_larger_equal': 
  3629. $data['operation'] = ">="; 
  3630. if ( $parentValue >= $checkValue ) { 
  3631. $return = true; 
  3632. break; 
  3633. case '<': 
  3634. case 'less': 
  3635. case 'is_smaller': 
  3636. $data['operation'] = "<"; 
  3637. if ( $parentValue < $checkValue ) { 
  3638. $return = true; 
  3639. break; 
  3640. case '<=': 
  3641. case 'less_equal': 
  3642. case 'is_smaller_equal': 
  3643. $data['operation'] = "<="; 
  3644. if ( $parentValue <= $checkValue ) { 
  3645. $return = true; 
  3646. break; 
  3647. case 'contains': 
  3648. if (is_array($parentValue)) { 
  3649. $parentValue = implode(', ', $parentValue); 
  3650.  
  3651. if (is_array($checkValue)) { 
  3652. foreach($checkValue as $idx => $opt) { 
  3653. if ( strpos( $parentValue, $opt ) !== false ) { 
  3654. $return = true; 
  3655. } else { 
  3656. if ( strpos( $parentValue, $checkValue ) !== false ) { 
  3657. $return = true; 
  3658.  
  3659. break; 
  3660. case 'doesnt_contain': 
  3661. case 'not_contain': 
  3662. if (is_array($parentValue)) { 
  3663. $parentValue = implode(', ', $parentValue); 
  3664.  
  3665. if (is_array($checkValue)) { 
  3666. foreach($checkValue as $idx => $opt) { 
  3667. if ( strpos( $parentValue, $opt ) === false ) { 
  3668. $return = true; 
  3669. } else { 
  3670. if ( strpos( $parentValue, $checkValue ) === false ) { 
  3671. $return = true; 
  3672.  
  3673. break; 
  3674. case 'is_empty_or': 
  3675. if ( empty( $parentValue ) || $parentValue == $checkValue ) { 
  3676. $return = true; 
  3677. break; 
  3678. case 'not_empty_and': 
  3679. if ( ! empty( $parentValue ) && $parentValue != $checkValue ) { 
  3680. $return = true; 
  3681. break; 
  3682. case 'is_empty': 
  3683. case 'empty': 
  3684. case '!isset': 
  3685. if ( empty( $parentValue ) || $parentValue == "" || $parentValue == null ) { 
  3686. $return = true; 
  3687. break; 
  3688. case 'not_empty': 
  3689. case '!empty': 
  3690. case 'isset': 
  3691. if ( ! empty( $parentValue ) && $parentValue != "" && $parentValue != null ) { 
  3692. $return = true; 
  3693. break; 
  3694.  
  3695. return $return; 
  3696.  
  3697. private function checkRequiredDependencies( $field, $data ) { 
  3698. //required field must not be hidden. otherwise hide this one by default 
  3699.  
  3700. if ( ! in_array( $data['parent'], $this->fieldsHidden ) && ( ! isset( $this->folds[ $field['id'] ] ) || $this->folds[ $field['id'] ] != "hide" ) ) { 
  3701. if ( isset( $this->options[ $data['parent'] ] ) ) { 
  3702. //echo $data['parent']; 
  3703. $return = $this->compareValueDependencies( $this->options[ $data['parent'] ], $data['checkValue'], $data['operation'] ); 
  3704. //$return = $this->compareValueDependencies( $data['parent'], $data['checkValue'], $data['operation'] ); 
  3705.  
  3706. if ( ( isset( $return ) && $return ) && ( ! isset( $this->folds[ $field['id'] ] ) || $this->folds[ $field['id'] ] != "hide" ) ) { 
  3707. $this->folds[ $field['id'] ] = "show"; 
  3708. } else { 
  3709. $this->folds[ $field['id'] ] = "hide"; 
  3710. if ( ! in_array( $field['id'], $this->fieldsHidden ) ) { 
  3711. $this->fieldsHidden[] = $field['id']; 
  3712.  
  3713. /** 
  3714. * converts an array into a html data string 
  3715. * @param array $data example input: array('id'=>'true') 
  3716. * @return string $data_string example output: data-id='true' 
  3717. */ 
  3718. public function create_data_string( $data = array() ) { 
  3719. $data_string = ""; 
  3720.  
  3721. foreach ( $data as $key => $value ) { 
  3722. if ( is_array( $value ) ) { 
  3723. $value = implode( "|", $value ); 
  3724. $data_string .= " data-$key='$value' "; 
  3725.  
  3726. return $data_string; 
  3727. } // ReduxFramework