Completed
Branch deps-array-update (1dbcd6)
by
unknown
52:00 queued 42:11
created

EntityReorder   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 147
Duplicated Lines 0 %

Coupling/Cohesion

Components 0
Dependencies 6

Importance

Changes 0
Metric Value
dl 0
loc 147
rs 10
c 0
b 0
f 0
wmc 16
lcom 0
cbo 6

2 Methods

Rating   Name   Duplication   Size   Complexity  
B mutateAndGetPayload() 0 59 4
C prepareEntityDetailsFromInput() 0 73 12
1
<?php
2
3
namespace EventEspresso\core\domain\services\graphql\mutators;
4
5
use EE_Registry;
6
use EEM_Base;
7
use EE_Base_Class;
8
9
use EE_Error;
10
use EventEspresso\core\exceptions\ExceptionStackTraceDisplay;
11
use Exception;
12
use InvalidArgumentException;
13
use ReflectionException;
14
use EventEspresso\core\exceptions\InvalidDataTypeException;
15
use EventEspresso\core\exceptions\InvalidInterfaceException;
16
17
use GraphQL\Type\Definition\ResolveInfo;
18
use RuntimeException;
19
use WPGraphQL\AppContext;
20
use GraphQL\Error\UserError;
21
use GraphQLRelay\Relay;
22
23
class EntityReorder
24
{
25
    /**
26
     * Defines the mutation data modification closure.
27
     *
28
     * @return callable
29
     */
30
    public static function mutateAndGetPayload()
31
    {
32
        /**
33
         * Updates an entity.
34
         *
35
         * @param array       $input   The input for the mutation
36
         * @param AppContext  $context The AppContext passed down to all resolvers
37
         * @param ResolveInfo $info    The ResolveInfo passed down to all resolvers
38
         * @return array
39
         * @throws UserError
40
         * @throws ReflectionException
41
         * @throws InvalidArgumentException
42
         * @throws InvalidInterfaceException
43
         * @throws InvalidDataTypeException
44
         * @throws EE_Error
45
         */
46
        return static function ($input, AppContext $context, ResolveInfo $info) {
47
            /**
48
             * Stop now if a user isn't allowed to reorder.
49
             */
50
            if (! current_user_can('ee_edit_events')) {
51
                throw new UserError(
52
                    esc_html__('Sorry, you do not have the required permissions to reorder entities', 'event_espresso')
53
                );
54
            }
55
56
            $details = EntityReorder::prepareEntityDetailsFromInput($input);
57
58
            $orderKey  = $details['keyPrefix'] . '_order'; // e.g. "TKT_order"
59
60
            $ok = false;
61
62
            // We do not want to continue reorder if one fails.
63
            // Thus wrap whole loop in try-catch
64
            try {
65
                foreach ($details['entityDbids'] as $order => $entityDbid) {
66
                    $args = [
67
                        $orderKey => $order + 1,
68
                    ];
69
                    $details['entities'][ $entityDbid ]->save($args);
70
                }
71
                $ok = true;
72
            } catch (Exception $exception) {
73
                new ExceptionStackTraceDisplay(
74
                    new RuntimeException(
75
                        sprintf(
76
                            esc_html__(
77
                                'Failed to update order because of the following error(s): %1$s',
78
                                'event_espresso'
79
                            ),
80
                            $exception->getMessage()
81
                        )
82
                    )
83
                );
84
            }
85
86
            return compact('ok');
87
        };
88
    }
89
90
    /**
91
     * Prepares entity details to use for mutations
92
     * @param array       $input   The input for the mutation
93
     *
94
     * @return array
95
     */
96
    public static function prepareEntityDetailsFromInput($input)
97
    {
98
        $entityGuids = ! empty($input['entityIds']) ? array_map('sanitize_text_field', (array) $input['entityIds']) : [];
99
        $entityType  = ! empty($input['entityType']) ? sanitize_text_field($input['entityType']) : null;
100
101
        /**
102
         * Make sure we have the IDs and entity type
103
         */
104
        if (empty($entityGuids) || empty($entityType)) {
105
            throw new UserError(
106
                // translators: the placeholders are the names of the fields
107
                sprintf(esc_html__('%1$s and %2$s are required.', 'event_espresso'), 'entityIds', 'entityType')
108
            );
109
        }
110
111
        $model = EE_Registry::instance()->load_model($entityType);
112
113
        if (!($model instanceof EEM_Base)) {
114
            throw new UserError(
115
                esc_html__(
116
                    'A valid data model could not be obtained. Did you supply a valid entity type?',
117
                    'event_espresso'
118
                )
119
            );
120
        }
121
122
        // convert GUIDs to DB IDs
123
        $entityDbids = array_map(function ($entityGuid) {
124
            $id_parts = Relay::fromGlobalId($entityGuid);
125
            return ! empty($id_parts['id']) ? absint($id_parts['id']) : 0;
126
        }, (array) $entityGuids);
127
        // remove 0 values
128
        $entityDbids = array_filter($entityDbids);
129
130
        /**
131
         * If we could not get DB IDs for some GUIDs
132
         */
133
        if (count($entityDbids) !== count($entityGuids)) {
134
            throw new UserError(
135
                esc_html__('Sorry, operation cancelled due to missing or invalid entity IDs.', 'event_espresso')
136
            );
137
        }
138
139
        // e.g. DTT_ID, TKT_ID
140
        $primaryKey = $model->get_primary_key_field()->get_name();
141
        // e.g. "DTT_ID" will give us "DTT"
142
        $keyPrefix = explode('_', $primaryKey)[0];
143
        $deletedKey  = $keyPrefix . '_deleted'; // e.g. "TKT_deleted"
144
145
        $entities = $model::instance()->get_all([
146
            [
147
                $primaryKey => ['IN', $entityDbids],
148
                $deletedKey => ['IN', [true, false]],
149
            ],
150
        ]);
151
152
        /**
153
         * If we could not get exactly same number of entities for the given DB IDs
154
         */
155
        if (count($entityDbids) !== count($entities)) {
156
            throw new UserError(esc_html__('Sorry, operation cancelled due to missing entities.', 'event_espresso'));
157
        }
158
159
        // Make sure we have an instance for every ID.
160
        foreach ($entityDbids as $entityDbid) {
161
            if (isset($entities[ $entityDbid ]) && $entities[ $entityDbid ] instanceof EE_Base_Class) {
162
                continue;
163
            }
164
            throw new UserError(esc_html__('Sorry, operation cancelled due to invalid entities.', 'event_espresso'));
165
        }
166
167
        return compact('entities', 'entityGuids', 'entityDbids', 'entityType', 'keyPrefix');
168
    }
169
}
170