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

_shouldProceedValidation()   C

Complexity

Conditions 7
Paths 6

Size

Total Lines 26
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 12
nc 6
nop 1
dl 0
loc 26
rs 6.7272
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
 * Handles retrieving data from the database and the submitted $_POST array.
12
 *
13
 * @abstract
14
 * @since           3.3.0
15
 * @package         AdminPageFramework
16
 * @subpackage      Factory/MetaBox
17
 * @internal
18
 */
19
abstract class AdminPageFramework_MetaBox_Model extends AdminPageFramework_MetaBox_Router {
20
    
21
    /**
22
     * Sets up hooks.
23
     * @since       3.7.9
24
     */
25
    public function __construct( $sMetaBoxID, $sTitle, $asPostTypeOrScreenID=array( 'post' ), $sContext='normal', $sPriority='default', $sCapability='edit_posts', $sTextDomain='admin-page-framework' ) {
26
         
27
        // This is important to set the hooks before the parent constructor 
28
        // as the setUp wil be called in there if the default action hook (current_screen) is already triggered.
29
        add_action( 'set_up_' . $this->oProp->sClassName, array( $this, '_replyToSetUpHooks' ) );
30
        add_action( 'set_up_' . $this->oProp->sClassName, array( $this, '_replyToSetUpValidationHooks' ) );                
31
                
32
        parent::__construct( 
33
            $sMetaBoxID, 
34
            $sTitle, 
35
            $asPostTypeOrScreenID, 
36
            $sContext, 
37
            $sPriority, 
38
            $sCapability, 
39
            $sTextDomain 
40
        );
41
                
42
    }    
43
    
44
    /**
45
     * Sets up hooks after calling the `setUp()` method.
46
     * 
47
     * @since       3.7.9
48
     * @callback    action      set_up_{instantiated class name}
49
     * @internal
50
     */
51
    public function _replyToSetUpHooks( $oFactory ) {
0 ignored issues
show
Unused Code introduced by
The parameter $oFactory is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
52
        $this->oUtil->registerAction(
53
            'add_meta_boxes',
54
            array( $this, '_replyToRegisterMetaBoxes' )
55
        );
56
    }
57
    
58
    /**
59
     * Sets up validation hooks.
60
     * 
61
     * @since       3.3.0
62
     * @since       3.7.9       Renamed from `_setUpValidationHooks`. Changed the scope to public from protected.
63
     * @callback    action      set_up_{instantiated class name}
64
     * @internal
65
     */
66
    public function _replyToSetUpValidationHooks( $oScreen ) {
67
68
        if ( 'attachment' === $oScreen->post_type && in_array( 'attachment', $this->oProp->aPostTypes ) ) {
69
            add_filter( 
70
                'wp_insert_attachment_data', 
71
                array( $this, '_replyToFilterSavingData' ), 
72
                10, 
73
                2 
74
            );
75
        } else {
76
            add_filter( 
77
                'wp_insert_post_data', 
78
                array( $this, '_replyToFilterSavingData' ), 
79
                10, 
80
                2 
81
            );
82
        }
83
    
84
    }    
85
    
86
    /**
87
     * A validation callback method.
88
     * 
89
     * The user may just override this method instead of defining a `validation_{...}` callback method.
90
     * 
91
     * @since       3.4.1
92
     * @since       3.5.3       Moved from `AdminPageFramework_Factory_Model`. or not.
93
     * @remark      Do not even declare this method to avoid PHP strict standard warnings.
94
     */
95
    // public function validate( $aInput, $aOldInput, $oFactory ) {
96
        // return $aInput;
97
    // }         
98
        
99
    /**
100
     * Adds the defined meta box.
101
     * 
102
     * @since       2.0.0
103
     * @since       3.7.10      Changed the name from `_replyToAddMetaBox()`.
104
     * @internal
105
     * @uses        add_meta_box()
106
     * @return      void
107
     * @callback    action      add_meta_boxes
108
     */ 
109
    public function _replyToRegisterMetaBoxes() {
110
        foreach( $this->oProp->aPostTypes as $sPostType ) {
111
            add_meta_box( 
112
                $this->oProp->sMetaBoxID,                       // id
113
                $this->oProp->sTitle,                           // title
114
                array( $this, '_replyToPrintMetaBoxContents' ), // callback
115
                $sPostType,                                     // post type
116
                $this->oProp->sContext,                         // context
117
                $this->oProp->sPriority,                        // priority
118
                null                                            // argument - deprecated $this->oForm->aFields
119
            );
120
        }      
121
    }     
122
123
    /**
124
     * Called when the form object tries to set the form data from the database.
125
     * 
126
     * @callback    form        `saved_data`    
127
     * @remark      The `oOptions` property will be automatically set with the overload method.
128
     * @return      array       The saved form data.
129
     * @since       3.7.0
130
     */
131
    public function _replyToGetSavedFormData() {
132
                
133
        $_oMetaData = new AdminPageFramework_MetaBox_Model___PostMeta(
134
            $this->_getPostID(),
135
            $this->oForm->aFieldsets
136
        );        
137
        $this->oProp->aOptions = $_oMetaData->get();
138
        
139
        // The parent method will handle applying filters with the set property object.
140
        return parent::_replyToGetSavedFormData();
141
    
142
    }
143
        /**
144
         * Returns the post ID associated with the loading page.
145
         * @since       3.4.1
146
         * @internal
147
         * @return      integer     The found post ID. `0` if not found.
148
         */
149
        private function _getPostID()  {
0 ignored issues
show
Coding Style introduced by
_getPostID uses the super-global variable $GLOBALS which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
_getPostID uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
_getPostID uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
150
            
151
            // for an editing post page.
152
            if ( isset( $GLOBALS[ 'post' ]->ID ) ) {
153
                return $GLOBALS[ 'post' ]->ID;
154
            }
155
            if ( isset( $_GET[ 'post' ] ) ) {
156
                return $_GET[ 'post' ];
157
            }
158
            // for post.php without any query key-values.
159
            if ( isset( $_POST[ 'post_ID' ] ) ) {
160
                return $_POST[ 'post_ID' ];
161
            }
162
            return 0;
163
            
164
        }
165
               
166
    /**
167
     * The submitted data for a new post being passed. 
168
     * 
169
     * Triggered when a post has not been created so no post id is assigned.
170
     * 
171
	 * @internal
172
     * @since       3.3.0
173
     * @callback    filter      wp_insert_attachment_data
174
     * @callback    filter      wp_insert_post_data
175
	 * @param       array       $aPostData      An array of slashed post data.
176
     * @param       array       $aUnmodified    An array of sanitized, but otherwise unmodified post data.
177
     */
178
    public function _replyToFilterSavingData( $aPostData, $aUnmodified ) {
0 ignored issues
show
Coding Style introduced by
_replyToFilterSavingData uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
179
180
        // Perform initial checks.
181
        if ( ! $this->_shouldProceedValidation( $aUnmodified ) ) { 
182
            return $aPostData; 
183
        }
184
                
185
        // Retrieve the submitted data. 
186
        $_aInputs       = $this->oForm->getSubmittedData(
187
            $_POST,     // subject data to be parsed
188
            true,       // extract data with the fieldset structure
189
            false       // strip slashes
190
        );
191
        $_aInputsRaw    = $_aInputs; // store one for the last input array.
192
        
193
        // Prepare the saved data. For a new post, the id is set to 0.
194
        $_iPostID       = $aUnmodified[ 'ID' ];  
195
        $_aSavedMeta    = $this->oUtil->getSavedPostMetaArray( 
196
            $_iPostID, 
197
            array_keys( $_aInputs )
198
        );
199
        
200
        // Apply filters to the array of the submitted values.
201
        $_aInputs = $this->oUtil->addAndApplyFilters( 
202
            $this, 
203
            "validation_{$this->oProp->sClassName}",
204
            call_user_func_array( 
205
                array( $this, 'validate' ), // triggers __call()
206
                array( $_aInputs, $_aSavedMeta, $this ) 
207
            ), // 3.5.3+            
208
            $_aSavedMeta, 
209
            $this 
210
        ); 
211
 
212
        // If there are validation errors. Change the post status to 'pending'.
213
        if ( $this->hasFieldError() ) {
214
            $this->setLastInputs( $_aInputsRaw );
215
            $aPostData[ 'post_status' ] = 'pending';
216
            add_filter( 
217
                'redirect_post_location', 
218
                array( $this, '_replyToModifyRedirectPostLocation' )
219
            );
220
        }
221
                    
222
        $this->oForm->updateMetaDataByType( 
223
            $_iPostID,   // object id
224
            $_aInputs,   // user submit form data
225
            $this->oForm->dropRepeatableElements( $_aSavedMeta ), // Drop repeatable section elements from the saved meta array.
226
            $this->oForm->sStructureType   // fields type
227
        );        
228
        
229
        return $aPostData;
230
        
231
    }
232
233
        /**
234
         * Modifies the 'message' query value in the redirect url of the post publish.
235
         * 
236
         * This method is called when a publishing post contains a field error of meta boxes added by the framework.
237
         * And the query url gets modified to disable the WordPress default admin notice, "Post published.".
238
         * 
239
         * @internal
240
         * @callback    filter      redirect_post_location
241
         * @since       3.3.0
242
         * @return      string      The modified url to be redirected after publishing the post.
243
         */
244
        public function _replyToModifyRedirectPostLocation( $sLocation ) {
245
246
            remove_filter( 
247
                'redirect_post_location', 
248
                array( $this, __FUNCTION__ ) 
249
            );
250
            return add_query_arg(
251
                array( 
252
                    'message'       => 'apf_field_error', 
253
                    'field_errors'  => true
254
                ), 
255
                $sLocation 
256
            );
257
            
258
        }        
259
            
260
        /**
261
         * Checks whether the function call of processing submitted field values is valid or not.
262
         * 
263
         * @since       3.3.0
264
         * @since       3.6.0       Added the `$aUnmodified` parameter.
265
         * @since       3.7.0      Renamed from `_validateCall()`.
266
         * @internal
267
         * @return      boolean
268
         */
269
        private function _shouldProceedValidation( array $aUnmodified ) {
0 ignored issues
show
Coding Style introduced by
_shouldProceedValidation uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
270
            
271
            if ( 'auto-draft' === $aUnmodified[ 'post_status' ] ) { 
272
                return false; 
273
            }            
274
            
275
            // Bail if we're doing an auto save
276
            if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) { 
277
                return false;
278
            }
279
     
280
            // If our nonce isn't there, or we can't verify it, bail
281
            if ( ! isset( $_POST[ $this->oProp->sMetaBoxID ] ) ) {
282
                return false;
283
            }
284
            if ( ! wp_verify_nonce( $_POST[ $this->oProp->sMetaBoxID ], $this->oProp->sMetaBoxID ) ) {
285
                return false;
286
            }
287
            
288
            if ( ! in_array( $aUnmodified[ 'post_type' ], $this->oProp->aPostTypes ) ) {
289
                return false;
290
            }              
291
            
292
            return current_user_can( $this->oProp->sCapability, $aUnmodified[ 'ID' ] );
293
            
294
        }            
295
    
296
}
297