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

ArchiveRepository::prepareDataReader()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace App\Blog\Archive;
6
7
use App\Blog\Entity\Post;
8
use App\Blog\Post\PostRepository;
9
use Cycle\ORM\ORMInterface;
10
use Cycle\ORM\Select;
11
use Spiral\Database\DatabaseInterface;
12
use Spiral\Database\Driver\DriverInterface;
13
use Spiral\Database\Driver\SQLite\SQLiteDriver;
14
use Spiral\Database\Injection\Fragment;
15
use Yiisoft\Data\Reader\DataReaderInterface;
16
use Yiisoft\Data\Reader\Sort;
17
use Yiisoft\Yii\Cycle\DataReader\SelectDataReader;
18
19
/**
20
 * This repository is not associated with Post entity
21
 */
22
final class ArchiveRepository
23
{
24
    private PostRepository $postRepo;
25
26
    public function __construct(ORMInterface $orm)
27
    {
28
        /** @var PostRepository $postRepo */
29
        $postRepo = $orm->getRepository(Post::class);
30
        $this->postRepo = $postRepo;
31
    }
32
33
    public function select(): Select
34
    {
35
        return $this->postRepo->select();
36
    }
37
38
    /**
39
     * @param int $year
40
     * @param int $month
41
     * @return SelectDataReader
42
     * @throws \Exception
43
     */
44
    public function getMonthlyArchive(int $year, int $month): DataReaderInterface
45
    {
46
        $begin = (new \DateTimeImmutable())->setDate($year, $month, 1)->setTime(0, 0, 0);
47
        $end = $begin->setDate($year, $month + 1, 1)->setTime(0, 0, -1);
48
49
        $query = $this->select()
50
                    ->andWhere('published_at', 'between', $begin, $end)
51
                    ->load(['user', 'tags']);
52
        return $this->prepareDataReader($query);
53
    }
54
55
    public function getYearlyArchive(int $year): DataReaderInterface
56
    {
57
        $begin = (new \DateTimeImmutable())->setDate($year, 1, 1)->setTime(0, 0, 0);
58
        $end = $begin->setDate($year + 1, 1, 1)->setTime(0, 0, -1);
59
60
        $query = $this
61
            ->select()
62
            ->andWhere('published_at', 'between', $begin, $end)
63
            ->load('user', ['method' => Select::SINGLE_QUERY])
64
            ->orderBy(['published_at' => 'asc']);
65
        return $this->prepareDataReader($query);
66
    }
67
68
    /**
69
     * @return SelectDataReader Collection of Array('Count' => '123', 'Month' => '8', 'Year' => '2019')
70
     */
71
    public function getFullArchive(): DataReaderInterface
72
    {
73
        $sort = (new Sort([]))->withOrder(['year' => 'desc', 'month' => 'desc']);
74
75
        $query = $this
76
            ->select()
77
            ->buildQuery()
78
            ->columns([
79
                'count(post.id) count',
80
                $this->extractFromDateColumn('month'),
81
                $this->extractFromDateColumn('year'),
82
            ])
83
            ->groupBy('year, month');
84
85
        return (new SelectDataReader($query))->withSort($sort);
86
    }
87
88
    /**
89
     * @param string $attr Can be 'day', 'month' or 'year'
90
     * @return Fragment
91
     */
92
    private function extractFromDateColumn(string $attr): Fragment
93
    {
94
        if ($this->getDriver() instanceof SQLiteDriver) {
95
            $str = ['year' => '%Y', 'month' => '%m', 'day' => '%d'][$attr];
96
            return new Fragment("strftime('{$str}', post.published_at) {$attr}");
97
        }
98
        return new Fragment("extract({$attr} from post.published_at) {$attr}");
99
    }
100
101
    private function getDriver(): DriverInterface
102
    {
103
        return $this->select()
104
                    ->getBuilder()
105
                    ->getLoader()
106
                    ->getSource()
107
                    ->getDatabase()
108
                    ->getDriver(DatabaseInterface::READ);
109
    }
110
111
    /**
112
     * @param Select|SelectQuery $query
0 ignored issues
show
Bug introduced by
The type App\Blog\Archive\SelectQuery was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
113
     * @return SelectDataReader
114
     */
115
    private function prepareDataReader($query): SelectDataReader
116
    {
117
        return (new SelectDataReader($query))->withSort((new Sort([]))->withOrder(['published_at' => 'desc']));
118
    }
119
}
120