NamedScopeBehavior.php 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. <?php
  2. App::uses('ModelBehavior', 'Model');
  3. // basic code taken and modified/fixed from https://github.com/netguru/namedscopebehavior
  4. /**
  5. * Edited version
  6. *
  7. * - it's now "scope" instead of "scopes" (singular and now analogous to "contain" etc)
  8. * - corrected syntax, indentation
  9. * - reads the model's 'scopes' attribute if applicable
  10. *
  11. * If used across models, it is adviced to load this globally via $actAs in the AppModel
  12. * (just as with Containable).
  13. *
  14. * In case you need to dynamically set the Model->scopes attribute, use the constructor:
  15. *
  16. * public function __construct($id = false, $table = null, $ds = null) {
  17. * parent::__construct($id, $table, $ds);
  18. * $this->scopes = ...
  19. * }
  20. *
  21. * Note that it can be vital to use the model prefixes in the conditions and in the scopes
  22. * to avoid SQL errors or naming conflicts.
  23. *
  24. * @license MIT
  25. * @author Mark Scherer
  26. */
  27. class NamedScopeBehavior extends ModelBehavior {
  28. protected $_defaults = array(
  29. 'scope' => array(), // Container to hold all scopes
  30. 'attribute' => 'scopes' // Where to find the declared scopes of the model
  31. );
  32. /**
  33. * NamedScopeBehavior::setup()
  34. *
  35. * @param Model $Model
  36. * @param array $settings
  37. * @return void
  38. */
  39. public function setup(Model $Model, $settings = array()) {
  40. if (!empty($Model->scope)) {
  41. $settings['scope'] = !empty($settings['scope']) ? array_merge($Model->scope, $settings['scope']) : $Model->scope;
  42. }
  43. $this->settings[$Model->alias] = $settings + $this->_defaults;
  44. }
  45. /**
  46. * NamedScopeBehavior::beforeFind()
  47. *
  48. * @param Model $Model
  49. * @param array $queryData
  50. * @return mixed
  51. */
  52. public function beforeFind(Model $Model, $queryData) {
  53. $scopes = array();
  54. // passed as scopes
  55. if (!empty($queryData['scope'])) {
  56. $scope = !is_array($queryData['scope']) ? array($queryData['scope']) : $queryData['scope'];
  57. $scopes = array_merge($scopes, $scope);
  58. }
  59. // passed as conditions['scope']
  60. if (is_array($queryData['conditions']) && !empty($queryData['conditions']['scope'])) {
  61. $scope = !is_array($queryData['conditions']['scope']) ? array($queryData['conditions']['scope']) : $queryData['conditions']['scope'];
  62. unset($queryData['conditions']['scope']);
  63. $scopes = array_merge($scopes, $scope);
  64. }
  65. // if there are scopes defined, we need to get rid of possible condition set earlier by find() method if model->id was set
  66. if (!empty($scopes) && !empty($Model->id) && !empty($queryData['conditions']["`{$Model->alias}`.`{$Model->primaryKey}`"]) && $queryData['conditions']["`{$Model->alias}`.`{$Model->primaryKey}`"] ==
  67. $Model->id) {
  68. unset($queryData['conditions']["`{$Model->alias}`.`{$Model->primaryKey}`"]);
  69. }
  70. $queryData['conditions'][] = $this->_conditions($scopes, $Model->alias);
  71. return $queryData;
  72. }
  73. /**
  74. * NamedScopeBehavior::scope()
  75. *
  76. * @param Model $Model
  77. * @param string $name
  78. * @param mixed $value
  79. * @return mixed
  80. */
  81. public function scope(Model $Model, $name = null, $value = null) {
  82. if ($name === null) {
  83. return $this->settings[$Model->alias]['scope'];
  84. }
  85. if (in_array($name, $this->settings[$Model->alias]['scope'])) {
  86. continue;
  87. }
  88. $this->settings[$Model->alias]['scope'][$name] = $value;
  89. }
  90. /**
  91. * NamedScopeBehavior::_conditions()
  92. *
  93. * @param array $scopes
  94. * @param string $modelName
  95. * @return array
  96. */
  97. protected function _conditions(array $scopes, $modelName) {
  98. $conditions = array();
  99. foreach ($scopes as $scope) {
  100. if (strpos($scope, '.')) {
  101. list($scopeModel, $scope) = explode('.', $scope);
  102. } else {
  103. $scopeModel = $modelName;
  104. }
  105. if (!empty($this->settings[$scopeModel]['scope'][$scope])) {
  106. $conditions[] = array($this->settings[$scopeModel]['scope'][$scope]);
  107. }
  108. }
  109. return $conditions;
  110. }
  111. }