From f2049ed1481edd8db67e14fc14fd07b7f3930093 Mon Sep 17 00:00:00 2001 From: Chuck Scott Date: Thu, 21 Jul 2016 13:03:33 -0400 Subject: [PATCH] Added html (print) and CSV (spreadsheet) member report links from member list admin page. --- controllers/admin.php | 74 ++++++- models/admin/ajax/membersListExport.php | 214 +++++++++++++++++++++ models/admin/ajax/readme.txt | 3 + setup/standardTemplateParams.php | 4 +- setup/validActions.php | 61 +++--- views/admin/ajax/membersListExport.html | 56 ++++++ views/admin/ajax/membersListExportCsv.html | 5 + views/admin/members/list.html | 15 ++ 8 files changed, 400 insertions(+), 32 deletions(-) create mode 100644 models/admin/ajax/membersListExport.php create mode 100644 views/admin/ajax/membersListExport.html create mode 100644 views/admin/ajax/membersListExportCsv.html diff --git a/controllers/admin.php b/controllers/admin.php index 966b7b1d..f0e6fbc5 100644 --- a/controllers/admin.php +++ b/controllers/admin.php @@ -280,7 +280,8 @@ class glmMembersAdmin extends GlmPluginSupport // Instantiate the model and ask it to perform the work $model = new $className($this->wpdb, $this->config); - $model->modelAction(); + $results = $model->modelAction(); + } } @@ -292,6 +293,77 @@ class glmMembersAdmin extends GlmPluginSupport trigger_error ( $err, E_USER_ERROR); } + // Get the current theme directory to check for modified views + $theme = get_template_directory(); + + // Get name of plugin where model and view are located + $plugIn = $this->config['validActions']['adminActions']['ajax'][$glmAction]; + + // Get the specified view file path and name + $view = false; + if (isset($results['view'])) { + $view = $results['view']; + } + + // If a view file is specified + $badView = false; + if ($view) { + + // Get the specified view file - check theme first + $viewPath = "$theme/$plugIn/views"; + $viewFile = $view; + + if (!is_file($viewPath.'/'.$viewFile)) { + + // Next try the plugin/add-on + $viewPath = GLM_MEMBERS_WORDPRESS_PLUGIN_PATH . "$plugIn/views"; + $viewFile = $view; + if (!is_file($viewPath.'/'.$viewFile)) { + + // No matching view file found + $errorMsg .= "Bad or missing view file: $viewPath/$viewfile"; + $badView = true; + + } + + } + + } + + /* + * Merge data returned from the model with the selected view + */ + + // Load Smarty Template support + $smarty = new smartyTemplateSupport(); + + // Add standard template parameters + require GLM_MEMBERS_PLUGIN_SETUP_PATH.'/standardTemplateParams.php'; + + // Add data from model to Smarty template + if (is_array($results['data']) && count($results['data']) > 0) { + foreach ($results['data'] as $k => $d) { + $smarty->templateAssign($k, $d); + } + } + + $smarty->templateAssign ( 'thisAction', $glmAction); + + // Update the Smarty view path - *** NEEED TO FIX THIS TO SUPPORT THEME VIEWS SOMEHOW **** + $smarty->template->addTemplateDir($viewPath); + + // Generate output from model data and view + $smarty->template->display($viewFile); + + // If debug is requested, create debug window + if (GLM_MEMBERS_PLUGIN_ADMIN_DEBUG) { + echo " + + "; + } +exit; wp_die(); } diff --git a/models/admin/ajax/membersListExport.php b/models/admin/ajax/membersListExport.php new file mode 100644 index 00000000..c1365eab --- /dev/null +++ b/models/admin/ajax/membersListExport.php @@ -0,0 +1,214 @@ + + * @license http://www.gaslightmedia.com Gaslightmedia + * @version 0.1 + */ + + +// Load Member Info data abstract +require_once(GLM_MEMBERS_PLUGIN_CLASS_PATH.'/data/dataMemberInfo.php'); + +/* + * This class exports the currently selected members list + * to a printable HTML file, to a CSV file, or otherwise. + */ +class GlmMembersAdmin_ajax_membersListExport extends GlmDataMemberInfo +{ + + /** + * 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; + + parent::__construct(false, false); + + } + + /* + * 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) + { + + $where = ' true '; + $categories = false; + $haveMembers = false; + $list = false; + $success = false; + $filterPending = false; + $filterArchived = false; + $haveFilter = false; + $numbDisplayed = false; + $lastDisplayed = false; + $paging = true; + $prevStart = false; + $nextStart = false; + $start = 1; + $limit = 20; // Set to the number of listings per page + $namesList = false; + + // Check if this is a request to show archived members + if (isset($_REQUEST['filterArchived'])) { + $where .= " AND access = ".$this->config['access_numb']['Archived']; + $filterArchived = true; + $haveFilter = true; + + // If not, don't show them + } else { +// $where .= " AND access != ".$this->config['access_numb']['Archived']; + } + + // Check if there is a category filter (multi-select) + if (isset($_REQUEST['filterCategories']) && count($_REQUEST['filterCategories']) > 0) { + + $cats = ''; + $catsSep = ''; + + // For each selected category + foreach($_REQUEST['filterCategories'] as $c) { + $cats .= $catsSep.$c; + $catsSep = ','; + $categories[$c]['selected'] = true; + } + + $where .= " AND T.id in ( + SELECT DISTINCT(I.member) + FROM ".GLM_MEMBERS_PLUGIN_DB_PREFIX."member_info I, + ".GLM_MEMBERS_PLUGIN_DB_PREFIX."category_member_info M, + ".GLM_MEMBERS_PLUGIN_DB_PREFIX."categories C + WHERE I.id = M.member_info + AND ( + M.category in ($cats) + OR (C.parent in ($cats) AND M.category = C.id) + ) + )"; + } + + // Check for "Pending Only + if (isset($_REQUEST['filterPending'])) { + + // Refine search only to members with pending Info data + $where .= " AND ( + SELECT COUNT(id) + FROM ".GLM_MEMBERS_PLUGIN_DB_PREFIX."member_info I + WHERE I.status = ".$this->config['status_numb']['Pending']." + AND I.member = T.id + )"; + + $filterPending = true; + $haveFilter = true; + } + + // Get a current list of members without paging + $list = $this->getList($where, "member_name"); + + // If we have list entries - even if it's an empty list + $success = true; + $haveMembers = false; + if ($list !== false) { + + $success = true; + + // If we have any entries + $memberCount = count($list); + if ($memberCount > 0) { + $haveMembers = true; + } + } + + if (GLM_MEMBERS_PLUGIN_ADMIN_DEBUG_VERBOSE) { + glmMembersAdmin::addNotice($list, 'DataBlock', 'Member Data'); + } + + // Compile template data + $templateData = array( + 'haveMembers' => $haveMembers, + 'members' => $list, + 'memberCount' => $memberCount, + 'categories' => $categories, + 'haveFilter' => $haveFilter, + 'filterArchived' => $filterArchived, + 'filterPending' => $filterPending, + 'numbDisplayed' => $numbDisplayed, + 'lastDisplayed' => $lastDisplayed, + 'paging' => $paging, + 'prevStart' => $prevStart, + 'nextStart' => $nextStart, + 'start' => $start, + 'limit' => $limit, + 'namesList' => $namesList + ); + + $view = 'admin/ajax/membersListExport.html'; + if ($_REQUEST['type'] == 'csv') { + $view = 'admin/ajax/membersListExportCsv.html'; + header("Content-Type: text/csv"); + header("Content-Disposition: attachment; filename=file.csv"); + } else { + header("Content-Type: text/html"); + header("Content-Disposition: attachment; filename=file.html"); + } + + // Disable caching + header("Cache-Control: no-cache, no-store, must-revalidate"); // HTTP 1.1 + header("Pragma: no-cache"); // HTTP 1.0 + header("Expires: 0"); // Proxies + + // Return status, suggested view, and data to controller + return array( + 'status' => $success, + 'menuItemRedirect' => false, + 'modelRedirect' => false, + 'view' => $view, + 'data' => $templateData + ); + + } + +} diff --git a/models/admin/ajax/readme.txt b/models/admin/ajax/readme.txt index 07c37ec9..5fa07f84 100644 --- a/models/admin/ajax/readme.txt +++ b/models/admin/ajax/readme.txt @@ -36,5 +36,8 @@ output. Output may include custom headers and any desired content. The controlle wp_die() function call to terminate any further processing if there is a return from the model's modelAction() function. This prevents any additional output from reaching the browser. +AJAX support now includes processing of returned model data and template output. + +NOTE: There is currently no support for model redirection. \ No newline at end of file diff --git a/setup/standardTemplateParams.php b/setup/standardTemplateParams.php index 9bbffd66..981c2a57 100644 --- a/setup/standardTemplateParams.php +++ b/setup/standardTemplateParams.php @@ -42,7 +42,9 @@ if (is_admin()) { // Admin specific $smarty->templateAssign('adminDebug', GLM_MEMBERS_PLUGIN_ADMIN_DEBUG); - $smarty->templateAssign('addOnTabs', $addOnTabs); + if (isset($addOnTabs)) { + $smarty->templateAssign('addOnTabs', $addOnTabs); + } $smarty->templateAssign('adminUrl', GLM_MEMBERS_PLUGIN_ADMIN_URL); } else { diff --git a/setup/validActions.php b/setup/validActions.php index be7b0f0d..b8765002 100644 --- a/setup/validActions.php +++ b/setup/validActions.php @@ -33,57 +33,58 @@ $glmMembersValidActions = array( 'adminActions' => array( 'ajax' => array( - 'imageUpload' => 'glm-member-db', - 'newOldMemberIdsCsv' => 'glm-member-db' + 'imageUpload' => 'glm-member-db', + 'newOldMemberIdsCsv' => 'glm-member-db', + 'membersListExport' => 'glm-member-db' ), 'dashboardWidget' => array( - 'index' => 'glm-member-db', + 'index' => 'glm-member-db', ), 'members' => array( - 'index' => 'glm-member-db', // member list - 'list' => 'glm-member-db', - 'reports' => 'glm-member-db', - 'other' => 'glm-member-db', + 'index' => 'glm-member-db', // member list + 'list' => 'glm-member-db', + 'reports' => 'glm-member-db', + 'other' => 'glm-member-db', ), 'member' => array( - 'index' => 'glm-member-db', // Member Dashboard - 'memberInfo' => 'glm-member-db', - 'memberEdit' => 'glm-member-db', - 'locations' => 'glm-member-db', + 'index' => 'glm-member-db', // Member Dashboard + 'memberInfo' => 'glm-member-db', + 'memberEdit' => 'glm-member-db', + 'locations' => 'glm-member-db', ) , 'settings' => array( - 'index' => 'glm-member-db', // Member Types - 'categories' => 'glm-member-db', - 'cities' => 'glm-member-db', - 'regions' => 'glm-member-db', - 'amenities' => 'glm-member-db', + 'index' => 'glm-member-db', // Member Types + 'categories' => 'glm-member-db', + 'cities' => 'glm-member-db', + 'regions' => 'glm-member-db', + 'amenities' => 'glm-member-db', ), 'management' => array( - 'index' => 'glm-member-db', // General Options - 'terms' => 'glm-member-db', - 'development' => 'glm-member-db', - 'theme' => 'glm-member-db', - 'import' => 'glm-member-db', - 'addons' => 'glm-member-db', - 'hooks' => 'glm-member-db', + 'index' => 'glm-member-db', // General Options + 'terms' => 'glm-member-db', + 'development' => 'glm-member-db', + 'theme' => 'glm-member-db', + 'import' => 'glm-member-db', + 'addons' => 'glm-member-db', + 'hooks' => 'glm-member-db', ), 'shortcodes' => array( - 'index' => 'glm-member-db' + 'index' => 'glm-member-db' ), 'error' => array( - 'index' => 'glm-member-db', - 'badAction' => 'glm-member-db', + 'index' => 'glm-member-db', + 'badAction' => 'glm-member-db', ) ), 'frontActions' => array( 'members' => array( - 'list' => 'glm-member-db', - 'detail' => 'glm-member-db', + 'list' => 'glm-member-db', + 'detail' => 'glm-member-db', ), 'error' => array( - 'index' => 'glm-member-db', - 'badAction' => 'glm-member-db', + 'index' => 'glm-member-db', + 'badAction' => 'glm-member-db', ) ) ); diff --git a/views/admin/ajax/membersListExport.html b/views/admin/ajax/membersListExport.html new file mode 100644 index 00000000..9bca5631 --- /dev/null +++ b/views/admin/ajax/membersListExport.html @@ -0,0 +1,56 @@ + + +

