diff --git a/administrator/components/com_admin/sql/updates/mysql/3.8.7-2018-03-22.sql b/administrator/components/com_admin/sql/updates/mysql/3.8.7-2018-03-22.sql new file mode 100644 index 0000000000000..07a5643838373 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/mysql/3.8.7-2018-03-22.sql @@ -0,0 +1,2 @@ +ALTER TABLE `#__fields` ADD COLUMN `access_form` int(11) NOT NULL DEFAULT '1' AFTER `access`; +ALTER TABLE `#__fields_groups` ADD COLUMN `access_form` int(11) NOT NULL DEFAULT '1' AFTER `access`; diff --git a/administrator/components/com_admin/sql/updates/postgresql/3.8.7-2018-03-22.sql b/administrator/components/com_admin/sql/updates/postgresql/3.8.7-2018-03-22.sql new file mode 100644 index 0000000000000..5b8235e433858 --- /dev/null +++ b/administrator/components/com_admin/sql/updates/postgresql/3.8.7-2018-03-22.sql @@ -0,0 +1,2 @@ +ALTER TABLE "#__fields" ADD COLUMN "access_form" int(11) DEFAULT "1" NOT NULL; +ALTER TABLE "#__fields_groups" ADD COLUMN "access_form" int(11) DEFAULT "1" NOT NULL; diff --git a/administrator/components/com_admin/sql/updates/sqlazure/3.8.7-2018-03-22.sql b/administrator/components/com_admin/sql/updates/sqlazure/3.8.7-2018-03-22.sql new file mode 100644 index 0000000000000..4d7e17cf4438e --- /dev/null +++ b/administrator/components/com_admin/sql/updates/sqlazure/3.8.7-2018-03-22.sql @@ -0,0 +1,3 @@ +ALTER TABLE [#__fields] ADD [access_form] [int] NOT NULL DEFAULT 1; +ALTER TABLE [#__fields_groups] ADD [access_form] [int] NOT NULL DEFAULT 1; + diff --git a/administrator/components/com_fields/helpers/fields.php b/administrator/components/com_fields/helpers/fields.php index afbc2cefafbd0..6b68648613c19 100644 --- a/administrator/components/com_fields/helpers/fields.php +++ b/administrator/components/com_fields/helpers/fields.php @@ -363,6 +363,10 @@ function categoryHasChanged(element) { // Organizing the fields according to their group $fieldsPerGroup = array(0 => array()); + // Limiting the Fields for the Form + $user = JFactory::getUser(); + $accessForm = $user->getAuthorisedViewLevels(); + foreach ($fields as $field) { if (!array_key_exists($field->type, $fieldTypes)) @@ -371,6 +375,12 @@ function categoryHasChanged(element) { continue; } + if (!in_array($field->access_form, $accessForm)) + { + // Field not available on Form + continue; + } + if (!array_key_exists($field->group_id, $fieldsPerGroup)) { $fieldsPerGroup[$field->group_id] = array(); diff --git a/administrator/components/com_fields/models/field.php b/administrator/components/com_fields/models/field.php index 02802f897d0ef..6cf51090da0f1 100644 --- a/administrator/components/com_fields/models/field.php +++ b/administrator/components/com_fields/models/field.php @@ -589,8 +589,9 @@ public function setFieldValue($fieldId, $itemId, $value) } elseif (count($value) == 1 && count((array) $oldValue) == 1) { - // Only a single row value update can be done - $needsUpdate = true; + // Only a single row value update can be done when not empty + $needsUpdate = is_array($value[0]) ? count($value[0]) : strlen($value[0]); + $needsDelete = !$needsUpdate; } else { diff --git a/administrator/components/com_fields/models/fields.php b/administrator/components/com_fields/models/fields.php index 271191d1c8e33..7ae65dce98c15 100644 --- a/administrator/components/com_fields/models/fields.php +++ b/administrator/components/com_fields/models/fields.php @@ -37,7 +37,9 @@ public function __construct($config = array()) 'name', 'a.name', 'state', 'a.state', 'access', 'a.access', + 'access_form', 'a.access_form', 'access_level', + 'access_form_level', 'language', 'a.language', 'ordering', 'a.ordering', 'checked_out', 'a.checked_out', @@ -134,7 +136,7 @@ protected function getListQuery() $this->getState( 'list.select', 'a.id, a.title, a.name, a.checked_out, a.checked_out_time, a.note' . - ', a.state, a.access, a.created_time, a.created_user_id, a.ordering, a.language' . + ', a.state, a.access, a.access_form, a.created_time, a.created_user_id, a.ordering, a.language' . ', a.fieldparams, a.params, a.type, a.default_value, a.context, a.group_id' . ', a.label, a.description, a.required' ) @@ -150,6 +152,7 @@ protected function getListQuery() // Join over the asset groups. $query->select('ag.title AS access_level')->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access'); + $query->select('afg.title AS access_form_level')->join('LEFT', '#__viewlevels AS afg ON afg.id = a.access_form'); // Join over the users for the author. $query->select('ua.name AS author_name')->join('LEFT', '#__users AS ua ON ua.id = a.created_user_id'); @@ -178,6 +181,20 @@ protected function getListQuery() } } + // Filter by access_form level. + if ($accessForm = $this->getState('filter.access_form')) + { + if (is_array($accessForm)) + { + $accessForm = ArrayHelper::toInteger($accessForm); + $query->where('a.access_form in (' . implode(',', $accessForm) . ')'); + } + else + { + $query->where('a.access_form = ' . (int) $accessForm); + } + } + if (($categories = $this->getState('filter.assigned_cat_ids')) && $context) { $categories = (array) $categories; diff --git a/administrator/components/com_fields/models/forms/field.xml b/administrator/components/com_fields/models/forms/field.xml index 17de81827a690..61a817fa702b7 100644 --- a/administrator/components/com_fields/models/forms/field.xml +++ b/administrator/components/com_fields/models/forms/field.xml @@ -201,6 +201,13 @@ description="JFIELD_ACCESS_DESC" /> + + JOPTION_SELECT_ACCESS + + + + COM_FIELDS_VIEW_FIELDS_SORT_GROUP_DESC + + diff --git a/administrator/components/com_fields/models/forms/filter_groups.xml b/administrator/components/com_fields/models/forms/filter_groups.xml index 6e18a7daf0b23..f88f09038ce2e 100644 --- a/administrator/components/com_fields/models/forms/filter_groups.xml +++ b/administrator/components/com_fields/models/forms/filter_groups.xml @@ -31,6 +31,14 @@ + + + + JGLOBAL_TITLE_DESC + + diff --git a/administrator/components/com_fields/models/forms/group.xml b/administrator/components/com_fields/models/forms/group.xml index 03a6619019378..78bcb1b2ca71b 100644 --- a/administrator/components/com_fields/models/forms/group.xml +++ b/administrator/components/com_fields/models/forms/group.xml @@ -89,8 +89,8 @@ filter="user_utc" /> - + + select('ag.title AS access_level')->join('LEFT', '#__viewlevels AS ag ON ag.id = a.access'); + $query->select('afg.title AS access_form_level')->join('LEFT', '#__viewlevels AS afg ON afg.id = a.access_form'); // Join over the users for the author. $query->select('ua.name AS author_name')->join('LEFT', '#__users AS ua ON ua.id = a.created_by'); @@ -157,11 +160,26 @@ protected function getListQuery() } } + // Filter by access_form level. + if ($accessForm = $this->getState('filter.access_form')) + { + if (is_array($accessForm)) + { + $accessForm = ArrayHelper::toInteger($access); + $query->where('a.access_form in (' . implode(',', $accessForm) . ')'); + } + else + { + $query->where('a.access_form = ' . (int) $accessForm); + } + } + // Implement View Level Access if (!$user->authorise('core.admin')) { $groups = implode(',', $user->getAuthorisedViewLevels()); $query->where('a.access IN (' . $groups . ')'); + $query->where('a.access_form IN (' . $groups . ')'); } // Filter by published state diff --git a/administrator/components/com_fields/views/field/tmpl/edit.php b/administrator/components/com_fields/views/field/tmpl/edit.php index 991273c74cbdf..798367ee41038 100644 --- a/administrator/components/com_fields/views/field/tmpl/edit.php +++ b/administrator/components/com_fields/views/field/tmpl/edit.php @@ -74,6 +74,7 @@ 'group_id', 'assigned_cat_ids', 'access', + 'access_form', 'language', 'note', ) diff --git a/administrator/components/com_fields/views/fields/tmpl/default.php b/administrator/components/com_fields/views/fields/tmpl/default.php index 34fda9402c41c..709bf2c4333ac 100644 --- a/administrator/components/com_fields/views/fields/tmpl/default.php +++ b/administrator/components/com_fields/views/fields/tmpl/default.php @@ -75,6 +75,9 @@ + + + @@ -166,6 +169,9 @@ escape($item->access_level); ?> + + escape($item->access_form_level); ?> + diff --git a/administrator/components/com_fields/views/group/tmpl/edit.php b/administrator/components/com_fields/views/group/tmpl/edit.php index e00f223e871c5..3adf745241edd 100644 --- a/administrator/components/com_fields/views/group/tmpl/edit.php +++ b/administrator/components/com_fields/views/group/tmpl/edit.php @@ -49,6 +49,7 @@ 'enabled', ), 'access', + 'access_form', 'language', 'note', ) diff --git a/administrator/components/com_fields/views/groups/tmpl/default.php b/administrator/components/com_fields/views/groups/tmpl/default.php index 65da48e8832c9..d9d2d592b8b89 100644 --- a/administrator/components/com_fields/views/groups/tmpl/default.php +++ b/administrator/components/com_fields/views/groups/tmpl/default.php @@ -73,6 +73,9 @@ + + + @@ -145,6 +148,9 @@ escape($item->access_level); ?> + + escape($item->access_form_level); ?> + diff --git a/administrator/language/en-GB/en-GB.ini b/administrator/language/en-GB/en-GB.ini index b4078de2faa2d..64c0a07cc610e 100644 --- a/administrator/language/en-GB/en-GB.ini +++ b/administrator/language/en-GB/en-GB.ini @@ -184,6 +184,8 @@ JERROR_SAVE_FAILED="Could not save data. Error: %s" JFIELD_ACCESS_DESC="The access level group that is allowed to view this item." JFIELD_ACCESS_LABEL="Access" +JFIELD_ACCESSFORM_DESC="The access level group that is allowed to display this item on forms." +JFIELD_ACCESSFORM_LABEL="Access Form" JFIELD_ALIAS_DESC="The Alias will be used in the SEF URL. Leave this blank and Joomla will fill in a default value from the title. This value will depend on the SEO settings (Global Configuration->Site).
Using Unicode will produce UTF-8 aliases. You may also enter manually any UTF-8 character. Spaces and some forbidden characters will be changed to hyphens.
When using default transliteration it will produce an alias in lower case and with dashes instead of spaces. You may enter the Alias manually. Use lowercase letters and hyphens (-). No spaces or underscores are allowed. Default value will be a date and time if the title is typed in non-latin letters." JFIELD_ALIAS_LABEL="Alias" JFIELD_ALIAS_PLACEHOLDER="Auto-generate from title" @@ -628,6 +630,9 @@ JGLOBAL_WIDTH="Width" JGRID_HEADING_ACCESS="Access" JGRID_HEADING_ACCESS_ASC="Access ascending" JGRID_HEADING_ACCESS_DESC="Access descending" +JGRID_HEADING_ACCESS_FORM="Access Form" +JGRID_HEADING_ACCESS_FORM_ASC="Access Form ascending" +JGRID_HEADING_ACCESS_FORM_DESC="Access Form descending" JGRID_HEADING_CREATED_BY="Created by" JGRID_HEADING_ID="ID" JGRID_HEADING_ID_ASC="ID ascending" @@ -875,6 +880,7 @@ JOPTION_ORDER_FIRST="Order First" JOPTION_ORDER_LAST="Order Last" JOPTION_REQUIRED="Required" JOPTION_SELECT_ACCESS="- Select Access -" +JOPTION_SELECT_ACCESS_FORM="- Select Access Form -" JOPTION_SELECT_AUTHOR_ALIAS="- Select Author Alias -" JOPTION_SELECT_AUTHOR_ALIASES="- Select Author Aliases -" JOPTION_SELECT_AUTHOR="- Select Author -" diff --git a/components/com_users/controllers/profile.php b/components/com_users/controllers/profile.php index 594ee0b404ac6..3175402a60221 100644 --- a/components/com_users/controllers/profile.php +++ b/components/com_users/controllers/profile.php @@ -113,6 +113,14 @@ public function save() return false; } + // Send an object which can be modified through the plugin event + $objData = (object) $requestData; + $app->triggerEvent( + 'onContentNormaliseRequestData', + array('com_users.user', $objData, $form) + ); + $requestData = (array) $objData; + // Validate the posted data. $data = $model->validate($form, $requestData); diff --git a/installation/sql/mysql/joomla.sql b/installation/sql/mysql/joomla.sql index 72dddaa5bb888..39f888ab61fef 100644 --- a/installation/sql/mysql/joomla.sql +++ b/installation/sql/mysql/joomla.sql @@ -683,6 +683,7 @@ CREATE TABLE IF NOT EXISTS `#__fields` ( `modified_time` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `modified_by` int(10) unsigned NOT NULL DEFAULT '0', `access` int(11) NOT NULL DEFAULT '1', + `access_form` int(11) NOT NULL DEFAULT '1', PRIMARY KEY (`id`), KEY `idx_checkout` (`checked_out`), KEY `idx_state` (`state`), @@ -728,6 +729,7 @@ CREATE TABLE IF NOT EXISTS `#__fields_groups` ( `modified` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', `modified_by` int(10) unsigned NOT NULL DEFAULT '0', `access` int(11) NOT NULL DEFAULT '1', + `access_form` int(11) NOT NULL DEFAULT '1', PRIMARY KEY (`id`), KEY `idx_checkout` (`checked_out`), KEY `idx_state` (`state`), diff --git a/installation/sql/postgresql/joomla.sql b/installation/sql/postgresql/joomla.sql index d5686a2e6f61c..f9c1ee56b0e5c 100644 --- a/installation/sql/postgresql/joomla.sql +++ b/installation/sql/postgresql/joomla.sql @@ -697,6 +697,7 @@ CREATE TABLE "#__fields" ( "modified_time" timestamp without time zone DEFAULT '1970-01-01 00:00:00' NOT NULL, "modified_by" bigint DEFAULT 0 NOT NULL, "access" bigint DEFAULT 0 NOT NULL, + "access_form" bigint DEFAULT 0 NOT NULL, PRIMARY KEY ("id") ); CREATE INDEX "#__fields_idx_checked_out" ON "#__fields" ("checked_out"); diff --git a/installation/sql/sqlazure/joomla.sql b/installation/sql/sqlazure/joomla.sql index 49e643241b005..0d5a17d62a916 100644 --- a/installation/sql/sqlazure/joomla.sql +++ b/installation/sql/sqlazure/joomla.sql @@ -912,6 +912,7 @@ CREATE TABLE "#__fields" ( "modified_time" datetime2(0) NOT NULL DEFAULT '1900-01-01 00:00:00', "modified_by" bigint NOT NULL DEFAULT 0, "access" int NOT NULL DEFAULT 1, + "access_form" int NOT NULL DEFAULT 1, CONSTRAINT "PK_#__fields_id" PRIMARY KEY CLUSTERED( "id" ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON diff --git a/libraries/src/MVC/Controller/FormController.php b/libraries/src/MVC/Controller/FormController.php index 5052dedd5c560..27d532a5d00b8 100644 --- a/libraries/src/MVC/Controller/FormController.php +++ b/libraries/src/MVC/Controller/FormController.php @@ -694,6 +694,14 @@ public function save($key = null, $urlVar = null) return false; } + // Send an object which can be modified through the plugin event + $objData = (object) $data; + $app->triggerEvent( + 'onContentNormaliseRequestData', + array($this->option . '.' . $this->context, $objData, $form) + ); + $data = (array) $objData; + // Test whether the data is valid. $validData = $model->validate($form, $data); diff --git a/plugins/system/fields/fields.php b/plugins/system/fields/fields.php index ba1e1396b3009..746f689f5eedb 100644 --- a/plugins/system/fields/fields.php +++ b/plugins/system/fields/fields.php @@ -9,6 +9,7 @@ defined('_JEXEC') or die; +use Joomla\CMS\Form\Form; use Joomla\Registry\Registry; use Joomla\CMS\Factory; use Joomla\CMS\Language\Multilanguage; @@ -30,6 +31,38 @@ class PlgSystemFields extends JPlugin */ protected $autoloadLanguage = true; + /** + * Normalizes the request data. + * + * @param string $context The context + * @param object $data The object + * @param Form $form The form + * + * @return void + * + * @since __DEPLOY_VERSION__ + */ + public function onContentNormaliseRequestData($context, $data, Form $form) + { + if (!FieldsHelper::extract($context, $data)) + { + return true; + } + + // Loop over all fields + foreach ($form->getGroup('com_fields') as $field) + { + // Make sure the data object has an entry + if (isset($data->com_fields[$field->fieldname])) + { + continue; + } + + // Set a default value for the field + $data->com_fields[$field->fieldname] = false; + } + } + /** * The save event. * @@ -45,7 +78,7 @@ class PlgSystemFields extends JPlugin public function onContentAfterSave($context, $item, $isNew, $data = array()) { // Check if data is an array and the item has an id - if (!is_array($data) || empty($item->id)) + if (!is_array($data) || empty($item->id) || empty($data['com_fields'])) { return true; } @@ -78,17 +111,28 @@ public function onContentAfterSave($context, $item, $isNew, $data = array()) return true; } - // Get the fields data - $fieldsData = !empty($data['com_fields']) ? $data['com_fields'] : array(); - // Loading the model $model = JModelLegacy::getInstance('Field', 'FieldsModel', array('ignore_request' => true)); // Loop over the fields foreach ($fields as $field) { - // Determine the value if it is available from the data - $value = key_exists($field->name, $fieldsData) ? $fieldsData[$field->name] : null; + // Determine the value if it is (un)available from the data + if (key_exists($field->name, $data['com_fields'])) + { + $value = $data['com_fields'][$field->name] === false ? null : $data['com_fields'][$field->name]; + } + // Field not available on form, use stored value + else + { + $value = $field->rawvalue; + } + + // If no value set (empty) remove value from database + if (is_array($value) ? !count($value) : !strlen($value)) + { + $value = null; + } // JSON encode value for complex fields if (is_array($value) && (count($value, COUNT_NORMAL) !== count($value, COUNT_RECURSIVE) || !count(array_filter(array_keys($value), 'is_numeric'))))