Issues (216)

src/GraphQL/Resolvers/Resolver.php (10 issues)

1
<?php
2
3
namespace DNADesign\Elemental\GraphQL\Resolvers;
4
5
use DNADesign\Elemental\Models\BaseElement;
6
use DNADesign\Elemental\Models\ElementalArea;
7
use DNADesign\Elemental\Services\ReorderElements;
8
use GraphQL\Type\Definition\ResolveInfo;
9
use SilverStripe\Core\Injector\Injector;
10
use SilverStripe\GraphQL\QueryHandler\QueryHandler;
0 ignored issues
show
The type SilverStripe\GraphQL\QueryHandler\QueryHandler was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use SilverStripe\GraphQL\QueryHandler\UserContextProvider;
0 ignored issues
show
The type SilverStripe\GraphQL\Que...ler\UserContextProvider was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use SilverStripe\ORM\ValidationException;
13
use InvalidArgumentException;
14
use Exception;
15
16
class Resolver
17
{
18
    /**
19
     * @param $value
20
     * @return object
21
     */
22
    public static function serialiseObjectType($value)
23
    {
24
        return (object) $value;
25
    }
26
27
    /**
28
     * @param $value
29
     * @return array
30
     */
31
    public static function parseValueObjectType($value)
32
    {
33
        return (array) $value;
34
    }
35
36
    /**
37
     * @param $ast
38
     * @return mixed
39
     */
40
    public static function parseLiteralObjectType($ast)
41
    {
42
        return $ast->value;
43
    }
44
45
    /**
46
     * @param $obj
47
     * @param array $args
48
     * @param array $context
49
     * @param ResolveInfo $info
50
     * @return BaseElement
51
     * @throws ValidationException
52
     * @throws InvalidArgumentException
53
     */
54
    public static function resolveAddElementToArea(
55
        $obj,
0 ignored issues
show
The parameter $obj is not used and could be removed. ( Ignorable by Annotation )

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

55
        /** @scrutinizer ignore-unused */ $obj,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
56
        array $args,
57
        array $context,
58
        ResolveInfo $info
0 ignored issues
show
The parameter $info is not used and could be removed. ( Ignorable by Annotation )

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

58
        /** @scrutinizer ignore-unused */ ResolveInfo $info

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
59
    ): BaseElement {
60
        $elementClass = $args['className'];
61
        $elementalAreaID = $args['elementalAreaID'];
62
        $afterElementID = $args['afterElementID'] ?? null;
63
64
        if (!is_subclass_of($elementClass, BaseElement::class)) {
65
            throw new InvalidArgumentException("$elementClass is not a subclass of " . BaseElement::class);
66
        }
67
68
        $elementalArea = ElementalArea::get()->byID($elementalAreaID);
69
70
        if (!$elementalArea) {
71
            throw new InvalidArgumentException("Invalid ElementalAreaID: $elementalAreaID");
72
        }
73
74
        $member = UserContextProvider::get($context);
75
        if (!$elementalArea->canEdit($member)) {
76
            throw new InvalidArgumentException("The current user has insufficient permission to edit ElementalAreas");
77
        }
78
79
        /** @var BaseElement $newElement */
80
        $newElement = Injector::inst()->create($elementClass);
81
82
        $member = UserContextProvider::get($context);
83
        if (!$newElement->canEdit($member)) {
84
            throw new InvalidArgumentException(
85
                'The current user has insufficient permission to edit Elements'
86
            );
87
        }
88
89
        // Assign the parent ID directly rather than via HasManyList to prevent multiple writes.
90
        // See BaseElement::$has_one for the "Parent" naming.
91
        $newElement->ParentID = $elementalArea->ID;
92
        // Ensure that a sort order is assigned - see BaseElement::onBeforeWrite()
93
        $newElement->onBeforeWrite();
94
95
        if ($afterElementID !== null) {
96
            /** @var ReorderElements $reorderer */
97
            $reorderer = Injector::inst()->create(ReorderElements::class, $newElement);
98
            $reorderer->reorder($afterElementID); // also writes the element
99
        } else {
100
            $newElement->write();
101
        }
102
103
        return $newElement;
104
    }
105
106
    /**
107
     * @param $object
108
     * @param array $args
109
     * @param $context
110
     * @param ResolveInfo $info
111
     * @return BaseElement
112
     * @throws ValidationException
113
     */
114
    public static function resolveDuplicateBlock($object, array $args, $context, ResolveInfo $info)
0 ignored issues
show
The parameter $info is not used and could be removed. ( Ignorable by Annotation )

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

114
    public static function resolveDuplicateBlock($object, array $args, $context, /** @scrutinizer ignore-unused */ ResolveInfo $info)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $object is not used and could be removed. ( Ignorable by Annotation )

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

114
    public static function resolveDuplicateBlock(/** @scrutinizer ignore-unused */ $object, array $args, $context, ResolveInfo $info)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
115
    {
116
        // load element to clone
117
        $elementID = $args['id'];
118
        $element = BaseElement::get_by_id($elementID);
119
        if (!$element) {
0 ignored issues
show
$element is of type DNADesign\Elemental\Models\BaseElement, thus it always evaluated to true.
Loading history...
120
            throw new InvalidArgumentException("Invalid BaseElementID: $elementID");
121
        }
122
123
        // check can edit the elemental area
124
        $areaID = $element->ParentID;
125
        $area = ElementalArea::get_by_id($areaID);
126
        if (!$area) {
0 ignored issues
show
$area is of type DNADesign\Elemental\Models\ElementalArea, thus it always evaluated to true.
Loading history...
127
            throw new InvalidArgumentException("Invalid ParentID on BaseElement: $elementID");
128
        }
129
        $member = UserContextProvider::get($context);
130
        if (!$area->canEdit($member)) {
131
            throw new InvalidArgumentException(
132
                "The current user has insufficient permission to edit ElementalArea: $areaID"
133
            );
134
        }
135
136
        try {
137
            // clone element
138
            $clone = $element->duplicate(false);
139
            $clone->Title = static::newTitle($clone->Title ?? '');
140
            $clone->Sort = 0; // must be zeroed for reorder to work
141
            $area->Elements()->add($clone);
142
143
            // reorder
144
            $reorderer = Injector::inst()->create(ReorderElements::class, $clone);
145
            $reorderer->reorder($elementID);
146
147
            return $clone;
148
        } catch (Exception $e) {
149
            throw new Exception("Something went wrong when duplicating element: $elementID");
150
        }
151
    }
152
153
    public static function newTitle(string $title = ''): ?string
154
    {
155
        $hasCopyPattern = '/^.*(\scopy($|\s[0-9]+$))/';
156
        $hasNumPattern = '/^.*(\s[0-9]+$)/';
157
        $parts = [];
158
159
        // does $title end with 'copy' (ignoring numbers for now)?
160
        if (preg_match($hasCopyPattern ?? '', $title ?? '', $parts)) {
161
            $copy = $parts[1];
162
            // does $title end with numbers?
163
            if (preg_match($hasNumPattern ?? '', $copy ?? '', $parts)) {
164
                $num = trim($parts[1] ?? '');
165
                $len = strlen($num ?? '');
166
                $inc = (int)$num + 1;
167
                return substr($title ?? '', 0, -$len) . "$inc";
168
            } else {
169
                return $title . ' 2';
170
            }
171
        } else {
172
            return $title . ' copy';
173
        }
174
    }
175
176
    public static function resolveSortBlock($object, array $args, $context, ResolveInfo $info)
0 ignored issues
show
The parameter $object is not used and could be removed. ( Ignorable by Annotation )

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

176
    public static function resolveSortBlock(/** @scrutinizer ignore-unused */ $object, array $args, $context, ResolveInfo $info)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
The parameter $info is not used and could be removed. ( Ignorable by Annotation )

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

176
    public static function resolveSortBlock($object, array $args, $context, /** @scrutinizer ignore-unused */ ResolveInfo $info)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
177
    {
178
        $element = BaseElement::get()->byID($args['id']);
179
180
        if (!$element) {
181
            throw new InvalidArgumentException(sprintf(
182
                '%s#%s not found',
183
                BaseElement::class,
184
                $args['ID']
185
            ));
186
        }
187
        $member = UserContextProvider::get($context);
188
        if (!$element->canEdit($member)) {
189
            throw new InvalidArgumentException(
190
                'Changing the sort order of blocks is not allowed for the current user'
191
            );
192
        }
193
194
        $reorderingService = Injector::inst()->create(ReorderElements::class, $element);
195
        return $reorderingService->reorder($args['afterBlockID']);
196
    }
197
}
198