PageRenderTime 49ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/htdocs/wp-content/plugins/breadcrumb-navxt/includes/mtekk_adminkit.php

https://bitbucket.org/dkrzos/phc
PHP | 1015 lines | 607 code | 6 blank | 402 comment | 74 complexity | 360154ad3bfc9c8c8849f31ed4fc3703 MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. /*
  3. Copyright 2009-2013 John Havlik (email : mtekkmonkey@gmail.com)
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  15. */
  16. require_once(dirname(__FILE__) . '/block_direct_access.php');
  17. abstract class mtekk_adminKit
  18. {
  19. private $__version = '1.1';
  20. protected $version;
  21. protected $full_name;
  22. protected $short_name;
  23. protected $plugin_basename;
  24. protected $access_level = 'manage_options';
  25. protected $identifier;
  26. protected $unique_prefix;
  27. protected $opt = array();
  28. protected $message;
  29. protected $support_url;
  30. protected $allowed_html;
  31. function __construct()
  32. {
  33. //Admin Init Hook
  34. add_action('admin_init', array($this, 'init'));
  35. //WordPress Admin interface hook
  36. add_action('admin_menu', array($this, 'add_page'));
  37. //Installation Script hook
  38. //register_activation_hook($this->plugin_basename, array($this, 'install'));
  39. add_action('activate_' . $this->plugin_basename, array($this, 'install'));
  40. //Initilizes l10n domain
  41. $this->local();
  42. add_action('wp_loaded', array($this, 'wp_loaded'));
  43. //Register Help Output
  44. //add_action('add_screen_help_and_options', array($this, 'help'));
  45. }
  46. function wp_loaded()
  47. {
  48. //Filter our allowed html tags
  49. $this->allowed_html = apply_filters($this->unique_prefix . '_allowed_html', wp_kses_allowed_html('post'));
  50. }
  51. /**
  52. * Returns the internal mtekk_admin_class version
  53. */
  54. function get_admin_class_version()
  55. {
  56. return $__version;
  57. }
  58. /**
  59. * Return the URL of the settings page for the plugin
  60. */
  61. function admin_url()
  62. {
  63. return admin_url('options-general.php?page=' . $this->identifier);
  64. }
  65. /**
  66. * A wrapper for nonced_anchor returns a nonced anchor for admin pages
  67. *
  68. * @param string $mode The nonce "mode", a unique string at the end of the standardized nonce identifier
  69. * @param string $title (optional) The text to use in the title portion of the anchor
  70. * @param string $text (optional) The text that will be surrounded by the anchor tags
  71. * @return string the assembled anchor
  72. */
  73. function admin_anchor($mode, $title = '', $text = '')
  74. {
  75. return $this->nonced_anchor($this->admin_url(), 'admin_' . $mode, 'true', $title, $text);
  76. }
  77. /**
  78. * Returns a properly formed nonced anchor to the specified URI
  79. *
  80. * @param string $uri The URI that the anchor should be for
  81. * @param string $mode The nonce "mode", a unique string at the end of the standardized nonce identifier
  82. * @param mixed $value (optional) The value to place in the query string
  83. * @param string $title (optional) The text to use in the title portion of the anchor
  84. * @param string $text (optional) The text that will be surrounded by the anchor tags
  85. * @param string $extras (optional) This text is placed within the opening anchor tag, good for adding id, classe, rel field
  86. * @return string the assembled anchor
  87. */
  88. function nonced_anchor($uri, $mode, $value = 'true', $title = '', $text = '', $extras = '')
  89. {
  90. //Assemble our url, nonce and all
  91. $url = wp_nonce_url($uri . '&' . $this->unique_prefix . '_' . $mode . '=' . $value, $this->unique_prefix . '_' . $mode);
  92. //Return a valid anchor
  93. return ' <a title="' . $title . '" href="' . $url . '" '. $extras . '>' . $text . '</a>';
  94. }
  95. /**
  96. * Abstracts the check_admin_referer so that all the end user has to supply is the mode
  97. *
  98. * @param string $mode The specific nonce "mode" (see nonced_anchor) that is being checked
  99. */
  100. function check_nonce($mode)
  101. {
  102. check_admin_referer($this->unique_prefix . '_' . $mode);
  103. }
  104. function init()
  105. {
  106. //Admin Options reset hook
  107. if(isset($_POST[$this->unique_prefix . '_admin_reset']))
  108. {
  109. //Run the reset function on init if reset form has been submitted
  110. $this->opts_reset();
  111. }
  112. //Admin Options export hook
  113. else if(isset($_POST[$this->unique_prefix . '_admin_export']))
  114. {
  115. //Run the export function on init if export form has been submitted
  116. $this->opts_export();
  117. }
  118. //Admin Options import hook
  119. else if(isset($_FILES[$this->unique_prefix . '_admin_import_file']) && !empty($_FILES[$this->unique_prefix . '_admin_import_file']['name']))
  120. {
  121. //Run the import function on init if import form has been submitted
  122. $this->opts_import();
  123. }
  124. //Admin Options rollback hook
  125. else if(isset($_GET[$this->unique_prefix . '_admin_undo']))
  126. {
  127. //Run the rollback function on init if undo button has been pressed
  128. $this->opts_undo();
  129. }
  130. //Admin Options upgrade hook
  131. else if(isset($_GET[$this->unique_prefix . '_admin_upgrade']))
  132. {
  133. //Run the upgrade function on init if upgrade button has been pressed
  134. $this->opts_upgrade_wrapper();
  135. }
  136. //Admin Options fix hook
  137. else if(isset($_GET[$this->unique_prefix . '_admin_fix']))
  138. {
  139. //Run the options fix function on init if fix button has been pressed
  140. $this->opts_upgrade_wrapper();
  141. }
  142. //Add in the nice "settings" link to the plugins page
  143. add_filter('plugin_action_links', array($this, 'filter_plugin_actions'), 10, 2);
  144. //Register JS for tabs
  145. wp_register_script('mtekk_adminkit_tabs', plugins_url('/mtekk_adminkit_tabs.js', dirname(__FILE__) . '/mtekk_adminkit_tabs.js'), array('jquery-ui-tabs'));
  146. //Register CSS for tabs
  147. wp_register_style('mtekk_adminkit_tabs', plugins_url('/mtekk_adminkit_tabs.css', dirname(__FILE__) . '/mtekk_adminkit_tabs.css'));
  148. //Register options
  149. register_setting($this->unique_prefix . '_options', $this->unique_prefix . '_options', '');
  150. //Synchronize up our settings with the database as we're done modifying them now
  151. $this->opt = mtekk_adminKit::parse_args(get_option($this->unique_prefix . '_options'), $this->opt);
  152. //Run the opts fix filter
  153. $this->opts_fix($this->opt);
  154. }
  155. /**
  156. * Adds the adminpage the menu and the nice little settings link
  157. * TODO: make this more generic for easier extension
  158. */
  159. function add_page()
  160. {
  161. //Add the submenu page to "settings" menu
  162. $hookname = add_submenu_page('options-general.php', __($this->full_name, $this->identifier), $this->short_name, $this->access_level, $this->identifier, array($this, 'admin_page'));
  163. // check capability of user to manage options (access control)
  164. if(current_user_can($this->access_level))
  165. {
  166. //Register admin_head-$hookname callback
  167. add_action('admin_head-' . $hookname, array($this, 'admin_head'));
  168. //Register admin_print_styles-$hookname callback
  169. add_action('admin_print_styles-' . $hookname, array($this, 'admin_styles'));
  170. //Register admin_print_scripts-$hookname callback
  171. add_action('admin_print_scripts-' . $hookname, array($this, 'admin_scripts'));
  172. //Register Help Output
  173. add_action('load-' . $hookname, array($this, 'help'));
  174. }
  175. }
  176. /**
  177. * Initilizes localization textdomain for translations (if applicable)
  178. *
  179. * Will conditionally load the textdomain for translations. This is here for
  180. * plugins that span multiple files and have localization in more than one file
  181. *
  182. * @return void
  183. */
  184. function local()
  185. {
  186. global $l10n;
  187. // the global and the check might become obsolete in
  188. // further wordpress versions
  189. // @see https://core.trac.wordpress.org/ticket/10527
  190. if(!isset($l10n[$this->identifier]))
  191. {
  192. load_plugin_textdomain($this->identifier, false, $this->identifier . '/languages');
  193. }
  194. }
  195. /**
  196. * Places in a link to the settings page in the plugins listing entry
  197. *
  198. * @param array $links An array of links that are output in the listing
  199. * @param string $file The file that is currently in processing
  200. * @return array Array of links that are output in the listing.
  201. */
  202. function filter_plugin_actions($links, $file)
  203. {
  204. //Make sure we are adding only for the current plugin
  205. if($file == $this->plugin_basename)
  206. {
  207. //Add our link to the end of the array to better integrate into the WP 2.8 plugins page
  208. $links[] = '<a href="' . $this->admin_url() . '">' . __('Settings') . '</a>';
  209. }
  210. return $links;
  211. }
  212. /**
  213. * Checks to see if the plugin has been fully installed
  214. *
  215. * @return bool whether or not the plugin has been installed
  216. */
  217. function is_installed()
  218. {
  219. }
  220. /**
  221. * This sets up and upgrades the database settings, runs on every activation
  222. */
  223. function install()
  224. {
  225. //Call our little security function
  226. $this->security();
  227. //Try retrieving the options from the database
  228. $opts = get_option($this->unique_prefix . '_options');
  229. //If there are no settings, copy over the default settings
  230. if(!is_array($opts))
  231. {
  232. //Grab defaults from the object
  233. $opts = $this->opt;
  234. //Add the options
  235. add_option($this->unique_prefix . '_options', $opts);
  236. add_option($this->unique_prefix . '_options_bk', $opts, '', 'no');
  237. //Add the version, no need to autoload the db version
  238. add_option($this->unique_prefix . '_version', $this->version, '', 'no');
  239. }
  240. else
  241. {
  242. //Retrieve the database version
  243. $db_version = get_option($this->unique_prefix . '_version');
  244. if($this->version !== $db_version)
  245. {
  246. //Run the settings update script
  247. $this->opts_upgrade($opts, $db_version);
  248. //Always have to update the version
  249. update_option($this->unique_prefix . '_version', $this->version);
  250. //Store the options
  251. update_option($this->unique_prefix . '_options', $this->opt);
  252. }
  253. }
  254. }
  255. /**
  256. * This removes database settings upon deletion of the plugin from WordPress
  257. */
  258. function uninstall()
  259. {
  260. //Remove the option array setting
  261. delete_option($this->unique_prefix . '_options');
  262. //Remove the option backup array setting
  263. delete_option($this->unique_prefix . '_options_bk');
  264. //Remove the version setting
  265. delete_option($this->unique_prefix . '_version');
  266. }
  267. /**
  268. * Compares the supplided version with the internal version, places an upgrade warning if there is a missmatch
  269. * TODO: change this to being auto called in admin_init action
  270. */
  271. function version_check($version)
  272. {
  273. //Do a quick version check
  274. if(version_compare($version, $this->version, '<') && is_array($this->opt))
  275. {
  276. //Throw an error since the DB version is out of date
  277. $this->message['error'][] = __('Your settings are out of date.', $this->identifier) . $this->admin_anchor('upgrade', __('Migrate the settings now.', $this->identifier), __('Migrate now.', $this->identifier));
  278. //Output any messages that there may be
  279. $this->message();
  280. return false;
  281. }
  282. //Do a quick version check
  283. else if(version_compare($version, $this->version, '>') && is_array($this->opt))
  284. {
  285. //Throw an error since the DB version is out of date
  286. $this->message['error'][] = __('Your settings are for a newer version.', $this->identifier) . $this->admin_anchor('upgrade', __('Migrate the settings now.', $this->identifier), __('Migrate now.', $this->identifier));
  287. //Output any messages that there may be
  288. $this->message();
  289. return true;
  290. }
  291. else if(!is_array($this->opt))
  292. {
  293. //Throw an error since it appears the options were never registered
  294. $this->message['error'][] = __('Your plugin install is incomplete.', $this->identifier) . $this->admin_anchor('upgrade', __('Load default settings now.', $this->identifier), __('Complete now.', $this->identifier));
  295. //Output any messages that there may be
  296. $this->message();
  297. return false;
  298. }
  299. else if(!$this->opts_validate($this->opt))
  300. {
  301. //Throw an error since it appears the options contain invalid data
  302. $this->message['error'][] = __('Your plugin settings are invalid.', $this->identifier) . $this->admin_anchor('fix', __('Attempt to fix settings now.', $this->identifier), __('Fix now.', $this->identifier));
  303. //Output any messages that there may be
  304. $this->message();
  305. return false;
  306. }
  307. return true;
  308. }
  309. /**
  310. * A prototype function. End user should override if they need this feature.
  311. */
  312. function opts_validate(&$opts)
  313. {
  314. return true;
  315. }
  316. /**
  317. * A prototype function. End user should override if they need this feature.
  318. *
  319. * @param array $opts
  320. */
  321. function opts_fix(&$opts)
  322. {
  323. }
  324. /**
  325. * Synchronizes the backup options entry with the current options entry
  326. */
  327. function opts_backup()
  328. {
  329. //Set the backup options in the DB to the current options
  330. update_option($this->unique_prefix . '_options_bk', get_option($this->unique_prefix . '_options'));
  331. }
  332. /**
  333. * Runs recursivly through the opts array, sanitizing and merging in updates from the $input array
  334. *
  335. * @param array $opts good, clean array
  336. * @param array $input unsanitzed input array, not trusted at all
  337. */
  338. protected function opts_update_loop(&$opts, $input)
  339. {
  340. //Loop through all of the existing options (avoids random setting injection)
  341. foreach($opts as $option => $value)
  342. {
  343. //If we have an array, dive into another recursive loop
  344. if(isset($input[$option]) && is_array($value))
  345. {
  346. $this->opts_update_loop($opts[$option], $input[$option]);
  347. }
  348. //We must check for unset settings, but booleans are ok to be unset
  349. else if(isset($input[$option]) || $option[0] == 'b')
  350. {
  351. switch($option[0])
  352. {
  353. //Handle the boolean options
  354. case 'b':
  355. $opts[$option] = isset($input[$option]);
  356. break;
  357. //Handle the integer options
  358. case 'i':
  359. $opts[$option] = (int) $input[$option];
  360. break;
  361. //Handle the absolute integer options
  362. case 'a':
  363. $opts[$option] = absint($input[$option]);
  364. break;
  365. //Handle the floating point options
  366. case 'f':
  367. $opts[$option] = (float) $input[$option];
  368. break;
  369. //Handle the HTML options
  370. case 'h':
  371. //May be better to use wp_kses here
  372. $opts[$option] = wp_kses(stripslashes($input[$option]), $this->allowed_html);
  373. break;
  374. //Handle the HTML options that must not be null
  375. case 'H':
  376. if(isset($input[$option]))
  377. {
  378. $opts[$option] = wp_kses(stripslashes($input[$option]), $this->allowed_html);
  379. }
  380. break;
  381. //Handle the text options that must not be null
  382. case 'S':
  383. if(isset($input[$option]))
  384. {
  385. $opts[$option] = esc_html($input[$option]);
  386. }
  387. break;
  388. //Treat everything else as a normal string
  389. case 's':
  390. default:
  391. $opts[$option] = esc_html($input[$option]);
  392. }
  393. }
  394. }
  395. }
  396. /**
  397. * A better version of parse_args, will recrusivly follow arrays
  398. *
  399. * @param mixed $args The arguments to be parsed
  400. * @param mixed $defaults (optional) The default values to validate against
  401. * @return mixed
  402. */
  403. static function parse_args($args, $defaults = '')
  404. {
  405. if(is_object($args))
  406. {
  407. $r = get_object_vars($args);
  408. }
  409. else if(is_array($args))
  410. {
  411. $r =& $args;
  412. }
  413. else
  414. {
  415. wp_parse_str($args, $r);
  416. }
  417. if(is_array($defaults))
  418. {
  419. return mtekk_adminKit::array_merge_recursive($defaults, $r);
  420. }
  421. return $r;
  422. }
  423. /**
  424. * An alternate version of array_merge_recursive, less flexible
  425. * still recursive, ~2x faster than the more flexible version
  426. *
  427. * @param array $arg1 first array
  428. * @param array $arg2 second array to merge into $arg1
  429. * @return array
  430. */
  431. static function array_merge_recursive($arg1, $arg2)
  432. {
  433. foreach($arg2 as $key => $value)
  434. {
  435. if(array_key_exists($key, $arg1) && is_array($value))
  436. {
  437. $arg1[$key] = mtekk_adminKit::array_merge_recursive($arg1[$key], $value);
  438. }
  439. else
  440. {
  441. $arg1[$key] = $value;
  442. }
  443. }
  444. return $arg1;
  445. }
  446. /**
  447. * An action that fires just before the options backup, use to add in dynamically detected options
  448. *
  449. * @param array $opts the options array, passed in by reference
  450. * @return null
  451. */
  452. function opts_update_prebk(&$opts)
  453. {
  454. //Just a prototype function
  455. }
  456. /**
  457. * Updates the database settings from the webform
  458. */
  459. function opts_update()
  460. {
  461. //Do some security related thigns as we are not using the normal WP settings API
  462. $this->security();
  463. //Do a nonce check, prevent malicious link/form problems
  464. check_admin_referer($this->unique_prefix . '_options-options');
  465. //Update local options from database
  466. $this->opt = mtekk_adminKit::parse_args(get_option($this->unique_prefix . '_options'), $this->opt);
  467. $this->opts_update_prebk($this->opt);
  468. //Update our backup options
  469. update_option($this->unique_prefix . '_options_bk', $this->opt);
  470. //Grab our incomming array (the data is dirty)
  471. $input = $_POST[$this->unique_prefix . '_options'];
  472. //Run the update loop
  473. $this->opts_update_loop($this->opt, $input);
  474. //Commit the option changes
  475. update_option($this->unique_prefix . '_options', $this->opt);
  476. //Check if known settings match attempted save
  477. if(count(array_diff_key($input, $this->opt)) == 0)
  478. {
  479. //Let the user know everything went ok
  480. $this->message['updated fade'][] = __('Settings successfully saved.', $this->identifier) . $this->admin_anchor('undo', __('Undo the options save.', $this->identifier), __('Undo', $this->identifier));
  481. }
  482. else
  483. {
  484. //Let the user know the following were not saved
  485. $this->message['updated fade'][] = __('Some settings were not saved.', $this->identifier) . $this->admin_anchor('undo', __('Undo the options save.', $this->identifier), __('Undo', $this->identifier));
  486. $temp = __('The following settings were not saved:', $this->identifier);
  487. foreach(array_diff_key($input, $this->opt) as $setting => $value)
  488. {
  489. $temp .= '<br />' . $setting;
  490. }
  491. $this->message['updated fade'][] = $temp . '<br />' . sprintf(__('Please include this message in your %sbug report%s.', $this->identifier),'<a title="' . sprintf(__('Go to the %s support post for your version.', $this->identifier), $this->short_name) . '" href="' . $this->support_url . $this->version . '/#respond">', '</a>');
  492. }
  493. add_action('admin_notices', array($this, 'message'));
  494. }
  495. /**
  496. * Exports a XML options document
  497. */
  498. function opts_export()
  499. {
  500. //Do a nonce check, prevent malicious link/form problems
  501. check_admin_referer($this->unique_prefix . '_admin_import_export');
  502. //Update our internal settings
  503. $this->opt = get_option($this->unique_prefix . '_options');
  504. //Create a DOM document
  505. $dom = new DOMDocument('1.0', 'UTF-8');
  506. //Adds in newlines and tabs to the output
  507. $dom->formatOutput = true;
  508. //We're not using a DTD therefore we need to specify it as a standalone document
  509. $dom->xmlStandalone = true;
  510. //Add an element called options
  511. $node = $dom->createElement('options');
  512. $parnode = $dom->appendChild($node);
  513. //Add a child element named plugin
  514. $node = $dom->createElement('plugin');
  515. $plugnode = $parnode->appendChild($node);
  516. //Add some attributes that identify the plugin and version for the options export
  517. $plugnode->setAttribute('name', $this->short_name);
  518. $plugnode->setAttribute('version', $this->version);
  519. //Change our headder to text/xml for direct save
  520. header('Cache-Control: public');
  521. //The next two will cause good browsers to download instead of displaying the file
  522. header('Content-Description: File Transfer');
  523. header('Content-disposition: attachemnt; filename=' . $this->unique_prefix . '_settings.xml');
  524. header('Content-Type: text/xml');
  525. //Loop through the options array
  526. foreach($this->opt as $key=>$option)
  527. {
  528. //Add a option tag under the options tag, store the option value
  529. $node = $dom->createElement('option', htmlentities($option, ENT_COMPAT, 'UTF-8'));
  530. $newnode = $plugnode->appendChild($node);
  531. //Change the tag's name to that of the stored option
  532. $newnode->setAttribute('name', $key);
  533. }
  534. //Prepair the XML for output
  535. $output = $dom->saveXML();
  536. //Let the browser know how long the file is
  537. header('Content-Length: ' . strlen($output)); // binary length
  538. //Output the file
  539. echo $output;
  540. //Prevent WordPress from continuing on
  541. die();
  542. }
  543. /**
  544. * Imports a XML options document
  545. */
  546. function opts_import()
  547. {
  548. //Our quick and dirty error supressor
  549. function error($errno, $errstr, $eerfile, $errline)
  550. {
  551. return true;
  552. }
  553. //Do a nonce check, prevent malicious link/form problems
  554. check_admin_referer($this->unique_prefix . '_admin_import_export');
  555. //Set the backup options in the DB to the current options
  556. $this->opts_backup();
  557. //Create a DOM document
  558. $dom = new DOMDocument('1.0', 'UTF-8');
  559. //We want to catch errors ourselves
  560. set_error_handler('error');
  561. //Load the user uploaded file, handle failure gracefully
  562. if($dom->load($_FILES[$this->unique_prefix . '_admin_import_file']['tmp_name']))
  563. {
  564. $opts_temp = array();
  565. $version = '';
  566. //Have to use an xpath query otherwise we run into problems
  567. $xpath = new DOMXPath($dom);
  568. $option_sets = $xpath->query('plugin');
  569. //Loop through all of the xpath query results
  570. foreach($option_sets as $options)
  571. {
  572. //We only want to import options for only this plugin
  573. if($options->getAttribute('name') === $this->short_name)
  574. {
  575. //Grab the file version
  576. $version = explode('.', $options->getAttribute('version'));
  577. //Loop around all of the options
  578. foreach($options->getelementsByTagName('option') as $child)
  579. {
  580. //Place the option into the option array, DOMDocument decodes html entities for us
  581. $opts_temp[$child->getAttribute('name')] = $child->nodeValue;
  582. }
  583. }
  584. }
  585. //Make sure we safely import and upgrade settings if needed
  586. $this->opts_upgrade($opts_temp, $version);
  587. //Commit the loaded options to the database
  588. update_option($this->unique_prefix . '_options', $this->opt);
  589. //Everything was successful, let the user know
  590. $this->message['updated fade'][] = __('Settings successfully imported from the uploaded file.', $this->identifier) . $this->admin_anchor('undo', __('Undo the options import.', $this->identifier), __('Undo', $this->identifier));
  591. }
  592. else
  593. {
  594. //Throw an error since we could not load the file for various reasons
  595. $this->message['error'][] = __('Importing settings from file failed.', $this->identifier);
  596. }
  597. //Reset to the default error handler after we're done
  598. restore_error_handler();
  599. //Output any messages that there may be
  600. add_action('admin_notices', array($this, 'message'));
  601. }
  602. /**
  603. * Resets the database settings array to the default set in opt
  604. */
  605. function opts_reset()
  606. {
  607. //Do a nonce check, prevent malicious link/form problems
  608. check_admin_referer($this->unique_prefix . '_admin_import_export');
  609. //Set the backup options in the DB to the current options
  610. $this->opts_backup();
  611. //Load in the hard coded default option values
  612. update_option($this->unique_prefix . '_options', $this->opt);
  613. //Reset successful, let the user know
  614. $this->message['updated fade'][] = __('Settings successfully reset to the default values.', $this->identifier) . $this->admin_anchor('undo', __('Undo the options reset.', $this->identifier), __('Undo', $this->identifier));
  615. add_action('admin_notices', array($this, 'message'));
  616. }
  617. /**
  618. * Undos the last settings save/reset/import
  619. */
  620. function opts_undo()
  621. {
  622. //Do a nonce check, prevent malicious link/form problems
  623. check_admin_referer($this->unique_prefix . '_admin_undo');
  624. //Set the options array to the current options
  625. $opt = get_option($this->unique_prefix . '_options');
  626. //Set the options in the DB to the backup options
  627. update_option($this->unique_prefix . '_options', get_option($this->unique_prefix . '_options_bk'));
  628. //Set the backup options to the undone options
  629. update_option($this->unique_prefix . '_options_bk', $opt);
  630. //Send the success/undo message
  631. $this->message['updated fade'][] = __('Settings successfully undid the last operation.', $this->identifier) . $this->admin_anchor('undo', __('Undo the last undo operation.', $this->identifier), __('Undo', $this->identifier));
  632. add_action('admin_notices', array($this, 'message'));
  633. }
  634. /**
  635. * Upgrades input options array, sets to $this->opt, designed to be overwritten
  636. *
  637. * @param array $opts
  638. * @param string $version the version of the passed in options
  639. */
  640. function opts_upgrade($opts, $version)
  641. {
  642. //We don't support using newer versioned option files in older releases
  643. if(version_compare($this->version, $version, '>='))
  644. {
  645. $this->opt = $opts;
  646. }
  647. }
  648. /**
  649. * Forces a database settings upgrade
  650. */
  651. function opts_upgrade_wrapper()
  652. {
  653. //Do a nonce check, prevent malicious link/form problems
  654. check_admin_referer($this->unique_prefix . '_admin_upgrade');
  655. //Grab the database options
  656. $opts = get_option($this->unique_prefix . '_options');
  657. if(is_array($opts))
  658. {
  659. //Feed the just read options into the upgrade function
  660. $this->opts_upgrade($opts, get_option($this->unique_prefix . '_version'));
  661. //Always have to update the version
  662. update_option($this->unique_prefix . '_version', $this->version);
  663. //Store the options
  664. update_option($this->unique_prefix . '_options', $this->opt);
  665. //Send the success message
  666. $this->message['updated fade'][] = __('Settings successfully migrated.', $this->identifier);
  667. }
  668. else
  669. {
  670. //Run the install script
  671. $this->install();
  672. //Send the success message
  673. $this->message['updated fade'][] = __('Default settings successfully installed.', $this->identifier);
  674. }
  675. add_action('admin_notices', array($this, 'message'));
  676. }
  677. /**
  678. * help action hook function, meant to be overridden
  679. *
  680. * @return string
  681. *
  682. */
  683. function help()
  684. {
  685. $screen = get_current_screen();
  686. //Add contextual help on current screen
  687. if($screen->id == 'settings_page_' . $this->identifier)
  688. {
  689. }
  690. }
  691. /**
  692. * Prints to screen all of the messages stored in the message member variable
  693. */
  694. function message()
  695. {
  696. if(count($this->message))
  697. {
  698. //Loop through our message classes
  699. foreach($this->message as $key => $class)
  700. {
  701. //Loop through the messages in the current class
  702. foreach($class as $message)
  703. {
  704. printf('<div class="%s"><p>%s</p></div>', $key, $message);
  705. }
  706. }
  707. }
  708. $this->message = array();
  709. }
  710. /**
  711. * Function prototype to prevent errors
  712. */
  713. function admin_styles()
  714. {
  715. }
  716. /**
  717. * Function prototype to prevent errors
  718. */
  719. function admin_scripts()
  720. {
  721. }
  722. /**
  723. * Function prototype to prevent errors
  724. */
  725. function admin_head()
  726. {
  727. }
  728. /**
  729. * Function prototype to prevent errors
  730. */
  731. function admin_page()
  732. {
  733. //Admin Options update hook
  734. if(isset($_POST[$this->unique_prefix . '_admin_options']))
  735. {
  736. //Temporarily add update function on init if form has been submitted
  737. $this->opts_update();
  738. }
  739. }
  740. /**
  741. * Function prototype to prevent errors
  742. */
  743. protected function _get_help_text()
  744. {
  745. }
  746. /**
  747. * Returns a valid xHTML element ID
  748. *
  749. * @param object $option
  750. * @return
  751. */
  752. function get_valid_id($option)
  753. {
  754. if(is_numeric($option[0]))
  755. {
  756. return 'p' . $option;
  757. }
  758. else
  759. {
  760. return $option;
  761. }
  762. }
  763. function import_form()
  764. {
  765. $form = '<div id="mtekk_admin_import_export_relocate">';
  766. $form .= sprintf('<form action="options-general.php?page=%s" method="post" enctype="multipart/form-data" id="%s_admin_upload">', $this->identifier, $this->unique_prefix);
  767. $form .= wp_nonce_field($this->unique_prefix . '_admin_import_export', '_wpnonce', true, false);
  768. $form .= sprintf('<fieldset id="import_export" class="%s_options">', $this->unique_prefix);
  769. $form .= '<p>' . __('Import settings from a XML file, export the current settings to a XML file, or reset to the default settings.', $this->identifier) . '</p>';
  770. $form .= '<table class="form-table"><tr valign="top"><th scope="row">';
  771. $form .= sprintf('<label for="%s_admin_import_file">', $this->unique_prefix);
  772. $form .= __('Settings File', $this->identifier);
  773. $form .= '</label></th><td>';
  774. $form .= sprintf('<input type="file" name="%s_admin_import_file" id="%s_admin_import_file" size="32" /><p class="description">', $this->unique_prefix, $this->unique_prefix);
  775. $form .= __('Select a XML settings file to upload and import settings from.', 'breadcrumb_navxt');
  776. $form .= '</p></td></tr></table><p class="submit">';
  777. $form .= sprintf('<input type="submit" class="button" name="%s_admin_import" value="' . __('Import', $this->identifier) . '"/>', $this->unique_prefix, $this->unique_prefix);
  778. $form .= sprintf('<input type="submit" class="button" name="%s_admin_export" value="' . __('Export', $this->identifier) . '"/>', $this->unique_prefix);
  779. $form .= sprintf('<input type="submit" class="button" name="%s_admin_reset" value="' . __('Reset', $this->identifier) . '"/>', $this->unique_prefix, $this->unique_prefix);
  780. $form .= '</p></fieldset></form></div>';
  781. return $form;
  782. }
  783. /**
  784. * This will output a well formed hidden option
  785. *
  786. * @param string $option
  787. * @return
  788. */
  789. function input_hidden($option)
  790. {
  791. $optid = $this->get_valid_id($option);?>
  792. <input type="hidden" name="<?php echo $this->unique_prefix . '_options[' . $option;?>]" id="<?php echo $optid;?>" value="<?php echo htmlentities($this->opt[$option], ENT_COMPAT, 'UTF-8');?>"/>
  793. <?php
  794. }
  795. /**
  796. * This will output a well formed table row for a text input
  797. *
  798. * @param string $label
  799. * @param string $option
  800. * @param string $class [optional]
  801. * @param bool $disable [optional]
  802. * @param string $description [optional]
  803. * @return
  804. */
  805. function input_text($label, $option, $class = 'regular-text', $disable = false, $description = '')
  806. {
  807. $optid = $this->get_valid_id($option);
  808. if($disable)
  809. {?>
  810. <input type="hidden" name="<?php echo $this->unique_prefix . '_options[' . $option;?>]" value="<?php echo htmlentities($this->opt[$option], ENT_COMPAT, 'UTF-8');?>" />
  811. <?php } ?>
  812. <tr valign="top">
  813. <th scope="row">
  814. <label for="<?php echo $optid;?>"><?php echo $label;?></label>
  815. </th>
  816. <td>
  817. <input type="text" name="<?php echo $this->unique_prefix . '_options[' . $option;?>]" id="<?php echo $optid;?>" <?php if($disable){echo 'disabled="disabled"'; $class .= ' disabled';}?> value="<?php echo htmlentities($this->opt[$option], ENT_COMPAT, 'UTF-8');?>" class="<?php echo $class;?>" /><br />
  818. <?php if($description !== ''){?><p class="description"><?php echo $description;?></p><?php }?>
  819. </td>
  820. </tr>
  821. <?php
  822. }
  823. /**
  824. * This will output a well formed table row for a HTML5 number input
  825. *
  826. * @param string $label
  827. * @param string $option
  828. * @param string $class [optional]
  829. * @param bool $disable [optional]
  830. * @param string $description [optional]
  831. * @param int|string $min [optional]
  832. * @param int|string $max [optional]
  833. * @param int|string $step [optional]
  834. * @return
  835. */
  836. function input_number($label, $option, $class = 'small-text', $disable = false, $description = '', $min = '', $max = '', $step = '')
  837. {
  838. $optid = $this->get_valid_id($option);
  839. $extras = '';
  840. if($min !== '')
  841. {
  842. $extras .= 'min="' . $min . '" ';
  843. }
  844. if($max !== '')
  845. {
  846. $extras .= 'max="' . $max . '" ';
  847. }
  848. if($step !== '')
  849. {
  850. $extras .= 'step="' . $step . '" ';
  851. }
  852. if($disable)
  853. {?>
  854. <input type="hidden" name="<?php echo $this->unique_prefix . '_options[' . $option;?>]" value="<?php echo htmlentities($this->opt[$option], ENT_COMPAT, 'UTF-8');?>" />
  855. <?php } ?>
  856. <tr valign="top">
  857. <th scope="row">
  858. <label for="<?php echo $optid;?>"><?php echo $label;?></label>
  859. </th>
  860. <td>
  861. <input type="number" name="<?php echo $this->unique_prefix . '_options[' . $option;?>]" id="<?php echo $optid;?>" <?php echo $extras;?><?php if($disable){echo 'disabled="disabled"'; $class .= ' disabled';}?> value="<?php echo htmlentities($this->opt[$option], ENT_COMPAT, 'UTF-8');?>" class="<?php echo $class;?>" /><br />
  862. <?php if($description !== ''){?><p class="description"><?php echo $description;?></p><?php }?>
  863. </td>
  864. </tr>
  865. <?php
  866. }
  867. /**
  868. * This will output a well formed textbox
  869. *
  870. * @param string $label
  871. * @param string $option
  872. * @param string $rows [optional]
  873. * @param bool $disable [optional]
  874. * @param string $description [optional]
  875. */
  876. function textbox($label, $option, $height = '3', $disable = false, $description = '')
  877. {
  878. $optid = $this->get_valid_id($option);?>
  879. <p>
  880. <label for="<?php echo $optid;?>"><?php echo $label;?></label>
  881. </p>
  882. <textarea rows="<?php echo $height;?>" <?php if($disable){echo 'disabled="disabled" class="large-text code disabled"';}else{echo 'class="large-text code"';}?> id="<?php echo $optid;?>" name="<?php echo $this->unique_prefix . '_options[' . $option;?>]"><?php echo htmlentities($this->opt[$option], ENT_COMPAT, 'UTF-8');?></textarea><br />
  883. <?php if($description !== ''){?><p class="description"><?php echo $description;?></p><?php }
  884. }
  885. /**
  886. * This will output a well formed tiny mce ready textbox
  887. *
  888. * @param string $label
  889. * @param string $option
  890. * @param string $rows [optional]
  891. * @param bool $disable [optional]
  892. * @param string $description [optional]
  893. */
  894. function tinymce($label, $option, $height = '3', $disable = false, $description = '')
  895. {
  896. $optid = $this->get_valid_id($option);
  897. if($disable)
  898. {?>
  899. <input type="hidden" name="<?php echo $this->unique_prefix . '_options[' . $option;?>]" value="<?php echo htmlentities($this->opt[$option], ENT_COMPAT, 'UTF-8');?>" />
  900. <?php } ?>
  901. <tr valign="top">
  902. <th scope="row">
  903. <label for="<?php echo $optid;?>"><?php echo $label;?></label>
  904. </th>
  905. <td>
  906. <textarea rows="<?php echo $height;?>" <?php if($disable){echo 'disabled="disabled" class="mtekk_mce disabled"';}else{echo 'class="mtekk_mce"';}?> id="<?php echo $optid;?>" name="<?php echo $this->unique_prefix . '_options[' . $option;?>]"><?php echo htmlentities($this->opt[$option], ENT_COMPAT, 'UTF-8');?></textarea><br />
  907. <?php if($description !== ''){?><p class="description"><?php echo $description;?></p><?php }?>
  908. </td>
  909. </tr>
  910. <?php
  911. }
  912. /**
  913. * This will output a well formed table row for a checkbox input
  914. *
  915. * @param string $label
  916. * @param string $option
  917. * @param string $instruction
  918. * @param bool $disable [optional]
  919. * @param string $description [optional]
  920. * @return
  921. */
  922. function input_check($label, $option, $instruction, $disable = false, $description = '')
  923. {
  924. $optid = $this->get_valid_id($option);?>
  925. <tr valign="top">
  926. <th scope="row">
  927. <label for="<?php echo $optid;?>"><?php echo $label;?></label>
  928. </th>
  929. <td>
  930. <label>
  931. <input type="checkbox" name="<?php echo $this->unique_prefix . '_options[' . $option;?>]" id="<?php echo $optid;?>" <?php if($disable){echo 'disabled="disabled" class="disabled"';}?> value="true" <?php checked(true, $this->opt[$option]);?> />
  932. <?php echo $instruction; ?>
  933. </label><br />
  934. <?php if($description !== ''){?><p class="description"><?php echo $description;?></p><?php }?>
  935. </td>
  936. </tr>
  937. <?php
  938. }
  939. /**
  940. * This will output a singular radio type form input field
  941. *
  942. * @param string $option
  943. * @param string $value
  944. * @param string $instruction
  945. * @param object $disable [optional]
  946. * @return
  947. */
  948. function input_radio($option, $value, $instruction, $disable = false)
  949. {?>
  950. <label>
  951. <input name="<?php echo $this->unique_prefix . '_options[' . $option;?>]" type="radio" <?php if($disable){echo 'disabled="disabled" class="disabled togx"';}else{echo 'class="togx"';}?> value="<?php echo $value;?>" <?php checked($value, $this->opt[$option]);?> />
  952. <?php echo $instruction; ?>
  953. </label><br/>
  954. <?php
  955. }
  956. /**
  957. * This will output a well formed table row for a select input
  958. *
  959. * @param string $label
  960. * @param string $option
  961. * @param array $values
  962. * @param bool $disable [optional]
  963. * @param string $description [optional]
  964. * @return
  965. */
  966. function input_select($label, $option, $values, $disable = false, $description = '', $titles = false)
  967. {
  968. //If we don't have titles passed in, we'll use option names as values
  969. if(!$titles)
  970. {
  971. $titles = $values;
  972. }
  973. $optid = $this->get_valid_id($option);?>
  974. <tr valign="top">
  975. <th scope="row">
  976. <label for="<?php echo $optid;?>"><?php echo $label;?></label>
  977. </th>
  978. <td>
  979. <select name="<?php echo $this->unique_prefix . '_options[' . $option;?>]" id="<?php echo $optid;?>" <?php if($disable){echo 'disabled="disabled" class="disabled"';}?>>
  980. <?php $this->select_options($option, $titles, $values); ?>
  981. </select><br />
  982. <?php if($description !== ''){?><p class="description"><?php echo $description;?></p><?php }?>
  983. </td>
  984. </tr>
  985. <?php
  986. }
  987. /**
  988. * Displays wordpress options as <seclect>
  989. *
  990. * @param string $optionname name of wordpress options store
  991. * @param array $options array of names of options that can be selected
  992. * @param array $exclude[optional] array of names in $options array to be excluded
  993. */
  994. function select_options($optionname, $options, $values, $exclude = array())
  995. {
  996. $value = $this->opt[$optionname];
  997. //Now do the rest
  998. foreach($options as $key => $option)
  999. {
  1000. if(!in_array($option, $exclude))
  1001. {
  1002. printf('<option value="%s" %s>%s</option>', $values[$key], selected(true, ($value == $values[$key]), false), $option);
  1003. }
  1004. }
  1005. }
  1006. }