Completed
Push — master ( 6fdefe...ec2cdb )
by Jeff
04:37 queued 01:52
created

Content::getFilepath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
eloc 3
nc 1
nop 0
1
<?php
2
3
namespace app\models;
4
5
use Yii;
6
7
/**
8
 * This is the model class for table "content".
9
 *
10
 * @property int $id
11
 * @property string $name
12
 * @property string $description
13
 * @property int $flow_id
14
 * @property string $type_id
15
 * @property string $data
16
 * @property int $duration
17
 * @property string $start_ts
18
 * @property string $end_ts
19
 * @property string $add_ts
20
 * @property bool $enabled
21
 * @property Flow $flow
22
 * @property ContentType $type
23
 */
24
class Content extends \yii\db\ActiveRecord
25
{
26
    /**
27
     * {@inheritdoc}
28
     */
29
    public static function tableName()
30
    {
31
        return 'content';
32
    }
33
34
    /**
35
     * {@inheritdoc}
36
     */
37
    public function rules()
38
    {
39
        return array_merge([
40
            [['name', 'flow_id', 'type_id'], 'required'],
41
            [['flow_id', 'duration'], 'integer'],
42
            [['data'], 'string'],
43
            [['start_ts', 'end_ts', 'add_ts'], 'safe'],
44
            [['enabled'], 'boolean'],
45
            [['name'], 'string', 'max' => 64],
46
            [['type_id'], 'string', 'max' => 45],
47
            [['description'], 'string', 'max' => 1024],
48
            [['flow_id'], 'exist', 'skipOnError' => true, 'targetClass' => Flow::className(), 'targetAttribute' => ['flow_id' => 'id']],
49
            [['type_id'], 'exist', 'skipOnError' => true, 'targetClass' => ContentType::className(), 'targetAttribute' => ['type_id' => 'id']],
50
        ], $this->type ? $this->type->contentRules() : []);
51
    }
52
53
    /**
54
     * {@inheritdoc}
55
     */
56
    public function attributeLabels()
57
    {
58
        return array_merge([
59
            'id' => Yii::t('app', 'ID'),
60
            'name' => Yii::t('app', 'Name'),
61
            'description' => Yii::t('app', 'Description'),
62
            'flow_id' => Yii::t('app', 'Flow'),
63
            'type_id' => Yii::t('app', 'Type'),
64
            'data' => Yii::t('app', 'Content'),
65
            'duration' => Yii::t('app', 'Duration in seconds'),
66
            'start_ts' => Yii::t('app', 'Start at'),
67
            'end_ts' => Yii::t('app', 'End on'),
68
            'add_ts' => Yii::t('app', 'Added at'),
69
            'enabled' => Yii::t('app', 'Enabled'),
70
        ], $this->type ? $this->type->contentLabels() : []);
71
    }
72
73
    /**
74
     * @return \yii\db\ActiveQuery
75
     */
76
    public function getFlow()
77
    {
78
        return $this->hasOne(Flow::className(), ['id' => 'flow_id']);
79
    }
80
81
    /**
82
     * @return \yii\db\ActiveQuery
83
     */
84
    public function getType()
85
    {
86
        return $this->hasOne(ContentType::className(), ['id' => 'type_id']);
87
    }
88
89
    /**
90
     * Build a query for a specific user, allowing to see only authorized contents.
91
     *
92
     * @param \User $user
93
     *
94
     * @return \yii\db\ActiveQuery
95
     */
96
    public static function availableQuery($user)
97
    {
98
        if ($user->can('setFlowContent')) {
99
            return self::find()->joinWith(['type']);
100 View Code Duplication
        } elseif ($user->can('setOwnFlowContent')) {
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...
101
            return self::find()->joinWith(['type', 'flow.users'])->where(['username' => $user->identity->username]);
102
        }
103
    }
104
105
    /**
106
     * Check if a specific user is allowed to see this content.
107
     *
108
     * @param \User $user
109
     *
110
     * @return bool can see
111
     */
112 View Code Duplication
    public function canView($user)
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...
113
    {
114
        if ($user->can('setFlowContent')) {
115
            return true;
116
        }
117
        if ($user->can('setOwnFlowContent') && in_array($user->identity, $this->flow->users)) {
118
            return true;
119
        }
120
121
        return false;
122
    }
123
124
    /**
125
     * Get raw data and transform it to content type specific needs.
126
     *
127
     * @param string $data
128
     *
129
     * @return string transformed data
130
     */
131
    public function processData($data)
132
    {
133
        return $this->type->processData($data);
0 ignored issues
show
Documentation Bug introduced by
The method processData does not exist on object<app\models\ContentType>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
134
    }
135
136
    /**
137
     * Retrieve data for content
138
     * Transforming it if necessary (mostly urls).
139
     *
140
     * @return string usable data
141
     */
142
    public function getData()
143
    {
144
        $data = $this->data;
145
        if ($this->type->appendParams) {
146
            $data .= (strpos($data, '?') === false ? '?' : '&').$this->type->appendParams;
147
        }
148
149
        $data = $this->processData($data);
0 ignored issues
show
Bug introduced by
It seems like $data can also be of type boolean; however, app\models\Content::processData() 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...
150
151
        if ($this->type->html) {
152
            return str_replace('%data%', $data, $this->type->html);
153
        }
154
155
        return $data;
156
    }
157
158
    public function beforeSave($insert)
159
    {
160
        if (!parent::beforeSave($insert)) {
161
            return false;
162
        }
163
164
        $res = $this->type->beforeSaveContent($insert, $this->data);
0 ignored issues
show
Unused Code introduced by
The call to ContentType::beforeSaveContent() has too many arguments starting with $insert.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
165
        if ($res === true || $res === false) {
166
            return $res;
167
        }
168
169
        $this->data = $res;
170
171
        return true;
172
    }
173
174
    /**
175
     * After delete event
176
     * Try to delete file if necessary.
177
     */
178
    public function afterDelete()
179
    {
180
        if ($this->shouldDeleteFile()) {
181
            unlink($this->getRealFilepath());
182
        }
183
        parent::afterDelete();
184
    }
185
186
    /**
187
     * Decide if content file should be deleted by checking usage in DB.
188
     *
189
     * @return bool deletable
190
     */
191
    protected function shouldDeleteFile()
192
    {
193
        if ($this->type->input == ContentType::KINDS['FILE']) {
194
            return self::find()
195
                ->joinWith(['type'])
196
                ->where([ContentType::tableName().'.id' => ContentType::getAllFileTypeIds()])
197
                ->andWhere(['data' => $this->data])
198
                ->count() == 0;
199
        }
200
201
        return false;
202
    }
203
204
    /**
205
     * Get filepath from web root.
206
     *
207
     * @return string filepath
208
     */
209
    public function getFilepath()
210
    {
211
        $type = $this->type;
212
213
        return str_replace($type::BASE_URI, '', $this->getWebFilepath());
214
    }
215
216
    /**
217
     * Get Yii aliased filepath.
218
     *
219
     * @return string filepath
220
     */
221
    public function getWebFilepath()
222
    {
223
        return $this->data;
224
    }
225
226
    /**
227
     * Get filesystem filepath.
228
     *
229
     * @return string filepath
230
     */
231
    public function getRealFilepath()
232
    {
233
        return \Yii::getAlias('@app/').'web/'.$this->getFilepath();
234
    }
235
}
236