List of {$terms.term_member_plur_cap}

+
+ +

Total found: {$memberCount}  

+ + + + + + + + + + + + + + + + + + + + + +{if $haveMembers} + {foreach $members as $m} + + + + + + + + + + + + + + + + + {/foreach} +{else} + +{/if} + +
ID{$terms.term_member_cap} NameCurrent ProfileAddressAddr Line #2CityStateZIP/PostalPhoneToll FreeE-MailWeb AddressCategories
{$m.id}{$m.member}{$m.reference_name}{$m.addr1}{$m.addr2}{$m.city}{$m.state.value}{$m.zip}{$m.phone}{$m.toll_free}{$m.email}{$m.url} + {foreach $m.categories as $t} + {$t.name}, + {/foreach} +
(no {$terms.term_member_plur} listed)
+ \ No newline at end of file diff --git a/views/admin/ajax/membersListExportCsv.html b/views/admin/ajax/membersListExportCsv.html new file mode 100644 index 00000000..60182a7f --- /dev/null +++ b/views/admin/ajax/membersListExportCsv.html @@ -0,0 +1,5 @@ +{if $haveMembers}List of {$terms.term_member_plur_cap} - Number listed: {$memberCount} + +"ID","{$terms.term_member_cap} Name","Current Profile","Address","Addr Line #2","City","State","ZIP/Postal","Phone","Toll Free","E-Mail","Web Address","Categories" +{foreach $members as $m}"{$m.id}","{$m.member}","{$m.reference_name}","{$m.addr1}","{$m.addr2}","{$m.city}","{$m.state.value}","{$m.zip}","{$m.phone}","{$m.toll_free}","{$m.email}", "{$m.url}","{foreach $m.categories as $t}{$t.name},{/foreach}" +{/foreach}{else}No {$terms.term_member_plur_cap} Selected{/if} \ No newline at end of file diff --git a/views/admin/members/list.html b/views/admin/members/list.html index 5cafcf52..663aac8f 100644 --- a/views/admin/members/list.html +++ b/views/admin/members/list.html @@ -26,6 +26,9 @@

Total found: {$memberCount}  

+ + + {if $paging} @@ -100,6 +103,18 @@ return false; }); + // Perform Export + $("#glmMembersExport").on( 'click', function() { + window.open("{$ajaxUrl}?action=glm_members_admin_ajax&glm_action=membersListExport&type=print", 'Member Export'); + return false; + }); + + // Perform CSV Export + $("#glmMembersExportCsv").on( 'click', function() { + window.open("{$ajaxUrl}?action=glm_members_admin_ajax&glm_action=membersListExport&type=csv", 'Member Export CSV'); + return false; + }); + /* * Do autocomplete search for member * label: What will be searched -- 2.17.1