Completed
Push — master ( 43a823...7345d8 )
by Vitaly
06:25
created

CMS::prepare()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 64
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 12
Bugs 7 Features 5
Metric Value
c 12
b 7
f 5
dl 0
loc 64
rs 8.8726
cc 4
eloc 43
nc 4
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 21 and the first side effect is on line 5.

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
namespace samsoncms\api;
3
4
// Backward compatibility
5
require('generated/Material.php');
6
require('generated/Field.php');
7
require('generated/MaterialField.php');
8
require('generated/Structure.php');
9
require('generated/StructureField.php');
10
11
use samsonframework\core\ResourcesInterface;
12
use samsonframework\core\SystemInterface;
13
use samson\activerecord\TableRelation;
14
use samson\core\CompressableService;
15
use samson\activerecord\dbMySQLConnector;
16
17
/**
18
 * SamsonCMS API
19
 * @package samsoncms\api
20
 */
21
class CMS extends CompressableService
22
{
23
    /** Database entity name for relations between material and navigation */
24
    const MATERIAL_NAVIGATION_RELATION_ENTITY = '\samson\activerecord\structurematerial';
25
    /** Database entity name for relations between material and images */
26
    const MATERIAL_IMAGES_RELATION_ENTITY = '\samson\activerecord\gallery';
27
    /** Database entity name for relations between additional fields and navigation */
28
    const FIELD_NAVIGATION_RELATION_ENTITY = '\samson\activerecord\structurefield';
29
    /** Database entity name for relations between material and additional fields values */
30
    const MATERIAL_FIELD_RELATION_ENTITY = MaterialField::ENTITY;
31
32
    /** Identifier */
33
    protected $id = 'cmsapi2';
34
35
    /** @var \samsonframework\orm\DatabaseInterface */
36
    protected $database;
37
38
    /** @var array[string] Collection of generated queries */
39
    protected $queries;
40
41
    /** @var string Database table names prefix */
42
    public $tablePrefix = '';
43
44
    /**
45
     * CMS constructor.
46
     *
47
     * @param string $path
48
     * @param ResourcesInterface $resources
49
     * @param SystemInterface $system
50
     */
51
    public function  __construct($path, ResourcesInterface $resources, SystemInterface $system)
0 ignored issues
show
Coding Style introduced by
Expected "function abc(...)"; found "function abc(...)"
Loading history...
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 2 found
Loading history...
52
    {
53
        // TODO: This should changed to normal DI
54
        $this->database = db();
55
56
        parent::__construct($path, $resources, $system);
57
    }
58
59
    /**
60
     * Module initialization.
61
     *
62
     * @param array $params Initialization parameters
63
     * @return bool Initialization result
64
     */
65
    public function init(array $params = array())
66
    {
67
        $this->rewriteEntityLocale();
68
    }
69
70
    public function beforeCompress(& $obj = null, array & $code = null)
71
    {
72
73
    }
74
75
    public function afterCompress(& $obj = null, array & $code = null)
76
    {
77
        // Iterate through generated php code
78
        $files = array();
79
        foreach (\samson\core\File::dir($this->cache_path, 'php', '', $files, 1) as $file) {
80
            // No namespace for global function file
81
            $ns = strpos($file, 'func') === false ? __NAMESPACE__ : '';
82
83
            // Compress generated php code
84
            $obj->compress_php($file, $this, $code, $ns);
85
        }
86
    }
87
88
    /**
89
     * Entity additional fields localization support.
90
     */
91
    protected function rewriteEntityLocale()
92
    {
93
        // Iterate all generated entity classes
94
        foreach (get_declared_classes() as $entityClass) {
95
            if (is_subclass_of($entityClass, '\samsoncms\api\Entity')) {
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of returns inconsistent results on some PHP versions for interfaces; you could instead use ReflectionClass::implementsInterface.
Loading history...
96
                // Insert current application locale
97
                str_replace('@locale', locale(), $entityClass::$_sql_select);
98
            }
99
        }
100
    }
101
102
    //[PHPCOMPRESSOR(remove,start)]
103
    /**
104
     * Read SQL file with variables placeholders pasting
105
     * @param string $filePath SQL file for reading
106
     * @param string $prefix Prefix for addition
107
     * @return string SQL command text
108
     */
109
    public function readSQL($filePath, $prefix = '')
110
    {
111
        $sql = '';
112
113
        // Build path to SQL folder
114
        if (file_exists($filePath)) {
115
            // Replace prefix
116
            $sql = str_replace('@prefix', $prefix, file_get_contents($filePath));
117
        }
118
119
        return $sql;
120
    }
121
122
    /**
123
     * @see ModuleConnector::prepare()
124
     */
125
    public function prepare()
126
    {
127
        // Perform this migration and execute only once
128
        if ($this->migrator() != 40) {
129
            // Perform SQL table creation
130
            $path = __DIR__ . '/../sql/';
131
            foreach (array_slice(scandir($path), 2) as $file) {
132
                $this->database->execute($this->readSQL($path . $file, $this->tablePrefix));
133
            }
134
            $this->migrator(40);
135
        }
136
137
        // Initiate migration mechanism
138
        $this->database->migration(get_class($this), array($this, 'migrator'));
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface samsonframework\orm\DatabaseInterface as the method migration() does only exist in the following implementations of said interface: samson\activerecord\dbMySQL.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
139
140
                // Define permanent table relations
141
        new TableRelation('material', 'user', 'UserID', 0, 'user_id');
142
        new TableRelation('material', 'gallery', 'MaterialID', TableRelation::T_ONE_TO_MANY);
143
        new TableRelation('material', 'materialfield', 'MaterialID', TableRelation::T_ONE_TO_MANY);
144
        new TableRelation('material', 'field', 'materialfield.FieldID', TableRelation::T_ONE_TO_MANY);
145
        new TableRelation('material', 'structurematerial', 'MaterialID', TableRelation::T_ONE_TO_MANY);
146
        new TableRelation('material', 'structure', 'structurematerial.StructureID', TableRelation::T_ONE_TO_MANY);
147
        new TableRelation('materialfield', 'field', 'FieldID');
148
        new TableRelation('materialfield', 'material', 'MaterialID');
149
        new TableRelation('structurematerial', 'structure', 'StructureID');
150
        new TableRelation('structurematerial', 'materialfield', 'MaterialID', TableRelation::T_ONE_TO_MANY);
151
        new TableRelation('structurematerial', 'material', 'MaterialID', TableRelation::T_ONE_TO_MANY);
152
        new TableRelation('structure', 'material', 'structurematerial.MaterialID', TableRelation::T_ONE_TO_MANY, null, 'manymaterials');
153
        new TableRelation('structure', 'gallery', 'structurematerial.MaterialID', TableRelation::T_ONE_TO_MANY, null, 'manymaterials');
154
        /*new TableRelation( 'structure', 'material', 'MaterialID' );*/
155
        new TableRelation('structure', 'user', 'UserID', 0, 'user_id');
156
        new TableRelation('structure', 'materialfield', 'material.MaterialID', TableRelation::T_ONE_TO_MANY, 'MaterialID', '_mf');
157
        new TableRelation('structure', 'structurematerial', 'StructureID', TableRelation::T_ONE_TO_MANY);
158
        new TableRelation('related_materials', 'material', 'first_material', TableRelation::T_ONE_TO_MANY, 'MaterialID');
159
        new TableRelation('related_materials', 'materialfield', 'first_material', TableRelation::T_ONE_TO_MANY, 'MaterialID');
160
        new TableRelation('field', 'structurefield', 'FieldID');
161
        new TableRelation('field', 'structure', 'structurefield.StructureID');
162
        new TableRelation('structurefield', 'field', 'FieldID');
163
        new TableRelation('structurefield', 'materialfield', 'FieldID');
164
        new TableRelation('structurefield', 'material', 'materialfield.MaterialID');
165
        new TableRelation('structure', 'structure_relation', 'StructureID', TableRelation::T_ONE_TO_MANY, 'parent_id', 'children_relations');
166
        new TableRelation('structure', 'structure', 'children_relations.child_id', TableRelation::T_ONE_TO_MANY, 'StructureID', 'children');
167
        new TableRelation('structure', 'structure_relation', 'StructureID', TableRelation::T_ONE_TO_MANY, 'child_id', 'parents_relations');
168
        new TableRelation('structure', 'structure', 'parents_relations.parent_id', TableRelation::T_ONE_TO_MANY, 'StructureID', 'parents');
169
        new TableRelation('structurematerial', 'structure_relation', 'StructureID', TableRelation::T_ONE_TO_MANY, 'parent_id');
170
        new TableRelation('groupright', 'right', 'RightID', TableRelation::T_ONE_TO_MANY);
171
172
        // TODO: Should be removed
173
        m('activerecord')->relations();
174
175
        // Generate entities classes file
176
        $generator = new Generator($this->database);
177
178
        // Create cache file
179
        $file = md5($generator->entityHash()).'.php';
180
        if ($this->cache_refresh($file)) {
181
            file_put_contents($file, '<?php '.$generator->createEntityClasses());
182
        }
183
184
        // Include entities file
185
        require($file);
186
187
        return parent::prepare();
188
    }
189
190
    /**
191
     * Handler for CMSAPI database version manipulating
192
     * @param string $toVersion Version to switch to
193
     * @return string Current database version
194
     */
195
    public function migrator($toVersion = null)
196
    {
197
        // If something passed - change database version to it
198
        if (func_num_args()) {
199
            // Save current version to special db table
200
            $this->database->execute(
201
                "ALTER TABLE  `" . dbMySQLConnector::$prefix . "cms_version`
202
                CHANGE  `version`  `version` VARCHAR( 15 ) CHARACTER SET utf8
203
                COLLATE utf8_general_ci NOT NULL DEFAULT  '" . $toVersion . "';"
204
            );
205
            die('Database successfully migrated to [' . $toVersion . ']');
206
        } else { // Return current database version
207
            $version_row = $this->database->fetch('SHOW COLUMNS FROM `' . dbMySQLConnector::$prefix . 'cms_version`');
208
            if (isset($version_row[0]['Default'])) {
209
                return $version_row[0]['Default'];
210
            } else {
211
                return 0;
212
            }
213
        }
214
    }
215
    //[PHPCOMPRESSOR(remove,end)]
216
}
217