Completed
Branch master (d39ff3)
by Pierre-Henry
32:32
created

SettingFormProcess::noErrors()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 4
rs 10
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 18 and the first side effect is on line 11.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
/**
3
 * @author         Pierre-Henry Soria <[email protected]>
4
 * @copyright      (c) 2012-2018, Pierre-Henry Soria. All Rights Reserved.
5
 * @license        GNU General Public License; See PH7.LICENSE.txt and PH7.COPYRIGHT.txt in the root directory.
6
 * @package        PH7 / App / System / Module / Admin / From / Processing
7
 */
8
9
namespace PH7;
10
11
defined('PH7') or exit('Restricted access');
12
13
use PH7\Framework\Image\Image;
14
use PH7\Framework\Layout\Gzip\Gzip;
15
use PH7\Framework\Mvc\Model\DbConfig;
16
use PH7\Framework\Navigation\Browser;
17
18
class SettingFormProcess extends Form
19
{
20
    const LOGO_FILENAME = 'logo.png';
21
    const MIN_CSRF_TOKEN_LIFETIME = 10;
22
    const LOGO_WIDTH = 50;
23
    const LOGO_HEIGHT = 45;
24
    const MAX_WATERMARK_SIZE = 5;
25
    const DEFAULT_BROWSER_HEX_CODE = '#000000';
26
27
    /** @var boolean */
28
    private $bIsErr = false;
29
30
    /** @var array */
31
    private static $aSettingFields = [
32
        // General Settings
33
        'site_name' => 'siteName',
34
        'default_template' => 'defaultTemplate',
35
        'default_sys_module' => 'defaultSysModule',
36
        'default_language' => 'defaultLanguage',
37
        'map_type' => 'mapType',
38
        'profile_with_avatars' => 'profileWithAvatarSet',
39
        'splash_page' => 'splashPage',
40
        'bg_splash_vid' => 'bgSplashVideo',
41
        'users_block' => 'usersBlock',
42
        'number_profile_splash_page' => 'numberProfileSplashPage',
43
        'full_ajax_site' => 'fullAjaxSite',
44
        'site_status' => 'siteStatus',
45
        'social_media_widgets' => 'socialMediaWidgets',
46
        'disclaimer' => 'disclaimer',
47
        'cookie_consent_bar' => 'cookieConsentBar',
48
        'display_powered_by_link' => 'displayPoweredByLink',
49
        'is_software_news_feed' => 'isSoftwareNewsFeed',
50
51
        // Email
52
        'email_name' => 'emailName',
53
        'admin_email' => 'adminEmail',
54
        'feedback_email' => 'feedbackEmail',
55
        'return_email' => 'returnEmail',
56
57
        // Registration
58
        'user_activation_type' => 'userActivationType',
59
        'aff_activation_type' => 'affActivationType',
60
        'min_username_length' => 'minUsernameLength',
61
        'max_username_length' => 'maxUsernameLength',
62
        'min_age_registration' => 'minAgeRegistration',
63
        'max_age_registration' => 'maxAgeRegistration',
64
        'require_registration_avatar' => 'requireRegistrationAvatar',
65
        'default_membership_group_id' => 'defaultMembershipGroupId',
66
67
        // Picture and Video
68
        'watermark_text_image' => 'watermarkTextImage',
69
        'size_watermark_text_image' => 'sizeWatermarkTextImage',
70
        'default_video' => 'defaultVideo',
71
        'autoplay_video' => 'autoplayVideo',
72
73
        // Moderation
74
        'avatar_manual_approval' => 'avatarManualApproval',
75
        'bg_profile_manual_approval' => 'bgProfileManualApproval',
76
        'note_manual_approval' => 'noteManualApproval',
77
        'picture_manual_approval' => 'pictureManualApproval',
78
        'nudity_filter' => 'nudityFilter',
79
        'video_manual_approval' => 'videoManualApproval',
80
        'webcam_picture_manual_approval' => 'webcamPictureManualApproval',
81
82
        // Security
83
        'min_password_length' => 'minPasswordLength',
84
        'max_password_length' => 'maxPasswordLength',
85
        'is_user_login_attempt' => 'isUserLoginAttempt',
86
        'is_affiliate_login_attempt' => 'isAffiliateLoginAttempt',
87
        'is_admin_login_attempt' => 'isAdminLoginAttempt',
88
        'max_user_login_attempts' => 'maxUserLoginAttempts',
89
        'max_affiliate_login_attempts' => 'maxAffiliateLoginAttempts',
90
        'max_admin_login_attempts' => 'maxAdminLoginAttempts',
91
        'login_user_attempt_time' => 'loginUserAttemptTime',
92
        'login_affiliate_attempt_time' => 'loginAffiliateAttemptTime',
93
        'login_admin_attempt_time' => 'loginAdminAttemptTime',
94
        'send_report_mail' => 'sendReportMail',
95
        'ip_login' => 'ipLogin',
96
        'ban_word_replace' => 'banWordReplace',
97
        'security_token_forms' => 'securityToken',
98
        'security_token_lifetime' => 'securityTokenLifetime',
99
        'stop_DDoS' => 'DDoS',
100
101
        // Spam
102
        'time_delay_user_registration' => 'timeDelayUserRegistration',
103
        'time_delay_aff_registration' => 'timeDelayAffRegistration',
104
        'time_delay_send_note' => 'timeDelaySendNote',
105
        'time_delay_send_mail' => 'timeDelaySendMail',
106
        'time_delay_send_comment' => 'timeDelaySendComment',
107
        'time_delay_send_forum_topic' => 'timeDelaySendForumTopic',
108
        'time_delay_send_forum_msg' => 'timeDelaySendForumMsg',
109
110
        // Captcha
111
        'captcha_complexity' => 'captchaComplexity',
112
        'captcha_case_sensitive' => 'captchaCaseSensitive',
113
        'is_captcha_user_signup' => 'isCaptchaUserSignup',
114
        'is_captcha_affiliate_signup' => 'isCaptchaAffiliateSignup',
115
        'is_captcha_mail' => 'isCaptchaMail',
116
        'is_captcha_comment' => 'isCaptchaComment',
117
        'is_captcha_forum' => 'isCaptchaForum',
118
        'is_captcha_note' => 'isCaptchaNote',
119
        'clean_msg' => 'cleanMsg',
120
        'clean_comment' => 'cleanComment',
121
        'clean_messenger' => 'cleanMessenger',
122
123
        // Design
124
        'background_color' => 'backgroundColor',
125
        'text_color' => 'textColor',
126
        'link_color' => 'linkColor',
127
        'footer_link_color' => 'footerLinkColor',
128
        'link_hover_color' => 'linkHoverColor',
129
130
        // API
131
        'google_api_key' => 'googleApiKey',
132
        'ip_api' => 'ipApi',
133
        'chat_api' => 'chatApi',
134
        'chatroulette_api' => 'chatrouletteApi',
135
136
        // Automation
137
        'cron_security_hash' => 'cronSecurityHash',
138
        'user_timeout' => 'userTimeout'
139
    ];
140
141
    public function __construct()
142
    {
143
        parent::__construct();
144
145
        $this->updateLogo();
146
        $this->updateGenericFields();
147
148
        DbConfig::clearCache();
149
150
        if ($this->noErrors()) {
151
            \PFBC\Form::setSuccess('form_setting', t('Configurations successfully updated!'));
152
        }
153
    }
154
155
    /**
156
     * Update the other "generic" fields (if modified only).
157
     */
158
    private function updateGenericFields()
159
    {
160
        foreach (self::$aSettingFields as $sKey => $sVal) {
161
            if ($sKey === 'security_token_lifetime') {
162
                $iSecTokenLifetime = (int)$this->httpRequest->post('security_token_lifetime');
163
164
                if (!$this->str->equals($iSecTokenLifetime, DbConfig::getSetting('securityTokenLifetime'))) {
165
                    if ($iSecTokenLifetime < self::MIN_CSRF_TOKEN_LIFETIME) {
166
                        \PFBC\Form::setError('form_setting', t('The token lifetime cannot be below %0% seconds.', self::MIN_CSRF_TOKEN_LIFETIME));
167
                        $this->bIsErr = true;
168
                    } else {
169
                        DbConfig::setSetting($iSecTokenLifetime, 'securityTokenLifetime');
170
                    }
171
                }
172
            } elseif ($this->hasDataChanged($sKey, $sVal)) {
173
                switch ($sKey) {
174
                    case 'min_username_length': {
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
175
                        $iMaxUsernameLength = $this->httpRequest->post('max_username_length')-1;
176
                        if ($this->httpRequest->post('min_username_length') > $iMaxUsernameLength) {
177
                            \PFBC\Form::setError('form_setting', t('The minimum length of the username cannot exceed %0% characters.', $iMaxUsernameLength));
178
                             $this->bIsErr = true;
179
                         } else {
180
                            DbConfig::setSetting($this->httpRequest->post('min_username_length'), 'minUsernameLength');
181
                        }
182
                    } break;
183
184
                    case 'max_username_length': {
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
185
                        if ($this->httpRequest->post('max_username_length') > PH7_MAX_USERNAME_LENGTH) {
186
                            \PFBC\Form::setError('form_setting', t('The maximum length of the username cannot exceed %0% characters.', PH7_MAX_USERNAME_LENGTH));
187
                            $this->bIsErr = true;
188
                        } else {
189
                            DbConfig::setSetting($this->httpRequest->post('max_username_length'), 'maxUsernameLength');
190
                        }
191
                    } break;
192
193
                    case 'min_age_registration': {
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
194
                        if ($this->httpRequest->post('min_age_registration') >= $this->httpRequest->post('max_age_registration')) {
195
                            \PFBC\Form::setError('form_setting', t('You cannot specify a minimum age higher than the maximum age.'));
196
                            $this->bIsErr = true;
197
                        } else {
198
                            DbConfig::setSetting($this->httpRequest->post('min_age_registration'), 'minAgeRegistration');
199
                        }
200
                    } break;
201
202
                    case 'size_watermark_text_image': {
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
203
                        if ($this->httpRequest->post('size_watermark_text_image') >= 0 &&
204
                            $this->httpRequest->post('size_watermark_text_image') <= self::MAX_WATERMARK_SIZE) {
205
                            DbConfig::setSetting($this->httpRequest->post('size_watermark_text_image'), 'sizeWatermarkTextImage');
206
                        }
207
                    } break;
208
209
                    case 'background_color':
210
                    case 'text_color':
211
                    case 'link_color':
212
                    case 'footer_link_color':
213
                    case 'link_hover_color': {
0 ignored issues
show
Coding Style introduced by
case statements should be defined using a colon.

As per the PSR-2 coding standard, case statements should not be wrapped in curly braces. There is no need for braces, since each case is terminated by the next break.

There is also the option to use a semicolon instead of a colon, this is discouraged because many programmers do not even know it works and the colon is universal between programming languages.

switch ($expr) {
    case "A": { //wrong
        doSomething();
        break;
    }
    case "B"; //wrong
        doSomething();
        break;
    case "C": //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
214
                        // Don't update if value wasn't changed by user but was set by browser because field was empty
215
                        if ($this->httpRequest->post($sKey) !== self::DEFAULT_BROWSER_HEX_CODE) {
216
                            DbConfig::setSetting($this->httpRequest->post($sKey), $sVal);
217
                        }
218
                    } break;
219
220
                    default: {
0 ignored issues
show
Coding Style introduced by
DEFAULT statements must be defined using a colon

As per the PSR-2 coding standard, default statements should not be wrapped in curly braces.

switch ($expr) {
    default: { //wrong
        doSomething();
        break;
    }
}

switch ($expr) {
    default: //right
        doSomething();
        break;
}

To learn more about the PSR-2 coding standard, please refer to the PHP-Fig.

Loading history...
221
                        $sMethod = ($sKey === 'site_status' ? 'setSiteMode' : ($sKey === 'social_media_widgets' ? 'setSocialWidgets' : 'setSetting'));
222
                        DbConfig::$sMethod($this->httpRequest->post($sKey, null, true), $sVal);
223
                    }
224
                }
225
            }
226
        }
227
    }
228
229
    /**
230
     * Update Logo (if a new one if uploaded only).
231
     */
232
    private function updateLogo()
0 ignored issues
show
Coding Style introduced by
updateLogo uses the super-global variable $_FILES 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...
233
    {
234
        if (!empty($_FILES['logo']['tmp_name'])) {
235
            $oLogo = new Image($_FILES['logo']['tmp_name']);
236
            if (!$oLogo->validate()) {
237
                \PFBC\Form::setError('form_setting', Form::wrongImgFileTypeMsg());
238
                $this->bIsErr = true;
239
            } else {
240
                /*
241
                 * The method deleteFile first test if the file exists, if so it delete the file.
242
                 */
243
                $sPathName = PH7_PATH_TPL . PH7_TPL_NAME . PH7_DS . PH7_IMG . self::LOGO_FILENAME;
244
                $this->file->deleteFile($sPathName); // It erases the old logo.
245
                $oLogo->dynamicResize(self::LOGO_WIDTH, self::LOGO_HEIGHT);
246
                $oLogo->save($sPathName);
247
248
                // Clear CSS cache, because the logo is storaged with data URI in the CSS cache file
249
                $this->file->deleteDir(PH7_PATH_CACHE . Gzip::CACHE_DIR);
250
251
                // Clear the Web browser cache
252
                (new Browser)->noCache();
253
            }
254
        }
255
    }
256
257
    /**
258
     * @param string $sKey
259
     * @param string $sVal
260
     *
261
     * @return bool
262
     *
263
     * @throws Framework\Mvc\Request\WrongRequestMethodException
264
     */
265
    private function hasDataChanged($sKey, $sVal)
266
    {
267
        return !$this->str->equals($this->httpRequest->post($sKey), DbConfig::getSetting($sVal));
268
    }
269
270
    /**
271
     * @return bool
272
     */
273
    private function noErrors()
274
    {
275
        return !$this->bIsErr;
276
    }
277
}
278