. // Generates an array of various settings information function ui_array (Setup $setup, Locale $locale) { // Theme names $themes = array (); // Themes directory $themes_directory = $setup->getAbsolutePath ('themes'); // Get each theme directory name foreach (glob ($themes_directory . '/*', GLOB_ONLYDIR) as $directory) { $theme = basename ($directory); $themes[$theme] = $theme; } // Form fields options $field_options = array ( 'on' => $locale->text['enabled'], 'required' => $locale->text['required'], 'off' => $locale->text['disabled'], ); // Return array of settings allowed to be changed return array ( 'general' => array ( 'language' => array ( 'type' => 'select', 'value' => $setup->language, 'options' => array ( 'en-us' => 'English', 'pt-br' => 'Brazilian Portuguese', 'da-dk' => 'Danish', 'nl-nl' => 'Dutch', 'eo-eo' => 'Esperanto', 'fr-fr' => 'French', 'de-de' => 'German', 'el-el' => 'Greek', 'ja-jp' => 'Japanese', 'ko-kr' => 'Korean', 'lt-lt' => 'Lithuanian', 'fa-ir' => 'Persian', 'pl-pl' => 'Polish', 'ro-ro' => 'Romanian', 'ru-ru' => 'Russian', 'zh-cn' => 'Simplified Chinese', 'es-es' => 'Spanish', 'sv-se' => 'Swedish', 'tr-tr' => 'Turkish' ) ), 'theme' => array ( 'type' => 'select', 'value' => $setup->theme, 'options' => $themes ), 'default-sorting' => array ( 'type' => 'select', 'value' => $setup->defaultSorting, 'options' => array ( 'ascending' => $locale->text['sort-ascending'], 'descending' => $locale->text['sort-descending'], 'by-date' => $locale->text['sort-by-date'], 'by-likes' => $locale->text['sort-by-likes'], 'by-replies' => $locale->text['sort-by-replies'], 'by-name' => $locale->text['sort-by-name'], 'threads' => array ( 'threaded-descending' => $locale->text['sort-descending'], 'threaded-by-date' => $locale->text['sort-by-date'], 'threaded-by-likes' => $locale->text['sort-by-likes'], 'by-popularity' => $locale->text['sort-by-popularity'], 'by-discussion' => $locale->text['sort-by-discussion'], 'threaded-by-name' => $locale->text['sort-by-name'] ) ) ), 'uses-markdown' => array ( 'type' => 'checkbox', 'value' => $setup->usesMarkdown ), 'uses-ajax' => array ( 'type' => 'checkbox', 'value' => $setup->usesAjax ), 'shows-reply-count' => array ( 'type' => 'checkbox', 'value' => $setup->showsReplyCount ), 'allows-images' => array ( 'type' => 'checkbox', 'value' => $setup->allowsImages ), 'allows-likes' => array ( 'type' => 'checkbox', 'value' => $setup->allowsLikes ), 'allows-dislikes' => array ( 'type' => 'checkbox', 'value' => $setup->allowsDislikes ) ), 'moderation' => array ( 'uses-moderation' => array ( 'type' => 'checkbox', 'value' => $setup->usesModeration ), 'pends-user-edits' => array ( 'type' => 'checkbox', 'value' => $setup->pendsUserEdits ) ), 'e-mail' => array ( 'sends-notifications' => array ( 'type' => 'select', 'value' => $setup->sendsNotifications, 'options' => array ( 'to-everyone' => 'Everyone, admin and users', 'to-users' => 'Users only, when they reply to each other', 'to-admin' => 'Admin only', 'to-nobody' => 'Nobody' ) ), 'mail-type' => array ( 'type' => 'select', 'value' => $setup->mailType, 'options' => array ( 'text' => 'Text', 'html' => 'HTML' ) ), 'mailer' => array ( 'type' => 'select', 'value' => $setup->mailer, 'options' => array ( 'sendmail' => 'Sendmail', 'smtp' => 'SMTP' ) ), 'subscribes-user' => array ( 'type' => 'checkbox', 'value' => $setup->subscribesUser ), 'allows-user-replies' => array ( 'type' => 'checkbox', 'value' => $setup->allowsUserReplies ) ), 'cookies' => array ( 'sets-cookies' => array ( 'type' => 'checkbox', 'value' => $setup->setsCookies ), 'cookie-expiration' => array ( 'type' => 'text', 'value' => $setup->cookieExpiration ), 'secure-cookies' => array ( 'type' => 'checkbox', 'value' => $setup->secureCookies ) ), 'comment-collapsing' => array ( 'collapses-interface' => array ( 'type' => 'checkbox', 'value' => $setup->collapsesInterface ), 'collapses-comments' => array ( 'type' => 'checkbox', 'value' => $setup->collapsesComments ), 'collapse-limit' => array ( 'type' => 'number', 'value' => $setup->collapseLimit ) ), 'popular-comments' => array ( 'popularity-threshold' => array ( 'type' => 'number', 'value' => $setup->popularityThreshold ), 'popularity-limit' => array ( 'type' => 'number', 'value' => $setup->popularityLimit ) ), 'spam-protection' => array ( 'spam-database' => array ( 'type' => 'select', 'value' => $setup->spamDatabase, 'options' => array ( 'remote' => 'StopForumSpam.com', 'local' => 'Local CSV file' ) ), 'spam-check-modes' => array ( 'type' => 'select', 'value' => $setup->spamCheckModes, 'options' => array ( 'both' => 'Both', 'json' => 'JavaScript', 'php' => 'PHP' ) ) ), 'avatars' => array ( 'icon-mode' => array ( 'type' => 'select', 'value' => $setup->iconMode, 'options' => array ( 'image' => 'Image', 'count' => 'Count', 'none' => 'None' ) ), 'icon-size' => array ( 'type' => 'number', 'value' => $setup->iconSize ), 'gravatar-default' => array ( 'type' => 'select', 'value' => $setup->gravatarDefault, 'options' => array ( 'custom' => 'Custom', 'identicon' => 'Identicon', 'monsterid' => 'Monsterid', 'wavatar' => 'Wavatar', 'retro' => 'Retro' ) ), 'gravatar-force' => array ( 'type' => 'checkbox', 'value' => $setup->gravatarForce ) ), 'form-fields' => array ( 'form-position' => array ( 'type' => 'select', 'value' => $setup->formPosition, 'options' => array ( 'top' => 'Top', 'bottom' => 'Bottom' ) ), 'name-field' => array ( 'type' => 'select', 'value' => $setup->nameField, 'options' => $field_options ), 'password-field' => array ( 'type' => 'select', 'value' => $setup->passwordField, 'options' => $field_options ), 'email-field' => array ( 'type' => 'select', 'value' => $setup->emailField, 'options' => $field_options ), 'website-field' => array ( 'type' => 'select', 'value' => $setup->websiteField, 'options' => $field_options ), 'displays-title' => array ( 'type' => 'checkbox', 'value' => $setup->displaysTitle ), 'uses-cancel-buttons' => array ( 'type' => 'checkbox', 'value' => $setup->usesCancelButtons ), 'uses-labels' => array ( 'type' => 'checkbox', 'value' => $setup->usesLabels ) ), 'date-time' => array ( 'date-pattern' => array ( 'type' => 'text', 'value' => $setup->datePattern, 'show' => $setup->hasIntl ), 'time-pattern' => array ( 'type' => 'text', 'value' => $setup->timePattern, 'show' => $setup->hasIntl ), 'date-format' => array ( 'type' => 'text', 'value' => $setup->dateFormat, 'show' => !$setup->hasIntl ), 'time-format' => array ( 'type' => 'text', 'value' => $setup->timeFormat, 'show' => !$setup->hasIntl ), 'server-timezone' => array ( 'type' => 'text', 'value' => $setup->serverTimezone ), 'uses-user-timezone' => array ( 'type' => 'checkbox', 'value' => $setup->usesUserTimezone ), 'uses-short-dates' => array ( 'type' => 'checkbox', 'value' => $setup->usesShortDates ) ), 'login' => array ( 'login-method' => array ( 'type' => 'select', 'value' => $setup->loginMethod, 'options' => array ( 'DefaultLogin' => 'Cookies Login', 'SessionLogin' => 'Session Login' ) ), 'allows-login' => array ( 'type' => 'checkbox', 'value' => $setup->allowsLogin ), 'uses-auto-login' => array ( 'type' => 'checkbox', 'value' => $setup->usesAutoLogin ) ), 'technical' => array ( 'data-format' => array ( 'type' => 'select', 'value' => $setup->dataFormat, 'options' => array ( 'xml' => 'XML', 'json' => 'JSON', 'sql' => 'SQL' ) ), 'default-name' => array ( 'type' => 'text', 'value' => $setup->defaultName ), 'reply-mode' => array ( 'type' => 'select', 'value' => $setup->replyMode, 'options' => array ( 'thread' => 'Threaded', 'stream' => 'Stream' ) ), 'stream-depth' => array ( 'type' => 'number', 'value' => $setup->streamDepth ), 'image-format' => array ( 'type' => 'select', 'value' => $setup->imageFormat, 'options' => array ( 'png' => 'PNG', 'svg' => 'SVG' ) ), 'appends-css' => array ( 'type' => 'checkbox', 'value' => $setup->appendsCss ), 'appends-rss' => array ( 'type' => 'checkbox', 'value' => $setup->appendsRss ), 'counts-deletions' => array ( 'type' => 'checkbox', 'value' => $setup->countsDeletions ), 'local-metadata' => array ( 'type' => 'checkbox', 'value' => $setup->localMetadata ), 'stores-ip-address' => array ( 'type' => 'checkbox', 'value' => $setup->storesIpAddress ) ), 'JavaScript' => array ( 'minifies-javascript' => array ( 'type' => 'checkbox', 'value' => $setup->minifiesJavascript ), 'minify-level' => array ( 'type' => 'select', 'cast' => 'number', 'value' => $setup->minifyLevel, 'options' => array ( 1 => 'Basic (removes code comments)', 2 => 'Low (removes whitespace + Basic)', 3 => 'Medium (removes newlines + Low)', 4 => 'High (removes extra bits + Medium)' ) ) ) ); } // Creates a select element with setting options function create_select ($hashover, $name, array $setting) { // Create wrapper element for dropdown menu $element = new HTMLTag ('span', array ( 'class' => 'select-wrapper' )); // Create dropdown menu $select = new HTMLTag ('select', array ( 'id' => $name, 'name' => $name, 'size' => 1 )); // Run through setting options foreach ($setting['options'] as $value => $data) { // Check if the current option is an array if (is_array ($data)) { // If so, add an option group spacer to menu $select->appendChild (new HTMLTag ('optgroup', array ( 'label' => ' ' ))); // Create an option group with localized label $optgroup = new HTMLTag ('optgroup', array ( 'label' => $hashover->locale->text[$value] )); // Run through each optgroup option foreach ($data as $opt_value => $opt_text) { // Create setting option $option = new HTMLTag ('option', array ( 'value' => $opt_value, 'innerHTML' => $opt_text ), false); // Select proper option if ($opt_value === $setting['value']) { $option->createAttribute ('selected', 'true'); } // Append option to optgroup $optgroup->appendChild ($option); } // And append optgroup to menu $select->appendChild ($optgroup); } else { // If not, create setting option $option = new HTMLTag ('option', array ( 'value' => $value, 'innerHTML' => $data ), false); // Select proper option if ($value === $setting['value']) { $option->createAttribute ('selected', 'true'); } // Append option to menu $select->appendChild ($option); } } // Append dropdown menu to wrapper element $element->appendChild ($select); return $element; } // Creates a paragraph element for a setting value function create_paragraph ($hashover, $name, array $setting) { // Create setting description and value paragraph $paragraph = new HTMLTag ('p'); // Setting description locale string $text = $hashover->locale->text['setting-' . $name]; // Create description label $label = new HTMLTag ('label', array ( 'for' => $name, 'innerHTML' => $text ), false); // Get documentation locale string $docs = $hashover->locale->text['documentation']; // Create documentation link $docs_link = new HTMLTag ('a', array ( 'class' => 'docs-link', 'href' => '../docs/en-us/settings/#' . $name, 'target' => '_blank', 'title' => $docs, 'innerHTML' => '?' ), false); // Handle specific setting types switch ($setting['type']) { // Create checkbox for enabling/disabling the setting case 'checkbox': { // Create checkbox type input element $element = new HTMLTag ('input', array ( 'id' => $name, 'type' => 'checkbox', 'name' => $name ), false, true); // Set check based on current setting if ($setting['value'] !== false) { $element->createAttribute ('checked', 'true'); } break; } // Create text/number box for entering the setting value case 'number' : case 'text': { // Add class to make label a block element $label->createAttribute ('class', 'block'); // And create number or text type input element $element = new HTMLTag ('input', array ( 'id' => $name, 'type' => $setting['type'], 'name' => $name, 'value' => $setting['value'], 'size' => ($setting['type'] === 'text') ? '25' : '10' ), false, true); break; } // Create dropdown menu for selecting the setting value case 'select': { // Add class to make label a block element $label->createAttribute ('class', 'block'); // Create select element $element = create_select ($hashover, $name, $setting); break; } } // Check if setting is a checkbox if ($setting['type'] === 'checkbox') { // If so, append setting value element to paragraph $paragraph->appendChild ($element); // Then append label element to paragraph $paragraph->appendChild ($label); // Append documentation link to description and value paragraph $paragraph->appendChild ($docs_link); } else { // If not, append documentation link to description label $label->appendChild ($docs_link); // Append label element to paragraph $paragraph->appendChild ($label); // Then append setting value element to paragraph $paragraph->appendChild ($element); } // And return paragraph element return $paragraph; } try { // Do some standard HashOver setup work require (realpath ('../../backend/standard-setup.php')); // View setup require (realpath ('../view-setup.php')); // Get array of UI elements to create $ui = ui_array ($hashover->setup, $hashover->locale); // Check if the form has been submitted if (isset ($_POST['save'])) { // Settings JSON file path $settings_file = $hashover->setup->getAbsolutePath ('config/settings.json'); // Read JSON settings file $json = $data_files->readJSON ($settings_file); // Existing JSON settings or an empty array $settings = ($json !== false) ? $json : array (); // Run through configurable settings foreach ($ui as $items) { // Run through each settings category foreach ($items as $name => $setting) { // Use specified type or optional cast $type = !empty ($setting['cast']) ? 'cast' : 'type'; // Handle specific setting types switch ($setting[$type]) { // Set value to boolean based on POST data case 'checkbox': { $settings[$name] = isset ($_POST[$name]); break; } // Cast number values to integers case 'number': { $settings[$name] = (int)($_POST[$name]); break; } // All other values are strings default: { // Check if setting has a value if (!empty ($_POST[$name])) { // If so, cast it to string before setting it $settings[$name] = (string)($_POST[$name]); } else { // If not, remove the setting entirely unset ($settings[$name]); } break; } } } } // Check if the user login is admin if ($hashover->login->verifyAdmin () === true) { // If so, attempt to save the settings $saved = $data_files->saveJSON ($settings_file, $settings); // If saved successfully, redirect with success indicator if ($saved === true) { redirect ('./?status=success'); } } // Otherwise, redirect with failure indicator redirect ('./?status=failure'); } // Otherwise, create settings div $div = new HTMLTag ('div', array ( 'id' => 'settings' )); // Create settings divs foreach ($ui as $locale => $settings) { // Replace key with locale string if one exists if (!empty ($hashover->locale->text[$locale])) { $locale = $hashover->locale->text[$locale]; } // Append settings category text to settings div $div->appendChild (new HTMLTag ('p', array ( 'class' => 'settings-category', 'innerHTML' => $locale ), false)); // Create settings items element $items = new HTMLTag ('div', array ( 'class' => 'settings' )); // Run through settings foreach ($settings as $name => $setting) { // Append each settings category items to div if they are to be shown if (!isset ($setting['show']) or $setting['show'] === true) { $items->appendChild (create_paragraph ($hashover, $name, $setting)); } } // Append settings items element to div $div->appendChild ($items); } // Template data $template = array ( 'title' => $hashover->locale->text['settings'], 'sub-title' => $hashover->locale->text['settings-sub'], 'settings' => $div->asHTML ("\t"), 'save-button' => $hashover->locale->text['save'] ); // Load and parse HTML template echo parse_templates ('admin', 'settings.html', $template, $hashover); } catch (\Exception $error) { echo Misc::displayException ($error); }