initial commit
authorChuck Scott <cscott@gaslightmedia.com>
Mon, 4 Dec 2017 14:03:04 +0000 (09:03 -0500)
committerChuck Scott <cscott@gaslightmedia.com>
Mon, 4 Dec 2017 14:03:04 +0000 (09:03 -0500)
48 files changed:
activate.php [new file with mode: 0644]
assets/readme.txt [new file with mode: 0644]
classes/customFieldPluginSupport.php [new file with mode: 0644]
classes/data/dataCustomFields.php [new file with mode: 0644]
classes/data/dataCustomFieldsData.php [new file with mode: 0644]
classes/readme.txt [new file with mode: 0644]
config/plugin.ini [new file with mode: 0644]
css/admin.css [new file with mode: 0644]
css/front.css [new file with mode: 0644]
css/readme.txt [new file with mode: 0644]
deactivate.php [new file with mode: 0644]
defines.php [new file with mode: 0644]
index.php [new file with mode: 0644]
js/readme.txt [new file with mode: 0644]
lib/readme.txt [new file with mode: 0644]
misc/documentation/AddAnAdminTab.txt [new file with mode: 0644]
misc/documentation/CreateNewAddOn.txt [new file with mode: 0644]
models/admin/ajax/filterSearch.php [new file with mode: 0644]
models/admin/entity/fields.php [new file with mode: 0644]
models/admin/import/fields.php [new file with mode: 0644]
models/admin/management/fields.php [new file with mode: 0644]
models/admin/readme.txt [new file with mode: 0644]
models/front/fields/detail.php [new file with mode: 0644]
models/front/fields/list.php [new file with mode: 0644]
models/front/readme.txt [new file with mode: 0644]
readme.txt [new file with mode: 0644]
setup/adminHooks.php [new file with mode: 0644]
setup/adminMenus.php [new file with mode: 0644]
setup/adminTabs.php [new file with mode: 0644]
setup/commonHooks.php [new file with mode: 0644]
setup/databaseScripts/create_database_V1.0.0.sql [new file with mode: 0644]
setup/databaseScripts/dbVersions.php [new file with mode: 0644]
setup/frontHooks.php [new file with mode: 0644]
setup/hooksHelp.html [new file with mode: 0644]
setup/permissions.php [new file with mode: 0644]
setup/rolesAndCapabilities.php [new file with mode: 0644]
setup/shortcodes.php [new file with mode: 0644]
setup/validActions.php [new file with mode: 0644]
uninstall.php [new file with mode: 0644]
views/admin/entity/fields.html [new file with mode: 0644]
views/admin/import/fields.html [new file with mode: 0644]
views/admin/import/fieldsProcess.html [new file with mode: 0644]
views/admin/import/fieldsValidate.html [new file with mode: 0644]
views/admin/management/fields.html [new file with mode: 0644]
views/admin/readme.txt [new file with mode: 0644]
views/front/fields/detail.html [new file with mode: 0644]
views/front/fields/list.html [new file with mode: 0644]
views/front/readme.txt [new file with mode: 0644]

