Passed
Push — develop ( 96e1dd...fabd4f )
by Jens
02:30
created

ApiComponent::getDocumentsByPathResponse()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 7
nc 4
nop 0
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Created by jensk on 26-3-2018.
4
 */
5
6
namespace CloudControl\Cms\components;
7
8
9
use CloudControl\Cms\cc\Application;
10
use CloudControl\Cms\cc\Request;
11
use CloudControl\Cms\components\api\Response;
12
use CloudControl\Cms\search\CharacterFilter;
13
use CloudControl\Cms\search\results\SearchSuggestion;
14
use CloudControl\Cms\search\Search;
15
use CloudControl\Cms\search\Tokenizer;
16
use CloudControl\Cms\storage\entities\Document;
17
use CloudControl\Cms\storage\Storage;
18
use CloudControl\Cms\storage\storage\DocumentStorage;
19
20
class ApiComponent extends CachableBaseComponent
21
{
22
    /**
23
     * @var Response
24
     */
25
    protected $response;
26
27
    /**
28
     * @param Storage $storage
29
     */
30
    public function run(Storage $storage)
31
    {
32
        parent::run($storage);
33
        header('Content-Type: application/json');
34
        $this->setResponse();
35
    }
36
37
    private function setResponse()
38
    {
39
        try {
40
            if (isset($_GET['id'])) {
41
                $this->response = $this->getSingleDocumentResponse();
42
                return;
43
            }
44
45
            if (isset($_GET['q'])) {
46
                $this->response = $this->getSearchDocumentsResponse();
47
                return;
48
            }
49
50
            if (isset($_GET['path'])) {
51
                $this->response = $this->getDocumentsByPathResponse();
52
                return;
53
            }
54
            $this->response = '{"swagger":"2.0","info":{"description":"This is documentation for the ApiComponent of the Cloud Control Framework & CMS. See https://getcloudcontrol.org. Additional documentation regarding the ApiComponent can be found here: https://github.com/jenskooij/cloudcontrol/wiki/ApiComponent","title":"ApiComponent for Cloud Control - Framework & CMS","contact":{"name":"Cloud Control - Framework & CMS","url":"https://getcloudcontrol.org"},"license":{"name":"MIT","url":"https://github.com/jenskooij/cloudcontrol/blob/master/LICENSE"},"version":"1.0.0"},"basePath":"' . Request::$subfolders . '","paths":{"' . Request::$subfolders . Request::$relativeUri . '":{"get":{"summary":"Retrieve documents","produces":["application/json"],"parameters":[{"name":"id","in":"query","description":"The identifier for the document that you\'re looking up","required":false,"type":"string"},{"name":"q","in":"query","description":"Search query","required":false,"type":"string"},{"name":"path","in":"query","description":"The (folder) path of which you want to see the contents","required":false,"type":"string"}],"responses":{"200":{"description":"Successful operation","schema":{"$ref":"#/definitions/ApiResponse"}},"default":{"schema":{"type":"string","example":"{}"},"description":"When no parameters present, shows the swagger definition"}}}}},"definitions":{"ApiResponse":{"type":"object","properties":{"success":{"type":"boolean","title":"Wheter or not the call was processed succesful"},"results":{"type":"array","title":"The array of Documents that were found","items":{"$ref":"#/definitions/Document"}},"error":{"title":"If an error occured, it will be displayed, empty if not.","type":"string"},"folder":{"type":"string","title":"Path of the currently selected folder, by using the id parameter","example":"/folder"},"searchSuggestions":{"type":"array","items":{"type":"array","items":{"$ref":"#/definitions/SearchSuggestion"}}}}},"Document":{"type":"object","properties":{"id":{"type":"string","title":"The Document identifier","example":"1"},"path":{"type":"string","title":"The Document path"},"title":{"type":"string","title":"The Document title"},"slug":{"type":"string","title":"The Document slug"},"type":{"type":"string","title":"The Document type","enum":["document","folder"]},"documentType":{"type":"string","title":"The Document DocumentType, as defined in the CMS"},"documentTypeSlug":{"type":"string","title":"The Document DocumentType slug"},"state":{"type":"string","title":"The publication state for this document","enum":["published","unpublished"]},"lastModificationDate":{"type":"string","title":"The Document\'s last modification timestamp","example":"0"},"publicationDate":{"type":"string","title":"The Document\'s publication timestamp","example":"0"}}},"SearchSuggestion":{"type":"object","properties":{"original":{"type":"string","title":"The query that was retrieved from parameter q","example":"kyeword"},"term":{"type":"string","title":"An existing term that is closest to the original","example":"keyword"},"editDistance":{"type":"string","title":"The amount of changes were made to get from the term to the original","example":"2"}}}}}';
0 ignored issues
show
Documentation Bug introduced by
It seems like '{"swagger":"2.0","info"...al","example":"2"}}}}}' of type string is incompatible with the declared type CloudControl\Cms\components\api\Response of property $response.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
55
            return;
56
        } catch (\Exception $e) {
57
            $error = $e->getFile() . ':' . $e->getLine() . ' ' . $e->getMessage();
58
            $this->response = new Response(array(), false, $error);
59
            return;
60
        }
61
    }
62
63
    /**
64
     * @return Document
65
     */
66
    private function getDocumentById()
67
    {
68
        $id = intval($_GET['id']);
69
        $db = $this->storage->getRepository()->getContentRepository()->getContentDbHandle();
70
        $stmt = $this->getPDOStatement($db, $this->getDocumentByIdSql($db, $id));
71
        return $stmt->fetchObject(Document::class);
72
    }
73
74
    /**
75
     * @param \PDO $db
76
     * @param int $id
77
     * @return string
78
     */
79
    private function getDocumentByIdSql($db, $id)
80
    {
81
        return 'SELECT *
82
              FROM documents_published
83
             WHERE id = ' . $db->quote($id) . '
84
        ';
85
    }
86
87
    /**
88
     * @param \PDO $db
89
     * @param string $sql
90
     * @return \PDOStatement
91
     */
92
    private function getPDOStatement($db, $sql)
93
    {
94
        $stmt = $db->query($sql);
95
        if ($stmt === false) {
96
            $errorInfo = $db->errorInfo();
97
            $errorMsg = $errorInfo[2];
98
            throw new \RuntimeException('SQLite Exception: ' . $errorMsg . ' in SQL: <br /><pre>' . $sql . '</pre>');
99
        }
100
        return $stmt;
101
    }
102
103
    /**
104
     * @return Response
105
     */
106
    private function getSingleDocumentResponse()
107
    {
108
        $document = $this->getDocumentById();
109
110
        if ($document === false) {
0 ignored issues
show
introduced by
The condition $document === false is always false.
Loading history...
111
            return new Response();
112
        }
113
114
        if ($document->type === 'folder') {
115
            return $this->getFolderResponse($document);
116
        }
117
118
        $documentContent = $this->getDocumentContent($document);
119
        $document->documentContent = $documentContent;
120
121
        return new Response($document);
122
    }
123
124
    /**
125
     * @param Application $application
126
     */
127
    public function render($application = null)
128
    {
129
        $this->renderedContent = $this->response;
130
    }
131
132
    /**
133
     * @return Response
134
     * @throws \Exception
135
     */
136
    private function getDocumentsByPathResponse()
137
    {
138
        $path = $_GET['path'];
139
        if (substr($path, 0, 1) === '/') {
140
            $path = substr($path, 1);
141
        }
142
        $folderDocument = $this->storage->getDocuments()->getDocumentFolderBySlug($path);
143
        if ($folderDocument !== false) {
144
            return $this->getFolderResponse($folderDocument);
0 ignored issues
show
Bug introduced by
It seems like $folderDocument can also be of type true; however, parameter $document of CloudControl\Cms\compone...nt::getFolderResponse() does only seem to accept CloudControl\Cms\storage\entities\Document, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

144
            return $this->getFolderResponse(/** @scrutinizer ignore-type */ $folderDocument);
Loading history...
145
        }
146
147
        return new Response();
148
    }
149
150
    /**
151
     * @return Response
152
     * @throws \Exception
153
     */
154
    private function getSearchDocumentsResponse()
155
    {
156
        $rawResults = $this->getRawResults();
157
        $results = array();
158
        $suggestions = array();
159
        foreach ($rawResults as $rawResult) {
160
            if ($rawResult instanceof SearchSuggestion) {
161
                $suggestions[] = $rawResults;
162
                continue;
163
            }
164
            $result = $rawResult->getDocument();
165
            $result->searchInfo = $rawResult;
166
            $results[] = $result;
167
        }
168
        $response = new Response($results);
169
        $response->searchSuggestions = $suggestions;
170
        return $response;
171
    }
172
173
    /**
174
     * @param Document $document
175
     * @return \stdClass
176
     */
177
    private function getDocumentContent($document)
178
    {
179
        $documentContent = new \stdClass();
180
        $documentContent->fields = $document->fields;
181
        $documentContent->bricks = $document->bricks;
182
        $documentContent->dynamicBricks = $document->dynamicBricks;
183
        return $documentContent;
184
    }
185
186
    /**
187
     * @return array
188
     * @throws \Exception
189
     */
190
    private function getRawResults()
191
    {
192
        $filteredQuery = new CharacterFilter($_GET['q']);
193
        $tokenizer = new Tokenizer($filteredQuery);
194
        $search = new Search($this->storage);
195
        $rawResults = $search->getDocumentsForTokenizer($tokenizer);
196
        return $rawResults;
197
    }
198
199
    /**
200
     * @param Document $document
201
     * @return Response
202
     */
203
    private function getFolderResponse($document)
204
    {
205
        if ($document->type !== 'folder') {
206
            return new Response();
207
        }
208
        $document->dbHandle = $this->storage->getContentDbHandle();
209
        $document->documentStorage = new DocumentStorage($this->storage->getRepository());
210
        $document->getContent();
211
        $response = new Response($document->getContent());
212
        $response->folder = $document->path;
213
        return $response;
214
    }
215
216
217
}