Passed
Push — master ( 891151...7b6b24 )
by Julito
12:45
created

getRootNodesQueryBuilder()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
nc 1
nop 2
dl 0
loc 3
rs 10
c 1
b 0
f 0
1
<?php
2
3
namespace Chamilo\CoreBundle\Traits\Repository\ORM;
4
5
use Gedmo\Tree\Strategy;
6
use Gedmo\Tool\Wrapper\EntityWrapper;
7
8
/**
9
 * The MaterializedPathRepository has some useful functions
10
 * to interact with MaterializedPath tree. Repository uses
11
 * the strategy used by listener
12
 *
13
 * @author Gustavo Falco <[email protected]>
14
 * @author Gediminas Morkevicius <[email protected]>
15
 * @license MIT License (http://www.opensource.org/licenses/mit-license.php)
16
 */
17
trait MaterializedPathRepositoryTrait
18
{
19
    use TreeRepositoryTrait;
20
21
    /**
22
     * Get tree query builder
23
     *
24
     * @param object $rootNode
25
     *
26
     * @return \Doctrine\ORM\QueryBuilder
27
     */
28
    public function getTreeQueryBuilder($rootNode = null)
29
    {
30
        return $this->getChildrenQueryBuilder($rootNode, false, null, 'asc', true);
31
    }
32
33
    /**
34
     * Get tree query
35
     *
36
     * @param object $rootNode
37
     *
38
     * @return \Doctrine\ORM\Query
39
     */
40
    public function getTreeQuery($rootNode = null)
41
    {
42
        return $this->getTreeQueryBuilder($rootNode)->getQuery();
43
    }
44
45
    /**
46
     * Get tree
47
     *
48
     * @param object $rootNode
49
     *
50
     * @return array
51
     */
52
    public function getTree($rootNode = null)
53
    {
54
        return $this->getTreeQuery($rootNode)->execute();
55
    }
56
57
    /**
58
     * {@inheritDoc}
59
     */
60
    public function getRootNodesQueryBuilder($sortByField = null, $direction = 'asc')
61
    {
62
        return $this->getChildrenQueryBuilder(null, true, $sortByField, $direction);
63
    }
64
65
    /**
66
     * {@inheritDoc}
67
     */
68
    public function getRootNodesQuery($sortByField = null, $direction = 'asc')
69
    {
70
        return $this->getRootNodesQueryBuilder($sortByField, $direction)->getQuery();
71
    }
72
73
    /**
74
     * {@inheritDoc}
75
     */
76
    public function getRootNodes($sortByField = null, $direction = 'asc')
77
    {
78
        return $this->getRootNodesQuery($sortByField, $direction)->execute();
79
    }
80
81
    /**
82
     * Get the Tree path query builder by given $node
83
     *
84
     * @param object $node
85
     *
86
     * @return \Doctrine\ORM\QueryBuilder
87
     */
88
    public function getPathQueryBuilder($node)
89
    {
90
        $meta = $this->getClassMetadata();
91
        $config = $this->listener->getConfiguration($this->_em, $meta->name);
92
        $alias = 'materialized_path_entity';
93
        $qb = $this->getQueryBuilder()
94
            ->select($alias)
95
            ->from($config['useObjectClass'], $alias);
96
97
        $node = new EntityWrapper($node, $this->_em);
98
        $nodePath = $node->getPropertyValue($config['path']);
99
        $paths = [];
100
        $nodePathLength = strlen($nodePath);
101
        $separatorMatchOffset = 0;
102
        while ($separatorMatchOffset < $nodePathLength) {
103
            $separatorPos = strpos($nodePath, $config['path_separator'], $separatorMatchOffset);
104
105
            if ($separatorPos === false || $separatorPos === $nodePathLength - 1) {
106
                // last node, done
107
                $paths[] = $nodePath;
108
                $separatorMatchOffset = $nodePathLength;
109
            } elseif ($separatorPos === 0) {
110
                // path starts with separator, continue
111
                $separatorMatchOffset = 1;
112
            } else {
113
                // add node
114
                $paths[] = substr($nodePath, 0, $config['path_ends_with_separator'] ? $separatorPos + 1 : $separatorPos);
115
                $separatorMatchOffset = $separatorPos + 1;
116
            }
117
        }
118
        $qb->where($qb->expr()->in(
119
            $alias.'.'.$config['path'],
120
            $paths
121
        ));
122
        $qb->orderBy($alias.'.'.$config['level'], 'ASC');
123
124
        return $qb;
125
    }
126
127
    /**
128
     * Get the Tree path query by given $node
129
     *
130
     * @param object $node
131
     *
132
     * @return \Doctrine\ORM\Query
133
     */
134
    public function getPathQuery($node)
135
    {
136
        return $this->getPathQueryBuilder($node)->getQuery();
137
    }
138
139
    /**
140
     * Get the Tree path of Nodes by given $node
141
     *
142
     * @param object $node
143
     *
144
     * @return array - list of Nodes in path
145
     */
146
    public function getPath($node)
147
    {
148
        return $this->getPathQuery($node)->getResult();
149
    }
150
151
    /**
152
     * {@inheritDoc}
153
     */
154
    public function getChildrenQueryBuilder($node = null, $direct = false, $sortByField = null, $direction = 'asc', $includeNode = false)
155
    {
156
        $meta = $this->getClassMetadata();
157
        $config = $this->listener->getConfiguration($this->getEntityManager(), $meta->name);
158
        $separator = addcslashes($config['path_separator'], '%');
159
        $alias = 'materialized_path_entity';
160
        $path = $config['path'];
161
        $qb = $this->getQueryBuilder()
162
            ->select($alias)
163
            ->from($config['useObjectClass'], $alias);
164
        $expr = '';
165
        $includeNodeExpr = '';
166
167
        if (is_object($node) && $node instanceof $meta->name) {
168
            $node = new EntityWrapper($node, $this->getEntityManager());
169
            $nodePath = $node->getPropertyValue($path);
170
            $expr = $qb->expr()->andx()->add(
171
                $qb->expr()->like(
172
                    $alias.'.'.$path,
173
                    $qb->expr()->literal(
174
                        $nodePath
175
                        .($config['path_ends_with_separator'] ? '' : $separator).'%'
176
                    )
177
                )
178
            );
179
180
            if ($includeNode) {
181
                $includeNodeExpr = $qb->expr()->eq($alias.'.'.$path, $qb->expr()->literal($nodePath));
182
            } else {
183
                $expr->add($qb->expr()->neq($alias.'.'.$path, $qb->expr()->literal($nodePath)));
184
            }
185
186
            if ($direct) {
187
                $expr->add(
188
                    $qb->expr()->orx(
189
                        $qb->expr()->eq($alias.'.'.$config['level'], $qb->expr()->literal($node->getPropertyValue($config['level']))),
190
                        $qb->expr()->eq($alias.'.'.$config['level'], $qb->expr()->literal($node->getPropertyValue($config['level']) + 1))
191
                    )
192
                );
193
            }
194
        } elseif ($direct) {
195
            $expr = $qb->expr()->not(
196
                $qb->expr()->like($alias.'.'.$path,
197
                    $qb->expr()->literal(
198
                        ($config['path_starts_with_separator'] ? $separator : '')
199
                        .'%'.$separator.'%'
200
                        .($config['path_ends_with_separator'] ? $separator : '')
201
                    )
202
                )
203
            );
204
        }
205
206
        if ($expr) {
207
            $qb->where('('.$expr.')');
208
        }
209
210
        if ($includeNodeExpr) {
211
            $qb->orWhere('('.$includeNodeExpr.')');
212
        }
213
214
        $orderByField = null === $sortByField ? $alias.'.'.$config['path'] : $alias.'.'.$sortByField;
215
        $orderByDir = $direction === 'asc' ? 'asc' : 'desc';
216
        $qb->orderBy($orderByField, $orderByDir);
217
218
        return $qb;
219
    }
220
221
    /**
222
     * {@inheritDoc}
223
     */
224
    public function getChildrenQuery($node = null, $direct = false, $sortByField = null, $direction = 'asc', $includeNode = false)
225
    {
226
        return $this->getChildrenQueryBuilder($node, $direct, $sortByField, $direction, $includeNode)->getQuery();
227
    }
228
229
    /**
230
     * {@inheritDoc}
231
     */
232
    public function getChildren($node = null, $direct = false, $sortByField = null, $direction = 'asc', $includeNode = false)
233
    {
234
        return $this->getChildrenQuery($node, $direct, $sortByField, $direction, $includeNode)->execute();
235
    }
236
237
    /**
238
     * {@inheritdoc}
239
     */
240
    public function getNodesHierarchyQueryBuilder($node = null, $direct = false, array $options = array(), $includeNode = false)
241
    {
242
        $sortBy = array(
243
            'field'     => null,
244
            'dir'       => 'asc',
245
        );
246
247
        if (isset($options['childSort'])) {
248
            $sortBy = array_merge($sortBy, $options['childSort']);
249
        }
250
251
        return $this->getChildrenQueryBuilder($node, $direct, $sortBy['field'], $sortBy['dir'], $includeNode);
252
    }
253
254
    /**
255
     * {@inheritdoc}
256
     */
257
    public function getNodesHierarchyQuery($node = null, $direct = false, array $options = array(), $includeNode = false)
258
    {
259
        return $this->getNodesHierarchyQueryBuilder($node, $direct, $options, $includeNode)->getQuery();
260
    }
261
262
    /**
263
     * {@inheritdoc}
264
     */
265
    public function getNodesHierarchy($node = null, $direct = false, array $options = array(), $includeNode = false)
266
    {
267
        $meta = $this->getClassMetadata();
268
        $config = $this->listener->getConfiguration($this->_em, $meta->name);
269
        $path = $config['path'];
270
271
        $nodes = $this->getNodesHierarchyQuery($node, $direct, $options, $includeNode)->getArrayResult();
272
        usort(
273
            $nodes,
274
            function ($a, $b) use ($path) {
275
                return strcmp($a[$path], $b[$path]);
276
            }
277
        );
278
        return $nodes;
279
    }
280
281
    /**
282
     * {@inheritdoc}
283
     */
284
    protected function validate()
285
    {
286
        return $this->listener->getStrategy($this->getEntityManager(), $this->getClassMetadata()->name)->getName() === Strategy::MATERIALIZED_PATH;
287
    }
288
}
289