AdminPageFramework_Utility_ArraySetter   A
last analyzed

Complexity

Total Complexity 39

Size/Duplication

Total Lines 328
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 39
eloc 69
dl 0
loc 328
rs 9.28
c 0
b 0
f 0

11 Methods

Rating   Name   Duplication   Size   Complexity  
A dropElementsByType() 0 7 3
A invertCastArrayContents() 0 10 3
A unsetDimensionalArrayElement() 0 11 5
A dropElementByValue() 0 10 3
A dropElementsByKey() 0 6 2
A numerizeElements() 0 11 3
A setMultiDimensionalArray() 0 12 4
A sortArrayByKey() 0 4 2
B uniteArraysRecursive() 0 30 10
A uniteArrays() 0 10 2
A castArrayContents() 0 11 2
1
<?php
2
/**
3
 * Admin Page Framework
4
 * 
5
 * http://admin-page-framework.michaeluno.jp/
6
 * Copyright (c) 2013-2022, Michael Uno; Licensed MIT
7
 * 
8
 */
9
10
/**
11
 * Provides utility methods dealing with PHP arrays which do not use WordPress functions.
12
 *
13
 * Listed methods are to modify array contents.
14
 * 
15
 * @since       3.7.0
16
 * @package     AdminPageFramework/Utility
17
 * @extends     AdminPageFramework_Utility_String
18
 * @internal
19
 */
