Completed
Push — master ( 06c1ce...67d37c )
by Jeroen
06:20
created

MediaBundle/Repository/FolderRepository.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Kunstmaan\MediaBundle\Repository;
4
5
use Doctrine\ORM\EntityNotFoundException;
6
use Doctrine\ORM\Query;
7
use Doctrine\ORM\QueryBuilder;
8
use Gedmo\Tree\Entity\Repository\NestedTreeRepository;
9
use Kunstmaan\MediaBundle\Entity\Folder;
10
use Kunstmaan\MediaBundle\Entity\Media;
11
12
/**
13
 * FolderRepository
14
 *
15
 * @method FolderRepository persistAsFirstChild(object $node)
16
 * @method FolderRepository persistAsFirstChildOf(object $node, object $parent)
17
 * @method FolderRepository persistAsLastChild(object $node)
18
 * @method FolderRepository persistAsLastChildOf(object $node, object $parent)
19
 * @method FolderRepository persistAsNextSibling(object $node)
20
 * @method FolderRepository persistAsNextSiblingOf(object $node, object $sibling)
21
 * @method FolderRepository persistAsPrevSibling(object $node)
22
 * @method FolderRepository persistAsPrevSiblingOf(object $node, object $sibling)
23
 */
24
class FolderRepository extends NestedTreeRepository
25
{
26
    /**
27
     * @param Folder $folder The folder
28
     *
29
     * @throws \Exception
30
     */
31
    public function save(Folder $folder)
32
    {
33
        $em = $this->getEntityManager();
34
        $parent = $folder->getParent();
35
36
        $em->beginTransaction();
37
38
        try {
39
            if (!\is_null($parent)) {
40
                $this->persistInOrderedTree($folder, $parent);
41
            } else {
42
                $em->persist($folder);
43
            }
44
            $em->commit();
45
            $em->flush();
46
        } catch (\Exception $e) {
47
            $em->rollback();
48
49
            throw $e;
50
        }
51
    }
52
53
    /**
54
     * @param Folder $folder
55
     */
56 View Code Duplication
    public function delete(Folder $folder)
57
    {
58
        $em = $this->getEntityManager();
59
60
        $this->deleteMedia($folder);
61
        $this->deleteChildren($folder);
62
        $folder->setDeleted(true);
63
        $em->persist($folder);
64
        $em->flush();
65
    }
66
67
    /**
68
     * @param Folder $folder
69
     * @param bool   $alsoDeleteFolders
70
     */
71 View Code Duplication
    public function emptyFolder(Folder $folder, $alsoDeleteFolders = false)
72
    {
73
        $em = $this->getEntityManager();
74
        $this->deleteMedia($folder);
75
        if ($alsoDeleteFolders) {
76
            $this->deleteChildren($folder);
77
        }
78
        $em->flush();
79
    }
80
81
    /**
82
     * @param Folder $folder
83
     */
84
    private function deleteMedia(Folder $folder)
85
    {
86
        $em = $this->getEntityManager();
87
88
        /** @var Media $media */
89
        foreach ($folder->getMedia() as $media) {
90
            $media->setDeleted(true);
91
            $em->persist($media);
92
        }
93
    }
94
95
    /**
96
     * @param Folder $folder
97
     */
98 View Code Duplication
    private function deleteChildren(Folder $folder)
99
    {
100
        $em = $this->getEntityManager();
101
102
        /** @var Folder $child */
103
        foreach ($folder->getChildren() as $child) {
104
            $this->deleteMedia($child);
105
            $this->deleteChildren($child);
106
            $child->setDeleted(true);
107
            $em->persist($child);
108
        }
109
    }
110
111
    /**
112
     * @param int $limit
113
     *
114
     * @return array
115
     */
116
    public function getAllFolders($limit = null)
117
    {
118
        $qb = $this->createQueryBuilder('folder')
119
            ->select('folder')
120
            ->where('folder.parent is null AND folder.deleted != true')
121
            ->orderBy('folder.name');
122
123
        if (false === \is_null($limit)) {
124
            $qb->setMaxResults($limit);
125
        }
126
127
        return $qb->getQuery()->getResult();
128
    }
129
130
    /**
131
     * @param int $folderId
132
     *
133
     * @return object
134
     *
135
     * @throws EntityNotFoundException
136
     */
137
    public function getFolder($folderId)
138
    {
139
        $folder = $this->find($folderId);
140
        if (!$folder) {
141
            throw new EntityNotFoundException();
142
        }
143
144
        return $folder;
145
    }
146
147
    public function getFirstTopFolder()
148
    {
149
        $folder = $this->findOneBy(array('parent' => null));
150
        if (!$folder) {
151
            throw new EntityNotFoundException();
152
        }
153
154
        return $folder;
155
    }
156
157
    public function getParentIds(Folder $folder)
158
    {
159
        /** @var QueryBuilder $qb */
160
        $qb = $this->getPathQueryBuilder($folder)
161
            ->select('node.id');
162
163
        $result = $qb->getQuery()->getScalarResult();
164
        $ids = array_map('current', $result);
165
166
        return $ids;
167
    }
168
169
    /**
170
     * {@inheritdoc}
171
     */
172
    public function getPathQueryBuilder($node)
173
    {
174
        /** @var QueryBuilder $qb */
175
        $qb = parent::getPathQueryBuilder($node);
176
        $qb->andWhere('node.deleted != true');
177
178
        return $qb;
179
    }
180
181
    /**
182
     * {@inheritdoc}
183
     */
184
    public function getRootNodesQueryBuilder($sortByField = null, $direction = 'asc')
185
    {
186
        /** @var QueryBuilder $qb */
187
        $qb = parent::getRootNodesQueryBuilder($sortByField, $direction);
188
        $qb->andWhere('node.deleted != true');
189
190
        return $qb;
191
    }
192
193
    /**
194
     * {@inheritdoc}
195
     */
196
    public function childrenQueryBuilder(
197
        $node = null,
198
        $direct = false,
199
        $sortByField = null,
200
        $direction = 'ASC',
201
        $includeNode = false
202
    ) {
203
        /** @var QueryBuilder $qb */
204
        $qb = parent::childrenQueryBuilder($node, $direct, $sortByField, $direction, $includeNode);
205
        $qb->andWhere('node.deleted != true');
206
207
        return $qb;
208
    }
209
210
    /**
211
     * {@inheritdoc}
212
     */
213
    public function getLeafsQueryBuilder($root = null, $sortByField = null, $direction = 'ASC')
214
    {
215
        /** @var QueryBuilder $qb */
216
        $qb = parent::getLeafsQueryBuilder($root, $sortByField, $direction);
217
        $qb->andWhere('node.deleted != true');
218
219
        return $qb;
220
    }
221
222
    /**
223
     * {@inheritdoc}
224
     */
225
    public function getNextSiblingsQueryBuilder($node, $includeSelf = false)
226
    {
227
        /** @var QueryBuilder $qb */
228
        $qb = parent::getNextSiblingsQueryBuilder($node, $includeSelf);
229
        $qb->andWhere('node.deleted != true');
230
231
        return $qb;
232
    }
233
234
    /**
235
     * {@inheritdoc}
236
     */
237
    public function getPrevSiblingsQueryBuilder($node, $includeSelf = false)
238
    {
239
        /** @var QueryBuilder $qb */
240
        $qb = parent::getPrevSiblingsQueryBuilder($node, $includeSelf);
241
        $qb->andWhere('node.deleted != true');
242
243
        return $qb;
244
    }
245
246
    /**
247
     * {@inheritdoc}
248
     */
249
    public function getNodesHierarchyQueryBuilder(
250
        $node = null,
251
        $direct = false,
252
        array $options = array(),
253
        $includeNode = false
254
    ) {
255
        /** @var QueryBuilder $qb */
256
        $qb = parent::getNodesHierarchyQueryBuilder($node, $direct, $options, $includeNode);
257
        $qb->andWhere('node.deleted != true');
258
259
        return $qb;
260
    }
261
262
    /**
263
     * {@inheritdoc}
264
     */
265
    public function getNodesHierarchy($node = null, $direct = false, array $options = array(), $includeNode = false)
266
    {
267
        $query = $this->getNodesHierarchyQuery($node, $direct, $options, $includeNode);
268
        $query->setHint(
269
            Query::HINT_CUSTOM_OUTPUT_WALKER,
270
            'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker'
271
        );
272
273
        return $query->getArrayResult();
274
    }
275
276
    /**
277
     * Rebuild the nested tree
278
     */
279
    public function rebuildTree()
280
    {
281
        $em = $this->getEntityManager();
282
283
        // Reset tree...
284
        $sql = 'UPDATE kuma_folders SET lvl=NULL,lft=NULL,rgt=NULL';
285
        $stmt = $em->getConnection()->prepare($sql);
286
        $stmt->execute();
287
288
        $folders = $this->findBy(array(), array('parent' => 'ASC', 'name' => 'asc'));
289
290
        $rootFolder = $folders[0];
291
        $first = true;
292
        foreach ($folders as $folder) {
293
            // Force parent load
294
            $parent = $folder->getParent();
295
            if (\is_null($parent)) {
296
                $folder->setLevel(0);
297
                if ($first) {
298
                    $this->persistAsFirstChild($folder);
299
                    $first = false;
300
                } else {
301
                    $this->persistAsNextSiblingOf($folder, $rootFolder);
302
                }
303
            } else {
304
                $folder->setLevel($parent->getLevel() + 1);
305
                $this->persistAsLastChildOf($folder, $parent);
306
            }
307
        }
308
        $em->flush();
309
    }
310
311
    /**
312
     * Used as querybuilder for Folder entity selectors
313
     *
314
     * @param Folder $ignoreSubtree Folder (with children) that has to be filtered out (optional)
0 ignored issues
show
Should the type for parameter $ignoreSubtree not be null|Folder?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
315
     *
316
     * @return QueryBuilder
317
     */
318
    public function selectFolderQueryBuilder(Folder $ignoreSubtree = null)
319
    {
320
        /** @var QueryBuilder $qb */
321
        $qb = $this->createQueryBuilder('f');
322
        $qb->where('f.deleted != true')
323
            ->orderBy('f.lft');
324
325
        // Fetch all folders except the current one and its children
326
        if (!\is_null($ignoreSubtree) && $ignoreSubtree->getId() !== null) {
327
            $orX = $qb->expr()->orX();
328
            $orX->add('f.rgt > :right')
329
                ->add('f.lft < :left');
330
331
            $qb->andWhere($orX)
332
                ->setParameter('left', $ignoreSubtree->getLeft())
333
                ->setParameter('right', $ignoreSubtree->getRight());
334
        }
335
336
        return $qb;
337
    }
338
339
    /**
340
     * @param Folder $folder
341
     * @param        $parent
342
     */
343
    private function persistInOrderedTree(Folder $folder, $parent)
344
    {
345
        // Find where to insert the new item
346
        $children = $parent->getChildren(true);
347
        if ($children->isEmpty()) {
348
            // No children yet - insert as first child
349
            $this->persistAsFirstChildOf($folder, $parent);
350
        } else {
351
            $previousChild = null;
352
            foreach ($children as $child) {
353
                // Alphabetical sorting - could be nice if we implemented a sorting strategy
354
                if (strcasecmp($folder->getName(), $child->getName()) < 0) {
355
                    break;
356
                }
357
                $previousChild = $child;
358
            }
359
            if (\is_null($previousChild)) {
360
                $this->persistAsPrevSiblingOf($folder, $children[0]);
361
            } else {
362
                $this->persistAsNextSiblingOf($folder, $previousChild);
363
            }
364
        }
365
    }
366
}
367