1 <?php
declare(strict_types
=1);
4 * This file is part of the Rapsys TreeBundle package.
6 * (c) Raphaël Gertz <symfony@rapsys.eu>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Rapsys\TreeBundle\Repository
;
14 use Doctrine\ORM\Query\ResultSetMapping
;
16 use Rapsys\TreeBundle\Repository
;
21 class AlbumRepository
extends Repository
{
23 * Find album count as int
25 * @param ?integer $uid The user id
26 * @return integer The albums count
28 public function countByUidAsInt(?int $uid): int {
44 SELECT COUNT(DISTINCT a.album_id) AS count
45 FROM Rapsys\TreeBundle\Entity\Element AS a
49 //Get result set mapping instance
50 $req = $this->replace($req);
52 //Get result set mapping instance
53 //XXX: DEBUG: see ../blog.orig/src/Rapsys/BlogBundle/Repository/ArticleRepository.php
54 $rsm = new ResultSetMapping();
57 //XXX: see vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Types.php
58 //addScalarResult($sqlColName, $resColName, $type = 'string');
59 $rsm->addScalarResult('count', 'count', 'integer');
63 ->createNativeQuery($req, $rsm)
64 ->setParameter('uid', $uid)
65 ->getSingleScalarResult();
69 * Find albums as array
71 * @param ?integer $uid The user id
72 * @param integer $page The page
73 * @param integer $count The count
74 * @return array The albums array
76 public function findByUidAsArray(?int $uid, int $page, int $count): array {
83 GREATEST(a.created, e.created) AS created,
84 GREATEST(a.updated, e.updated) AS updated,
85 GREATEST(a.created, e.created, a.updated, e.updated) AS modified,
86 GROUP_CONCAT(e.id ORDER BY e.id SEPARATOR "\\n") AS e_ids,
87 GROUP_CONCAT(e.path ORDER BY e.id SEPARATOR "\\n") AS e_paths
88 FROM Rapsys\TreeBundle\Entity\Album AS a
89 JOIN Rapsys\TreeBundle\Entity\Element AS e ON (e.album_id = a.id AND e.user_id IN (NULL, :uid))
91 ORDER BY updated, created DESC, a.id
95 //Replace bundle entity name by table name
96 $req = $this->replace($req);
98 //Get result set mapping instance
99 $rsm = new ResultSetMapping();
102 //XXX: see vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Types.php
103 //addScalarResult($sqlColName, $resColName, $type = 'string');
104 $rsm->addScalarResult('id', 'id', 'integer')
105 ->addScalarResult('path', 'path', 'string')
106 ->addScalarResult('slug', 'slug', 'string')
107 ->addScalarResult('created', 'created', 'datetime')
108 ->addScalarResult('updated', 'updated', 'datetime')
109 ->addScalarResult('modified', 'modified', 'datetime')
110 ->addScalarResult('e_ids', 'e_ids', 'string')
111 ->addScalarResult('e_paths', 'e_paths', 'string')
112 ->addIndexByScalar('id');
116 ->createNativeQuery($req, $rsm)
117 ->setParameter('offset', $page * $count)
118 ->setParameter('count', $count)
119 ->setParameter('uid', $uid)
125 //Iterate on each album
126 foreach($result as $data) {
128 $return[$data['id']] = [
129 'id' => $id = $data['id'],
130 'slug' => $slug = $data['slug'],
131 'path' => $data['path'],
132 'created' => $data['created'],
133 'updated' => $data['updated'],
134 'modified' => $data['modified'],
135 'link' => $this->router
->generate('rapsystree_album', [ 'id' => $id, 'slug' => $slug ]),
139 //Explode element ids
140 $data['e_ids'] = explode("\n", $data['e_ids']);
142 //Explode element paths
143 $data['e_paths'] = explode("\n", $data['e_paths']);
145 foreach($data['e_ids'] as $e => $eid) {
146 $return[$data['id']]['elements'][$eid] = [
148 'name' => trim(str_replace('/', ' / ', '/'.($path = $data['e_paths'][$e]))),
150 'link' => $this->router
->generate('rapsystree_element', [ 'id' => $eid, 'path' => $path ]),
160 * Find album as array
162 * @param integer $id The album id
163 * @param string $path The album path
164 * @return ?array The album array
166 public function findOneByIdPathAsArray(int $id, string $path): ?array {
173 GREATEST(a.created, e.created) AS created,
174 GREATEST(a.updated, e.updated) AS updated,
175 GREATEST(a.created, e.created, a.updated, e.updated) AS modified,
176 GROUP_CONCAT(e.id ORDER BY e.id SEPARATOR "\\n") AS e_ids,
177 GROUP_CONCAT(e.path ORDER BY e.id SEPARATOR "\\n") AS e_paths,
178 GROUP_CONCAT(e.user_id ORDER BY e.id SEPARATOR "\\n") AS e_uids
179 FROM Rapsys\TreeBundle\Entity\Album AS a
180 JOIN Rapsys\TreeBundle\Entity\Element AS e ON (e.album_id = a.id)
184 //Replace bundle entity name by table name
185 $req = $this->replace($req);
187 //Get result set mapping instance
188 $rsm = new ResultSetMapping();
191 //XXX: see vendor/doctrine/dbal/lib/Doctrine/DBAL/Types/Types.php
192 //addScalarResult($sqlColName, $resColName, $type = 'string');
193 $rsm->addScalarResult('id', 'id', 'integer')
194 ->addScalarResult('path', 'path', 'string')
195 ->addScalarResult('slug', 'slug', 'string')
196 ->addScalarResult('created', 'created', 'datetime')
197 ->addScalarResult('updated', 'updated', 'datetime')
198 ->addScalarResult('modified', 'modified', 'datetime')
199 ->addScalarResult('e_ids', 'e_ids', 'string')
200 ->addScalarResult('e_paths', 'e_paths', 'string')
201 ->addScalarResult('e_uids', 'e_uids', 'string')
202 ->addIndexByScalar('id');
206 ->createNativeQuery($req, $rsm)
207 ->setParameter('id', $id)
208 ->getOneOrNullResult();
215 !($realpath = realpath($result['path'].($path?DIRECTORY_SEPARATOR
.$path:''))) ||
216 //Realpath not matching element path
217 $result['path'] !== substr($realpath, 0, strlen($result['path']))
227 'name' => $name = ucfirst($slug = $result['slug']),
228 'link' => $link = $this->router
->generate('rapsystree_album', [ 'id' => $result['id'], 'path' => '', 'slug' => $slug ])
235 //Iterate on intermediate breadcrumbs
236 foreach(array_slice(explode('/', substr($realpath, strlen($result['path']))), 1) as $value) {
239 'name' => '/ '.$value,
240 'link' => $this->router
->generate('rapsystree_album', [ 'id' => $result['id'], 'path' => ($base .= ($base == '' ? '' : '/').$value), 'slug' => $slug ])
254 if (is_dir($realpath)) {
255 //Iterate on directory
256 foreach(array_diff(scandir($realpath), ['.', '..']) as $item) {
257 //TODO: exclude .svn, .git, .passwd, .*.un~, etc... (if not already protected by haproxy/apache)
261 //Without item realpath
262 !($itempath = realpath($realpath.DIRECTORY_SEPARATOR
.$item)) ||
263 //Item realpath not matching album path
264 $result['path'] !== substr($itempath, 0, strlen($result['path']))
271 if (is_dir($itempath)) {
273 $directories[$item.'/'] = $this->router
->generate('rapsystree_album', [ 'id' => $result['id'], 'path' => ($path ? $path.'/' : '').$item, 'slug' => $slug ]);
275 } elseif (is_file($itempath)) {
277 $fileinfos = $this->file
->infos($itempath);
280 $files[$fileinfos['name']] = [
282 'link' => $this->router
->generate('rapsystree_album', [ 'id' => $result['id'], 'path' => ($path ? $path.'/' : '').$item, 'slug' => $slug ])
287 throw new \
Exception('Unknown element item type');
291 } elseif (is_file($realpath)) {
293 $fileinfos = $this->file
->infos($realpath);
298 'link' => $this->router
->generate('rapsystree_album', [ 'id' => $result['id'], 'path' => $path, 'slug' => $slug ])
303 throw new \
Exception('Unknown element type');
308 'id' => $result['id'],
310 'path' => $result['path'],
312 'created' => $result['created'],
313 'updated' => $result['updated'],
314 'modified' => $result['modified'],
317 'breadcrumbs' => $breadcrumbs,
318 'directories' => $directories,
323 //Explode element ids
324 $result['e_ids'] = explode("\n", $result['e_ids']);
326 //Explode element paths
327 $result['e_paths'] = explode("\n", $result['e_paths']);
329 //Explode element uids
330 $result['e_uids'] = explode("\n", $result['e_uids']);
332 //Iterate on elements
333 foreach($result['e_ids'] as $e => $eid) {
335 $album['elements'][$eid] = [
337 'name' => trim(str_replace('/', ' / ', '/'.($epath = $result['e_paths'][$e]))),
339 'uid' => $result['e_uids'][$e],
340 'link' => $this->router
->generate('rapsystree_album', ['id' => $result['id'], 'path' => $epath, 'slug' => $slug]),