Test Failed
Pull Request — master (#2)
by
unknown
12:11
created

NewsManagerAwareTrait   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 285
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 0
Metric Value
wmc 30
lcom 1
cbo 3
dl 0
loc 285
rs 10
c 0
b 0
f 0

19 Methods

Rating   Name   Duplication   Size   Complexity  
A newsList() 0 7 2
A newsArchiveList() 0 7 2
A currentNews() 0 16 3
A featNews() 0 12 4
A nextNews() 0 10 2
A prevNews() 0 10 2
A numNews() 0 4 1
A numNewsPages() 0 4 1
A newsHasPager() 0 4 1
A newsCategoryList() 0 7 2
A newsCategory() 0 6 1
A getNewsDateFormat() 0 6 1
A newsFormatShort() 0 11 2
A newsFormatNav() 0 10 1
B newsFormatFull() 0 25 1
A newsFormatCategory() 0 7 1
A newsManager() 0 12 2
A setNewsManager() 0 6 1
dateHelper() 0 1 ?
1
<?php
2
3
namespace Charcoal\Cms\Support\Traits;
4
5
// local dependencies
6
use Charcoal\Cms\NewsInterface;
7
use Charcoal\Cms\Service\Manager\NewsManager;
8
9
// dependencies from `charcoal-base`
10
use Charcoal\Object\CategoryInterface;
11
12
// dependencies from pimple
13
use Slim\Exception\ContainerException;
14
15
trait NewsManagerAwareTrait
16
{
17
    /**
18
     * Currently displayed news.
19
     * @var array $news City/Object/News
20
     */
21
    private $currentNews;
22
23
    /**
24
     * @var NewsManager $newsManager
25
     */
26
    private $newsManager;
27
28
    // ==========================================================================
29
    // FUNCTIONS
30
    // ==========================================================================
31
32
    /**
33
     * Formatted news list
34
     * Returns the entries for the current page.
35
     * @return \Generator|void
36
     */
37
    public function newsList()
38
    {
39
        $entries = $this->newsManager()->entries();
40
        foreach ($entries as $news) {
41
            yield $this->newsFormatShort($news);
42
        }
43
    }
44
45
    /**
46
     * Formatted news archive list
47
     * Returns the entries for the current page.
48
     * @return \Generator|void
49
     */
50
    public function newsArchiveList()
51
    {
52
        $entries = $this->newsManager()->archive();
53
        foreach ($entries as $entry) {
54
            yield $this->newsFormatShort($entry);
55
        }
56
    }
57
58
    /**
59
     * Current news.
60
     * @return array The properties of the current news
61
     */
62
    public function currentNews()
63
    {
64
        if ($this->currentNews) {
65
            return $this->currentNews;
66
        }
67
68
        // The the current news
69
        $news = $this->newsManager()->entry();
70
71
        // Format the news if there's any
72
        if ($news) {
73
            $this->currentNews = $this->newsFormatFull($news);
74
        }
75
76
        return $this->currentNews;
77
    }
78
79
    /**
80
     * @return \Generator
81
     */
82
    public function featNews()
83
    {
84
        $entries = $this->newsManager()->featList();
85
86
        if (count($entries) > 0) {
87
            foreach ($entries as $entry) {
0 ignored issues
show
Bug introduced by
The expression $entries of type null|array|object is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
88
                if ($entry->id()) {
89
                    yield $this->newsFormatFull($entry);
90
                }
91
            }
92
        }
93
    }
94
95
    /**
96
     * Next news in list.
97
     * @return array The next news properties.
98
     */
99
    public function nextNews()
100
    {
101
        $next = $this->newsManager()->next();
102
103
        if (!$next) {
104
            return null;
105
        }
106
107
        return $this->newsFormatNav($next);
108
    }
109
110
    /**
111
     * Next news in list.
112
     * @return array The next news properties.
113
     */
114
    public function prevNews()
115
    {
116
        $prev = $this->newsManager()->prev();
117
118
        if (!$prev) {
119
            return null;
120
        }
121
122
        return $this->newsFormatNav($prev);
123
    }
124
125
    /**
126
     * Amount of news (total)
127
     * @return integer How many news?
128
     */
129
    public function numNews()
130
    {
131
        return $this->newsManager()->numNews();
132
    }
133
134
    /**
135
     * @return float
136
     */
137
    public function numNewsPages()
138
    {
139
        return $this->newsManager()->numPages();
140
    }
141
142
    /**
143
     * @return boolean
144
     */
145
    public function newsHasPager()
146
    {
147
        return $this->newsManager()->hasPager();
148
    }
149
150
    /**
151
     * @return \Generator
152
     */
153
    public function newsCategoryList()
154
    {
155
        $cats = $this->newsManager()->categoryItems();
156
        foreach ($cats as $cat) {
157
            yield $this->newsFormatCategory($cat);
158
        }
159
    }
160
161
    /**
162
     * @param NewsInterface $news Charcoal\Cms\NewsInterface.
163
     * @return CategoryInterface
164
     */
165
    public function newsCategory(NewsInterface $news)
166
    {
167
        $id = $news->category();
168
169
        return $this->newsManager()->categoryItem($id);
170
    }
171
172
    // ==========================================================================
173
    // FORMATTER
174
    // ==========================================================================
175
176
    /**
177
     * @param NewsInterface $news Charcoal\Cms\NewsInterface.
178
     * @return string
179
     */
180
    protected function getNewsDateFormat(NewsInterface $news)
181
    {
182
        return $this->dateHelper()->formatDate(
183
            $news->newsDate()
184
        );
185
    }
186
187
    /**
188
     * Formatting expected in templates
189
     * @param NewsInterface $news A single news.
190
     * @return array The needed news properties.
191
     */
192
    protected function newsFormatShort(NewsInterface $news)
193
    {
194
        return [
195
            'title'        => (string)$news->title(),
196
            'url'          => (string)$news->url(),
197
            'date'         => $this->getNewsDateFormat($news),
198
            'active'       => ($this->currentNews() && ($this->currentNews()['id'] == $news->id())),
199
            'category'     => $news->category(),
200
            'categoryName' => $this->newsCategory($news)->name()
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Charcoal\Object\CategoryInterface as the method name() does only exist in the following implementations of said interface: Charcoal\Attachment\Object\Category\Generic, Charcoal\Cms\NewsCategory, Charcoal\Cms\Tag.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
201
        ];
202
    }
203
204
    /**
205
     * Formatting expected in templates
206
     * @param NewsInterface $news A single news.
207
     * @return array The needed news properties.
208
     */
209
    protected function newsFormatNav(NewsInterface $news)
210
    {
211
        return [
212
            'date'         => $this->getNewsDateFormat($news),
213
            'title'        => (string)$news->title(),
214
            'url'          => $news->url(),
215
            'category'     => $news->category(),
216
            'categoryName' => $this->newsCategory($news)->name()
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Charcoal\Object\CategoryInterface as the method name() does only exist in the following implementations of said interface: Charcoal\Attachment\Object\Category\Generic, Charcoal\Cms\NewsCategory, Charcoal\Cms\Tag.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
217
        ];
218
    }
219
220
    /**
221
     * @param NewsInterface $news The current news.
222
     * @return array The needed properties.
223
     */
224
    protected function newsFormatFull(NewsInterface $news)
225
    {
226
        $contentBlocks = $news->attachments('content');
0 ignored issues
show
Bug introduced by
The method attachments() does not seem to exist on object<Charcoal\Cms\NewsInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
227
        $gallery = $news->attachments('image-gallery');
0 ignored issues
show
Bug introduced by
The method attachments() does not seem to exist on object<Charcoal\Cms\NewsInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
228
        $documents = $news->attachments('document');
0 ignored issues
show
Bug introduced by
The method attachments() does not seem to exist on object<Charcoal\Cms\NewsInterface>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
229
230
        return [
231
            'id'               => $news->id(),
232
            'title'            => (string)$news->title(),
233
            'summary'          => (string)$news->summary(),
234
            'content'          => (string)$news->content(),
235
            'image'            => $news->image(),
236
            'date'             => $this->getNewsDateFormat($news),
237
            'contentBlocks'    => $contentBlocks,
238
            'hasContentBlocks' => !!(count($contentBlocks)),
239
            'documents'        => $documents,
240
            'hasDocuments'     => !!(count($documents)),
241
            'gallery'          => $gallery,
242
            'hasGallery'       => !!(count($gallery)),
243
            'url'              => $news->url(),
244
            'metaTitle'        => (string)$news->metaTitle(),
245
            'category'         => $news->category(),
246
            'categoryName'     => $this->newsCategory($news)->name()
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Charcoal\Object\CategoryInterface as the method name() does only exist in the following implementations of said interface: Charcoal\Attachment\Object\Category\Generic, Charcoal\Cms\NewsCategory, Charcoal\Cms\Tag.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
247
        ];
248
    }
249
250
    /**
251
     * @param CategoryInterface $category The category item.
252
     * @return array The formatted category item.
253
     */
254
    protected function newsFormatCategory(CategoryInterface $category)
255
    {
256
        return [
257
            'id'   => $category->id(),
258
            'name' => (string)$category->name(),
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Charcoal\Object\CategoryInterface as the method name() does only exist in the following implementations of said interface: Charcoal\Attachment\Object\Category\Generic, Charcoal\Cms\NewsCategory, Charcoal\Cms\Tag.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
259
        ];
260
    }
261
262
    // ==========================================================================
263
    // DEPENDENCIES
264
    // ==========================================================================
265
266
    /**
267
     * @return NewsManager
268
     * @throws ContainerException When dependency is missing.
269
     */
270
    protected function newsManager()
271
    {
272
        if (!$this->newsManager instanceof NewsManager) {
273
            throw new ContainerException(sprintf(
274
                'Missing dependency for %s: %s',
275
                get_called_class(),
276
                NewsManager::class
277
            ));
278
        }
279
280
        return $this->newsManager;
281
    }
282
283
    /**
284
     * @param NewsManager $newsManager The news Manager class.
285
     * @return self
286
     */
287
    protected function setNewsManager(NewsManager $newsManager)
288
    {
289
        $this->newsManager = $newsManager;
290
291
        return $this;
292
    }
293
294
    /**
295
     * dateHelperAwareTrait dependency
296
     * @return mixed
297
     */
298
    abstract protected function dateHelper();
299
}
300