Passed
Push — master ( fc74b2...1443bb )
by Jeremy
05:28 queued 10s
created

WallabagExtension::themeClass()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 1
nc 4
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Wallabag\CoreBundle\Twig;
4
5
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
6
use Symfony\Component\Translation\TranslatorInterface;
7
use Twig\Extension\AbstractExtension;
8
use Twig\Extension\GlobalsInterface;
9
use Twig\TwigFilter;
10
use Twig\TwigFunction;
11
use Wallabag\CoreBundle\Repository\EntryRepository;
12
use Wallabag\CoreBundle\Repository\TagRepository;
13
14
class WallabagExtension extends AbstractExtension implements GlobalsInterface
15
{
16
    private $tokenStorage;
17
    private $entryRepository;
18
    private $tagRepository;
19
    private $lifeTime;
20
    private $translator;
21
    private $rootDir;
22
23
    public function __construct(EntryRepository $entryRepository, TagRepository $tagRepository, TokenStorageInterface $tokenStorage, $lifeTime, TranslatorInterface $translator, string $rootDir)
24
    {
25
        $this->entryRepository = $entryRepository;
26
        $this->tagRepository = $tagRepository;
27
        $this->tokenStorage = $tokenStorage;
28
        $this->lifeTime = $lifeTime;
29
        $this->translator = $translator;
30
        $this->rootDir = $rootDir;
31
    }
32
33
    public function getGlobals()
34
    {
35
        return [];
36
    }
37
38
    public function getFilters()
39
    {
40
        return [
41
            new TwigFilter('removeWww', [$this, 'removeWww']),
42
            new TwigFilter('removeScheme', [$this, 'removeScheme']),
43
            new TwigFilter('removeSchemeAndWww', [$this, 'removeSchemeAndWww']),
44
        ];
45
    }
46
47
    public function getFunctions()
48
    {
49
        return [
50
            new TwigFunction('count_entries', [$this, 'countEntries']),
51
            new TwigFunction('count_tags', [$this, 'countTags']),
52
            new TwigFunction('display_stats', [$this, 'displayStats']),
53
            new TwigFunction('asset_file_exists', [$this, 'assetFileExists']),
54
            new TwigFunction('theme_class', [$this, 'themeClass']),
55
        ];
56
    }
57
58
    public function removeWww($url)
59
    {
60
        return preg_replace('/^www\./i', '', $url);
61
    }
62
63
    public function removeScheme($url)
64
    {
65
        return preg_replace('#^https?://#i', '', $url);
66
    }
67
68
    public function removeSchemeAndWww($url)
69
    {
70
        return $this->removeWww($this->removeScheme($url));
71
    }
72
73
    /**
74
     * Return number of entries depending of the type (unread, archive, starred or all).
75
     *
76
     * @param string $type Type of entries to count
77
     *
78
     * @return int
79
     */
80
    public function countEntries($type)
81
    {
82
        $user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null;
83
84
        if (null === $user || !\is_object($user)) {
85
            return 0;
86
        }
87
88
        switch ($type) {
89
            case 'starred':
90
                $qb = $this->entryRepository->getBuilderForStarredByUser($user->getId());
0 ignored issues
show
Bug introduced by
The method getId() does not exist on Stringable. ( Ignorable by Annotation )

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

90
                $qb = $this->entryRepository->getBuilderForStarredByUser($user->/** @scrutinizer ignore-call */ getId());

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...
Bug introduced by
The method getId() does not exist on Symfony\Component\Security\Core\User\UserInterface. It seems like you code against a sub-type of Symfony\Component\Security\Core\User\UserInterface such as FOS\OAuthServerBundle\Te...\TestBundle\Entity\User or FOS\UserBundle\Model\UserInterface. ( Ignorable by Annotation )

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

90
                $qb = $this->entryRepository->getBuilderForStarredByUser($user->/** @scrutinizer ignore-call */ getId());
Loading history...
91
                break;
92
            case 'archive':
93
                $qb = $this->entryRepository->getBuilderForArchiveByUser($user->getId());
94
                break;
95
            case 'unread':
96
                $qb = $this->entryRepository->getBuilderForUnreadByUser($user->getId());
97
                break;
98
            case 'all':
99
                $qb = $this->entryRepository->getBuilderForAllByUser($user->getId());
100
                break;
101
            default:
102
                throw new \InvalidArgumentException(sprintf('Type "%s" is not implemented.', $type));
103
        }
104
105
        // THANKS to PostgreSQL we CAN'T make a DEAD SIMPLE count(e.id)
106
        // ERROR: column "e0_.id" must appear in the GROUP BY clause or be used in an aggregate function
107
        $query = $qb
108
            ->select('e.id')
109
            ->groupBy('e.id')
110
            ->getQuery();
111
112
        $query->useQueryCache(true);
113
        $query->enableResultCache($this->lifeTime);
114
115
        return \count($query->getArrayResult());
116
    }
117
118
    /**
119
     * Return number of tags.
120
     *
121
     * @return int
122
     */
123
    public function countTags()
124
    {
125
        $user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null;
126
127
        if (null === $user || !\is_object($user)) {
128
            return 0;
129
        }
130
131
        return $this->tagRepository->countAllTags($user->getId());
132
    }
133
134
    /**
135
     * Display a single line about reading stats.
136
     *
137
     * @return string
138
     */
139
    public function displayStats()
140
    {
141
        $user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null;
142
143
        if (null === $user || !\is_object($user)) {
144
            return 0;
145
        }
146
147
        $query = $this->entryRepository->getBuilderForArchiveByUser($user->getId())
148
            ->select('e.id')
149
            ->groupBy('e.id')
150
            ->getQuery();
151
152
        $query->useQueryCache(true);
153
        $query->enableResultCache($this->lifeTime);
154
155
        $nbArchives = \count($query->getArrayResult());
156
157
        $interval = $user->getCreatedAt()->diff(new \DateTime('now'));
0 ignored issues
show
Bug introduced by
The method getCreatedAt() does not exist on Stringable. ( Ignorable by Annotation )

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

157
        $interval = $user->/** @scrutinizer ignore-call */ getCreatedAt()->diff(new \DateTime('now'));

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...
Bug introduced by
The method getCreatedAt() does not exist on Symfony\Component\Security\Core\User\UserInterface. It seems like you code against a sub-type of Symfony\Component\Security\Core\User\UserInterface such as Wallabag\UserBundle\Entity\User. ( Ignorable by Annotation )

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

157
        $interval = $user->/** @scrutinizer ignore-call */ getCreatedAt()->diff(new \DateTime('now'));
Loading history...
158
        $nbDays = (int) $interval->format('%a') ?: 1;
159
160
        // force setlocale for date translation
161
        setlocale(LC_TIME, strtolower($user->getConfig()->getLanguage()) . '_' . strtoupper(strtolower($user->getConfig()->getLanguage())));
0 ignored issues
show
Bug introduced by
The method getConfig() does not exist on Symfony\Component\Security\Core\User\UserInterface. It seems like you code against a sub-type of Symfony\Component\Security\Core\User\UserInterface such as Wallabag\UserBundle\Entity\User. ( Ignorable by Annotation )

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

161
        setlocale(LC_TIME, strtolower($user->/** @scrutinizer ignore-call */ getConfig()->getLanguage()) . '_' . strtoupper(strtolower($user->getConfig()->getLanguage())));
Loading history...
Bug introduced by
The method getConfig() does not exist on Stringable. ( Ignorable by Annotation )

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

161
        setlocale(LC_TIME, strtolower($user->/** @scrutinizer ignore-call */ getConfig()->getLanguage()) . '_' . strtoupper(strtolower($user->getConfig()->getLanguage())));

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...
162
163
        return $this->translator->trans('footer.stats', [
164
            '%user_creation%' => strftime('%e %B %Y', $user->getCreatedAt()->getTimestamp()),
165
            '%nb_archives%' => $nbArchives,
166
            '%per_day%' => round($nbArchives / $nbDays, 2),
167
        ]);
168
    }
169
170
    public function assetFileExists($name)
171
    {
172
        return file_exists(realpath($this->rootDir . '/../web/' . $name));
173
    }
174
175
    public function themeClass()
176
    {
177
        return isset($_COOKIE['theme']) && 'dark' === $_COOKIE['theme'] ? 'dark-theme' : '';
178
    }
179
180
    public function getName()
181
    {
182
        return 'wallabag_extension';
183
    }
184
}
185