Completed
Branch dev (1ad2e5)
by
unknown
04:33
created

uniteArraysRecursive()   D

Complexity

Conditions 9
Paths 10

Size

Total Lines 26
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

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