Completed
Push — master ( 3d3760...b0d42a )
by John
30s queued 13s
created

User::getDojoStatistics()   B

Complexity

Conditions 6
Paths 106

Size

Total Lines 43
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 6
eloc 27
c 1
b 0
f 1
nc 106
nop 0
dl 0
loc 43
rs 8.8257
1
<?php
2
3
namespace App\Models\Eloquent;
4
5
use Illuminate\Notifications\Notifiable;
6
use Illuminate\Contracts\Auth\MustVerifyEmail;
7
use Illuminate\Foundation\Auth\User as Authenticatable;
8
use Laravel\Passport\HasApiTokens;
9
use App\Models\Eloquent\UserExtra;
10
use App\Models\Eloquent\Dojo\DojoProblem;
11
use Carbon;
12
use DB;
13
use Log;
14
use Exception;
15
16
class User extends Authenticatable
17
{
18
    use HasApiTokens, Notifiable;
0 ignored issues
show
Bug introduced by
The trait Illuminate\Notifications\Notifiable requires the property $email which is not provided by App\Models\Eloquent\User.
Loading history...
19
20
    protected $table='users';
21
22
    /**
23
     * The attributes that are mass assignable.
24
     *
25
     * @var array
26
     */
27
    protected $fillable=[
28
        'name', 'email', 'password', 'avatar', 'contest_account'
29
    ];
30
31
    /**
32
     * The attributes that should be hidden for arrays.
33
     *
34
     * @var array
35
     */
36
    protected $hidden=[
37
        'password', 'remember_token', 'tokens'
38
    ];
39
40
    public function submissions()
41
    {
42
        return $this->hasMany('App\Models\Eloquent\Submission', 'uid');
43
    }
44
45
    public function banneds() {
46
        return $this->hasMany('App\Models\Eloquent\UserBanned');
47
    }
48
49
    public function announcements() {
50
        return $this->hasMany('App\Models\Eloquent\Announcement');
51
    }
52
53
    public function permissions() {
54
        return $this->hasMany('App\Models\Eloquent\UserPermission');
55
    }
56
57
    public function imagehostings() {
58
        return $this->hasMany('App\Models\Eloquent\Tool\ImageHosting');
59
    }
60
61
    public function extras() {
62
        return $this->hasMany('App\Models\Eloquent\UserExtra', 'uid');
63
    }
64
65
    public function hasPermission($permissionID) {
66
        return ($this->permissions()->where(['permission_id'=>$permissionID])->count())>0;
67
    }
68
69
    public function hasIndependentPassword() {
70
        return filled($this->password);
71
    }
72
73
    public function hasIndependentEmail() {
74
        return !in_array(explode('@', $this->email)[1], ['temporary.email']) && !$this->contest_account;
75
    }
76
77
    public function isIndependent() {
78
        return $this->hasIndependentPassword() && $this->hasIndependentEmail();
79
    }
80
81
    public function getReadableNameAttribute()
82
    {
83
        return $this->name.' ('.$this->email.')';
84
    }
85
86
    /**
87
     * To get some extra info of a user.
88
     *
89
     * @param string|array $need An array is returned when an array is passed in, Only one value is returned when a string is passed in.
90
     * @param int|null $secretLevel the secret level this query currently running on
91
     * @return string|array $result
92
     */
93
    public function getExtra($need, $secretLevel=0) {
94
        $ret=$this->extras()->orderBy('key')->get()->toArray();
95
        $result=[];
96
        if (!empty($ret)) {
97
            if (is_string($need)) {
98
                foreach ($ret as $value) {
99
                    if (empty($value['secret_level']) || $value['secret_level']<=$secretLevel) {
100
                        $keyName=UserExtra::$extraMapping[$value['key']] ?? 'unknown';
101
                        if ($keyName==$need) {
102
                            return $value['value'];
103
                        }
104
                    }
105
                }
106
                return null;
107
            } else {
108
                foreach ($ret as $value) {
109
                    if (empty($value['secret_level']) || $value['secret_level']<=$secretLevel) {
110
                        $keyName=UserExtra::$extraMapping[$value['key']] ?? 'unknown';
111
                        if (in_array($keyName, $need)) {
112
                            $result[$keyName]=$value['value'];
113
                        }
114
                    }
115
                }
116
            }
117
        }
118
        return $result;
119
    }
120
121
    /**
122
     * To set some extra info of a user.
123
     *
124
     * @param string $keyName insert when key not found or update when key exists. Only values declared in UserExtra Model are accepted
125
     * @param string|null $value the extra info will be delete when value is null
126
     * @param int|null $secretLevel the secret level this query currently running on
127
     * @return mixed $result
128
     */
129
    public function setExtra($keyName, $value=null, $secretLevel=-1) {
130
        $key=array_search($keyName, UserExtra::$extraMapping);
131
        if ($key===false) {
132
            return false;
133
        }
134
        $ret=$this->extras()->where('key', $key)->limit(1)->get()->toArray();
135
        if (!empty($ret)) {
136
            $ret=$ret[0];
137
            unset($ret['id']);
138
            if (!is_null($value)) {
139
                $ret['value']=$value;
140
            } else {
141
                $this->extras()->where('key', $key)->delete();
142
                return true;
143
            }
144
            if ($secretLevel!=-1) {
145
                $ret['secret_level']=$secretLevel;
146
            }
147
            return $this->extras()->where('key', $key)->update($ret);
148
        } else {
149
            if ($value===null) {
150
                return true;
151
            }
152
            return $this->extras()->create([
153
                'key' => $key,
154
                'value' => $value,
155
                'secret_level' => $secretLevel==-1 ? 0 : $secretLevel,
156
            ])->id;
157
        }
158
    }
159
160
    public function getSocialiteInfo($secretLevel=-1)
0 ignored issues
show
Unused Code introduced by
The parameter $secretLevel is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

160
    public function getSocialiteInfo(/** @scrutinizer ignore-unused */ $secretLevel=-1)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
161
    {
162
        $socialites=[];
163
        foreach (UserExtra::$socialite_support as $key => $value) {
164
            $id_keyname=$key.'_id';
165
            $id=$this->getExtra($id_keyname);
166
            if (!empty($id)) {
167
                $info=[
168
                    'id' => $id,
169
                ];
170
                foreach ($value as $info_name) {
171
                    $info_temp=$this->getExtra($key.'_'.$info_name);
172
                    if ($info_temp!==null) {
173
                        $info[$info_name]=$info_temp;
174
                    }
175
                }
176
                $socialites[$key]=$info;
177
            }
178
        }
179
180
        return $socialites;
181
    }
182
183
    public function problems_latest_submission($problems, $contestID = null, Carbon $till = null, $verdictFilter = [])
184
    {
185
        if (filled($contestID)) {
186
            $endedAt = Carbon::parse(Contest::findOrFail($contestID)->endedAt);
187
        }
188
189
        $lastRecordSubQuery = $this->submissions()->select('pid', DB::raw('MAX(submission_date) as submission_date'))->whereIntegerInRaw('pid', $problems)->where('cid', $contestID)->groupBy('pid');
190
191
        if (filled($contestID)) {
192
            $lastRecordSubQuery = $lastRecordSubQuery->where("submission_date", "<", $endedAt->timestamp);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $endedAt does not seem to be defined for all execution paths leading up to this point.
Loading history...
193
        }
194
195
        if (filled($till)) {
196
            $lastRecordSubQuery = $lastRecordSubQuery->where("submission_date", "<", $till->timestamp);
197
        }
198
199
        if(filled($verdictFilter)) {
200
            $lastRecordSubQuery = $lastRecordSubQuery->whereIn('verdict', $verdictFilter);
201
        }
202
203
        $query = DB::table(DB::raw("({$lastRecordSubQuery->toSql()}) last_sub"))->leftJoinSub(Submission::toBase(), 'submissions', function ($join) {
204
            $join->on('last_sub.submission_date', '=', 'submissions.submission_date')->on('last_sub.pid', '=', 'submissions.pid');
205
        })->select('sid', 'last_sub.submission_date as submission_date', 'last_sub.pid as pid', 'verdict', 'color')->orderBy('pid', 'ASC');
206
207
        return $query->mergeBindings($lastRecordSubQuery->toBase());
208
    }
209
210
    public function getDojoStatistics()
211
    {
212
        try {
213
            $statistics = [];
214
            $problemIDArr = DojoProblem::select('problem_id')->distinct()->get()->pluck('problem_id');
215
216
            foreach ($problemIDArr as $problemID) {
217
                $defaultVerdict[$problemID] = [
218
                    "icon" => "checkbox-blank-circle-outline",
219
                    "color" => "wemd-grey-text"
220
                ];
221
            }
222
223
            $problemCompleteIDArr = [];
224
225
            foreach ($this->problems_latest_submission($problemIDArr->diff($problemCompleteIDArr), null, null, ['Accepted'])->get() as $acceptedRecord) {
226
                $statistics[$acceptedRecord['pid']] = [
227
                    "icon" => "checkbox-blank-circle",
228
                    "color" => $acceptedRecord['color']
229
                ];
230
                $problemCompleteIDArr[] = $acceptedRecord['pid'];
231
            }
232
233
            foreach ($this->problems_latest_submission($problemIDArr->diff($problemCompleteIDArr), null, null, ['Partially Accepted'])->get() as $acceptedRecord) {
234
                $statistics[$acceptedRecord['pid']] = [
235
                    "icon" => "cisco-webex",
236
                    "color" => $acceptedRecord['color']
237
                ];
238
                $problemCompleteIDArr[] = $acceptedRecord['pid'];
239
            }
240
241
            foreach ($this->problems_latest_submission($problemIDArr->diff($problemCompleteIDArr), null, null)->get() as $acceptedRecord) {
242
                $statistics[$acceptedRecord['pid']] = [
243
                    "icon" => "cisco-webex",
244
                    "color" => $acceptedRecord['color']
245
                ];
246
                $problemCompleteIDArr[] = $acceptedRecord['pid'];
247
            }
248
249
            return $statistics;
250
        } catch (Exception $e) {
251
            Log::alert($e);
252
            return false;
253
        }
254
    }
255
}
256