Completed
Pull Request — 5.6 (#2830)
by Jeroen
14:14
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 View Code Duplication
    public function delete(Folder $folder)
54
    {
55
        $em = $this->getEntityManager();
56
57
        $this->deleteMedia($folder);
58
        $this->deleteChildren($folder);
59
        $folder->setDeleted(true);
60
        $em->persist($folder);
61
        $em->flush();
62
    }
63
64
    /**
65
     * @param bool $alsoDeleteFolders
66
     */
67 View Code Duplication
    public function emptyFolder(Folder $folder, $alsoDeleteFolders = false)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
68
    {
69
        $em = $this->getEntityManager();
70
        $this->deleteMedia($folder);
71
        if ($alsoDeleteFolders) {
72
            $this->deleteChildren($folder);
73
        }
74
        $em->flush();
75
    }
76
77
    private function deleteMedia(Folder $folder)
78
    {
79
        $em = $this->getEntityManager();
80
81
        /** @var Media $media */
82
        foreach ($folder->getMedia() as $media) {
83
            $media->setDeleted(true);
84
            $em->persist($media);
85
        }
86
    }
87
88 View Code Duplication
    private function deleteChildren(Folder $folder)
89
    {
90
        $em = $this->getEntityManager();
91
92
        /** @var Folder $child */
93
        foreach ($folder->getChildren() as $child) {
94
            $this->deleteMedia($child);
95
            $this->deleteChildren($child);
96
            $child->setDeleted(true);
97
            $em->persist($child);
98
        }
99
    }
100
101
    /**
102
     * @param int $limit
103
     *
104
     * @return array
105
     */
106
    public function getAllFolders($limit = null)
107
    {
108
        $qb = $this->createQueryBuilder('folder')
109
            ->select('folder')
110
            ->where('folder.parent is null AND folder.deleted != true')
111
            ->orderBy('folder.name');
112
113
        if (false === \is_null($limit)) {
114
            $qb->setMaxResults($limit);
115
        }
116
117
        return $qb->getQuery()->getResult();
118
    }
119
120
    /**
121
     * @param int $folderId
122
     *
123
     * @return object
124
     *
125
     * @throws EntityNotFoundException
126
     */
127
    public function getFolder($folderId)
128
    {
129
        $folder = $this->find($folderId);
130
        if (!$folder) {
131
            throw new EntityNotFoundException();
132
        }
133
134
        return $folder;
135
    }
136
137
    public function getFirstTopFolder()
138
    {
139
        $folder = $this->findOneBy(['parent' => null]);
140
        if (!$folder) {
141
            throw new EntityNotFoundException();
142
        }
143
144
        return $folder;
145
    }
146
147
    public function getParentIds(Folder $folder)
148
    {
149
        /** @var QueryBuilder $qb */
150
        $qb = $this->getPathQueryBuilder($folder)
151
            ->select('node.id');
152
153
        $result = $qb->getQuery()->getScalarResult();
154
        $ids = array_map('current', $result);
155
156
        return $ids;
157
    }
158
159
    /**
160
     * {@inheritdoc}
161
     */
162
    public function getPathQueryBuilder($node)
163
    {
164
        /** @var QueryBuilder $qb */
165
        $qb = parent::getPathQueryBuilder($node);
166
        $qb->andWhere('node.deleted != true');
167
168
        return $qb;
169
    }
170
171
    /**
172
     * {@inheritdoc}
173
     */
174
    public function getRootNodesQueryBuilder($sortByField = null, $direction = 'asc')
175
    {
176
        /** @var QueryBuilder $qb */
177
        $qb = parent::getRootNodesQueryBuilder($sortByField, $direction);
178
        $qb->andWhere('node.deleted != true');
179
180
        return $qb;
181
    }
182
183
    /**
184
     * {@inheritdoc}
185
     */
186
    public function childrenQueryBuilder(
187
        $node = null,
188
        $direct = false,
189
        $sortByField = null,
190
        $direction = 'ASC',
191
        $includeNode = false
192
    ) {
193
        /** @var QueryBuilder $qb */
194
        $qb = parent::childrenQueryBuilder($node, $direct, $sortByField, $direction, $includeNode);
195
        $qb->andWhere('node.deleted != true');
196
197
        return $qb;
198
    }
199
200
    /**
201
     * {@inheritdoc}
202
     */
203
    public function getLeafsQueryBuilder($root = null, $sortByField = null, $direction = 'ASC')
204
    {
205
        /** @var QueryBuilder $qb */
206
        $qb = parent::getLeafsQueryBuilder($root, $sortByField, $direction);
207
        $qb->andWhere('node.deleted != true');
208
209
        return $qb;
210
    }
211
212
    /**
213
     * {@inheritdoc}
214
     */
215
    public function getNextSiblingsQueryBuilder($node, $includeSelf = false)
216
    {
217
        /** @var QueryBuilder $qb */
218
        $qb = parent::getNextSiblingsQueryBuilder($node, $includeSelf);
219
        $qb->andWhere('node.deleted != true');
220
221
        return $qb;
222
    }
223
224
    /**
225
     * {@inheritdoc}
226
     */
227
    public function getPrevSiblingsQueryBuilder($node, $includeSelf = false)
228
    {
229
        /** @var QueryBuilder $qb */
230
        $qb = parent::getPrevSiblingsQueryBuilder($node, $includeSelf);
231
        $qb->andWhere('node.deleted != true');
232
233
        return $qb;
234
    }
235
236
    /**
237
     * {@inheritdoc}
238
     */
239
    public function getNodesHierarchyQueryBuilder(
240
        $node = null,
241
        $direct = false,
242
        array $options = [],
243
        $includeNode = false
244
    ) {
245
        /** @var QueryBuilder $qb */
246
        $qb = parent::getNodesHierarchyQueryBuilder($node, $direct, $options, $includeNode);
247
        $qb->andWhere('node.deleted != true');
248
249
        return $qb;
250
    }
251
252
    /**
253
     * {@inheritdoc}
254
     */
255
    public function getNodesHierarchy($node = null, $direct = false, array $options = [], $includeNode = false)
256
    {
257
        $query = $this->getNodesHierarchyQuery($node, $direct, $options, $includeNode);
258
        $query->setHint(
259
            Query::HINT_CUSTOM_OUTPUT_WALKER,
260
            'Gedmo\\Translatable\\Query\\TreeWalker\\TranslationWalker'
261
        );
262
263
        return $query->getArrayResult();
264
    }
265
266
    /**
267
     * Rebuild the nested tree
268
     */
269
    public function rebuildTree()
270
    {
271
        $em = $this->getEntityManager();
272
273
        // Reset tree...
274
        $sql = 'UPDATE kuma_folders SET lvl=NULL,lft=NULL,rgt=NULL';
275
        $stmt = $em->getConnection()->prepare($sql);
276
        $stmt->execute();
277
278
        $folders = $this->findBy([], ['parent' => 'ASC', 'name' => 'asc']);
279
280
        $rootFolder = $folders[0];
281
        $first = true;
282
        foreach ($folders as $folder) {
283
            // Force parent load
284
            $parent = $folder->getParent();
285
            if (\is_null($parent)) {
286
                $folder->setLevel(0);
287
                if ($first) {
288
                    $this->persistAsFirstChild($folder);
289
                    $first = false;
290
                } else {
291
                    $this->persistAsNextSiblingOf($folder, $rootFolder);
292
                }
293
            } else {
294
                $folder->setLevel($parent->getLevel() + 1);
295
                $this->persistAsLastChildOf($folder, $parent);
296
            }
297
        }
298
        $em->flush();
299
    }
300
301
    /**
302
     * Used as querybuilder for Folder entity selectors
303
     *
304
     * @param Folder $ignoreSubtree Folder (with children) that has to be filtered out (optional)
305
     *
306
     * @return QueryBuilder
307
     */
308
    public function selectFolderQueryBuilder(Folder $ignoreSubtree = null)
309
    {
310
        /** @var QueryBuilder $qb */
311
        $qb = $this->createQueryBuilder('f');
312
        $qb->where('f.deleted != true')
313
            ->orderBy('f.lft');
314
315
        // Fetch all folders except the current one and its children
316
        if (!\is_null($ignoreSubtree) && $ignoreSubtree->getId() !== null) {
317
            $orX = $qb->expr()->orX();
318
            $orX->add('f.rgt > :right')
319
                ->add('f.lft < :left');
320
321
            $qb->andWhere($orX)
322
                ->setParameter('left', $ignoreSubtree->getLeft())
323
                ->setParameter('right', $ignoreSubtree->getRight());
324
        }
325
326
        return $qb;
327
    }
328
329
    /**
330
     * @param $parent
331
     */
332
    private function persistInOrderedTree(Folder $folder, $parent)
333
    {
334
        // Find where to insert the new item
335
        $children = $parent->getChildren(true);
336
        if ($children->isEmpty()) {
337
            // No children yet - insert as first child
338
            $this->persistAsFirstChildOf($folder, $parent);
339
        } else {
340
            $previousChild = null;
341
            foreach ($children as $child) {
342
                // Alphabetical sorting - could be nice if we implemented a sorting strategy
343
                if (strcasecmp($folder->getName(), $child->getName()) < 0) {
344
                    break;
345
                }
346
                $previousChild = $child;
347
            }
348
            if (\is_null($previousChild)) {
349
                $this->persistAsPrevSiblingOf($folder, $children[0]);
350
            } else {
351
                $this->persistAsNextSiblingOf($folder, $previousChild);
352
            }
353
        }
354
    }
355
}
356