GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

GraphQLPersistedQueryPostType   A
last analyzed

Complexity

Total Complexity 25

Size/Duplication

Total Lines 304
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 7
Bugs 0 Features 0
Metric Value
eloc 76
c 7
b 0
f 0
dl 0
loc 304
ccs 0
cts 72
cp 0
rs 10
wmc 25

17 Methods

Rating   Name   Duplication   Size   Complexity  
A doURLParamsOverrideGraphQLVariables() 0 10 2
A getTaxonomies() 0 4 1
A lockGutenbergTemplate() 0 3 1
A getExecuteActionLabel() 0 3 1
A getSlugBase() 0 3 1
A getPostTypeLabels() 0 9 1
A isPublic() 0 3 1
A usePostExcerptAsDescription() 0 3 1
A getPostType() 0 3 1
A getQueryExecutionOptionsBlock() 0 8 1
A getPostTypeName() 0 3 1
A getPostTypePluralNames() 0 3 1
A isHierarchical() 0 3 1
B getGraphQLQuerySourceContent() 0 60 6
A getGraphQLQueryAndVariables() 0 6 1
A getGutenbergTemplate() 0 20 1
A addGraphQLVars() 0 30 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace GraphQLAPI\GraphQLAPI\PostTypes;
6
7
use GraphQLAPI\GraphQLAPI\Blocks\PersistedQueryGraphiQLBlock;
8
use GraphQLAPI\GraphQLAPI\ComponentConfiguration;
9
use GraphQLAPI\GraphQLAPI\Security\UserAuthorization;
10
use GraphQLAPI\GraphQLAPI\General\BlockContentHelpers;
11
use PoP\ComponentModel\Facades\Instances\InstanceManagerFacade;
12
use GraphQLAPI\GraphQLAPI\Taxonomies\GraphQLQueryTaxonomy;
13
use GraphQLAPI\GraphQLAPI\Blocks\PersistedQueryOptionsBlock;
14
use GraphQLAPI\GraphQLAPI\General\GraphQLQueryPostTypeHelpers;
15
use GraphQLAPI\GraphQLAPI\Blocks\AbstractQueryExecutionOptionsBlock;
16
use GraphQLAPI\GraphQLAPI\PostTypes\AbstractGraphQLQueryExecutionPostType;
17
use GraphQLByPoP\GraphQLRequest\Hooks\VarsHooks as GraphQLRequestVarsHooks;
18
use WP_Post;
19
20
class GraphQLPersistedQueryPostType extends AbstractGraphQLQueryExecutionPostType
21
{
22
    /**
23
     * Custom Post Type name
24
     */
25
    public const POST_TYPE = 'graphql-query';
26
27
    /**
28
     * Custom Post Type name
29
     *
30
     * @return string
31
     */
32
    protected function getPostType(): string
33
    {
34
        return self::POST_TYPE;
35
    }
36
37
    /**
38
     * Access endpoints under /graphql-query, or wherever it is configured to
39
     *
40
     * @return string|null
41
     */
42
    protected function getSlugBase(): ?string
43
    {
44
        return ComponentConfiguration::getPersistedQuerySlugBase();
45
    }
46
47
    /**
48
     * Custom post type name
49
     */
50
    public function getPostTypeName(): string
51
    {
52
        return \__('GraphQL persisted query', 'graphql-api');
53
    }
54
55
    /**
56
     * Custom Post Type plural name
57
     *
58
     * @param bool $uppercase Indicate if the name must be uppercase (for starting a sentence) or, otherwise, lowercase
59
     * @return string
60
     */
61
    protected function getPostTypePluralNames(bool $uppercase): string
62
    {
63
        return \__('GraphQL persisted queries', 'graphql-api');
64
    }
65
66
    /**
67
     * Label to show on the "execute" action in the CPT table
68
     *
69
     * @return string
70
     */
71
    protected function getExecuteActionLabel(): string
72
    {
73
        return __('Execute query', 'graphql-api');
74
    }
75
76
    /**
77
     * Labels for registering the post type
78
     *
79
     * @param string $name_uc Singular name uppercase
80
     * @param string $names_uc Plural name uppercase
81
     * @param string $names_lc Plural name lowercase
82
     * @return array<string, string>
83
     */
84
    protected function getPostTypeLabels(string $name_uc, string $names_uc, string $names_lc): array
85
    {
86
        /**
87
         * Because the name is too long, shorten it for the admin menu only
88
         */
89
        return array_merge(
90
            parent::getPostTypeLabels($name_uc, $names_uc, $names_lc),
91
            array(
92
                'all_items' => \__('Persisted Queries', 'graphql-api'),
93
            )
94
        );
95
    }
96
97
    /**
98
     * The Query is publicly accessible, and the permalink must be configurable
99
     *
100
     * @return boolean
101
     */
102
    protected function isPublic(): bool
103
    {
104
        return true;
105
    }
106
107
    /**
108
     * Taxonomies
109
     *
110
     * @return string[]
111
     */
112
    protected function getTaxonomies(): array
113
    {
114
        return [
115
            GraphQLQueryTaxonomy::TAXONOMY_CATEGORY,
116
        ];
117
    }
118
119
    /**
120
     * Hierarchical
121
     */
122
    protected function isHierarchical(): bool
123
    {
124
        return true;
125
    }
126
127
    // /**
128
    //  * Show in admin bar
129
    //  *
130
    //  * @return bool
131
    //  */
132
    // protected function showInAdminBar(): bool
133
    // {
134
    //     return true;
135
    // }
136
137
    /**
138
     * Gutenberg templates to lock down the Custom Post Type to
139
     *
140
     * @return array<array> Every element is an array with template name in first pos, and attributes then
141
     */
142
    protected function getGutenbergTemplate(): array
143
    {
144
        $template = parent::getGutenbergTemplate();
145
146
        $instanceManager = InstanceManagerFacade::getInstance();
147
        /**
148
         * @var PersistedQueryGraphiQLBlock
149
         */
150
        $graphiQLBlock = $instanceManager->getInstance(PersistedQueryGraphiQLBlock::class);
151
        /**
152
         * Add before the SchemaConfiguration block
153
         */
154
        array_unshift($template, [$graphiQLBlock->getBlockFullName()]);
155
156
        /**
157
         * @var PersistedQueryOptionsBlock
158
         */
159
        $persistedQueryOptionsBlock = $instanceManager->getInstance(PersistedQueryOptionsBlock::class);
160
        $template[] = [$persistedQueryOptionsBlock->getBlockFullName()];
161
        return $template;
162
    }
163
164
    /**
165
     * Indicates if to lock the Gutenberg templates
166
     *
167
     * @return boolean
168
     */
169
    protected function lockGutenbergTemplate(): bool
170
    {
171
        return true;
172
    }
173
174
    /**
175
     * Indicate if the excerpt must be used as the CPT's description and rendered when rendering the post
176
     *
177
     * @return boolean
178
     */
179
    public function usePostExcerptAsDescription(): bool
180
    {
181
        return true;
182
    }
183
184
    /**
185
     * Add the parent query to the rendering of the GraphQL Query CPT
186
     */
187
    protected function getGraphQLQuerySourceContent(string $content, WP_Post $graphQLQueryPost): string
188
    {
189
        $content = parent::getGraphQLQuerySourceContent($content, $graphQLQueryPost);
190
191
        /**
192
         * If the GraphQL query has a parent, possibly it is missing the query/variables/acl/ccl attributes,
193
         * which inherits from some parent
194
         * In that case, render the block twice:
195
         * 1. The current block, with missing attributes
196
         * 2. The final block, completing the missing attributes from its parent
197
         */
198
        if ($graphQLQueryPost->post_parent) {
199
            $instanceManager = InstanceManagerFacade::getInstance();
200
            /**
201
             * @var PersistedQueryGraphiQLBlock
202
             */
203
            $graphiQLBlock = $instanceManager->getInstance(PersistedQueryGraphiQLBlock::class);
204
205
            // Check if the user is authorized to see the content
206
            $ancestorContent = null;
207
            if (UserAuthorization::canAccessSchemaEditor()) {
208
                /**
209
                 * If the query has a parent, also render the inherited output
210
                 */
211
                list(
212
                    $inheritQuery
213
                ) = BlockContentHelpers::getSinglePersistedQueryOptionsBlockAttributesFromPost($graphQLQueryPost);
214
                if ($inheritQuery) {
215
                    // Fetch the attributes using inheritance
216
                    list(
217
                        $inheritedGraphQLQuery,
218
                        $inheritedGraphQLVariables
219
                    ) = GraphQLQueryPostTypeHelpers::getGraphQLQueryPostAttributes($graphQLQueryPost, true);
220
                    // To render the variables in the block, they must be json_encoded
221
                    if ($inheritedGraphQLVariables) {
222
                        $inheritedGraphQLVariables = json_encode($inheritedGraphQLVariables);
223
                    }
224
                    // Render the block again, using the inherited attributes
225
                    $inheritedGraphQLBlockAttributes = [
226
                        PersistedQueryGraphiQLBlock::ATTRIBUTE_NAME_QUERY => $inheritedGraphQLQuery,
227
                        PersistedQueryGraphiQLBlock::ATTRIBUTE_NAME_VARIABLES => $inheritedGraphQLVariables,
228
                    ];
229
                    // Add the new rendering to the output, and a description for each
230
                    $ancestorContent = $graphiQLBlock->renderBlock($inheritedGraphQLBlockAttributes, '');
231
                }
232
            } else {
233
                $ancestorContent = $graphiQLBlock->renderUnauthorizedAccess();
234
            }
235
            if (!is_null($ancestorContent)) {
236
                $content = sprintf(
237
                    '%s%s<hr/>%s%s',
238
                    \__('<p><u>GraphQL query, inheriting properties from ancestor(s): </u></p>'),
239
                    $ancestorContent,
240
                    \__('<p><u>GraphQL query, as defined in this level: </u></p>'),
241
                    $content
242
                );
243
            }
244
        }
245
246
        return $content;
247
    }
248
249
    /**
250
     * Provide the query to execute and its variables
251
     *
252
     * @return mixed[] Array with 2 elements: [$graphQLQuery, $graphQLVariables]
253
     */
254
    protected function getGraphQLQueryAndVariables(?WP_Post $graphQLQueryPost): array
255
    {
256
        /**
257
         * Extract the query from the post (or from its parents), and set it in $vars
258
         */
259
        return GraphQLQueryPostTypeHelpers::getGraphQLQueryPostAttributes($graphQLQueryPost, true);
260
    }
261
262
    protected function getQueryExecutionOptionsBlock(): AbstractQueryExecutionOptionsBlock
263
    {
264
        $instanceManager = InstanceManagerFacade::getInstance();
265
        /**
266
         * @var PersistedQueryOptionsBlock
267
         */
268
        $block = $instanceManager->getInstance(PersistedQueryOptionsBlock::class);
269
        return $block;
270
    }
271
272
    /**
273
     * Indicate if the GraphQL variables must override the URL params
274
     *
275
     * @param WP_Post|int $postOrID
276
     */
277
    protected function doURLParamsOverrideGraphQLVariables($postOrID): bool
278
    {
279
        $default = true;
280
        $optionsBlockDataItem = $this->getOptionsBlockDataItem($postOrID);
281
        if (is_null($optionsBlockDataItem)) {
282
            return $default;
283
        }
284
285
        // `true` is the default option in Gutenberg, so it's not saved to the DB!
286
        return $optionsBlockDataItem['attrs'][PersistedQueryOptionsBlock::ATTRIBUTE_NAME_ACCEPT_VARIABLES_AS_URL_PARAMS] ?? $default;
287
    }
288
289
    /**
290
     * Check if requesting the single post of this CPT and, in this case, set the request with the needed API params
291
     *
292
     * @param array<array> $vars_in_array
293
     */
294
    public function addGraphQLVars(array $vars_in_array): void
295
    {
296
        if (\is_singular($this->getPostType())) {
297
            // Check if it is enabled, by configuration
298
            [&$vars] = $vars_in_array;
299
            if (!$this->isEnabled($vars['routing-state']['queried-object-id'])) {
300
                return;
301
            }
302
303
            $instanceManager = InstanceManagerFacade::getInstance();
304
            /** @var GraphQLRequestVarsHooks */
305
            $graphQLAPIRequestHookSet = $instanceManager->getInstance(GraphQLRequestVarsHooks::class);
306
307
            // The Persisted Query is also standard GraphQL
308
            $graphQLAPIRequestHookSet->setStandardGraphQLVars($vars);
309
310
            // Remove the VarsHooks from the GraphQLRequest, so it doesn't process the GraphQL query
311
            // Otherwise it will add error "The query in the body is empty"
312
            /**
313
             * @var callable
314
             */
315
            $action = [$graphQLAPIRequestHookSet, 'addVars'];
316
            \remove_action(
317
                'ApplicationState:addVars',
318
                $action,
319
                20
320
            );
321
322
            // Execute the original logic
323
            parent::addGraphQLVars($vars_in_array);
324
        }
325
    }
326
}
327