diff --git a/.hg/branchheads.cache b/.hg/branchheads.cache index fe9dad67c..c4d37d1a3 100644 --- a/.hg/branchheads.cache +++ b/.hg/branchheads.cache @@ -1,4 +1,4 @@ -a74fcab8266a49dcbf5434b89eff7182dfbd51c6 7298 +441679d8f08a562de20bd2d3e327652fa2eb2ded 7307 528aeb46da83bbc059a81856f22080d3afcbafcc 0.6.9-development b54558ec1152000af342afa1a8e8d71e410fd308 newuserinterface 2653dd0a3d797fbe612f7b80af3f99dfa70a4d28 webApi2 @@ -8,13 +8,13 @@ b5bf0195a342f5fb90a2503d4e5eba6c71360769 Iteration18 33d15992195a243b446fafcf706979eac97dfa9e functionalTests 134cda65e593500869641853e41156b2a78207b6 redbean3.0 b4e083129e977178f041ca290573c872a450e576 metaLabelsFix -d6e01659170f9168b66be46f4af97344b59710df candidate +e7d2aedb30634a5d3fba1161b6fd8e5124e6deec candidate e9d5ddaea0c3793d04774624508acd6089564cee profileavatar f4205aa2a8c5a5087af5ce73021e1d07d00dc123 stable 23f0d4d012bbfb8973027966a75406ae1b294beb 0.7.4-development 7dfbccadc5256db4139488e151a948e0cbb01c08 submitbugs -290f7e88f2f3db6c5d242cfcfabe1eae7bd15827 securityUI -7fd27b036654a9ec87d632568037cd3121f787a3 apiRefactoring +171ecad82f5a9c8fe6eb0bf10744051d51f9b63b optimizeFileImport +bb6dcb66116c3f8714f2018465f174f008ffff8b evalResolutionFix 0f917bee0cf77000526a9a2ab8876c2a8ae9fcbb commandLineUnitTests 95688e21aa93e1f0160044e32d2dfca3b27776f7 Mobile 2f550bd49e7bec96f20900471e9456ccaa6c6d07 classbeanrefactor @@ -22,18 +22,18 @@ f4205aa2a8c5a5087af5ce73021e1d07d00dc123 stable 24890a9d5293d9c2b7165d151c66851dd098a9cb newAttributeTypes a5e74086a840265b63c4dd92cf59583cc0fcd2fc imapEncode 4c99b60f2effb4ea6b8e51d7bd66433254e14e41 SavedSearch -6f24c0b152dcd3bc9b03ed5814d5c2d368e948af developmenttools +b42b9711a2aa1bbd30fd0e6c9a3c4adbe2b24474 Themes 6016a237a40cae0d6512d51bd55009a824e22111 0.7.60 dfcdaf8ee99e5b3afc482efc1645993ec9e26dc6 memcacheImprovements 130854662b9687a821c60f0f89e54cc9a00c58cb additionalInstallationCheck -82ebff8069bf3b13b01ac3cf92d1e142d441cb56 release +e41a29c6bc8d59785a31e0324d96cdad11906898 release 5f0c06ebc1bfb2b783f0e45bebd479941e304cdf 0.7.0-development a5626156edc87b42054d306069e4235777ff0336 zurmoUpgrade 02a08af4aac4bda448afdfbeea160b92e86e662d i18nv2 a837f842ea961f5ea6cc2481dc63a8763c3c4e87 export 99cdd170c057c283307ead10f04bcda8768eb8e4 fix_email_export_header 7ea98584caac52a5aefcc781a6ea552d11aeaa33 listviewcolumnselection -b42b9711a2aa1bbd30fd0e6c9a3c4adbe2b24474 Themes +6f24c0b152dcd3bc9b03ed5814d5c2d368e948af developmenttools 55a5c3f8fde482ef3e37d431edc95566e454a33f composeAndSendEmail 254cf51f34a2764918b32e6bc2cb24eb0b2e0da0 MarketingList a1a2184f2b39a9cd27bb40ec2de64a4cb9104c47 i18nExtras @@ -48,18 +48,18 @@ f2fdd9ab8b7e2014550a42c5ad1fd44a70f0b548 TwoAttributesSorting 02f5d279c5b86e92ff4d61ca5f8b3cda38d48ed5 webApi c0b9a0a3bd3f73347e35609620707160536e3c01 kanbanBoard f00a70da7758e5cb37a7e1aeba48d1b1bae2f45d unittestargv -4c16182014bafe9525561a5c692cde6918cd23f2 reports +88120704755816e08e25d189824fcd300e037d3d logoFileUpload 17f626025b769f42a55967e3e69f80c2f895d263 products -f075150ad2a79f2ded8bc1702e75d027dc312746 Spanish d442b631e0320eb0bcefe6c1d7808146e2832b84 socialitems 8b6013834c1db7c7693da6be8066b330c8dfdb87 l10nServerUtil -171ecad82f5a9c8fe6eb0bf10744051d51f9b63b optimizeFileImport +290f7e88f2f3db6c5d242cfcfabe1eae7bd15827 securityUI 7023f8a5874c056f09b4657f57e03653841b42b2 emailPasswords 933761bbd4afdeaeeac7b31c3cb72442d7fb9a30 improvements 233f19fe5348ffee6697402b1a0f0f3b5da5e341 convoandmissions 8b27201a9531e166bad8ae588f8a4eab04567cf1 messageSourceComponent 8a16935be6f25f173e73b2c1184545fee8c53a48 userinterface2 -bc3acfe2bc1f24774836e0c062cb522f7127874c IE +4467ae59f4ac2efdcad4d9b5775cbdde0802487b performance3 +276b8a1f96c1c3d40e0b9a52eb0653440a687ecd probabilityRule 6932aade11190a08a3710c14cb4272de98ee9681 &IssueFix 480f523b88a5bc9bba5f544361a29db93e2cbd8e limitStringLengthInDb 0b65e6649e31418135864267756053b366bb0197 cliInstallationFix @@ -68,7 +68,7 @@ a3f8a7d24ffc53ac9b910cb84406640cfa73edb4 globalsearchlist ab023c7160585ea3e0e4dc22d0993b7b1d91af6e stabilizingselenium f90dcf1f4c7d8bb30d0a2142652e7583fd2e986f subqueryfix 618a88277622a6f765cf65ce3985865a638f0c75 user_default_timezone_global -a74fcab8266a49dcbf5434b89eff7182dfbd51c6 default +441679d8f08a562de20bd2d3e327652fa2eb2ded default 2e440b45637a04c6ef9ca74d2f1d018a03eec244 multibyte-label 090661edd1811c5288282e568d4bf1646a2dc87b globalsearch b600995a49ffd972c74c00252fb562f1735ca50d copyAddressAndCloning @@ -77,13 +77,13 @@ fe65a71608dde103bed28c9fc5413a834aaf433a OptimizeDemoDataInstallation 7e3f4cdee31efcacc25dc2adead14e8a2bf620fc testMakeErrorsData dc87114b543cef2e514caaf53158a0cec6c16ba7 apiMergeWithDefault cbe3d8bd7bb9330cdce8032993dc2126676b4d05 additionalApiFeatures -b485e0a0f583e08f8551677729fccb7591472ecd bugFixing +282966349e4abf1868d3a4b345531bdbe68df041 bugFixing cbd2ce866432bfab51a36dcb183ffd839c6dcf55 0.7.2-development 06c6c4d7bff588aa140a1f2634fe72317ad365b9 conversationsv2 59f5787db30191cb4d866d997c60f1a388003b65 installationTest -88120704755816e08e25d189824fcd300e037d3d logoFileUpload +4c16182014bafe9525561a5c692cde6918cd23f2 reports 0787dfecc87555afad2130e9a9bb20f5a792b317 fix_story_46344681 -bb6dcb66116c3f8714f2018465f174f008ffff8b evalResolutionFix +7fd27b036654a9ec87d632568037cd3121f787a3 apiRefactoring 85c9fa1642c1fe95bd667eeebc05f5e245eccf8e performance2 c378f2d409109c0351e614de97565ba5a75e88a4 workflow_security 02dcdd9b6d122d707bf7ae1d095cc390362879d3 newTranslateCalls @@ -100,9 +100,9 @@ bb0adb9e0c5759a69c6183c22d3050df3f17902c mapping 3d2d78c7e16a931c789c571c978049352a82a0d8 jobsAndNotifications 26615b2519a4a9da4dfeeaa60ee1e71bb5019bf5 animations 9b400573ef09b68f458aca3795fb82c9f6d11f68 UI Lab -276b8a1f96c1c3d40e0b9a52eb0653440a687ecd probabilityRule +bc3acfe2bc1f24774836e0c062cb522f7127874c IE a0c0a6986f1e133fd831ea141ab943fb95c878a3 emailNotificationsRefactor bffddc52734347d49731ea659b5f119cf2f22ae2 logoFix fb9dce13d2066c7ce8e11fea944888f7002728d6 databasePort -4467ae59f4ac2efdcad4d9b5775cbdde0802487b performance3 +f075150ad2a79f2ded8bc1702e75d027dc312746 Spanish 1cc6420a42456d6e5ab3cb06739e205beba34091 current_user_timezone diff --git a/.hg/dirstate b/.hg/dirstate index 85887dd96..8029e71a6 100644 Binary files a/.hg/dirstate and b/.hg/dirstate differ diff --git a/.hg/store/00changelog.d b/.hg/store/00changelog.d index 51e703821..ad1cfa2f5 100644 Binary files a/.hg/store/00changelog.d and b/.hg/store/00changelog.d differ diff --git a/.hg/store/00changelog.i b/.hg/store/00changelog.i index eac517c83..eb7aed9bc 100644 Binary files a/.hg/store/00changelog.i and b/.hg/store/00changelog.i differ diff --git a/.hg/store/00manifest.d b/.hg/store/00manifest.d index 2570b8ad1..71c1a21e6 100644 Binary files a/.hg/store/00manifest.d and b/.hg/store/00manifest.d differ diff --git a/.hg/store/00manifest.i b/.hg/store/00manifest.i index db94f6724..1a5b6ceda 100644 Binary files a/.hg/store/00manifest.i and b/.hg/store/00manifest.i differ diff --git a/.hg/store/data/.hgtags.i b/.hg/store/data/.hgtags.i index 55308fa3c..2ecb5f9c8 100644 Binary files a/.hg/store/data/.hgtags.i and b/.hg/store/data/.hgtags.i differ diff --git a/.hg/store/data/app/protected/core/elements/_model_element.php.i b/.hg/store/data/app/protected/core/elements/_model_element.php.i index c1a402e29..b2f9d8379 100644 Binary files a/.hg/store/data/app/protected/core/elements/_model_element.php.i and b/.hg/store/data/app/protected/core/elements/_model_element.php.i differ diff --git a/.hg/store/data/app/protected/core/utils/_modal_list_link_provider.php.i b/.hg/store/data/app/protected/core/utils/_modal_list_link_provider.php.i index ba923cf3a..d2978d009 100644 Binary files a/.hg/store/data/app/protected/core/utils/_modal_list_link_provider.php.i and b/.hg/store/data/app/protected/core/utils/_modal_list_link_provider.php.i differ diff --git a/.hg/store/data/app/protected/core/utils/_select_from_related_edit_modal_list_link_provider.php.i b/.hg/store/data/app/protected/core/utils/_select_from_related_edit_modal_list_link_provider.php.i index d66196082..2cf02f8bf 100644 Binary files a/.hg/store/data/app/protected/core/utils/_select_from_related_edit_modal_list_link_provider.php.i and b/.hg/store/data/app/protected/core/utils/_select_from_related_edit_modal_list_link_provider.php.i differ diff --git a/.hg/store/data/app/protected/core/views/_edit_and_details_view.php.i b/.hg/store/data/app/protected/core/views/_edit_and_details_view.php.i index 6830649f4..97fb894d4 100644 Binary files a/.hg/store/data/app/protected/core/views/_edit_and_details_view.php.i and b/.hg/store/data/app/protected/core/views/_edit_and_details_view.php.i differ diff --git a/.hg/store/data/app/protected/core/views/_edit_view.php.i b/.hg/store/data/app/protected/core/views/_edit_view.php.i index 30437cd9c..d4e83fcc2 100644 Binary files a/.hg/store/data/app/protected/core/views/_edit_view.php.i and b/.hg/store/data/app/protected/core/views/_edit_view.php.i differ diff --git a/.hg/store/data/app/protected/core/views/_modal_config_edit_view.php.i b/.hg/store/data/app/protected/core/views/_modal_config_edit_view.php.i index 6073b3263..63c628622 100644 Binary files a/.hg/store/data/app/protected/core/views/_modal_config_edit_view.php.i and b/.hg/store/data/app/protected/core/views/_modal_config_edit_view.php.i differ diff --git a/.hg/store/data/app/protected/modules/accounts/controllers/_default_controller.php.i b/.hg/store/data/app/protected/modules/accounts/controllers/_default_controller.php.i index 67b3be59e..73af69d2f 100644 Binary files a/.hg/store/data/app/protected/modules/accounts/controllers/_default_controller.php.i and b/.hg/store/data/app/protected/modules/accounts/controllers/_default_controller.php.i differ diff --git a/.hg/store/data/app/protected/modules/contacts/controllers/_default_controller.php.i b/.hg/store/data/app/protected/modules/contacts/controllers/_default_controller.php.i index d2538be2b..4705efc8e 100644 Binary files a/.hg/store/data/app/protected/modules/contacts/controllers/_default_controller.php.i and b/.hg/store/data/app/protected/modules/contacts/controllers/_default_controller.php.i differ diff --git a/.hg/store/data/app/protected/modules/contacts/controllers/_variable_contact_state_controller.php.i b/.hg/store/data/app/protected/modules/contacts/controllers/_variable_contact_state_controller.php.i index 00d741029..cb402083f 100644 Binary files a/.hg/store/data/app/protected/modules/contacts/controllers/_variable_contact_state_controller.php.i and b/.hg/store/data/app/protected/modules/contacts/controllers/_variable_contact_state_controller.php.i differ diff --git a/.hg/store/data/app/protected/modules/leads/controllers/_default_controller.php.i b/.hg/store/data/app/protected/modules/leads/controllers/_default_controller.php.i index 760725287..b38a81579 100644 Binary files a/.hg/store/data/app/protected/modules/leads/controllers/_default_controller.php.i and b/.hg/store/data/app/protected/modules/leads/controllers/_default_controller.php.i differ diff --git a/.hg/store/data/app/protected/modules/marketing_lists/controllers/_default_controller.php.i b/.hg/store/data/app/protected/modules/marketing_lists/controllers/_default_controller.php.i index 8cae90232..37f526f42 100644 Binary files a/.hg/store/data/app/protected/modules/marketing_lists/controllers/_default_controller.php.i and b/.hg/store/data/app/protected/modules/marketing_lists/controllers/_default_controller.php.i differ diff --git a/.hg/store/data/app/protected/modules/opportunities/controllers/_default_controller.php.i b/.hg/store/data/app/protected/modules/opportunities/controllers/_default_controller.php.i index ee561f4f3..2cbe18a42 100644 Binary files a/.hg/store/data/app/protected/modules/opportunities/controllers/_default_controller.php.i and b/.hg/store/data/app/protected/modules/opportunities/controllers/_default_controller.php.i differ diff --git a/.hg/store/data/app/protected/modules/users/controllers/_default_controller.php.i b/.hg/store/data/app/protected/modules/users/controllers/_default_controller.php.i index 0748b3e86..ad5d13cce 100644 Binary files a/.hg/store/data/app/protected/modules/users/controllers/_default_controller.php.i and b/.hg/store/data/app/protected/modules/users/controllers/_default_controller.php.i differ diff --git a/.hg/store/data/app/version.php.i b/.hg/store/data/app/version.php.i index beec76f93..d418853e1 100644 Binary files a/.hg/store/data/app/version.php.i and b/.hg/store/data/app/version.php.i differ diff --git a/.hg/store/undo b/.hg/store/undo index 66cb759ee..928b025c0 100644 Binary files a/.hg/store/undo and b/.hg/store/undo differ diff --git a/.hg/undo.desc b/.hg/undo.desc index cfdfa59ca..1b2e802b9 100644 --- a/.hg/undo.desc +++ b/.hg/undo.desc @@ -1,3 +1,3 @@ -7252 +7299 pull https://bitbucket.org/zurmo/zurmo diff --git a/.hg/undo.dirstate b/.hg/undo.dirstate index fd4fae8ad..85887dd96 100644 Binary files a/.hg/undo.dirstate and b/.hg/undo.dirstate differ diff --git a/.hgtags b/.hgtags index d58c419c8..04a2ae807 100644 --- a/.hgtags +++ b/.hgtags @@ -308,3 +308,8 @@ cfdf73acd7e1bd4597dbac7fedcb7c22d4c0bd9a stable 67bf4e0edaaafe62d51b4174009cf93180eb3d93 unstable cfdf73acd7e1bd4597dbac7fedcb7c22d4c0bd9a unstable cfdf73acd7e1bd4597dbac7fedcb7c22d4c0bd9a 1.5.15 +cfdf73acd7e1bd4597dbac7fedcb7c22d4c0bd9a stable +8c4d5d4461197bf3f2ab5f67b40b00405d9fb28d stable +cfdf73acd7e1bd4597dbac7fedcb7c22d4c0bd9a unstable +8c4d5d4461197bf3f2ab5f67b40b00405d9fb28d unstable +8c4d5d4461197bf3f2ab5f67b40b00405d9fb28d 1.6.00 diff --git a/app/protected/core/adapters/columns/IntegerListViewColumnAdapter.php b/app/protected/core/adapters/columns/IntegerListViewColumnAdapter.php index cc694964c..de6022ee6 100644 --- a/app/protected/core/adapters/columns/IntegerListViewColumnAdapter.php +++ b/app/protected/core/adapters/columns/IntegerListViewColumnAdapter.php @@ -39,9 +39,23 @@ class IntegerListViewColumnAdapter extends TextListViewColumnAdapter public function renderGridViewData() { return array( - 'type' => 'Number', 'name' => $this->attribute, + 'value' => 'IntegerListViewColumnAdapter::renderNonEditableStatically($data, "' . $this->attribute . '")', + 'type' => 'raw', ); } + + public static function renderNonEditableStatically($model, $attribute) + { + if($model instanceof RedBeanModel && $model->isAttributeFormattedAsProbability($attribute)) + { + $resolvedValue = NumberUtil::divisionForZero($model->{$attribute}, 100); + return Yii::app()->numberFormatter->formatPercentage($resolvedValue); + } + else + { + return $model->{$attribute}; + } + } } ?> \ No newline at end of file diff --git a/app/protected/core/components/DataColumn.php b/app/protected/core/components/DataColumn.php index 58d8a66df..c729aab67 100644 --- a/app/protected/core/components/DataColumn.php +++ b/app/protected/core/components/DataColumn.php @@ -41,6 +41,45 @@ */ class DataColumn extends CDataColumn { + /** + * Renders the header cell content. + * This method will render a link that can trigger the sorting if the column is sortable. + */ + protected function renderHeaderCellContent() + { + if($this->grid->enableSorting && $this->sortable && $this->name !== null) + { + echo $this->grid->dataProvider->getSort()->link($this->name, $this->header, array('class' => 'sort-link')); + } + elseif($this->name!==null && $this->header===null) + { + if($this->grid->dataProvider instanceof CActiveDataProvider) + { + echo CHtml::encode($this->grid->dataProvider->model->getAttributeLabel($this->name)); + } + elseif($this->grid->dataProvider instanceof RedBeanModelDataProvider) + { + $modelClassName = $this->grid->dataProvider->getModelClassName(); + if($modelClassName::isAnAttribute($this->name)) + { + echo CHtml::encode($modelClassName::getAnAttributeLabel($this->name)); + } + else + { + echo CHtml::encode($this->name); + } + } + else + { + echo CHtml::encode($this->name); + } + } + else + { + echo parent::renderHeaderCellContent(); + } + } + /** * Override to add in offset information * (non-PHPdoc) diff --git a/app/protected/core/elements/IntegerElement.php b/app/protected/core/elements/IntegerElement.php index b755dfe27..89bdedb1e 100644 --- a/app/protected/core/elements/IntegerElement.php +++ b/app/protected/core/elements/IntegerElement.php @@ -35,9 +35,26 @@ ********************************************************************************/ /** - * TODO + * Class for displaying an integer attribute value in the user interface */ class IntegerElement extends TextElement { + /** + * Renders the attribute from the model. + * Directs Url to open in new page. + * @return The element's content. + */ + protected function renderControlNonEditable() + { + if($this->model instanceof RedBeanModel && $this->model->isAttributeFormattedAsProbability($this->attribute)) + { + $resolvedValue = NumberUtil::divisionForZero($this->model->{$this->attribute}, 100); + return Yii::app()->numberFormatter->formatPercentage($resolvedValue); + } + else + { + return parent::renderControlNonEditable(); + } + } } ?> diff --git a/app/protected/core/elements/ModelElement.php b/app/protected/core/elements/ModelElement.php index 8c23ca362..41704ccb2 100644 --- a/app/protected/core/elements/ModelElement.php +++ b/app/protected/core/elements/ModelElement.php @@ -156,7 +156,7 @@ function clearIdFromAutoCompleteField(value, id) 'source' => Yii::app()->createUrl($this->resolveModuleId() . '/' . $this->getAutoCompleteControllerId() . '/' . static::$autoCompleteActionId), 'options' => array( - 'select' => 'js:function(event, ui){ jQuery("#' . $idInputName . '").val(ui.item["id"]);}', // Not Coding Standard + 'select' => 'js:function(event, ui){ jQuery("#' . $idInputName . '").val(ui.item["id"]).trigger("change");}', // Not Coding Standard 'appendTo' => 'js:$("#' . $this->getIdForTextField() . '").parent().parent()', 'search' => 'js: function(event, ui) { diff --git a/app/protected/core/elements/actions/CopyLinkActionElement.php b/app/protected/core/elements/actions/CopyLinkActionElement.php new file mode 100644 index 000000000..75895974d --- /dev/null +++ b/app/protected/core/elements/actions/CopyLinkActionElement.php @@ -0,0 +1,63 @@ + $this->modelId); + if (Yii::app()->request->getParam('redirectUrl') != null) + { + $params = array_merge($params, array('redirectUrl' => Yii::app()->request->getParam('redirectUrl'))); + } + elseif ($this->getRedirectUrl() != null) + { + $params = array_merge($params, array('redirectUrl' => $this->getRedirectUrl())); + } + return Yii::app()->createUrl($this->moduleId . '/' . $this->controllerId . '/copy/', $params); + } + } +?> \ No newline at end of file diff --git a/app/protected/core/elements/assets/Modal.js b/app/protected/core/elements/assets/Modal.js index a3337ff1b..708c19904 100644 --- a/app/protected/core/elements/assets/Modal.js +++ b/app/protected/core/elements/assets/Modal.js @@ -2,7 +2,7 @@ function transferModalValues(dialogId, data) { $.each(data, function(sourceFieldId, value) { - $('#'+ sourceFieldId).val(value); + $('#'+ sourceFieldId).val(value).trigger('change'); }); $(dialogId).dialog("close"); } \ No newline at end of file diff --git a/app/protected/core/models/RedBeanModel.php b/app/protected/core/models/RedBeanModel.php index 94a044c08..9a78f3780 100644 --- a/app/protected/core/models/RedBeanModel.php +++ b/app/protected/core/models/RedBeanModel.php @@ -123,6 +123,7 @@ abstract class RedBeanModel extends BeanModel implements Serializable protected $isValidating = false; protected $isSaving = false; protected $isNewModel = false; + protected $isCopied = false; /** * Can this model be saved when save is called from a related model? True if it can, false if it cannot. @@ -144,6 +145,7 @@ abstract class RedBeanModel extends BeanModel implements Serializable 'defaultCalculatedDate' => 'RedBeanModelDefaultCalculatedDateValidator', 'readOnly' => 'RedBeanModelReadOnlyValidator', 'dateTimeDefault' => 'RedBeanModelDateTimeDefaultValueValidator', + 'probability' => 'RedBeanModelProbabilityValidator', ); /** @@ -1475,6 +1477,25 @@ public function isAttributeReadOnly($attributeName) return false; } + /** + * Returns true if the attribute is formattted as probability + */ + public function isAttributeFormattedAsProbability($attributeName) + { + assert("\$this->isAttribute(\"$attributeName\")"); + foreach ($this->validators as $validator) + { + if ($validator instanceof RedBeanModelProbabilityValidator) + { + if (in_array($attributeName, $validator->attributes, true)) + { + return true; + } + } + } + return false; + } + /** * @param boolean $attributeName * @return true/false whether the attributeName specified, it is allowed to be set externally even though it is @@ -3001,5 +3022,21 @@ public static function getSortAttributesByAttribute($attribute) { return array($attribute); } + + /** + * Utilized by copy mechanism, helps elements, views, understand the model better before the new model is saved. + */ + public function setIsCopied() + { + $this->isCopied = true; + } + + /** + * @return bool + */ + public function isCopied() + { + return $this->isCopied; + } } ?> diff --git a/app/protected/core/utils/ModelDataProviderUtil.php b/app/protected/core/utils/ModelDataProviderUtil.php index 06e46aa4e..1359fbb8e 100644 --- a/app/protected/core/utils/ModelDataProviderUtil.php +++ b/app/protected/core/utils/ModelDataProviderUtil.php @@ -270,10 +270,20 @@ protected static function processMetadataClause($modelClassName, $clausePosition ArrayUtil::getArrayValue($clauseInformation, 'modifierType')); $builder->resolveJoinsAndBuildWhere( $clauseInformation['operatorType'], $clauseInformation['value'], $clausePosition, - $where, $onTableAliasName); + $where, $onTableAliasName, + static::resolveResolveSubqueryValue($clauseInformation)); } } + protected static function resolveResolveSubqueryValue(Array $clauseInformation) + { + if(null == $resolveAsSubquery = ArrayUtil::getArrayValue($clauseInformation, 'resolveAsSubquery')) + { + return false; + } + return $resolveAsSubquery; + } + /** * @param string $modelClassName * @param integer $clausePosition diff --git a/app/protected/core/utils/ModelWhereAndJoinBuilder.php b/app/protected/core/utils/ModelWhereAndJoinBuilder.php index 86688238f..ad9acd950 100644 --- a/app/protected/core/utils/ModelWhereAndJoinBuilder.php +++ b/app/protected/core/utils/ModelWhereAndJoinBuilder.php @@ -59,13 +59,15 @@ public function __construct(RedBeanModelAttributeToDataProviderAdapter * @param $clausePosition * @param $where * @param null | string $onTableAliasName + * @param boolean | $resolveAsSubquery */ public function resolveJoinsAndBuildWhere($operatorType, $value, & $clausePosition, & $where, - $onTableAliasName = null) + $onTableAliasName = null, $resolveAsSubquery = false) { assert('is_string($operatorType)'); assert('is_array($where)'); assert('is_string($onTableAliasName) || $onTableAliasName == null'); + assert('is_bool($resolveAsSubquery)'); if (!$this->modelAttributeToDataProviderAdapter->hasRelatedAttribute()) { $tableAliasName = $this->resolveJoins($onTableAliasName, @@ -83,7 +85,7 @@ public function resolveJoinsAndBuildWhere($operatorType, $value, & $clausePositi else { $this->buildJoinAndWhereForRelatedAttribute($operatorType, $value, $clausePosition, $where, - $onTableAliasName); + $onTableAliasName, $resolveAsSubquery); } } @@ -96,12 +98,13 @@ public function resolveJoinsAndBuildWhere($operatorType, $value, & $clausePositi * @param null | string $onTableAliasName */ protected function buildJoinAndWhereForRelatedAttribute($operatorType, $value, $whereKey, &$where, - $onTableAliasName = null) + $onTableAliasName = null, $resolveAsSubquery = false) { assert('is_string($operatorType)'); assert('is_int($whereKey)'); assert('is_array($where)'); assert('is_string($onTableAliasName) || $onTableAliasName == null'); + assert('is_bool($resolveAsSubquery)'); $relationWhere = array(); if ($this->modelAttributeToDataProviderAdapter->getRelationType() == RedBeanModel::MANY_MANY) { @@ -111,11 +114,12 @@ protected function buildJoinAndWhereForRelatedAttribute($operatorType, $value, $ $relationAttributeTableAliasName, $this->modelAttributeToDataProviderAdapter->resolveManyToManyColumnName()); } - elseif ($this->modelAttributeToDataProviderAdapter->isRelatedAttributeRelation() && + elseif (($this->modelAttributeToDataProviderAdapter->isRelatedAttributeRelation() && $this->modelAttributeToDataProviderAdapter->getRelatedAttributeRelationType() == RedBeanModel::HAS_MANY) + || $resolveAsSubquery) { - $relationAttributeTableAliasName = $this->resolveOnlyAttributeJoins($onTableAliasName, - ModelDataProviderUtil::resolveCanUseFromJoins($onTableAliasName)); + $relationAttributeTableAliasName = $this->resolveRelationAttributeTableAliasNameForResolveSubquery( + $onTableAliasName, $resolveAsSubquery); $this->buildWhereForRelatedAttributeThatIsItselfAHasManyRelation( $relationAttributeTableAliasName, $operatorType, @@ -137,6 +141,34 @@ protected function buildJoinAndWhereForRelatedAttribute($operatorType, $value, $ $where[$whereKey] = strtr('1', $relationWhere); } + protected function resolveRelationAttributeTableAliasNameForResolveSubquery($onTableAliasName, $resolveAsSubquery = false) + { + assert('is_string($onTableAliasName) || $onTableAliasName == null'); + assert('is_bool($resolveAsSubquery)'); + if($resolveAsSubquery) + { + return $this->resolveRelationAttributeTableAliasNameForResolveSubqueryAsTrue($onTableAliasName); + } + else + { + return $this->resolveOnlyAttributeJoins($onTableAliasName, + ModelDataProviderUtil::resolveCanUseFromJoins($onTableAliasName)); + } + } + + protected function resolveRelationAttributeTableAliasNameForResolveSubqueryAsTrue($onTableAliasName) + { + assert('is_string($onTableAliasName) || $onTableAliasName == null'); + if($onTableAliasName == null) + { + return $this->modelAttributeToDataProviderAdapter->getModelTableName(); + } + else + { + return $onTableAliasName; + } + } + /** * Given a related attribute on a model and the related attribute is a has_many relation, * build the join and where sql string information. @@ -156,27 +188,32 @@ protected function buildWhereForRelatedAttributeThatIsItselfAHasManyRelation($on { assert('is_string($onTableAliasName)'); assert('is_string($operatorType)'); - assert('(is_array($value) && count($value) > 0) || is_string($value)'); + assert('(is_array($value) && count($value) > 0) || is_string($value) || is_int($value)'); assert('is_array($where)'); assert('is_int($whereKey)'); + if(!$this->modelAttributeToDataProviderAdapter->getRelatedAttributeRelationType() == RedBeanModel::HAS_MANY) + { + throw new NotSupportedException(); + } $relationAttributeModelClassName = $this->modelAttributeToDataProviderAdapter->getRelatedAttributeRelationModelClassName(); if ($relationAttributeModelClassName != 'CustomFieldValue' && $operatorType != 'allOf') { - //Until we can add a third parameter to the search adapter metadata, we have to assume we are only doing - //this for CustomFieldValue searches. Below we have $joinColumnName, since we don't have any other way - //of ascertaining this information for now. - - //Once we add allOf, need to have an alternative sub-query - //below that uses if/else logic to compare count against how many possibles. then return 1 or 0. - throw new NotSupportedException('modelClassName: ' . $relationAttributeModelClassName . - ' operatorType: ' . $operatorType); + $modelClassName = $this->modelAttributeToDataProviderAdapter->getRelationModelClassName(); + $relationAttributeTableName = RedBeanModel::getTableName($modelClassName); + $joinColumnName = $modelClassName::getColumnNameByAttribute( + $this->modelAttributeToDataProviderAdapter->getRelatedAttribute()); + $relationColumnName = self::resolveForeignKey(RedBeanModel::getTableName( + $this->modelAttributeToDataProviderAdapter->getModelClassName())); } - $relationAttributeTableName = RedBeanModel::getTableName($relationAttributeModelClassName); - $tableAliasName = $relationAttributeTableName; - $joinColumnName = 'value'; - $relationColumnName = self::resolveForeignKey(RedBeanModel::getTableName( - $this->modelAttributeToDataProviderAdapter-> + else + { + $relationAttributeTableName = RedBeanModel::getTableName($relationAttributeModelClassName); + $joinColumnName = 'value'; + $relationColumnName = self::resolveForeignKey(RedBeanModel::getTableName( + $this->modelAttributeToDataProviderAdapter-> getRelatedAttributeModelClassName())); + } + $tableAliasName = $relationAttributeTableName; $quote = DatabaseCompatibilityUtil::getQuote(); $where[$whereKey] = "(1 = (select 1 from $quote$relationAttributeTableName$quote $tableAliasName " . // Not Coding Standard "where $quote$tableAliasName$quote.$quote$relationColumnName$quote = " . // Not Coding Standard diff --git a/app/protected/core/utils/NumberUtil.php b/app/protected/core/utils/NumberUtil.php new file mode 100644 index 000000000..20a7870f9 --- /dev/null +++ b/app/protected/core/utils/NumberUtil.php @@ -0,0 +1,62 @@ + diff --git a/app/protected/core/utils/RedBeanDatabaseBuilderUtil.php b/app/protected/core/utils/RedBeanDatabaseBuilderUtil.php index 21f3699ea..d7c4c6dd6 100644 --- a/app/protected/core/utils/RedBeanDatabaseBuilderUtil.php +++ b/app/protected/core/utils/RedBeanDatabaseBuilderUtil.php @@ -584,6 +584,7 @@ protected static function setMadeUpMemberValue($model, $memberName) case 'CUnsafeValidator': case 'RedBeanModelCompareDateTimeValidator': case 'RedBeanModelRequiredValidator': + case 'RedBeanModelProbabilityValidator': case 'UsernameLengthValidator': case 'ValidateTimeZone': case 'AtLeastOneContentAreaRequiredValidator': diff --git a/app/protected/core/validators/RedBeanModelProbabilityValidator.php b/app/protected/core/validators/RedBeanModelProbabilityValidator.php new file mode 100644 index 000000000..febf2b684 --- /dev/null +++ b/app/protected/core/validators/RedBeanModelProbabilityValidator.php @@ -0,0 +1,52 @@ + diff --git a/app/protected/core/views/EditAndDetailsView.php b/app/protected/core/views/EditAndDetailsView.php index ff5f5e091..54ec03b7d 100644 --- a/app/protected/core/views/EditAndDetailsView.php +++ b/app/protected/core/views/EditAndDetailsView.php @@ -96,7 +96,15 @@ protected function renderContent() ); $content .= $formStart; $content .= '