Passed
Push — master ( bda6ce...afc50f )
by Mihail
05:03
created

FormNarrowContentUpdate::rules()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 17

Duplication

Lines 5
Ratio 21.74 %

Importance

Changes 1
Bugs 1 Features 1
Metric Value
cc 2
eloc 17
nc 2
nop 0
dl 5
loc 23
rs 9.0856
c 1
b 1
f 1
1
<?php
2
3
namespace Apps\Model\Front\Content;
4
5
use Apps\ActiveRecord\ContentCategory;
6
use Ffcms\Core\App;
7
use Ffcms\Core\Arch\Model;
8
use Ffcms\Core\Helper\FileSystem\Directory;
9
use Ffcms\Core\Helper\FileSystem\Normalize;
10
use Ffcms\Core\Helper\Serialize;
11
use Apps\ActiveRecord\Content;
12
use Ffcms\Core\Helper\Type\Obj;
13
use Ffcms\Core\Helper\Type\Str;
14
use Gregwar\Image\Image;
15
16
class FormNarrowContentUpdate extends Model
17
{
18
    public $title = [];
19
    public $text = [];
20
    public $path;
21
    public $categoryId;
22
    /** @var \Symfony\Component\HttpFoundation\File\UploadedFile $poster */
23
    public $poster;
24
25
    public $authorId;
26
27
    /** @var Content */
28
    private $_record;
29
    /** @var array */
30
    private $_configs;
31
32
    private $_new = false;
33
34
    /**
35
     * FormNarrowContentUpdate constructor. Pass record object inside.
36
     * @param Content $record
37
     * @param array $configs
38
     */
39
    public function __construct(Content $record, $configs)
40
    {
41
        $this->_record = $record;
42
        $this->_configs = $configs;
43
        parent::__construct();
44
    }
45
46
    /**
47
    * Set default values from database record
48
    */
49
    public function before()
50
    {
51
        // set data from db record
52
        $this->title = Serialize::decode($this->_record->title);
0 ignored issues
show
Documentation Bug introduced by
It seems like \Ffcms\Core\Helper\Seria...($this->_record->title) can also be of type string. However, the property $title is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

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

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
53
        $this->text = Serialize::decode($this->_record->text);
0 ignored issues
show
Documentation Bug introduced by
It seems like \Ffcms\Core\Helper\Seria...e($this->_record->text) can also be of type string. However, the property $text is declared as type array. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

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

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
54
        $this->path = $this->_record->path;
55
        $this->categoryId = $this->_record->category_id;
56
57
        // set current user id
58
        $this->authorId = App::$User->identity()->getId();
59
        // set true if it is a new content item
60
        if ($this->_record->id === null || (int)$this->_record->id < 1) {
61
            $this->_new = true;
62
        }
63
64
        // set random path slug if not defined
65
        if ($this->path === null || Str::likeEmpty($this->path)) {
66
            $randPath = date('d-m-Y') . '-' . Str::randomLatin(mt_rand(8,12));
67
            $this->path = Str::lowerCase($randPath);
68
        }
69
    }
70
71
    /**
72
     * Form field input sources: post/get/file
73
     * {@inheritDoc}
74
     * @see \Ffcms\Core\Arch\Model::sources()
75
     */
76
    public function sources()
77
    {
78
        return [
79
            'poster' => 'file',
80
            'title' => 'post',
81
            'text' => 'post',
82
            'path' => 'post',
83
            'categoryId' => 'post'
84
        ];
85
    }
86
87
    /**
88
    * Form labels
89
    * @return array
90
    */
91
    public function labels()
92
    {
93
        return [
94
            'title' => __('Title'),
95
            'text' => __('Text'),
96
            'path' => __('Path slug'),
97
            'categoryId' => __('Category'),
98
            'poster' => __('Poster')
99
        ];
100
    }
101
102
    /**
103
    * Content update form validation rules
104
    * @return array
105
    */
106
    public function rules()
107
    {
108
        $r = [
109
            [['path', 'categoryId'], 'required'],
110
            ['title.' . App::$Request->getLanguage(), 'required'],
111
            ['text.' . App::$Request->getLanguage(), 'required', null, true, true],
112
            ['text', 'used', null, true, true],
113
            ['path', 'direct_match', '/^[a-zA-Z0-9\-]+$/'],
114
            ['categoryId', 'in', $this->categoryIds()],
115
            ['path', 'Apps\Model\Front\Content\FormNarrowContentUpdate::validatePath'],
116
            ['poster', 'used'],
117
            ['poster', 'isFile', ['jpg', 'png', 'gif', 'jpeg']],
118
            ['poster', 'sizeFile', (int)$this->_configs['gallerySize'] * 1024] // in bytes
119
        ];
120
121 View Code Duplication
        foreach (App::$Properties->get('languages') as $lang) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
122
            $r[] = ['title.' . $lang, 'length_max', 120, null, true, true];
123
            $r[] = ['keywords.' . $lang, 'length_max', 150];
124
            $r[] = ['description.' . $lang, 'length_max', 250];
125
        }
126
127
        return $r;
128
    }
