1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* This file is part of the Superdesk Web Publisher Content Bundle. |
5
|
|
|
* |
6
|
|
|
* Copyright 2015 Sourcefabric z.u. and contributors. |
7
|
|
|
* |
8
|
|
|
* For the full copyright and license information, please see the |
9
|
|
|
* AUTHORS and LICENSE files distributed with this source code. |
10
|
|
|
* |
11
|
|
|
* @copyright 2015 Sourcefabric z.ú |
12
|
|
|
* @license http://www.superdesk.org/license |
13
|
|
|
*/ |
14
|
|
|
|
15
|
|
|
namespace SWP\Bundle\ContentBundle\Loader; |
16
|
|
|
|
17
|
|
|
use PHPCR\Query\QueryInterface; |
18
|
|
|
use SWP\Bundle\ContentBundle\Doctrine\ODM\PHPCR\ArticleInterface; |
19
|
|
|
use SWP\Component\TemplatesSystem\Gimme\Context\Context; |
20
|
|
|
use SWP\Component\TemplatesSystem\Gimme\Factory\MetaFactoryInterface; |
21
|
|
|
use SWP\Component\TemplatesSystem\Gimme\Loader\LoaderInterface; |
22
|
|
|
use SWP\Component\TemplatesSystem\Gimme\Meta\Meta; |
23
|
|
|
use SWP\Component\TemplatesSystem\Gimme\Meta\MetaCollection; |
24
|
|
|
use Doctrine\ODM\PHPCR\DocumentManager; |
25
|
|
|
use SWP\Component\MultiTenancy\PathBuilder\TenantAwarePathBuilderInterface; |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* Class ArticleLoader. |
29
|
|
|
*/ |
30
|
|
|
class ArticleLoader implements LoaderInterface |
31
|
|
|
{ |
32
|
|
|
/** |
33
|
|
|
* @var DocumentManager |
34
|
|
|
*/ |
35
|
|
|
protected $dm; |
36
|
|
|
|
37
|
|
|
/** |
38
|
|
|
* @var TenantAwarePathBuilderInterface |
39
|
|
|
*/ |
40
|
|
|
protected $pathBuilder; |
41
|
|
|
|
42
|
|
|
/** |
43
|
|
|
* @var string |
44
|
|
|
*/ |
45
|
|
|
protected $routeBasepaths; |
46
|
|
|
|
47
|
|
|
/** |
48
|
|
|
* @var MetaFactoryInterface |
49
|
|
|
*/ |
50
|
|
|
protected $metaFactory; |
51
|
|
|
|
52
|
|
|
/** |
53
|
|
|
* @var Context |
54
|
|
|
*/ |
55
|
|
|
protected $context; |
56
|
|
|
|
57
|
|
|
/** |
58
|
|
|
* ArticleLoader constructor. |
59
|
|
|
* |
60
|
|
|
* @param DocumentManager $dm |
61
|
|
|
* @param TenantAwarePathBuilderInterface $pathBuilder |
62
|
|
|
* @param string $routeBasepaths |
63
|
|
|
* @param MetaFactoryInterface $metaFactory |
64
|
|
|
* @param Context $context |
65
|
|
|
*/ |
66
|
95 |
|
public function __construct( |
67
|
|
|
DocumentManager $dm, |
68
|
|
|
TenantAwarePathBuilderInterface $pathBuilder, |
69
|
|
|
$routeBasepaths, |
70
|
|
|
MetaFactoryInterface $metaFactory, |
71
|
|
|
Context $context |
72
|
|
|
) { |
73
|
95 |
|
$this->dm = $dm; |
74
|
95 |
|
$this->pathBuilder = $pathBuilder; |
75
|
95 |
|
$this->routeBasepaths = $routeBasepaths; |
76
|
95 |
|
$this->metaFactory = $metaFactory; |
77
|
95 |
|
$this->context = $context; |
78
|
95 |
|
} |
79
|
|
|
|
80
|
|
|
/** |
81
|
|
|
* Load meta object by provided type and parameters. |
82
|
|
|
* |
83
|
|
|
* @MetaLoaderDoc( |
84
|
|
|
* description="Article Loader loads articles from Content Repository", |
85
|
|
|
* parameters={ |
86
|
|
|
* contentPath="SINGLE|required content path", |
87
|
|
|
* slug="SINGLE|required content slug", |
88
|
|
|
* pageName="COLLECTiON|name of Page for required articles" |
89
|
|
|
* } |
90
|
|
|
* ) |
91
|
|
|
* |
92
|
|
|
* @param string $type object type |
93
|
|
|
* @param array $parameters parameters needed to load required object type |
94
|
|
|
* @param int $responseType response type: single meta (LoaderInterface::SINGLE) or collection of metas (LoaderInterface::COLLECTION) |
95
|
|
|
* |
96
|
|
|
* @return Meta|Meta[]|bool false if meta cannot be loaded, a Meta instance otherwise |
97
|
|
|
* |
98
|
|
|
* @throws \Exception |
99
|
|
|
*/ |
100
|
18 |
|
public function load($type, $parameters = [], $responseType = LoaderInterface::SINGLE) |
101
|
|
|
{ |
102
|
18 |
|
$article = null; |
103
|
|
|
|
104
|
18 |
|
if ($responseType === LoaderInterface::SINGLE) { |
105
|
14 |
|
if (array_key_exists('contentPath', $parameters)) { |
106
|
3 |
|
$article = $this->dm->find('SWP\Bundle\ContentBundle\Doctrine\ODM\PHPCR\Article', $parameters['contentPath']); |
107
|
3 |
|
if (null !== $article && !$article->isPublished()) { |
108
|
3 |
|
$article = null; |
109
|
|
|
} |
110
|
11 |
|
} elseif (array_key_exists('article', $parameters)) { |
111
|
|
|
$this->dm->detach($parameters['article']); |
112
|
|
|
$article = $this->dm->find('SWP\Bundle\ContentBundle\Doctrine\ODM\PHPCR\Article', $parameters['article']->getId()); |
113
|
|
|
if (null !== $article && !$article->isPublished()) { |
114
|
|
|
$article = null; |
115
|
|
|
} |
116
|
11 |
|
} elseif (array_key_exists('slug', $parameters)) { |
117
|
11 |
|
$article = $this->dm->getRepository('SWP\Bundle\ContentBundle\Doctrine\ODM\PHPCR\Article')->findOneBy([ |
118
|
11 |
|
'slug' => $parameters['slug'], |
119
|
11 |
|
'status' => ArticleInterface::STATUS_PUBLISHED, |
120
|
|
|
]); |
121
|
|
|
} |
122
|
|
|
|
123
|
14 |
|
return $this->getArticleMeta($article); |
124
|
6 |
|
} elseif ($responseType === LoaderInterface::COLLECTION) { |
125
|
6 |
|
$route = null; |
126
|
6 |
|
if (array_key_exists('route', $parameters)) { |
127
|
6 |
|
$route = $this->dm->find(null, $this->pathBuilder->build($this->routeBasepaths[0].$parameters['route'])); |
|
|
|
|
128
|
3 |
|
} elseif (null !== ($currentPage = $this->context->getCurrentPage())) { |
129
|
2 |
|
$route = $currentPage->getValues(); |
130
|
|
|
} |
131
|
|
|
|
132
|
6 |
|
if (null !== $route && is_object($route)) { |
133
|
6 |
|
$identifier = $this->dm->getNodeForDocument($route)->getIdentifier(); |
134
|
6 |
|
$query = $this->dm->createPhpcrQuery($this->getQueryString($identifier, $parameters), QueryInterface::JCR_SQL2); |
135
|
5 |
|
$countQuery = clone $query; |
136
|
|
|
|
137
|
5 |
|
if (isset($parameters['limit'])) { |
138
|
1 |
|
$query->setLimit($parameters['limit']); |
139
|
|
|
} |
140
|
|
|
|
141
|
5 |
|
if (isset($parameters['start'])) { |
142
|
1 |
|
$query->setOffset($parameters['start']); |
143
|
|
|
} |
144
|
|
|
|
145
|
5 |
|
$articles = $this->dm->getDocumentsByPhpcrQuery($query); |
146
|
5 |
|
$metaCollection = new MetaCollection(); |
147
|
5 |
|
$metaCollection->setTotalItemsCount($countQuery->execute()->getRows()->count()); |
148
|
5 |
|
foreach ($articles as $article) { |
149
|
5 |
|
$articleMeta = $this->getArticleMeta($article); |
|
|
|
|
150
|
5 |
|
if ($articleMeta) { |
151
|
5 |
|
$metaCollection->add($articleMeta); |
152
|
|
|
} |
153
|
|
|
} |
154
|
|
|
|
155
|
5 |
|
return $metaCollection; |
156
|
|
|
} |
157
|
|
|
} |
158
|
|
|
|
159
|
1 |
|
return; |
160
|
|
|
} |
161
|
|
|
|
162
|
|
|
/** |
163
|
|
|
* Checks if Loader supports provided type. |
164
|
|
|
* |
165
|
|
|
* @param string $type |
166
|
|
|
* |
167
|
|
|
* @return bool |
168
|
|
|
*/ |
169
|
17 |
|
public function isSupported($type) |
170
|
|
|
{ |
171
|
17 |
|
return in_array($type, ['articles', 'article']); |
172
|
|
|
} |
173
|
|
|
|
174
|
17 |
|
private function getArticleMeta($article) |
175
|
|
|
{ |
176
|
17 |
|
if (!is_null($article)) { |
177
|
15 |
|
return $this->metaFactory->create($article); |
178
|
|
|
} |
179
|
|
|
|
180
|
4 |
|
return; |
181
|
|
|
} |
182
|
|
|
|
183
|
6 |
|
private function getQueryString($identifier, $parameters) |
184
|
|
|
{ |
185
|
6 |
|
$queryStr = sprintf("SELECT * FROM [nt:unstructured] as S WHERE S.phpcr:class='SWP\Bundle\ContentBundle\Doctrine\ODM\PHPCR\Article' AND S.route=%s AND S.status=published", $identifier); |
186
|
6 |
|
if (isset($parameters['order'])) { |
187
|
3 |
|
$order = $parameters['order']; |
188
|
3 |
|
if (!is_array($order) || count($order) !== 2 || (strtoupper($order[1]) != 'ASC' && strtoupper($order[1]) != 'DESC')) { |
189
|
|
|
throw new \Exception('Order filter must have two parameters with second one asc or desc, e.g. order(id, desc)'); |
190
|
|
|
} |
191
|
3 |
|
if ($order[0] === 'id') { |
192
|
1 |
|
$order[0] = 'jcr:uuid'; |
193
|
|
|
} else { |
194
|
|
|
// Check that the given parameter is actually a field name of a route |
195
|
2 |
|
$metaData = $this->dm->getClassMetadata('SWP\Bundle\ContentBundle\Doctrine\ODM\PHPCR\Article'); |
196
|
2 |
|
if (!in_array($order[0], $metaData->getFieldNames())) { |
197
|
1 |
|
throw new \Exception('Order parameter must be id or the name of one of the fields in the route class'); |
198
|
|
|
} |
199
|
|
|
} |
200
|
2 |
|
$queryStr .= sprintf(' ORDER BY S.%s %s', $order[0], $order[1]); |
201
|
|
|
} |
202
|
|
|
|
203
|
5 |
|
return $queryStr; |
204
|
|
|
} |
205
|
|
|
} |
206
|
|
|
|
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.