AddElementToAreaMutation::resolve()   B
last analyzed

Complexity

Conditions 7
Paths 12

Size

Total Lines 44
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 2
Metric Value
cc 7
eloc 22
c 2
b 0
f 2
nc 12
nop 4
dl 0
loc 44
rs 8.6346
1
<?php
2
3
namespace DNADesign\Elemental\GraphQL;
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 GraphQL\Type\Definition\Type;
10
use InvalidArgumentException;
11
use SilverStripe\Core\Injector\Injector;
12
use SilverStripe\GraphQL\MutationCreator;
13
use SilverStripe\GraphQL\OperationResolver;
14
use SilverStripe\GraphQL\Scaffolding\StaticSchema;
15
16
class AddElementToAreaMutation extends MutationCreator implements OperationResolver
17
{
18
    public function attributes()
19
    {
20
        return [
21
            'name' => 'addElementToArea',
22
            'description' => 'Adds an Element to an ElementalArea, optionally after another Element'
23
        ];
24
    }
25
26
    public function type()
27
    {
28
        return $this->manager->getType(StaticSchema::inst()->typeNameForDataObject(BaseElement::class));
29
    }
30
31
    public function args()
32
    {
33
        return [
34
            'ClassName' => ['type' => Type::nonNull(Type::string())],
35
            'ElementalAreaID' => ['type' => Type::nonNull(Type::id())],
36
            'AfterElementID' => ['type' => Type::id()],
37
        ];
38
    }
39
40
    public function resolve($object, array $args, $context, ResolveInfo $info)
41
    {
42
        $elementClass = $args['ClassName'];
43
        $elementalAreaID = $args['ElementalAreaID'];
44
        $afterElementID = isset($args['AfterElementID']) ? $args['AfterElementID'] : null;
45
46
        if (!is_subclass_of($elementClass, BaseElement::class)) {
47
            throw new InvalidArgumentException("$elementClass is not a subclass of " . BaseElement::class);
48
        }
49
50
        $elementalArea = ElementalArea::get()->byID($elementalAreaID);
51
52
        if (!$elementalArea) {
0 ignored issues
show
introduced by
$elementalArea is of type SilverStripe\ORM\DataObject, thus it always evaluated to true.
Loading history...
53
            throw new InvalidArgumentException("Invalid ElementalAreaID: $elementalAreaID");
54
        }
55
56
        if (!$elementalArea->canEdit($context['currentUser'])) {
57
            throw new InvalidArgumentException("The current user has insufficient permission to edit ElementalAreas");
58
        }
59
60
        /** @var BaseElement $newElement */
61
        $newElement = Injector::inst()->create($elementClass);
62
63
        if (!$newElement->canEdit($context['currentUser'])) {
64
            throw new InvalidArgumentException(
65
                'The current user has insufficient permission to edit Elements'
66
            );
67
        }
68
69
        // Assign the parent ID directly rather than via HasManyList to prevent multiple writes.
70
        // See BaseElement::$has_one for the "Parent" naming.
71
        $newElement->ParentID = $elementalArea->ID;
0 ignored issues
show
Bug Best Practice introduced by
The property ParentID does not exist on DNADesign\Elemental\Models\BaseElement. Since you implemented __set, consider adding a @property annotation.
Loading history...
72
        // Ensure that a sort order is assigned - see BaseElement::onBeforeWrite()
73
        $newElement->onBeforeWrite();
74
75
        if ($afterElementID !== null) {
76
            /** @var ReorderElements $reorderer */
77
            $reorderer = Injector::inst()->create(ReorderElements::class, $newElement);
78
            $reorderer->reorder($afterElementID); // also writes the element
79
        } else {
80
            $newElement->write();
81
        }
82
83
        return $newElement;
84
    }
85
}
86