Completed
Push — master ( 108b89...0a9573 )
by Craig
06:27
created

UsersModuleInstaller::defaultdata()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 37
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 28
nc 1
nop 0
dl 0
loc 37
rs 8.8571
c 1
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of the Zikula package.
5
 *
6
 * Copyright Zikula Foundation - http://zikula.org/
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Zikula\UsersModule;
13
14
use Zikula\Core\AbstractExtensionInstaller;
15
use Zikula\ExtensionsModule\Api\VariableApi;
16
use Zikula\UsersModule\Constant as UsersConstant;
17
use Zikula\ZAuthModule\ZAuthConstant;
18
19
/**
20
 * Installation and upgrade routines for the users module.
21
 */
22
class UsersModuleInstaller extends AbstractExtensionInstaller
23
{
24
    /**
25
     * Initialise the users module.
26
     *
27
     * This function is only ever called once during the lifetime of a particular
28
     * module instance. This function MUST exist in the pninit file for a module.
29
     *
30
     * @return bool True on success, false otherwise
31
     */
32
    public function install()
33
    {
34
        // create the tables
35
        $classes = [
36
            'Zikula\UsersModule\Entity\UserEntity',
37
            'Zikula\UsersModule\Entity\UserAttributeEntity',
38
            'Zikula\UsersModule\Entity\UserSessionEntity',
39
        ];
40
        try {
41
            $this->schemaTool->create($classes);
42
        } catch (\Exception $e) {
43
            return false;
44
        }
45
46
        // Set default values and modvars for module
47
        $this->defaultdata();
48
        $this->setVars($this->getDefaultModvars());
49
        $this->container->get('zikula_extensions_module.api.variable')->set(VariableApi::CONFIG, 'authenticationMethodsStatus', ['native_uname' => true]);
50
51
        // Register hook bundles
52
        $this->hookApi->installSubscriberHooks($this->bundle->getMetaData());
53
        $this->hookApi->installProviderHooks($this->bundle->getMetaData());
54
55
        // Initialisation successful
56
        return true;
57
    }
58
59
    /**
60
     * Upgrade the users module from an older version.
61
     *
62
     * This function must consider all the released versions of the module!
63
     * If the upgrade fails at some point, it returns the last upgraded version.
64
     *
65
     * @param string $oldVersion Version number string to upgrade from
66
     *
67
     * @return bool|string True on success, last valid version string or false if fails
68
     */
69
    public function upgrade($oldVersion)
70
    {
71
        $connection = $this->entityManager->getConnection();
72
        // Upgrade dependent on old version number
73
        switch ($oldVersion) {
74
            case '2.2.0': // version shipped with Core 1.3.5 -> current 1.3.x
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
75
                $sql = "ALTER TABLE users ENGINE = InnoDB";
76
                $stmt = $connection->prepare($sql);
77
                $stmt->execute();
78
                // add new table
79
                $this->schemaTool->create(['Zikula\UsersModule\Entity\UserAttributeEntity']);
80
                $this->migrateAttributes();
81
            case '2.2.1':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
82
                $currentModVars = $this->getVars();
83
                $defaultModVars = $this->getDefaultModvars();
84
85
                // Remove modvars that are no longer defined.
86
                foreach ($currentModVars as $modVar => $currentValue) {
87
                    if (!array_key_exists($modVar, $defaultModVars)) {
88
                        $this->delVar($modVar);
89
                    }
90
                }
91
92
                // Add modvars that are new to the version
93
                foreach ($defaultModVars as $modVar => $defaultValue) {
94
                    if (!array_key_exists($modVar, $currentModVars)) {
95
                        $this->setVar($modVar, $defaultValue);
96
                    }
97
                }
98
            case '2.2.2':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
99
                if ($this->getVar('gravatarimage', null) == 'gravatar.gif') {
100
                    $this->setVar('gravatarimage', 'gravatar.jpg');
101
                }
102
            case '2.2.3':
103
                // Nothing to do.
104
            case '2.2.4':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
105
                $sql = "UPDATE users_attributes SET value='gravatar.jpg' WHERE value='gravatar.gif'";
106
                $stmt = $connection->prepare($sql);
107
                $stmt->execute();
108
            case '2.2.5':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
109
                $modvarsToConvertToBool = [
110
                    UsersConstant::MODVAR_ACCOUNT_DISPLAY_GRAPHICS,
111
                    UsersConstant::MODVAR_REGISTRATION_ENABLED,
112
                    UsersConstant::MODVAR_REGISTRATION_APPROVAL_REQUIRED,
113
                    UsersConstant::MODVAR_REGISTRATION_AUTO_LOGIN,
114
                    UsersConstant::MODVAR_LOGIN_DISPLAY_INACTIVE_STATUS,
115
                    UsersConstant::MODVAR_LOGIN_DISPLAY_VERIFY_STATUS,
116
                    UsersConstant::MODVAR_LOGIN_DISPLAY_APPROVAL_STATUS
117
                ];
118
                foreach ($modvarsToConvertToBool as $modvarToConvert) {
119
                    $this->setVar($modvarToConvert, (bool) $this->getVar($modvarToConvert));
120
                }
121
                $this->schemaTool->update(['Zikula\UsersModule\Entity\UserEntity']);
122
                $this->delVar('login_redirect');
123
            case '2.2.8':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
124
                $this->container->get('zikula_extensions_module.api.variable')->set(VariableApi::CONFIG, 'authenticationMethodsStatus', ['native_uname' => true]);
125
            case '2.2.9':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
126
                // migrate modvar values to ZAuth and remove from Users
127
                $this->migrateModVarsToZAuth();
128
                // update users table
129
                $sql = "UPDATE users SET pass='' WHERE pass='NO_USERS_AUTHENTICATION'";
130
                $stmt = $connection->prepare($sql);
131
                $stmt->execute();
132
                // expire all sessions so everyone has to login again (to force migration)
133
                $this->entityManager->createQuery('DELETE FROM Zikula\UsersModule\Entity\UserSessionEntity')->execute();
134
            case '3.0.0':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
135
                $this->schemaTool->update(['Zikula\UsersModule\Entity\UserSessionEntity']);
136
            case '3.0.1':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
137
                $sql = "ALTER TABLE users_attributes ADD FOREIGN KEY (user_id) REFERENCES users(uid) ON DELETE CASCADE";
138
                $stmt = $connection->prepare($sql);
139
                $stmt->execute();
140
            case '3.0.2':
0 ignored issues
show
Coding Style introduced by
There must be a comment when fall-through is intentional in a non-empty case body
Loading history...
141
                // remove password reminder
142
                $this->schemaTool->update(['Zikula\UsersModule\Entity\UserEntity']);
143
                $this->delVar('password_reminder_enabled');
144
                $this->delVar('password_reminder_mandatory');
145
            case '3.0.3':
146
                // current version
147
        }
148
149
        /**
150
         * Update successful.
151
         */
152
        return true;
153
    }
154
155
    /**
156
     * Delete the users module.
157
     *
158
     * This function is only ever called once during the lifetime of a particular
159
     * module instance. This function MUST exist in the pninit file for a module.
160
     *
161
     * Since the users module should never be deleted we'all always return false here.
162
     *
163
     * @return bool false
164
     */
165
    public function uninstall()
166
    {
167
        // Deletion not allowed
168
        return false;
169
    }
170
171
    /**
172
     * Build and return an array of all current module variables, with their default values.
173
     *
174
     * @return array An array of all current module variables, with their default values, suitable for {@link setVars()}
175
     */
176
    private function getDefaultModvars()
177
    {
178
        return [
179
            UsersConstant::MODVAR_ACCOUNT_DISPLAY_GRAPHICS              => UsersConstant::DEFAULT_ACCOUNT_DISPLAY_GRAPHICS,
180
            UsersConstant::MODVAR_ACCOUNT_ITEMS_PER_PAGE                => UsersConstant::DEFAULT_ACCOUNT_ITEMS_PER_PAGE,
181
            UsersConstant::MODVAR_ACCOUNT_ITEMS_PER_ROW                 => UsersConstant::DEFAULT_ACCOUNT_ITEMS_PER_ROW,
182
            UsersConstant::MODVAR_ACCOUNT_PAGE_IMAGE_PATH               => UsersConstant::DEFAULT_ACCOUNT_PAGE_IMAGE_PATH,
183
            UsersConstant::MODVAR_ANONYMOUS_DISPLAY_NAME                => $this->__(/* Anonymous (guest) account display name */'Guest'),
184
            UsersConstant::MODVAR_ITEMS_PER_PAGE                        => UsersConstant::DEFAULT_ITEMS_PER_PAGE,
185
            UsersConstant::MODVAR_LOGIN_DISPLAY_APPROVAL_STATUS         => UsersConstant::DEFAULT_LOGIN_DISPLAY_APPROVAL_STATUS,
186
            UsersConstant::MODVAR_LOGIN_DISPLAY_DELETE_STATUS           => UsersConstant::DEFAULT_LOGIN_DISPLAY_DELETE_STATUS,
187
            UsersConstant::MODVAR_LOGIN_DISPLAY_INACTIVE_STATUS         => UsersConstant::DEFAULT_LOGIN_DISPLAY_INACTIVE_STATUS,
188
            UsersConstant::MODVAR_LOGIN_DISPLAY_VERIFY_STATUS           => UsersConstant::DEFAULT_LOGIN_DISPLAY_VERIFY_STATUS,
189
            UsersConstant::MODVAR_REGISTRATION_ADMIN_NOTIFICATION_EMAIL => '',
190
            UsersConstant::MODVAR_REGISTRATION_APPROVAL_REQUIRED        => UsersConstant::DEFAULT_REGISTRATION_APPROVAL_REQUIRED,
191
            UsersConstant::MODVAR_REGISTRATION_AUTO_LOGIN               => UsersConstant::DEFAULT_REGISTRATION_AUTO_LOGIN,
192
            UsersConstant::MODVAR_REGISTRATION_DISABLED_REASON          => $this->__(/* registration disabled reason (default value, */'Sorry! New user registration is currently disabled.'),
193
            UsersConstant::MODVAR_REGISTRATION_ENABLED                  => UsersConstant::DEFAULT_REGISTRATION_ENABLED,
194
            UsersConstant::MODVAR_REGISTRATION_ILLEGAL_AGENTS           => '',
195
            UsersConstant::MODVAR_REGISTRATION_ILLEGAL_DOMAINS          => '',
196
            UsersConstant::MODVAR_REGISTRATION_ILLEGAL_UNAMES           => $this->__(/* illegal username list */'root, webmaster, admin, administrator, nobody, anonymous, username'),
197
        ];
198
    }
199
200
    /**
201
     * Create the default data for the users module.
202
     *
203
     * This function is only ever called once during the lifetime of a particular
204
     * module instance.
205
     *
206
     * @return void
207
     */
208
    private function defaultdata()
209
    {
210
        $nowUTC = new \DateTime(null, new \DateTimeZone('UTC'));
211
        $nowUTCStr = $nowUTC->format(UsersConstant::DATETIME_FORMAT);
212
213
        // Anonymous
214
        $record = [
215
            'uid'           => 1,
216
            'uname'         => 'guest',
217
            'email'         => '',
218
            'activated'     => UsersConstant::ACTIVATED_ACTIVE,
219
            'approved_date' => '1970-01-01 00:00:00',
220
            'approved_by'   => 0,
221
            'user_regdate'  => '1970-01-01 00:00:00',
222
            'lastlogin'     => '1970-01-01 00:00:00',
223
        ];
224
        $user = new \Zikula\UsersModule\Entity\UserEntity();
225
        $user->merge($record);
226
        $this->entityManager->persist($user);
227
228
        // Admin
229
        $record = [
230
            'uid'           => 2,
231
            'uname'         => 'admin',
232
            'email'         => '',
233
            'activated'     => UsersConstant::ACTIVATED_ACTIVE,
234
            'approved_date' => $nowUTCStr,
235
            'approved_by'   => 2,
236
            'user_regdate'  => $nowUTCStr,
237
            'lastlogin'     => '1970-01-01 00:00:00',
238
        ];
239
        $user = new \Zikula\UsersModule\Entity\UserEntity();
240
        $user->merge($record);
241
        $this->entityManager->persist($user);
242
243
        $this->entityManager->flush();
244
    }
245
246
    /**
247
     * migrate all data from the objectdata_attributes table to the users_attributes
248
     * where object_type = 'users'
249
     */
250
    private function migrateAttributes()
251
    {
252
        $connection = $this->entityManager->getConnection();
253
        $sqls = [];
254
        // copy data from objectdata_attributes to users_attributes
255
        $sqls[] = 'INSERT INTO users_attributes
256
                    (user_id, name, value)
257
                    SELECT object_id, attribute_name, value
258
                    FROM objectdata_attributes
259
                    WHERE object_type = \'users\'
260
                    ORDER BY object_id, attribute_name';
261
        // remove old data
262
        $sqls[] = 'DELETE FROM objectdata_attributes
263
                    WHERE object_type = \'users\'';
264
        foreach ($sqls as $sql) {
265
            $stmt = $connection->prepare($sql);
266
            $stmt->execute();
267
        }
268
    }
269
270
    /**
271
     * v2.2.9 -> 3.0.0
272
     * move select modvar values to ZAuthModule.
273
     * change to boolean where required.
274
     */
275
    private function migrateModVarsToZAuth()
276
    {
277
        $migratedModVarNames = $this->getMigratedModVarNames();
278
        foreach ($migratedModVarNames as $migratedModVarName) {
279
            $value = $this->getVar($migratedModVarName);
280
            $this->delVar($migratedModVarName); // removes from UsersModule
281
            $migratedModVarName = ($migratedModVarName == 'reg_verifyemail') ? ZAuthConstant::MODVAR_EMAIL_VERIFICATION_REQUIRED : $migratedModVarName;
282
            $value = in_array($migratedModVarName, [
283
                ZAuthConstant::MODVAR_EMAIL_VERIFICATION_REQUIRED,
284
                ZAuthConstant::MODVAR_PASSWORD_STRENGTH_METER_ENABLED
285
            ]) ? (bool) $value : $value;
286
            $this->container->get('zikula_extensions_module.api.variable')->set('ZikulaZAuthModule', $migratedModVarName, $value);
287
        }
288
    }
289
290
    /**
291
     * These modvar names used to have UsersConstant values, but have been moved to ZAuthConstant and maintain their actual values.
292
     * @return array
293
     */
294
    private function getMigratedModVarNames()
295
    {
296
        return [
297
            ZAuthConstant::MODVAR_HASH_METHOD,
298
            ZAuthConstant::MODVAR_PASSWORD_MINIMUM_LENGTH,
299
            ZAuthConstant::MODVAR_PASSWORD_STRENGTH_METER_ENABLED, // convert to bool
300
            ZAuthConstant::MODVAR_REGISTRATION_ANTISPAM_QUESTION,
301
            ZAuthConstant::MODVAR_REGISTRATION_ANTISPAM_ANSWER,
302
            ZAuthConstant::MODVAR_EXPIRE_DAYS_REGISTRATION,
303
            ZAuthConstant::MODVAR_EXPIRE_DAYS_CHANGE_EMAIL,
304
            ZAuthConstant::MODVAR_EXPIRE_DAYS_CHANGE_PASSWORD,
305
            'reg_verifyemail', // convert to bool
306
        ];
307
    }
308
}
309