Completed
Push — master ( 91fdab...75a7b9 )
by
unknown
13:37
created

src/Kunstmaan/SeoBundle/Twig/SeoTwigExtension.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Kunstmaan\SeoBundle\Twig;
4
5
use Doctrine\ORM\EntityManager;
6
use Kunstmaan\AdminBundle\Entity\AbstractEntity;
7
8
use Kunstmaan\NodeBundle\Entity\AbstractPage;
9
10
use Kunstmaan\SeoBundle\Entity\Seo;
11
12
use Twig_Environment;
13
14
use Twig_Extension;
15
16
/**
17
 * Twig extensions for Seo
18
 */
19
class SeoTwigExtension extends Twig_Extension
20
{
21
22
    /**
23
     * @var EntityManager
24
     */
25
    protected $em;
26
27
    /**
28
     * Website title defined in your parameters
29
     * @var string
30
     */
31
    private $websiteTitle;
32
33
    /**
34
     * Saves querying the db multiple times, if you happen to use any of the defined
35
     * functions more than once in your templates
36
     * @var array
37
     */
38
    private $seoCache = [];
39
40
    /**
41
     * @param EntityManager $em
42
     */
43
    public function __construct(EntityManager $em)
44
    {
45
        $this->em = $em;
46
    }
47
48
    /**
49
     * Returns a list of functions to add to the existing list.
50
     *
51
     * @return array An array of functions
52
     */
53
    public function getFunctions()
54
    {
55
        return array(
56
            new \Twig_SimpleFunction('render_seo_metadata_for', array($this, 'renderSeoMetadataFor'), array('is_safe' => array('html'), 'needs_environment' => true)),
57
            new \Twig_SimpleFunction('get_seo_for', array($this, 'getSeoFor')),
58
            new \Twig_SimpleFunction('get_title_for', array($this, 'getTitleFor')),
59
            new \Twig_SimpleFunction('get_title_for_page_or_default', array($this, 'getTitleForPageOrDefault')),
60
            new \Twig_SimpleFunction('get_absolute_url', array($this, 'getAbsoluteUrl')),
61
            new \Twig_SimpleFunction('get_image_dimensions', array($this, 'getImageDimensions')),
62
        );
63
    }
64
65
    /**
66
     * Validates the $url value as URL (according to » http://www.faqs.org/rfcs/rfc2396), optionally with required components.
67
     * It will just return the url if it's valid. If it starts with '/', the $host will be prepended.
68
     *
69
     * @param string $url
70
     * @param string $host
0 ignored issues
show
Should the type for parameter $host not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
71
     * @return string
0 ignored issues
show
Should the return type not be string|false?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
72
     */
73
    public function getAbsoluteUrl($url, $host = null)
74
    {
75
        $validUrl = filter_var($url, FILTER_VALIDATE_URL);
76
        $host = rtrim($host, '/');
77
78
        if (!$validUrl === false) {
79
            // The url is valid
80
            return $url;
81
        } else {
82
            // Prepend with $host if $url starts with "/"
83
            if ($url[0] == '/') {
84
                return $url = $host.$url;
85
            }
86
87
            return false;
88
        }
89
    }
90
91
    /**
92
     * @param AbstractPage $entity
93
     *
94
     * @return Seo
95
     */
96
    public function getSeoFor(AbstractPage $entity)
97
    {
98
        $key = md5(get_class($entity).$entity->getId());
99
100
        if (!array_key_exists($key, $this->seoCache)) {
101
            $seo = $this->em->getRepository('KunstmaanSeoBundle:Seo')->findOrCreateFor($entity);
102
            $this->seoCache[$key] = $seo;
103
        }
104
105
        return $this->seoCache[$key];
106
    }
107
108
    /**
109
     * The first value that is not null or empty will be returned.
110
     *
111
     * @param AbstractPage $entity The entity for which you want the page title.
112
     *
113
     * @return string The page title. Will look in the SEO meta first, then the NodeTranslation, then the page.
114
     */
115
    public function getTitleFor(AbstractPage $entity)
116
    {
117
        $arr = array();
118
119
        $arr[] = $this->getSeoTitle($entity);
120
121
        $arr[] = $entity->getTitle();
122
123
        return $this->getPreferredValue($arr);
124
    }
125
126
    /**
127
     * @param AbstractPage $entity
128
     * @param null|string  $default If given we'll return this text if no SEO title was found.
129
     *
130
     * @return string
131
     */
132
    public function getTitleForPageOrDefault(AbstractPage $entity = null, $default = null)
133
    {
134
        if (is_null($entity)) {
135
            return $default;
136
        }
137
138
        $arr = array();
139
140
        $arr[] = $this->getSeoTitle($entity);
141
142
        $arr[] = $default;
143
144
        $arr[] = $entity->getTitle();
145
146
        return $this->getPreferredValue($arr);
147
    }
148
149
    /**
150
     * @param \Twig_Environment $environment
151
     * @param AbstractEntity    $entity      The entity
152
     * @param mixed             $currentNode The current node
153
     * @param string            $template    The template
154
     *
155
     * @return string
156
     */
157
    public function renderSeoMetadataFor(\Twig_Environment $environment, AbstractEntity $entity, $currentNode = null, $template = 'KunstmaanSeoBundle:SeoTwigExtension:metadata.html.twig')
158
    {
159
        $seo = $this->getSeoFor($entity);
160
        $template = $environment->loadTemplate($template);
161
162
        return $template->render(
163
            array(
164
                'seo' => $seo,
165
                'entity' => $entity,
166
                'currentNode' => $currentNode,
167
            )
168
        );
169
    }
170
171
    /**
172
     * @param array $values
173
     *
174
     * @return string
175
     */
176
    protected function getPreferredValue(array $values)
177
    {
178
        foreach ($values as $v) {
179
            if (!is_null($v) && !empty($v)) {
180
                return $v;
181
            }
182
        }
183
184
        return '';
185
    }
186
187
    /**
188
     * @param AbstractPage $entity
189
     *
190
     * @return null|string
191
     */
192
    private function getSeoTitle(AbstractPage $entity = null)
193
    {
194
        if (is_null($entity)) {
195
            return null;
196
        }
197
198
        $seo = $this->getSeoFor($entity);
199
        if (!is_null($seo)) {
200
            $title = $seo->getMetaTitle();
201
            if (!empty($title)) {
202
                return str_replace('%websitetitle%', $this->getWebsiteTitle(), $title);
203
            }
204
        }
205
206
207
        return null;
208
    }
209
210
211
    /**
212
     * Gets the Website title defined in your parameters.
213
     *
214
     * @return string
215
     */
216
    public function getWebsiteTitle()
217
    {
218
        return $this->websiteTitle;
219
    }
220
221
    /**
222
     * Sets the Website title defined in your parameters.
223
     *
224
     * @param string $websiteTitle the website title
225
     *
226
     * @return self
227
     */
228
    public function setWebsiteTitle($websiteTitle)
229
    {
230
        $this->websiteTitle = $websiteTitle;
231
232
        return $this;
233
    }
234
235
    /**
236
     * @param $src
237
     *
238
     * @return array|null
239
     */
240
    public function getImageDimensions($src)
241
    {
242
        try {
243
            list($width, $height) = getimagesize($src);
244
        } catch (\Exception $e) {
245
            return null;
246
        }
247
248
        return array('width' => $width, 'height' => $height);
249
    }
250
}
251