129
130
    /**
131
     * Save input data to database
132
     */
133
    public function make()
134
    {
135
        // save data to db
136
        $this->_record->title = Serialize::encode(App::$Security->strip_tags($this->title));
137
        $this->_record->text = Serialize::encode(App::$Security->secureHtml($this->text));
138
        $this->_record->path = $this->path;
139
        $this->_record->category_id = (int)$this->categoryId;
140
        $this->_record->display = 0; // set to premoderation
141
        $this->_record->author_id = (int)$this->authorId;
142
        if ($this->_new === true) {
143
            $this->_record->comment_hash = $this->generateCommentHash();
144
        }
145
146
        $this->_record->save();
147
148
        // work with poster data
149
        if ($this->poster !== null) {
150
            // lets move poster from tmp to gallery
151
            $originDir = '/upload/gallery/' . $this->_record->id . '/orig/';
152
            $thumbDir = '/upload/gallery/' . $this->_record->id . '/thumb/';
153
            if (!Directory::exist($originDir)) {
154
                Directory::create($originDir);
155
            }
156
            if (!Directory::exist($thumbDir)) {
157
                Directory::create($thumbDir);
158
            }
159
160
            $fileName = App::$Security->simpleHash($this->poster->getClientOriginalName() . $this->poster->getSize());
161
            $newFullName = $fileName . '.' . $this->poster->guessExtension();
162
            // move poster to upload gallery directory
163
            $this->poster->move(Normalize::diskFullPath($originDir), $newFullName);
164
            // initialize image resizer
165
            $thumb = new Image();
166
            $thumb->setCacheDir(root . '/Private/Cache/images');
167
168
            // open original file, resize it and save
169
            $thumbSaveName = Normalize::diskFullPath($thumbDir) . '/' . $fileName . '.jpg';
170
            $thumb->open(Normalize::diskFullPath($originDir) . DIRECTORY_SEPARATOR . $newFullName)
171
                ->cropResize($this->_configs['galleryResize'])
172
                ->save($thumbSaveName, 'jpg', 90);
173
            $thumb = null;
0 ignored issues
show
Unused Code introduced by
$thumb is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
174
175
            // update poster in database
176
            $this->_record->poster = $newFullName;
177
            $this->_record->save();
178
        }
179
    }
180
181
    /**
182
     * Get allowed category ids as array (string values for validation)
183
     * @return array
184
     */
185 View Code Duplication
    public function categoryIds()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
186
    {
187
        $data = ContentCategory::getSortedCategories();
188
        $response = [];
189
        foreach ($data as $key=>$val) {
190
            $response[] = (string)$key;
191
        }
192
        return $response;
193
    }
194
195 View Code Duplication
    public function validatePath()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
196
    {
197
        // try to find this item
198
        $find = Content::where('path', '=', $this->path);
199
        // exclude self id
200
        if ($this->_record->id !== null && Obj::isLikeInt($this->_record->id)) {
201
            $find->where('id', '!=', $this->_record->id);
202
        }
203
204
        // limit only current category id
205
        $find->where('category_id', '=', $this->categoryId);
206
207
        return $find->count() < 1;
208
    }
209
210
    /**
211
     * Generate random string for comment hash value
212
     * @return string
213
     */
214 View Code Duplication
    private function generateCommentHash()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
215
    {
216
        $hash = Str::randomLatinNumeric(mt_rand(32, 128));
217
        $find = Content::where('comment_hash', '=', $hash)->count();
218
        // hmmm, is always exist? Chance of it is TOOOO low, but lets recursion re-generate
219
        if ($find !== 0) {
220
            return $this->generateCommentHash();
221
        }
222
223
        return $hash;
224
    }
225
}