<?php /** * Includes Layout Engine for the admin dashboard. * * @filesource * @author Stefan Herndler * @since 1.5.0 12.09.14 10:56 */ /** * Layout Engine for the administration dashboard. * * @author Stefan Herndler * @since 1.5.0 */ abstract class MCI_Footnotes_LayoutEngine { /** * Stores the Hook connection string for the child sub page. * * @author Stefan Herndler * @since 1.5.0 * @var null|string */ protected $a_str_SubPageHook = null; /** * Stores all Sections for the child sub page. * * @author Stefan Herndler * @since 1.5.0 * @var array */ protected $a_arr_Sections = array(); /** * Returns a Priority index. Lower numbers have a higher Priority. * * @author Stefan Herndler * @since 1.5.0 * @return int */ abstract public function getPriority(); /** * Returns the unique slug of the child sub page. * * @author Stefan Herndler * @since 1.5.0 * @return string */ abstract protected function getSubPageSlug(); /** * Returns the title of the child sub page. * * @author Stefan Herndler * @since 1.5.0 * @return string */ abstract protected function getSubPageTitle(); /** * Returns an array of all registered sections for a sub page. * * @author Stefan Herndler * @since 1.5.0 * @return array */ abstract protected function getSections(); /** * Returns an array of all registered meta boxes. * * @author Stefan Herndler * @since 1.5.0 * @return array */ abstract protected function getMetaBoxes(); /** * Returns an array describing a sub page section. * * @author Stefan Herndler * @since 1.5.0 * @param string $p_str_ID Unique ID suffix. * @param string $p_str_Title Title of the section. * @param int $p_int_SettingsContainerIndex Settings Container Index. * @param bool $p_bool_hasSubmitButton Should a Submit Button be displayed for this section, default: true. * @return array Array describing the section. */ protected function addSection($p_str_ID, $p_str_Title, $p_int_SettingsContainerIndex, $p_bool_hasSubmitButton = true) { return array("id" => MCI_Footnotes_Config::C_STR_PLUGIN_NAME . "-" . $p_str_ID, "title" => $p_str_Title, "submit" => $p_bool_hasSubmitButton, "container" => $p_int_SettingsContainerIndex); } /** * Returns an array describing a meta box. * * @author Stefan Herndler * @since 1.5.0 * @param string $p_str_SectionID Parent Section ID. * @param string $p_str_ID Unique ID suffix. * @param string $p_str_Title Title for the meta box. * @param string $p_str_CallbackFunctionName Class method name for callback. * @return array meta box description to be able to append a meta box to the output. */ protected function addMetaBox($p_str_SectionID, $p_str_ID, $p_str_Title, $p_str_CallbackFunctionName) { return array("parent" => MCI_Footnotes_Config::C_STR_PLUGIN_NAME . "-" . $p_str_SectionID, "id" => $p_str_ID, "title" => $p_str_Title, "callback" => $p_str_CallbackFunctionName); } /** * Registers a sub page. * * @author Stefan Herndler * @since 1.5.0 */ public function registerSubPage() { global $submenu; // iterate through each sub menu foreach($submenu as $l_arr_SubMenu) { // iterate through each sub menu attribute foreach($l_arr_SubMenu as $l_str_Attribute) { // sub menu already added, stop if ($l_str_Attribute == MCI_Footnotes_Layout_Init::C_STR_MAIN_MENU_SLUG . $this->getSubPageSlug()) { return; } } } $this->a_str_SubPageHook = add_submenu_page( MCI_Footnotes_Layout_Init::C_STR_MAIN_MENU_SLUG, // parent slug $this->getSubPageTitle(), // page title $this->getSubPageTitle(), // menu title 'manage_options', // capability MCI_Footnotes_Layout_Init::C_STR_MAIN_MENU_SLUG . $this->getSubPageSlug(), // menu slug array($this, 'displayContent') // function ); } /** * Registers all sections for a sub page. * * @author Stefan Herndler * @since 1.5.0 */ public function registerSections() { // iterate through each section foreach($this->getSections() as $l_arr_Section) { // append tab to the tab-array $this->a_arr_Sections[$l_arr_Section["id"]] = $l_arr_Section; add_settings_section( $l_arr_Section["id"], // unique id "", //$l_arr_Section["title"], // title array($this, 'Description'), // callback function for the description $l_arr_Section["id"] // parent sub page slug ); $this->registerMetaBoxes($l_arr_Section["id"]); } } /** * Registers all Meta boxes for a sub page. * * @author Stefan Herndler * @since 1.5.0 * @param string $p_str_ParentID Parent section unique id. */ private function registerMetaBoxes($p_str_ParentID) { // iterate through each meta box foreach($this->getMetaBoxes() as $l_arr_MetaBox) { if ($l_arr_MetaBox["parent"] != $p_str_ParentID) { continue; } add_meta_box( $p_str_ParentID. "-" . $l_arr_MetaBox["id"], // unique id $l_arr_MetaBox["title"], // meta box title array($this, $l_arr_MetaBox["callback"]), // callback function to display (echo) the content $p_str_ParentID, // post type = parent section id 'main' // context ); } } /** * Append javascript and css files for specific sub page. * * @author Stefan Herndler * @since 1.5.0 */ private function appendScripts() { // add jQuery to the sub menu page wp_enqueue_script('jquery'); // enable meta boxes layout and close functionality wp_enqueue_script('postbox'); // register stylesheet wp_register_style('mci-footnotes-admin-styles', plugins_url('../../css/settings.css', __FILE__)); // add stylesheet to the output wp_enqueue_style('mci-footnotes-admin-styles'); } /** * Displays the content of specific sub page. * * @author Stefan Herndler * @since 1.5.0 */ public function displayContent() { // register and enqueue scripts and styling $this->appendScripts(); // get current section reset($this->a_arr_Sections); $l_str_ActiveSectionID = isset($_GET['t']) ? $_GET['t'] : key($this->a_arr_Sections); $l_arr_ActiveSection = $this->a_arr_Sections[$l_str_ActiveSectionID]; // store settings $l_bool_SettingsUpdated = false; if (array_key_exists("save-settings", $_POST)) { if ($_POST["save-settings"] == "save") { $l_bool_SettingsUpdated = $this->saveSettings(); } } // display all sections and highlight the active section echo '<div class="wrap">'; echo '<h2 class="nav-tab-wrapper">'; // iterate through all register sections foreach ($this->a_arr_Sections as $l_str_ID => $l_arr_Description) { echo sprintf( '<a class="nav-tab%s" href="?page=%s&t=%s">%s</a>', $l_arr_ActiveSection["id"] == $l_str_ID ? ' nav-tab-active' : '', MCI_Footnotes_Layout_Init::C_STR_MAIN_MENU_SLUG . $this->getSubPageSlug(), $l_str_ID, $l_arr_Description["title"] ); } echo '</h2><br/>'; if ($l_bool_SettingsUpdated) { echo sprintf('<div id="message" class="updated">%s</div>', __("Settings saved", MCI_Footnotes_Config::C_STR_PLUGIN_NAME)); } // form to submit the active section echo '<!--suppress HtmlUnknownTarget --><form method="post" action="">'; settings_fields($l_arr_ActiveSection["container"]); echo '<input type="hidden" name="save-settings" value="save" />'; // outputs the settings field of the active section do_settings_sections($l_arr_ActiveSection["id"]); do_meta_boxes($l_arr_ActiveSection["id"], 'main', NULL); // add submit button to active section if defined if ($l_arr_ActiveSection["submit"]) { submit_button(); } // close the form to submit data echo '</form>'; // close container for the settings page echo '</div>'; // output special javascript for the expand/collapse function of the meta boxes echo '<script type="text/javascript">'; echo "jQuery(document).ready(function ($) {"; echo "jQuery('.if-js-closed').removeClass('if-js-closed').addClass('closed');"; echo "postboxes.add_postbox_toggles('" . $this->a_str_SubPageHook . "');"; echo "});"; echo '</script>'; } /** * Save all Plugin settings. * * @author Stefan Herndler * @since 1.5.0 * @return bool */ private function saveSettings() { // get only Footnotes settings $l_arr_Settings = array(); foreach($_POST as $l_str_SettingsName => $l_str_Value) { if (substr($l_str_SettingsName, 0, 8) == "footnote") { $l_arr_Settings[$l_str_SettingsName] = $l_str_Value; } } // get current section reset($this->a_arr_Sections); $l_str_ActiveSectionID = isset($_GET['t']) ? $_GET['t'] : key($this->a_arr_Sections); $l_arr_ActiveSection = $this->a_arr_Sections[$l_str_ActiveSectionID]; // update settings return MCI_Footnotes_Settings::instance()->saveOptions($l_arr_ActiveSection["container"], $l_arr_Settings); } /** * Output the Description of a section. May be overwritten in any section. * * @author Stefan Herndler * @since 1.5.0 */ public function Description() { // default no description will be displayed } /** * Loads specific setting and returns an array with the keys [id, name, value]. * * @author Stefan Herndler * @since 1.5.0 * @param string $p_str_SettingKeyName Settings Array key name. * @return array Contains Settings ID, Settings Name and Settings Value. */ protected function LoadSetting($p_str_SettingKeyName) { // get current section reset($this->a_arr_Sections); $l_str_ActiveSectionID = isset($_GET['t']) ? $_GET['t'] : key($this->a_arr_Sections); $l_arr_ActiveSection = $this->a_arr_Sections[$l_str_ActiveSectionID]; $p_arr_Return = array(); $p_arr_Return["id"] = sprintf('%s', $p_str_SettingKeyName); //$p_arr_Return["name"] = sprintf('%s[%s]', MCI_Footnotes_Settings::instance()->getContainer($l_arr_ActiveSection["container"]), $p_str_SettingKeyName); $p_arr_Return["name"] = sprintf('%s', $p_str_SettingKeyName); $p_arr_Return["value"] = esc_attr(MCI_Footnotes_Settings::instance()->get($p_str_SettingKeyName)); return $p_arr_Return; } /** * Returns a line break to start a new line. * * @author Stefan Herndler * @since 1.5.0 * @return string */ protected function addNewline() { return '<br/>'; } /** * Returns a line break to have a space between two lines. * * @author Stefan Herndler * @since 1.5.0 * @return string */ protected function addLineSpace() { return '<br/><br/>'; } /** * Returns a simple text inside html <span> text. * * @author Stefan Herndler * @since 1.5.0 * @param string $p_str_Text Message to be surrounded with simple html tag (span). * @return string */ protected function addText($p_str_Text) { return sprintf('<span>%s</span>', $p_str_Text); } /** * Returns the html tag for an input/select label. * * @author Stefan Herndler * @since 1.5.0 * @param string $p_str_SettingName Name of the Settings key to connect the Label with the input/select field. * @param string $p_str_Caption Label caption. * @return string */ protected function addLabel($p_str_SettingName, $p_str_Caption) { if (empty($p_str_Caption)) { return ""; } return sprintf('<label for="%s">%s:</label>', $p_str_SettingName, $p_str_Caption); } /** * Returns the html tag for an input [type = text]. * * @author Stefan Herndler * @since 1.5.0 * @param string $p_str_SettingName Name of the Settings key to pre load the input field. * @param int $p_str_MaxLength Maximum length of the input, default 999 characters. * @param bool $p_bool_Readonly Set the input to be read only, default false. * @param bool $p_bool_Hidden Set the input to be hidden, default false. * @return string */ protected function addTextBox($p_str_SettingName, $p_str_MaxLength = 999, $p_bool_Readonly = false, $p_bool_Hidden = false) { $l_str_Style = ""; // collect data for given settings field $l_arr_Data = $this->LoadSetting($p_str_SettingName); if ($p_bool_Hidden) { $l_str_Style .= 'display:none;'; } return sprintf('<input type="text" name="%s" id="%s" maxlength="%d" style="%s" value="%s" %s/>', $l_arr_Data["name"], $l_arr_Data["id"], $p_str_MaxLength, $l_str_Style, $l_arr_Data["value"], $p_bool_Readonly ? 'readonly="readonly"' : ''); } /** * Returns the html tag for an input [type = checkbox]. * * @author Stefan Herndler * @since 1.5.0 * @param string $p_str_SettingName Name of the Settings key to pre load the input field. * @return string */ protected function addCheckbox($p_str_SettingName) { // collect data for given settings field $l_arr_Data = $this->LoadSetting($p_str_SettingName); return sprintf('<input type="checkbox" name="%s" id="%s" %s/>', $l_arr_Data["name"], $l_arr_Data["id"], MCI_Footnotes_Convert::toBool($l_arr_Data["value"]) ? 'checked="checked"' : ''); } /** * Returns the html tag for a select box. * * @author Stefan Herndler * @since 1.5.0 * @param string $p_str_SettingName Name of the Settings key to pre select the current value. * @param array $p_arr_Options Possible options to be selected. * @return string */ protected function addSelectBox($p_str_SettingName, $p_arr_Options) { // collect data for given settings field $l_arr_Data = $this->LoadSetting($p_str_SettingName); $l_str_Options = ""; /* loop through all array keys */ foreach ($p_arr_Options as $l_str_Value => $l_str_Caption) { $l_str_Options .= sprintf('<option value="%s" %s>%s</option>', $l_str_Value, $l_arr_Data["value"] == $l_str_Value ? "selected" : "", $l_str_Caption); } return sprintf('<select name="%s" id="%s">%s</select>', $l_arr_Data["name"], $l_arr_Data["id"], $l_str_Options); } /** * Returns the html tag for a text area. * * @author Stefan Herndler * @since 1.5.0 * @param string $p_str_SettingName Name of the Settings key to pre fill the text area. * @return string */ protected function addTextArea($p_str_SettingName) { // collect data for given settings field $l_arr_Data = $this->LoadSetting($p_str_SettingName); return sprintf('<textarea name="%s" id="%s">%s</textarea>', $l_arr_Data["name"], $l_arr_Data["id"], $l_arr_Data["value"]); } } // end of class