diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6437cd1
--- /dev/null
+++ b/README.md
@@ -0,0 +1,14 @@
+# WPU Error Logs
+
+Make sense of your log files
+
+
+## Roadmap
+
+- [ ] Admin widget
+- [ ] Github actions
+- [ ] Store errors in database
+- [ ] View details for each error : help / error times, etc
+- [ ] Push top errors via slack / mail
+- [ ] Parse yesterday file if it exists.
+- [ ] Ignore some logs
diff --git a/inc/.htaccess b/inc/.htaccess
new file mode 100644
index 0000000..b22492d
--- /dev/null
+++ b/inc/.htaccess
@@ -0,0 +1,4 @@
+deny from all
+
+ Allow From All
+
diff --git a/inc/WPUBaseAdminDatas/README.md b/inc/WPUBaseAdminDatas/README.md
new file mode 100644
index 0000000..b82a15f
--- /dev/null
+++ b/inc/WPUBaseAdminDatas/README.md
@@ -0,0 +1,47 @@
+WPU Base Admin Datas
+---
+
+Add admin datas and a database in your plugin.
+
+## Insert in the INIT hook
+
+```php
+include dirname( __FILE__ ) . '/inc/WPUBaseAdminDatas/WPUBaseAdminDatas.php';
+$this->baseadmindatas = new \wpubaseplugin\WPUBaseAdminDatas();
+$this->baseadmindatas->init(array(
+ 'plugin_id' => 'my_plugin',
+ 'table_name' => 'my_table',
+ 'table_fields' => array(
+ 'value' => array(
+ 'public_name' => 'Value',
+ 'sql' => 'varchar(100) DEFAULT NULL'
+ )
+ )
+));
+```
+
+## Display table :
+
+- Default :
+
+```php
+echo $this->baseadmindatas->get_admin_table();
+```
+
+- Advanced :
+
+```php
+$array_values = false; // ($array_values are automatically retrieved if not a valid array)
+echo $this->baseadmindatas->get_admin_table(
+ $array_values,
+ array(
+ 'perpage' => 10,
+ 'columns' => array('creation' => 'Creation date')
+ )
+);
+```
+
+## TODO
+
+* Uninstall
+* Default field type ( date => timestamp, text => varchar(100) )
diff --git a/inc/WPUBaseAdminDatas/WPUBaseAdminDatas.php b/inc/WPUBaseAdminDatas/WPUBaseAdminDatas.php
new file mode 100644
index 0000000..f42f2cc
--- /dev/null
+++ b/inc/WPUBaseAdminDatas/WPUBaseAdminDatas.php
@@ -0,0 +1,896 @@
+apply_settings($settings);
+ $this->check_database();
+ $this->admin_export();
+ add_action('admin_post_admindatas_' . $this->settings['plugin_id'], array(&$this,
+ 'delete_lines_postAction'
+ ));
+ if ($this->settings['can_edit']) {
+ add_action('admin_post_admindatas_edit_' . $this->settings['plugin_id'], array(&$this,
+ 'edit_line_postAction'
+ ));
+ }
+ if ($this->settings['can_create']) {
+ add_action('admin_post_admindatas_create_' . $this->settings['plugin_id'], array(&$this,
+ 'create_line_postAction'
+ ));
+ }
+ }
+
+ public function apply_settings($settings) {
+ $default_settings = array(
+ 'plugin_id' => 'my_plugin',
+ 'admin_url' => 'admin.php',
+ 'table_name' => 'my_table',
+ 'table_fields' => array(
+ 'value_1' => array(
+ 'public_name' => 'Value 1'
+ ),
+ 'value_2' => array(
+ 'public_name' => 'Value 2'
+ )
+ )
+ );
+ if (!is_array($settings)) {
+ $settings = $default_settings;
+ }
+ foreach ($default_settings as $key => $val) {
+ if (!isset($settings[$key])) {
+ $settings[$key] = $val;
+ }
+ }
+
+ // Remove id column
+ if (isset($settings['table_fields']['id'])) {
+ unset($settings['table_fields']['id']);
+ }
+ // Remove creation column
+ if (isset($settings['table_fields']['creation'])) {
+ unset($settings['table_fields']['creation']);
+ }
+
+ // Build query
+ foreach ($settings['table_fields'] as $id => $field) {
+ if (!isset($field['public_name'])) {
+ $settings['table_fields'][$id]['public_name'] = $id;
+ }
+ if (!isset($field['type'])) {
+ $settings['table_fields'][$id]['type'] = isset($field['type']) ? $field['type'] : 'varchar';
+ }
+ if (!isset($field['field_type']) || !in_array($field['field_type'], $this->field_types)) {
+ $settings['table_fields'][$id]['field_type'] = 'text';
+ }
+ if (!isset($field['edit'])) {
+ $settings['table_fields'][$id]['edit'] = false;
+ }
+ if (!isset($field['create'])) {
+ $settings['table_fields'][$id]['create'] = false;
+ }
+ }
+
+ if (!isset($settings['user_level'])) {
+ $settings['user_level'] = $this->user_level;
+ }
+
+ if (!isset($settings['handle_database'])) {
+ $settings['handle_database'] = true;
+ }
+
+ if (!isset($settings['can_create']) || !current_user_can($settings['user_level'])) {
+ $settings['can_create'] = false;
+ }
+
+ if (!isset($settings['can_edit']) || !current_user_can($settings['user_level'])) {
+ $settings['can_edit'] = $settings['can_create'];
+ }
+
+ $this->settings = $settings;
+
+ $this->user_level = $settings['user_level'];
+ $this->pageid = $this->settings['plugin_id'];
+ if (isset($this->settings['plugin_pageid'])) {
+ $this->pageid = $this->settings['plugin_pageid'];
+ }
+ $this->pagename = admin_url($this->settings['admin_url'] . '?page=' . $this->pageid);
+ $this->sql_option_name = $this->settings['plugin_id'] . '_' . $this->settings['table_name'] . '_version';
+
+ global $wpdb;
+ $this->tablename = $wpdb->prefix . $this->settings['table_name'];
+ }
+
+ /* ----------------------------------------------------------
+ Database Creation
+ ---------------------------------------------------------- */
+
+ public function drop_database() {
+ global $wpdb;
+ $wpdb->query("DROP TABLE IF EXISTS " . $this->tablename);
+ delete_option($this->sql_option_name);
+ }
+
+ public function check_database() {
+ if ($this->settings['handle_database']) {
+ return;
+ }
+ global $wpdb;
+
+ // Assemble fields
+ $fields_query = array(
+ 'id mediumint(8) unsigned NOT NULL auto_increment',
+ 'creation TIMESTAMP DEFAULT CURRENT_TIMESTAMP',
+ 'PRIMARY KEY (id)'
+ );
+
+ // Build query
+ /* Two spaces to avoid temporary table WP fix */
+ $sql_query = "CREATE TABLE " . $this->tablename;
+ $sql_query .= " (\n" . implode(",\n", $fields_query) . "\n)";
+ $sql_query .= " DEFAULT CHARSET=utf8;";
+
+ // If query has changed since last time
+ $sql_md5 = md5(serialize($this->settings['table_fields']));
+ $sql_option_value = get_option($this->sql_option_name);
+ if ($sql_md5 != $sql_option_value) {
+ // Update or create table
+ require_once ABSPATH . 'wp-admin/includes/upgrade.php';
+
+ // Create table
+ maybe_create_table($this->tablename, $sql_query);
+
+ foreach ($this->settings['table_fields'] as $column_name => $col) {
+ switch ($col['type']) {
+ case 'varchar':
+ $col_sql = 'varchar(100) DEFAULT NULL';
+ break;
+ case 'number':
+ $col_sql = 'MEDIUMINT UNSIGNED';
+ break;
+ case 'timestamp':
+ $col_sql = 'TIMESTAMP';
+ break;
+ default:
+ $col_sql = $col['sql'];
+ }
+
+ maybe_add_column($this->tablename, $column_name, 'ALTER TABLE ' . $this->tablename . ' ADD ' . $column_name . ' ' . $col_sql);
+ }
+
+ // Update option hash
+ update_option($this->sql_option_name, $sql_md5);
+ }
+ }
+
+ /* ----------------------------------------------------------
+ Utilities : Requests
+ ---------------------------------------------------------- */
+
+ public function get_pager_limit($perpage = false, $req_details = '') {
+ global $wpdb;
+
+ // Ensure good format for table name
+ if (empty($this->tablename) || !preg_match('/^([A-Za-z0-9_-]+)$/', $this->tablename)) {
+ return array(
+ 'pagenum' => 0,
+ 'max_pages' => 0,
+ 'limit' => ''
+ );
+ }
+
+ // Ensure good format for perpage
+ if (empty($perpage) || !is_numeric($perpage)) {
+ $perpage = $this->default_perpage;
+ }
+
+ // Get number of elements in table
+ $elements_count = $wpdb->get_var("SELECT COUNT(*) FROM " . $this->tablename . $req_details);
+
+ // Get max page number
+ $max_pages = ceil($elements_count / $perpage);
+
+ // Obtain Page Number
+ $pagenum = (isset($_GET['pagenum']) && is_numeric($_GET['pagenum']) ? $_GET['pagenum'] : 1);
+ $pagenum = min($pagenum, $max_pages);
+
+ // Set SQL limit
+ $limit_min = max(0, ($pagenum * $perpage - $perpage));
+ $limit = 'LIMIT ' . $limit_min . ', ' . $perpage;
+
+ return array(
+ 'pagenum' => $pagenum,
+ 'max_pages' => $max_pages,
+ 'max_elements' => $elements_count,
+ 'limit' => $limit
+ );
+ }
+
+ /* ----------------------------------------------------------
+ Lines
+ ---------------------------------------------------------- */
+
+ public function get_line($line_id) {
+ return $this->get_line_by('id', $line_id, '%d');
+ }
+
+ public function get_line_by($field, $value = '', $value_type = '%s') {
+ global $wpdb;
+ return $wpdb->get_row($wpdb->prepare("SELECT * FROM " . $this->tablename . " WHERE " . $field . "=" . $value_type, $value), ARRAY_A);
+ }
+
+ /* ----------------------------------------------------------
+ Create line
+ ---------------------------------------------------------- */
+
+ public function create_line_postAction() {
+ $_return_value = false;
+ if (current_user_can($this->user_level) && !empty($_POST) && isset($_POST['admindatas_fields'], $_POST['page']) && is_array($_POST['admindatas_fields'])) {
+ $action_id = 'action-create-form-admin-datas-' . $_POST['page'];
+ if (isset($_POST[$action_id]) && wp_verify_nonce($_POST[$action_id], 'action-create-form-' . $_POST['page'])) {
+ $_return_value = $this->create_line($_POST['admindatas_fields']);
+ }
+ }
+ if (isset($_POST['page']) && is_numeric($_return_value)) {
+ $_back_url = $this->pagename . '&item_id=' . $_return_value;
+ if (isset($_POST['backquery'])) {
+ $_back_url = add_query_arg(array('backquery' => $_POST['backquery']), $_back_url);
+ }
+ wp_redirect($_back_url);
+ die;
+ }
+ }
+
+ public function create_line($datas) {
+ $_datas_create = array();
+ $_return_value = false;
+ foreach ($this->settings['table_fields'] as $id => $field) {
+ if (!isset($datas[$id])) {
+ continue;
+ }
+ /* Invalid field */
+ if (!$this->validate_field_value($field, $datas[$id])) {
+ continue;
+ }
+ $_datas_create[$id] = $datas[$id];
+ }
+ if (!empty($_datas_create)) {
+ global $wpdb;
+ $_return_value = $wpdb->insert(
+ $this->tablename,
+ $_datas_create
+ );
+ if ($wpdb->last_error !== '') {
+ $wpdb->print_error();
+ }
+ }
+ if ($_return_value) {
+ $_return_value = $wpdb->insert_id;
+ }
+ return $_return_value;
+ }
+
+ /* ----------------------------------------------------------
+ Edit line
+ ---------------------------------------------------------- */
+
+ public function edit_line_postAction() {
+ if (current_user_can($this->user_level) && !empty($_POST) && isset($_POST['edit_line'], $_POST['admindatas_fields'], $_POST['page']) && is_numeric($_POST['edit_line']) && is_array($_POST['admindatas_fields'])) {
+ $action_id = 'action-edit-form-admin-datas-' . $_POST['page'];
+ if (isset($_POST[$action_id]) && wp_verify_nonce($_POST[$action_id], 'action-edit-form-' . $_POST['page'])) {
+ $this->edit_line($_POST['edit_line'], $_POST['admindatas_fields']);
+ }
+ }
+ if (isset($_POST['page'], $_POST['edit_line']) && is_numeric($_POST['edit_line'])) {
+ $_back_url = $this->pagename . '&item_id=' . $_POST['edit_line'];
+ if (isset($_POST['backquery'])) {
+ $_back_url = add_query_arg(array('backquery' => $_POST['backquery']), $_back_url);
+ }
+ wp_redirect($_back_url);
+ die;
+ }
+ }
+
+ public function edit_line($item_id, $new_datas) {
+ $_datas = $this->get_line($item_id);
+ $_datas_update = array();
+ foreach ($new_datas as $key => $var) {
+ /* Same value */
+ if ($_datas[$key] == $var) {
+ continue;
+ }
+ /* Fake field */
+ if (!isset($this->settings['table_fields'][$key])) {
+ continue;
+ }
+ /* Invalid field */
+ if (!$this->validate_field_value($this->settings['table_fields'][$key], $var)) {
+ continue;
+ }
+ $_datas_update[$key] = $var;
+ }
+
+ if (!empty($_datas_update)) {
+ global $wpdb;
+ $wpdb->update(
+ $this->tablename,
+ $_datas_update,
+ array('ID' => $item_id)
+ );
+ }
+ }
+
+ /* ----------------------------------------------------------
+ Validate
+ ---------------------------------------------------------- */
+
+ public function validate_field_value($field, $value) {
+ switch ($field['field_type']) {
+ case 'email':
+ return !!filter_var($value, FILTER_VALIDATE_EMAIL);
+ break;
+
+ case 'url':
+ return !!filter_var($value, FILTER_VALIDATE_URL);
+ break;
+
+ case 'number':
+ return is_numeric($value);
+ break;
+
+ default:
+ return true;
+ }
+
+ }
+
+ /* ----------------------------------------------------------
+ Delete lines
+ ---------------------------------------------------------- */
+
+ public function delete_lines_postAction() {
+ if (current_user_can($this->user_level) && !empty($_POST) && isset($_POST['select_line'], $_POST['page']) && is_array($_POST['select_line'])) {
+ $action_id = 'action-main-form-admin-datas-' . $_POST['page'];
+ if (isset($_POST[$action_id]) && wp_verify_nonce($_POST[$action_id], 'action-main-form-' . $_POST['page'])) {
+ $this->delete_lines($_POST['select_line']);
+ }
+ }
+ if (isset($_POST['page'])) {
+ wp_redirect($this->pagename);
+ die;
+ }
+ }
+
+ public function delete_lines($lines = array()) {
+ $_lines = array();
+ foreach ($lines as $line) {
+ // Stop if a line is not valid
+ if (!is_numeric($line)) {
+ break;
+ }
+ $_lines[] = $line;
+ }
+ if (!empty($_lines)) {
+ global $wpdb;
+ $wpdb->query(
+ "DELETE FROM " . $this->tablename . " WHERE ID IN(" . implode(",", $_lines) . ");"
+ );
+ }
+ }
+
+ /* ----------------------------------------------------------
+ Utilities : Export
+ ---------------------------------------------------------- */
+
+ public function export_array_to_csv($array, $name) {
+ if (isset($array[0])) {
+ header('Content-Type: application/csv');
+ header('Content-Disposition: attachment; filename=export-list-' . $name . '-' . date_i18n('y-m-d') . '.csv');
+ header('Pragma: no-cache');
+ echo implode(';', array_keys($array[0])) . "\n";
+ foreach ($array as $line) {
+ echo implode(';', $line) . "\n";
+ }
+ die;
+ }
+ }
+
+ /* ----------------------------------------------------------
+ Export all
+ ---------------------------------------------------------- */
+
+ public function admin_export() {
+ if (!is_admin()) {
+ return;
+ }
+ if (!current_user_can($this->settings['user_level'])) {
+ return;
+ }
+ if (!$this->tablename) {
+ return;
+ }
+ if (!isset($_GET['wpubaseadmindatas_export']) || ($_GET['wpubaseadmindatas_export'] != $this->tablename)) {
+ return;
+ }
+ $this->export_datas();
+ }
+
+ /* Thanks to https://stackoverflow.com/a/55482704 */
+ public function export_datas() {
+ global $wpdb;
+
+ $query = "SELECT * FROM " . $this->tablename . " WHERE 1=1";
+ $columns = $wpdb->get_results("SHOW COLUMNS FROM " . $this->tablename, ARRAY_A);
+
+ /* Filters */
+ if (isset($_GET['filter_key'], $_GET['filter_value'])) {
+ $has_filter_key = true;
+ $query .= " AND " . esc_sql($_GET['filter_key']) . " = '" . esc_sql($_GET['filter_value']) . "'";
+ }
+
+ /* Search */
+ if (isset($_GET['where_text']) && $_GET['where_text']) {
+ $where = array();
+ $where_text = trim($_GET['where_text']);
+ foreach ($columns as $field) {
+ $id = $field['Field'];
+ if ($id != 'id' && $id != 'creation') {
+ $where[] = "$id LIKE '%" . esc_sql($_GET['where_text']) . "%'";
+ }
+ }
+ $query .= " AND (" . implode(' OR ', $where) . ")";
+ }
+
+ $rows = $wpdb->get_results($query, ARRAY_A);
+
+ $fp = fopen('php://output', 'w');
+
+ header('Content-Type: application/csv');
+ header("Content-Disposition: attachment; filename=export-" . $this->tablename . "-" . date_i18n('Ymd-His') . ".csv");
+ header('Pragma: no-cache');
+
+ if (is_array($columns) && !empty($columns)) {
+ fputcsv($fp, array_column($columns, 'Field'));
+ }
+
+ if (!empty($rows)) {
+ foreach ($rows as $row) {
+ fputcsv($fp, $row);
+ }
+ }
+
+ fclose($fp);
+ exit;
+ }
+
+ /* ----------------------------------------------------------
+ Utilities : Display
+ ---------------------------------------------------------- */
+
+ public function get_admin_view($values = array(), $args = array()) {
+ if (isset($_GET['item_id']) && is_numeric($_GET['item_id'])) {
+ $_content = $this->get_admin_item($_GET['item_id']);
+ } elseif (isset($_GET['create'])) {
+ $_content = $this->get_admin_item();
+ } else {
+ $args['is_admin_view'] = true;
+ $_content = $this->get_admin_table($values, $args);
+ }
+
+ return $_content;
+ }
+
+ public function get_admin_item($item_id = false) {
+ $_html = '';
+
+ $_back_query = '';
+ $_back_url_args = array();
+ $page_id = $this->get_page_id();
+ $datas = $item_id ? $this->get_line($item_id) : array();
+
+ /* Save back query if valid */
+ if (isset($_GET['backquery'])) {
+ $_back_args = json_decode(base64_decode($_GET['backquery']));
+ if (is_object($_back_args)) {
+ $_back_url_args = (array) $_back_args;
+ $_back_query = $_GET['backquery'];
+ }
+ }
+
+ /* Diff between edit & create form */
+ $_has_form = ($this->settings['can_edit'] && $item_id) || ($this->settings['can_create'] && !$item_id);
+
+ /* Actions */
+ $_form_action = $item_id ? 'admindatas_edit_' : 'admindatas_create_';
+ $_form_nonce = $item_id ? 'action-edit-form-' : 'action-create-form-';
+
+ if ($_has_form) {
+ $_html .= '
';
+ }
+
+ return $_html;
+ }
+
+ public function get_admin_table($values = array(), $args = array()) {
+ global $wpdb;
+
+ $pagination = '';
+
+ $is_admin_view = isset($args['is_admin_view']) && $args['is_admin_view'];
+ $export_url = 'index.php?wpubaseadmindatas_export=' . $this->tablename;
+ $export_url_base = $export_url;
+
+ if (!is_array($args)) {
+ $args = array();
+ }
+
+ // Per page
+ if (!isset($args['perpage']) || !is_numeric($args['perpage'])) {
+ $args['perpage'] = $this->default_perpage;
+ }
+
+ // Add ID
+ $default_columns = array(
+ 'creation' => array(
+ 'has_filter' => false,
+ 'label' => 'Creation date'
+ ),
+ 'id' => array(
+ 'has_filter' => false,
+ 'label' => 'ID'
+ )
+ );
+ $base_columns = array();
+ $args['primary_column'] = 'id';
+ if (isset($args['columns']) && is_array($args['columns'])) {
+ $new_args_column = array();
+ foreach ($args['columns'] as $id => $field) {
+ if (!isset($args['primary_column'])) {
+ $args['primary_column'] = $id;
+ }
+ $has_filter = false;
+ $field_label = $field;
+ if (is_array($field)) {
+ $field_label = $id;
+ if (isset($field['label'])) {
+ $field_label = $field['label'];
+ }
+ if (isset($field['has_filter'])) {
+ $has_filter = $field['has_filter'];
+ }
+ }
+ $new_args_column[$id] = array(
+ 'has_filter' => $has_filter,
+ 'label' => $field_label
+ );
+ }
+ $args['columns'] = $new_args_column;
+ }
+ $base_columns = array_merge($base_columns, $default_columns);
+
+ // Default columns
+ if (!isset($args['columns'])) {
+ $args['columns'] = $base_columns;
+ }
+
+ // Filter results
+ $where_glue = (isset($_GET['where_glue']) && in_array($_GET['where_glue'], array('AND', 'OR'))) ? $_GET['where_glue'] : 'AND';
+ $where = array();
+ $where_text = isset($_GET['where_text']) ? trim($_GET['where_text']) : '';
+ if (!empty($where_text)) {
+ $where_glue = 'OR';
+ $export_url .= '&where_text=' . esc_html($_GET['where_text']);
+ foreach ($args['columns'] as $id => $name) {
+ if ($id != 'id' && $id != 'creation') {
+ $where[] = "$id LIKE '%" . esc_sql($where_text) . "%'";
+ }
+ }
+ }
+
+ // Filter
+ $has_filter_key = false;
+ if (isset($_GET['filter_key'], $_GET['filter_value'])) {
+ $has_filter_key = true;
+ $export_url .= '&filter_key=' . esc_html($_GET['filter_key']) . '&filter_value=' . esc_html($_GET['filter_value']);
+ $where[] = esc_sql($_GET['filter_key']) . " = '" . esc_sql($_GET['filter_value']) . "'";
+ }
+
+ // Order results
+ if (!isset($args['order'])) {
+ $args['order'] = isset($_GET['order']) && in_array($_GET['order'], array('asc', 'desc')) ? $_GET['order'] : 'desc';
+ }
+
+ if (!isset($args['orderby'])) {
+ $args['orderby'] = isset($_GET['orderby']) && array_key_exists($_GET['orderby'], $args['columns']) ? $_GET['orderby'] : 'id';
+ }
+
+ // Build filter query
+ $sql_where = '';
+ if (!empty($where)) {
+ $sql_where .= " WHERE " . implode(" " . $where_glue . " ", $where) . " ";
+ }
+
+ // Build order
+ $sql_order = ' ORDER BY ' . $args['orderby'] . ' ' . strtoupper($args['order']) . ' ';
+
+ // Default pagenum & max pages
+ if (!isset($args['pagenum']) || !isset($args['max_pages']) || !isset($args['limit']) || !isset($args['max_elements'])) {
+ $pager = $this->get_pager_limit($args['perpage'], $sql_where);
+ if (!isset($args['pagenum'])) {
+ $args['pagenum'] = $pager['pagenum'];
+ }
+ if (!isset($args['max_pages'])) {
+ $args['max_pages'] = $pager['max_pages'];
+ }
+ if (!isset($args['limit'])) {
+ $args['limit'] = $pager['limit'];
+ }
+ if (!isset($args['max_elements'])) {
+ $args['max_elements'] = $pager['max_elements'];
+ }
+ }
+
+ // Default list
+ $total_nb = 0;
+ if (empty($values) || !is_array($values)) {
+ $columns = array_keys($args['columns']);
+ $query = "SELECT " . implode(", ", $columns) . " FROM " . $this->tablename . " " . $sql_where . " " . $sql_order . " " . $args['limit'];
+ $query_total = "SELECT count(" . $columns[0] . ") FROM " . $this->tablename . " " . $sql_where;
+ $values = $wpdb->get_results($query);
+ $total_nb = $wpdb->get_var($query_total);
+ }
+
+ $page_id = $this->get_page_id();
+ if (isset($args['page_id'])) {
+ $page_id = $args['page_id'];
+ }
+
+ $url_items_clear = array(
+ 'order' => $args['order'],
+ 'orderby' => $args['orderby'],
+ 'page' => $page_id
+ );
+ $url_items = $url_items_clear;
+ $url_items['pagenum'] = '%#%';
+ $url_items['where_glue'] = $where_glue;
+ $url_items['where_text'] = $where_text;
+
+ /* Back query used in single page */
+ $url_items_edit = $url_items;
+ unset($url_items_edit['pagenum']);
+ $_back_query = base64_encode(json_encode($url_items_edit));
+
+ $page_links = paginate_links(array(
+ 'base' => add_query_arg($url_items),
+ 'format' => '',
+ 'prev_text' => '«',
+ 'next_text' => '»',
+ 'total' => $args['max_pages'],
+ 'current' => $args['pagenum']
+ ));
+
+ $start_element = max(0, ($args['pagenum'] - 1) * $args['perpage'] + 1);
+ $end_element = min($args['pagenum'] * $args['perpage'], $args['max_elements']);
+ $pagination = '';
+ $pagination .= '
';
+ $pagination .= sprintf(__('Items %s - %s', $this->settings['plugin_id']), $start_element, $end_element);
+ if ($total_nb) {
+ $pagination .= ' / ' . $total_nb;
+ }
+ $pagination .= '
';
+ if ($page_links) {
+ $pagination .= '
' . $page_links . '
';
+ }
+ $pagination .= '
';
+
+ $clear_form = '';
+ if ($has_filter_key) {
+ $clear_form .= '';
+ $clear_form .= sprintf(__('Filter : %s • Value : %s', $this->settings['plugin_id']), esc_html($_GET['filter_key']), esc_html($_GET['filter_value']));
+ $clear_form .= '
' . __('Reset') . '';
+ $clear_form .= '
';
+ }
+
+ $search_form = '';
+
+ $has_id = isset($values[0]) && is_object($values[0]) && isset($values[0]->id);
+
+ $content = '';
+ $content .= $clear_form;
+ $content .= $search_form;
+ $content .= $pagination;
+ $content .= '' . __('Export all') . '';
+ if ($where_text || $has_filter_key) {
+ $content .= ' ' . __('Export filtered view') . '';
+ }
+ $content .= <<
+.admindatas-search-filter{
+ text-align: right;
+}
+.admindatas-search-form {margin:1em 0;}
+@media (min-width:768px) {
+ .admindatas-delete-button {float: left;}
+}
+@media (max-width:767px) {
+ .admindatas-search-form .search-box {position: relative!important;height:auto;margin:0;}
+}
+
+HTML;
+ return $content;
+ }
+
+ /* ----------------------------------------------------------
+ Helpers
+ ---------------------------------------------------------- */
+
+ public function get_page_id() {
+ $screen = get_current_screen();
+ $page_id = '';
+ if (property_exists($screen, 'parent_base')) {
+ $page_id = $screen->parent_base;
+ }
+ return $page_id;
+ }
+}
diff --git a/inc/WPUBaseAdminPage/README.md b/inc/WPUBaseAdminPage/README.md
new file mode 100644
index 0000000..f357864
--- /dev/null
+++ b/inc/WPUBaseAdminPage/README.md
@@ -0,0 +1,45 @@
+WPU Base Admin Page
+---
+
+Add an admin page in your plugin.
+
+## Insert in the plugins_loaded hook
+
+```php
+$admin_pages = array(
+ 'main' => array(
+ 'menu_name' => 'Base plugin',
+ 'name' => 'Main page',
+ 'settings_link' => true,
+ 'settings_name' => 'Settings',
+ 'function_content' => array(&$this,
+ 'page_content__main'
+ ),
+ 'function_action' => array(&$this,
+ 'page_action__main'
+ )
+ ),
+ 'subpage' => array(
+ 'parent' => 'main',
+ 'name' => 'Subpage page',
+ 'function_content' => array(&$this,
+ 'page_content__subpage'
+ ),
+ 'function_action' => array(&$this,
+ 'page_action__subpage'
+ )
+ )
+);
+
+$pages_options = array(
+ 'id' => 'wpubaseplugin',
+ 'level' => 'manage_options',
+ 'basename' => plugin_basename(__FILE__)
+);
+
+// Init admin page
+include dirname( __FILE__ ) . '/inc/WPUBaseAdminPage/WPUBaseAdminPage.php';
+$this->adminpages = new \wpubaseplugin\WPUBaseAdminPage();
+$this->adminpages->init($pages_options, $admin_pages);
+
+```
diff --git a/inc/WPUBaseAdminPage/WPUBaseAdminPage.php b/inc/WPUBaseAdminPage/WPUBaseAdminPage.php
new file mode 100644
index 0000000..16cd3e0
--- /dev/null
+++ b/inc/WPUBaseAdminPage/WPUBaseAdminPage.php
@@ -0,0 +1,274 @@
+options = $options;
+ $this->pages = $pages;
+ $this->prefix = $this->options['id'] . '-';
+ $this->pages = $this->set_pages($this->pages);
+ add_action('admin_menu', array(&$this,
+ 'set_admin_menu'
+ ));
+ add_action('admin_bar_menu', array(&$this,
+ 'set_adminbar_menu'
+ ), 100);
+ add_filter("plugin_action_links_" . $this->options['basename'], array(&$this,
+ 'add_settings_link'
+ ));
+ // Only on a plugin admin page
+ $current_page = $this->get_page();
+ if (array_key_exists($current_page, $this->pages)) {
+ add_action('admin_post_' . $this->options['id'], array(&$this,
+ 'set_admin_page_main_postAction'
+ ));
+ }
+ foreach ($this->pages as $p_id => $p) {
+ if ($p_id == $current_page) {
+ foreach ($p['actions'] as $action) {
+ add_action($action[0], $action[1]);
+ }
+ foreach ($p['filters'] as $filter) {
+ add_filter($filter[0], $filter[1]);
+ }
+ }
+ }
+ }
+
+ public function set_pages($pages) {
+ foreach ($pages as $id => $page) {
+ $page['id'] = $this->prefix . $id;
+ $page['url'] = admin_url('admin.php?page=' . $page['id']);
+ if (!isset($page['section'])) {
+ $page['section'] = '';
+ } else {
+ $path = (strpos($page['section'], '?') !== false ? '&' : '?') . 'page=' . $page['id'];
+ $page['url'] = admin_url($page['section'] . $path);
+ }
+ if (!isset($page['name'])) {
+ $page['name'] = $id;
+ }
+ if (!isset($page['menu_name'])) {
+ $page['menu_name'] = $page['name'];
+ }
+ if (!isset($page['settings_name'])) {
+ $page['settings_name'] = $page['name'];
+ }
+ if (!isset($page['parent'])) {
+ $page['parent'] = '';
+ }
+ if (!isset($page['actions'])) {
+ $page['actions'] = array();
+ }
+ if (!isset($page['filters'])) {
+ $page['filters'] = array();
+ }
+ if (!isset($page['display_banner_menu'])) {
+ $page['display_banner_menu'] = false;
+ }
+ if (!isset($page['function_content'])) {
+ $page['function_content'] = array(&$this,
+ 'page_content__' . $id
+ );
+ }
+ if (!isset($page['function_action'])) {
+ $page['function_action'] = array(&$this,
+ 'page_action__' . $id
+ );
+ }
+ if (!isset($page['level'])) {
+ $page['level'] = $this->options['level'];
+ }
+ if (!isset($page['icon_url'])) {
+ $page['icon_url'] = '';
+ }
+ if (!isset($page['has_file'])) {
+ $page['has_file'] = false;
+ }
+ if (!isset($page['settings_link'])) {
+ $page['settings_link'] = false;
+ }
+ if (!isset($page['has_form'])) {
+ $page['has_form'] = true;
+ }
+ if (!isset($page['page_help'])) {
+ $page['page_help'] = false;
+ }
+ $pages[$id] = $page;
+ }
+ return $pages;
+ }
+
+ public function set_admin_menu() {
+ $parent = false;
+ foreach ($this->pages as $id => $page) {
+
+ $page_id = $page['id'];
+ $page_action = array(&$this,
+ 'set_admin_page_main'
+ );
+ $page_title = $page['name'];
+ if (isset($page['page_title'])) {
+ $page_title = $page['page_title'];
+ }
+
+ // A parent is defined
+ if (array_key_exists($page['parent'], $this->pages)) {
+ $this->page_hook = add_submenu_page($this->prefix . $page['parent'], $page_title, $page['menu_name'], $page['level'], $page_id, $page_action);
+ // A section is defined
+ } elseif (!empty($page['section'])) {
+ $this->page_hook = add_submenu_page($page['section'], $page_title, $page['menu_name'], $page['level'], $page_id, $page_action);
+ } else {
+ // Create a parent menu page
+ add_menu_page($page['name'], $page['menu_name'], $page['level'], $page_id, $page_action, $page['icon_url']);
+ $this->page_hook = add_submenu_page($page_id, $page_title, $page['name'], $page['level'], $page_id, $page_action);
+ }
+ add_action('load-' . $this->page_hook, array(&$this, 'add_help'), 10, 1);
+ }
+ }
+
+ public function add_help($arg) {
+
+ $screen = get_current_screen();
+ if (!isset($_GET['page']) || !is_object($screen) || !property_exists($screen, 'base')) {
+ return;
+ }
+ $base_str = str_replace(array($this->prefix, 'toplevel_page_'), '', $screen->base);
+ // Add help tabs
+ if (isset($this->pages[$base_str]['page_help']) && !empty($this->pages[$base_str]['page_help'])) {
+ $help_page = $this->pages[$base_str]['page_help'];
+ // If multiple one pages are available
+ if (is_array($help_page)) {
+ foreach ($help_page as $id => $help_tab) {
+ $help_tab['title'] = isset($help_tab['title']) ? $help_tab['title'] : $id;
+ $help_tab['content'] = isset($help_tab['content']) ? $help_tab['content'] : $help_tab['title'];
+ $screen->add_help_tab(array(
+ 'id' => 'help-' . $base_str . '-' . $id,
+ 'title' => $help_tab['title'],
+ 'content' => $help_tab['content']
+ ));
+ }
+ } else {
+ // If only one tab available
+ $screen->add_help_tab(array(
+ 'id' => 'help-' . $base_str,
+ 'title' => __('Help'),
+ 'content' => $help_page
+ ));
+ }
+ }
+
+ // Add help sidebar
+ if (isset($this->pages[$base_str]['page_help_sidebar']) && !empty($this->pages[$base_str]['page_help_sidebar'])) {
+ $screen->set_help_sidebar($this->pages[$base_str]['page_help_sidebar']);
+ }
+ }
+
+ public function set_adminbar_menu($admin_bar) {
+ foreach ($this->pages as $id => $page) {
+ if (!$page['display_banner_menu']) {
+ continue;
+ }
+ $menu_details = array(
+ 'id' => $page['id'],
+ 'title' => $page['menu_name'],
+ 'href' => $page['url'],
+ 'meta' => array(
+ 'title' => $page['menu_name']
+ )
+ );
+ if (isset($page['parent']) && array_key_exists($page['parent'], $this->pages)) {
+ $menu_details['parent'] = $this->prefix . $page['parent'];
+ }
+ $admin_bar->add_menu($menu_details);
+ }
+ }
+
+ public function add_settings_link($links) {
+ foreach ($this->pages as $id => $page) {
+ if (!$page['settings_link']) {
+ continue;
+ }
+ $settings_link = '' . $page['settings_name'] . '';
+ array_unshift($links, $settings_link);
+ }
+ return $links;
+ }
+
+ public function set_admin_page_main() {
+ $page = $this->get_page();
+
+ echo $this->get_wrapper_start();
+
+ // Default Form
+ if ($this->pages[$page]['has_form']):
+ echo '';
+ endif;
+
+ echo $this->get_wrapper_end();
+ }
+
+ public function set_admin_page_main_postAction() {
+ $page = $this->get_page();
+ $action_id = 'action-main-form-' . $this->options['id'] . '-' . $page;
+ if (empty($_POST) || !isset($_POST[$action_id]) || !wp_verify_nonce($_POST[$action_id], 'action-main-form-' . $page)) {
+ return;
+ }
+ call_user_func($this->pages[$page]['function_action']);
+ wp_redirect($this->pages[$page]['url']);
+ }
+
+ private function get_wrapper_start() {
+ return '' . get_admin_page_title() . '
';
+ }
+
+ private function get_wrapper_end() {
+ return '';
+ }
+
+ private function get_page() {
+ $page = '';
+ if (isset($_GET['page'])) {
+ $page = str_replace($this->options['id'] . '-', '', $_GET['page']);
+ }
+ if (isset($_POST['page_name'])) {
+ $page = str_replace($this->options['id'] . '-', '', $_POST['page_name']);
+ }
+ return $page;
+ }
+}
diff --git a/inc/WPUBaseCron/README.md b/inc/WPUBaseCron/README.md
new file mode 100644
index 0000000..5b35b4e
--- /dev/null
+++ b/inc/WPUBaseCron/README.md
@@ -0,0 +1,25 @@
+WPU Base Cron
+---
+
+Add Cron to your plugin.
+
+## Insert in the plugins_loaded hook
+
+```php
+include 'inc/WPUBaseCron.php';
+$this->basecron = new \wpubaseplugin\WPUBaseCron(array(
+ 'pluginname' => 'Base Plugin', // Default : [Namespace]
+ 'cronhook' => 'wpubaseplugin__cron_hook', // Default : [namespace__cron_hook]
+ 'croninterval' => 900 // Default : [3600]
+));
+/* Callback when hook is triggered by the cron */
+add_action('wpubaseplugin__cron_hook', array(&$this,
+ 'wpubaseplugin__callback_function'
+), 10);
+```
+
+## uninstall hook ##
+
+```php
+$this->basecron->uninstall();
+```
diff --git a/inc/WPUBaseCron/WPUBaseCron.php b/inc/WPUBaseCron/WPUBaseCron.php
new file mode 100644
index 0000000..3eb0265
--- /dev/null
+++ b/inc/WPUBaseCron/WPUBaseCron.php
@@ -0,0 +1,160 @@
+ns = preg_replace('/\W+/', '', __NAMESPACE__);
+
+ /* Settings */
+ $this->pluginname = isset($settings['pluginname']) ? $settings['pluginname'] : ucfirst($this->ns);
+ $this->cronhook = isset($settings['cronhook']) ? $settings['cronhook'] : $this->ns . '__cron_hook';
+ $this->croninterval = isset($settings['croninterval']) ? $settings['croninterval'] : 3600;
+
+ /* Internal values */
+ $this->cronoption = $this->cronhook . '_croninterval';
+ $this->cronschedule = $this->cronhook . '_schedule';
+ $this->cronlastexec = $this->cronhook . '_lastexec';
+
+ /* Hooks */
+ add_filter('cron_schedules', array(&$this,
+ 'add_schedule'
+ ));
+ add_action($this->cronhook, array(&$this,
+ 'store_execution_time'
+ ), 99);
+
+ /* Check cron */
+ add_action('wp', array(&$this,
+ 'check_cron'
+ ));
+ add_action('admin_init', array(&$this,
+ 'check_cron'
+ ));
+ }
+
+ /* Create schedule */
+ public function add_schedule($schedules) {
+ $schedules[$this->cronschedule] = array(
+ 'interval' => $this->croninterval,
+ 'display' => $this->pluginname . ' - Custom'
+ );
+ return $schedules;
+ }
+
+ /* Schedule cron if possible */
+ public function check_cron() {
+ $croninterval = intval(get_option($this->cronoption), 10);
+ $schedule = wp_next_scheduled($this->cronhook);
+
+ // If no schedule cron or new interval or incorrect interval
+ if (!$schedule || $croninterval != $this->croninterval) {
+ $this->install();
+ return;
+ }
+
+ // Schedule is too in the future
+ if ($schedule - time() - $croninterval > 0) {
+ do_action($this->cronhook);
+ $this->install();
+ return;
+ }
+
+ // Schedule is too in the past
+ if ($schedule - time() < $croninterval * 12 * -1) {
+ do_action($this->cronhook);
+ $this->install();
+ }
+ }
+
+ /* ----------------------------------------------------------
+ Time
+ ---------------------------------------------------------- */
+
+ /* Get time */
+ public function get_time_details($schedule, $delta) {
+ if (!is_numeric($schedule) || !is_numeric($delta)) {
+ return false;
+ }
+ $minutes = 0;
+ $seconds = abs($delta);
+ if ($seconds >= 60) {
+ $minutes = (int) ($seconds / 60);
+ $seconds = $seconds % 60;
+ }
+ return array(
+ 'timestamp' => $schedule,
+ 'delta' => $delta,
+ 'min' => $minutes,
+ 'sec' => $seconds
+ );
+ }
+
+ /* Get next scheduled */
+ public function get_next_scheduled() {
+ $schedule = wp_next_scheduled($this->cronhook);
+ return $this->get_time_details($schedule, $schedule - time());
+ }
+
+ /* Get previous execution */
+ public function get_previous_exec() {
+ $schedule = get_option($this->cronlastexec);
+ return $this->get_time_details($schedule, time() - $schedule);
+ }
+
+ public function store_execution_time() {
+ update_option($this->cronlastexec, time());
+ }
+
+ /* ----------------------------------------------------------
+ Activation
+ ---------------------------------------------------------- */
+
+ /* Create cron */
+ public function install() {
+ wp_clear_scheduled_hook($this->cronhook);
+ update_option($this->cronoption, $this->croninterval);
+ wp_schedule_event(time() + $this->croninterval, $this->cronschedule, $this->cronhook);
+ }
+
+ /* Destroy cron */
+ public function uninstall() {
+ wp_clear_scheduled_hook($this->cronhook);
+ delete_option($this->cronlastexec);
+ delete_option($this->cronoption);
+ flush_rewrite_rules();
+ }
+}
+
+/*
+ ## plugins_loaded ##
+ include 'inc/WPUBaseCron.php';
+ $WPUBaseCron = new WPUBaseCron(array(
+ 'pluginname' => 'Base Plugin',
+ 'cronhook' => 'wpubaseplugin__cron_hook',
+ 'croninterval' => 900
+ ));
+
+ ## uninstall hook ##
+ $WPUBaseCron->uninstall();
+ *
+ */
diff --git a/inc/WPUBaseEmail/README.md b/inc/WPUBaseEmail/README.md
new file mode 100644
index 0000000..a88b36f
--- /dev/null
+++ b/inc/WPUBaseEmail/README.md
@@ -0,0 +1,17 @@
+WPU Base Email
+---
+
+Nicely formatted emails in your plugin.
+
+## Insert in the INIT hook
+
+```php
+require_once dirname(__FILE__) . '/inc/WPUBaseEmail/WPUBaseEmail.php';
+$this->baseemail = new \wpu_polls\WPUBaseEmail();
+```
+
+## Send an email where you need it
+
+```php
+$this->baseemail->send_email('test subject', 'test content');
+``
diff --git a/inc/WPUBaseEmail/WPUBaseEmail.php b/inc/WPUBaseEmail/WPUBaseEmail.php
new file mode 100644
index 0000000..9d9667c
--- /dev/null
+++ b/inc/WPUBaseEmail/WPUBaseEmail.php
@@ -0,0 +1,44 @@
+
+
+
+ .link-nostyle { color: inherit; }
+
+
+
+
+
+
+
+
+
+
+
+
+ Hello World
+
+ Hello World
+
+
+
+
diff --git a/inc/WPUBaseEmail/templates/template.php b/inc/WPUBaseEmail/templates/template.php
new file mode 100644
index 0000000..2bbf75d
--- /dev/null
+++ b/inc/WPUBaseEmail/templates/template.php
@@ -0,0 +1,52 @@
+
diff --git a/inc/WPUBaseSettings/README.md b/inc/WPUBaseSettings/README.md
new file mode 100644
index 0000000..2103da3
--- /dev/null
+++ b/inc/WPUBaseSettings/README.md
@@ -0,0 +1,45 @@
+WPU Base Settings
+---
+
+Add settings in your plugin.
+
+## Insert in the INIT hook
+
+```php
+$this->settings_details = array(
+ # Admin page
+ 'create_page' => true,
+ 'plugin_basename' => plugin_basename(__FILE__),
+ # Default
+ 'plugin_name' => 'Import Twitter',
+ 'plugin_id' => 'wpuimporttwitter',
+ 'option_id' => 'wpuimporttwitter_options',
+ 'sections' => array(
+ 'import' => array(
+ 'name' => __('Import Settings', 'wpuimporttwitter')
+ )
+ )
+);
+$this->settings = array(
+ 'sources' => array(
+ 'label' => __('Sources', 'wpuimporttwitter'),
+ 'help' => __('One #hashtag or one @user per line.', 'wpuimporttwitter'),
+ 'type' => 'textarea'
+ )
+);
+if (is_admin()) {
+ include dirname( __FILE__ ) . '/inc/WPUBaseSettings/WPUBaseSettings.php';
+ new \wpuimporttwitter\WPUBaseSettings($this->settings_details,$this->settings);
+}
+```
+
+## Insert in your admin page content ( if needed )
+
+```php
+settings_errors();
+echo '';
+``
diff --git a/inc/WPUBaseSettings/WPUBaseSettings.php b/inc/WPUBaseSettings/WPUBaseSettings.php
new file mode 100644
index 0000000..ac6cccc
--- /dev/null
+++ b/inc/WPUBaseSettings/WPUBaseSettings.php
@@ -0,0 +1,722 @@
+init($settings_details, $settings);
+ }
+
+ public function init($settings_details = array(), $settings = array()) {
+ if (empty($settings_details) || empty($settings)) {
+ return;
+ }
+ $this->set_datas($settings_details, $settings);
+ $this->has_media_setting = false;
+ foreach ($this->settings as $setting) {
+ if ($setting['type'] == 'media') {
+ $this->has_media_setting = true;
+ }
+ }
+
+ $this->is_admin_page = isset($_GET['page']) && $_GET['page'] == $this->settings_details['plugin_id'];
+ $this->has_create_page = isset($settings_details['create_page']) && $settings_details['create_page'];
+
+ $opt = $this->get_settings();
+ add_action('admin_init', array(&$this,
+ 'add_settings'
+ ));
+ add_filter('option_page_capability_' . $this->settings_details['option_id'], array(&$this,
+ 'set_min_capability'
+ ));
+ add_action('admin_notices', array(&$this,
+ 'admin_notices'
+ ));
+ if ($this->has_create_page) {
+ add_action('admin_menu', array(&$this,
+ 'admin_menu'
+ ));
+ $this->admin_url = admin_url($this->settings_details['parent_page_url'] . '?page=' . $this->settings_details['plugin_id']);
+ if (isset($settings_details['plugin_basename'])) {
+ add_filter("plugin_action_links_" . $settings_details['plugin_basename'], array(&$this, 'plugin_add_settings_link'));
+ }
+ } else {
+ add_action('init', array(&$this, 'load_assets'));
+ }
+ }
+
+ public function admin_notices() {
+ if (!$this->is_admin_page) {
+ return;
+ }
+ if ($this->settings_details['parent_page'] == 'options-general.php') {
+ return;
+ }
+ settings_errors();
+ }
+
+ public function get_settings() {
+ return $this->get_setting_values();
+ }
+
+ public function get_setting($id, $lang = false) {
+ $opt = $this->get_settings();
+ if ($lang === true) {
+ $id = $this->get_current_language() . '__' . $id;
+ }
+ if (isset($opt[$id])) {
+ return $opt[$id];
+ }
+ return false;
+ }
+
+ public function update_setting($id, $value) {
+ $opt = $this->get_settings();
+ $opt[$id] = $value;
+ update_option($this->settings_details['option_id'], $opt);
+ }
+
+ public function set_min_capability() {
+ return $this->settings_details['user_cap'];
+ }
+
+ public function set_datas($settings_details, $settings) {
+ if (!is_array($settings_details)) {
+ $settings_details = array();
+ }
+ if (!isset($settings_details['plugin_id'])) {
+ $settings_details['plugin_id'] = 'wpubasesettingsdefault';
+ }
+ if (!isset($settings_details['user_cap'])) {
+ $settings_details['user_cap'] = 'manage_options';
+ }
+ if (!isset($settings_details['option_id'])) {
+ $settings_details['option_id'] = $settings_details['plugin_id'] . '_options';
+ }
+ if (!isset($settings_details['parent_page'])) {
+ $settings_details['parent_page'] = 'options-general.php';
+ }
+ if (!isset($settings_details['parent_page_url'])) {
+ $settings_details['parent_page_url'] = $settings_details['parent_page'];
+ }
+ if (!isset($settings_details['plugin_name'])) {
+ $settings_details['plugin_name'] = $settings_details['plugin_id'];
+ }
+ if (!isset($settings_details['show_in_rest'])) {
+ $settings_details['show_in_rest'] = false;
+ }
+ if (!isset($settings_details['sections']) || empty($settings_details['sections'])) {
+ $settings_details['sections'] = array(
+ 'default' => array(
+ 'name' => __('Settings')
+ )
+ );
+ }
+ foreach ($settings_details['sections'] as $id => $section) {
+ if (!isset($section['user_cap'])) {
+ $settings_details['sections'][$id]['user_cap'] = $settings_details['user_cap'];
+ }
+ }
+ $this->settings_details = $settings_details;
+ if (!is_array($settings)) {
+ $settings = array(
+ 'option_example' => array(
+ 'label' => 'My label',
+ 'help' => 'My help',
+ 'type' => 'textarea'
+ )
+ );
+ }
+
+ $default_section = key($this->settings_details['sections']);
+ foreach ($settings as $id => $input) {
+ $settings[$id]['required'] = isset($input['required']) ? $input['required'] : false;
+ $settings[$id]['default_value'] = isset($input['default_value']) ? $input['default_value'] : '';
+ $settings[$id]['label'] = isset($input['label']) ? $input['label'] : '';
+ $settings[$id]['label_check'] = isset($input['label_check']) ? $input['label_check'] : $settings[$id]['label'];
+ $settings[$id]['help'] = isset($input['help']) ? $input['help'] : '';
+ $settings[$id]['type'] = isset($input['type']) ? $input['type'] : 'text';
+ $settings[$id]['post_type'] = isset($input['post_type']) ? $input['post_type'] : 'post';
+ $settings[$id]['section'] = isset($input['section']) ? $input['section'] : $default_section;
+ $settings[$id]['datas'] = isset($input['datas']) && is_array($input['datas']) ? $input['datas'] : array(__('No'), __('Yes'));
+ $settings[$id]['editor_args'] = isset($input['editor_args']) && is_array($input['editor_args']) ? $input['editor_args'] : array();
+ $settings[$id]['user_cap'] = $this->settings_details['sections'][$settings[$id]['section']]['user_cap'];
+ }
+
+ $languages = $this->get_languages();
+
+ /* Set multilingual fields */
+ $new_settings = array();
+ foreach ($settings as $id => $input) {
+ if (!isset($input['lang']) || empty($languages)) {
+ $new_settings[$id] = $input;
+ continue;
+ }
+ foreach ($languages as $lang => $lang_name) {
+ $input_lang = $input;
+ unset($input_lang['lang']);
+ $input_lang['translated_from'] = $id;
+ $input_lang['lang_id'] = $lang;
+ $input_lang['label'] = '[' . $lang . '] ' . $input_lang['label'];
+ $new_settings[$lang . '__' . $id] = $input_lang;
+ }
+
+ }
+
+ $this->settings = $new_settings;
+ }
+
+ public function add_settings() {
+ register_setting($this->settings_details['option_id'], $this->settings_details['option_id'], array(
+ 'sanitize_callback' => array(&$this, 'options_validate'),
+ 'show_in_rest' => $this->settings_details,
+ 'default' => array()
+ ));
+ foreach ($this->settings_details['sections'] as $id => $section) {
+ if (current_user_can($section['user_cap'])) {
+ add_settings_section($id,
+ $section['name'],
+ isset($section['description']) ? $section['description'] : '',
+ $this->settings_details['plugin_id']
+ );
+ }
+ }
+
+ foreach ($this->settings as $id => $input) {
+ // Hide input if not in capacity
+ if (!current_user_can($input['user_cap'])) {
+ continue;
+ }
+ $lang_id = '';
+ if (isset($input['lang_id'])) {
+ $lang_id = $input['lang_id'];
+ }
+ add_settings_field($id, $this->settings[$id]['label'], array(&$this,
+ 'render__field'
+ ), $this->settings_details['plugin_id'], $this->settings[$id]['section'], array(
+ 'name' => $this->settings_details['option_id'] . '[' . $id . ']',
+ 'id' => $id,
+ 'lang_id' => $lang_id,
+ 'label_for' => $id,
+ 'translated_from' => isset($this->settings[$id]['translated_from']) ? $this->settings[$id]['translated_from'] : false,
+ 'required' => $this->settings[$id]['required'],
+ 'post_type' => $this->settings[$id]['post_type'],
+ 'datas' => $this->settings[$id]['datas'],
+ 'type' => $this->settings[$id]['type'],
+ 'help' => $this->settings[$id]['help'],
+ 'default_value' => $this->settings[$id]['default_value'],
+ 'editor_args' => $this->settings[$id]['editor_args'],
+ 'label_check' => $this->settings[$id]['label_check']
+ ));
+ }
+ }
+
+ public function options_validate($input) {
+ $options = get_option($this->settings_details['option_id']);
+ foreach ($this->settings as $id => $setting) {
+
+ // If regex : use it to validate the field
+ if (isset($setting['regex'])) {
+ if (isset($input[$id]) && preg_match($setting['regex'], $input[$id])) {
+ $options[$id] = $input[$id];
+ } else {
+ if (isset($setting['default'])) {
+ $options[$id] = $setting['default'];
+ }
+ }
+ continue;
+ }
+
+ // Set a default value
+ if ($setting['type'] != 'checkbox') {
+ // - if not sent or if user is not allowed
+ if (!isset($input[$id]) || !current_user_can($setting['user_cap'])) {
+ $input[$id] = isset($options[$id]) ? $options[$id] : '0';
+ }
+ $option_id = $input[$id];
+ }
+ switch ($setting['type']) {
+ case 'checkbox':
+ $option_id = isset($input[$id]) && !in_array($input[$id], array('0', '')) ? '1' : '0';
+ break;
+ case 'radio':
+ case 'select':
+ if (!array_key_exists($input[$id], $setting['datas'])) {
+ $option_id = key($setting['datas']);
+ }
+ break;
+ case 'email':
+ if (filter_var($input[$id], FILTER_VALIDATE_EMAIL) === false) {
+ $option_id = '';
+ }
+ break;
+ case 'url':
+ if (filter_var($input[$id], FILTER_VALIDATE_URL) === false) {
+ $option_id = '';
+ }
+ break;
+ case 'post':
+ case 'page':
+ case 'media':
+ case 'number':
+ if (!is_numeric($input[$id])) {
+ $option_id = 0;
+ }
+ break;
+ case 'editor':
+ $option_id = trim($input[$id]);
+ break;
+ default:
+ $option_id = esc_html(trim($input[$id]));
+ }
+
+ $options[$id] = $option_id;
+ }
+
+ add_settings_error(
+ $this->settings_details['option_id'],
+ $this->settings_details['option_id'] . esc_attr('settings_updated'),
+ __('Settings saved.'),
+ 'updated'
+ );
+
+ return $options;
+ }
+
+ public function render__field($args = array()) {
+ $option_id = $this->settings_details['option_id'];
+ $options = get_option($option_id);
+ $name_val = $option_id . '[' . $args['id'] . ']';
+ $name = ' name="' . $name_val . '" ';
+ $id = ' id="' . $args['id'] . '" ';
+ $attr = '';
+ if (isset($args['lang_id']) && $args['lang_id']) {
+ $attr .= ' data-wpulang="' . esc_attr($args['lang_id']) . '" ';
+ }
+ if (isset($args['required']) && $args['required']) {
+ $attr .= ' required="required" ';
+ }
+ if (isset($args['placeholder']) && $args['placeholder']) {
+ $attr .= ' placeholder="' . esc_attr($args['placeholder']) . '" ';
+ }
+ if (isset($args['attributes_html']) && $args['attributes_html']) {
+ $attr .= ' ' . $args['attributes_html'];
+ }
+ $id .= $attr;
+ $value = isset($options[$args['id']]) ? $options[$args['id']] : $args['default_value'];
+ if(!isset($options[$args['id']]) && isset($args['translated_from']) && $args['translated_from'] && isset($options[$args['translated_from']]) && $options[$args['translated_from']]){
+ $value = $options[$args['translated_from']];
+ }
+
+ switch ($args['type']) {
+ case 'checkbox':
+ $checked_val = isset($options[$args['id']]) ? $options[$args['id']] : '0';
+ echo '';
+ break;
+ case 'textarea':
+ echo '';
+ break;
+ case 'media':
+ $img_src = '';
+ if (is_numeric($value)) {
+ $tmp_src = wp_get_attachment_image_src($value, 'medium');
+ if (is_array($tmp_src)) {
+ $img_src = ' src="' . esc_attr($tmp_src[0]) . '" ';
+ }
+ }
+ echo '';
+ break;
+ case 'radio':
+ foreach ($args['datas'] as $_id => $_data) {
+ echo '';
+ echo '';
+ echo '';
+ echo '
';
+ }
+ break;
+ case 'post':
+ case 'page':
+ $code_dropdown = wp_dropdown_pages(array(
+ 'echo' => false,
+ 'name' => $name_val,
+ 'id' => $args['id'],
+ 'selected' => $value,
+ 'post_type' => isset($args['post_type']) ? $args['post_type'] : $args['type']
+ ));
+ echo str_replace('';
+ break;
+ case 'editor':
+ $editor_args = array(
+ 'textarea_rows' => isset($args['textarea_rows']) && is_numeric($args['textarea_rows']) ? $args['textarea_rows'] : 3
+ );
+ if (isset($args['editor_args']) && is_array($args['editor_args'])) {
+ $editor_args = $args['editor_args'];
+ }
+ $editor_args['textarea_name'] = $name_val;
+ wp_editor($value, $option_id . '_' . $args['id'], $editor_args);
+ echo '';
+ break;
+ case 'url':
+ case 'number':
+ case 'email':
+ case 'text':
+ echo '';
+ }
+ if (!empty($args['help'])) {
+ echo '' . $args['help'] . '
';
+ }
+ }
+
+ public static function isRegex($str0) {
+ /* Thx https://stackoverflow.com/a/16098097 */
+ $regex = "/^\/[\s\S]+\/$/";
+ return preg_match($regex, $str0);
+ }
+
+ /* Media */
+ public function load_assets() {
+ add_action('admin_footer', array(&$this, 'admin_footer'));
+
+ if (!$this->has_media_setting) {
+ return;
+ }
+
+ add_action('admin_print_scripts', array(&$this, 'admin_scripts'));
+ add_action('admin_print_styles', array(&$this, 'admin_styles'));
+ add_action('admin_head', array(&$this, 'admin_head'));
+ add_action('admin_footer', array(&$this, 'admin_footer_medias'));
+ }
+
+ public function admin_scripts() {
+ wp_enqueue_script('media-upload');
+ wp_enqueue_media();
+ }
+
+ public function admin_styles() {
+ wp_enqueue_style('thickbox');
+ }
+
+ public function admin_head() {
+ echo <<
+.wpubasesettings-mediabox .img-preview {
+ z-index: 1;
+ position: relative;
+}
+
+.wpubasesettings-mediabox .img-preview img {
+ max-width: 100px;
+}
+
+.wpubasesettings-mediabox .img-preview .x {
+ z-index: 1;
+ position: absolute;
+ top: 0;
+ left: 0;
+ padding: 0.2em;
+ text-decoration: none;
+ font-weight: bold;
+ line-height: 1;
+ color: #000;
+ background-color: #fff;
+}
+
+EOT;
+ }
+
+ public function admin_footer_medias() {
+ echo <<
+/* Delete image */
+jQuery('.wpubasesettings-mediabox .x').click(function(e) {
+ var \$this = jQuery(this),
+ \$parent = \$this.closest('.wpubasesettings-mediabox'),
+ \$imgPreview = \$parent.find('.img-preview');
+ \$imgField = \$parent.find('input[type="hidden"]');
+ e.preventDefault();
+ \$imgPreview.css({'display':'none'});
+ \$imgField.val('');
+});
+
+/* Add image */
+jQuery('.wpubasesettings-mediabox .button').click(function(e) {
+ var \$this = jQuery(this),
+ \$parent = \$this.closest('.wpubasesettings-mediabox'),
+ \$imgPreview = \$parent.find('.img-preview');
+ \$imgField = \$parent.find('input[type="hidden"]');
+
+ var frame = wp.media({multiple: false });
+
+ // When an image is selected in the media frame...
+ frame.on('select', function() {
+ var attachment = frame.state().get('selection').first().toJSON();
+ \$imgPreview.css({'display':'block'});
+ \$imgPreview.find('img').attr('src',attachment.url);
+ // Send the attachment id to our hidden input
+ \$imgField.val(attachment.id);
+ });
+
+ // Finally, open the modal on click
+ frame.open();
+
+ e.preventDefault();
+});
+
+
+EOT;
+ }
+
+ public function admin_footer() {
+ $option_id = $this->settings_details['option_id'];
+ $languages = json_encode($this->get_languages());
+ $label_txt = __('Language');
+ echo <<
+(function(){
+/* Check langs */
+var _langs = {$languages};
+if(!_langs){
+ return;
+}
+
+/* Get items */
+var jQinput = jQuery('input[type="hidden"][name="option_page"][value="{$option_id}"]');
+if(!jQinput.length){
+ return;
+}
+var jQform = jQinput.closest('form');
+
+/* Add lang on TR */
+jQform.find('[data-wpulang]').each(function(i,el){
+ var jQel = jQuery(el);
+ jQel.closest('tr').attr('data-wpulangtr', jQel.attr('data-wpulang'));
+});
+var jQTr = jQform.find('[data-wpulangtr]'),
+ _firstLang = Object.keys(_langs)[0];
+if(!jQTr.length){
+ return;
+}
+
+/* Build switch */
+var select_html='';
+for(var _l in _langs){
+ select_html+='';
+}
+var jQSelect = jQuery('');
+jQSelect.prependTo(jQform);
+
+/* Switch */
+function show_lang(_lang_id){
+ jQTr.hide();
+ jQTr.filter('[data-wpulangtr="'+_lang_id+'"]').show();
+}
+show_lang(_firstLang);
+jQSelect.on('change', 'select',function(){
+ show_lang(jQuery(this).val());
+});
+
+}());
+
+EOT;
+ }
+
+ /* Base settings */
+
+ public function admin_menu() {
+ $this->hook_page = add_submenu_page($this->settings_details['parent_page'], $this->settings_details['plugin_name'] . ' - ' . __('Settings'), $this->settings_details['plugin_name'], $this->settings_details['user_cap'], $this->settings_details['plugin_id'], array(&$this,
+ 'admin_settings'
+ ), 110);
+ add_action('load-' . $this->hook_page, array(&$this, 'load_assets'));
+ }
+
+ public function plugin_add_settings_link($links) {
+ $settings_link = '' . __('Settings') . '';
+ array_push($links, $settings_link);
+ return $links;
+ }
+
+ public function admin_settings() {
+ echo '';
+ do_action('wpubasesettings_after_wrap_start' . $this->hook_page);
+ echo apply_filters('wpubasesettings_page_title_' . $this->hook_page, '
' . get_admin_page_title() . '
');
+ do_action('wpubasesettings_before_content_' . $this->hook_page);
+ if (current_user_can($this->settings_details['user_cap'])) {
+ echo apply_filters('wpubasesettings_before_form_' . $this->hook_page, '
');
+ echo '';
+ }
+ do_action('wpubasesettings_after_content_' . $this->hook_page);
+ do_action('wpubasesettings_before_wrap_end' . $this->hook_page);
+ echo '';
+ }
+
+ /* Get settings */
+
+ public function get_setting_values($lang = false) {
+ if (!isset($this->settings) || !is_array($this->settings)) {
+ return array();
+ }
+ if (!$lang) {
+ $lang = $this->get_current_language();
+ }
+ $settings = get_option($this->settings_details['option_id']);
+ if (!is_array($settings)) {
+ $settings = array();
+ }
+ foreach ($this->settings as $key => $setting) {
+ /* Default fields */
+ if (!isset($settings[$key]) && !isset($setting['translated_from'])) {
+ $default_value = false;
+ if (isset($this->settings[$key], $this->settings[$key]['default'])) {
+ $default_value = $this->settings[$key]['default'];
+ }
+ $settings[$key] = $default_value;
+ }
+ if (isset($setting['translated_from'], $setting['lang_id'], $settings[$key]) && $lang == $setting['lang_id'] && $settings[$key] !== false) {
+ $settings[$setting['translated_from']] = $settings[$key];
+ }
+ }
+ return $settings;
+ }
+
+ public function get_languages() {
+ // Obtaining from Qtranslate
+ if (function_exists('qtrans_getSortedLanguages')) {
+ return qtrans_getSortedLanguages();
+ }
+
+ // Obtaining from Qtranslate X
+ if (function_exists('qtranxf_getSortedLanguages')) {
+ return qtranxf_getSortedLanguages();
+ }
+
+ // Obtaining from Polylang
+ global $polylang;
+ if (function_exists('pll_the_languages') && is_object($polylang)) {
+ $poly_langs = $polylang->model->get_languages_list();
+ $languages = array();
+ foreach ($poly_langs as $lang) {
+ $languages[$lang->slug] = $lang->slug;
+ }
+ return $languages;
+ }
+
+ // Obtaining from WPML
+ if (function_exists('icl_get_languages')) {
+ $wpml_lang = icl_get_languages();
+ foreach ($wpml_lang as $lang) {
+ $languages[$lang['code']] = $lang['native_name'];
+ }
+ return $languages;
+ }
+ return array();
+
+ }
+
+ public function get_current_language() {
+
+ // Obtaining from Qtranslate
+ if (function_exists('qtrans_getLanguage')) {
+ return qtrans_getLanguage();
+ }
+
+ // Obtaining from Qtranslate X
+ if (function_exists('qtranxf_getLanguage')) {
+ return qtranxf_getLanguage();
+ }
+
+ // Obtaining from Polylang
+ if (function_exists('pll_current_language')) {
+ return pll_current_language();
+ }
+
+ // Obtaining from WPML
+ if (defined('ICL_LANGUAGE_CODE')) {
+ return ICL_LANGUAGE_CODE;
+ }
+
+ return '';
+ }
+
+}
+
+/*
+ ## INIT ##
+ $this->settings_details = array(
+ # Create admin page
+ 'create_page' => true,
+ 'parent_page' => 'tools.php',
+ 'plugin_name' => 'Maps Autocomplete',
+ # Default
+ 'plugin_id' => 'wpuimporttwitter',
+ 'user_cap' => 'manage_options',
+ 'option_id' => 'wpuimporttwitter_options',
+ 'sections' => array(
+ 'import' => array(
+ 'name' => __('Import Settings', 'wpuimporttwitter')
+ )
+ )
+ );
+ $this->settings = array(
+ 'sources' => array(
+ 'label' => __('Sources', 'wpuimporttwitter'),
+ 'help' => __('One #hashtag or one @user per line.', 'wpuimporttwitter'),
+ 'type' => 'textarea'
+ )
+ );
+ if (is_admin()) {
+ include 'inc/WPUBaseSettings.php';
+ $settings_obj = new \wpuimporttwitter\WPUBaseSettings($this->settings_details, $this->settings);
+
+ ## if no auto create_page and medias ##
+ if(isset($_GET['page']) && $_GET['page'] == 'wpuimporttwitter'){
+ add_action('admin_init', array(&$settings_obj, 'load_assets'));
+ }
+ }
+
+ ## IN ADMIN PAGE if no auto create_page ##
+ echo '';
+*/
diff --git a/inc/WPUBaseToolbox/README.md b/inc/WPUBaseToolbox/README.md
new file mode 100644
index 0000000..e5fcb9f
--- /dev/null
+++ b/inc/WPUBaseToolbox/README.md
@@ -0,0 +1,35 @@
+WPU Base Toolbox
+---
+
+Cool helpers for WordPress Plugins.
+
+## Insert in the INIT hook
+
+```php
+require_once dirname(__FILE__) . '/inc/WPUBaseToolbox/WPUBaseToolbox.php';
+$this->basetoolbox = new \myplugin\WPUBaseToolbox();
+```
+
+## Use functions
+
+
+### Get form HTML
+
+```php
+echo $this->basetoolbox->get_form_html('form_edit_note', array(
+ 'note_name' => array(
+ 'label' => __('Note Name', 'myplugin'),
+ 'value' => 'base value'
+ ),
+ 'note_content' => array(
+ 'label' => __('Note Content', 'myplugin'),
+ 'type' => 'textarea'
+ )
+), array(
+ 'button_label' => __('Send modifications', 'myplugin'),
+ 'hidden_fields' => array(
+ 'method' => 'edit_note',
+ 'action' => 'myplugin_callback_crud'
+ )
+));
+```
diff --git a/inc/WPUBaseToolbox/WPUBaseToolbox.php b/inc/WPUBaseToolbox/WPUBaseToolbox.php
new file mode 100644
index 0000000..5a6d10d
--- /dev/null
+++ b/inc/WPUBaseToolbox/WPUBaseToolbox.php
@@ -0,0 +1,398 @@
+plugin_version);
+ }
+
+ /* ----------------------------------------------------------
+ Forms
+ ---------------------------------------------------------- */
+
+ /* Wrapper
+ -------------------------- */
+
+ public function get_form_html($form_id, $fields = array(), $args = array()) {
+ $html = '';
+ if (!is_array($fields) || !is_array($args)) {
+ return '';
+ }
+
+ $args = $this->get_clean_form_args($form_id, $fields, $args);
+
+ $extra_post_attributes = $args['form_attributes'];
+
+ /* Clean & check fields */
+ $has_file = false;
+ foreach ($fields as $field_name => $field) {
+ $fields[$field_name] = $this->get_clean_field($field_name, $field, $form_id, $args);
+ if ($fields[$field_name]['type'] == 'file') {
+ $has_file = true;
+ }
+ }
+
+ /* Extra attributes */
+ if ($has_file) {
+ $extra_post_attributes .= ' enctype="multipart/form-data"';
+ }
+
+ $button_submit = '';
+
+ /* Start form */
+ $html .= '';
+
+ return $html;
+ }
+
+ /* Clean form value
+ -------------------------- */
+
+ public function get_clean_form_args($form_id, $fields = array(), $args = array()) {
+ $default_args = array(
+ 'button_label' => __('Submit'),
+ 'button_classname' => 'cssc-button',
+ 'fieldsets' => array(
+ 'default' => array(
+ 'label' => '',
+ 'attributes' => array(),
+ 'content_before' => '',
+ 'content_after' => ''
+ )
+ ),
+ 'form_attributes' => '',
+ 'form_classname' => 'cssc-form',
+ 'field_group_classname' => 'twoboxes',
+ 'field_box_classname' => 'box',
+ 'submit_box_classname' => 'box--submit',
+ 'html_before_content' => '',
+ 'html_after_content' => '',
+ 'hidden_fields' => array(),
+ 'has_nonce' => true,
+ 'nonce_id' => $form_id,
+ 'nonce_name' => $form_id . '_nonce',
+ 'wizard_mode' => false,
+ 'wizard_steps' => false,
+ 'wizard_prev_button_class' => 'btn--prev',
+ 'wizard_next_button_class' => 'btn--next',
+ 'wizard_prev_button_label' => __('Previous'),
+ 'wizard_next_button_label' => __('Next')
+ );
+ $args = array_merge($default_args, $args);
+
+ $args = apply_filters('wpubasetoolbox_get_form_html_args_' . __NAMESPACE__, $args);
+ if (!is_array($args['hidden_fields']) || !isset($args['hidden_fields'])) {
+ $args['hidden_fields'] = array();
+ }
+ if (!is_array($args['fieldsets']) || !isset($args['fieldsets'])) {
+ $args['fieldsets'] = array();
+ }
+ foreach ($args['fieldsets'] as $fieldset_id => $fieldset) {
+ $args['fieldsets'][$fieldset_id] = array_merge($default_args['fieldsets']['default'], $fieldset);
+ if (!is_array($args['fieldsets'][$fieldset_id]['attributes'])) {
+ $args['fieldsets'][$fieldset_id]['attributes'] = array();
+ }
+ }
+ return $args;
+ }
+
+ /* Clean field values
+ -------------------------- */
+
+ public function get_clean_field($field_name, $field, $form_id, $args) {
+ if (!is_array($field)) {
+ $field = array();
+ }
+
+ if (!isset($field['fieldset']) || !array_key_exists($field['fieldset'], $args['fieldsets'])) {
+ $field['fieldset'] = array_key_first($args['fieldsets']);
+ }
+
+ $default_field = array(
+ 'label' => $field_name,
+ 'type' => 'text',
+ 'fieldgroup_start' => false,
+ 'fieldgroup_end' => false,
+ 'html_before_fieldgroup' => '',
+ 'html_before_fieldgroup_inner' => '',
+ 'html_after_fieldgroup' => '',
+ 'html_after_fieldgroup_inner' => '',
+ 'html_before_content' => '',
+ 'html_after_content' => '',
+ 'value' => '',
+ 'extra_attributes' => '',
+ 'data_html' => '',
+ 'sub_fields' => array(),
+ 'data' => array(
+ '0' => __('No'),
+ '1' => __('Yes')
+ ),
+ 'required' => false
+ );
+ $field = array_merge($default_field, $field);
+
+ /* Ensure format */
+ if (!is_array($field['data'])) {
+ $field['data'] = array();
+ }
+
+ if (!is_array($field['sub_fields'])) {
+ $field['sub_fields'] = array();
+ }
+
+ foreach ($field['sub_fields'] as $subfield_name => $sub_field) {
+ $field['sub_fields'][$subfield_name] = $this->get_clean_field($subfield_name, $sub_field, $form_id, $args);
+ }
+
+ return $field;
+ }
+
+ public function get_field_html($field_name, $field, $form_id, $args = array()) {
+
+ if (!isset($field['extra_attributes'])) {
+ echo wp_debug_backtrace_summary();
+ die;
+ }
+
+ /* Values */
+ $field_id = strtolower($form_id . '__' . $field_name);
+ $field_id_name = ' name="' . esc_attr($field_name) . '" id="' . esc_attr($field_id) . '" ' . $field['extra_attributes'];
+ if ($field['required']) {
+ $field_id_name .= ' required';
+ }
+
+ /* Label */
+ $default_label = '';
+
+ /* Content */
+ $html = '';
+ switch ($field['type']) {
+ case 'textarea':
+ $html .= $default_label;
+ $html .= '';
+ break;
+
+ case 'select':
+ $html .= $default_label;
+ $html .= '';
+ break;
+
+ case 'radio':
+ $html .= $default_label;
+ foreach ($field['data'] as $key => $var) {
+ $id_field = strtolower($field_id . '___' . $key);
+ $html .= '';
+ $html .= '';
+ $html .= '';
+ $html .= '';
+ }
+ break;
+
+ case 'checkbox':
+ $checked = $field['value'] ? ' checked="checked"' : '';
+ $html .= '';
+ $html .= $default_label;
+ break;
+
+ case 'group':
+ foreach ($field['sub_fields'] as $subfield_name => $sub_field) {
+ $html .= $this->get_field_html($subfield_name, $sub_field, $form_id, $args);
+ }
+ break;
+
+ default:
+ $html .= $default_label;
+ $html .= '';
+ }
+
+ if ($html) {
+ $field_html = $html;
+ $field_tag = ($field['type'] == 'group') ? 'div' : 'p';
+ $html = '';
+ $html .= $field['html_before_fieldgroup'];
+ if ($field['fieldgroup_start']) {
+ $html .= '';
+ }
+ $html .= $field['html_before_fieldgroup_inner'];
+ $html .= '<' . $field_tag . ' class="' . $args['field_box_classname'] . '" data-box-name="' . $field_name . '" data-box-type="' . esc_attr($field['type']) . '">';
+ $html .= $field['html_before_content'];
+ $html .= $field_html;
+ $html .= '';
+ $html .= $field['html_after_content'];
+ $html .= '' . $field_tag . '>';
+ $html .= $field['html_after_fieldgroup_inner'];
+ if ($field['fieldgroup_end']) {
+ $html .= '
';
+ }
+ $html .= $field['html_after_fieldgroup'];
+ }
+
+ return $html;
+ }
+
+ /* Validate form
+ -------------------------- */
+
+ function validate_form($source, $form_id, $fields = array(), $args = array()) {
+ if (!is_array($source) || empty($source) || empty($fields)) {
+ return false;
+ }
+
+ $errors = array();
+
+ $args = $this->get_clean_form_args($form_id, $fields, $args);
+
+ /* Check nonce */
+ if ($args['has_nonce']) {
+ if (!isset($_POST[$args['nonce_name']]) || !wp_verify_nonce($_POST[$args['nonce_name']], $args['nonce_id'])) {
+ wp_nonce_ays('');
+ }
+ }
+
+ /* Check required fields */
+ foreach ($fields as $field_name => $field) {
+ $field = $this->get_clean_field($field_name, $field, $form_id, $args);
+ $value = isset($source[$field_name]) ? $source[$field_name] : false;
+
+ if ($field['required'] && !isset($source[$field_name])) {
+ $errors[] = sprintf(__('The field “%s” is required', __NAMESPACE__), $field['label']);
+ continue;
+ }
+
+ if ($field['type'] == 'email' && $field['type'] && !is_email($value)) {
+ $errors[] = sprintf(__('The field “%s” should be an email', __NAMESPACE__), $field['label']);
+ }
+ }
+
+ return $errors;
+ }
+
+ /* ----------------------------------------------------------
+ HTML Helpers
+ ---------------------------------------------------------- */
+
+ function array_to_html_attributes($attributes = array()) {
+ if (!is_array($attributes)) {
+ return '';
+ }
+
+ $html = '';
+ foreach ($attributes as $key => $value) {
+ $html .= ' ' . $key . '="' . esc_attr($value) . '"';
+ }
+
+ return trim($html);
+ }
+
+}
diff --git a/inc/WPUBaseToolbox/assets/form-validation.js b/inc/WPUBaseToolbox/assets/form-validation.js
new file mode 100644
index 0000000..12885ca
--- /dev/null
+++ b/inc/WPUBaseToolbox/assets/form-validation.js
@@ -0,0 +1,160 @@
+document.addEventListener("DOMContentLoaded", function() {
+ 'use strict';
+ /* Boxes */
+ Array.prototype.forEach.call(document.querySelectorAll('.wpubasetoolbox-form [data-box-name]'), wpubasetoolbox_box_validation);
+
+ /* Wizard */
+ Array.prototype.forEach.call(document.querySelectorAll('.wpubasetoolbox-form[data-wizard="1"]'), wpubasetoolbox_form_setup_wizard);
+});
+
+/* ----------------------------------------------------------
+ Fieldset switch
+---------------------------------------------------------- */
+
+function wpubasetoolbox_form_setup_wizard($form) {
+ 'use strict';
+ var $fieldsets = $form.querySelectorAll('fieldset');
+ var _currentFieldset = 0;
+ var _nbFieldsets = $fieldsets.length;
+ var $wizardSteps = $form.querySelectorAll(' .form-wizard-steps [data-go]');
+
+ /* Display first fieldset */
+ wpubasetoolbox_fieldset_display($fieldsets, _currentFieldset);
+
+ /* On button click : change visible fieldset */
+ Array.prototype.forEach.call($form.querySelectorAll(' .form-navigation [data-dir]'), function($btn) {
+ $btn.querySelector('span').style['pointer-events'] = 'none';
+ $btn.addEventListener('click', btn_click_event, 1);
+ });
+ Array.prototype.forEach.call($wizardSteps, function($btn) {
+ $btn.querySelector('span').style['pointer-events'] = 'none';
+ $btn.addEventListener('click', btn_click_event_go, 1);
+ });
+
+ function btn_click_event(e) {
+ var _dir = e.target.getAttribute('data-dir');
+ e.preventDefault();
+ if (_dir == 'next') {
+ /* Check if a field is invalid in this fieldset*/
+ if (wpubasetoolbox_fieldset_fieldset_has_invalid_fields($fieldsets[_currentFieldset])) {
+ return;
+ }
+ /* Allow next fieldset */
+ _currentFieldset++;
+ }
+ else {
+ /* Always allow previous fieldset */
+ _currentFieldset--;
+ }
+ go_to_fieldset(_currentFieldset);
+ }
+
+ function btn_click_event_go(e) {
+ var _target_fieldset = parseInt(e.target.getAttribute('data-go'), 10);
+ e.preventDefault();
+ for (var i = 0; i <= _target_fieldset; i++) {
+ go_to_fieldset(i);
+ /* Do not check target fieldset */
+ if (i == _target_fieldset) {
+ break;
+ }
+ /* Check if a field is invalid in this fieldset */
+ if (wpubasetoolbox_fieldset_fieldset_has_invalid_fields($fieldsets[i])) {
+ break;
+ }
+ }
+ }
+
+ function go_to_fieldset(_fieldset) {
+ /* Ensure everything is ok */
+ _currentFieldset = Math.max(0, _fieldset);
+ _currentFieldset = Math.min(_nbFieldsets - 1, _currentFieldset);
+
+ $form.setAttribute('data-current-fieldset', _currentFieldset);
+
+ /* Display fieldset */
+ wpubasetoolbox_fieldset_display($fieldsets, _currentFieldset);
+
+ /* Current wizard step */
+ if ($wizardSteps.length) {
+ Array.prototype.forEach.call($wizardSteps, function(el) {
+ el.setAttribute('data-active', 0);
+ });
+ $wizardSteps[_currentFieldset].setAttribute('data-active', 1);
+ }
+
+ /* Event */
+ $form.dispatchEvent(new CustomEvent("wpubasetoolbox_form_set_fieldset", {
+ detail: {
+ id: _currentFieldset,
+ item: $fieldsets[_currentFieldset]
+ }
+ }));
+ }
+}
+
+function wpubasetoolbox_fieldset_fieldset_has_invalid_fields($fieldset) {
+ 'use strict';
+ var $invalidFields = $fieldset.querySelectorAll(':invalid');
+ Array.prototype.forEach.call($invalidFields, function(el) {
+ el.dispatchEvent(new Event('change'));
+ });
+ return $invalidFields.length > 0;
+}
+
+function wpubasetoolbox_fieldset_display($fieldsets, _nb) {
+ 'use strict';
+ Array.prototype.forEach.call($fieldsets, function(el) {
+ el.style.display = 'none';
+ });
+ $fieldsets[_nb].style.display = '';
+}
+
+/* ----------------------------------------------------------
+ Box validation
+---------------------------------------------------------- */
+
+function wpubasetoolbox_box_validation($box) {
+ 'use strict';
+ var _id = $box.getAttribute('data-box-name'),
+ $fields = $box.querySelectorAll('[name="' + _id + '"]'),
+ $message = $box.querySelector('.wpubasetoolbox-form-validation-message'),
+ _ischecking = false;
+
+ if (!$fields.length || !$message) {
+ return;
+ }
+
+ function check_field_error($tmp_field) {
+ if (_ischecking) {
+ return false;
+ }
+ _ischecking = true;
+ var _valid = $tmp_field.checkValidity();
+ _ischecking = false;
+ if (_valid) {
+ $box.setAttribute('data-box-error', '0');
+ $message.innerHTML = '';
+ return;
+ }
+ setTimeout(function() {
+ window.scrollTo({
+ top: $box.getBoundingClientRect().top + window.pageYOffset - 100,
+ behavior: 'smooth'
+ });
+ }, 10);
+
+ $box.setAttribute('data-box-error', '1');
+ $message.innerHTML = $tmp_field.validationMessage;
+ }
+
+ Array.prototype.forEach.call($fields, function($tmp_field) {
+ $tmp_field.addEventListener("invalid", function() {
+ check_field_error($tmp_field);
+ });
+ $tmp_field.addEventListener("change", function() {
+ check_field_error($tmp_field);
+ });
+ });
+
+}
diff --git a/index.php b/index.php
new file mode 100644
index 0000000..2b6a61c
--- /dev/null
+++ b/index.php
@@ -0,0 +1 @@
+query("DROP TABLE IF EXISTS {$wpdb->prefix}wpuerrorlogs_logs");
diff --git a/wpuerrorlogs.php b/wpuerrorlogs.php
new file mode 100644
index 0000000..af4e7e4
--- /dev/null
+++ b/wpuerrorlogs.php
@@ -0,0 +1,322 @@
+ 'wpuerrorlogs',
+ 'name' => 'WPU Error Logs'
+ );
+ private $basetoolbox;
+ private $baseemail;
+ private $basecron;
+ private $adminpages;
+ private $baseadmindatas;
+ private $settings;
+ private $settings_obj;
+ private $settings_details;
+ private $plugin_description;
+
+ public function __construct() {
+ add_action('plugins_loaded', array(&$this, 'plugins_loaded'));
+ }
+
+ public function plugins_loaded() {
+ # TRANSLATION
+ if (!load_plugin_textdomain('wpuerrorlogs', false, dirname(plugin_basename(__FILE__)) . '/lang/')) {
+ load_muplugin_textdomain('wpuerrorlogs', dirname(plugin_basename(__FILE__)) . '/lang/');
+ }
+ $this->plugin_description = __('Make sense of your log files', 'wpuerrorlogs');
+ # TOOLBOX
+ require_once __DIR__ . '/inc/WPUBaseToolbox/WPUBaseToolbox.php';
+ $this->basetoolbox = new \wpuerrorlogs\WPUBaseToolbox();
+ # EMAIL
+ require_once __DIR__ . '/inc/WPUBaseEmail/WPUBaseEmail.php';
+ $this->baseemail = new \wpuerrorlogs\WPUBaseEmail();
+ # CUSTOM PAGE
+ $admin_pages = array(
+ 'main' => array(
+ 'icon_url' => 'dashicons-admin-generic',
+ 'menu_name' => $this->plugin_settings['name'],
+ 'name' => 'Main page',
+ 'settings_link' => true,
+ 'settings_name' => __('Settings'),
+ 'function_content' => array(&$this,
+ 'page_content__main'
+ )
+ )
+ );
+ $pages_options = array(
+ 'id' => $this->plugin_settings['id'],
+ 'level' => 'manage_options',
+ 'basename' => plugin_basename(__FILE__)
+ );
+ // Init admin page
+ require_once __DIR__ . '/inc/WPUBaseAdminPage/WPUBaseAdminPage.php';
+ $this->adminpages = new \wpuerrorlogs\WPUBaseAdminPage();
+ $this->adminpages->init($pages_options, $admin_pages);
+ # CUSTOM TABLE
+ require_once __DIR__ . '/inc/WPUBaseAdminDatas/WPUBaseAdminDatas.php';
+ $this->baseadmindatas = new \wpuerrorlogs\WPUBaseAdminDatas();
+ $this->baseadmindatas->init(array(
+ 'handle_database' => false,
+ 'plugin_id' => $this->plugin_settings['id'],
+ 'table_name' => 'wpuerrorlogs_logs',
+ 'table_fields' => array(
+ 'message' => array(
+ 'public_name' => 'message',
+ 'type' => 'sql',
+ 'sql' => 'MEDIUMTEXT'
+ )
+ )
+ ));
+ # SETTINGS
+ $this->settings_details = array(
+ # Admin page
+ 'create_page' => false,
+ 'plugin_basename' => plugin_basename(__FILE__),
+ # Default
+ 'plugin_name' => $this->plugin_settings['name'],
+ 'plugin_id' => $this->plugin_settings['id'],
+ 'option_id' => $this->plugin_settings['id'] . '_options',
+ 'sections' => array(
+ 'import' => array(
+ 'name' => __('Import Settings', 'wpuerrorlogs')
+ )
+ )
+ );
+ $this->settings = array(
+ // 'value' => array(
+ // 'label' => __('My Value', 'wpuerrorlogs'),
+ // 'help' => __('A little help.', 'wpuerrorlogs'),
+ // 'type' => 'textarea'
+ // )
+ );
+ require_once __DIR__ . '/inc/WPUBaseSettings/WPUBaseSettings.php';
+ $this->settings_obj = new \wpuerrorlogs\WPUBaseSettings($this->settings_details, $this->settings);
+ /* Include hooks */
+ require_once __DIR__ . '/inc/WPUBaseCron/WPUBaseCron.php';
+ $this->basecron = new \wpuerrorlogs\WPUBaseCron(array(
+ 'pluginname' => $this->plugin_settings['name'],
+ 'cronhook' => 'wpuerrorlogs__cron_hook',
+ 'croninterval' => 3600
+ ));
+ /* Callback when hook is triggered by the cron */
+ add_action('wpuerrorlogs__cron_hook', array(&$this,
+ 'wpuerrorlogs__cron_hook'
+ ), 10);
+ }
+
+ public function wpuerrorlogs__cron_hook() {
+
+ }
+
+ public function page_content__main() {
+
+ /* Find debug file */
+ $logfile = ABSPATH . '/wp-content/debug.log';
+ if (!WP_DEBUG_LOG) {
+ echo 'Debug logs are not enabled';
+ return;
+ }
+ if (is_readable(WP_DEBUG_LOG)) {
+ $logfile = WP_DEBUG_LOG;
+ }
+
+ $errors = $this->extract_logs_from_file($logfile);
+
+ $textCounts = [];
+
+ foreach ($errors as $error) {
+ if (!isset($textCounts[$error['text']])) {
+ $textCounts[$error['text']] = 0;
+ }
+ $textCounts[$error['text']]++;
+ }
+ arsort($textCounts);
+
+ /* Keep only first five and extract data */
+ $textCounts = array_slice($textCounts, 0, 5, true);
+ $display_values = array();
+ foreach ($textCounts as $text => $count) {
+ $display_values[] = array(
+ 'count' => $count,
+ 'text' => $this->expand_error_text($text)
+ );
+ }
+
+ $colnames = array(
+ 'count' => __('Count', 'wpuerrorlogs'),
+ 'date' => __('Date', 'wpuerrorlogs'),
+ 'type' => __('Type', 'wpuerrorlogs'),
+ 'text' => __('Text', 'wpuerrorlogs')
+ );
+
+ echo '' . __('Top errors', 'wpuerrorlogs') . '
';
+ echo $this->array_to_html_table($display_values, array(
+ 'table_classname' => 'widefat',
+ 'colnames' => $colnames
+ ));
+
+ $latest_errors = array_reverse($errors);
+ $latest_errors = array_slice($latest_errors, 0, 5, true);
+ echo '' . __('Latest errors', 'wpuerrorlogs') . '
';
+ echo $this->array_to_html_table($latest_errors, array(
+ 'table_classname' => 'widefat',
+ 'colnames' => $colnames
+ ));
+
+ }
+
+ /* ----------------------------------------------------------
+ Extract logs from file
+ ---------------------------------------------------------- */
+
+ function extract_logs_from_file($file) {
+ $lines = file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
+ $errors = [];
+ $currentError = array();
+
+ foreach ($lines as $line) {
+
+ /* Is it a new error */
+ if (substr($line, 0, 1) == '[' && preg_match('/^\[\d{2}-[A-Za-z]{3}-\d{4} \d{2}:\d{2}:\d{2} UTC\]/', $line, $matches)) {
+ if (!empty($currentError)) {
+ $currentError['text'] = $this->minimize_error_text($currentError['text']);
+ $errors[] = $currentError;
+ $currentError = array();
+ }
+
+ $currentError = $this->get_error_from_line($line);
+
+ } else {
+ /* Is is the next line of an existing error */
+ $currentError['text'] .= "\n" . $line;
+ }
+ }
+
+ if (!empty($currentError)) {
+ $currentError['text'] = $this->minimize_error_text($currentError['text']);
+ $errors[] = $currentError;
+ }
+
+ return $errors;
+ }
+
+ function get_error_from_line($line) {
+ /* Extract values */
+ $date_parts = explode(']', $line);
+ $date = str_replace('[', '', $date_parts[0]);
+ $text = trim(substr($line, strlen('[' . $date . ']'), -1));
+
+ /* Extract type */
+ $type = 'none';
+ $text_parts_type = explode(':', $text);
+ switch ($text_parts_type[0]) {
+ case 'PHP Warning':
+ $type = 'php-warning';
+ break;
+ case 'PHP Parse error':
+ $type = 'php-parse';
+ break;
+ case 'PHP Deprecated':
+ $type = 'php-deprecated';
+ break;
+ case 'PHP Fatal error':
+ $type = 'php-fatal';
+ break;
+ default:
+ }
+
+ /* Return value */
+ return array(
+ 'date' => $date,
+ 'type' => $type,
+ 'text' => $text
+ );
+ }
+
+ /* ----------------------------------------------------------
+ Helpers
+ ---------------------------------------------------------- */
+
+ function minimize_get_correspondances() {
+ return array(
+ 'abs' => ABSPATH,
+ 'plug' => 'wp-content/plugins/'
+ );
+ }
+
+ function expand_error_text($text) {
+ $correspondances = $this->minimize_get_correspondances();
+ foreach ($correspondances as $min => $max) {
+ $text = str_replace('#!' . $min . '!#', $max, $text);
+ }
+ return $text;
+ }
+
+ function minimize_error_text($text) {
+ $correspondances = $this->minimize_get_correspondances();
+ foreach ($correspondances as $min => $max) {
+ $text = str_replace($max, '#!' . $min . '!#', $text);
+ }
+ return $text;
+ }
+
+ function array_to_html_table($array, $args = array()) {
+ $default_args = array(
+ 'table_classname' => 'widefat',
+ 'colnames' => array()
+ );
+ if (!is_array($args)) {
+ $args = array();
+ }
+ $args = array_merge($default_args, $args);
+
+ $html = '';
+
+ // HEAD
+ $html .= '';
+ foreach ($array[0] as $key => $value) {
+ $label = htmlspecialchars($key);
+ if (isset($args['colnames'][$key])) {
+ $label = $args['colnames'][$key];
+ }
+ $html .= '' . $label . ' | ';
+ }
+ $html .= '
';
+
+ $html .= '';
+ foreach ($array as $key => $value) {
+ $html .= '';
+ foreach ($value as $key2 => $value2) {
+ $html .= '' . htmlspecialchars($value2) . ' | ';
+ }
+ $html .= '
';
+ }
+ $html .= '';
+ $html .= '
';
+ return $html;
+ }
+
+}
+
+$WPUErrorLogs = new WPUErrorLogs();