Completed
Push — master ( ff1c82...da0740 )
by
unknown
12s
created

src/GraphQL/SortBlockMutationCreator.php (7 issues)

1
<?php
2
namespace DNADesign\Elemental\GraphQL;
3
4
use DNADesign\Elemental\Models\BaseElement;
5
use GraphQL\Type\Definition\ResolveInfo;
0 ignored issues
show
The type GraphQL\Type\Definition\ResolveInfo 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...
6
use GraphQL\Type\Definition\Type;
0 ignored issues
show
The type GraphQL\Type\Definition\Type 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...
7
use SilverStripe\Core\Convert;
8
use SilverStripe\GraphQL\MutationCreator;
0 ignored issues
show
The type SilverStripe\GraphQL\MutationCreator 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...
9
use SilverStripe\GraphQL\OperationResolver;
0 ignored issues
show
The type SilverStripe\GraphQL\OperationResolver 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...
10
use SilverStripe\ORM\DataObject;
11
use SilverStripe\ORM\Queries\SQLUpdate;
12
13
/**
14
 * Given a source block ID and the ID of the block to reorder the source block after, update all affected sort
15
 * orders for the block and its siblings. Only the source block will have a new version written, all siblings
16
 * will be updated underneath the ORM to avoid this.
17
 */
18
class SortBlockMutationCreator extends MutationCreator implements OperationResolver
19
{
20
    public function attributes()
21
    {
22
        return [
23
            'name' => 'sortBlock',
24
            'description' => 'Changes the sort position of an element'
25
        ];
26
    }
27
28
    public function type()
29
    {
30
        return $this->manager->getType('Block');
31
    }
32
33
    public function args()
34
    {
35
        return [
36
            'ID' => ['type' => Type::nonNull(Type::id())],
37
            'AfterBlockID' => ['type' => Type::nonNull(Type::id())],
38
        ];
39
    }
40
41
    public function resolve($object, array $args, $context, ResolveInfo $info)
42
    {
43
        /** @var BaseElement $block */
44
        $block = BaseElement::get_by_id($args['ID']);
45
46
        if (!$block) {
0 ignored issues
show
$block is of type DNADesign\Elemental\Models\BaseElement, thus it always evaluated to true. If $block can have other possible types, add them to src/GraphQL/SortBlockMutationCreator.php:43
Loading history...
47
            throw new \InvalidArgumentException(sprintf(
48
                '%s#%s not found',
49
                BaseElement::class,
50
                $args['ID']
51
            ));
52
        }
53
54
        if (!$block->canEdit($context['currentUser'])) {
55
            throw new \InvalidArgumentException(
56
                'Changing the sort order of blocks is not allowed'
57
            );
58
        }
59
60
        $parentId = $block->ParentID;
0 ignored issues
show
Bug Best Practice introduced by
The property ParentID does not exist on DNADesign\Elemental\Models\BaseElement. Since you implemented __get, consider adding a @property annotation.
Loading history...
61
        $blockPosition = (int) $block->Sort;
62
63
        $sortAfterPosition = 0;
64
        $afterBlockID = $args['AfterBlockID'];
65
        if ($afterBlockID) {
66
            /** @var BaseElement $afterBlock */
67
            $afterBlock = BaseElement::get_by_id($afterBlockID);
68
69
            if (!$afterBlock) {
0 ignored issues
show
$afterBlock is of type DNADesign\Elemental\Models\BaseElement, thus it always evaluated to true. If $afterBlock can have other possible types, add them to src/GraphQL/SortBlockMutationCreator.php:66
Loading history...
70
                throw new \InvalidArgumentException(
71
                    'Trying to sort block after a block in a different elemental area'
72
                );
73
            }
74
            if ($afterBlock->ParentID !== $parentId) {
75
                throw new \InvalidArgumentException(sprintf(
76
                    '%s#%s not found',
77
                    BaseElement::class,
78
                    $parentId
79
                ));
80
            }
81
82
            $sortAfterPosition = (int) $afterBlock->Sort;
83
        }
84
85
        // We are updating records with SQL queries to avoid the ORM triggering the creation of new versions
86
        // for each element that is affected by this reordering.
87
        $tableName = Convert::raw2sql(DataObject::getSchema()->tableName(BaseElement::class));
88
89
        if ($sortAfterPosition < $blockPosition) {
90
            $operator = '+';
91
            $filter = "\"$tableName\".\"Sort\" > $sortAfterPosition AND \"$tableName\".\"Sort\" < $blockPosition";
92
            $newBlockPosition = $sortAfterPosition + 1;
93
        } else {
94
            $operator = '-';
95
            $filter = "\"$tableName\".\"Sort\" <= $sortAfterPosition AND \"$tableName\".\"Sort\" > $blockPosition";
96
            $newBlockPosition = $sortAfterPosition;
97
        }
98
99
        $query = SQLUpdate::create()
100
           ->setTable("\"$tableName\"")
101
           ->assignSQL('"Sort"', "\"$tableName\".\"Sort\" $operator 1")
102
           ->addWhere([$filter, "\"$tableName\".\"ParentID\"" => $parentId]);
103
104
        $query->execute();
105
106
        // Now use the ORM to write a new version of the record that we are directly reordering
107
        $block->Sort = $newBlockPosition;
108
        $block->write();
109
110
        return $block;
111
    }
112
}
113