]> git.immae.eu Git - github/wallabag/wallabag.git/blob - src/Wallabag/CoreBundle/Twig/WallabagExtension.php
Load custom.css only if exists
[github/wallabag/wallabag.git] / src / Wallabag / CoreBundle / Twig / WallabagExtension.php
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 ];
55 }
56
57 public function removeWww($url)
58 {
59 return preg_replace('/^www\./i', '', $url);
60 }
61
62 public function removeScheme($url)
63 {
64 return preg_replace('#^https?://#i', '', $url);
65 }
66
67 public function removeSchemeAndWww($url)
68 {
69 return $this->removeWww($this->removeScheme($url));
70 }
71
72 /**
73 * Return number of entries depending of the type (unread, archive, starred or all).
74 *
75 * @param string $type Type of entries to count
76 *
77 * @return int
78 */
79 public function countEntries($type)
80 {
81 $user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null;
82
83 if (null === $user || !\is_object($user)) {
84 return 0;
85 }
86
87 switch ($type) {
88 case 'starred':
89 $qb = $this->entryRepository->getBuilderForStarredByUser($user->getId());
90 break;
91 case 'archive':
92 $qb = $this->entryRepository->getBuilderForArchiveByUser($user->getId());
93 break;
94 case 'unread':
95 $qb = $this->entryRepository->getBuilderForUnreadByUser($user->getId());
96 break;
97 case 'all':
98 $qb = $this->entryRepository->getBuilderForAllByUser($user->getId());
99 break;
100 default:
101 throw new \InvalidArgumentException(sprintf('Type "%s" is not implemented.', $type));
102 }
103
104 // THANKS to PostgreSQL we CAN'T make a DEAD SIMPLE count(e.id)
105 // ERROR: column "e0_.id" must appear in the GROUP BY clause or be used in an aggregate function
106 $query = $qb
107 ->select('e.id')
108 ->groupBy('e.id')
109 ->getQuery();
110
111 $query->useQueryCache(true);
112 $query->useResultCache(true);
113 $query->setResultCacheLifetime($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->useResultCache(true);
154 $query->setResultCacheLifetime($this->lifeTime);
155
156 $nbArchives = \count($query->getArrayResult());
157
158 $interval = $user->getCreatedAt()->diff(new \DateTime('now'));
159 $nbDays = (int) $interval->format('%a') ?: 1;
160
161 // force setlocale for date translation
162 setlocale(LC_TIME, strtolower($user->getConfig()->getLanguage()) . '_' . strtoupper(strtolower($user->getConfig()->getLanguage())));
163
164 return $this->translator->trans('footer.stats', [
165 '%user_creation%' => strftime('%e %B %Y', $user->getCreatedAt()->getTimestamp()),
166 '%nb_archives%' => $nbArchives,
167 '%per_day%' => round($nbArchives / $nbDays, 2),
168 ]);
169 }
170
171 public function assetFileExists($name)
172 {
173 return file_exists(realpath($this->rootDir . '/../web/' . $name));
174 }
175
176 public function getName()
177 {
178 return 'wallabag_extension';
179 }
180 }