/** * initializes the record edit object */ public function __construct($shortcode_atts) { // define shortcode-specific attributes to use $add_atts = array('module' => 'single', 'class' => $this->wrap_class, 'term' => 'id'); // run the parent class initialization to set up the parent methods parent::__construct($shortcode_atts, $add_atts); /* * determine the ID of the record to show * * 'pdb' is a generic $_GET variable that indexes the record according to * the 'term' value, which defaults to 'id' * */ if ($this->shortcode_atts['record_id'] !== false) { $id = $this->shortcode_atts['record_id']; } else { $id = 0; } // override the shortcode att if the value is in the URI if (isset($_GET['pdb'])) { $id = $_GET['pdb']; } $record_id = Participants_Db::get_record_id_by_term($this->shortcode_atts['term'], $id); if (false === $record_id) { $this->_not_found(); } else { $this->participant_values = Participants_Db::get_participant($record_id); $this->participant_id = $record_id; $this->_setup_iteration(); $this->_print_from_template(); } }
/** * supplies an image/file upload location * * relative to WP root * * @return string relative path to the plugin files location */ public static function files_location() { /** * @version 1.6.0 * filter: pdb-files_location * * allows access to the "image_upload_location" plugin setting value */ return Participants_Db::set_filter('files_location', Participants_Db::plugin_setting('image_upload_location')); }
/** * instantiates a field group object * * @param object a object with all the field group's properties */ public function __construct($fields, $id, $module = 'none') { $this->module = $module; // set up the common properties parent::__construct($fields); // get rid of unneeded properties unset($this->name, $this->title); // add the record field objects // this needs to by typed as array for the iterators to work $this->fields = (array) $fields; $this->record_id = $id; $this->values = Participants_Db::get_participant($id); }
/** * construct the class * * we check the setting for using PHP session, if false, we use a WP Transient-based session * * we are just using this alternate form of session mnagement instead of PHP * sessions for now */ public function __construct() { $this->use_php_sessions = Participants_Db::plugin_setting_is_true('use_php_sessions'); $this->session_name = Participants_Db::$prefix . 'session'; if ($this->use_php_sessions) { if (!session_id()) { add_action('init', 'session_start', -2); } } else { // Use WP_Session (default) require_once plugin_dir_path(__FILE__) . 'wp-session.inc.php'; if (!defined('WP_SESSION_COOKIE')) { define('WP_SESSION_COOKIE', Participants_Db::$prefix . 'wp_session'); } } add_action('plugins_loaded', array($this, 'init'), -1); }
function store_record($post) { // add the record data to the database $id = Participants_Db::process_form($post, 'insert'); // count the insert type for the record switch (Participants_Db::$insert_status) { case 'insert': $this->insert_count++; break; case 'update': $this->update_count++; break; case 'skip': $this->skip_count++; break; } }
/** * initializes the record edit object */ public function __construct($shortcode_atts) { // define shortcode-specific attributes to use $add_atts = array('module' => 'record', 'class' => 'edit-participant ' . $this->wrap_class); // run the parent class initialization to set up the parent methods parent::__construct($shortcode_atts, $add_atts); // set the action URI for the form $this->_set_submission_page(); if (false === $this->shortcode_atts['record_id']) { $this->_not_found(); } else { $this->participant_id = $this->shortcode_atts['record_id']; $this->participant_values = Participants_Db::get_participant($this->participant_id); if (false === $this->participant_values) { $this->_not_found(); } else { // update the access timestamp Participants_Db::set_record_access($this->participant_id); $this->_get_validation_errors(); $this->_setup_iteration(); $this->_print_from_template(); } } }
/** * outputs a single record link * * @param string $template an optional template for showing the link * * @return string the HTML for the single record link * */ public function output_single_record_link($template = false) { $template = $template ? $template : '<a class="single-record-link" href="%1$s" title="%2$s" >%2$s</a>'; $url = get_permalink(Participants_Db::$plugin_options['single_record_page']); $url = Participants_Db::add_uri_conjunction($url) . 'pdb=' . $this->record_id; return sprintf($template, $url, empty($this->value) ? $this->default : $this->value); }
/** * adds a List_Query_Filter object to the where clauses * * @param string $column the name of the field to target * @param string $operator the operator * @param string $search_term the term to filter by * @param string $logic the logic term to add to the array * @param bool $shortcode true if the current filter is from the shortcode * @return null */ private function _add_single_statement($column, $operator, $search_term = '', $logic = 'AND', $shortcode = false) { /* * don't add an 'id = 0' clause if there is a user search. This gives us a * way to create a "search results only" list if the shortcode contains * a filter for 'id=0' * * we flag it for suppression. Later, if there is no other clause for the ID * column, the list display will be suppressed */ if ($column == 'id' and $search_term == '0') { $this->suppress = true; return false; } /* * if the column is not valid skip this statement */ if (!Participants_Db::is_column($column)) { return false; } $field_atts = Participants_Db::get_column($column); $filter = new PDb_List_Query_Filter(array('field' => $column, 'logic' => $logic, 'shortcode' => $shortcode, 'term' => trim(urldecode($search_term)), 'index' => $this->clause_index)); $this->increment_clause_index(); $statement = false; /* * set up special-case field types */ if (in_array($field_atts->form_element, array('date', 'timestamp')) and $filter->is_string_search()) { /* * if we're dealing with a date element, the target value needs to be * conditioned to get a correct comparison */ $search_term = Participants_Db::parse_date($filter->get_raw_term(), $field_atts); // if we don't get a valid date, skip this statement if ($search_term === false) { return false; } $operator = in_array($operator, array('>', '<')) ? $operator : '='; if ($field_atts->form_element == 'timestamp') { //$statement = 'DATE(p.' . $column . ') ' . $operator . ' CONVERT_TZ(FROM_UNIXTIME(' . $search_term . '), @@session.time_zone, "+00:00") '; $statement = 'DATE(p.' . $column . ') ' . $operator . ' DATE(FROM_UNIXTIME(' . $search_term . ')) '; } else { $statement = 'p.' . $column . ' ' . $operator . ' CAST(' . $search_term . ' AS SIGNED)'; } } elseif ($filter->is_empty_search()) { if ($operator === 'NOT LIKE' or $operator === '!') { $pattern = '(p.%1$s IS NOT NULL AND p.%1$s <> "")'; } else { $pattern = '(p.%1$s IS NULL OR p.%1$s = "")'; } $statement = sprintf($pattern, $column); } else { if ($operator === NULL) { $operator = 'LIKE'; } $delimiter = array('"', '"'); /* * set the operator and delimiters */ switch ($operator) { case '~': case 'LIKE': $operator = 'LIKE'; $delimiter = $filter->wildcard_present() ? array('"', '"') : array('"%', '%"'); break; case '!': case 'NOT LIKE': $operator = 'NOT LIKE'; $delimiter = $filter->wildcard_present() ? array('"', '"') : array('"%', '%"'); break; case 'ne': case '!=': case '<>': $operator = '<>'; break; case 'eq': case '=': /* * if the field's exact value will be found in an array (actually a * serialized array), we must prepare a special statement to search * for the double quotes surrounding the value in the serialization */ if (in_array($field_atts->form_element, array('multi-checkbox', 'multi-select-other', 'link', 'array'))) { $delimiter = array('\'%"', '"%\''); $operator = 'LIKE'; /* * this is so the search term will be treated as a comparison string * in a LIKE statement */ $filter->like_term = true; } elseif ($filter->wildcard_present()) { $operator = 'LIKE'; } else { $operator = '='; } break; case 'gt': case '>': $operator = '>='; break; case 'lt': case '<': $operator = '<'; break; default: // invalid operator: don't add the statement return false; } $statement = sprintf('p.%s %s %s%s%s', $column, $operator, $delimiter[0], $filter->get_term(), $delimiter[1]); } if ($statement) { $filter->update_parameters(array('statement' => $statement)); $this->subclauses[$column][] = $filter; } }
/** * sets up the captcha * * this uses the type to set up the captcha parameters. Externally-defined captcha * types will be processed here. External definitions will be expected to set the * 'validation and 'HTML' properties, and optionally, the 'info' array. The * math_captcha method should be studied for an example of a captcha definition. * * the captcha setup sets three object properties: * validation this is a regex to validate the user input with * HTML the is the HTML needed to present the captcha challenge to the user * captcha_params this is an array of values used to reconstruct the captcha in order * to provide user feedback (optional) * * @return null */ private function captcha_setup() { /* * the pdb-capcha_setup filter expects the PDb_CAPTCHA::HTML property to be * filled with the HTML of the custom captcha element. The validation of the * response should be included as a regex string in PDb_CAPTCHA::validation */ Participants_Db::set_filter('captcha_setup', $this); if (empty($this->HTML)) { switch ($this->captcha_type) { case 'math': $this->math_capcha(); break; } } /* * the $info array will be used to pass values to the validation object; What * we are calling 'nonce' is actually the XOR-encrypted regex. If we need to * expand the types of CAPTCHAS in the future, we can use this to tell the * validation object how to validate the field */ $this->info = array('type' => $this->captcha_type, 'nonce' => PDb_FormValidation::xcrypt($this->validation, $this->key), 'info' => $this->captcha_params); }
/** * sets an admin area error message * * @param string $message the message to be dislayed * @param string $type the type of message: 'updated' (yellow) or 'error' (red) */ public static function set_admin_message($message, $type = 'error') { if (is_admin()) { Participants_Db::$session->set('admin_message', array($message, $type)); Participants_Db::$admin_message = $message; Participants_Db::$admin_message_type = $type; } }
/** * indicates whether groups are to be printed in the form * * signup and record forms print group titles/descriptions only if the setting for that form is true * all other shortcodes always print groups, but they're really only seen in single record displays * * @return bool true if groups are to be printed */ public function printing_groups() { switch ($this->module) { case 'signup': $optionname = 'signup_show_group_descriptions'; break; case 'record': $optionname = 'show_group_descriptions'; break; default: return true; } return Participants_Db::plugin_setting_is_true($optionname); }
private function _do_receipt() { $email_field = Participants_Db::$plugin_options['primary_email_address_field']; if (!isset($this->participant_values[$email_field]) || empty($this->participant_values[$email_field])) { error_log(__METHOD__ . ' no valid email address was found, mail could not be sent.'); return NULL; } $this->_mail($this->participant_values[$email_field], $this->_proc_tags($this->receipt_subject), Participants_Db::process_rich_text($this->_proc_tags($this->receipt_body))); }
/** * determines if a field type is "linkable" * * meaning it is displayed as a string that can be wrapped in an anchor tag * * @param object $field the field object * @return bool true if the type is linkable */ public static function field_is_linkable($field) { $linkable = in_array($field->form_element, array('text-line', 'image-upload', 'file-upload', 'dropdown', 'checkbox', 'radio')); return Participants_Db::set_filter('field_is_linkable', $linkable, $field->form_element); }
<?php $CSV_import = new PDb_CSV_Import('csv_file_upload'); ?> <div class="wrap <?php echo Participants_Db::$prefix; ?> csv-upload"> <?php Participants_Db::admin_page_heading(); ?> <div id="poststuff"> <div id="post-body"> <h2><?php echo __('Import CSV File', 'participants-database'); ?> </h2> <?php if (!empty($CSV_import->errors)) { ?> <div class="<?php echo $CSV_import->error_status; ?> fade below-h2" id="message"> <p><?php echo implode('</p><p>', $CSV_import->errors); ?> </p> </div>
/** * displays an edit field for a field attribute * * @param string $field name of the field * @return array contains parameters to use in instantiating the xnau_FormElement object */ function PDb_get_edit_field_type($field) { switch ($field) { // small integer fields case 'id': return array('type' => 'hidden'); case 'order': return array('type' => 'drag-sort'); case 'admin_column': case 'display_column': return array('type' => 'text', 'attributes' => array('class' => 'digit')); // all the booleans // all the booleans case 'persistent': case 'sortable': case 'CSV': case 'signup': case 'readonly': return array('type' => 'checkbox', 'options' => array(1, 0)); // field names can't be edited // field names can't be edited case 'name': return array('type' => 'text', 'attributes' => array('readonly' => 'readonly')); // all the text-area fields // all the text-area fields case 'values': case 'help_text': return array('type' => 'text-area'); // drop-down fields // drop-down fields case 'form_element': // populate the dropdown with the available field types from the xnau_FormElement class return array('type' => 'dropdown', 'options' => array_flip(PDb_FormElement::get_types()) + array('null_select' => false)); case 'validation': return array('type' => 'dropdown-other', 'options' => array(__('Not Required', 'participants-database') => 'no', __('Required', 'participants-database') => 'yes', __('Email', 'participants-database') => 'email-regex', 'CAPTCHA' => 'captcha', 'null_select' => false), 'attributes' => array('other' => 'regex/match')); case 'group': // these options are defined on the "settings" page return array('type' => 'dropdown', 'options' => Participants_Db::get_groups('name', 'internal') + array('null_select' => false)); case 'link': case 'title': default: return array('type' => 'text'); } }
/** * sets up the root path for the uploaded file * * defaults to the WP root */ function _set_root_path() { $this->root_path = Participants_Db::app_base_path(); }
<?php $this->print_submit_button('button-primary'); // you can specify a class for the button, second parameter sets button text ?> </td> </tr> </tbody> </table><!-- end group --> <?php $this->print_form_close(); ?> <?php } else { ?> <?php /* * this part of the template is used if no record is found */ echo empty(Participants_Db::$plugin_options['no_record_error_message']) ? '' : '<p class="alert alert-error">' . Participants_Db::plugin_setting('no_record_error_message') . '</p>'; ?> <?php } ?> </div>
private function _setup_record_groups() { foreach ($this->shortcode_object->display_groups as $group_name) { $this->record->{$group_name} = new PDb_Template_Field_Group(Participants_Db::get_group($group_name)); } }
/** * gets a permalink for a page or post for displaying a record * * it is assumed the [pdb_single] shortcode is on that page * * @var string|int $page the page slug, path or ID */ public function set_detail_page($page) { $this->detail_page = Participants_Db::find_permalink($page); }
/** * displays a settings page form using the WP Settings API * * this function is called by the plugin on it's settings page * * @return null */ public function show_settings_form() { ?> <div class="wrap participants_db settings-class"> <?php Participants_Db::admin_page_heading(Participants_Db::$plugin_title . ' ' . __('Settings', 'participants-database')); ?> <?php settings_errors(); ?> <form action="options.php" method="post" > <div class="ui-tabs"> <?php /* ?> <h2 class="nav-tab-wrapper"> <?php foreach ($this->sections as $id => $title) printf('<a class="nav-tab" href="#%s">%s</a>', Participants_Db::make_anchor($id), $title); ?> </h2> <?php */ ?> <ul class="ui-tabs-nav"> <?php foreach ($this->sections as $id => $title) { printf('<li><a href="#%s">%s</a></li>', Participants_Db::make_anchor($id), $title); } ?> </ul> <?php settings_fields($this->WP_setting); do_settings_sections($this->settings_page); ?> </div> <?php $args = array('type' => 'submit', 'class' => $this->submit_class, 'value' => $this->submit_button, 'name' => 'submit'); printf($this->submit_wrap, PDb_FormElement::get_element($args)); ?> </form> </div> <?php }
/** * triggers the shortcode present action the first time a plugin shortcode is instantiated * */ public function plugin_shortcode_action() { if (!Participants_Db::$shortcode_present) { Participants_Db::$shortcode_present = true; do_action(Participants_Db::$prefix . 'shortcode_active'); } }
break; case 'image-upload': $column->value = empty($column->value) ? '' : $column->value; break; case 'multi-select-other': case 'multi-checkbox': $column->value = is_array($column->value) ? $column->value : explode(',', $column->value); break; case 'password': $column->value = ''; break; case 'hidden': $column->form_element = 'text-line'; break; case 'timestamp': if (Participants_Db::import_timestamp($column->value) === false) { $column->value = ''; } break; } } if ('rich-text' == $column->form_element) { wp_editor($column->value, preg_replace('#[0-9_-]#', '', Participants_Db::$prefix . $column->name), array('media_buttons' => false, 'textarea_name' => $column->name, 'editor_class' => $field_class)); } else { $params = array('type' => $column->form_element, 'value' => $column->value, 'name' => $column->name, 'options' => $column->values, 'class' => $field_class, 'attributes' => $attributes, 'module' => 'admin-edit'); PDb_FormElement::print_element($params); } if (!empty($column->help_text)) { ?> <span class="helptext"><?php echo stripslashes(trim($column->help_text));
/** * supplies the current empty state logic value * * true - empty search allowed * false - empty searches not allowed * * @return bool */ public function empty_search_allowed() { if ($this->is_shortcode() || Participants_Db::plugin_setting_is_true('empty_search', false)) { return true; } return false; }
* * if you do this, check out the case below where we make a clickable * link: it does the same test so we don't duplicate the field. You'll * have to modify that in the same way */ if ($this->field->is_single_record_link()) { /* * normally, when a value is empty, nothing is shown...but if the field * has been designated as the single record link, we must have something * to click on, so, we use the default value of the field if there is no * stored value. This makes it possible to create a 'static' link to the * single record by defining a read-only field with a default value */ $value = empty($value) ? $this->field->default : $value; // add the record ID to the single record link $single_record_uri = Participants_Db::add_uri_conjunction($single_record_link) . 'pdb=' . $this->record->record_id; /* * print the opening tag of the single record link */ echo '<a class="single-record-link" href="' . $single_record_uri . '" >'; } ?> <?php /* * here is where we determine how each field value is presented, * depending on what kind of field it is */ switch ($this->field->form_element) { case 'image-upload': $image = new PDb_Image(array('filename' => $value, 'mode' => 'image', 'module' => 'list'));
/** * renders the plugin settings page * * this generic rendering is expected to be overridden in the subclass */ function render_settings_page() { ?> <div class="wrap" > <?php Participants_Db::admin_page_heading(); ?> <h2><?php echo $this->aux_plugin_title; ?> </h2> <?php settings_errors(); ?> <form method="post" action="options.php"> <?php settings_fields($this->aux_plugin_name . '_settings'); do_settings_sections($this->aux_plugin_name); submit_button(); ?> </form> </div><!-- /.wrap --> <?php }
/** * sets the record edit url * * @return null */ private function _set_record_edit_url() { $this->registration_page_url = get_bloginfo('url') . '/' . Participants_Db::plugin_setting('registration_page', ''); }
/** * prepares the error messages and CSS for a main database submission * * @return array indexed array of error messages */ public function get_validation_errors() { // check for errors if (!$this->errors_exist()) { return array(); } $output = ''; $error_messages = array(); $this->error_CSS = array(); foreach ($this->errors as $field => $error) { $field_atts = Participants_Db::get_field_atts($field); switch ($field_atts->form_element) { case 'rich-text': case 'text-area': case 'textarea': $element = 'textarea'; break; case 'link': case 'captcha': $field_atts->name .= '[]'; case 'text': case 'text-line': case 'date': $element = 'input'; break; case 'image-upload': case 'file-upload': $element = 'input'; break; default: $element = false; } $this->error_CSS[] = '[class*="' . Participants_Db::$prefix . '"] [name="' . $field_atts->name . '"]'; if (isset($this->error_messages[$error])) { $error_messages[] = $error == 'nonmatching' ? sprintf($this->error_messages[$error], $field_atts->title, Participants_Db::column_title($field_atts->validation)) : sprintf($this->error_messages[$error], $field_atts->title); $this->error_class = Participants_Db::$prefix . 'error'; } else { $error_messages[] = $error; $this->error_class = empty($field) ? Participants_Db::$prefix . 'message' : Participants_Db::$prefix . 'error'; } } // $this->errors return $error_messages; }
_e('<strong>Submit:</strong> save record and return to list<br><strong>Apply:</strong> save record and continue with same record<br><strong>Next:</strong> save record and then start a new one', 'participants-database'); ?> <br /> <?php if (!empty($input_id)) { _e('<strong>Previous:</strong> save and move to previous record', 'participants-database'); } ?> </td> </tr> <?php } else { ?> <tr> <th><h3><?php echo Participants_Db::set_filter('translate_string', $options['save_changes_label']); ?> </h3></th> <td class="submit-buttons"> <input class="button button-primary pdb-submit" type="submit" value="<?php _e($options['save_changes_button']); ?> " name="save"> <input name="submit_button" type="hidden" value="<?php echo self::$i18n['apply']; ?> "> </td> </tr> <?php }
/** * sets up a few internationalization words */ private static function _set_i18n() { self::$i18n = array('submit' => __('Submit', 'participants-database'), 'apply' => __('Apply', 'participants-database'), 'next' => __('Next', 'participants-database'), 'previous' => __('Previous', 'participants-database'), 'updated' => __('The record has been updated.', 'participants-database'), 'added' => __('The new record has been added.', 'participants-database'), 'zero_rows_error' => __('No record was added on query: %s', 'participants-database'), 'database_error' => __('Database Error: %2$s on query: %1$s', 'participants-database')); }
public static function get_types() { $types = array('text-line' => __('Text-line', 'participants-database'), 'text-area' => __('Text Area', 'participants-database'), 'rich-text' => __('Rich Text', 'participants-database'), 'checkbox' => __('Checkbox', 'participants-database'), 'radio' => __('Radio Buttons', 'participants-database'), 'dropdown' => __('Dropdown List', 'participants-database'), 'date' => __('Date Field', 'participants-database'), 'dropdown-other' => __('Dropdown/Other', 'participants-database'), 'multi-checkbox' => __('Multiselect Checkbox', 'participants-database'), 'select-other' => __('Radio Buttons/Other', 'participants-database'), 'multi-select-other' => __('Multiselect/Other', 'participants-database'), 'link' => __('Link Field', 'participants-database'), 'image-upload' => __('Image Upload Field', 'participants-database'), 'file-upload' => __('File Upload Field', 'participants-database'), 'hidden' => __('Hidden Field', 'participants-database'), 'password' => __('Password Field', 'participants-database'), 'captcha' => __('CAPTCHA', 'participants-database')); /* * this gives access to the list of form element types for alteration before * it is set */ return Participants_Db::set_filter('set_form_element_types', $types); }