Blame view

protected/components/NodeUrlRule.php 4.35 KB
a1684257   Administrator   first commit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
  <?php
  
  class NodeUrlRule extends CBaseUrlRule
  {
      public $rules = array();
      public $langExpression = '(en|ru)';
      public $langVar = 'lang';
      public $nodeVar = 'node_id';
  
      /**
       * Creates a URL based on this rule.
       * @param CUrlManager $manager the manager
       * @param string $route the route
       * @param array $params list of parameters (name=>value) associated with the route
       * @param string $ampersand the token separating name-value pairs in the URL.
       * @return mixed the constructed URL. False if this rule does not apply.
       */
      public function createUrl($manager, $route, $params, $ampersand)
      {
          if (!isset($params[$this->nodeVar])) return false;
          /** @var $node Node */
          $node = Node::model()->findByPk($params[$this->nodeVar]);
          if (empty($node)) return false;
          if (!isset($this->rules[$node->data_type])) return false;
          foreach ($this->rules[$node->data_type] as $k => $v) {
              if (is_string($k) && is_string($v)) {
                  $rule = new CUrlRule($v, $k);
                  $this->rules[$node->data_type][$k] = $rule;
              } else {
                  $rule = $v;
              }
              $newParams = $params;
              unset($newParams[$this->langVar]);
              unset($newParams[$this->nodeVar]);
              $url = $rule->createUrl($manager, $route, $newParams, $ampersand);
              if ($url !== false) {
                  $path = "/{$node->link}";
                  for ($t = $node; $t->node_id != null; $t = $t->node) {
                      $path = "/{$t->node->link}{$path}";
                  }
                  return "{$params[$this->langVar]}{$path}/{$url}";
              }
          }
          return false;
      }
  
      /**
       * Parses a URL based on this rule.
       * @param CUrlManager $manager the URL manager
       * @param CHttpRequest $request the request object
       * @param string $pathInfo path info part of the URL (URL suffix is already removed based on {@link CUrlManager::urlSuffix})
       * @param string $rawPathInfo path info that contains the potential URL suffix
       * @return mixed the route that consists of the controller ID and action ID. False if this rule does not apply.
       */
      public function parseUrl($manager, $request, $pathInfo, $rawPathInfo)
      {
          //$rawPathInfo = $request->getPathInfo();
          //$pathInfo = $rawPathInfo;
          preg_match("#^{$this->langExpression}#", $pathInfo, $langMatches);
          if (0 == count($langMatches)) return false;
          $lang = $langMatches[0];
          //subtract lang prefix
          $pathInfo = substr($pathInfo, strlen($lang) + 1);
  
  
          //subtract at least one node link
          $nodes = array();
          /** @var $node Node|null */
          while (true) {
              preg_match('#^([^\/]+)#', $pathInfo, $matches);
              if (0 == count($matches)) break;
              $link = $matches[0];
              $nodeCriteria = new CDbCriteria();
              $nodeCriteria->compare('link', $link);
              if (!empty($node)) {
                  $nodeCriteria->compare('node_id', $node->id);
              } else {
                  $nodeCriteria->addCondition('node_id is null');
              }
              $node = Node::model()->find($nodeCriteria);
              if (empty($node)) break;
              $nodes[] = $node;
              if (strlen($link) == strlen($pathInfo)) {
                  $pathInfo = '';
                  break;
              }
              if ($pathInfo[strlen($link)] == '/') {
                  $pathInfo = substr($pathInfo, strlen($link) + 1);
              } else {
                  $pathInfo = substr($pathInfo, strlen($link));
              }
          }
          if (0 == count($nodes)) return false; // no matching nodes
          $node = end($nodes);
          if (!isset($this->rules[$node->data_type])) return false; //no rules for type
          //parse rest
          foreach ($this->rules[$node->data_type] as $k => $v) {
              if (is_string($k) && is_string($v)) {
                  $rule = new CUrlRule($v, $k);
                  $this->rules[$node->data_type][$k] = $rule;
              } else {
                  $rule = $v;
              }
              $route = $rule->parseUrl($manager, $request, $pathInfo, $pathInfo);
              if ($route !== false) {
                  $_GET[$this->langVar] = $lang;
                  $_GET[$this->nodeVar] = $node->id;
                  return $route;
              }
          }
          return false;
      }
  }