opticore/includes/class-framework.php

648 lines
20 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/**
* OptiCore Admin Framework
*
* Professional admin panel framework inspired by CodeStar Framework
*
* @package OptiCore
* @version 1.0.0
*/
if (!defined('ABSPATH')) {
exit;
}
class OptiCore_Framework {
/**
* Instance
*/
private static $instance = null;
/**
* Settings
*/
private $settings = array();
/**
* Sections
*/
private $sections = array();
/**
* Options
*/
private $options = array();
/**
* Errors
*/
private $errors = array();
/**
* Get instance
*/
public static function get_instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor
*/
private function __construct() {
// Set settings without translations first
$this->settings = array(
'menu_slug' => 'opticore-settings',
'menu_type' => 'submenu',
'menu_parent' => 'opticore',
'menu_icon' => 'dashicons-admin-settings',
'menu_position' => null,
'ajax_save' => true,
'show_reset' => true,
'show_export' => true,
'show_import' => true,
'theme' => 'modern',
'database' => 'opticore_settings',
);
$this->init_hooks();
}
/**
* Get translatable settings
*/
private function get_translatable_settings() {
return array(
'framework_title' => __('OptiCore Settings', 'opticore'),
'menu_title' => __('Settings', 'opticore'),
);
}
/**
* Initialize hooks
*/
private function init_hooks() {
add_action('admin_menu', array($this, 'add_admin_menu'));
add_action('admin_init', array($this, 'load_config'));
add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts'));
add_action('wp_ajax_opticore_save_settings', array($this, 'ajax_save_settings'));
add_action('wp_ajax_opticore_reset_section', array($this, 'ajax_reset_section'));
add_action('wp_ajax_opticore_reset_all', array($this, 'ajax_reset_all'));
}
/**
* Load configuration
*/
public function load_config() {
if (file_exists(OPTICORE_PLUGIN_DIR . 'includes/framework-config.php')) {
require_once OPTICORE_PLUGIN_DIR . 'includes/framework-config.php';
}
}
/**
* Add admin menu
*/
public function add_admin_menu() {
// Get translatable strings
$translatable = $this->get_translatable_settings();
if ($this->settings['menu_type'] === 'submenu' && !empty($this->settings['menu_parent'])) {
add_submenu_page(
$this->settings['menu_parent'],
$translatable['framework_title'],
$translatable['menu_title'],
'manage_options',
$this->settings['menu_slug'],
array($this, 'render_framework')
);
} else {
add_menu_page(
$translatable['framework_title'],
$translatable['menu_title'],
'manage_options',
$this->settings['menu_slug'],
array($this, 'render_framework'),
$this->settings['menu_icon'],
$this->settings['menu_position']
);
}
}
/**
* Create section
*/
public function create_section($section) {
$defaults = array(
'id' => '',
'title' => '',
'icon' => 'dashicons-admin-generic',
'fields' => array(),
);
$section = wp_parse_args($section, $defaults);
if (empty($section['id'])) {
return false;
}
$this->sections[$section['id']] = $section;
return true;
}
/**
* Create field
*/
public function create_field($section_id, $field) {
$defaults = array(
'id' => '',
'type' => 'text',
'title' => '',
'subtitle' => '',
'desc' => '',
'default' => '',
'attributes' => array(),
'dependency' => array(),
'sanitize' => '',
);
$field = wp_parse_args($field, $defaults);
if (empty($field['id'])) {
return false;
}
if (isset($this->sections[$section_id])) {
$this->sections[$section_id]['fields'][] = $field;
}
return true;
}
/**
* Get option value
*/
public function get_option($key = '', $default = '') {
$options = get_option($this->settings['database'], array());
if (empty($key)) {
return $options;
}
return isset($options[$key]) ? $options[$key] : $default;
}
/**
* Set option value
*/
public function set_option($key, $value) {
$options = get_option($this->settings['database'], array());
$options[$key] = $value;
update_option($this->settings['database'], $options);
}
/**
* Enqueue scripts and styles
*/
public function enqueue_scripts($hook) {
// Check if we're on the framework page
$valid_hooks = array(
'toplevel_page_' . $this->settings['menu_slug'],
'opticore_page_' . $this->settings['menu_slug'],
);
if (!in_array($hook, $valid_hooks)) {
return;
}
// Enqueue WordPress color picker
wp_enqueue_style('wp-color-picker');
wp_enqueue_script('wp-color-picker');
// Enqueue media uploader
wp_enqueue_media();
// Framework styles
wp_enqueue_style(
'opticore-framework',
OPTICORE_PLUGIN_URL . 'assets/css/framework.css',
array('wp-color-picker'),
OPTICORE_VERSION
);
// Framework scripts
wp_enqueue_script(
'opticore-framework',
OPTICORE_PLUGIN_URL . 'assets/js/framework.js',
array('jquery', 'wp-color-picker'),
OPTICORE_VERSION,
true
);
// Localize script
wp_localize_script('opticore-framework', 'opticoreFramework', array(
'ajaxurl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('opticore_framework_nonce'),
'i18n' => array(
'saving' => __('Saving...', 'opticore'),
'saved' => __('Settings Saved!', 'opticore'),
'error' => __('Error saving settings', 'opticore'),
'resetting' => __('Resetting...', 'opticore'),
'reset' => __('Reset successful!', 'opticore'),
'confirmReset' => __('Are you sure you want to reset this section?', 'opticore'),
'confirmResetAll' => __('Are you sure you want to reset ALL settings? This cannot be undone!', 'opticore'),
),
));
}
/**
* Render framework
*/
public function render_framework() {
$options = $this->get_option();
// Merge translatable settings
$this->settings = array_merge($this->settings, $this->get_translatable_settings());
include OPTICORE_PLUGIN_DIR . 'admin/framework-template.php';
}
/**
* AJAX: Save settings
*/
public function ajax_save_settings() {
check_ajax_referer('opticore_framework_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(array('message' => __('Permission denied.', 'opticore')));
}
$data = isset($_POST['data']) ? $_POST['data'] : array();
$sanitized = array();
// Sanitize each field
foreach ($data as $key => $value) {
$sanitized[$key] = $this->sanitize_field($key, $value);
}
// Update options
update_option($this->settings['database'], $sanitized);
wp_send_json_success(array(
'message' => __('Settings saved successfully!', 'opticore'),
));
}
/**
* AJAX: Reset section
*/
public function ajax_reset_section() {
check_ajax_referer('opticore_framework_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(array('message' => __('Permission denied.', 'opticore')));
}
$section_id = isset($_POST['section']) ? sanitize_text_field($_POST['section']) : '';
if (empty($section_id) || !isset($this->sections[$section_id])) {
wp_send_json_error(array('message' => __('Invalid section.', 'opticore')));
}
$options = $this->get_option();
$section = $this->sections[$section_id];
// Reset fields in this section
foreach ($section['fields'] as $field) {
if (isset($options[$field['id']])) {
unset($options[$field['id']]);
}
}
update_option($this->settings['database'], $options);
wp_send_json_success(array(
'message' => __('Section reset successfully!', 'opticore'),
));
}
/**
* AJAX: Reset all settings
*/
public function ajax_reset_all() {
check_ajax_referer('opticore_framework_nonce', 'nonce');
if (!current_user_can('manage_options')) {
wp_send_json_error(array('message' => __('Permission denied.', 'opticore')));
}
delete_option($this->settings['database']);
wp_send_json_success(array(
'message' => __('All settings reset successfully!', 'opticore'),
));
}
/**
* Sanitize field value
*/
private function sanitize_field($key, $value) {
// Find field type
$field_type = 'text';
foreach ($this->sections as $section) {
foreach ($section['fields'] as $field) {
if ($field['id'] === $key) {
$field_type = $field['type'];
break 2;
}
}
}
// Sanitize based on type
switch ($field_type) {
case 'text':
case 'select':
case 'radio':
return sanitize_text_field($value);
case 'textarea':
return sanitize_textarea_field($value);
case 'email':
return sanitize_email($value);
case 'url':
return esc_url_raw($value);
case 'number':
return absint($value);
case 'checkbox':
case 'switcher':
return (bool) $value;
case 'color':
return sanitize_hex_color($value);
case 'editor':
return wp_kses_post($value);
default:
return sanitize_text_field($value);
}
}
/**
* Render field
*/
public function render_field($field, $value = '') {
// Fields like heading, notice, content don't have ID
$field_id = isset($field['id']) ? $field['id'] : '';
$field_name = $field_id;
// Get value (only for fields with ID)
if ($field_id && $value === '') {
$value = $this->get_option($field_id, isset($field['default']) ? $field['default'] : '');
}
// Check dependency
$dependency_class = '';
$dependency_data = '';
if (!empty($field['dependency'])) {
$dependency_class = 'opticore-dependency-field';
$dependency_data = ' data-dependency="' . esc_attr(json_encode($field['dependency'])) . '"';
}
echo '<div class="opticore-field opticore-field-' . esc_attr($field['type']) . ' ' . esc_attr($dependency_class) . '"' . $dependency_data . '>';
// Field wrapper
echo '<div class="opticore-field-content">';
// Render field based on type
$method = 'render_field_' . $field['type'];
if (method_exists($this, $method)) {
$this->$method($field, $value);
} else {
$this->render_field_text($field, $value);
}
// Field description
if (!empty($field['desc'])) {
echo '<p class="opticore-field-desc">' . wp_kses_post($field['desc']) . '</p>';
}
echo '</div>'; // .opticore-field-content
echo '</div>'; // .opticore-field
}
/**
* Render text field
*/
private function render_field_text($field, $value) {
$attributes = $this->get_field_attributes($field);
echo '<input type="text" ';
echo 'id="' . esc_attr($field['id']) . '" ';
echo 'name="' . esc_attr($field['id']) . '" ';
echo 'value="' . esc_attr($value) . '" ';
echo $attributes;
echo 'class="opticore-input-text" />';
}
/**
* Render textarea field
*/
private function render_field_textarea($field, $value) {
$attributes = $this->get_field_attributes($field);
echo '<textarea ';
echo 'id="' . esc_attr($field['id']) . '" ';
echo 'name="' . esc_attr($field['id']) . '" ';
echo $attributes;
echo 'class="opticore-input-textarea" rows="5">';
echo esc_textarea($value);
echo '</textarea>';
}
/**
* Render number field
*/
private function render_field_number($field, $value) {
$attributes = $this->get_field_attributes($field);
echo '<input type="number" ';
echo 'id="' . esc_attr($field['id']) . '" ';
echo 'name="' . esc_attr($field['id']) . '" ';
echo 'value="' . esc_attr($value) . '" ';
echo $attributes;
echo 'class="opticore-input-number" />';
}
/**
* Render switcher field
*/
private function render_field_switcher($field, $value) {
$checked = !empty($value) ? 'checked' : '';
echo '<label class="opticore-switcher">';
echo '<input type="checkbox" ';
echo 'id="' . esc_attr($field['id']) . '" ';
echo 'name="' . esc_attr($field['id']) . '" ';
echo 'value="1" ';
echo $checked;
echo ' class="opticore-input-switcher" />';
echo '<span class="opticore-switcher-slider"></span>';
echo '<span class="opticore-switcher-on">' . __('ON', 'opticore') . '</span>';
echo '<span class="opticore-switcher-off">' . __('OFF', 'opticore') . '</span>';
echo '</label>';
}
/**
* Render select field
*/
private function render_field_select($field, $value) {
$attributes = $this->get_field_attributes($field);
$options = isset($field['options']) ? $field['options'] : array();
echo '<select ';
echo 'id="' . esc_attr($field['id']) . '" ';
echo 'name="' . esc_attr($field['id']) . '" ';
echo $attributes;
echo 'class="opticore-input-select">';
foreach ($options as $option_value => $option_label) {
echo '<option value="' . esc_attr($option_value) . '" ';
selected($value, $option_value);
echo '>' . esc_html($option_label) . '</option>';
}
echo '</select>';
}
/**
* Render radio field
*/
private function render_field_radio($field, $value) {
$options = isset($field['options']) ? $field['options'] : array();
echo '<div class="opticore-radio-group">';
foreach ($options as $option_value => $option_label) {
$checked = checked($value, $option_value, false);
$radio_id = $field['id'] . '_' . $option_value;
echo '<label class="opticore-radio-label">';
echo '<input type="radio" ';
echo 'id="' . esc_attr($radio_id) . '" ';
echo 'name="' . esc_attr($field['id']) . '" ';
echo 'value="' . esc_attr($option_value) . '" ';
echo $checked;
echo ' class="opticore-input-radio" />';
echo '<span class="opticore-radio-text">' . esc_html($option_label) . '</span>';
echo '</label>';
}
echo '</div>';
}
/**
* Render color field
*/
private function render_field_color($field, $value) {
$default = isset($field['default']) ? $field['default'] : '#667eea';
echo '<input type="text" ';
echo 'id="' . esc_attr($field['id']) . '" ';
echo 'name="' . esc_attr($field['id']) . '" ';
echo 'value="' . esc_attr($value) . '" ';
echo 'data-default-color="' . esc_attr($default) . '" ';
echo 'class="opticore-color-picker" />';
}
/**
* Render media field
*/
private function render_field_media($field, $value) {
$preview = '';
if (!empty($value)) {
$preview = '<div class="opticore-media-preview">';
$preview .= '<img src="' . esc_url($value) . '" alt="" />';
$preview .= '<a href="#" class="opticore-media-remove">×</a>';
$preview .= '</div>';
}
echo '<div class="opticore-media-wrapper">';
echo $preview;
echo '<input type="hidden" ';
echo 'id="' . esc_attr($field['id']) . '" ';
echo 'name="' . esc_attr($field['id']) . '" ';
echo 'value="' . esc_attr($value) . '" ';
echo 'class="opticore-input-media" />';
echo '<button type="button" class="button opticore-media-upload">';
echo '<span class="dashicons dashicons-upload"></span> ';
echo __('Upload', 'opticore');
echo '</button>';
echo '</div>';
}
/**
* Render heading field
*/
private function render_field_heading($field, $value) {
$content = isset($field['content']) ? $field['content'] : '';
echo '<div class="opticore-heading">';
echo wp_kses_post($content);
echo '</div>';
}
/**
* Render content field
*/
private function render_field_content($field, $value) {
$content = isset($field['content']) ? $field['content'] : '';
echo '<div class="opticore-content">';
echo wp_kses_post($content);
echo '</div>';
}
/**
* Render notice field
*/
private function render_field_notice($field, $value) {
$content = isset($field['content']) ? $field['content'] : '';
$notice_type = isset($field['notice_type']) ? $field['notice_type'] : 'info';
echo '<div class="opticore-notice opticore-notice-' . esc_attr($notice_type) . '">';
echo wp_kses_post($content);
echo '</div>';
}
/**
* Get field attributes
*/
private function get_field_attributes($field) {
$attributes = '';
if (!empty($field['attributes']) && is_array($field['attributes'])) {
foreach ($field['attributes'] as $attr_key => $attr_value) {
$attributes .= esc_attr($attr_key) . '="' . esc_attr($attr_value) . '" ';
}
}
// Add placeholder if exists
if (!empty($field['placeholder'])) {
$attributes .= 'placeholder="' . esc_attr($field['placeholder']) . '" ';
}
return $attributes;
}
}