From 8f27be11509824110a0b5ce56146ed0438ccf23a Mon Sep 17 00:00:00 2001 From: Cameron Date: Mon, 18 Jan 2021 18:10:00 -0800 Subject: [PATCH] Added e_user.php 'settings' method to define additional (extended) user fields dynamically. See _blank/e_user.php --- e107_admin/users_extended.php | 18 ++- e107_handlers/form_handler.php | 10 +- e107_handlers/plugin_class.php | 113 +++++++++++++++++- e107_handlers/upload_handler.php | 12 +- e107_handlers/user_extended_class.php | 68 ++++++++++- e107_plugins/_blank/e_user.php | 29 +++++ e107_plugins/_blank/plugin.xml | 1 - .../tests/unit/e107_user_extendedTest.php | 45 ++++++- e107_tests/tests/unit/pluginsTest.php | 16 +++ 9 files changed, 289 insertions(+), 23 deletions(-) diff --git a/e107_admin/users_extended.php b/e107_admin/users_extended.php index 0249e28b0..b1f59a510 100755 --- a/e107_admin/users_extended.php +++ b/e107_admin/users_extended.php @@ -354,7 +354,7 @@ e107::js('footer-inline', js()); protected $fields = array ( 'checkboxes' => array ( 'title' => '', 'type' => null, 'data' => null, 'width' => '5%', 'thclass' => 'center', 'forced' => '1', 'class' => 'center', 'toggle' => 'e-multiselect', ), 'user_extended_struct_id' => array ( 'title' => LAN_ID, 'data' => 'int', 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), - 'user_extended_struct_name' => array ( 'title' => LAN_NAME, 'type' => 'text', 'data' => 'str', 'readonly'=>true, 'width' => 'auto', 'help' => '', 'readParms' => '', 'writeParms' => 'tdClassRight=form-inline&pre=user_ ', 'class' => 'left', 'thclass' => 'left', ), + 'user_extended_struct_name' => array ( 'title' => LAN_NAME, 'type' => 'method', 'data' => 'str', 'readonly'=>true, 'width' => '350px', 'help' => '', 'readParms' => '', 'writeParms' => 'tdClassRight=form-inline&pre=user_ ', 'class' => 'left', 'thclass' => 'left', ), 'user_extended_struct_text' => array ( 'title' => EXTLAN_79, 'type' => 'text', 'data' => 'str', 'width' => 'auto', 'inline' => true, 'help' => '', 'readParms' => 'constant=1', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), 'user_extended_struct_type' => array ( 'title' => EXTLAN_2, 'type' => 'method', 'data' => 'int', 'width' => 'auto', 'batch' => true, 'filter' => true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), 'user_extended_struct_values' => array ( 'title' => EXTLAN_82, 'type' => 'method', 'nolist'=>true, 'data' => 'str', 'width' => 'auto', 'inline' => true, 'help' => '', 'readParms' => '', 'writeParms' => '', 'class' => 'left', 'thclass' => 'left', ), @@ -895,8 +895,24 @@ e107::js('footer-inline', js()); } + // Custom Method/Function + function user_extended_struct_name($curVal,$mode) + { + switch($mode) + { + case 'read': // List Page + case 'write': // Edit Page + return str_replace('plugin_', "".LAN_PLUGIN." ",$curVal); + break; + case 'filter': + case 'batch': + return array(); + break; + } + } + // Custom Method/Function function user_extended_struct_values($curVal,$mode) diff --git a/e107_handlers/form_handler.php b/e107_handlers/form_handler.php index 80ab4ffb2..1d6b91e68 100644 --- a/e107_handlers/form_handler.php +++ b/e107_handlers/form_handler.php @@ -6679,7 +6679,15 @@ var_dump($select_options);*/ $cls = $this; } - $ret = call_user_func_array(array($cls, $meth), array($value, 'write', $parms)); + if(method_exists($cls, $meth)) + { + $ret = call_user_func_array(array($cls, $meth), array($value, 'write', $parms)); + } + else + { + $ret = "(Method ".$meth." not found in ".get_class($cls).")"; + } + break; case 'upload': //TODO - from method diff --git a/e107_handlers/plugin_class.php b/e107_handlers/plugin_class.php index b1ac31424..bcde7f146 100644 --- a/e107_handlers/plugin_class.php +++ b/e107_handlers/plugin_class.php @@ -2881,8 +2881,8 @@ class e107plugin $this->XmlMediaCategories($function, $plug_vars); } - $this->XmlMenus($this->plugFolder, $function, $plug_vars['files']); - + $this->addonMenu($this->plugFolder, $function, $plug_vars['files']); + $this->addonUser($this->plugFolder, $function); $this->manage_icons($this->plugFolder, $function); @@ -2999,7 +2999,110 @@ class e107plugin } - private function XmlMenus($plug, $function, $files) + + /** + * Manager e_user extended fields + * @param string $plug + * @param string $function + * @param array $opts + * @return null + */ + private function addonUser($plug, $function, $opts=array()) + { + $this->log("Running ".__FUNCTION__); + $path = e_PLUGIN.$plug.'/e_user.php'; + + if(!file_exists(e_PLUGIN.$plug.'/e_user.php')) + { + $this->log("No e_user.php addon found."); + return null; + } + + require_once($path); + + if(!$list = e107::callMethod($plug.'_user', 'settings')) + { + $this->log("Settings method NOT found"); + return null; + } + + $this->log("Settings method found: ".print_r($list, true)); + + $ue = e107::getUserExt(); + + foreach($list as $field=>$attrib) + { + $read = varset($attrib['read'], e_UC_MEMBER); + $write = varset($attrib['write'], e_UC_MEMBER); + $applic = varset($attrib['applicable'], e_UC_MEMBER); + $req = varset($attrib['required'], 0); + $type = varset($attrib['fieldType'], 'VARCHAR(255)'); + + unset($attrib['read'], $attrib['write'], $attrib['applicable'], $attrib['required'], $attrib['fieldType']); + + $name = $this->ue_field_name($plug, EUF_ADDON, $field); + + $insert = array( + 'name' => $name, + 'text' => varset($attrib['title'], "None Specified"), + 'type' => EUF_ADDON, + 'parms' => $plug, + 'values' => e107::serialize($attrib, 'json'), + 'default' => null, + 'parent' => 0, + 'required' => $req, + 'read' => $read, + 'write' => $write, + 'applicable' => $applic, + 'fieldType' => $type, + ); + + switch($function) + { + case "install": + if($ue->user_extended_add($insert)) + { + $this->log("User Ext. field added. (".$field.")"); + e107::getMessage()->addSuccess(EPL_ADLAN_249 .$name.' ... '); + } + else + { + e107::getMessage()->addError(EPL_ADLAN_249 .$name.' ... '); + $this->log("ERROR: User Ext. field couldn't be added. ".print_r($insert,true)); + } + break; + + case "uninstall": + if($ue->user_extended_remove($name, $name)) + { + e107::getMessage()->addSuccess(EPL_ADLAN_250 .$name.' ... '); + $this->log("User Ext. field removed. (".$field.")"); + } + else + { + e107::getMessage()->addError(EPL_ADLAN_250 .$name.' ... '); + $this->log("ERROR: User Ext. field couldn't be removed. (".$field.")"); + } + break; + + default: + // code to be executed if n is different from all labels; + } + + + } + + } + + + /** + * Manage xxxxx_menu files. + * @param string $plug + * @param string $function + * @param $files + * @return false|null + */ + private function addonMenu($plug, $function, $files) { $this->log("Running ".__FUNCTION__); @@ -4197,7 +4300,7 @@ class e107plugin $this->manage_notify('add', $eplug_folder); - $this->XmlMenus($plug_vars['folder'], $function, $plug_vars['files']); + $this->addonMenu($plug_vars['folder'], $function, $plug_vars['files']); $eplug_addons = $this->getAddons($eplug_folder); @@ -4463,7 +4566,7 @@ class e107plugin $sql->delete('menus', "menu_name='{$eplug_menu_name}' "); }*/ $folderFiles = scandir(e_PLUGIN . $plug['plugin_path']); - $this->XmlMenus($eplug_folder, 'uninstall', $folderFiles); + $this->addonMenu($eplug_folder, 'uninstall', $folderFiles); if ($eplug_link) { diff --git a/e107_handlers/upload_handler.php b/e107_handlers/upload_handler.php index 8d0568438..71c238631 100644 --- a/e107_handlers/upload_handler.php +++ b/e107_handlers/upload_handler.php @@ -144,14 +144,14 @@ function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL) { if (UH_DEBUG) { - e107::getLog()->addEvent(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "Invalid directory: ".$uploaddir, FALSE, FALSE); + // e107::getLog()->addEvent(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "Invalid directory: ".$uploaddir, FALSE, FALSE); } return FALSE; // Need a valid directory } if (UH_DEBUG) { - e107::getLog()->addEvent(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "Destination directory: ".$uploaddir, FALSE, FALSE); + // e107::getLog()->addEvent(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "Destination directory: ".$uploaddir, FALSE, FALSE); } $final_chmod = varset($options['final_chmod'], 0644); @@ -167,9 +167,9 @@ function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL) $max_file_count = varset($options['max_file_count'], 0); - if (!is_array($files)) + if (empty($files)) { - if (UH_DEBUG) + if (deftrue('UH_DEBUG')) { e107::getLog()->addEvent(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "No files uploaded", FALSE, FALSE); } @@ -184,9 +184,9 @@ function process_uploaded_files($uploaddir, $fileinfo = FALSE, $options = NULL) // That's the basics set up - we can start processing files now - if (UH_DEBUG) + if (deftrue('UH_DEBUG')) { - e107::getLog()->addEvent(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "Start individual files: ".count($files['name'])." Max upload: ".$max_upload_size, FALSE, FALSE); + // e107::getLog()->addEvent(10, __FILE__."|".__FUNCTION__."@".__LINE__, "DEBUG", "Upload Handler test", "Start individual files: ".count($files['name'])." Max upload: ".$max_upload_size, FALSE, FALSE); } $c = 0; diff --git a/e107_handlers/user_extended_class.php b/e107_handlers/user_extended_class.php index a4c6a95b4..cbb9d36be 100644 --- a/e107_handlers/user_extended_class.php +++ b/e107_handlers/user_extended_class.php @@ -282,7 +282,11 @@ class e107_user_extended $index = $this->nameIndex[$fieldname]; - switch ($this->fieldDefinitions[$index]['user_extended_struct_type']) + $type = $this->fieldDefinitions[$index]['user_extended_struct_type']; + + $ret = null; + + switch($type) { case EUF_TEXT : case EUF_DB_FIELD : @@ -293,7 +297,7 @@ class e107_user_extended case EUF_LANGUAGE : case EUF_PREDEFINED : case EUF_RADIO : - $ret = 'todb'; + $ret = 'todb'; break; case EUF_CHECKBOX : @@ -303,9 +307,30 @@ class e107_user_extended case EUF_INTEGER : $ret = 'int'; break; - } + + // admin-ui format 'data' ie. 'str', 'int', 'array'; + case EUF_ADDON : + $ret = 'JSON'; + + if(!empty($this->fieldDefinitions[$index]['user_extended_struct_values'])) + { + if($tmp = e107::unserialize($this->fieldDefinitions[$index]['user_extended_struct_values'])) + { + if(isset($tmp['data'])) + { + $ret = $tmp['data']; + } + + } + + } + + break; + } + return $ret; + } /** @@ -837,7 +862,7 @@ class e107_user_extended case EUF_ADDON: return 'JSON'; break; - + default: e107::getMessage()->addDebug("Unknown type '{$type}' for user extended field."); return false; @@ -878,7 +903,6 @@ class e107_user_extended - function user_extended_add($name, $text='', $type='', $parms='', $values='', $default='', $required='', $read='', $write='', $applicable='', $order='', $parent='') { @@ -909,6 +933,11 @@ class e107_user_extended } $field_info = $this->user_extended_type_text($type, $default); + + if($type === EUF_ADDON && !empty($fieldType)) + { + $field_info = $fieldType; + } // wrong type if(false === $field_info) @@ -941,7 +970,7 @@ class e107_user_extended 'user_extended_struct_text' => (string) $tp -> toDB($text, true), 'user_extended_struct_type' => (int) $type, 'user_extended_struct_parms' => (string) $tp -> toDB($parms, true), - 'user_extended_struct_values' => (string) $tp -> toDB($values, true), + 'user_extended_struct_values' => ($type === EUF_ADDON) ? (string) $values : (string) $tp -> toDB($values, true), 'user_extended_struct_default' => (string) $tp -> toDB($default, true), 'user_extended_struct_read' => (int) $read, 'user_extended_struct_write' => (int) $write, @@ -955,6 +984,8 @@ class e107_user_extended if(!$this->user_extended_field_exist($name)) { + + $nid = $sql->insert('user_extended_struct', $extStructInsert); $this->init(); // rebuild the list. @@ -1112,6 +1143,29 @@ class e107_user_extended switch($struct['user_extended_struct_type']) { + case EUF_ADDON: + $attributes = e107::unserialize($struct['user_extended_struct_values']); + + $plug = $struct['user_extended_struct_parms']; + if(!$form = e107::getAddon($plug,'e_user',$plug."_user_form")) // custom form. + { + $form = e107::getForm(); + } + + // $method = str_replace('plugin_'.$plug.'_', '', $struct['user_extended_struct_name']); + + if(empty($attributes['type'])) + { + trigger_error("'type' is missing from field definition", E_USER_NOTICE); + return null; + } + + $attributes['method'] = 'user_'.$struct['user_extended_struct_name']; + + return $form->renderElement($fname,$curval, $attributes); + break; + + case EUF_COUNTRY: return e107::getForm()->country($fname,$curval, $opts); break; @@ -1771,6 +1825,8 @@ class e107_user_extended return $ret; } + + } diff --git a/e107_plugins/_blank/e_user.php b/e107_plugins/_blank/e_user.php index 42e96bd2f..c6541f769 100644 --- a/e107_plugins/_blank/e_user.php +++ b/e107_plugins/_blank/e_user.php @@ -24,6 +24,22 @@ class _blank_user // plugin-folder + '_user' return $var; } + /** + * The same field format as admin-ui, with the addition of 'fieldType', 'read', 'write', 'appliable' and 'required' as used in extended fields table. + * + * @return array + */ + function settings() + { + $fields = array(); + $fields['field1'] = array('title' => "Field 1", 'fieldType' => 'varchar(30)', 'read'=> e_UC_ADMIN, 'write'=>e_UC_MEMBER, 'type' => 'text', 'writeParms' => array('size' => 'xxlarge')); + $fields['field2'] = array('title' => "Field 2", 'fieldType' => 'int(2)', 'type' => 'number', 'data'=>'int'); + $fields['field3'] = array('title' => "Field 3", 'fieldType' => 'int(1)', 'type' => 'method', 'data'=>'str', 'required'=>true); // see below. + + return $fields; + + } + /** * Experimental and subject to change without notice. @@ -54,4 +70,17 @@ class _blank_user // plugin-folder + '_user' +} + +// (plugin-folder)_user_form - only required when using custom methods. +class _blank_user_form extends e_form +{ + // user_plugin_(plugin-folder)_(fieldname) + public function user_plugin__blank_field3($curVal, $mode, $att=array()) + { + $opts = array(1,2,3,4); + return $this->select('user_plugin__blank_field3', $opts, $curVal); + } + + } \ No newline at end of file diff --git a/e107_plugins/_blank/plugin.xml b/e107_plugins/_blank/plugin.xml index f05c659b3..e08aec4ce 100644 --- a/e107_plugins/_blank/plugin.xml +++ b/e107_plugins/_blank/plugin.xml @@ -29,7 +29,6 @@ - Blank Images diff --git a/e107_tests/tests/unit/e107_user_extendedTest.php b/e107_tests/tests/unit/e107_user_extendedTest.php index 20dd3ef4d..c9b531254 100644 --- a/e107_tests/tests/unit/e107_user_extendedTest.php +++ b/e107_tests/tests/unit/e107_user_extendedTest.php @@ -35,6 +35,7 @@ $this->ue->__construct(); + $this->structTypes = array( 'text' => EUF_TEXT, 'homepage' => EUF_TEXT, @@ -76,7 +77,11 @@ 'dbfield' => 'core_media_cat,media_cat_id,media_cat_title,media_cat_order', 'list' => 'timezones', 'radio' => 'M => UE_LAN_MALE,F => UE_LAN_FEMALE', - 'checkbox' => 'check1,check2,check3' + 'checkbox' => 'check1,check2,check3', + 'addon' => e107::serialize( + array('type'=> 'number', 'data' => 'int', 'title' => $this->structLabels['addon']), + 'json') + ); $this->structDefault = array( @@ -137,6 +142,13 @@ 'required' => (isset($this->structRequired[$k])) ? $this->structRequired[$k] : 0, ); + // simulate data from e_user.php 'settings' method. + if($v === EUF_ADDON) + { + $insert['fieldType'] = 'int(2)'; + $insert['parms'] = '_blank'; // plugin dir. + } + $this->ue->user_extended_add($insert); // $this->ue->user_extended_add($k, ucfirst($k), $v , null, $value); } @@ -213,7 +225,7 @@ */ public function testUserExtendedShortcode() { - // e107::setRegistry('corelan/English_user_extended_front'); + $this->fixRegistry('before'); foreach($this->userValues as $field => $value) { @@ -318,7 +330,7 @@ $this->assertStringContainsString($legacyExpectedIcons[$field], $result); } - + $this->fixRegistry('after'); } @@ -339,6 +351,11 @@ public function testSignupExtendedUserFieldsShortcode() { + $this->fixRegistry('before'); + + + + $sc = e107::getScBatch('signup'); @@ -365,9 +382,31 @@ } + $this->fixRegistry('after'); + + + } + private function fixRegistry($mode) + { + $regID = 'core/e107/singleton/e107_user_extended'; + static $originalRegistry; + + if($mode == 'before') + { + $originalRegistry = e107::getRegistry($regID); + e107::setRegistry($regID, $this->ue); + } + + if($mode === 'after') + { + e107::setRegistry($regID, $originalRegistry); + } + + + } public function testGetUserExtendedFieldData() { diff --git a/e107_tests/tests/unit/pluginsTest.php b/e107_tests/tests/unit/pluginsTest.php index 89baad549..18e7274bc 100644 --- a/e107_tests/tests/unit/pluginsTest.php +++ b/e107_tests/tests/unit/pluginsTest.php @@ -118,6 +118,22 @@ ); } + /** + * @see https://github.com/e107inc/e107/issues/3547 + */ + public function testBlank() + { + // $this->_debugPlugin = '_blank'; + + $this->pluginInstall('_blank'); + + // $this->pluginUninstall('_blank'); + + + } + + + /** * @see https://github.com/e107inc/e107/issues/3547 */