PageRenderTime 155ms CodeModel.GetById 41ms RepoModel.GetById 9ms app.codeStats 0ms

/Croogo/Lib/Utility/VisibilityFilter.php

https://github.com/kareypowell/croogo
PHP | 152 lines | 88 code | 16 blank | 48 comment | 18 complexity | bfcf94a5002c63f9a5653551a28f8157 MD5 | raw file
  1. <?php
  2. App::uses('StringConverter', 'Croogo.Lib/Utility');
  3. /**
  4. * VisibilityFilter
  5. *
  6. * @author Rachman Chavik <rchavik@xintesa.com>
  7. * @package Croogo.Croogo.Lib.Utility
  8. * @license http://www.opensource.org/licenses/mit-license.php The MIT License
  9. * @link http://www.croogo.org
  10. */
  11. class VisibilityFilter {
  12. /**
  13. * StringConverter instance
  14. */
  15. protected $_converter = null;
  16. /**
  17. * Known url keys
  18. */
  19. protected $_urlKeys = array(
  20. 'admin' => false,
  21. 'plugin' => false,
  22. 'controller' => false,
  23. 'action' => false,
  24. 'named' => false,
  25. 'pass' => false,
  26. );
  27. /**
  28. * Constructor
  29. *
  30. * @param CakeRequest $request
  31. */
  32. public function __construct(CakeRequest $request = null) {
  33. if ($request) {
  34. $this->_request = $request;
  35. } else {
  36. $this->_request = new CakeRequest();
  37. }
  38. $this->_converter = new StringConverter();
  39. }
  40. /**
  41. * Check that request (passed in the constructor) is visible based on list of
  42. * specified rules. The rules can specified in link string format or just a
  43. * plain URL fragment. Whenever possible, use link string formatted rule since
  44. * a URL fragment can be expensive.
  45. *
  46. * The current request is checked against negative rules first (implicitly
  47. * hidden), then against positive rules (implicitly visible).
  48. * If there's no positive rule, defaults to visible.
  49. *
  50. * @param array $rules Array of rules in link string format
  51. * @return bool True if the rules are satisfied
  52. * @see StringConverter::linkStringToArray()
  53. */
  54. protected function _isVisible($rules) {
  55. $negativeRules = array_filter($rules, function($value) {
  56. if ($value[0] === '-') {
  57. return true;
  58. }
  59. return false;
  60. });
  61. foreach ($negativeRules as $rule) {
  62. if ($this->_ruleMatch(substr($rule, 1))) {
  63. return false;
  64. }
  65. }
  66. $positiveRules = array_diff($rules, $negativeRules);
  67. if (empty($positiveRules)) {
  68. return true;
  69. }
  70. foreach ($positiveRules as $rule) {
  71. if ($rule[0] == '+') {
  72. $rule = substr($rule, 1);
  73. }
  74. if ($this->_ruleMatch($rule)) {
  75. return true;
  76. }
  77. }
  78. return false;
  79. }
  80. /**
  81. * Check that request matches a single rule
  82. *
  83. * @param string $rule Rule in link string or plain URL fragment
  84. * @return bool True if request satisfies the rule
  85. */
  86. protected function _ruleMatch($rule) {
  87. if (strpos($rule, ':') !== false) {
  88. $url = array_filter($this->_converter->linkStringToArray($rule));
  89. if (isset($url['?'])) {
  90. $queryString = $url['?'];
  91. unset($url['?']);
  92. }
  93. } else {
  94. $url = Router::parse($rule);
  95. $named = array_diff_key($url, $this->_urlKeys);
  96. $url['named'] = $named;
  97. }
  98. $intersect = array_intersect_key($this->_request->params, $url);
  99. $matched = $intersect == $url;
  100. if ($matched && isset($queryString)) {
  101. $matched = $this->_request->query == $queryString;
  102. }
  103. return $matched;
  104. }
  105. /**
  106. * Remove values based on rules in visibility_path field.
  107. *
  108. * Options:
  109. * - model Model alias in $values
  110. * - field Field name containing the visibility path rules
  111. *
  112. * @param array $values Array of data to filter
  113. */
  114. public function remove($values, $options = array()) {
  115. $options = Hash::merge(array(
  116. 'model' => null,
  117. 'field' => null,
  118. ), $options);
  119. $model = $options['model'];
  120. $field = $options['field'];
  121. $results = array();
  122. foreach ($values as $value) {
  123. if (empty($value[$model][$field])) {
  124. $results[] = $value;
  125. continue;
  126. }
  127. if (!is_array($value[$model][$field])) {
  128. CakeLog::error('Invalid visibility_path rule');
  129. }
  130. if ($this->_isVisible($value[$model][$field])) {
  131. $results[] = $value;
  132. }
  133. }
  134. return $results;
  135. }
  136. }