20
abstract class AdminPageFramework_Utility_ArraySetter extends AdminPageFramework_Utility_ArrayGetter {
21
 
22
    /**
23
     * Calculates the subtraction of two values with the array key of `order`.
24
     * 
25
     * This is used to sort arrays.
26
     * 
27
     * @since       2.0.0
28
     * @since       3.0.0       Moved from the property class.
29
     * @since       3.3.1       Moved from `AdminPageFramework_Base`.
30
     * @since       3.6.0       Moved from `AdminPageFramework_Router`.
31
     * @since       3.7.0       Moved from `AdminPageFramework_Utility`.
32
     * @remark      a callback method for `uasort()`.
33
     * @return      integer
34
     * @internal
35
     */        
36
    static public function sortArrayByKey( $a, $b, $sKey='order' ) {
37
        return isset( $a[ $sKey ], $b[ $sKey ] )
38
            ? $a[ $sKey ] - $b[ $sKey ]
39
            : 1;
40
    }
41
 
42
    /**
43
     * Unsets an element of a multi-dimensional array by given keys.
44
     * 
45
     * <code>
46
     * $a = array(
47
     *  'a' => array(
48
     *      'b' => array(
49
     *          'c' => array(
50
     *              'd' => array(
51
     *                  'e' => 'eee',
52
     *              ),
53
     *          ),
54
     *      ),
55
     *  ),
56
     *  );
57
     *  $aKeys = array( 'a', 'b', 'c' );
58
     *  unsetDimensionalArrayElement( $a, $aKeys );
59
     *  var_dump( $a );
60
     * </code>
61
     * Will produce
62
     * <code>
63
     * array(
64
     *  'a' => array(
65
     *      'b' => array(
66
     *      )
67
     *  )
68
     * )
69
     * </code>
70
     * 
71
     * @remark      Introduced for resetting options with dimensional keys.
72
     * @since       3.5.3
73
     * @since       3.7.0       Moved from `AdminPageFramework_Utility_Array`.
74
     * @return      void
75
     */
76
    static public function unsetDimensionalArrayElement( &$mSubject, array $aKeys ) {
77
        
78
        $_sKey = array_shift( $aKeys );
79
        if ( ! empty( $aKeys ) ) {
80
            if ( isset( $mSubject[ $_sKey ] ) && is_array( $mSubject[ $_sKey ] ) ) {
81
                self::unsetDimensionalArrayElement( $mSubject[ $_sKey ], $aKeys );
82
            }
83
            return;            
84
        }
85
        if ( is_array( $mSubject ) ) {
86
            unset( $mSubject[ $_sKey ] );
87
        }
88
        
89
    }
90
    
91
    /**
92
     * Sets a dimensional array value by dimensional array key path.
93
     * @since       3.5.3
94
     * @since       3.7.0       Moved from `AdminPageFramework_Utility_Array`.
95
     * @return      void
96
     */
97
    static public function setMultiDimensionalArray( &$mSubject, array $aKeys, $mValue ) {
98
99
        $_sKey = array_shift( $aKeys );
100
        if ( ! empty( $aKeys ) ) {
101
            if( ! isset( $mSubject[ $_sKey ] ) || ! is_array( $mSubject[ $_sKey ] ) ) {
102
                $mSubject[ $_sKey ] = array();
103
            }
104
            self::setMultiDimensionalArray( $mSubject[ $_sKey ], $aKeys, $mValue );
105
            return;
106
            
107
        }
108
        $mSubject[ $_sKey ] = $mValue;
109
110
    }     
111
 
112
    /**
113
     * Reconstructs the given array by numerizing the keys. 
114
     * 
115
     * @since       3.0.0
116
     * @since       3.5.3       Added a type hint in the first parameter.
117
     * @since       3.7.0       Moved from `AdminPageFramework_Utility_Array`.
118
     * @return      array       The passed array structure looks like this.
119
     * <code>
120
     *   array( 
121
     *      0 => array(
122
     *          'field_id_1' => array( ... ),
123
     *          'field_id_2' => array( ... ),
124
     *      ), 
125
     *      1 => array(
126
     *          'field_id_1' => array( ... ),
127
     *          'field_id_2' => array( ... ),
128
     *      ),
129
     *      'field_id_1' => array( ... ),
130
     *      'field_id_2' => array( ... ),
131
     *   )
132
     * </code>
133
     * It will be converted to to
134
     * <code>
135
     *   array(
136
     *      0 => array(
137
     *          'field_id_1' => array( ... ),
138
     *          'field_id_2' => array( ... ),
139
     *      ), 
140
     *      1 => array(
141
     *          'field_id_1' => array( ... ),
142
     *          'field_id_2' => array( ... ),
143
     *      ),     
144
     *      2 => array(
145
     *          'field_id_1' => array( ... ),
146
     *          'field_id_2' => array( ... ),
147
     *      ),
148
     *   )
149
     * </code>
150
     */
151
    static public function numerizeElements( array $aSubject ) {
152
153
        $_aNumeric      = self::getIntegerKeyElements( $aSubject );
154
        $_aAssociative  = self::invertCastArrayContents( $aSubject, $_aNumeric );
155
        foreach( $_aNumeric as &$_aElem ) {
156
            $_aElem = self::uniteArrays( $_aElem, $_aAssociative );
157
        }
158
        if ( ! empty( $_aAssociative ) ) {
159
            array_unshift( $_aNumeric, $_aAssociative ); // insert the main section to the beginning of the array.
160
        }
161
        return $_aNumeric;
162
        
163
    }
164
 
165
    /**
166
     * Casts array contents into another while keeping the same key structure.
167
     * 
168
     * @since       3.0.0
169
     * @since       3.5.3       Added type hints to the parameter.
170
     * @since       3.7.0       Moved from `AdminPageFramework_Utility_Array`.
171
     * @remark      It does not check key structure deeper than or equal to the second dimension.
172
     * @remark      If a key exists in the passed model array but does not exists in the subject array, 
173
     * a `null` value will be assigned to the resulting array.
174
     * @param       array       $aModel         the array that holds the necessary keys.
175
     * @param       array       $aSubject       the array from which the contents to be extracted.
176
     * @return      array       the extracted array contents with the keys of the model array.
177
     */
178
    public static function castArrayContents( array $aModel, array $aSubject ) {
179
        
180
        $_aCast = array();
181
        foreach( $aModel as $_isKey => $_v ) {
182
            $_aCast[ $_isKey ] = self::getElement(
183
                $aSubject,  // subject array
184
                $_isKey,    // key
185
                null        // default
186
            );                 
187
        }
188
        return $_aCast;
189
        
190
    }
191
    
192
    /**
193
     * Returns an array consisting of keys which don't exist in the other.
194
     * 
195
     * @since       3.0.0
196
     * @since       3.7.0       Moved from `AdminPageFramework_Utility_Array`.
197
     * @remark      It won't check key structure deeper than or equal to the second dimension.
198
     * @param       array     $aModel       the array that holds the necessary keys.
199
     * @param       array     $aSubject     the array from which the contents to be extracted.
200
     * @return      array     the extracted array contents with the keys that do not exist in the model array.
201
     */
202
    public static function invertCastArrayContents( array $aModel, array $aSubject ) {
203
        
204
        $_aInvert = array();
205
        foreach( $aModel as $_isKey => $_v ) {
206
            if ( array_key_exists( $_isKey, $aSubject ) ) { 
207
                continue; 
208
            }
209
            $_aInvert[ $_isKey ] = $_v;
210
        }
211
        return $_aInvert;
212
        
213
    }
214
    
215
    /**
216
     * Merges multiple multi-dimensional arrays recursively.
217
     * 
218
     * The advantage of using this method over the array unite operator or `array_merge() is 
219
     * that it merges recursively and the null values of the preceding array will be overridden.
220
     * 
221
     * @since       2.1.2
222
     * @since       3.7.0       Moved from `AdminPageFramework_Utility_Array`.
223
     * @static
224
     * @access      public
225
     * @remark      The parameters are variadic and can add arrays as many as necessary.
226
     * @return      array     the united array.
227
     */
228
    public static function uniteArrays( /* $aPrecedence, $aArray1, $aArray2, ... */ ) {
229
                
230
        $_aArray = array();
231
        foreach( array_reverse( func_get_args() ) as $_aArg ) {
232
            $_aArray = self::uniteArraysRecursive( 
233
                self::getAsArray( $_aArg ), 
234
                $_aArray 
235
            );
236
        }
237
        return $_aArray;
238
        
239
    }
240
    
241
    /**
242
     * Merges two multi-dimensional arrays recursively.
243
     * 
244
     * The first parameter array takes its precedence. This is useful to merge default option values. 
245
     * An alternative to `array_replace_recursive()` which is not available PHP 5.2.x or below.
246
     * 
247
     * @since       2.0.0
248
     * @since       2.1.5       Changed the visibility scope to `static`. 
249
     * @since       3.7.0       Moved from `AdminPageFramework_Utility_Array`.
250
     * @access      public
251
     * @remark      null values will be overwritten.     
252
     * @param       array     the array that overrides the same keys.
253
     * @param       array     the array that is going to be overridden.
254
     * @return      array     the united array.
255
     */ 
256
    public static function uniteArraysRecursive( $aPrecedence, $aDefault ) {
257
                
258
        if ( is_null( $aPrecedence ) ) { 
259
            $aPrecedence = array(); 
260
        }
261
                
262
        if ( ! is_array( $aDefault ) || ! is_array( $aPrecedence ) ) { 
263
            return $aPrecedence; 
264
        }
265
        
266
        // For cases like `array( $this, 'callbackFunc' )`
267
        if ( is_callable( $aPrecedence ) ) {
268
            return $aPrecedence;
269
        }
270
        
271
        foreach( $aDefault as $sKey => $v ) {
272
            
273
            // If the precedence does not have the key, assign the default's value.
274
            if ( ! array_key_exists( $sKey, $aPrecedence ) || is_null( $aPrecedence[ $sKey ] ) ) {
275
                $aPrecedence[ $sKey ] = $v;
276
            } else {
277
                
278
                // if the both are arrays, do the recursive process.
279
                if ( is_array( $aPrecedence[ $sKey ] ) && is_array( $v ) ) {
280
                    $aPrecedence[ $sKey ] = self::uniteArraysRecursive( $aPrecedence[ $sKey ], $v );     
281
                }
282
            
283
            }
284
        }
285
        return $aPrecedence;     
286
    }
287
 
288
    /**
289
     * Removes array elements by the specified type.
290
     * 
291
     * @since       3.3.1
292
     * @since       3.7.0       Moved from `AdminPageFramework_Utility_Array`.
293
     * @param       array       $aArray     The subject array to parse.
294
     * @param       array       $aTypes     The value types to drop. The supported types are the followings.
295
     *  - boolean
296
     *  - integer
297
     *  - double
298
     *  - string
299
     *  - array 
300
     *  - object
301
     *  - resource
302
     *  - NULL
303
     * @return      array       The modified array.
304
     */
305
    static public function dropElementsByType( array $aArray, $aTypes=array( 'array' ) ) {
306
        foreach( $aArray as $isKey => $vValue ) {
307
            if ( in_array( gettype( $vValue ), $aTypes, true ) ) {
308
                unset( $aArray[ $isKey ] );
309
            }
310
        }
311
        return $aArray;
312
    }
313
    
314
    /**
315
     * Removes an array element(s) by the given value.
316
     * @since       3.4.0
317
     * @since       3.7.0       Moved from `AdminPageFramework_Utility_Array`.
318
     * @return      array       The modified array.
319
     */
320
    static public function dropElementByValue( array $aArray, $vValue ) {
321
         
322
        foreach( self::getAsArray( $vValue, true ) as $_vValue ) {
323
            $_sKey = array_search( $_vValue, $aArray, true );
324
            if ( $_sKey === false ) {
325
                continue;
326
            }
327
            unset( $aArray[ $_sKey ] );
328
        }
329
        return $aArray;
330
        
331
    }
332
    
333
    /**
334
     * Removes given keys from the array.
335
     * 
336
     * This is used to drop unnecessary keys for a multidimensional array as multidimensinal arrays can cause PHP warnings used with `array_diff()`.
337
     * 
338
     * @since       3.4.6
339
     * @since       3.7.0       Moved from `AdminPageFramework_Utility_Array`.
340
     * @return      array       The modified array.
341
     */
342
    static public function dropElementsByKey( array $aArray, $asKeys ) {
343
        
344
        foreach( self::getAsArray( $asKeys, true ) as $_isKey ) {
345
            unset( $aArray[ $_isKey ] );
346
        }
347
        return $aArray;
348
        
349
    }  
350
   
351
}
352