From 0ba2a0e8cf8c1b8585cd49b23ecc6e3f1c51054b Mon Sep 17 00:00:00 2001 From: Llewellyn van der Merwe Date: Tue, 27 Mar 2018 11:57:16 +0200 Subject: [PATCH] Added validation rules resolve gh-254. Removed empty sql files. Improved the field area. --- README.md | 14 +- admin/README.txt | 14 +- admin/access.xml | 24 +- admin/assets/css/validation_rule.css | 27 + admin/assets/css/validation_rules.css | 27 + .../{getsnippets.png => get_snippets.png} | Bin .../assets/images/icons/help_document_add.png | Bin 26419 -> 0 bytes .../assets/images/icons/validation_rules.png | Bin 0 -> 18323 bytes admin/compiler/joomla_3/JFormRule.php | 25 +- admin/controller.php | 1 + admin/controllers/ajax.json.php | 118 +++ admin/controllers/validation_rule.php | 326 +++++++ admin/controllers/validation_rules.php | 111 +++ admin/helpers/compiler/a_Get.php | 38 + admin/helpers/compiler/c_Fields.php | 19 + admin/helpers/compiler/f_Infusion.php | 15 + admin/helpers/componentbuilder.php | 67 +- .../en-GB/en-GB.com_componentbuilder.ini | 228 ++++- .../en-GB/en-GB.com_componentbuilder.sys.ini | 31 +- .../extends_formrule_above.php | 41 + .../extends_formrule_fullwidth.php | 48 + .../validation_rule/extends_formrule_left.php | 54 ++ .../extends_formrule_right.php | 54 ++ admin/layouts/validation_rule/index.html | 1 + admin/layouts/validation_rule/publishing.php | 58 ++ admin/layouts/validation_rule/publlshing.php | 60 ++ admin/models/ajax.php | 174 +++- admin/models/componentbuilder.php | 10 +- .../models/fields/existingvalidationrules.php | 165 ++++ admin/models/forms/custom_code.js | 6 +- admin/models/forms/field.js | 26 +- admin/models/forms/validation_rule.js | 109 +++ admin/models/forms/validation_rule.xml | 160 ++++ admin/models/import_joomla_components.php | 138 +-- admin/models/validation_rule.php | 887 ++++++++++++++++++ admin/models/validation_rules.php | 377 ++++++++ admin/sql/install.mysql.utf8.sql | 32 +- admin/sql/uninstall.mysql.utf8.sql | 1 + admin/sql/updates/mysql/2.5.0.sql | 1 - admin/sql/updates/mysql/2.5.4.sql | 1 - admin/sql/updates/mysql/2.6.0.sql | 1 - admin/sql/updates/mysql/2.6.1.sql | 1 - admin/sql/updates/mysql/2.6.10.sql | 1 - admin/sql/updates/mysql/2.6.15.sql | 1 - admin/sql/updates/mysql/2.6.2.sql | 1 - admin/sql/updates/mysql/2.6.7.sql | 1 - admin/sql/updates/mysql/2.6.8.sql | 1 - admin/sql/updates/mysql/2.7.0.sql | 27 + admin/tables/validation_rule.php | 351 +++++++ admin/views/custom_code/view.html.php | 3 + admin/views/field/tmpl/edit.php | 10 +- admin/views/layout/view.html.php | 11 +- admin/views/template/view.html.php | 11 +- admin/views/validation_rule/submitbutton.js | 49 + admin/views/validation_rule/tmpl/edit.php | 156 +++ admin/views/validation_rule/tmpl/index.html | 1 + admin/views/validation_rule/view.html.php | 218 +++++ admin/views/validation_rules/index.html | 1 + admin/views/validation_rules/tmpl/default.php | 99 ++ .../tmpl/default_batch_body.php | 32 + .../tmpl/default_batch_footer.php | 37 + .../validation_rules/tmpl/default_body.php | 111 +++ .../validation_rules/tmpl/default_foot.php | 32 + .../validation_rules/tmpl/default_head.php | 64 ++ .../validation_rules/tmpl/default_toolbar.php | 59 ++ admin/views/validation_rules/tmpl/index.html | 1 + admin/views/validation_rules/view.html.php | 253 +++++ componentbuilder.xml | 7 +- componentbuilder_update_server.xml | 170 +--- script.php | 129 ++- site/helpers/componentbuilder.php | 9 +- .../en-GB/en-GB.com_componentbuilder.ini | 3 + 72 files changed, 5002 insertions(+), 337 deletions(-) create mode 100644 admin/assets/css/validation_rule.css create mode 100644 admin/assets/css/validation_rules.css rename admin/assets/images/icons/{getsnippets.png => get_snippets.png} (100%) delete mode 100644 admin/assets/images/icons/help_document_add.png create mode 100644 admin/assets/images/icons/validation_rules.png create mode 100644 admin/controllers/validation_rule.php create mode 100644 admin/controllers/validation_rules.php create mode 100644 admin/layouts/validation_rule/extends_formrule_above.php create mode 100644 admin/layouts/validation_rule/extends_formrule_fullwidth.php create mode 100644 admin/layouts/validation_rule/extends_formrule_left.php create mode 100644 admin/layouts/validation_rule/extends_formrule_right.php create mode 100644 admin/layouts/validation_rule/index.html create mode 100644 admin/layouts/validation_rule/publishing.php create mode 100644 admin/layouts/validation_rule/publlshing.php create mode 100644 admin/models/fields/existingvalidationrules.php create mode 100644 admin/models/forms/validation_rule.js create mode 100644 admin/models/forms/validation_rule.xml create mode 100644 admin/models/validation_rule.php create mode 100644 admin/models/validation_rules.php delete mode 100644 admin/sql/updates/mysql/2.5.0.sql delete mode 100644 admin/sql/updates/mysql/2.5.4.sql delete mode 100644 admin/sql/updates/mysql/2.6.0.sql delete mode 100644 admin/sql/updates/mysql/2.6.1.sql delete mode 100644 admin/sql/updates/mysql/2.6.10.sql delete mode 100644 admin/sql/updates/mysql/2.6.15.sql delete mode 100644 admin/sql/updates/mysql/2.6.2.sql delete mode 100644 admin/sql/updates/mysql/2.6.7.sql delete mode 100644 admin/sql/updates/mysql/2.6.8.sql create mode 100644 admin/sql/updates/mysql/2.7.0.sql create mode 100644 admin/tables/validation_rule.php create mode 100644 admin/views/validation_rule/submitbutton.js create mode 100644 admin/views/validation_rule/tmpl/edit.php create mode 100644 admin/views/validation_rule/tmpl/index.html create mode 100644 admin/views/validation_rule/view.html.php create mode 100644 admin/views/validation_rules/index.html create mode 100644 admin/views/validation_rules/tmpl/default.php create mode 100644 admin/views/validation_rules/tmpl/default_batch_body.php create mode 100644 admin/views/validation_rules/tmpl/default_batch_footer.php create mode 100644 admin/views/validation_rules/tmpl/default_body.php create mode 100644 admin/views/validation_rules/tmpl/default_foot.php create mode 100644 admin/views/validation_rules/tmpl/default_head.php create mode 100644 admin/views/validation_rules/tmpl/default_toolbar.php create mode 100644 admin/views/validation_rules/tmpl/index.html create mode 100644 admin/views/validation_rules/view.html.php diff --git a/README.md b/README.md index 88a9b8b6c..e951e6ed0 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ The Component Builder for [Joomla](https://extensions.joomla.org/extension/compo Whether you're a seasoned [Joomla](https://extensions.joomla.org/extension/component-builder/) developer, or have just started, Component Builder will safe you lots of time and money. A real must have! -You can install it quite easily and with no limitations. On [github](https://github.com/vdm-io/Joomla-Component-Builder/releases) is the latest release (2.7.0) with **ALL** its features and **ALL** concepts totally open-source and free! +You can install it quite easily and with no limitations. On [github](https://github.com/vdm-io/Joomla-Component-Builder/releases) is the latest release (2.7.1) with **ALL** its features and **ALL** concepts totally open-source and free! > Watch Quick Build of a Hello World component in [JCB on Youtube](https://www.youtube.com/watch?v=IQfsLYIeblk&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&index=45) @@ -126,14 +126,14 @@ Component Builder is mapped as a component in itself on my local development env + *Author*: [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com) + *Name*: [Component Builder](http://joomlacomponentbuilder.com) + *First Build*: 30th April, 2015 -+ *Last Build*: 24th March, 2018 -+ *Version*: 2.7.0 ++ *Last Build*: 27th March, 2018 ++ *Version*: 2.7.1 + *Copyright*: Copyright (C) 2015. All Rights Reserved + *License*: GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html -+ *Line count*: **186317** -+ *Field count*: **994** -+ *File count*: **1173** -+ *Folder count*: **189** ++ *Line count*: **190902** ++ *Field count*: **1007** ++ *File count*: **1196** ++ *Folder count*: **193** > This **component** was build with a Joomla [Automated Component Builder](http://joomlacomponentbuilder.com). > Developed by [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com) diff --git a/admin/README.txt b/admin/README.txt index 88a9b8b6c..e951e6ed0 100644 --- a/admin/README.txt +++ b/admin/README.txt @@ -9,7 +9,7 @@ The Component Builder for [Joomla](https://extensions.joomla.org/extension/compo Whether you're a seasoned [Joomla](https://extensions.joomla.org/extension/component-builder/) developer, or have just started, Component Builder will safe you lots of time and money. A real must have! -You can install it quite easily and with no limitations. On [github](https://github.com/vdm-io/Joomla-Component-Builder/releases) is the latest release (2.7.0) with **ALL** its features and **ALL** concepts totally open-source and free! +You can install it quite easily and with no limitations. On [github](https://github.com/vdm-io/Joomla-Component-Builder/releases) is the latest release (2.7.1) with **ALL** its features and **ALL** concepts totally open-source and free! > Watch Quick Build of a Hello World component in [JCB on Youtube](https://www.youtube.com/watch?v=IQfsLYIeblk&list=PLQRGFI8XZ_wtGvPQZWBfDzzlERLQgpMRE&index=45) @@ -126,14 +126,14 @@ Component Builder is mapped as a component in itself on my local development env + *Author*: [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com) + *Name*: [Component Builder](http://joomlacomponentbuilder.com) + *First Build*: 30th April, 2015 -+ *Last Build*: 24th March, 2018 -+ *Version*: 2.7.0 ++ *Last Build*: 27th March, 2018 ++ *Version*: 2.7.1 + *Copyright*: Copyright (C) 2015. All Rights Reserved + *License*: GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html -+ *Line count*: **186317** -+ *Field count*: **994** -+ *File count*: **1173** -+ *Folder count*: **189** ++ *Line count*: **190902** ++ *Field count*: **1007** ++ *File count*: **1196** ++ *Folder count*: **193** > This **component** was build with a Joomla [Automated Component Builder](http://joomlacomponentbuilder.com). > Developed by [Llewellyn van der Merwe](mailto:llewellyn@joomlacomponentbuilder.com) diff --git a/admin/access.xml b/admin/access.xml index a4f8040d9..1e03fea0e 100644 --- a/admin/access.xml +++ b/admin/access.xml @@ -212,15 +212,16 @@ + + - @@ -358,6 +359,18 @@ + + + + + + + + + + + +
@@ -455,6 +468,15 @@
+
+ + + + + + + +
diff --git a/admin/assets/css/validation_rule.css b/admin/assets/css/validation_rule.css new file mode 100644 index 000000000..eea5d6f4b --- /dev/null +++ b/admin/assets/css/validation_rule.css @@ -0,0 +1,27 @@ +/*--------------------------------------------------------------------------------------------------------| www.vdm.io |------/ + __ __ _ _____ _ _ __ __ _ _ _ + \ \ / / | | | __ \ | | | | | \/ | | | | | | | + \ \ / /_ _ ___| |_ | | | | _____ _____| | ___ _ __ _ __ ___ ___ _ __ | |_ | \ / | ___| |_| |__ ___ __| | + \ \/ / _` / __| __| | | | |/ _ \ \ / / _ \ |/ _ \| '_ \| '_ ` _ \ / _ \ '_ \| __| | |\/| |/ _ \ __| '_ \ / _ \ / _` | + \ / (_| \__ \ |_ | |__| | __/\ V / __/ | (_) | |_) | | | | | | __/ | | | |_ | | | | __/ |_| | | | (_) | (_| | + \/ \__,_|___/\__| |_____/ \___| \_/ \___|_|\___/| .__/|_| |_| |_|\___|_| |_|\__| |_| |_|\___|\__|_| |_|\___/ \__,_| + | | + |_| +/-------------------------------------------------------------------------------------------------------------------------------/ + + @version 2.7.x + @created 30th April, 2015 + @package Component Builder + @subpackage validation_rule.css + @author Llewellyn van der Merwe + @github Joomla Component Builder + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + + Builds Complex Joomla Components + +/-----------------------------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/css/validation_rules.css b/admin/assets/css/validation_rules.css new file mode 100644 index 000000000..f91e4a23d --- /dev/null +++ b/admin/assets/css/validation_rules.css @@ -0,0 +1,27 @@ +/*--------------------------------------------------------------------------------------------------------| www.vdm.io |------/ + __ __ _ _____ _ _ __ __ _ _ _ + \ \ / / | | | __ \ | | | | | \/ | | | | | | | + \ \ / /_ _ ___| |_ | | | | _____ _____| | ___ _ __ _ __ ___ ___ _ __ | |_ | \ / | ___| |_| |__ ___ __| | + \ \/ / _` / __| __| | | | |/ _ \ \ / / _ \ |/ _ \| '_ \| '_ ` _ \ / _ \ '_ \| __| | |\/| |/ _ \ __| '_ \ / _ \ / _` | + \ / (_| \__ \ |_ | |__| | __/\ V / __/ | (_) | |_) | | | | | | __/ | | | |_ | | | | __/ |_| | | | (_) | (_| | + \/ \__,_|___/\__| |_____/ \___| \_/ \___|_|\___/| .__/|_| |_| |_|\___|_| |_|\__| |_| |_|\___|\__|_| |_|\___/ \__,_| + | | + |_| +/-------------------------------------------------------------------------------------------------------------------------------/ + + @version 2.7.x + @created 30th April, 2015 + @package Component Builder + @subpackage validation_rules.css + @author Llewellyn van der Merwe + @github Joomla Component Builder + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + + Builds Complex Joomla Components + +/-----------------------------------------------------------------------------------------------------------------------------*/ + +/* CSS Document */ + + diff --git a/admin/assets/images/icons/getsnippets.png b/admin/assets/images/icons/get_snippets.png similarity index 100% rename from admin/assets/images/icons/getsnippets.png rename to admin/assets/images/icons/get_snippets.png diff --git a/admin/assets/images/icons/help_document_add.png b/admin/assets/images/icons/help_document_add.png deleted file mode 100644 index 52889e109bc68a4e088155d58ba75169f99fef4f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26419 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 diff --git a/admin/assets/images/icons/validation_rules.png b/admin/assets/images/icons/validation_rules.png new file mode 100644 index 0000000000000000000000000000000000000000..2969d2caeb14f453213254fd2de09d8c3959f297 GIT binary patch literal 18323 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 ###BOM### -// No direct access to this file -defined('_JEXEC') or die('Restricted access'); +namespace Joomla\CMS\Form\Rule; + +defined('JPATH_PLATFORM') or die; + +use Joomla\CMS\Form\Form; +use Joomla\CMS\Form\FormRule; +use Joomla\Registry\Registry; -// import Joomla formrule library -jimport('joomla.form.formrule'); /** - * Form Rule class for the Joomla Framework. + * Form Rule (###Name###) class for the Joomla Platform. */ -class JFormRule###Name### extends JFormRule -{ - /** - * The regular expression. - * - * @access protected - * @var string - * @since 2.5 - */ - protected $regex = '^[^_]+$'; +class JFormRule###Name### extends FormRule +{###VALIDATION_RULE_METHODS### } diff --git a/admin/controller.php b/admin/controller.php index 8a041d7e1..a85e2b6d1 100644 --- a/admin/controller.php +++ b/admin/controller.php @@ -117,6 +117,7 @@ class ComponentbuilderController extends JControllerLegacy 'custom_code' => 'custom_codes', 'library' => 'libraries', 'snippet' => 'snippets', + 'validation_rule' => 'validation_rules', 'field' => 'fields', 'fieldtype' => 'fieldtypes', 'language_translation' => 'language_translations', diff --git a/admin/controllers/ajax.json.php b/admin/controllers/ajax.json.php index c52ef1b82..64e91ff4c 100644 --- a/admin/controllers/ajax.json.php +++ b/admin/controllers/ajax.json.php @@ -60,6 +60,9 @@ class ComponentbuilderControllerAjax extends JControllerLegacy $this->registerTask('getDynamicValues', 'ajax'); $this->registerTask('checkFunctionName', 'ajax'); $this->registerTask('usedin', 'ajax'); + $this->registerTask('getExistingValidationRuleCode', 'ajax'); + $this->registerTask('getValidationRulesTable', 'ajax'); + $this->registerTask('checkRuleName', 'ajax'); $this->registerTask('fieldOptions', 'ajax'); $this->registerTask('snippetDetails', 'ajax'); $this->registerTask('setSnippetGithub', 'ajax'); @@ -771,6 +774,121 @@ class ComponentbuilderControllerAjax extends JControllerLegacy } } break; + case 'getExistingValidationRuleCode': + try + { + $returnRaw = $jinput->get('raw', false, 'BOOLEAN'); + $nameValue = $jinput->get('name', NULL, 'WORD'); + if($nameValue && $user->id != 0) + { + $result = $this->getModel('ajax')->getExistingValidationRuleCode($nameValue); + } + else + { + $result = false; + } + if($callback = $jinput->get('callback', null, 'CMD')) + { + echo $callback . "(".json_encode($result).");"; + } + elseif($returnRaw) + { + echo json_encode($result); + } + else + { + echo "(".json_encode($result).");"; + } + } + catch(Exception $e) + { + if($callback = $jinput->get('callback', null, 'CMD')) + { + echo $callback."(".json_encode($e).");"; + } + else + { + echo "(".json_encode($e).");"; + } + } + break; + case 'getValidationRulesTable': + try + { + $returnRaw = $jinput->get('raw', false, 'BOOLEAN'); + $idValue = $jinput->get('id', NULL, 'INT'); + if($idValue && $user->id != 0) + { + $result = $this->getModel('ajax')->getValidationRulesTable($idValue); + } + else + { + $result = false; + } + if($callback = $jinput->get('callback', null, 'CMD')) + { + echo $callback . "(".json_encode($result).");"; + } + elseif($returnRaw) + { + echo json_encode($result); + } + else + { + echo "(".json_encode($result).");"; + } + } + catch(Exception $e) + { + if($callback = $jinput->get('callback', null, 'CMD')) + { + echo $callback."(".json_encode($e).");"; + } + else + { + echo "(".json_encode($e).");"; + } + } + break; + case 'checkRuleName': + try + { + $returnRaw = $jinput->get('raw', false, 'BOOLEAN'); + $nameValue = $jinput->get('name', NULL, 'STRING'); + $idValue = $jinput->get('id', NULL, 'INT'); + if($nameValue && $idValue && $user->id != 0) + { + $result = $this->getModel('ajax')->checkRuleName($nameValue, $idValue); + } + else + { + $result = false; + } + if($callback = $jinput->get('callback', null, 'CMD')) + { + echo $callback . "(".json_encode($result).");"; + } + elseif($returnRaw) + { + echo json_encode($result); + } + else + { + echo "(".json_encode($result).");"; + } + } + catch(Exception $e) + { + if($callback = $jinput->get('callback', null, 'CMD')) + { + echo $callback."(".json_encode($e).");"; + } + else + { + echo "(".json_encode($e).");"; + } + } + break; case 'fieldOptions': try { diff --git a/admin/controllers/validation_rule.php b/admin/controllers/validation_rule.php new file mode 100644 index 000000000..457bbeb79 --- /dev/null +++ b/admin/controllers/validation_rule.php @@ -0,0 +1,326 @@ + + @github Joomla Component Builder + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + + Builds Complex Joomla Components + +/-----------------------------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import Joomla controllerform library +jimport('joomla.application.component.controllerform'); + +/** + * Validation_rule Controller + */ +class ComponentbuilderControllerValidation_rule extends JControllerForm +{ + /** + * Current or most recently performed task. + * + * @var string + * @since 12.2 + * @note Replaces _task. + */ + protected $task; + + public function __construct($config = array()) + { + $this->view_list = 'Validation_rules'; // safeguard for setting the return view listing to the main view. + parent::__construct($config); + } + + /** + * Method override to check if you can add a new record. + * + * @param array $data An array of input data. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowAdd($data = array()) + { + // Access check. + $access = JFactory::getUser()->authorise('validation_rule.access', 'com_componentbuilder'); + if (!$access) + { + return false; + } + // In the absense of better information, revert to the component permissions. + return JFactory::getUser()->authorise('validation_rule.create', $this->option); + } + + /** + * Method override to check if you can edit an existing record. + * + * @param array $data An array of input data. + * @param string $key The name of the key for the primary key. + * + * @return boolean + * + * @since 1.6 + */ + protected function allowEdit($data = array(), $key = 'id') + { + // get user object. + $user = JFactory::getUser(); + // get record id. + $recordId = (int) isset($data[$key]) ? $data[$key] : 0; + + + // Access check. + $access = ($user->authorise('validation_rule.access', 'com_componentbuilder.validation_rule.' . (int) $recordId) && $user->authorise('validation_rule.access', 'com_componentbuilder')); + if (!$access) + { + return false; + } + + if ($recordId) + { + // The record has been set. Check the record permissions. + $permission = $user->authorise('validation_rule.edit', 'com_componentbuilder.validation_rule.' . (int) $recordId); + if (!$permission) + { + if ($user->authorise('validation_rule.edit.own', 'com_componentbuilder.validation_rule.' . $recordId)) + { + // Now test the owner is the user. + $ownerId = (int) isset($data['created_by']) ? $data['created_by'] : 0; + if (empty($ownerId)) + { + // Need to do a lookup from the model. + $record = $this->getModel()->getItem($recordId); + + if (empty($record)) + { + return false; + } + $ownerId = $record->created_by; + } + + // If the owner matches 'me' then allow. + if ($ownerId == $user->id) + { + if ($user->authorise('validation_rule.edit.own', 'com_componentbuilder')) + { + return true; + } + } + } + return false; + } + } + // Since there is no permission, revert to the component permissions. + return $user->authorise('validation_rule.edit', $this->option); + } + + /** + * Gets the URL arguments to append to an item redirect. + * + * @param integer $recordId The primary key id for the item. + * @param string $urlVar The name of the URL variable for the id. + * + * @return string The arguments to append to the redirect URL. + * + * @since 12.2 + */ + protected function getRedirectToItemAppend($recordId = null, $urlVar = 'id') + { + $tmpl = $this->input->get('tmpl'); + $layout = $this->input->get('layout', 'edit', 'string'); + + $ref = $this->input->get('ref', 0, 'string'); + $refid = $this->input->get('refid', 0, 'int'); + + // Setup redirect info. + + $append = ''; + + if ($refid) + { + $append .= '&ref='.(string)$ref.'&refid='.(int)$refid; + } + elseif ($ref) + { + $append .= '&ref='.(string)$ref; + } + + if ($tmpl) + { + $append .= '&tmpl=' . $tmpl; + } + + if ($layout) + { + $append .= '&layout=' . $layout; + } + + if ($recordId) + { + $append .= '&' . $urlVar . '=' . $recordId; + } + + return $append; + } + + /** + * Method to run batch operations. + * + * @param object $model The model. + * + * @return boolean True if successful, false otherwise and internal error is set. + * + * @since 2.5 + */ + public function batch($model = null) + { + JSession::checkToken() or jexit(JText::_('JINVALID_TOKEN')); + + // Set the model + $model = $this->getModel('Validation_rule', '', array()); + + // Preset the redirect + $this->setRedirect(JRoute::_('index.php?option=com_componentbuilder&view=validation_rules' . $this->getRedirectToListAppend(), false)); + + return parent::batch($model); + } + + /** + * Method to cancel an edit. + * + * @param string $key The name of the primary key of the URL variable. + * + * @return boolean True if access level checks pass, false otherwise. + * + * @since 12.2 + */ + public function cancel($key = null) + { + // get the referal details + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + $cancel = parent::cancel($key); + + if ($cancel) + { + if ($this->refid) + { + $redirect = '&view='.(string)$this->ref.'&layout=edit&id='.(int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref) + { + $redirect = '&view='.(string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + } + else + { + // Redirect to the items screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . '&view=' . $this->view_list, false + ) + ); + } + return $cancel; + } + + /** + * Method to save a record. + * + * @param string $key The name of the primary key of the URL variable. + * @param string $urlVar The name of the URL variable if different from the primary key (sometimes required to avoid router collisions). + * + * @return boolean True if successful, false otherwise. + * + * @since 12.2 + */ + public function save($key = null, $urlVar = null) + { + // get the referal details + $this->ref = $this->input->get('ref', 0, 'word'); + $this->refid = $this->input->get('refid', 0, 'int'); + + if ($this->ref || $this->refid) + { + // to make sure the item is checkedin on redirect + $this->task = 'save'; + } + + $saved = parent::save($key, $urlVar); + + if ($this->refid && $saved) + { + $redirect = '&view='.(string)$this->ref.'&layout=edit&id='.(int)$this->refid; + + // Redirect to the item screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + elseif ($this->ref && $saved) + { + $redirect = '&view='.(string)$this->ref; + + // Redirect to the list screen. + $this->setRedirect( + JRoute::_( + 'index.php?option=' . $this->option . $redirect, false + ) + ); + } + return $saved; + } + + /** + * Function that allows child controller access to model data + * after the data has been saved. + * + * @param JModel &$model The data model object. + * @param array $validData The validated data. + * + * @return void + * + * @since 11.1 + */ + protected function postSaveHook(JModelLegacy $model, $validData = array()) + { + return; + } + +} diff --git a/admin/controllers/validation_rules.php b/admin/controllers/validation_rules.php new file mode 100644 index 000000000..868d1971f --- /dev/null +++ b/admin/controllers/validation_rules.php @@ -0,0 +1,111 @@ + + @github Joomla Component Builder + @copyright Copyright (C) 2015. All Rights Reserved + @license GNU/GPL Version 2 or later - http://www.gnu.org/licenses/gpl-2.0.html + + Builds Complex Joomla Components + +/-----------------------------------------------------------------------------------------------------------------------------*/ + +// No direct access to this file +defined('_JEXEC') or die('Restricted access'); + +// import Joomla controlleradmin library +jimport('joomla.application.component.controlleradmin'); + +/** + * Validation_rules Controller + */ +class ComponentbuilderControllerValidation_rules extends JControllerAdmin +{ + protected $text_prefix = 'COM_COMPONENTBUILDER_VALIDATION_RULES'; + /** + * Proxy for getModel. + * @since 2.5 + */ + public function getModel($name = 'Validation_rule', $prefix = 'ComponentbuilderModel', $config = array()) + { + $model = parent::getModel($name, $prefix, array('ignore_request' => true)); + + return $model; + } + + public function exportData() + { + // Check for request forgeries + JSession::checkToken() or die(JText::_('JINVALID_TOKEN')); + // check if export is allowed for this user. + $user = JFactory::getUser(); + if ($user->authorise('validation_rule.export', 'com_componentbuilder') && $user->authorise('core.export', 'com_componentbuilder')) + { + // Get the input + $input = JFactory::getApplication()->input; + $pks = $input->post->get('cid', array(), 'array'); + // Sanitize the input + JArrayHelper::toInteger($pks); + // Get the model + $model = $this->getModel('Validation_rules'); + // get the data to export + $data = $model->getExportData($pks); + if (ComponentbuilderHelper::checkArray($data)) + { + // now set the data to the spreadsheet + $date = JFactory::getDate(); + ComponentbuilderHelper::xls($data,'Validation_rules_'.$date->format('jS_F_Y'),'Validation rules exported ('.$date->format('jS F, Y').')','validation rules'); + } + } + // Redirect to the list screen with error. + $message = JText::_('COM_COMPONENTBUILDER_EXPORT_FAILED'); + $this->setRedirect(JRoute::_('index.php?option=com_componentbuilder&view=validation_rules', false), $message, 'error'); + return; + } + + + public function importData() + { + // Check for request forgeries + JSession::checkToken() or die(JText::_('JINVALID_TOKEN')); + // check if import is allowed for this user. + $user = JFactory::getUser(); + if ($user->authorise('validation_rule.import', 'com_componentbuilder') && $user->authorise('core.import', 'com_componentbuilder')) + { + // Get the import model + $model = $this->getModel('Validation_rules'); + // get the headers to import + $headers = $model->getExImPortHeaders(); + if (ComponentbuilderHelper::checkObject($headers)) + { + // Load headers to session. + $session = JFactory::getSession(); + $headers = json_encode($headers); + $session->set('validation_rule_VDM_IMPORTHEADERS', $headers); + $session->set('backto_VDM_IMPORT', 'validation_rules'); + $session->set('dataType_VDM_IMPORTINTO', 'validation_rule'); + // Redirect to import view. + $message = JText::_('COM_COMPONENTBUILDER_IMPORT_SELECT_FILE_FOR_VALIDATION_RULES'); + $this->setRedirect(JRoute::_('index.php?option=com_componentbuilder&view=import', false), $message); + return; + } + } + // Redirect to the list screen with error. + $message = JText::_('COM_COMPONENTBUILDER_IMPORT_FAILED'); + $this->setRedirect(JRoute::_('index.php?option=com_componentbuilder&view=validation_rules', false), $message, 'error'); + return; + } +} diff --git a/admin/helpers/compiler/a_Get.php b/admin/helpers/compiler/a_Get.php index 272312b1d..fe2615b9c 100644 --- a/admin/helpers/compiler/a_Get.php +++ b/admin/helpers/compiler/a_Get.php @@ -414,6 +414,13 @@ class Get */ public $sqlTweak = array(); + /** + * The validation rules that should be added + * + * @var array + */ + public $validationRules = array(); + /** * The admin views data array * @@ -2082,6 +2089,37 @@ class Get // load the values form params $field->xml = $this->setDynamicValues(json_decode($field->xml)); + + // check if we have validate (validation rule set) + $validationRule = ComponentbuilderHelper::getBetween($field->xml, 'validate="', '"'); + if (ComponentbuilderHelper::checkString($validationRule)) + { + // make sure it is lowercase + $validationRule = ComponentbuilderHelper::safeString($validationRule); + // make sure it is not already set + if (!isset($this->validationRules[$validationRule])) + { + // get joomla core validation names + if ($coreValidationRules = ComponentbuilderHelper::getExistingValidationRuleNames(true)) + { + // make sure this rule is not a core validation rule + if (!in_array($validationRule, $coreValidationRules)) + { + // get the class methods for this rule if it exists + if ($this->validationRules[$validationRule] = ComponentbuilderHelper::getVar('validation_rule', $validationRule, 'name','php')) + { + // open and set the validation rule + $this->validationRules[$validationRule] = $this->setDynamicValues(base64_decode($this->validationRules[$validationRule])); + } + else + { + // set the notice that this validation rule is custom and was not found + + } + } + } + } + } // load the type values form type params $field->properties = (isset($field->properties) && ComponentbuilderHelper::checkJson($field->properties)) ? json_decode($field->properties, true) : null; diff --git a/admin/helpers/compiler/c_Fields.php b/admin/helpers/compiler/c_Fields.php index ba18df700..e532a7dbf 100644 --- a/admin/helpers/compiler/c_Fields.php +++ b/admin/helpers/compiler/c_Fields.php @@ -2083,6 +2083,15 @@ class Fields extends Structure // get the actual field name $xmlValue = $this->setPlaceholders($name, $placeholders); } + elseif ($property['name'] === 'validate') + { + // check if we have validate (validation rule set) + $xmlValue = ComponentbuilderHelper::getBetween($field['settings']->xml, 'validate="', '"'); + if (ComponentbuilderHelper::checkString($xmlValue)) + { + $xmlValue = ComponentbuilderHelper::safeString($xmlValue); + } + } elseif ($property['name'] === 'extension' || $property['name'] === 'directory' || $property['name'] === 'formsource') { $xmlValue = ComponentbuilderHelper::getBetween($field['settings']->xml, $property['name'] . '="', '"'); @@ -2290,6 +2299,16 @@ class Fields extends Structure { $fieldAttributes['display'] = $display; } + // make sure validation is set if found (even it not part of field properties) + if (!isset($fieldAttributes['validate'])) + { + // check if we have validate (validation rule set) + $validationRule = ComponentbuilderHelper::getBetween($field['settings']->xml, 'validate="', '"'); + if (ComponentbuilderHelper::checkString($validationRule)) + { + $fieldAttributes['validate'] = ComponentbuilderHelper::safeString($validationRule); + } + } } } return $fieldAttributes; diff --git a/admin/helpers/compiler/f_Infusion.php b/admin/helpers/compiler/f_Infusion.php index 576b0aad6..706092265 100644 --- a/admin/helpers/compiler/f_Infusion.php +++ b/admin/helpers/compiler/f_Infusion.php @@ -815,6 +815,21 @@ class Infusion extends Interpretation // set the module $this->fileContentDynamic['ajax']['###AJAX_SITE_MODEL_METHODS###'] = $this->setAjaxModelMethods('site'); } + + // build the validation rules + if (isset($this->validationRules) && ComponentbuilderHelper::checkArray($this->validationRules)) + { + foreach ($this->validationRules as $rule => $_php) + { + // setup rule file + $target = array('admin' => 'a_rule_zi'); + $this->buildDynamique($target, 'rule', $rule); + // set the JFormRule Name + $this->fileContentDynamic['a_rule_zi_'.$rule]['###Name###'] = ucfirst($rule); + // set the JFormRule PHP + $this->fileContentDynamic['a_rule_zi_'.$rule]['###VALIDATION_RULE_METHODS###'] = PHP_EOL . $_php; + } + } // run the second run if needed if (isset($this->secondRunAdmin) && ComponentbuilderHelper::checkArray($this->secondRunAdmin)) diff --git a/admin/helpers/componentbuilder.php b/admin/helpers/componentbuilder.php index e845bcddb..040f3f76b 100644 --- a/admin/helpers/componentbuilder.php +++ b/admin/helpers/componentbuilder.php @@ -157,6 +157,60 @@ abstract class ComponentbuilderHelper } return $object; } + + /* + * Get the Array of Existing Validation Rule Names + * + * @return array + */ + public static function getExistingValidationRuleNames($lowercase = false) + { + if (!$items = self::get('_existing_validation_rules_VDM', null)) + { + // load the file class + jimport('joomla.filesystem.file'); + jimport('joomla.filesystem.folder'); + // set the path to the form validation rules + $path = JPATH_LIBRARIES . '/src/Form/Rule'; + // check if the path exist + if (!JFolder::exists($path)) + { + return false; + } + // we must first store the current working directory + $joomla = getcwd(); + // go to that folder + chdir($path); + // load all the files in this path + $items = JFolder::files('.', '\.php', true, true); + // change back to Joomla working directory + chdir($joomla); + // make sure we have an array + if (!self::checkArray($items)) + { + return false; + } + // remove the Rule.php from the name + $items = array_map( function ($name) { + return str_replace(array('./','Rule.php'), '', $name); + }, $items); + // store the names for next run + self::set('_existing_validation_rules_VDM', json_encode($items)); + } + // make sure it is no longer json + if (self::checkJson($items)) + { + $items = json_decode($items, true); + } + // check if the names should be all lowercase + if ($lowercase) + { + $items = array_map( function($item) { + return strtolower($item); + }, $items); + } + return $items; + } public static function getDynamicScripts($type, $fieldName = false) { @@ -1626,10 +1680,13 @@ abstract class ComponentbuilderHelper { $result = $db->loadObject(); $properties = json_decode($result->properties,true); - $field = array('values' => " '