diff --git a/activate.php b/activate.php
new file mode 100644 (file)
index 0000000..257ff9e
--- /dev/null
@@ -0,0 +1,153 @@
+<?php
+
+/**
+ * GLM Members Database Custom Fields
+ * Activate Plugin Tasks
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package  glmMembersCustomFields
+ * @author   Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @release  activate.php,v 1.0 2014/10/31 19:31:47 cscott Exp $
+ * @link     http://dev.gaslightmedia.com/
+ */
+
+// Check that we're being called by WordPress.
+if (!defined('ABSPATH')) {
+    die("Please do not call this code directly!");
+}
+
+/*
+ * This class performs all necessary additional work when this
+ * plugin is activated.
+ *
+ * Currently the only actions are to add role capability to display and modify
+ * prototypes.
+ */
+class glmMembersCustomFieldsPluginActivate
+{
+
+    /**
+     * WordPress Database Object
+     *
+     * @var $wpdb
+     * @access public
+     */
+    public $wpdb;
+    /**
+     * Plugin Configuration Data
+     *
+     * @var $config
+     * @access public
+     */
+    public $config;
+
+    /*
+     * Constructor
+     *
+     * Note that the $noDatabaseCheck is used to access the database versions
+     * without triggering a database check.
+     *
+     * Performs all the work for this model
+     */
+    public function __construct ($wpdb, $config)
+    {
+
+        // Make sure the current user has this capability
+        if (! current_user_can('activate_plugins')) {
+            $this->addNotice("Interesting, you don't have permission to activate plugins.");
+            die();
+        }
+
+        // Save WordPress Database object
+        $this->wpdb = $wpdb;
+
+        // Save plugin configuration object
+        $this->config = $config;
+
+        // Set current plugin version
+        update_option('glmMembersCustomFieldsPluginVersion', GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_VERSION);
+
+        // Set Roles and Capabilities for this plugin
+        require_once GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SETUP_PATH.'/rolesAndCapabilities.php';
+    }
+
+    /*
+     * Add a capability to all current roles
+     *
+     * @param string $capability Name of capability to add
+     * @param array $default Whether capability should be on by default
+     *           array(
+     *               'author' => false,
+     *               'contributor' => false,
+     *               'editor' => false,
+     *               'subscriber' => false
+     *           )
+     *
+     * @return void
+     * @access private
+     */
+    private function addRoleCapability($capability, $default)
+    {
+        // Get list of role objects
+        $roleObjects = $GLOBALS['wp_roles']->role_objects;
+
+        // Get list of roles we can edit
+        $roles = get_editable_roles();
+
+        // For each role object
+        foreach ($roleObjects as $key => $role) {
+
+            // Check if the role exists in list of editable roles and
+            // the capability does not exist
+            if (isset($roles[$key]) && ! isset($role->capabilities[$capability])) {
+
+                // Check if a default value has been specified in the $default array
+                $enabled = false;
+                if (isset($default[$role->name])) {
+
+                    // It has, so use that
+                    $enabled = $default[$role->name];
+
+                }
+
+                // Add the role
+                $role->add_cap($capability, $enabled);
+
+            }
+        }
+    }
+
+
+    /*
+     * Delete a capability from all current roles
+     *
+     * @param string $capability Name of capability to add
+     *
+     * @return void
+     * @access private
+     */
+    private function deleteRoleCapability($capability)
+    {
+        // Get list of role objects
+        $roleObjects = $GLOBALS['wp_roles']->role_objects;
+
+        // Get list of roles we can edit
+        $roles = get_editable_roles();
+
+        // For each role object
+        foreach ($roleObjects as $key => $role) {
+
+            if ( isset($role->capabilities[$capability])) {
+                $role->remove_cap($capability);
+            }
+
+        }
+
+    }
+
+
+
+}
diff --git a/assets/readme.txt b/assets/readme.txt
new file mode 100644 (file)
index 0000000..34a6135
--- /dev/null
@@ -0,0 +1,2 @@
+Assets folder for things like images and other 
+files that might need to be read directly.
\ No newline at end of file
diff --git a/classes/customFieldPluginSupport.php b/classes/customFieldPluginSupport.php
new file mode 100644 (file)
index 0000000..3b55d02
--- /dev/null
@@ -0,0 +1,166 @@
+<?php
+/**
+ * Plugin Support Functions for the Custom Fields plugin
+ *
+ */
+/**
+ * customFieldsSaveMemberInfoFields
+ *
+ * Save the data for the Member Info custom fields.
+ * Uses the $_REQUEST variable glm_custom_field.
+ *
+ * @param mixed $entityID Id for the member info record
+ *
+ * @access public
+ * @return void
+ */
+function customFieldsSaveFields( $entityID ){
+    global $wpdb;
+    $fieldFail = array();
+    // If no data for custom field then return
+    if ( !isset( $_REQUEST['glm_custom_field'] ) ) {
+        return false;
+    }
+    //echo "Trying to save entity of type $uid";
+//    print_r(customFieldsGetFields($entityID));
+    // See if this memberInfo has current field data
+    $currentCustomFields = customFieldsGetFieldData( $entityID );
+    // Insert the custom field record
+    $fieldDataFormat = array(
+        '%d',
+        '%d',
+        '%s'
+    );
+    $sql = "SELECT * FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX  . "custom_fields WHERE required=1";
+    $required = $wpdb->get_results($sql);
+
+    if(!empty($required)){
+        foreach($required as $req){
+            $requiredFields[] = $req->id;
+        }
+
+        foreach($_REQUEST['glm_custom_field'] as $fieldID =>$fieldValue){
+            $cfData[$fieldID] = $fieldValue;
+            if( in_array( $fieldID,$requiredFields )){
+                if($fieldValue  === ''){
+                    $fieldFail['fieldFail'][$fieldID] = true;
+                }
+            }
+        }
+    }
+    if(!empty($fieldFail)){
+        $fieldFailData = $cfData + $fieldFail;
+         return $fieldFailData;
+    }
+    // Loop through the glm_custom_field array
+    foreach ( $_REQUEST['glm_custom_field'] as $fieldId => $fieldValue ) {
+        $fieldData =array(
+            'entity_id'  => $entityID,
+            'field_id'   => $fieldId,
+            'field_data' => wp_kses_post(stripslashes($fieldValue))
+        );
+        if ( !isset($currentCustomFields[$fieldId]) ) {
+            // Insert Entries
+            $wpdb->insert(
+                GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_field_data",
+                $fieldData,
+                $fieldDataFormat
+            );
+        } else {
+            // Update Entries
+            $wpdb->update(
+                GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_field_data",
+                $fieldData,
+                array(
+                    'entity_id' => $entityID,
+                    'field_id'  => $fieldId
+                ),
+                $fieldDataFormat,
+                '%d'
+            );
+        }
+    }
+    return true;
+}
+
+function customFieldsCloneFields( $oldId, $newId )
+{
+    global $wpdb;
+    $customFields = customFieldsGetFields( $oldId );
+    $fieldDataFormat = array(
+        '%d',
+        '%d',
+        '%s'
+    );
+    if ( isset( $customFields ) ) {
+        foreach ( $customFields as $fieldId => $fieldData ) {
+            $fieldData =array(
+                'entity_id'   => $newId,
+                'field_id'   => $fieldId,
+                'field_data' => $fieldData
+            );
+            $wpdb->insert(
+                GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_field_data",
+                $fieldData,
+                $fieldDataFormat
+            );
+        }
+    }
+}
+
+/**
+ * customFieldsGetMemberInfoFields
+ *
+ * Pull the member info custom field data.
+ * This will be used more for admin side.
+ *
+ * @param mixed $entityID Id for the member info record
+ *
+ * @access public
+ * @return void
+ */
+function customFieldsGetFieldData( $entityID )
+{
+    global $wpdb;
+    if ( !$entityID ) {
+        return false;
+    }
+    $data = array();
+    $sql = "
+    SELECT *
+      FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_field_data
+     WHERE entity_id = %d";
+    $fieldData = $wpdb->get_results( $wpdb->prepare( $sql, $entityID ), ARRAY_A );
+    if ( $fieldData ) {
+        foreach ( $fieldData as $key => $val ) {
+            $data[$val['field_id']] = $val['field_data'];
+        }
+        return $data;
+    } else {
+        return false;
+    }
+}
+/**
+ * customFieldsGetFields
+ * Pull the member info custom field data.
+ * This will be used more for admin side.
+ *
+ * @param mixed $entityID Id for the member info record
+ *
+ * @access public
+ * @return void
+ */
+function customFieldsGetFields( $entityID, $where = ' AND true ', $uid )
+{
+    global $wpdb;
+    if ( !$entityID) {
+        return false;
+    }
+    $data = array();
+    $sql = "
+    SELECT *
+      FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_fields
+      WHERE id IN (select field_id from ".GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_field_data WHERE entity_id = %d)" . $where;
+    $fieldData = $wpdb->get_results( $wpdb->prepare( $sql, $uid ), ARRAY_A );
+    echo '<pre>',  print_r($fieldData), '</pre>';
+}
diff --git a/classes/data/dataCustomFields.php b/classes/data/dataCustomFields.php
new file mode 100644 (file)
index 0000000..814118d
--- /dev/null
@@ -0,0 +1,185 @@
+<?php
+/**
+ * GLM Member-DB WordPress Add-On Plugin
+ * Data Class Fields
+ *
+ * PHP version 5.3
+ *
+ * @category Data
+ * @package  GLM Member-DB
+ * @author   Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @release  SVN: $Id: dataFields.php,v 1.0 2011/01/25 19:31:47 cscott Exp $
+ */
+
+/**
+ * GlmDataEvent class
+ *
+ * PHP version 5
+ *
+ * @category Data
+ * @package GLM Member DB
+ * @author  Chuck Scott <cscott@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ *          @release SVN: $Id: dataMembers.php,v 1.0 2011/01/25 19:31:47 cscott
+ *          Exp $
+ */
+class GlmDataFieldsCustomFields extends GlmDataAbstract
+{
+
+    /**
+     * WordPress Database Object
+     *
+     * @var $wpdb
+     * @access public
+     */
+    public $wpdb;
+    /**
+     * Plugin Configuration Data
+     *
+     * @var $config
+     * @access public
+     */
+    public $config;
+    /**
+     * Data Table Name
+     *
+     * @var $table
+     * @access public
+     */
+    public $table;
+    /**
+     * Field definitions
+     *
+     * 'type' is type of field as defined by the application
+     * text Regular text field
+     * pointer Pointer to an entry in another table
+     * 'filters' is the filter name for a particular filter ID in PHP filter
+     * functions
+     * See PHP filter_id()
+     *
+     * 'use' is when to use the field
+     * l = List
+     * g = Get
+     * n = New
+     * i = Insert
+     * e = Edit
+     * u = Update
+     * d = Delete
+     * a = All
+     *
+     * @var $ini
+     * @access public
+     */
+    public $fields = false;
+    /**
+     * MemberInfo DB object
+     *
+     * @var $MemberInfo
+     * @access public
+     */
+    public $MemberInfo;
+
+    /**
+     * Constructor
+     *
+     * @param object $d database connection
+     * @param array $config Configuration array
+     * @param bool $limitedEdit Flag to say indicate limited edit requested
+     *
+     * @return void
+     * @access public
+     */
+    public function __construct($wpdb, $config, $limitedEdit = false)
+    {
+
+        // If this class is not being extended along with existing $wpdb and $config
+        if (!$this->wpdb) {
+
+            // Save WordPress Database object
+            $this->wpdb = $wpdb;
+
+            // Save plugin configuration object
+            $this->config = $config;
+
+        }
+
+        /*
+         * Table Name
+         */
+        $this->table = GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . 'custom_fields';
+
+        /*
+         * Table Data Fields
+         */
+
+        $this->fields = array (
+
+            'id' => array (
+                'field'     => 'id',
+                'type'      => 'integer',
+                'view_only' => true,
+                'use'       => 'a'
+            ),
+
+            // Event ID
+            'field_name' => array(
+                'field'    => 'field_name',
+                'type'     => 'text',
+                'required' => true,
+                'use'      => 'a'
+            ),
+            // group id
+            'uid' => array (
+                'field'     => 'uid',
+                'type'      => 'text',
+                'view_only' => false,
+                'use'       => 'a'
+            ),
+            // Category ID
+            'field_type' => array(
+                'field'    => 'field_type',
+                'type'     => 'list',
+                'list'     => $this->config['custom_field_types'],
+                'required' => true,
+                'use'      => 'a'
+            ),
+            // required field
+            'required' => array(
+                'field'    => 'required',
+                'type'     => 'checkbox',
+                'default' => false,
+                'use'      => 'a'
+            ),
+            // admin_search flag
+            'admin_search' => array (
+                'field'   => 'admin_search',
+                'type'    => 'checkbox',
+                'default' => false,
+                'use'     => 'a'
+            ),
+
+        );
+
+    }
+
+    /*
+     * Entry Post Processing Call-Back Method
+     *
+     * Perform post-processing for all result entries.
+     *
+     * In this case we're using it to append an array of category
+     * data to each member result and also sort by member name.
+     *
+     * @param array $r Array of field result data for a single entry
+     * @param string $a Action being performed (l, i, g, ...)
+     *
+     * @return object Class object
+     *
+     */
+    public function entryPostProcessing($r, $a)
+    {
+        return $r;
+    }
+
+}
diff --git a/classes/data/dataCustomFieldsData.php b/classes/data/dataCustomFieldsData.php
new file mode 100644 (file)
index 0000000..76436ed
--- /dev/null
@@ -0,0 +1,169 @@
+<?php
+/**
+ * GLM Member-DB WordPress Add-On Plugin
+ * Data Class Fields
+ *
+ * PHP version 5.3
+ *
+ * @category Data
+ * @package  GLM Member-DB
+ * @author   Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @release  SVN: $Id: dataFields.php,v 1.0 2011/01/25 19:31:47 cscott Exp $
+ */
+
+/**
+ * GlmDataEvent class
+ *
+ * PHP version 5
+ *
+ * @category Data
+ * @package GLM Member DB
+ * @author  Chuck Scott <cscott@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ *          @release SVN: $Id: dataMembers.php,v 1.0 2011/01/25 19:31:47 cscott
+ *          Exp $
+ */
+class GlmDataFieldsCustomFieldsData extends GlmDataAbstract
+{
+
+    /**
+     * WordPress Database Object
+     *
+     * @var $wpdb
+     * @access public
+     */
+    public $wpdb;
+    /**
+     * Plugin Configuration Data
+     *
+     * @var $config
+     * @access public
+     */
+    public $config;
+    /**
+     * Data Table Name
+     *
+     * @var $table
+     * @access public
+     */
+    public $table;
+    /**
+     * Field definitions
+     *
+     * 'type' is type of field as defined by the application
+     * text Regular text field
+     * pointer Pointer to an entry in another table
+     * 'filters' is the filter name for a particular filter ID in PHP filter
+     * functions
+     * See PHP filter_id()
+     *
+     * 'use' is when to use the field
+     * l = List
+     * g = Get
+     * n = New
+     * i = Insert
+     * e = Edit
+     * u = Update
+     * d = Delete
+     * a = All
+     *
+     * @var $ini
+     * @access public
+     */
+    public $fields = false;
+    /**
+     * MemberInfo DB object
+     *
+     * @var $MemberInfo
+     * @access public
+     */
+    public $MemberInfo;
+
+    /**
+     * Constructor
+     *
+     * @param object $d database connection
+     * @param array $config Configuration array
+     * @param bool $limitedEdit Flag to say indicate limited edit requested
+     *
+     * @return void
+     * @access public
+     */
+    public function __construct($wpdb, $config, $limitedEdit = false)
+    {
+
+        // If this class is not being extended along with existing $wpdb and $config
+        if (!$this->wpdb) {
+
+            // Save WordPress Database object
+            $this->wpdb = $wpdb;
+
+            // Save plugin configuration object
+            $this->config = $config;
+
+        }
+
+        /*
+         * Table Name
+         */
+        $this->table = GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . 'custom_field_data';
+
+        /*
+         * Table Data Fields
+         */
+
+        $this->fields = array (
+
+            'id' => array (
+                'field'     => 'id',
+                'type'      => 'integer',
+                'view_only' => true,
+                'use'       => 'a'
+            ),
+            // Entity ID (event, member, package)
+            'entity_id' => array (
+                'field'     => 'entity_id',
+                'type'      => 'integer',
+                'view_only' => false,
+                'use'       => 'a'
+            ),
+            // Event ID
+            'field_id' => array(
+                'field'    => 'field_id',
+                'type'     => 'integer',
+                'required' => true,
+                'use'      => 'a'
+            ),
+
+            'field_data' => array(
+                'field'    => 'field_data',
+                'type'     => 'text',
+                'required' => true,
+                'use'      => 'a'
+            ),
+
+        );
+
+    }
+
+    /*
+     * Entry Post Processing Call-Back Method
+     *
+     * Perform post-processing for all result entries.
+     *
+     * In this case we're using it to append an array of category
+     * data to each member result and also sort by member name.
+     *
+     * @param array $r Array of field result data for a single entry
+     * @param string $a Action being performed (l, i, g, ...)
+     *
+     * @return object Class object
+     *
+     */
+    public function entryPostProcessing($r, $a)
+    {
+        return $r;
+    }
+
+}
diff --git a/classes/readme.txt b/classes/readme.txt
new file mode 100644 (file)
index 0000000..fa5f44e
--- /dev/null
@@ -0,0 +1,3 @@
+General class libraries developed specifically for this add-on should be placed in this directory.
+
+The lib directory should be considered instead for any standard class libraries not specifically developed for this add-on.
\ No newline at end of file
diff --git a/config/plugin.ini b/config/plugin.ini
new file mode 100644 (file)
index 0000000..e6f76cb
--- /dev/null
@@ -0,0 +1,11 @@
+;
+; Main Configuration File
+; {descrName}
+;
+; Place any static configuration parameters here.
+;
+
+[custom_field_types]
+text = 'text'
+textarea = 'textarea'
+checkbox = 'checkbox'
diff --git a/css/admin.css b/css/admin.css
new file mode 100644 (file)
index 0000000..cdd8308
--- /dev/null
@@ -0,0 +1,20 @@
+.glm-admin-custom-fields .glm-columns{
+    padding: 0 5px 10px 5px;
+}
+.glm-admin-custom-fields .glm-custom-field-label{
+    font-weight: bold;
+    line-height: 1;
+}
+.glm-admin-custom-fields .glm-input-wrapper{
+    display: inline-block;
+}
+@media(min-width: 1024px){
+    .glm-admin-custom-fields input[type=text]{
+/*        width: 50%;*/
+    }
+}
+@media(max-width: 1024px){
+    .glm-admin-custom-fields input[type=text]{
+        width: 100%;
+    }
+}
diff --git a/css/front.css b/css/front.css
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/css/readme.txt b/css/readme.txt
new file mode 100644 (file)
index 0000000..954cc9c
--- /dev/null
@@ -0,0 +1 @@
+Add admin.css and/or front.css to this directory to have those registered automatically.
\ No newline at end of file
diff --git a/deactivate.php b/deactivate.php
new file mode 100644 (file)
index 0000000..df95a60
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+/**
+ * GLM Members Database Custom Fields
+ * Deactivate Plugin Tasks
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package  glmMembersCustomFields
+ * @author   Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @release  admin.php,v 1.0 2014/10/31 19:31:47 cscott Exp $
+ * @link     http://dev.gaslightmedia.com/
+ */
+
+// Check that we're being called by WordPress.
+if (!defined('ABSPATH')) {
+    die("Please do not call this code directly!");
+}
+
+/*
+ * This class performs all necessary additional work when this
+ * plugin is deactivated.
+ */
+class glmMembersCustomFieldsPluginDeactivate
+{
+
+    /**
+     * WordPress Database Object
+     *
+     * @var $wpdb
+     * @access public
+     */
+    public $wpdb;
+    /**
+     * Plugin Configuration Data
+     *
+     * @var $config
+     * @access public
+     */
+    public $config;
+
+    /*
+     * Constructor
+     *
+     * Performs all the work for this model
+     */
+    public function __construct ($wpdb, $config)
+    {
+
+        // Save WordPress Database object
+        $this->wpdb = $wpdb;
+
+        // Save plugin configuration object
+        $this->config = $config;
+
+        // Delete our version from WordPress Options
+        delete_option('glmMembersCustomFieldsPluginVersion');
+    }
+
+}
diff --git a/defines.php b/defines.php
new file mode 100644 (file)
index 0000000..1c56832
--- /dev/null
@@ -0,0 +1,64 @@
+<?php
+/**
+ * {DescrName}
+ *
+ * Set standard defined parameters
+ */
+
+// NOTE: Plugin & Database versions are defined in "/glm-member-db.php".
+
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_NAME', 'GLM Members Database Custom Fields');
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SHORT_NAME', 'Fields');
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG', 'glm-member-db-customfields');
+
+// Database table prefixes - change if using add-on tables
+global $wpdb;
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX', $wpdb->prefix.'glm_MembersCustomFields_');
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_ACTIVE_DB_OPTION', 'glmMembersCustomFieldsDbVersion');
+
+// Determine which system we're running on - If not provided, assume PRODUCTION
+$host = getenv('GLM_HOST_ID');
+if (trim($host) == '') {
+    $host = 'PRODUCTION';
+}
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_HOST', $host);
+
+// Determine current http/https protocol
+$pageProtocol = 'http';
+if (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == '443') {
+    $pageProtocol = 'https';
+}
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_HTTP_PROTOCOL', $pageProtocol);
+
+// Get various pieces of the URL
+$urlParts = parse_url(get_bloginfo('url'));
+$pageUri = explode('?', $_SERVER['REQUEST_URI']);               // Bust this up to access URL path and script name only
+
+$WPUploadDir = wp_upload_dir();
+
+/*
+ *  Create a copy of the plugin slug that can be used as a variable prefix used to keep
+ *  global instances from clashing with instances in other plugins.
+ */
+$vprefix = str_replace('-', '_', GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG);
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_PREFIX', $vprefix.'_');
+
+// URLs
+define('GLM_MEMBERS_CUSTOMFIELDS_SITE_BASE_URL', home_url('/') );
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_URL', plugin_dir_url(__FILE__));
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_ADMIN_URL', admin_url('admin.php'));
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_BASE_URL', WP_PLUGIN_URL.'/'.GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG);
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_CURRENT_URL', $urlParts['scheme'].'://'.$urlParts['host'].$pageUri[0]);
+
+// Directories
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_PATH', dirname(__FILE__));
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SETUP_PATH', GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_PATH.'/setup');
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_SCRIPTS', GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SETUP_PATH.'/databaseScripts');
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_CLASS_PATH', GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_PATH.'/classes');
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_CONFIG_PATH', GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_PATH.'/config');
+
+// Parameters related to the Main GLM Member DB plugin - Depending on what's going on these may already defined by the main plugin
+$pluginsPath = str_replace(GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG, '', GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_PATH);
+define('GLM_MEMBERS_CUSTOMFIELDS_MAIN_PLUGIN_PATH', $pluginsPath.'/glm-member-db');
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_LIB_PATH', GLM_MEMBERS_CUSTOMFIELDS_MAIN_PLUGIN_PATH.'/lib');
+
diff --git a/index.php b/index.php
new file mode 100644 (file)
index 0000000..74fb839
--- /dev/null
+++ b/index.php
@@ -0,0 +1,261 @@
+<?php
+/**
+ * Plugin Name: GLM Members Database Custom Fields
+ * Plugin URI: http://www.gaslightmedia.com/
+ * Description: Custom Fields Add On
+ * Version: 1.0.0
+ * Author: Gaslight Media
+ * Author URI: http://www.gaslightmedia.com/
+ * License: GPL2
+ */
+
+/**
+ * GLM Members Database Custom Fields
+ * Index
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPluginChild
+ * @package glmMembersCustomFieldsAddOn
+ * @author Chuck Scott <cscott@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ * @version 1.0.0
+ */
+
+/*
+ *  Plugin and Database Versions
+ *
+ *  Note that the database version matches the version of the last
+ *  plugin version where there was a change in the database.
+ *
+ *  Updates to checkDatabase() in glmPluginSupport.php must be
+ *  made together with the DB_VERSION below. ONLY bump the DB
+ *  version when there's a change in the database!! Use the
+ *  version number of that release for the DB version.
+ *
+ *  We check the plugin version stored in the WordPress option below
+ *  so that we're sure the other add-ons see an up to date
+ *  version from this plugin.
+ */
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_VERSION', '1.0.0');
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_VERSION', '1.0.0');
+
+// This is the minimum version of the GLM Members DB plugin require for this plugin.
+define('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_MIN_MEMBERS_REQUIRED_VERSION', '2.8.0');
+
+// Check if plugin version is not current in WordPress option and if needed updated it
+if (GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_VERSION != get_option('glmMembersCustomFieldsPluginVersion')) {
+    update_option('glmMembersCustomFieldsPluginVersion', GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_VERSION);
+}
+
+/*
+ * Copyright 2014 Charles Scott (email : cscott@gaslightmedia.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+
+// Check that we're being called by WordPress.
+if (!defined('ABSPATH')) {
+    die("Please do not call this code directly!");
+}
+
+/*
+* Some initial setup and tests
+*/
+
+$startupNotices = '';
+
+// Get standard defined parameters
+require_once 'defines.php';
+
+// Required to be able to get user capabilities when being called as a filter from the main plugin
+require_once ABSPATH . 'wp-includes/pluggable.php';
+
+// Include defines to tell if a plugin is active
+include_once ABSPATH . 'wp-admin/includes/plugin.php';
+
+/*
+ * Do some preliminary sanity checks
+ */
+
+// Check if database version should be defined and it isn't - This would be a plugin/add-on setup issue
+if (is_file(GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_PATH.'/setup/databaseScripts/dbVersions.php') && !defined('GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_VERSION')) {
+    die('You have database scripts but have not defined a current database version at the top of index.php for this plugin/add-on!');
+}
+
+/*
+ * Check installation, activation, and version of main Member DB plugin
+ */
+
+// Check for main plugin and that it's active
+function glmMembersCustomFieldsPluginRequired() {
+    echo '
+        <div class="error">
+            <p>The '.GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_NAME.' add-on requires the base GLM Member DB plugin to be installed and active!</p>
+            <p>The '.GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_NAME.' plugin has been de-activated.</p>
+        </div>
+    ';
+}
+$plugin_name = 'glm-member-db/index.php';
+$is_active = is_plugin_active($plugin_name);
+if ($is_active != '1') {
+    add_action( 'admin_notices', 'glmMembersCustomFieldsPluginRequired' );
+    deactivate_plugins('/'.GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG.'/index.php');
+}
+
+// Check for Minimum DB version for main Member DB
+function glmMembersCustomFieldsMinVerRequired() {
+    echo '
+        <div class="error">
+            <p>The '.GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_NAME.' requires that the main GLM Member DB plugin version be no older than '
+                .GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_MIN_MEMBERS_REQUIRED_VERSION.'!<br>
+                    '.GLM_MEMBERS_CUSTOMFIELDS_MIN_VERSION_NOTE.'</p>
+            <p>The '.GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_NAME.' plugin has been de-activated.</p>
+        </div>
+    ';
+}
+$glmMembersDatabasePluginVersion = get_option('glmMembersDatabasePluginVersion');
+if (version_compare($glmMembersDatabasePluginVersion, GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_MIN_MEMBERS_REQUIRED_VERSION) < 0) {
+    define('GLM_MEMBERS_CUSTOMFIELDS_MIN_VERSION_NOTE', "Members DB: $glmMembersDatabasePluginVersion, Fields Requires: ".GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_MIN_MEMBERS_REQUIRED_VERSION);
+    add_action( 'admin_notices', 'glmMembersCustomFieldsMinVerRequired');
+    deactivate_plugins('/'.GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG.'/'.GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG.'.php');
+}
+
+/*
+ * Register this add-on with the main GLM Member DB plugin and get information on all add-ons loaded.
+ */
+require_once GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SETUP_PATH.'/validActions.php';
+require_once GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SETUP_PATH.'/shortcodes.php';
+if (is_file(GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_SCRIPTS.'/dbVersions.php')) {
+    require_once GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_SCRIPTS.'/dbVersions.php';
+}
+
+// Load Add-On Management Settings data
+/* None - Need to figure out a smooth way to do this.
+$glmMembersCustomFieldsManagementSettings = $wpdb->get_row( "SELECT * FROM ".GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX."management WHERE id = 1", ARRAY_A );
+unset($glmMembersCustomFieldsManagementSettings['id']);
+*/
+function glmMembersCustomFieldsRegisterAddOn($addOns) {
+
+    // Add this add-on to the add-ons array
+    $addOns[GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG] =  array(
+        'dir' => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_PATH,
+        'name' =>  GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_NAME,
+        'short_name' => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SHORT_NAME,
+        'slug' => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG,
+        'actions' => $GLOBALS['glmMembersCustomFieldsAddOnValidActions'],
+        'config' => parse_ini_file(GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_PATH.'/config/plugin.ini', true),
+        'shortcodes' => $GLOBALS['glmMembersCustomFieldsShortcodes'],
+        'shortcodesDescription' => $GLOBALS['glmMembersCustomFieldsShortcodesDescription']
+    );
+
+    // If we have database tables for this plugin/addon, provide that data also
+    if (isset($GLOBALS['glmMembersCustomFieldsDbVersions'])) {
+        $addOns[GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG]['database'] = array(
+            'dbPrefix' => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX,
+            'dbCurrentVersion' => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_VERSION,
+            'dbActiveVersionOption' => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_ACTIVE_DB_OPTION,
+            'dbScriptPath' => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_SCRIPTS,
+            'dbVersions' => $GLOBALS['glmMembersCustomFieldsDbVersions']
+        );
+    } else {
+        $addOns[GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG]['database'] = false;
+    }
+
+    // Return the array with our data added
+    return $addOns;
+}
+add_filter('glm-member-db-register-addon','glmMembersCustomFieldsRegisterAddOn', 10, 1);
+
+/*
+ * Plugin Update Support - uses Gaslight Media update server
+ */
+/* Not functional yet - Need to resolve JavaScript conflicts with this feature in other plugins
+require GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_LIB_PATH.'/opentools-update-checker/opentools-update-checker.php';
+${GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_PREFIX."updateChecker"} = new OpenToolsPluginUpdateChecker(
+     'http://www.gaslightmedia.com/update_server/?action=get_metadata&slug='.GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG,
+    __FILE__,
+    GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG
+);
+
+${GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_PREFIX."updateChecker"}->declareCredentials(array(
+  'license_key' => __('License Key:')
+));
+*/
+
+/*
+  *
+  * Activate and Deactivate hooks
+  *
+ */
+
+ // Activate
+function glmMembersCustomFieldsPluginActivate ()
+ {
+     global $wpdb, $config;
+     require_once GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_PATH . '/activate.php';
+     new glmMembersCustomFieldsPluginActivate($wpdb, $config);
+ }
+ register_activation_hook(__FILE__, 'glmMembersCustomFieldsPluginActivate');
+
+ // Deactivate
+ function glmMembersCustomFieldsPluginDeactivate ()
+ {
+     global $wpdb, $config;
+     require_once GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_PATH . '/deactivate.php';
+     $x = new glmMembersCustomFieldsPluginDeactivate($wpdb, $config);
+     return false;
+ }
+ register_deactivation_hook(__FILE__, 'glmMembersCustomFieldsPluginDeactivate');
+
+/*
+ * Hooks for testing capabilities provided by this add-on
+ */
+ require_once GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SETUP_PATH.'/permissions.php';
+
+/*
+ * Adding filter for updating the shortcode attributes for the member list shortcode
+ * This has to be done before the frontHooks are run.
+ */
+add_filter( 'glm-custom-fields-shortcodes', function( $shortCodes ){
+    global $wpdb;
+    if ( !is_array( $shortCodes ) || empty( $shortCodes ) ) {
+        return $shortCodes;
+    }
+    // Get all custom fields
+    $customFields = $wpdb->get_results(
+        "SELECT field_name,field_type
+           FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX .  "custom_fields",
+        ARRAY_A
+    );
+    foreach ( $customFields as $field ) {
+        switch ( $field['field_type'] ) {
+        case 'checkbox':
+            $fieldName = preg_replace( '/[ -]/', '_', strtolower( $field['field_name'] ) );
+            // If the attributes array exists in glm-members-list and the one for the custome
+            // field name has not been set yet, then set it.
+            if ( isset( $shortCodes['glm-members-list']['attributes'] )
+                && !isset( $shortCodes['glm-members-list']['attributes'][$fieldName] )
+            ) {
+                $shortCodes['glm-members-list']['attributes'][$fieldName] = false;
+            }
+            break;
+        }
+    }
+    return $shortCodes;
+    },
+    10,
+    1
+);
diff --git a/js/readme.txt b/js/readme.txt
new file mode 100644 (file)
index 0000000..f642355
--- /dev/null
@@ -0,0 +1 @@
+Add admin.js and/or front.js to this directory to have those registered automatically.
\ No newline at end of file
diff --git a/lib/readme.txt b/lib/readme.txt
new file mode 100644 (file)
index 0000000..8373066
--- /dev/null
@@ -0,0 +1,3 @@
+Standard class libraries not specifically developed for this add-on should be placed here.
+
+The classes directory should be considered instead for class libraries developed specifically for this add-on.
diff --git a/misc/documentation/AddAnAdminTab.txt b/misc/documentation/AddAnAdminTab.txt
new file mode 100644 (file)
index 0000000..c697b47
--- /dev/null
@@ -0,0 +1,15 @@
+Add an admin tab
+
+* Add a new section in setup/adminTabs.php
+
+* Add a model file - models/admin/{menu}/{action}.php
+
+* Add a view file - views/admin/{menu}/{action}.html
+
+* Add action to setup/validActions.php
+
+* If needed add a database table to the create_database_V...sql file
+  and update name to current database version, add an
+  update_database_V....sql file, and/or update dbVersions.php
+
+* If required add a data definition for any new tables
diff --git a/misc/documentation/CreateNewAddOn.txt b/misc/documentation/CreateNewAddOn.txt
new file mode 100644 (file)
index 0000000..b93235f
--- /dev/null
@@ -0,0 +1,49 @@
+Procedure to create a new GLM Members add-on plugin
+----------------------------------------------------
+
+* Checkout glm-member-db-sample and rename directory to glm-member-db-{add-on name}
+
+* From a bash prompt, run "SETUP_SCRIPT" 
+
+* Create new repository named WP-Plugins/glm-member-db-{name of add-on}.git
+
+* If there are any databases associated with this add-on, setup the database scripts and
+  data under the "setup/databaseScripts" directory. If there are no database tables
+  with this add-on, remove all but the "readme.txt" file from that directory. 
+  NOTE: No "update_database..." files should be there for a new add-on with new tables.
+  NOTE: There should be only one entry in the "dbVersions.php" file.
+
+* Carefully review "defines.php" file and update as needed.
+
+* Do a quick review of the readme.txt file and update as desired.
+
+* TEST - At this point the add-on should install and activate but not do anything.
+    - If there are any database tables, make sure they were created and are correct.
+    - Go to "Members" -> "Management" -> "Add-Ons" and make sure the add-on was
+      properly registered with the main plugin and that any database data is shown.
+
+* Adding menus
+    - Update "setup/adminMenus.php" and add menu section as described there.
+    - Add an entry in the validActions.php file. Pay attention to how slug name is 
+      constructed ("glm-members-admin-{page}-{action}").
+    - If needed add a database table to the create_database_V...sql file
+      Also add a "classes/data/data{Table}.php file
+    - Add a model file as "models/admin/{page}/{action}.php
+    - Add any desired view file as "views/admin/{page}/{action}.html
+        Note that additional possible view files should be named as...
+            "views/admin/{page}/{action}{Name}.html
+    - Test that when add-on is activated that the menu shows and is functional.
+    
+* Adding tabs
+    - Update "setup/admin/Tabs.php" and add new tab filter as described there.
+    - Add an entry in the validActions.php file. Pay attention to how slug name is 
+      constructed ("glm-members-admin-{page}-{action}").
+    - If needed add a database table to the create_database_V...sql file
+      Also add a "classes/data/data{Table}.php file
+    - Add a model file as "models/admin/{page}/{action}.php
+    - Add any desired view file as "views/admin/{page}/{action}.html
+        Note that additional possible view files should be named as...
+            "views/admin/{page}/{action}{Name}.html
+    - Test that when add-on is activated that the tab shows and is functional.
+    
+ * 
\ No newline at end of file
diff --git a/models/admin/ajax/filterSearch.php b/models/admin/ajax/filterSearch.php
new file mode 100644 (file)
index 0000000..18fb75a
--- /dev/null
@@ -0,0 +1,119 @@
+<?php
+
+/**
+ * Gaslight Media Members Database
+ * Get events for a monty for AJAX call
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package  glmMembersDatabase
+ * @author   Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @version  0.1
+ */
+
+// Load Event Times data abstract
+require_once GLM_MEMBERS_PLUGIN_CLASS_PATH .'/data/dataCategories.php';
+
+
+/*
+ * This class performs the work of handling images passed to it via
+ * an AJAX call that goes through the WorPress AJAX Handler.
+ *
+ */
+class GlmMembersAdmin_ajax_filterSearch extends GlmDataCategories
+{
+
+    /**
+     * WordPress Database Object
+     *
+     * @var $wpdb
+     * @access public
+     */
+    public $wpdb;
+    /**
+     * Plugin Configuration Data
+     *
+     * @var $config
+     * @access public
+     */
+    public $config;
+
+    /*
+     * Constructor
+     *
+     * This contructor sets up this model. At this time that only includes
+     * storing away the WordPress data object.
+     *
+     * @return object Class object
+     *
+     */
+    public function __construct ($wpdb, $config)
+    {
+
+        // Save WordPress Database object
+        $this->wpdb = $wpdb;
+
+        // Save plugin configuration object
+        $this->config = $config;
+
+        // Run constructor for members data class
+        parent::__construct(false, false);
+
+    }
+        /**
+     * getModelEventsData
+     *
+     * Return the array of events.
+     *
+     * @param integer $categoryId Id of the category for filtering events (optional)
+     * @param integer $limit      Number of events to return (optional)
+     * @param integer $memberID Member ID if filtering by member
+     *
+     * @access public
+     * @return array events
+     */
+
+
+    /*
+     * Perform Model Action
+     *
+     * This modelAction takes an AJAX image upload and stores the image in the
+     * media/images directory of the plugin.
+     *
+     * This model action does not return, it simply does it's work then calls die();
+     *
+     * @param $actionData
+     *
+     * Echos JSON string as response and does not return
+     */
+    public function modelAction ($actionData = false)
+    {
+
+        global $wpdb;
+//        
+//        $category_ids    = $_REQUEST['cat_ids'];
+//        $category_names = $_REQUEST['cat_names'];
+//        
+//        // get cat ids by name
+//        foreach($category_names as $cat_name){
+//            $sql = 'SELECT id FROM ' . GLM_MEMBERS_PLUGIN_DB_PREFIX . "categories WHERE name = '$cat_name';";
+//            $cat_id = $wpdb->get_var($sql); 
+//            
+//            // get the 
+//        }
+//        
+//        
+//        $categories = $this->getListSortedParentChild();
+//        $categories = $categories[$category_id];
+        $return = array(
+//            'manufacturers'    => $category_ids, 
+//            'brands'           => $cat_id
+        );
+
+        header('Content-type:application/json;charset=utf-8', true);
+        echo json_encode($return);
+        wp_die();
+    }
+}
diff --git a/models/admin/entity/fields.php b/models/admin/entity/fields.php
new file mode 100644 (file)
index 0000000..6049837
--- /dev/null
@@ -0,0 +1,192 @@
+<?php
+/**
+ * Gaslight Media Members Database
+ * GLM Members DB - Fields Add-on - Management Fields Tab
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package  glmMembersDatabase
+ * @author     Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @release  fields.php,v 1.0 2014/10/31 19:31:47 cscott Exp $
+ * @link     http://dev.gaslightmedia.com/
+ */
+
+// Load Management Fields data abstract
+require_once GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_CLASS_PATH.'/data/dataCustomFields.php';
+
+/**
+ * GlmMembersAdmin_management_fields
+ *
+ * PHP version 5
+ *
+ * @category Model
+ * @package GLM Member DB
+ * @author    Chuck Scott <cscott@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ *            @release SVN: $Id: packaging.php,v 1.0 2011/01/25 19:31:47 cscott
+ *            Exp $
+ */
+class GlmMembersAdmin_entity_fields extends GlmDataFieldsCustomFields
+{
+
+    /**
+     * WordPress Database Object
+     *
+     * @var $wpdb
+     * @access public
+     */
+    public $wpdb;
+    /**
+     * dbh Postgres database connection
+     *
+     * @var mixed
+     * @access public
+     */
+    public $dbh;
+    /**
+     * settings used for the schema and tablenames
+     *
+     * @var mixed
+     * @access public
+     */
+    public $settings = array();
+    /**
+     * categories
+     *
+     * @var bool
+     * @access public
+     */
+    public $categories = array();
+    public $oldCatMap = array();
+    /**
+     * fields
+     *
+     * @var bool
+     * @access public
+     */
+    public $fields = array();
+    public $image_owner;
+
+    /**
+     * Constructor
+     *
+     * This contructor performs the work for this model. This model returns
+     * an array containing the following.
+     *
+     * 'status'
+     *
+     * True if successfull and false if there was a fatal failure.
+     *
+     * 'view'
+     *
+     * A suggested view name that the contoller should use instead of the
+     * default view for this model or false to indicate that the default view
+     * should be used.
+     *
+     * 'data'
+     *
+     * Data that the model is returning for use in merging with the view to
+     * produce output.
+     *
+     * @wpdb object WordPress database object
+     *
+     * @return array Array containing status, suggested view, and any data
+     */
+    public function __construct ($wpdb, $config)
+    {
+        // Save WordPress Database object
+        $this->wpdb = $wpdb;
+
+        // Save plugin configuration object
+        $this->config = $config;
+
+        // Run constructor for members data class
+        parent::__construct(false, false);
+
+    }
+
+    /**
+     * modelAction
+     *
+     * @param bool $actionData
+     * @access public
+     * @return void
+     */
+    public function modelAction($actionData = false)
+    {
+        $option           = false;
+        $customFields     = false;
+        $haveCustomFields = false;
+        $customFieldData  = false;
+        $where = 'true';
+        $uid = '';
+
+        if (isset($_REQUEST['option'])) {
+            $option = $_REQUEST['option'];
+        }
+
+        // Check if a field ID is supplied
+        $id = 0;
+        if (isset($_REQUEST['id'])) {
+            $id = $_REQUEST['id']-0;
+        }
+        $entityID = 0;
+        if (isset($actionData)) {
+            $entityID = $actionData['entityID'];
+            $uid = $actionData['uid'];
+            $fieldFail = $actionData['cfData'];
+//            print_r($fieldFail);
+        }
+
+        switch ($option) {
+
+            default:
+                // Make sure option is set if default
+                $option = 'list';
+
+                break;
+
+        }
+        // $where .= " AND field_id in (select id from " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX ."custom_fields where uid = 'glm-member-db')";
+        $where .= " AND uid = '$uid'";
+        // Get list of Custom Fields
+        $customFields = $this->getList( $where, 'field_order,id' );
+        if ( isset($customFields) && $customFields && count( $customFields ) > 0 ) {
+            $haveCustomFields = true;
+        }
+
+        require_once GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_CLASS_PATH . '/customFieldPluginSupport.php';
+        // is array ensures that the data passed BAD
+        if(is_array($fieldFail)){
+            $customFieldsData = $fieldFail;
+        }else {
+            $customFieldsData = customFieldsGetFieldData( $entityID );
+        }
+
+
+        // Compile template data
+        $template_data = array(
+            'prefix'           => 'glm_custom_field',
+            'customFields'     => $customFields,
+            'customFieldsData' => $customFieldsData,
+            'fieldFail'        => $fieldFail,
+            'fieldTypes'       => $this->config['custom_field_types'],
+            'haveCustomFields' => $haveCustomFields,
+            'uid'              => $uid
+        );
+
+        // Return status, suggested view, and data to controller
+        return array(
+            'status'           => true,
+            'menuItemRedirect' => false,
+            'modelRedirect'    => false,
+            'view'             => 'admin/entity/fields.html',
+            'data'             => $template_data
+        );
+
+
+    }
+
+}
diff --git a/models/admin/import/fields.php b/models/admin/import/fields.php
new file mode 100644 (file)
index 0000000..6736069
--- /dev/null
@@ -0,0 +1,411 @@
+<?php
+
+/**
+ * Gaslight Media Members Database
+ * Admin Data Import
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package  glmMembersDatabase
+ * @author   Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @version  0.1
+ */
+require_once GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_CLASS_PATH.'/data/dataCustomFieldsData.php';
+require_once GLM_MEMBERS_PLUGIN_CLASS_PATH.'/data/dataMemberInfo.php';
+/*
+ * This class performs the work for the default action of the "Import" menu
+ * option.
+ *
+ */
+class GlmMembersAdmin_import_fields extends GlmDataFieldsCustomFieldsData
+{
+
+    const CSV_CHARS_PER_LINE = 6000;
+    /**
+     * WordPress Database Object
+     *
+     * @var $wpdb
+     * @access public
+     */
+    public $wpdb;
+    /**
+     * Plugin Configuration Data
+     *
+     * @var $config
+     * @access public
+     */
+    public $config;
+
+    /**
+     * errors
+     *
+     * @var $errors
+     * @access public
+     */
+    public $errors = array();
+
+    /**
+     * numberProcessed
+     *
+     * @var float
+     * @access public
+     */
+    public $numberProcessed = 0;
+
+    /**
+     * totalFields
+     *
+     * @var float
+     * @access public
+     */
+    public $totalFields = 0;
+
+    /**
+     * processingComplete
+     *
+     * @var bool
+     * @access public
+     */
+    public $processingComplete = false;
+
+    /**
+     * Constructor
+     *
+     * This contractor sets up this model. At this time that only includes
+     * storing away the WordPress data object.
+     *
+     * @return object Class object
+     *
+     */
+    public function __construct ($wpdb, $config)
+    {
+
+        // Save WordPress Database object
+        $this->wpdb = $wpdb;
+
+        // Save plugin configuration object
+        $this->config = $config;
+
+        // Run constructor for members data class
+        parent::__construct(false, false);
+
+    }
+
+    /**
+     * Perform Model Action
+     *
+     * This method does the work for this model and returns any resulting data
+     *
+     * @return array Status and data array
+     *
+     * 'status'
+     *
+     * True if successful and false if there was a fatal failure.
+     *
+     * 'menuItemRedirect'
+     *
+     * If not false, provides a menu item the controller should
+     * execute after this one. Normally if this is used, there would also be a
+     * modelRedirect value supplied as well.
+     *
+     * 'modelRedirect'
+     *
+     * If not false, provides an action the controller should execute after
+     * this one.
+     *
+     * 'view'
+     *
+     * A suggested view name that the controller should use instead of the
+     * default view for this model or false to indicate that the default view
+     * should be used.
+     *
+     * 'data'
+     *
+     * Data that the model is returning for use in merging with the view to
+     * produce output.
+     *
+     */
+    public function modelAction ($actionData = false)
+    {
+        // Set the view file
+        $view        = 'fields.html';
+        $failure     = false;
+        $option      = 'fields';
+        $clearData   = false;
+        $importRet   = false;
+        $haveMembers = false;
+        $fileExists  = false;
+        $isValid     = false;
+        // Check to see if they have members
+        $haveMembers = $this->wpdb->get_var(
+            "SELECT count(id)
+               FROM " .  GLM_MEMBERS_PLUGIN_DB_PREFIX . "members"
+        );
+        // $fileData - The main files needed for the member import
+        // - field:    input field name
+        // - name:     file name
+        // - exists:   Does file exists. Set to false at first.
+        // - validate: Validation array. Header line must match this.
+        // - type:     Type of file. Used in the processing function.
+        $fileData = array(
+            'Fields' => array(
+                'field'    => 'fields_file',
+                'name'     => 'fieldsData.csv',
+                'exists'   => false,
+                'validate' => array( 'member_id', 'field_name', 'field_value' ),
+                'type'     => 'fields',
+            ),
+        );
+        // Setting readyToProcess to false (initialize)
+        $readyToProcess = false;
+
+        // Set the $option if found in $_REQUEST array
+        if (isset($_REQUEST['option']) && $_REQUEST['option'] != '') {
+            $option = $_REQUEST['option'];
+        }
+
+        // Set the $option2 if found in $_REQUEST array
+        if (isset($_REQUEST['option2']) && $_REQUEST['option2'] != '') {
+            $option2 = $_REQUEST['option2'];
+        }
+
+        // Set variable for the upload directory
+        $wpUploadDir = wp_get_upload_dir();
+
+        // Set the $uploadPath for import files
+        $uploadPath = $wpUploadDir['basedir'] . '/' . 'glm-member-import';
+
+        // If the folder for the upload import files doesn't exists create one.
+        if ( !is_dir( $uploadPath ) ) {
+            // Get old umask
+            $oldMask = umask(0);
+            // Set folder permission
+            mkdir( $uploadPath, 0770 );
+            // reset old umask
+            umask( $oldMask );
+        }
+
+        switch( $option ) {
+
+        case 'fieldsValidate';
+            $validFiles = 0;
+            // Set the view file
+            $view       = 'fieldsValidate.html';
+            $fileCount  = count( $fileData );
+            // Move any files uploaded
+            if ( isset( $_FILES ) ) {
+                foreach ( $fileData as $fileHeader => $file ) {
+                    if ( !$_FILES[$file['field']]['error'] ) {
+                        move_uploaded_file( $_FILES[$file['field']]['tmp_name'], $uploadPath . '/'. $file['name'] );
+                    }
+                }
+            }
+            // Check that each file exists
+            foreach ( $fileData as $fileHeader => $file ) {
+                if ( is_file( $uploadPath . '/' . $file['name'] ) ) {
+                    $fileData[$fileHeader]['exists']  = true;
+                    $fData = $this->readCSVFileHeaders( $uploadPath . '/' . $file['name'] );
+                    $isValid = ( $file['validate'] == $fData );
+                    if ( $isValid ) {
+                        $validFiles++;
+                    }
+                    $fileData[$fileHeader]['data']    = $fData;
+                    $fileData[$fileHeader]['isValid'] = $isValid;
+                }
+            }
+            $readyToProcess = ( $validFiles == $fileCount );
+            break;
+
+        case 'fieldsProcess':
+            $memberInfoData = new GlmDataMemberInfo( $this->wpdb, $this->config );
+            foreach ( $fileData as $fileHeader => $file ) {
+                if ( is_file( $uploadPath . '/' . $file['name'] ) ) {
+                    $fields = $this->readCSVFields( $uploadPath . '/'. $file['name'] );
+                    //echo '<pre>$fields: ' . print_r( $fields, true ) . '</pre>';
+                    $this->totalFields = count( $fields );
+                    // Clear the custom field data table
+                    $this->wpdb->query( "DELETE FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX .  "custom_field_data" );
+                    foreach ( $fields as $customRow ) {
+                        // Need to first get the member id from the database
+                        // It will match from the old_member_id field
+                        $memberId = $this->wpdb->get_var(
+                            $this->wpdb->prepare(
+                                "SELECT id
+                                   FROM " . GLM_MEMBERS_PLUGIN_DB_PREFIX . "members
+                                  WHERE old_member_id = %d",
+                                $customRow[0]
+                            )
+                        );
+                        // get the active member info id
+                        $memberInfoId =
+                            $memberInfoData->getActiveInfoIdForMember( $memberId );
+                        $customFieldId = $this->wpdb->get_var(
+                            $this->wpdb->prepare(
+                                "SELECT id
+                                   FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_fields
+                                  WHERE field_name = %s",
+                                $customRow[1]
+                            )
+                        );
+                        if ( $customFieldId ) {
+                            $newId = $this->wpdb->insert(
+                                GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX .  'custom_field_data',
+                                array(
+                                    'ref_dest'   => $memberInfoId,
+                                    'field_id'   => $customFieldId,
+                                    'field_data' => $customRow[2],
+                                ),
+                                array(
+                                    '%d',
+                                    '%d',
+                                    '%s'
+                                )
+                            );
+                            $this->numberProcessed++;
+                        }
+                    }
+                    $importRet = array();
+                }
+            }
+            if ( count( $this->errors ) == 0 ) {
+                $readyToProcess = true;
+            }
+            // Here we need to check to see if we processed all members.
+            // Also the counter has to increment the total processed so far.
+            if ( $this->numberProcessed == $this->totalFields ) {
+                $this->processingComplete = true;
+            }
+            // Set the view file:<
+            $view = 'fieldsProcess.html';
+            break;
+
+        case 'fields':
+        default:
+            // Set the view file
+            $view = 'fields.html';
+            // check upload dir to see if they have any files in yet
+            foreach ( $fileData as $fileHeader => $file ) {
+                if ( is_file( $uploadPath . '/' . $file['name'] ) ) {
+                    $fileData[$fileHeader]['exists'] = true;
+                    $fileData[$fileHeader]['mtime']  = filemtime( $uploadPath . '/' . $file['name'] );
+                }
+            }
+
+            break;
+
+        }
+
+        // Setup the template data array
+        $templateData = array(
+            'fileExists'      => $fileExists,
+            'option'          => $option,
+            'errors'          => $this->errors,
+            'numberProcessed' => $this->numberProcessed,
+            'totalFields'     => $this->totalFields,
+            'completed'       => $this->processingComplete,
+            'data'            => false,
+            'fileData'        => $fileData,
+            'clearData'       => $clearData,
+            'importRet'       => $importRet,
+            'csvData'         => '<pre>$fileData: ' . print_r( $fileData, true ) . '</pre>',
+            'readyToProcess'  => $readyToProcess,
+            'haveMembers'     => $haveMembers,
+            'isValid'         => $isValid,
+            'sampleFileUrl'   => GLM_MEMBERS_PLUGIN_BASE_URL . '/sample-files/',
+        );
+
+        // Return status, suggested view, and data to controller
+        return array(
+            'status'           => true,
+            'menuItemRedirect' => false,
+            'modelRedirect'    => false,
+            'view'             => 'admin/import/' . $view,
+            'data'             => $templateData,
+        );
+
+    }
+
+    /**
+     * Read in fields from a csv file
+     *
+     * Header line as follows. Data follows immediately below this line. this
+     * line and all above it are ignored.
+     *
+     *  'member_id','member_name','member_login','member_passwd','contact_email'
+     *
+     * @param string $csv Temporary file name of csv file upload
+     *
+     * @return array Array of data from CSV file or an error message
+     *
+     */
+    public function readCSVFields($csv)
+    {
+
+        $fields = array();
+        $startImport = false;
+
+        // Try to open file
+        if (($handle = fopen($csv, "r")) !== false) {
+
+            // For each line in the file
+            while (($c = fgetcsv($handle, 1000, ",")) !== false) {
+
+                // If we're past the header, the first item is numeric, and we have at least 5 fields
+                if($startImport && ($c[0]-0) > 0 && count($c) >= 3) {
+
+                    // Add this line of data to Contacts
+                    $fields[] = $c;
+
+                }
+
+                // If we find the header, assume all data is below that
+                if ($c[0] == 'member_id') {
+                    $startImport = true;
+                }
+
+            }
+
+            fclose($handle);
+
+        } else {
+            return "No file submitted.";
+        }
+
+        // If we never found the header
+        if (!$startImport) {
+            return "Required header not found in file.";
+        }
+
+        // If we found no data below the header
+        if (count($fields) == 0) {
+            return "Header found but no data followed";
+        }
+
+        return $fields;
+
+    }
+
+    /**
+     * readCSVFileHeaders
+     *
+     * Read the cvs file. Just the first line is read.
+     *
+     * @param mixed $fileName Name of the file (path)
+
+     * @access public
+     * @return void
+     */
+    public function readCSVFileHeaders( $fileName )
+    {
+        $fileHeaders = array();
+        if ( ( $fp = fopen( $fileName, 'r' ) ) !== false ) {
+            // get first line to use as headers
+            $fileHeaders = fgetcsv( $fp, SELF::CSV_CHARS_PER_LINE, ',' );
+            fclose( $fp );
+        }
+
+        return $fileHeaders;
+    }
+}
diff --git a/models/admin/management/fields.php b/models/admin/management/fields.php
new file mode 100644 (file)
index 0000000..cc22962
--- /dev/null
@@ -0,0 +1,228 @@
+<?php
+/**
+ * Gaslight Media Members Database
+ * GLM Members DB - Fields Add-on - Management Fields Tab
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package  glmMembersDatabase
+ * @author     Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @release  fields.php,v 1.0 2014/10/31 19:31:47 cscott Exp $
+ * @link     http://dev.gaslightmedia.com/
+ */
+
+// Load Management Fields data abstract
+require_once GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_CLASS_PATH.'/data/dataCustomFields.php';
+
+/**
+ * GlmMembersAdmin_management_fields
+ *
+ * PHP version 5
+ *
+ * @category Model
+ * @package GLM Member DB
+ * @author    Chuck Scott <cscott@gaslightmedia.com>
+ * @license http://www.gaslightmedia.com Gaslightmedia
+ *            @release SVN: $Id: packaging.php,v 1.0 2011/01/25 19:31:47 cscott
+ *            Exp $
+ */
+class GlmMembersAdmin_management_fields extends GlmDataFieldsCustomFields
+{
+
+    /**
+     * WordPress Database Object
+     *
+     * @var $wpdb
+     * @access public
+     */
+    public $wpdb;
+    /**
+     * dbh Postgres database connection
+     *
+     * @var mixed
+     * @access public
+     */
+    public $dbh;
+    /**
+     * settings used for the schema and tablenames
+     *
+     * @var mixed
+     * @access public
+     */
+    public $settings = array();
+    /**
+     * categories
+     *
+     * @var bool
+     * @access public
+     */
+    public $categories = array();
+    public $oldCatMap = array();
+    /**
+     * fields
+     *
+     * @var bool
+     * @access public
+     */
+    public $fields = array();
+    public $image_owner;
+
+    /**
+     * Constructor
+     *
+     * This contructor performs the work for this model. This model returns
+     * an array containing the following.
+     *
+     * 'status'
+     *
+     * True if successfull and false if there was a fatal failure.
+     *
+     * 'view'
+     *
+     * A suggested view name that the contoller should use instead of the
+     * default view for this model or false to indicate that the default view
+     * should be used.
+     *
+     * 'data'
+     *
+     * Data that the model is returning for use in merging with the view to
+     * produce output.
+     *
+     * @wpdb object WordPress database object
+     *
+     * @return array Array containing status, suggested view, and any data
+     */
+    public function __construct ($wpdb, $config)
+    {
+
+        // Save WordPress Database object
+        $this->wpdb = $wpdb;
+
+        // Save plugin configuration object
+        $this->config = $config;
+
+        // Run constructor for members data class
+        parent::__construct(false, false);
+
+    }
+
+    /**
+     * modelAction
+     *
+     * @param bool $actionData
+     * @access public
+     * @return void
+     */
+    public function modelAction($actionData = false)
+    {
+        $glm_action            = '';
+        $option                = false;
+        $settings_updated      = false;
+        $settings_update_error = false;
+        $custom_fields         = false;
+        $haveCustomFields      = false;
+        $where                 = ' TRUE ';
+
+        if (isset($_REQUEST['option2'])) {
+            $option = $_REQUEST['option2'];
+        }
+
+        if (isset($_GET['glm_action'])) {
+            $glm_action = $_GET['glm_action'];
+        }
+
+        // Check if a field ID is supplied
+        $id = 0;
+        if (isset($_REQUEST['id'])) {
+            $id = $_REQUEST['id']-0;
+        }
+
+        $uid = 0;
+
+        if (isset($actionData['uid'])) {
+            $uid = $actionData['uid'];
+        }
+
+        switch ($option) {
+
+            case 'addNew':
+                $this->insertEntry();
+                break;
+
+            case 'update':
+                if ($id > 0) {
+                    $this->updateEntry($id);
+                }
+                break;
+
+            case 'delete':
+                if ($id > 0) {
+                    $this->deleteEntry($id, true);
+
+                    // Also delete any data entries
+                    $this->wpdb->delete(
+                        GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . 'custom_field_data',
+                        array( 'field_id' => $id )
+                    );
+                }
+                break;
+
+            default:
+                // Make sure option is set if default
+                $option = 'list';
+
+                // Determine if current user can edit configurations
+                if (!current_user_can('glm_members_management')) {
+                    return array(
+                        'status'           => false,
+                        'menuItemRedirect' => 'error',
+                        'modelRedirect'    => 'index',
+                        'view'             => 'admin/error/index.html',
+                        'data'             => array(
+                            'reason' => 'User does not have rights to make configuration changes.'
+                        )
+                    );
+                }
+
+                break;
+
+        }
+
+        $where .= " AND uid = '$uid' ";
+
+        // Get list of Custom Fields
+        $custom_fields = $this->getList( $where );
+        //  echo "<pre>REQUEST " . print_r($_REQUEST, true) . "</pre>";
+        //  echo "<pre>GET " . print_r($_GET, true) . "</pre>";
+        if ( isset($custom_fields) && $custom_fields && count( $custom_fields ) > 0 ) {
+            $haveCustomFields = true;
+        }
+
+        // Compile template data
+        $template_data = array(
+            'option2'             => $option,
+            'settingsUpdated'     => $settings_updated,
+            'settingsUpdateError' => $settings_update_error,
+            'custom_fields'       => $custom_fields,
+            'field_types'         => $this->config['custom_field_types'],
+            'haveCustomFields'    => $haveCustomFields,
+            'uid'                 => $uid,
+            'glm_action'          => $glm_action
+        );
+        // echo "<pre>Template data:" . print_r($template_data, true) . "</pre>";
+
+        // Return status, suggested view, and data to controller
+        return array(
+            'status'           => true,
+            'menuItemRedirect' => false,
+            'modelRedirect'    => false,
+            'view'             => 'admin/management/fields.html',
+            'data'             => $template_data
+        );
+
+
+    }
+
+}
diff --git a/models/admin/readme.txt b/models/admin/readme.txt
new file mode 100644 (file)
index 0000000..e9a199d
--- /dev/null
@@ -0,0 +1,5 @@
+The admin controller executes models under this directory.
+
+Typically you should add a directory here that matches the page where the action should take place.
+
+Under that directory place the model for the various actions.
\ No newline at end of file
diff --git a/models/front/fields/detail.php b/models/front/fields/detail.php
new file mode 100644 (file)
index 0000000..231a1d6
--- /dev/null
@@ -0,0 +1,134 @@
+<?php
+/**
+ * list.php
+ *
+ * This is the Members Fields Plugin model for the front list shortcode.
+ * Handles the default and searching of the fields. Then calls appropriate view
+ * files.
+ */
+require_once GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_CLASS_PATH . '/data/dataCustomFields.php';
+require_once GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_CLASS_PATH . '/data/dataCustomFieldsData.php';
+require_once GLM_MEMBERS_PLUGIN_CLASS_PATH . '/data/dataMemberInfo.php';
+
+/**
+ * GlmMembersFront_fields_detail
+ *
+ * @uses      GlmDataFields
+ * @package   GlmMemberFields
+ * @version   0.0.1
+ * @copyright Copyright (c) 2010 All rights reserved.
+ * @license   PHP Version 3.0 {@link http://www.php.net/license/3_0.txt}
+ */
+class GlmMembersFront_fields_detail extends GlmDataFieldsCustomFields
+{
+
+    /**
+     * modelAction
+     *
+     * @param bool $actionData Action Data passed to the modelAction
+     *
+     * @access public
+     * @return void
+     */
+    /**
+     * WordPress Database Object
+     *
+     * @var $wpdb
+     * @access public
+     */
+    public $wpdb;
+    /**
+     * Plugin Configuration Data
+     *
+     * @var $config
+     * @access public
+     */
+    public $config;
+
+    public function modelAction( $actionData = false )
+    {
+        $member_info_id = null;
+        $where          = '';
+        $order          = '';
+        $field_vals     = '';
+        $slash_price    = false;
+
+        global $wpdb;
+
+        // get the member id to pass to getList, set the where clause
+        if ( isset( $actionData['request']['member'] ) ) {
+            $member_info_id = $actionData['request']['member'] - 0;
+
+            $member_info_object = new GlmDataMemberInfo($this->wpdb, $this->config);
+            $member_info        = $member_info_object->getEntry($member_info_id);
+//            print_r($member_info);
+            $member_name = $member_info['member_name'];
+            $member_name = urlencode($member_name);
+
+            $where = "entity_id = $member_info_id";
+
+            $fields_data    = new GlmDataFieldsCustomFieldsData($this->wpdb, $this->config);
+            $field_values   = $fields_data->getList($where);
+
+            $sql = "
+            SELECT mt.name
+              FROM " . GLM_MEMBERS_PLUGIN_DB_PREFIX . "member_type mt, " . GLM_MEMBERS_PLUGIN_DB_PREFIX . "members m,
+                   " . GLM_MEMBERS_PLUGIN_DB_PREFIX . "member_info mi
+             WHERE mi.id = $member_info_id
+               AND m.id = mi.member
+               AND mt.id = m.member_type";
+            $member_type    = $wpdb->get_var($sql);
+/*
+            $sql            = "
+            SELECT mt.name
+              FROM " . GLM_MEMBERS_PLUGIN_DB_PREFIX . "member_type mt, " . GLM_MEMBERS_PLUGIN_DB_PREFIX . "members m
+             WHERE m.id = $member_info_id
+               AND mt.id = m.member_type";
+ */
+
+
+
+            foreach($field_values as $key=>$value){
+                $field_id       = $value['field_id'];
+                $field_value    = $value['field_data'];
+
+                $sql            = "SELECT field_name FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_fields WHERE id = $field_id;";
+                $field_name     = $wpdb->get_results($sql);
+                $field_name     = $field_name[0]->field_name;
+                $slug           = sanitize_title($field_name);
+
+                if( $field_value ){
+                    if( $slug === 'msrp-sale' && $field_value === 'Yes' || $slug === 'sale-price' && $field_value !== ''){
+                        $fields[$slug] = array('nice' => $field_name,'data' => $field_value, 'type' => $member_type, 'slash' => true);
+                    } else {
+                        $fields[$slug] = array('nice' => $field_name,'data' => $field_value, 'type' => $member_type, 'slash' => false);
+                    }
+                }
+            }
+        }
+        // Compile template data
+        $templateData = array(
+            'field_values'  => $fields,
+            'member_name'   => $member_name
+        );
+        error_reporting(E_ALL ^ E_NOTICE);
+        return array(
+            'status'           => $status,
+            'menuItemRedirect' => false,
+            'modelRedirect'    => false,
+            'view'             => 'front/fields/detail.html',
+            'data'             => $templateData,
+            'settings'         => $settings
+        );
+    }
+
+    public function cleanText($text){
+        $text = str_replace('&nbsp;', ' ', $text);
+        $text = str_replace('&ndash;', '-', $text);
+        $text = str_replace('&#39;', "'", $text);
+        $text = str_replace("\n", ' ', $text);
+        $text = str_replace("\r", '', $text);
+        return $text;
+    }
+}
+
diff --git a/models/front/fields/list.php b/models/front/fields/list.php
new file mode 100644 (file)
index 0000000..50b7206
--- /dev/null
@@ -0,0 +1,131 @@
+<?php
+/**
+ * list.php
+ *
+ * This is the Members Fields Plugin model for the front list shortcode.
+ * Handles the default and searching of the fields. Then calls appropriate view
+ * files.
+ */
+require_once GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_CLASS_PATH . '/data/dataCustomFields.php';
+require_once GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_CLASS_PATH . '/data/dataCustomFieldsData.php';
+require_once GLM_MEMBERS_PLUGIN_CLASS_PATH . '/data/dataMemberInfo.php';
+
+/**
+ * GlmMembersFront_fields_list
+ *
+ * @uses      GlmDataFields
+ * @package   GlmMemberFields
+ * @version   0.0.1
+ * @copyright Copyright (c) 2010 All rights reserved.
+ * @license   PHP Version 3.0 {@link http://www.php.net/license/3_0.txt}
+ */
+class GlmMembersFront_fields_list extends GlmDataFieldsCustomFields
+{
+
+    /**
+     * modelAction
+     *
+     * @param bool $actionData Action Data passed to the modelAction
+     *
+     * @access public
+     * @return void
+     */
+    /**
+     * WordPress Database Object
+     *
+     * @var $wpdb
+     * @access public
+     */
+    public $wpdb;
+    /**
+     * Plugin Configuration Data
+     *
+     * @var $config
+     * @access public
+     */
+    public $config;
+
+    public function modelAction( $actionData = false )
+    {
+        $member_info_id      = null;
+        $where          = '';
+        $order          = '';
+        $field_vals     = '';
+        $slash_price    = false;
+
+        global $wpdb;
+        $assets_dir  = get_stylesheet_directory_uri() .'/assets';
+
+        // get the member id to pass to getList, set the where clause
+        if ( isset( $actionData['request']['member'] ) ) {
+            $member_info_id = $actionData['request']['member'] - 0;
+
+            $where = "entity_id = $member_info_id";
+
+            $fields_data        = new GlmDataFieldsCustomFieldsData($this->wpdb, $this->config);
+            $field_values       = $fields_data->getList($where);
+
+            $sql = "
+            SELECT mt.name
+              FROM " . GLM_MEMBERS_PLUGIN_DB_PREFIX . "member_type mt, " . GLM_MEMBERS_PLUGIN_DB_PREFIX . "members m,
+                   " . GLM_MEMBERS_PLUGIN_DB_PREFIX . "member_info mi
+             WHERE mi.id = $member_info_id
+               AND m.id = mi.member
+               AND mt.id = m.member_type";
+            $member_type    = $wpdb->get_var($sql);
+
+            if ( isset( $field_values ) &&  is_array( $field_values ) ) {
+                foreach( $field_values as $key=>$value ){
+                    $field_id       = $value['field_id'];
+                    $field_value    = $value['field_data'];
+
+                    $sql            = "SELECT field_name FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_fields WHERE id = $field_id;";
+                    $field_name     = $wpdb->get_var($sql);
+                    $slug           = sanitize_title($field_name);
+
+                    if( $field_value ){
+                        if( $slug === 'msrp-sale' && $field_value === 'Yes' || $slug === 'sale-price' && $field_value !== ''){
+                            $fields[$slug] = array('nice' => $field_name,'data' => $field_value, 'type' => $member_type, 'slash' => true);
+                        } else {
+                            $fields[$slug] = array('nice' => $field_name,'data' => $field_value, 'type' => $member_type, 'slash' => false);
+                        }
+
+                    }
+                }
+            }
+        }
+        /*
+         * Check for which view file to use, else default to list
+         */
+        $view = "list";
+        if (isset($actionData['request']['view']) && $actionData['request']['view'] != "" ) {
+            $view = strtolower($actionData['request']['view']);
+        }
+
+        // Compile template data
+        $templateData = array(
+            'field_values'  => $fields,
+            'assets_dir'    => $assets_dir,
+            'view'          => $view
+        );
+        error_reporting(E_ALL ^ E_NOTICE);
+        return array(
+            'status'           => $status,
+            'menuItemRedirect' => false,
+            'modelRedirect'    => false,
+            'view'             => 'front/fields/list.html',
+            'data'             => $templateData,
+            'settings'         => $settings
+        );
+    }
+
+    public function cleanText($text){
+        $text = str_replace('&nbsp;', ' ', $text);
+        $text = str_replace('&ndash;', '-', $text);
+        $text = str_replace('&#39;', "'", $text);
+        $text = str_replace("\n", ' ', $text);
+        $text = str_replace("\r", '', $text);
+        return $text;
+    }
+}
+
diff --git a/models/front/readme.txt b/models/front/readme.txt
new file mode 100644 (file)
index 0000000..4c54852
--- /dev/null
@@ -0,0 +1,7 @@
+The front controller executes models under this directory.
+
+Typically you should add a directory here that matches the category of actions that will take place.
+
+Under that directory place the model for the various actions.
+
+Actions under this directory would normally be called due to processing of a shortcode.
\ No newline at end of file
diff --git a/readme.txt b/readme.txt
new file mode 100644 (file)
index 0000000..3f8f42b
--- /dev/null
@@ -0,0 +1,27 @@
+=== GLM Members Database Custom Fields ===
+Contributors: cscott@gaslightmedia.com
+Donate link: http://www.gaslightmedia.com
+Tags: Gaslight Media,Plugin,Fields
+Requires at least: 3.0.1
+Tested up to: 3.4
+Stable tag: 4.3
+License: GPLv2 or later
+License URI: http://www.gnu.org/licenses/gpl-2.0.html
+
+This is the GLM Members Database Custom Fields.
+
+== Description ==
+
+The GLM Members Database Custom Fields is an add-on to the Gaslight Media Members Database,
+which is required to install and run this plugin
+
+== Installation ==
+
+This section describes how to install the plugin and get it working.
+
+e.g.
+
+1. Upload `plugin-name.php` to the `/wp-content/plugins/` directory
+1. Activate the plugin through the 'Plugins' menu in WordPress
+
+
diff --git a/setup/adminHooks.php b/setup/adminHooks.php
new file mode 100644 (file)
index 0000000..803d3b1
--- /dev/null
@@ -0,0 +1,224 @@
+<?php
+/**
+ * GLM Members Database Custom Fields
+ * GLM Members Misc Admin Hooks and Filters
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package  glmMembersDatabase
+ * @author   Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @release  adminHooks.php,v 1.0 2014/10/31 19:31:47 cscott Exp $
+ * @link     http://dev.gaslightmedia.com/
+ */
+
+/*
+ * Place Misc Hooks and Filters here. If this file exists, it will be included
+ * by the add-on main plugin script.
+ *
+ * Note that filter and hook callback functions must be included in-line as shown below...
+ *
+ *  add_filter( 'filter_title', function( $parameter ) {
+ *     // Function code
+ *  });
+ *
+ *  Also note that parameters will be in the context of the main admin controller constructor.
+  */
+
+// Add hooksHelp.html file to admin Management hooks output
+add_filter('glm-member-db-admin-management-hooksHelp', function($content) {
+
+    // Read in this plugin/addon hook help file
+    $fname = GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_PATH.'/setup/hooksHelp.html';
+    if (is_file($fname)) {
+        $hooksHelp = file_get_contents($fname);
+        if ($hooksHelp != false) {
+            $content .= $hooksHelp;
+        }
+    }
+    return $content;
+},
+10,
+2
+);
+
+/**
+ * Filter will return true if the plugin is active.
+ */
+add_filter( 'glm-members-customfields-active', function( $active ){
+    return true;
+}, 10, 1 );
+
+/**
+ * Filter returns html from the management -> fields model.
+ */
+add_filter( 'glm-members-customfields-edit', function( $content, $uid ){
+    unset( $_REQUEST['glm_action'] );
+    $content .= $this->controller( 'management', 'fields', array( 'uid' => $uid ), true );
+    return $content;
+}, 10, 2 );
+
+/**
+ * Filter returns the html for the form segment
+ */
+add_filter( 'glm-members-custom-fields-form', function( $content, $uid, $id,$cfData = false ){
+    unset( $_REQUEST['glm_action'] );
+    // echo "CONTENT: " .  $content . " UID: " . $uid . " ID: " . $id . '<br>';
+    $content .= $this->controller( 'entity', 'fields', array( 'uid' => $uid, 'entityID' => $id,'cfData'=>$cfData ), true);
+    return $content;
+}, 10, 4 );
+
+/**
+ * Filter Captured Data Success Status
+ *
+ * Returns Stored Data
+ */
+add_filter( 'glm-members-customfields-capture', function( $content, $uid, $id ){
+
+}, 10, 3 );
+
+/**
+ * Filter to Return Stored Data
+ */
+add_filter( 'glm-members-customfields-data', function( $content, $uid, $id ){
+
+}, 10, 3 );
+
+/**
+ * Filter to Return a tab link for multi-page sub-tabs.
+ */
+add_filter( 'glm-member-db-customfields-nav', function( $content, $tableName ){
+    $out .= '<a id="glm-custom-fields" data-show-table="glm-table-custom-fields" class="glm-'.$tableName .'-tab nav-tab">Custom Fields</a>';
+    return $out;
+},10,2);
+
+/**
+ *  ?????????
+ */
+add_filter( 'glm-member-db-custom-fields-tab', function( $content, $entityID = '' ){
+    unset( $_REQUEST['glm_action'] );
+    $content = $this->controller( 'fields', 'fields', $entityID );
+    return $content;
+},1,2);
+
+/**
+ * Admin member list filter for displaying filters for the custom fields
+ */
+add_filter( 'glm-member-db-custom-filter-search', function ( $content ) {
+$parts = array();
+    $customFields = $this->wpdb->get_results(
+        "SELECT *
+           FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX .  "custom_fields
+          WHERE admin_search = 1",
+        ARRAY_A
+    );
+    if ( isset( $customFields ) && count( $customFields ) > 0 ) {
+        foreach ( $customFields as $key => $field ) {
+            switch ( $field['field_type'] ) {
+            case 'textarea':
+                break;
+            case 'text':
+                // convert name to lower case and replace spaces with _
+                $field_name = preg_replace( '/[ -]/', '_', strtolower( $field['field_name'] ) );
+                $parts[$field['id']] = '<b>' . $field['field_name'] . ':</b> <input type="text" size="10" name="' . $field_name . '"';
+                if ( isset( $_REQUEST[$field_name] ) && $fieldValue = filter_var( $_REQUEST[$field_name], FILTER_SANITIZE_STRING ) ) {
+                    $parts[$field['id']] .= ' value="' . $fieldValue . '"';
+                }
+                $parts[$field['id']] .= '></b>';
+
+                break;
+            case 'checkbox':
+                // convert name to lower case and replace spaces with _
+                $field_name = preg_replace( '/[ -]/', '_', strtolower( $field['field_name'] ) );
+                $parts[$field['id']] = '<b>' . $field['field_name'] . ':</b> <input type="checkbox" name="' . $field_name . '" value="1"';
+                if ( isset( $_REQUEST[$field_name] ) && filter_var( $_REQUEST[$field_name], FILTER_VALIDATE_BOOLEAN ) ) {
+                    $parts[$field['id']] .= ' checked';
+                }
+                $parts[$field['id']] .= '></b>';
+                break;
+            }
+        }
+    }
+    return implode( ' ', $parts );
+});
+
+/**
+ * Front End Query Hook for searching member by custom fields
+ */
+add_filter('glm-member-db-admin-search-query', function() {
+    $queryParts = array();
+    // Get all custom fields
+    $customFields = $this->wpdb->get_results(
+        "SELECT *
+           FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX .  "custom_fields
+          WHERE admin_search = 1",
+        ARRAY_A
+    );
+    if ( isset( $customFields ) && count( $customFields ) > 0 ) {
+        foreach ( $customFields as $key => $field ) {
+            switch ( $field['field_type'] ) {
+            case 'textarea':
+                break;
+            case 'text':
+                // convert name to lower case and replace spaces with _
+                $field_name = preg_replace( '/[ -]/', '_', strtolower( $field['field_name'] ) );
+                if ( isset( $_REQUEST[$field_name] ) && $fieldValue = filter_var( $_REQUEST[$field_name], FILTER_SANITIZE_STRING ) ) {
+                    $queryParts[] = " T.id IN (
+                        SELECT mi.member
+                          FROM " . GLM_MEMBERS_PLUGIN_DB_PREFIX . "member_info mi, " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_field_data cfd
+                         WHERE cfd.entity_id = mi.id
+                           AND cfd.field_data like '%" .  esc_sql( $fieldValue ) . "%'
+                           AND cfd.field_id = (SELECT id
+                                           FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_fields
+                                          WHERE field_name = '" . esc_sql( $field['field_name'] ) . "'))";
+                }
+
+                break;
+            case 'checkbox':
+                // convert name to lower case and replace spaces with _
+                $field_name = preg_replace( '/[ -]/', '_', strtolower( $field['field_name'] ) );
+                if ( isset( $_REQUEST[$field_name] ) && filter_var( $_REQUEST[$field_name], FILTER_VALIDATE_BOOLEAN ) ) {
+                    $queryParts[] = " T.id IN (
+                        SELECT mi.member
+                          FROM " . GLM_MEMBERS_PLUGIN_DB_PREFIX . "member_info mi, " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_field_data cfd
+                         WHERE cfd.entity_id = mi.id
+                           AND cfd.field_data = 'Yes'
+                           AND cfd.field_id = (SELECT id
+                                           FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_fields
+                                          WHERE field_name = '" . esc_sql( $field['field_name'] ) . "'))";
+                }
+                break;
+            }
+        }
+    }
+    return $queryParts;
+});
+
+/**
+ * ????????
+ */
+add_filter('glm-member-db-save-custom-fields', function( $entityID) {
+    require_once GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_CLASS_PATH . '/customFieldPluginSupport.php';
+    // this will save the member data
+    //echo "uid = $uid";
+    return customFieldsSaveFields( $entityID);
+
+    },
+    10,
+    1
+);
+
+/**
+ * ????????
+ */
+add_action(
+    'glm-member-db-clone-custom-fields',
+    function( $entityID, $newId ){
+        require_once GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_CLASS_PATH . '/customFieldPluginSupport.php';
+        // this will clone the custom fields data
+        customFieldsCloneFields( $entityID, $newId );
+    },
+    1,
+    2
+);
diff --git a/setup/adminMenus.php b/setup/adminMenus.php
new file mode 100644 (file)
index 0000000..81ad0d5
--- /dev/null
@@ -0,0 +1,52 @@
+<?php
+/**
+ * GLM Members Database Custom Fields
+ * GLM Members DB - Fields - Admin Menus
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package  glmMembersDatabase
+ * @author   Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @release  admin.php,v 1.0 2014/10/31 19:31:47 cscott Exp $
+ * @link     http://dev.gaslightmedia.com/
+ */
+
+/*
+ * Added menus or sub-menus examples
+ *
+ * // Add a main menu item
+ * add_menu_page(
+ *     'GLM Sample',                                       // Page Title
+ *     'GLM Sample',                                       // Menu Title
+ *     'glm-members-members',                              // Capability
+ *     'glm-members-admin-menu-glm-sample',                // Menu Slug
+ *     function() {$this->controller('sample');},          // Called function - typically controller() with the menu name
+ *     false,                                              // Icon URL
+ *     '92'                                                // Menu Position
+ * );
+ *
+ * // Add a sub-menu item
+ * add_submenu_page(
+ *     'glm-members-admin-menu-sample',                    // Parent slug
+ *     'Sample',                                           // Page title
+ *     'Sample',                                           // Menu Title
+ *     'glm_members_edit',                                 // Capability required
+ *     'glm-members-admin-menu-sample',                    // Menu slug
+ *     function() {$this->controller('sample');}
+ * );
+ *
+ * If creating a main menu item with add_menu_page(), please document
+ * that structure here.
+ *
+ * NOTE: The menu slug is the link for the page. It is also parsed by
+ * the controller and used to find the model to load. The
+ * "glm-members-admin-menu-" portion should not change, the last
+ * segment is the model directory name. By default the "index.php" file
+ * in that directory is executed. If the URL includes a "glm_action"
+ * parameter, then the model file called is in the same directory but
+ * is named the same as the "glm_action" parameter.
+ *
+ */
+
diff --git a/setup/adminTabs.php b/setup/adminTabs.php
new file mode 100644 (file)
index 0000000..d77793a
--- /dev/null
@@ -0,0 +1,79 @@
+<?php
+/**
+ * GLM Members Database Custom Fields
+ * GLM Members DB - Fields - Admin Tabs
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package  glmMembersDatabase
+ * @author   Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @release  admin.php,v 1.0 2014/10/31 19:31:47 cscott Exp $
+ * @link     http://dev.gaslightmedia.com/
+ */
+
+/*
+ * To add a new tab to an existing Member DB page use a block
+ * like this and replace the {} parameters.
+ *
+ * add_filter('glm-member-db-add-tab-for-{menu name}',
+ *     function($addOnTabs) {
+ *         $newTabs = array(
+ *             array(
+ *                 'text' => '{text for display on tab}',
+ *                 'menu' => '{menu name}',
+ *                 'action' => '{action to perform}'
+ *             )
+ *         );
+ *         $addOnTabs = array_merge($addOnTabs, $newTabs);
+ *         return $addOnTabs;
+ *     }
+ * );
+ *
+ */
+// If user can manage all members
+if (current_user_can('glm_members_members')) {
+    // add_filter('glm-member-db-add-tab-for-management',
+    //     function($addOnTabs) {
+    //         $newTabs = array(
+    //             array(
+    //                 'text' => 'Custom Fields',
+    //                 'menu' => 'fields',
+    //                 'action' => 'fields',
+    //                 'option' => 'list'
+    //             ),
+    //
+    //         );
+    //         $addOnTabs = array_merge($addOnTabs, $newTabs);
+    //         return $addOnTabs;
+    //     }
+    // );
+}
+if (current_user_can('glm_members_management')) {
+    add_filter('glm-member-db-add-tab-for-import',
+        function($addOnTabs) {
+            $newTabs = array(
+                array(
+                    'text'   => 'Custom Fields',
+                    'menu'   => 'import',
+                    'action' => 'fields',
+                )
+            );
+            $addOnTabs = array_merge($addOnTabs, $newTabs);
+            return $addOnTabs;
+        }
+    );
+    add_filter( 'glm-member-db-add-help-for-import',
+        function( $helpTabs ){
+            $helpTabs[] = array(
+                'id'      => 'glm-member-db-import-help-fields',
+                'title'   => __( 'Custom Fields' ),
+                'content' => '<p>' . __( 'Follow the Sample File provided in creating the file for custom field import.
+                Each record must have the following fields. <h3>Required Fields</h3><ul><li>member_id</li><li>member_name</li><li>member_login</li>
+                <li>member_passwd</li><li>member_email</li></ul>' )  . '</p>'
+            );
+            return $helpTabs;
+        }
+    );
+}
diff --git a/setup/commonHooks.php b/setup/commonHooks.php
new file mode 100644 (file)
index 0000000..76c044a
--- /dev/null
@@ -0,0 +1,29 @@
+<?php
+/**
+ * Gaslight Media Members Database
+ * GLM Members Misc Common Hooks and Filters
+ * Called by both Admin and Front controllers
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package  glmMembersDatabase
+ * @author   Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @release  commonHooks.php,v 1.0 2014/10/31 19:31:47 cscott Exp $
+ * @link     http://dev.gaslightmedia.com/
+ */
+
+/*
+ * Place Misc Hooks and Filters that should be available to both admin and front processes here. 
+ * If this file exists, it will be included by the main plugin script.
+ *
+ * Note that filter and hook callback functions must be included in-line as shown below...
+ *
+ *  add_filter( 'filter_title', function( $parameter ) {
+ *     // Function code
+ *  });
+ *
+ *  Also note that parameters will be in the context of the main admin controller constructor.
+  */
+
diff --git a/setup/databaseScripts/create_database_V1.0.0.sql b/setup/databaseScripts/create_database_V1.0.0.sql
new file mode 100644 (file)
index 0000000..cd0e4e7
--- /dev/null
@@ -0,0 +1,39 @@
+-- Gaslight Media Members Database - Fields Add-On
+-- File Created: 2017-03-27
+-- Database Version: 1.0.0
+-- Database Creation Script
+--
+-- This file is called to create a new set of tables for this
+-- add-on for the most recent database version for this add-on.
+--
+-- There should only be one such file in this directory
+--
+-- To permit each query below to be executed separately,
+-- all queries must be separated by a line with four dashes
+
+
+-- Field Setup Table
+CREATE TABLE {prefix}custom_fields (
+  id INT NOT NULL AUTO_INCREMENT,
+  field_name TINYTEXT NOT NULL DEFAULT '',      -- Field Name
+  field_type TINYTEXT NOT NULL DEFAULT '',      -- Field Type
+  field_order SMALLINT NOT NULL DEFAULT 0,      -- Order for Field
+  admin_search BOOLEAN NOT NULL DEFAULT '0',    -- If the field is added to member list filters.
+  required BOOLEAN NOT NULL DEFAULT '0',        -- If the field is required.
+  uid varchar(255) NOT NULL DEFAULT '',         -- id for the series of custom fields associated with an entity
+  PRIMARY KEY (id),
+  INDEX(field_name(20))
+);
+
+----
+
+-- Data Table
+CREATE TABLE {prefix}custom_field_data (
+  id INT NOT NULL AUTO_INCREMENT,
+  field_id INT NOT NULL DEFAULT 0,              -- Field Id             -- Member Info Id
+  field_data TEXT NOT NULL DEFAULT '',          -- Data for the field
+  entity_id INT NOT NULL DEFAULT 0,             -- id for the specific field associated with an entity
+  PRIMARY KEY (id),
+  INDEX(field_id),
+  INDEX(entity_id)
+);
diff --git a/setup/databaseScripts/dbVersions.php b/setup/databaseScripts/dbVersions.php
new file mode 100644 (file)
index 0000000..d6cf825
--- /dev/null
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Gaslight Media Members Database
+ * GLM Members Events DB Versions
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package  glmMembersDatabase
+ * @author   Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @release  dbVersions.php,v 1.0.0 2014/10/31 19:31:47 cscott Exp $
+ * @link     http://dev.gaslightmedia.com/
+ */
+
+$glmMembersCustomFieldsDbVersions = array(
+    '1.0.0' => array('version' => '1.0.0', 'tables' => 2, 'date' => '12/01/2017')
+);
+
diff --git a/setup/frontHooks.php b/setup/frontHooks.php
new file mode 100644 (file)
index 0000000..2fcd3e1
--- /dev/null
@@ -0,0 +1,199 @@
+<?php
+/**
+ * GLM Members Database Custom Fields
+ * Misc Hooks and Filters
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package  glmMembersDatabase
+ * @author   Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @release  frontHooks.php,v 1.0 2014/10/31 19:31:47 cscott Exp $
+ * @link     http://dev.gaslightmedia.com/
+ */
+
+/*
+ * Place Misc Hooks and Filters here. If this file exists, it will be included
+ * by the add-on main plugin script.
+ *
+ * Note that filter and hook callback functions must be included in-line as shown below...
+ *
+ *  add_filter( 'filter_title', function( $parameter ) {
+ *     // Function code
+ *  });
+ *
+ *  *** Also note that parameters will be in the context of the main front controller constructor. ***
+ */
+add_filter('glm-member-db-front-members-detail-sidebar', function($content, $id) {
+        $fieldData = do_shortcode('[glm-members-fields-detail member='.$id.', template="detail-sidemenu" order="title"]');
+        $content .= $fieldData;
+        return $content;
+    },
+    10,
+    2
+);
+add_filter('glm-member-db-front-members-list-info', function($content, $id) {
+        $fieldData = do_shortcode('[glm-members-fields-list member='.$id.', template="detail-sidemenu" order="title"]');
+        $content .= $fieldData;
+        return $content;
+    },
+    10,
+    2
+);
+
+add_filter( 'glm-member-db-front-search-query', function( $queryParts ) {
+    // Get all custom fields
+    $customFields = $this->wpdb->get_results(
+        "SELECT *
+           FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX .  "custom_fields",
+        ARRAY_A
+    );
+    if ( isset( $customFields ) && count( $customFields ) > 0 ) {
+        foreach ( $customFields as $key => $field ) {
+            switch ( $field['field_type'] ) {
+            case 'text':
+            case 'textarea':
+                $field_name = preg_replace( '/[ -]/', '_', strtolower( $field['field_name'] ) );
+                if ( isset( $_REQUEST[$field_name] ) && filter_var( $_REQUEST[$field_name], FILTER_SANITIZE_STRING ) ) {
+                    $textSearch = $this->wpdb->esc_like( $_REQUEST[$field_name] );
+                    $queryParts[] = " T.id IN (
+                        SELECT entity_id
+                          FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_field_data
+                         WHERE field_data like '%" . $textSearch . "%'
+                           AND field_id = (SELECT id
+                                             FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_fields
+                                            WHERE field_name = '" . esc_sql( $field['field_name'] ) . "')
+                    ) ";
+                }
+
+                break;
+            case 'checkbox':
+                // convert name to lower case and replace spaces with _
+                $field_name = preg_replace( '/[ -]/', '_', strtolower( $field['field_name'] ) );
+                if ( isset( $_REQUEST[$field_name] ) && filter_var( $_REQUEST[$field_name], FILTER_VALIDATE_BOOLEAN ) ) {
+                    $queryParts[] = " T.id IN (
+                        SELECT entity_id
+                          FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_field_data
+                         WHERE field_data = 'Yes'
+                           AND field_id = (SELECT id
+                                             FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_fields
+                                            WHERE field_name = '" . esc_sql( $field['field_name'] ) . "')
+                    ) ";
+                }
+                break;
+            }
+        }
+    }
+    return $queryParts;
+});
+add_filter( 'glm-member-db-front-search-request', function( $actionData ) {
+    global $wpdb;
+    // Get all custom fields
+    $customFields = $wpdb->get_results(
+        "SELECT *
+           FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX .  "custom_fields",
+        ARRAY_A
+    );
+    if ( isset( $customFields ) && count( $customFields ) > 0 ) {
+        foreach ( $customFields as $key => $field ) {
+            // convert name to lower case and replace spaces with _
+            $field_name = preg_replace( '/[ -]/', '_', strtolower( $field['field_name'] ) );
+            if ( isset( $actionData['request'][$field_name] ) && $actionData['request'][$field_name]) {
+                $_REQUEST[$field_name] = $actionData['request'][$field_name];
+            }
+        }
+    }
+    return $actionData;
+}, 10, 1);
+add_filter( 'glm-member-db-customfields-front-list-query-params', function( $query ){
+    $queryParams = array();
+    // Get all custom fields
+    $customFields = $this->wpdb->get_results(
+        "SELECT field_name,field_type
+           FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX .  "custom_fields",
+        ARRAY_A
+    );
+    foreach ( $customFields as $field ) {
+        switch ( $field['field_type'] ) {
+        case 'checkbox':
+            $fieldName = preg_replace( '/[ -]/', '_', strtolower( $field['field_name'] ) );
+            if ( isset( $_REQUEST[$fieldName] ) ) {
+                $queryParams[] = "$fieldName={$_REQUEST[$fieldName]}";
+            }
+            break;
+        }
+    }
+    return ( !empty( $queryParams ) ? $query . '&'.implode( '&', $queryParams): $query);
+},10, 1);
+
+add_filter('get_glm_custom_fields', function($uid,$entity_id) {
+    global $wpdb;
+    $fieldsTable   = GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_fields";
+    $dataTable     = GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_field_data";
+
+    $query = "SELECT $dataTable.field_data, $fieldsTable.field_type, $fieldsTable.field_name "
+    . "FROM $dataTable "
+    . "LEFT JOIN $fieldsTable "
+    . "ON $dataTable.field_id = $fieldsTable.id WHERE $dataTable.entity_id = $entity_id;";
+
+    $result = $this->wpdb->get_results( $query, ARRAY_A );
+    foreach($result as $key=>$value){
+        if ($result[$key]['field_type'] == 'textarea') {
+            $result[$key]['field_data'] = wpautop($result[$key]['field_data']);
+        }
+    }
+
+//    echo "<pre>AA" . print_r($result) . "ZZ";
+    return $result;
+    },
+    10,
+    2
+);
+add_filter('glm_custom_fields', function($attribute, $id = 0) {
+
+    global $wpdb;
+    $query = "SELECT D.field_data, F.field_type FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_field_data D, ".GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX."custom_fields F "
+        . "WHERE D.entity_id = $id "
+        . "AND D.field_id IN (SELECT id FROM ".GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX."custom_fields WHERE field_name LIKE '$attribute' ) "
+        . "AND F.field_name LIKE '$attribute'";
+
+    $result = $this->wpdb->get_row( $query, ARRAY_A );
+    if ($result['field_type'] == 'textarea') {
+        $result['field_data'] = wpautop($result['field_data']);
+    }
+//    echo "<pre>AA" . print_r($result) . "ZZ";
+    return $result['field_data'];
+    },
+    10,
+    2
+);
+add_filter('glm_custom_fields_member_types', function() {
+
+    $query = "SELECT name FROM " . GLM_MEMBERS_PLUGIN_DB_PREFIX . "member_type";
+    $result = $this->wpdb->get_results( $query, ARRAY_A );
+    return $result;
+    },
+    10,
+    2
+);
+
+/**
+ * Filter: glm-get-custom-field-count
+ * Usage: apply_filters( 'glm-get-custom-field-count','reviewed','Yes' )
+ */
+add_filter( 'glm-get-custom-field-count', function( $field_name, $field_value = '' ){
+    if ( $field_name ) {
+        global $wpdb;
+        $sql = "SELECT count(field_data) FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_field_data WHERE field_data LIKE '$field_value'"
+        . " AND field_id IN (SELECT id FROM " . GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_DB_PREFIX . "custom_fields WHERE field_name LIKE '$field_name')";
+        $count = $wpdb->get_var(
+            $sql
+        );
+        return $count;
+    }
+    return false;
+},
+10,
+2
+);
diff --git a/setup/hooksHelp.html b/setup/hooksHelp.html
new file mode 100644 (file)
index 0000000..41937f5
--- /dev/null
@@ -0,0 +1,102 @@
+<!-- Hooks Help for {descrName} with Example
+
+        <tr><th colspan="3" class="glm-notice"><p>Sample Add-On</p></th></tr>
+        
+        <tr><th colspan="3">User Permission Hooks</td></tr>
+        
+        <tr>
+            <td>some_hook_name</td>
+            <td>FILTER or ACTION</td>
+            <td></td>
+            <td>
+                What this hook does.
+            </td>
+        </tr>
+
+-->
+
+<tr><th colspan="3" class="glm-notice"><p>Custom Fields Add-On</p></th></tr>
+<tr><th colspan="3">Menu/Tab Hooks</th></tr>
+<tr>
+    <td>glm-members-customfields-active</td>
+    <td>FILTER</td>
+    <td></td>
+    <td>
+        Returns TRUE if Custom Fields Add-On is installed and active.
+    </td>
+</tr>
+<tr>
+    <td>glm-member-db-customfields-nav</td>
+    <td>FILTER</td>
+    <td>$content, $tableName</td>
+    <td>
+        Displays a tab to use for customer fields and will select the $tableName for display
+        when clicked. The $content parameter should be an empty string unless there is a 
+        desire to put additional HTML code before the tab. The return will be HTML to
+        display a functional tab.
+        <p>
+            Note that such tabs will require the correct scripting to make them work as
+            is used for sub-tabs in our add-ons.
+        </p>
+    </td>
+</tr>
+<tr><th colspan="3">Fields Add/Delete/Edit</th></tr>
+<tr>
+    <td>glm-members-customfields-edit</td>
+    <td>FILTER</td>
+    <td>$content, $uid</td>
+    <td>
+        Return HTML for field add/delete/edit for the specified form ($uid).
+        <p>
+            The $content parameter should be an empty string when this filter is applied. 
+            Any HTML returned from this filter will be appended to the supplied text.
+            If desired, HTML code may be provided to be included at the beginning of the 
+            resulting string that's returned.
+        </p>
+        <p>
+            The $uid parameter is a text string that is a unique identifier for the the form that is to
+            be edited. This should include the slug of the plugin that is calling
+            for this form and a name or other identifier for the specific form. This might
+            typically be specified in the form of a slug with hyphens between the words.
+        </p> 
+    </td>
+</tr>
+<tr><th colspan="3">Fields Use</th></tr>
+<tr>
+    <td>glm-members-custom-fields-form</td>
+    <td>FILTER</td>
+    <td>$content, $uid, $id, $cfData</td>
+    <td>
+        Displays a specific custom fields from to request user input.
+        <p>
+            The $content parameter should be an empty string when this filter is applied. 
+            Any HTML returned from this filter will be appended to the supplied text.
+            If desired, HTML code may be provided to be included at the beginning of the 
+            resulting string that's returned.
+        </p>
+        <p>
+            The $uid parameter is a text string that is a unique identifier for the the form that is to
+            be edited. This should include the slug of the plugin that is calling
+            for this form and a name or other identifier for the specific form. This might
+            typically be specified in the form of a slug with hyphens between the words.
+        </p>
+        <p>
+            The $id parameter is an INTEGER that is unique to this specific use of the form 
+            specified by $uid. For example, if $uid points to a form with added fields to
+            be used along with the usual fields in a contact information form, the $id 
+            parameter might be the 'id' field from the record containing the contact that's
+            being edited. Any results submitted will be stored along with this $id. If
+            this $uid and $id pair are used anywhere else, data submitted there will replace
+            the other uses of the same form and id. 
+        </p> 
+        <p>
+            The $cfData field is an array that contains field data to use as the default
+            when the form is displayed. This will usually come from a previous submission 
+            of the form that failed due to a missing required field or other failure. This
+            permit re-displaying the form again with the data in it that the user attempted
+            to subit. The $cfData may also have information that will be used by the custom
+            fields add-on to format failed fields differently to show which need attention.
+            If This is an initial display of the form, simply provide FALSE. ??????
+        </p>
+    </td>
+</tr>
diff --git a/setup/permissions.php b/setup/permissions.php
new file mode 100644 (file)
index 0000000..68554ec
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+/**
+ * {descrName
+ * Permissions
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package  glmMembersDatabase
+ * @author   Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @release  permissions.php,v 1.0 2014/10/31 19:31:47 cscott Exp $
+ * @link     http://dev.gaslightmedia.com/
+ */
+
+
+/*
+ * Below are permission checks for various specific things in this add-on and
+ * elsewhere in the Member DB main plugin and add-ons.
+ *
+ * Each location where a permission might be required has an apply_filters()
+ * hook with a tag name that includes the plugin or add-on name, the menu,
+ * the action, and a name for the specific thing that needs permissions.
+ *
+ * This can be included in code or in a Smarty template used in these plugins.
+ * For example, to check permissions for the main Members menu and it's "index"
+ * action to see if a member search is permitted, the template includes the
+ * following code...
+ *
+ * {if $membersList && apply_filters('glm_members_permit_admin_members_index_member_search', true)}
+ *      --- some template output ---
+ * {/if}
+ *
+ * In the case above, it's also checking to see if the members list even exists
+ * before checking the permissions. The default value of "true" in the hook ensures
+ * that the permission is granted if nothing has linked into the hook to say otherwise.
+ *
+ * Note that each add_filter() below first checks if the permission has already
+ * been retracted by prior hook. This requires all that are attached to the hook
+ * to permit the action.
+ *
+ * Of course any of these may test more than one capability if that's desired.
+ *
+ * Since we have capabilities that only exist if a particular add-on (such as Contacts)
+ * has been loaded and activated, it can be helpful to be able to test for a capability
+ * for the current user and permit some action if that capability doesn't exist. The
+ * main plugin therefore provides the following globally accessible function that will
+ * return true if the capability doesn't exist, otherwise it respects the capability.
+ *
+ *  glmMembersUserCan('glm_members_edit_any_member', $permit);
+ *
+ *  $permit is a boolean set before this function call for passing on permissions.
+*/
diff --git a/setup/rolesAndCapabilities.php b/setup/rolesAndCapabilities.php
new file mode 100644 (file)
index 0000000..0929d55
--- /dev/null
@@ -0,0 +1,19 @@
+<?php
+/**
+ * GLM Members Database Custom Fields
+ * Roles & Capabilities
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package  glmMembersCustomFields
+ * @author   Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @release  rolesAndPermissions.php,v 1.0 2014/10/31 19:31:47 cscott Exp $
+ * @link     http://dev.gaslightmedia.com/
+ */
+
+/**
+ * NOTE: This file is only included in the activate.php process.
+ *       It is not regularly used during operation.
+ */
diff --git a/setup/shortcodes.php b/setup/shortcodes.php
new file mode 100644 (file)
index 0000000..9e6a1e6
--- /dev/null
@@ -0,0 +1,123 @@
+<?php
+/**
+ * GLM Members Database Custom Fields
+ * Short Codes
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package  glmMembersCustomFields
+ * @author   Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @release  shortcodes.php,v 1.0 2014/10/31 19:31:47 cscott Exp $
+ * @link     http://dev.gaslightmedia.com/
+ */
+
+/*
+ * Array of short-code
+ *
+ * This array lists all of the short-codes available from the main
+ * member plugin and all add-ons that provide short-code features.
+ *
+ * This array is merged with the data from any registered add-ons
+ * providing short-code features. The plugin providing the short-code
+ * is designated in the 'plugin' elemeent.
+ *
+ * A shortcode is unique to a particular plugin. To provide additional
+ * data and features to a short-code, an add-on should use filters
+ * provided by the short-code to insert data into the template array,
+ * to insert additional format into the template, or to insert
+ * text directly into the completed template output.
+ *
+ * The "attributes" array is a list of available attributes for this
+ * shortcode and their default values. If a database table is provided,
+ * then the value for each attribute is a table column where we get
+ * the default value. If no table is provided, then the value for
+ * each attribute is the actual default value for that attribute.
+ * In the case that the data is taken from the database table, the
+ * "id" for the table entry where the data is stored is assumed to
+ * be 1.
+ *
+ * Note that if the value for a particular attribute is false, then
+ * it is not read from the database even if the table is specified
+ * but might be supplied at run-time as an attribute in the short-code.
+ * All attributes that might be specified in the shortcode must be
+ * listed in the 'attributes' array below. If an attribute is not
+ * specified here, it can't be read from the short-code.
+ *
+ * The following is an explanation of this array.
+ *
+ * array(
+ *      '{shortcode-slug} => array(
+ *          'plugin' => '{plugin (add-on) slug}',       // Identifies which plugin is providing the short-code
+ *          'menu' => '{menu name}',                    // Menu name in this context is simply where to find the action
+ *          'action' => '{shortcode action name},       // Action used to execute this shortcode
+ *          'table' => '{table prefix}{table name}',    // Database table where default attribute values are stored
+ *          'attributes' => array(                      // An array of all shortcode attributes (options)
+ *              '{attr name}' => '{field name}',        // Available attribute names and the database field names with the default value
+ *              ....
+ *          ),
+ *      ... additional short-codes
+ * )
+ *
+ * Shortcode descriptions sample
+ *
+ *      <tr>
+ *           <th>[glm-members-sample-shortcode]</th>
+ *           <td>&nbsp;</td>
+ *           <td width="50%">
+ *               Displays something related to this add-on.
+ *           </td>
+ *       </tr>
+ *       <tr>
+ *           <td>&nbsp;</td>
+ *           <th>type="{types}"</th>
+ *           <td>
+ *               The "type" attribute is used to select the type of data to be displayed.
+ *               Below is a list of available list types.
+ *               <p>
+ *                   <table width="100%">
+ *                       <tr><th colspan=3">List Types</th></tr>
+ *                       <tr><td>one</td><td>Type One</td></tr>
+ *                       <tr><td>two</td><td>Type Two</td></tr>
+ *                   </table>
+ *               </p>
+ *           </td>
+ *       </tr>
+ */
+
+$glmMembersCustomFieldsShortcodes = array(
+    'glm-members-fields-detail' => array(
+        'plugin'     => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG,
+        'menu'       => 'fields',
+        'action'     => 'detail',
+        'table'      => false,
+        'attributes' => array(
+            'type'     => 'all',
+            'order'    => 'title',
+            'member'   => false,
+            'template' => false,
+            'limit'    => null,
+            'featured' => null,
+            'current'  => null,
+        )
+    ),
+    'glm-members-fields-list' => array(
+        'plugin'     => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG,
+        'menu'       => 'fields',
+        'action'     => 'list',
+        'table'      => false,
+        'attributes' => array(
+            'type'     => 'all',
+            'order'    => 'title',
+            'member'   => false,
+            'template' => false,
+            'limit'    => null,
+            'featured' => null,
+            'current'  => null,
+        )
+    ),
+);
+
+$glmMembersCustomFieldsShortcodesDescription = '';
+
diff --git a/setup/validActions.php b/setup/validActions.php
new file mode 100644 (file)
index 0000000..fac0518
--- /dev/null
@@ -0,0 +1,81 @@
+<?php
+/**
+ * GLM Members Database Custom Fields
+ * Valid Actions
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package  glmMembersCustomFields
+ * @author   Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @release  admin.php,v 1.0 2014/10/31 19:31:47 cscott Exp $
+ * @link     http://dev.gaslightmedia.com/
+ */
+
+/*
+ * Array of valid menu items and actions.
+ *
+ * The higher level elements are valid menu items. These correlate to
+ * actual menu or sub menu items that are hooks back to this controller
+ * class.
+ *
+ * The lower level items below each menu item are actions that may be specified
+ * by a "glmMembersAction" form field.
+ *
+ * The string after the action is the slug of the plugin where the model/view
+ * is to perform that action.
+ *
+ * This array is integrated into the valid actions array in the main GLM Member
+ * DB plugin when this plugin registers itself.
+ *
+ * EXAMPLE
+ *
+ * $glmMembersCustomFieldsAddOnValidActions = array(
+ *     'adminActions' => array(
+ *         'members' => array(
+ *             'sample' => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG,
+ *         ),
+ *         'sample' => array(
+ *             'index' => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG,
+ *             'more' => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG,
+ *         ),
+ *         'info' => array(
+ *             'index' => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG
+ *         )
+ *     ),
+ *     'frontActions' => array(
+ *         'sample' => array(
+ *             'list' => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG,
+ *             'detail' => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG
+ *         )
+ *     )
+ * );
+ *
+ *
+ *
+ *
+ */
+
+$glmMembersCustomFieldsAddOnValidActions = array(
+    'adminActions' => array(
+        'ajax' => array(
+            'filterSearch' => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG,
+        ),
+        'entity' => array(
+            'fields' => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG,
+        ),
+        'management' => array(
+            'fields' => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG,
+        ),
+        'import' => array(
+            'fields' => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG,
+        ),
+    ),
+    'frontActions' => array(
+        'fields' => array(
+            'list' => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG,
+            'detail' => GLM_MEMBERS_CUSTOMFIELDS_PLUGIN_SLUG,
+        ),
+    )
+);
diff --git a/uninstall.php b/uninstall.php
new file mode 100644 (file)
index 0000000..623bb56
--- /dev/null
@@ -0,0 +1,27 @@
+<?php
+
+die('uninstall not configured - See plugin uninstall.php script!');
+
+/**
+ * GLM Members Database Custom Fields
+ * Uninstall Plugin
+ *
+ * PHP version 5.5
+ *
+ * @category glmWordPressPlugin
+ * @package  glmMembersCustomFields
+ * @author   Chuck Scott <cscott@gaslightmedia.com>
+ * @license  http://www.gaslightmedia.com Gaslightmedia
+ * @release  admin.php,v 1.0 2014/10/31 19:31:47 cscott Exp $
+ * @link     http://dev.gaslightmedia.com/
+ */
+
+// Check that we're being called by WordPress.
+if (!defined('ABSPATH')) {
+    die("Please do not call this code directly!");
+}
+
+//if uninstall not called from WordPress exit
+if (!defined('WP_UNINSTALL_PLUGIN')) {
+    die("Sorry, uninstall must be called by WordPress!");
+}
diff --git a/views/admin/entity/fields.html b/views/admin/entity/fields.html
new file mode 100644 (file)
index 0000000..2c69862
--- /dev/null
@@ -0,0 +1,38 @@
+<div id="glm-members-custom-fields-{$uid}" class="glm-row glm-custom-field-group glm-admin-custom-fields">
+    {foreach $customFields as $field}
+        <div class="glm-small-12 glm-large-2 glm-columns glm-custom-field-label {if $field.required.value == 1} glm-required {/if}">{$field.field_name}</div>
+        <div class="glm-small-12 glm-large-9 glm-columns glm-custom-field">
+            <input type="hidden" name="custom-required" value="{$field.required.value}">
+            
+           {$fail = ''}
+           {if is_array($customFieldsData)}
+            {if array_key_exists('fieldFail', $customFieldsData)}
+                 {if array_key_exists($field.id,$customFieldsData['fieldFail'])}
+                     {$fail = 'glm-form-bad-input'}
+                  {/if}
+            {/if}
+           {/if}
+           <div class="glm-input-wrapper {$fail}">
+                {if $field.field_type.name == 'text'}
+
+                    <input class="glm-input glm-form-text-input-medium" type="text" name="{$prefix}[{$field.id}]" value="{if isset($customFieldsData[$field.id])}{$customFieldsData[$field.id]|escape}{/if}" {if $field.required.value == 1} required{/if}>
+                {elseif $field.field_type.name == 'textarea'}
+                   {php}
+                        wp_editor('{if isset($customFieldsData[$field.id])}{$customFieldsData[$field.id]|escape:quotes}{/if}', 'custom-field-{$field.id}', array(
+                            'media_buttons' => false,
+                            // 'quicktags' => false,
+                            // 'wpautop' => false,  NOTE: Dont's use. Problem when numerous spaces before text.
+                            'textarea_name' => '{$prefix}[{$field.id}]',
+                            'editor_height' => 200,     // Height in px, overrides editor_rows
+                            // 'textarea_rows' => 8,
+                            {if $field.required.value == 1}'editor_class' => 'glm-required' {/if}
+                        ));
+                    {/php}
+                {elseif $field.field_type.name == 'checkbox'}
+                    <input type="hidden" name="{$prefix}[{$field.id}]" value="No" {if !isset($customFieldsData[$field.id]) || $customFieldsData[$field.id] == 'No'}checked{/if}>
+                    <input type="checkbox" name="{$prefix}[{$field.id}]" value="Yes" {if isset($customFieldsData[$field.id]) && $customFieldsData[$field.id] == 'Yes'}checked{/if} {if $field.required.value == 1} required{/if}>
+                {/if}
+           </div>
+        </div>
+    {/foreach}
+</div>
diff --git a/views/admin/import/fields.html b/views/admin/import/fields.html
new file mode 100644 (file)
index 0000000..0b17672
--- /dev/null
@@ -0,0 +1,48 @@
+{include file='admin/import/header.html'}
+
+    <h2>Social Data Import Step 1: Upload file</h2>
+
+    <form action="{$thisUrl}?page={$thisPage}" method="post" enctype="multipart/form-data">
+        <input type="hidden" name="glm_action" value="fields" />
+        <input type="hidden" name="option" value="fieldsValidate" />
+
+        <table class="glm-admin-table" border="0" cellspacing="5" cellpadding="10">
+            <tr>
+                <th>File Type</th>
+                <th>New File</th>
+                <th>Sample File</th>
+                <th>Current File</th>
+                <th>Updated</th>
+            </tr>
+            {$count = 0}
+            {foreach $fileData as $fileHeader => $file}
+            <tr{if $count%2 == 0} class="alternate"{/if}>
+                <td class="glm-import-td">
+                    {$fileHeader}
+                </td>
+                <td class="glm-import-td">
+                    <input type="file" name="{$file.field}">
+                </td>
+                <td class="glm-import-td">
+                    <a href="{$sampleFileUrl}{$file.name}">Sample {$fileHeader} File</a>
+                </td>
+                <td class="glm-import-td">
+                    {if $file.exists}
+                        {$fileHeader} File
+                    {/if}
+                </td>
+                <td class="glm-import-td">
+                    {if $file.exists}
+                        {$file.mtime|date_format:"%D %I:%M %p"}
+                    {/if}
+                </td>
+            </tr>
+            {$count = $count + 1}
+            {/foreach}
+        </table>
+
+        <input type="submit" value="Continue" class="button button-primary submit-import">
+
+    </form>
+
+{include file='admin/footer.html'}
diff --git a/views/admin/import/fieldsProcess.html b/views/admin/import/fieldsProcess.html
new file mode 100644 (file)
index 0000000..dab58af
--- /dev/null
@@ -0,0 +1,16 @@
+{include file='admin/import/header.html'}
+
+    <h2>Data Import Step 3: Process Fields File</h2>
+    <table class="glm-admin-table">
+        <tr>
+            <th>Total Records</th>
+            <td>{$totalFields}</td>
+        </tr>
+        <tr>
+            <th>Processed Records</th>
+            <td>{$numberProcessed}</td>
+        </tr>
+
+    </table>
+
+{include file='admin/footer.html'}
diff --git a/views/admin/import/fieldsValidate.html b/views/admin/import/fieldsValidate.html
new file mode 100644 (file)
index 0000000..9ff514d
--- /dev/null
@@ -0,0 +1,40 @@
+{include file='admin/import/header.html'}
+
+    <h2>Secial Import Step 2: Validate Fields file</h2>
+
+    <table class="glm-admin-table">
+        {foreach $fileData as $fileHeader => $file}
+        <tr>
+            <td>
+                {if $file.exists}
+                    {$fileHeader} File
+                {/if}
+            </td>
+            <td>
+                {if $file.isValid}
+                    Is Valid
+                {else}
+                    Not Valid
+                {/if}
+            </td>
+        </tr>
+        {/foreach}
+
+        {if $readyToProcess}
+        <tr>
+            <td colspan="2">
+                <a href="{$thisUrl}?page={$thisPage}&glm_action=fields&option=fieldsProcess" class="button">Process Files</a>
+            </td>
+        </tr>
+        {else}
+        <tr>
+            <td colspan="2">
+                <p>One or more of your files are not the correct csv format. Please go back and try again.</p>
+                <a href="{$thisUrl}?page={$thisPage}&glm_action=fields" class="button">Go Back</a>
+            </td>
+        </tr>
+        {/if}
+
+    </table>
+
+{include file='admin/footer.html'}
diff --git a/views/admin/management/fields.html b/views/admin/management/fields.html
new file mode 100644 (file)
index 0000000..fdd0d80
--- /dev/null
@@ -0,0 +1,259 @@
+<!-- Add Custom Field Button and Dialog Box -->
+<div id="newFieldButton" class="button button-primary glm-right">Add a Custom Field</div>
+<div id="newFieldDialog" class="glm-dialog-box" title="Enter a New Custom Field">
+    <form action="{$thisUrl}?page={$thisPage}&glm_action={$glm_action}&option=customfields" method="post" enctype="multipart/form-data">
+        <input type="hidden" name="glm_action" value="{$glm_action}">
+        <input type="hidden" name="option" value="customfields">
+        <input type="hidden" name="option2" value="addNew">
+
+        <table class="glm-admin-table">
+            <tr>
+                <th class="glm-required">Field Name:</th>
+                <td>
+                    <input type="text" name="field_name" class="glm-form-text-input">
+                </td>
+            </tr>
+            <tr>
+                <th class="glm-required">Field Type:</th>
+                <td>
+                    <select name="field_type">
+                        {foreach $field_types as $val => $label}
+                        <option value="{$val}">{$label}</option>
+                        {/foreach}
+                    </select>
+                </td>
+            </tr>
+            <!-- The UID check below is just a TEMPORARY measure until we have search filters implemented on plugins beyond glm-member-db -->
+            {if $uid == 'glm-member-db'}
+            <tr>
+                <th>Admin Searchable</th>
+                <td>
+                    <input type="hidden" name="admin_search" value="0" />
+                    <input type="checkbox" name="admin_search" value="1" />
+                    (text or checkbox only)
+                </td>
+            </tr>
+            {/if}
+            <tr>
+            <th>Required?</th>
+                <td>
+                    <input type="hidden" name="required" value="0" />
+                    <input type="checkbox" name="required" value="1" />
+                </td>
+            </tr>
+            <input type="hidden" name="uid" value="{$uid}">
+        </table>
+        <p><span class="glm-required">*</span> Required</p>
+        <a id="newFieldCancel" class="button button-primary glm-right">Cancel</a>
+        <input type="submit" value="Add new Custom Field" class="button button-primary">
+    </form>
+</div>
+
+<!-- Delete Field Button and Dialog Box -->
+<div id="deleteFieldDialog" class="glm-dialog-box" title="Delete Field">
+    <center>
+        <p>Are you sure you want to delete this field?</p>
+        <p><div id="deleteFieldConfirm" class="button button-primary">Yes, delete this field</div></p>
+        <p><div id="deleteFieldCancel" class="button button-primary">Cancel</div></p>
+    </center>
+</div>
+
+<!-- Edit Field Dialog Box -->
+<div id="editFieldDialog" class="glm-dialog-box" title="Edit this Field">
+    <form action="{$thisUrl}?page={$thisPage}&glm_action={$glm_action}&option=customfields" method="post" enctype="multipart/form-data">
+        <input type="hidden" name="glm_action" value="{$glm_action}">
+        <input type="hidden" name="option" value="customfields">
+        <input type="hidden" name="option2" value="update">
+        <input id="editFieldID" type="hidden" name="id" value="">
+        <table class="glm-admin-table">
+            <tr>
+                <th class="glm-required">Field Name:</th>
+                <td>
+                    <input id="editFieldName" type="text" name="field_name" class="glm-form-text-input">
+                </td>
+            </tr>
+            <tr>
+                <th class="glm-required">Field Type:</th>
+                <td>
+                    <select id="editFieldType" name="field_type">
+                        {foreach $field_types as $val => $label}
+                        <option value="{$val}">{$label}</option>
+                        {/foreach}
+                    </select>
+                </td>
+            </tr>
+            <!-- The UID check below is just a TEMPORARY measure until we have search filters implemented on plugins beyond glm-member-db -->
+            {if $uid == 'glm-member-db'}
+            <tr>
+                <th>Admin Searchable</th>
+                <td>
+                    <input type="hidden" name="admin_search" value="0" />
+                    <input type="checkbox" id="editAdminSearch" name="admin_search" value="1" />
+                    (text or checkbox only)
+                </td>
+            </tr>
+            {/if}
+            <tr>
+                <th>Required?</th>
+                <td>
+                    <input type="hidden" name="required" value="0" />
+                    <input type="checkbox" id="editRequired" name="required" value="1" />
+                </td>
+            </tr>
+            <input type="hidden" name="uid" value="{$uid}">
+        </table>
+        <p><span class="glm-required">*</span> Required</p>
+        <a id="editFieldCancel" class="button button-primary glm-right">Cancel</a>
+        <input type="submit" value="Update this Field">
+    </form>
+</div>
+<table id="glm-table-settings" class="glm-admin-table glm-settings-table{if $option2!='settings'} glm-hidden{/if}">
+    <tr>
+        <td colspan="2">
+            {if $settingsUpdated}<h2 class="glm-notice glm-flash-updated glm-right">Settings Updated</h2>{/if}
+            {if $settingsUpdateError}<span class="glm-error glm-flash-updated glm-right">Settings Update Error</span>{/if}
+            <h2>Custom Fields</h2>
+        </td>
+    </tr>
+</table>
+<table id="glm-table-settings" class="glm-admin-table glm-settings-table">
+    <thead>
+        <tr>
+            <th>ID</th>
+            <th>Field</th>
+            <th>Type</th>
+            <th>UID/Entity</th>
+            <th>Required</th>
+            <!-- The UID check below is just a TEMPORARY measure until we have search filters implemented on plugins beyond glm-member-db -->
+            {if $uid == 'glm-member-db'}<th>Admin Searchable</th>{/if}
+            <th>&nbsp;</th>
+        </tr>
+    </thead>
+    <tbody>
+        {if $haveCustomFields}
+        {assign var="i" value="0"}
+        {foreach $custom_fields as $t}
+        {if $i++ is odd by 1}
+        <tr>
+            {else}
+            <tr class="alternate">
+                {/if}
+                <td>{$t.id}</td>
+                <td>
+                    <div>
+                        <a class="editField" data-fieldID="{$t.id}" data-fieldType="{$t.field_type.name|escape:'html'}" data-adminSearch="{$t.admin_search.value}" data-required="{$t.required.value}">{$t.field_name}</a>
+                    </div>
+                </td>
+                <td id="editFieldType_{$t.id}">
+                    {$t.field_type.name}
+                </td>
+                <td>
+                    {$t.uid}
+                </td>
+                <td>
+                    {$t.required.name}
+                </td>
+                <td>
+                    {$t.admin_search.name}
+                </td>
+                <td>
+                    <div class="deleteFieldButton button button-secondary glm-button-small glm-right" data-fieldID="{$t.id}">Delete</div>
+                </td>
+            </tr>
+            {/foreach}
+            {else}
+            <tr class="alternate"><td colspan="2">(no custom fields listed)</td></tr>
+            {/if}
+    </tbody>
+</table>
+<!-- Tests -->
+
+<script type="text/javascript">
+jQuery(document).ready(function($) {
+
+    /*
+     * Edit area tabs
+     */
+    $('.glm-settings-tab').click( function() {
+
+        // Clear table highlights and hide all tables
+        $('.glm-settings-tab').removeClass('nav-tab-active');
+        $('.glm-settings-table').addClass('glm-hidden');
+
+        // Highlight selected tab
+        $(this).addClass('nav-tab-active');
+
+        // Show selected table
+        var table = $(this).attr('data-show-table');
+        $('#' + table).removeClass('glm-hidden');
+
+    });
+    $("#newFieldDialog").dialog({
+        autoOpen: false,
+        minWidth: 400,
+        dialogClass: "glm-dialog-no-close"
+    });
+    $("#editFieldDialog").dialog({
+        autoOpen: false,
+        minWidth: 400,
+        dialogClass: "glm-dialog-no-close"
+    });
+    $("#deleteFieldDialog").dialog({
+        autoOpen: false,
+        minWidth: 400,
+        dialogClass: "glm-dialog-no-close"
+    });
+    $('#newFieldButton').click( function() {
+        $("#newFieldDialog").dialog("open");
+    });
+    $('.editField').click( function() {
+        var fieldID     = $(this).attr('data-fieldID');
+        var fieldName   = $(this).text();
+        var fieldType   = $(this).attr('data-fieldType');
+        var adminSearch = $(this).attr('data-adminSearch');
+        var required    = $(this).attr('data-required');
+        
+        $('#editFieldID').val(fieldID);
+        $('#editFieldName').val(fieldName.trim());
+        $('#editFieldType').val(fieldType);
+        
+        if (adminSearch === '1') {
+            console.log('setting the checked to true');
+            $('#editAdminSearch').prop('checked', true);
+        } else {
+            console.log('setting the checked to false');
+            $('#editAdminSearch').prop('checked', false);
+        }
+        // check required fields
+        if (required === '1') {
+            $('#editRequired').prop('checked', true);
+        } else {
+            console.log('setting the checked to false');
+            $('#editRequired').prop('checked', false);
+        }
+        $("#editFieldDialog").dialog("open");
+    });
+    $('#editFieldCancel').click( function() {
+        $("#editFieldDialog").dialog("close");
+    });
+    $('#newFieldCancel').click( function() {
+        $("#newFieldDialog").dialog("close");
+    });
+
+    var id = false;
+    $('.deleteFieldButton').click( function() {
+        id = $(this).attr('data-fieldID');
+        $("#deleteFieldDialog").dialog("open");
+    });
+    $('#deleteFieldConfirm').click( function() {
+        $("#deleteFieldDialog").dialog("close");
+        window.location.href = "{$thisUrl}?page={$thisPage}&glm_action={$glm_action}&option=customfields&option2=delete&id=" + id;
+    });
+    $('#deleteFieldCancel').click( function() {
+        $("#deleteFieldDialog").dialog("close");
+    });
+
+    // Flash certain elements for a short time after display
+    $(".glm-flash-updated").fadeOut(500).fadeIn(500).fadeOut(500).fadeIn(500).fadeOut(500).fadeIn(500).fadeOut(500).fadeIn(500).fadeOut(500).fadeIn(500).fadeOut(500);
+});
+</script>
diff --git a/views/admin/readme.txt b/views/admin/readme.txt
new file mode 100644 (file)
index 0000000..5a9d7ea
--- /dev/null
@@ -0,0 +1,5 @@
+The admin controller uses views (templates) under this directory to generate final output.
+
+Typically you should add a directory here that matches the page where the view is used.
+
+Under that directory place the view (template) for the various actions.
\ No newline at end of file
diff --git a/views/front/fields/detail.html b/views/front/fields/detail.html
new file mode 100644 (file)
index 0000000..25b417d
--- /dev/null
@@ -0,0 +1,19 @@
+<h5>Specifications</h5>
+{foreach $field_values as $key=>$value}
+    {if $value.slash === true }
+        <div class="glm-row field-container slash-price">
+            <div class="glm-small-6 glm-medium-12 glm-large-6 glm-columns field-name detail-{$key}-key">{$value.nice}</div>
+            <div class="glm-small-6 glm-medium-12 glm-large-6 glm-columns field-value detail-{$key}-value">{$value.data}</div>
+        </div>
+    {elseif $value.data !== 'Yes' && $value.data !== 'No'}
+        <div class="glm-row field-container">
+            <div class="glm-small-6 glm-medium-12 glm-large-6 glm-columns field-name detail-{$key}-key">{$value.nice}</div>
+            <div class="glm-small-6 glm-medium-12 glm-large-6 glm-columns field-value detail-{$key}-value">{$value.data}</div>
+        </div>
+    {/if}
+{/foreach}
+{$stock = $field_values.stock.data}
+{$msrp = $field_values.msrp.data}
+{$sale = $field_values['sale-price'].data}
+{$prod = $member_name}
+ <a class="contact-sales" href="{apply_filters('get_form_permalink', 286)}?prod={$prod}&stock={$stock}&msrp={$msrp}&sale={$sale}">Contact Sales</a> 
\ No newline at end of file
diff --git a/views/front/fields/list.html b/views/front/fields/list.html
new file mode 100644 (file)
index 0000000..1851b53
--- /dev/null
@@ -0,0 +1,20 @@
+{foreach $field_values as $key=>$value}
+    {if $value.slash === true}
+        <div class="glm-row field-container slash-price {if $key === 'red-hot-deal' && $value.data === 'Yes'} red-hot {/if}">
+    {else}
+        <div class="glm-row field-container {if $key === 'red-hot-deal' && $value.data === 'Yes'} red-hot {/if}">
+    {/if}
+        {if $value.type == 'Home'}
+            <div class="glm-small-3 glm-large-4 glm-columns list-field-name home {$key}-key">{$value.nice}</div>
+            <div class="glm-small-9 glm-large-8 glm-columns list-field-value home {$key}-value">{$value.data}</div>
+        {else}
+            <div class="glm-small-3 glm-large-4 glm-columns list-field-name {$key}-key">{$value.nice}</div>
+            <div class="glm-small-9 glm-large-8 glm-columns list-field-value {$key}-value">{$value.data}</div>
+        {/if}
+           {if $key === 'red-hot-deal' && $value.data === 'Yes'}
+            <div class="glm-small-12 glm-columns field-value {$key}-logo-container">
+                <img src="{$assets_dir}/redhotdeals.gif">
+            </div>
+           {/if}
+        </div>
+{/foreach}
diff --git a/views/front/readme.txt b/views/front/readme.txt
new file mode 100644 (file)
index 0000000..1138d90
--- /dev/null
@@ -0,0 +1,7 @@
+The front controller uses views (templates) under this directory to generate final output.
+
+Typically you should add a directory here that matches the category of actions that will use these views.
+
+Under that directory place the view (template) for the various actions.
+
+Views under this directory would normally be called due to processing of a shortcode.
\ No newline at end of file