Passed
Push — master ( c86e8c...1b1f16 )
by Mihail
04:54
created

EntityContentRead   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 210
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 12

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 210
rs 10
wmc 26
lcom 1
cbo 12

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
C before() 0 59 9
C prepareGallery() 0 43 8
B expandCategoryNesting() 0 32 6
A getRecord() 0 4 1
A getCategory() 0 4 1
1
<?php
2
3
namespace Apps\Model\Front\Content;
4
5
use Apps\ActiveRecord\Content;
6
use Apps\ActiveRecord\ContentCategory;
7
use Ffcms\Core\App;
8
use Ffcms\Core\Arch\Model;
9
use Ffcms\Core\Exception\ForbiddenException;
10
use Ffcms\Core\Helper\Date;
11
use Ffcms\Core\Helper\FileSystem\Directory;
12
use Ffcms\Core\Helper\FileSystem\File;
13
use Ffcms\Core\Helper\Type\Any;
14
use Ffcms\Core\Helper\Type\Arr;
15
use Ffcms\Core\Helper\Type\Obj;
16
use Ffcms\Core\Helper\Type\Str;
17
18
/**
19
 * Class EntityContentRead. Prepare record object data to display.
20
 * @package Apps\Model\Front\Content
21
 */
22
class EntityContentRead extends Model
23
{
24
    public $id;
25
    public $title;
26
    public $path;
27
    public $text;
28
    public $display;
29
    public $createDate;
30
    public $editDate;
31
    public $catName;
32
    public $catPath;
33
    public $authorId;
34
    public $authorName;
35
    public $views;
36
    public $catNesting = [];
37
    public $source;
38
    public $posterThumb;
39
    public $posterFull;
40
    public $rating;
41
    public $canRate;
42
43
    public $metaTitle;
44
    public $metaDescription;
45
    public $metaKeywords;
46
47
    // gallery image key-value array as thumb->full
48
    public $galleryItems;
49
50
    // private activerecord relation objects
51
    private $_category;
52
    private $_content;
53
54
    /**
55
     * EntityContentRead constructor. Pass active record objects
56
     * @param ContentCategory $category
57
     * @param Content $content
58
     */
59
    public function __construct(ContentCategory $category, Content $content)
60
    {
61
        $this->_category = $category;
62
        $this->_content = $content;
63
        parent::__construct();
64
    }
65
66
    /**
67
     * Prepare model attributes from passed objects
68
     * @throws ForbiddenException
69
    */
70
    public function before()
71
    {
72
        $this->id = $this->_content->id;
73
        $this->title = $this->_content->getLocaled('title');
74
        $this->text = $this->_content->getLocaled('text');
75
        $this->display = (bool)$this->_content->display;
76
77
        // check if title and text are exists
78
        if (Str::length($this->title) < 1 || Str::length($this->text) < 1) {
0 ignored issues
show
Bug introduced by
It seems like $this->title can also be of type array or null; however, Ffcms\Core\Helper\Type\Str::length() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
Bug introduced by
It seems like $this->text can also be of type array or null; however, Ffcms\Core\Helper\Type\Str::length() does only seem to accept string, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
79
            throw new ForbiddenException('Content of this page is empty!');
80
        }
81
82
        // get meta data
83
        $this->metaTitle = $this->_content->getLocaled('meta_title');
84
        if (Any::isEmpty($this->metaTitle)) {
85
            $this->metaTitle = $this->title;
86
        }
87
88
        $this->metaDescription = $this->_content->getLocaled('meta_description');
89
        $tmpKeywords = $this->_content->getLocaled('meta_keywords');
90
        $this->metaKeywords = explode(',', $tmpKeywords);
91
92
        // set content date, category data
93
        $this->createDate = Date::humanize($this->_content->created_at);
0 ignored issues
show
Security Bug introduced by
It seems like $this->_content->created_at can also be of type false; however, Ffcms\Core\Helper\Date::humanize() does only seem to accept string|integer, did you maybe forget to handle an error condition?
Loading history...
94
        $this->catName = $this->_category->getLocaled('title');
95
        $this->catPath = $this->_category->path;
96
97
        // set user data
98
        if (App::$User->isExist($this->_content->author_id)) {
99
            $this->authorId = $this->_content->author_id;
100
            $profile = App::$User->identity($this->authorId)->profile;
101
            $this->authorName = $profile->getNickname();
102
        }
103
104
        $this->source = $this->_content->source;
105
        $this->views = $this->_content->views+1;
106
107
        // build category nesting sorted array
108
        $this->catNesting[] = $this->expandCategoryNesting();
109
        // set gallery thumbnail & image if exist
110
        $this->prepareGallery();
111
        
112
        // set rating data
113
        $this->rating = $this->_content->rating;
114
        $ignoredRate = App::$Session->get('content.rate.ignore');
115
        $this->canRate = true;
116
        if (Any::isArray($ignoredRate) && Arr::in((string)$this->id, $ignoredRate)) {
117
            $this->canRate = false;
118
        }
119
        if (!App::$User->isAuth()) {
120
            $this->canRate = false;
121
        } elseif ($this->authorId === App::$User->identity()->getId()) {
122
            $this->canRate = false;
123
        }
124
        
125
        // update views count
126
        $this->_content->views += 1;
127
        $this->_content->save();
128
    }
129
130
    /**
131
     * Prepare gallery items, poster and thumb
132
     */
133
    private function prepareGallery()
134
    {
135
        // get gallery images and poster data
136
        $galleryPath = '/upload/gallery/' . $this->_content->id;
137
        // check if gallery folder is exist
138
        if (Directory::exist($galleryPath)) {
139
            $originImages = File::listFiles($galleryPath . '/orig/', ['.jpg', '.png', '.gif', '.jpeg', '.bmp', '.webp'], true);
140
            // generate poster data
141
            if (Arr::in($this->_content->poster, $originImages)) {
142
                // original poster
143
                $posterName = $this->_content->poster;
144
                $this->posterFull = $galleryPath . '/orig/' . $posterName;
145
                if (!File::exist($this->posterFull)) {
146
                    $this->posterFull = null;
147
                }
148
149
                // thumb poster
150
                $posterSplit = explode('.', $posterName);
151
                array_pop($posterSplit);
152
                $posterCleanName = implode('.', $posterSplit);
153
                $this->posterThumb = $galleryPath . '/thumb/' . $posterCleanName . '.jpg';
154
                if (!File::exist($this->posterThumb)) {
155
                    $this->posterThumb = null;
156
                }
157
            }
158
159
            // generate full gallery
160
            foreach ($originImages as $image) {
161
                $imageSplit = explode('.', $image);
162
                array_pop($imageSplit);
163
                $imageClearName = implode('.', $imageSplit);
164
                // skip image used in poster
165
                if (Str::startsWith($imageClearName, $this->_content->poster)) {
166
                    continue;
167
                }
168
169
                $thumbPath = $galleryPath . '/thumb/' . $imageClearName . '.jpg';
170
                if (File::exist($thumbPath)) {
171
                    $this->galleryItems[$thumbPath] = $galleryPath . '/orig/' . $image;
172
                }
173
            }
174
        }
175
    }
176
177
    /**
178
     * Expand category nesting array
179
     * @return array
180
     */
181
    private function expandCategoryNesting()
182
    {
183
        // check for dependence, add '' for general cat, ex: general/depend1/depend2/.../depend-n
184
        $catNestingArray = Arr::merge([0 => ''], explode('/', $this->catPath));
185
        if ($catNestingArray > 1) {
186
            // latest element its a current nesting level, lets cleanup it
187
            array_pop($catNestingArray);
188
            $catNestingPath = null;
189
            foreach ($catNestingArray as $cPath) {
190
                $catNestingPath .= $cPath;
191
192
                // try to find category by path in db
193
                $record = ContentCategory::getByPath($catNestingPath);
194
                if ($record !== null && $record->count() > 0) {
195
                    // if founded - add to nesting data
196
                    $this->catNesting[] = [
197
                        'name' => $record->getLocaled('title'),
198
                        'path' => $record->path
199
                    ];
200
                }
201
                if (!Str::likeEmpty($catNestingPath)) {
202
                    $catNestingPath .= '/';
203
                }
204
            }
205
        }
206
207
        // build array of category nesting level
208
        return [
209
            'name' => $this->catName,
210
            'path' => $this->catPath
211
        ];
212
    }
213
214
    /**
215
     * Get content record obj
216
     * @return Content
217
     */
218
    public function getRecord()
219
    {
220
        return $this->_content;
221
    }
222
223
    /**
224
     * Get category relation of this content
225
     * @return ContentCategory
226
     */
227
    public function getCategory()
228
    {
229
        return $this->_category;
230
    }
231
}
232