DatedUpdateHolder::ExtractMonths()   B
last analyzed

Complexity

Conditions 9
Paths 52

Size

Total Lines 70
Code Lines 40

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 40
nc 52
nop 4
dl 0
loc 70
rs 7.7244
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace CWP\CWP\PageTypes;
4
5
use DateTime;
6
use Page;
0 ignored issues
show
Bug introduced by
The type Page 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...
7
use SilverStripe\CMS\Model\SiteTree;
8
use SilverStripe\Control\Director;
9
use SilverStripe\Control\HTTP;
10
use SilverStripe\Core\Config\Config;
11
use SilverStripe\Core\Convert;
12
use SilverStripe\ORM\ArrayList;
13
use SilverStripe\ORM\DataList;
14
use SilverStripe\ORM\DataObject;
15
use SilverStripe\ORM\PaginatedList;
16
use SilverStripe\Taxonomy\TaxonomyTerm;
17
18
class DatedUpdateHolder extends Page
19
{
20
    /**
21
     * Meant as an abstract base class.
22
     *
23
     * {@inheritDoc}
24
     */
25
    private static $hide_ancestor = DatedUpdateHolder::class;
0 ignored issues
show
introduced by
The private property $hide_ancestor is not used, and could be removed.
Loading history...
26
27
    private static $update_name = 'Updates';
0 ignored issues
show
introduced by
The private property $update_name is not used, and could be removed.
Loading history...
28
29
    private static $update_class = DatedUpdatePage::class;
0 ignored issues
show
introduced by
The private property $update_class is not used, and could be removed.
Loading history...
30
31
    private static $singular_name = 'Dated Update Holder';
0 ignored issues
show
introduced by
The private property $singular_name is not used, and could be removed.
Loading history...
32
33
    private static $plural_name = 'Dated Update Holders';
0 ignored issues
show
introduced by
The private property $plural_name is not used, and could be removed.
Loading history...
34
35
    private static $table_name = 'DatedUpdateHolder';
0 ignored issues
show
introduced by
The private property $table_name is not used, and could be removed.
Loading history...
36
37
    /**
38
     * Find all distinct tags (TaxonomyTerms) associated with the DatedUpdatePages under this holder.
39
     */
40
    public function UpdateTags()
41
    {
42
        $siteTree = DataObject::getSchema()->tableName(SiteTree::class);
43
        $taxonomy = DataObject::getSchema()->tableName(TaxonomyTerm::class);
44
45
        $tags = TaxonomyTerm::get()
46
            ->innerJoin('BasePage_Terms', sprintf('"%s"."ID"="BasePage_Terms"."TaxonomyTermID"', $taxonomy))
47
            ->innerJoin(
48
                $siteTree,
49
                sprintf(
50
                    '"%s"."ID" = "BasePage_Terms"."BasePageID" AND "%s"."ParentID" = \'%d\'',
51
                    $siteTree,
52
                    $siteTree,
53
                    $this->ID
54
                )
55
            )
56
            ->sort('Name');
57
58
        return $tags;
59
    }
60
61
    /**
62
     * Wrapper to find all updates belonging to this holder, based on some filters.
63
     */
64
    public function Updates($tagID = null, $dateFrom = null, $dateTo = null, $year = null, $monthNumber = null)
65
    {
66
        $className = Config::inst()->get($this->ClassName, 'update_class');
67
        return static::AllUpdates($className, $this->ID, $tagID, $dateFrom, $dateTo, $year, $monthNumber);
68
    }
69
70
    /**
71
     * Find all site's updates, based on some filters.
72
     * Omitting parameters will prevent relevant filters from being applied. The filters are ANDed together.
73
     *
74
     * @param string $className The name of the class to fetch.
75
     * @param int|null $parentID The ID of the holder to extract the updates from.
76
     * @param int|null $tagID The ID of the tag to filter the updates by.
77
     * @param string|null $dateFrom The beginning of a date filter range.
78
     * @param string|null $dateTo The end of the date filter range. If empty, only one day will be searched for.
79
     * @param int|null $year Numeric value of the year to show.
80
     * @param int|null $monthNumber Numeric value of the month to show.
81
     *
82
     * @returns DataList | PaginatedList
83
     */
84
    public static function AllUpdates(
85
        $className = DatedUpdatePage::class,
86
        $parentID = null,
87
        $tagID = null,
88
        $dateFrom = null,
89
        $dateTo = null,
90
        $year = null,
91
        $monthNumber = null
92
    ) {
93
94
        $items = $className::get();
95
        $dbTableName = DataObject::getSchema()->tableForField($className, 'Date');
96
        if (!$dbTableName) {
97
            $dbTableName = DatedUpdatePage::class;
98
        }
99
100
        // Filter by parent holder.
101
        if (isset($parentID)) {
102
            $items = $items->filter(['ParentID'=>$parentID]);
103
        }
104
105
        // Filter down to a single tag.
106
        if (isset($tagID)) {
107
            $taxonomy = DataObject::getSchema()->tableName(TaxonomyTerm::class);
108
            $tableName = DataObject::getSchema()->tableName($className);
109
110
            $items = $items->innerJoin(
111
                'BasePage_Terms',
112
                sprintf('"%s"."ID" = "BasePage_Terms"."BasePageID"', $tableName)
113
            )->innerJoin(
114
                $taxonomy,
115
                sprintf(
116
                    '"BasePage_Terms"."TaxonomyTermID" = "%s"."ID" AND "TaxonomyTerm"."ID" = \'%d\'',
117
                    $taxonomy,
118
                    $tagID
119
                )
120
            );
121
        }
122
123
        // Filter by date
124
        if (isset($dateFrom)) {
125
            if (!isset($dateTo)) {
126
                $dateTo = $dateFrom;
127
            }
128
129
            $items = $items->where([
130
                sprintf('"%s"."Date" >= \'%s\'', $dbTableName, Convert::raw2sql("$dateFrom 00:00:00")),
131
                sprintf('"%s"."Date" <= \'%s\'', $dbTableName, Convert::raw2sql("$dateTo 23:59:59"))
132
            ]);
133
        }
134
135
        // Filter down to single month.
136
        if (isset($year) && isset($monthNumber)) {
137
            $year = (int)$year;
138
            $monthNumber = (int)$monthNumber;
139
140
            $beginDate = sprintf("%04d-%02d-01 00:00:00", $year, $monthNumber);
141
            $endDate = date('Y-m-d H:i:s', strtotime("{$beginDate} +1 month"));
142
143
            $items = $items->where(array(
144
                sprintf('"%s"."Date" >= \'%s\'', $dbTableName, Convert::raw2sql($beginDate)),
145
                sprintf('"%s"."Date" < \'%s\'', $dbTableName, Convert::raw2sql($endDate))
146
            ));
147
        }
148
149
        // Unpaginated DataList.
150
        return $items;
151
    }
152
153
    /**
154
     * Produce an ArrayList of available months out of the updates contained in the DataList.
155
     *
156
     * Here is an example of the returned structure:
157
     * ArrayList:
158
     *   ArrayData:
159
     *     YearName => 2013
160
     *     Months => ArrayList:
161
     *       MonthName => Jan
162
     *       MonthNumber => 1
163
     *       MonthLink => (page URL)year=2012&month=1
164
     *       Active => true
165
     *   ArrayData:
166
     *     YearName => 2012
167
     *     Months => ArrayList:
168
     *     ...
169
     *
170
     * @param DataList $updates DataList DataList to extract months from.
171
     * @param string $link Link used as abase to construct the MonthLink.
172
     * @param int $currentYear Currently selected year, for computing the link active state.
173
     * @param int $currentMonthNumber Currently selected month, for computing the link active state.
174
     *
175
     * @returns ArrayList
176
     */
177
    public static function ExtractMonths(
178
        DataList $updates,
179
        $link = null,
180
        $currentYear = null,
181
        $currentMonthNumber = null
182
    ) {
183
        // Set the link to current URL in the same way the HTTP::setGetVar does it.
184
        if (!isset($link)) {
185
            $link = Director::makeRelative($_SERVER['REQUEST_URI']);
186
        }
187
188
        $dates = $updates->dataQuery()
189
            ->groupby('YEAR("Date")')
190
            ->groupby('MONTH("Date")')
191
            ->query()
192
            ->setSelect([
193
                'Year' => 'YEAR("Date")',
194
                'Month' => 'MONTH("Date")',
195
            ])
196
            ->addWhere('"Date" IS NOT NULL')
197
            ->setOrderBy([
198
                'YEAR("Date")' => 'DESC',
199
                'MONTH("Date")' => 'DESC',
200
            ])
201
            ->execute();
202
203
        $years = [];
204
        foreach ($dates as $date) {
205
            $monthNumber = $date['Month'];
206
            $year = $date['Year'];
207
            $dateObj = new DateTime(implode('-', [$year, $monthNumber, 1]));
208
            $monthName = $dateObj->Format('M');
209
210
            // Set up the relevant year array, if not yet available.
211
            if (!isset($years[$year])) {
212
                $years[$year] = ['YearName'=>$year, 'Months' => []];
213
            }
214
215
            // Check if the currently processed month is the one that is selected via GET params.
216
            $active = false;
217
            if (isset($year) && isset($monthNumber)) {
218
                $active = (((int)$currentYear)==$year && ((int)$currentMonthNumber)==$monthNumber);
219
            }
220
221
            // Build the link - keep the tag and date filter, but reset the pagination.
222
            if ($active) {
223
                // Allow clicking to deselect the month.
224
                $link = HTTP::setGetVar('month', null, $link, '&');
225
                $link = HTTP::setGetVar('year', null, $link, '&');
226
            } else {
227
                $link = HTTP::setGetVar('month', $monthNumber, $link, '&');
228
                $link = HTTP::setGetVar('year', $year, $link, '&');
229
            }
230
            $link = HTTP::setGetVar('start', null, $link, '&');
231
232
            $years[$year]['Months'][$monthNumber] = array(
233
                'MonthName'=>$monthName,
234
                'MonthNumber'=>$monthNumber,
235
                'MonthLink'=>$link,
236
                'Active'=>$active
237
            );
238
        }
239
240
        // ArrayList will not recursively walk through the supplied array, so manually build nested ArrayLists.
241
        foreach ($years as &$year) {
242
            $year['Months'] = new ArrayList($year['Months']);
243
        }
244
245
        // Reverse the list so the most recent years appear first.
246
        return new ArrayList($years);
247
    }
248
249
    public function getDefaultRSSLink()
250
    {
251
        return $this->Link('rss');
252
    }
253
254
    public function getDefaultAtomLink()
255
    {
256
        return $this->Link('atom');
257
    }
258
259
    public function getSubscriptionTitle()
260
    {
261
        return $this->Title;
262
    }
263
}
264