Passed
Pull Request — master (#49)
by
unknown
11:52
created

PostRepository::getArchive()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 14
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 23
rs 9.7998
1
<?php
2
3
namespace App\Blog\Post;
4
5
use App\Blog\Comment\Scope\PublicScope;
6
use App\Blog\Entity\Post;
7
use Cycle\ORM\Select;
8
use Spiral\Database\DatabaseInterface;
9
use Spiral\Database\Driver\DriverInterface;
10
use Spiral\Database\Driver\SQLite\SQLiteDriver;
11
use Spiral\Database\Injection\Fragment;
12
use Yiisoft\Data\Reader\DataReaderInterface;
13
use Yiisoft\Data\Reader\Sort;
14
use Yiisoft\Yii\Cycle\DataReader\SelectDataReader;
15
16
class PostRepository extends Select\Repository
17
{
18
    /**
19
     * Get posts without filter with preloaded Users and Tags
20
     * @return SelectDataReader
21
     */
22
    public function findAllPreloaded(): DataReaderInterface
23
    {
24
        $query = $this->select()
25
                ->load(['user', 'tags']);
26
        return $this->prepareDataReader($query);
27
    }
28
29
    /**
30
     * @param int $year
31
     * @param int $month
32
     * @return SelectDataReader
33
     * @throws \Exception
34
     */
35
    public function findArchivedPublic(int $year, int $month): DataReaderInterface
36
    {
37
        $begin = (new \DateTimeImmutable())->setDate($year, $month, 1)->setTime(0, 0, 0);
38
        $end = $begin->setDate($year, $month + 1, 1)->setTime(0, 0, -1);
39
40
        $query = $this->select()
41
                    ->andWhere('published_at', 'between', $begin, $end)
42
                    ->load(['user', 'tags']);
43
        return $this->prepareDataReader($query);
44
    }
45
46
    /**
47
     * @param int|string $tagId
48
     * @return SelectDataReader
49
     */
50
    public function findByTag($tagId): DataReaderInterface
51
    {
52
        $query = $this->select()
53
                    ->where(['tags.id' => $tagId])
54
                    ->load(['user']);
55
        return $this->prepareDataReader($query);
56
    }
57
58
    public function fullPostPage(string $slug, ?string $userId = null): ?Post
59
    {
60
        $query = $this->select()
61
                      ->where(['slug' => $slug])
62
                      ->load('user', [
63
                          'method' => Select::SINGLE_QUERY,
64
                      ])
65
                      ->load('tags', [
66
                          'method' => Select::OUTER_QUERY,
67
                      ])
68
                      // force loading in single query with comments
69
                      ->load('comments.user', ['method' => Select::SINGLE_QUERY])
70
                      ->load('comments', [
71
                          'method' => Select::OUTER_QUERY,
72
                          // not works (default Constraint would not be replaced):
73
                          'load' => new PublicScope($userId === null ? null : ['user_id' => $userId]),
74
                      ]);
75
        /** @var null|Post $post */
76
        $post = $query->fetchOne();
77
        // /** @var Select\Repository $commentRepo */
78
        // $commentRepo = $this->orm->getRepository(Comment::class);
79
        // $commentRepo->select()->load('user')->where('post_id', $post->getId())->fetchAll();
80
        return $post;
81
    }
82
83
    /**
84
     * @return SelectDataReader Collection of Array('Count' => '123', 'Month' => '8', 'Year' => '2019')
85
     */
86
    public function getArchive(): DataReaderInterface
87
    {
88
        $sort = (new Sort([]))->withOrder(['year' => 'desc', 'month' => 'desc']);
89
90
        $query = $this
91
            ->select()
92
            ->buildQuery()
93
            ->columns(
94
                $this->getDriver() instanceof SQLiteDriver
95
                    ? [
96
                        'count(post.id) count',
97
                        new Fragment('strftime(\'%m\', post.published_at) month'),
98
                        new Fragment('strftime(\'%Y\', post.published_at) year'),
99
                    ]
100
                    : [
101
                        'count(post.id) count',
102
                        new Fragment('extract(month from post.published_at) month'),
103
                        new Fragment('extract(year from post.published_at) year'),
104
                    ]
105
            )
106
            ->groupBy('year, month');
107
108
        return (new SelectDataReader($query))->withSort($sort);
109
    }
110
111
    private function getDriver(): DriverInterface
112
    {
113
        return $this->select()
114
                    ->getBuilder()
115
                    ->getLoader()
116
                    ->getSource()
117
                    ->getDatabase()
118
                    ->getDriver(DatabaseInterface::READ);
119
    }
120
121
    private function prepareDataReader($query): SelectDataReader
122
    {
123
        return (new SelectDataReader($query))->withSort((new Sort([]))->withOrder(['published_at' => 'desc']));
124
    }
125
}
126