3
3
4
4
namespace CloudPlayDev \ConfluenceClient \Api ;
5
5
6
- use CloudPlayDev \ConfluenceClient \Entity \Content as ContentEntity ;
6
+ use CloudPlayDev \ConfluenceClient \Entity \AbstractContent ;
7
+ use CloudPlayDev \ConfluenceClient \Entity \ContentComment ;
8
+ use CloudPlayDev \ConfluenceClient \Entity \ContentPage ;
7
9
use CloudPlayDev \ConfluenceClient \Exception \Exception ;
8
10
use CloudPlayDev \ConfluenceClient \Exception \RequestException ;
9
11
use Http \Client \Exception as HttpClientException ;
10
12
use JsonException ;
11
13
use Psr \Http \Message \ResponseInterface ;
14
+ use function assert ;
12
15
use function count ;
13
16
use function in_array ;
14
17
use function is_array ;
18
+ use function is_int ;
19
+ use function is_string ;
15
20
21
+ /**
22
+ * Class Content
23
+ * @package CloudPlayDev\ConfluenceClient\Api
24
+ */
16
25
class Content extends AbstractApi
17
26
{
18
27
/**
19
- * @param int|null $contentId
28
+ * ContentType for confluence attachments
29
+ */
30
+ public const CONTENT_TYPE_ATTACHMENT = 'attachment ' ;
31
+
32
+ /**
33
+ * ContentType for confluence comments
34
+ */
35
+ public const CONTENT_TYPE_COMMENT = 'comment ' ;
36
+
37
+ /**
38
+ * ContentType for confluence page content
39
+ */
40
+ public const CONTENT_TYPE_PAGE = 'page ' ;
41
+
42
+ /**
43
+ * @param string|int|null ...$parameter
20
44
* @return string
21
45
*/
22
- private static function getContentUri (? int $ contentId = null ): string
46
+ private static function getContentUri (... $ parameter ): string
23
47
{
24
48
$ uri = 'content ' ;
25
- if (null !== $ contentId ) {
26
- $ uri .= '/ ' . $ contentId ;
49
+ $ parameterString = implode ('/ ' , array_filter ($ parameter ));
50
+
51
+ if (!empty ($ parameterString )) {
52
+ $ uri .= '/ ' . $ parameterString ;
27
53
}
28
54
29
- return $ uri ;
55
+ return $ uri . ' ? ' ;
30
56
}
31
57
32
58
/**
33
59
* @param int $contentId
34
- * @return ContentEntity
60
+ * @return AbstractContent
35
61
* @throws Exception
36
62
* @throws JsonException
37
63
* @throws RequestException
38
64
* @throws HttpClientException
39
65
*/
40
- public function findOneById (int $ contentId ): ContentEntity
66
+ public function findOneById (int $ contentId ): AbstractContent
41
67
{
42
- $ response = $ this ->get (self ::getContentUri ($ contentId ));
68
+ $ response = $ this ->get (self ::getContentUri ($ contentId ), [ ' expand ' => ' space,version,body.storage ' ] );
43
69
44
70
if ($ response ->getStatusCode () !== 200 ) {
45
71
throw new RequestException ($ response );
@@ -49,13 +75,13 @@ public function findOneById(int $contentId): ContentEntity
49
75
}
50
76
51
77
/**
52
- * @param ContentEntity $page
78
+ * @param AbstractContent $page
53
79
* @return ResponseInterface
54
80
* @throws Exception
55
81
* @throws JsonException
56
82
* @throws HttpClientException
57
83
*/
58
- public function update (ContentEntity $ page ): ResponseInterface
84
+ public function update (AbstractContent $ page ): ResponseInterface
59
85
{
60
86
$ contentId = $ page ->getId ();
61
87
if (null === $ contentId ) {
@@ -80,13 +106,13 @@ public function update(ContentEntity $page): ResponseInterface
80
106
}
81
107
82
108
/**
83
- * @param ContentEntity $page
84
- * @return ContentEntity
109
+ * @param AbstractContent $page
110
+ * @return AbstractContent
85
111
* @throws Exception
86
112
* @throws HttpClientException
87
113
* @throws JsonException
88
114
*/
89
- public function create (ContentEntity $ page ): ContentEntity
115
+ public function create (AbstractContent $ page ): AbstractContent
90
116
{
91
117
if (null !== $ page ->getId ()) {
92
118
throw new Exception ('Only new pages can be created. ' );
@@ -115,10 +141,10 @@ public function create(ContentEntity $page): ContentEntity
115
141
}
116
142
117
143
/**
118
- * @param ContentEntity $page
144
+ * @param AbstractContent $page
119
145
* @return ResponseInterface
120
146
*/
121
- public function remove (ContentEntity $ page ): ResponseInterface
147
+ public function remove (AbstractContent $ page ): ResponseInterface
122
148
{
123
149
$ contentId = $ page ->getId ();
124
150
if (null === $ contentId ) {
@@ -128,43 +154,95 @@ public function remove(ContentEntity $page): ResponseInterface
128
154
}
129
155
130
156
/**
131
- * @param array{title?: string, spaceKey?: string, type?: string, id?: int|string, expand?: string} $searchParameter
132
- * @return ContentEntity|null
157
+ * @param AbstractContent $content
158
+ * @param string|null $contentType
159
+ * @return AbstractContent[]
160
+ * @throws HttpClientException
161
+ * @throws JsonException
162
+ */
163
+ public function children (AbstractContent $ content , ?string $ contentType = null ): array
164
+ {
165
+ return $ this ->parseSearchResults (
166
+ $ this ->get (
167
+ self ::getContentUri ($ content ->getId (), 'child ' , $ contentType ),
168
+ ['expand ' => 'space,version,body.storage ' ]
169
+ ),
170
+ );
171
+ }
172
+
173
+ /**
174
+ * @param AbstractContent $content
175
+ * @param string|null $contentType
176
+ * @return AbstractContent[]
177
+ * @throws HttpClientException
178
+ * @throws JsonException
179
+ */
180
+ public function descendants (AbstractContent $ content , ?string $ contentType = null ): array
181
+ {
182
+ return $ this ->parseSearchResults ($ this ->get (self ::getContentUri ($ content ->getId (), 'descendant ' , $ contentType )));
183
+ }
184
+
185
+ /**
186
+ * @param array{title?: string, spaceKey?: string, type?: string, id?: int|string} $searchParameter
187
+ * @return AbstractContent|null
133
188
* @throws Exception
134
189
* @throws JsonException
135
190
*/
136
- public function findOneBy (array $ searchParameter ): ?ContentEntity
191
+ public function findOneBy (array $ searchParameter ): ?AbstractContent
137
192
{
138
- $ allowedSearchParameter = ['title ' , 'spaceKey ' , 'type ' , 'id ' , ' expand ' ];
193
+ $ allowedSearchParameter = ['title ' , 'spaceKey ' , 'type ' , 'id ' ];
139
194
$ queryParameter = array_filter ($ searchParameter , static function (string $ searchKey ) use ($ allowedSearchParameter ) {
140
195
return in_array ($ searchKey , $ allowedSearchParameter , true );
141
196
}, ARRAY_FILTER_USE_KEY );
142
197
198
+ $ queryParameter ['expand ' ] = 'space,version,body.storage ' ;
199
+
143
200
$ searchResponse = $ this ->get ('content? ' , $ queryParameter );
144
201
145
202
if ($ searchResponse ->getStatusCode () !== 200 ) {
146
203
throw new RequestException ($ searchResponse );
147
204
}
148
205
149
- $ decodedSearchResponse = (array )json_decode ($ searchResponse ->getBody ()->getContents (), true , 512 , JSON_THROW_ON_ERROR );
206
+ $ searchResults = $ this ->parseSearchResults ($ searchResponse );
207
+ if (count ($ searchResults ) > 0 ) {
208
+ return reset ($ searchResults );
209
+ }
210
+
211
+ return null ;
212
+ }
213
+
214
+ /**
215
+ * @param ResponseInterface $response
216
+ * @return AbstractContent[]
217
+ * @throws JsonException
218
+ */
219
+ private function parseSearchResults (ResponseInterface $ response ): array
220
+ {
221
+ $ decodedSearchResponse = json_decode ($ response ->getBody ()->getContents (), true , 512 , JSON_THROW_ON_ERROR );
222
+ assert (is_array ($ decodedSearchResponse ));
223
+ assert (isset ($ decodedSearchResponse ['results ' ], $ decodedSearchResponse ['size ' ]));
224
+ assert (is_array ($ decodedSearchResponse ['results ' ]));
225
+ assert (is_int ($ decodedSearchResponse ['size ' ]));
226
+
227
+ $ results = [];
228
+ if ($ decodedSearchResponse ['size ' ] >= 1 && count ($ decodedSearchResponse ['results ' ]) >= 1 ) {
150
229
151
- if (isset ($ decodedSearchResponse ['results ' ], $ decodedSearchResponse ['size ' ]) && is_array ($ decodedSearchResponse ['results ' ]) && $ decodedSearchResponse ['size ' ] >= 1 && count ($ decodedSearchResponse ['results ' ]) >= 1 ) {
152
- $ firstPage = (array )reset ($ decodedSearchResponse ['results ' ]);
153
- if (isset ($ firstPage ['id ' ])) {
154
- return $ this ->findOneById ((int )$ firstPage ['id ' ]);
230
+ foreach ($ decodedSearchResponse ['results ' ] as $ resultEntity ) {
231
+ assert (is_array ($ resultEntity ));
232
+ $ results [] = $ this ->deserializeContent ($ resultEntity );
155
233
}
156
234
}
157
235
158
- return null ;
236
+ return $ results ;
159
237
}
160
238
161
239
/**
162
240
* @param ResponseInterface $response
163
- * @return ContentEntity
241
+ * @return AbstractContent
164
242
* @throws Exception
165
243
* @throws JsonException
166
244
*/
167
- private function deserialize (ResponseInterface $ response ): ContentEntity
245
+ private function deserialize (ResponseInterface $ response ): AbstractContent
168
246
{
169
247
$ responseData = $ response ->getBody ()->getContents ();
170
248
@@ -179,29 +257,42 @@ private function deserialize(ResponseInterface $response): ContentEntity
179
257
180
258
/**
181
259
* @param mixed[] $decodedData
182
- * @return ContentEntity
260
+ * @return AbstractContent
183
261
* @throws Exception
184
262
*/
185
- private function deserializeContent (array $ decodedData ): ContentEntity
263
+ private function deserializeContent (array $ decodedData ): AbstractContent
186
264
{
187
- if (! isset ($ decodedData ['id ' ],
265
+ assert ( isset ($ decodedData ['id ' ],
188
266
$ decodedData ['type ' ],
189
267
$ decodedData ['title ' ],
190
- $ decodedData ['_links ' ]['self ' ],
191
- $ decodedData ['space ' ]['key ' ],
192
- $ decodedData ['version ' ]['number ' ])
193
- ) {
194
- throw new Exception ('Invalid content data ' );
268
+ $ decodedData ['_links ' ]['self ' ]));
269
+ assert (is_string ($ decodedData ['type ' ]));
270
+
271
+ switch ($ decodedData ['type ' ]) {
272
+ case self ::CONTENT_TYPE_PAGE :
273
+ $ content = new ContentPage ();
274
+ break ;
275
+ case self ::CONTENT_TYPE_COMMENT :
276
+ $ content = new ContentComment ();
277
+ break ;
278
+ default :
279
+ throw new Exception ('Invalid content type: ' . $ decodedData ['type ' ]);
195
280
}
196
281
197
- $ page = new ContentEntity ();
198
- $ page ->setId ((int )$ decodedData ['id ' ]);
199
- $ page ->setType ((string )$ decodedData ['type ' ]);
200
- $ page ->setTitle ((string )$ decodedData ['title ' ]);
201
- $ page ->setUrl ((string )$ decodedData ['_links ' ]['self ' ]);
202
- $ page ->setSpace (str_replace ('/rest/api/space/ ' , '' , (string )$ decodedData ['space ' ]['key ' ]));
203
- $ page ->setVersion ((int )$ decodedData ['version ' ]['number ' ]);
282
+ $ content ->setId ((int )$ decodedData ['id ' ]);
283
+ $ content ->setType ($ decodedData ['type ' ]);
284
+ $ content ->setTitle ((string )$ decodedData ['title ' ]);
285
+ $ content ->setUrl ((string )$ decodedData ['_links ' ]['self ' ]);
286
+ if (isset ($ decodedData ['space ' ]['key ' ])) {
287
+ $ content ->setSpace ((string )$ decodedData ['space ' ]['key ' ]);
288
+ }
289
+ if (isset ($ decodedData ['version ' ]['number ' ])) {
290
+ $ content ->setVersion ((int )$ decodedData ['version ' ]['number ' ]);
291
+ }
292
+ if (isset ($ decodedData ['body ' ]['storage ' ]['value ' ])) {
293
+ $ content ->setContent ($ decodedData ['body ' ]['storage ' ]['value ' ]);
294
+ }
204
295
205
- return $ page ;
296
+ return $ content ;
206
297
}
207
298
}
0 commit comments