Completed
Push — master ( 1de9b7...830752 )
by Kristof
38:46 queued 24:09
created

src/Kunstmaan/SeoBundle/Twig/SeoTwigExtension.php (1 issue)

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
use Kunstmaan\NodeBundle\Entity\AbstractPage;
8
use Kunstmaan\SeoBundle\Entity\Seo;
9
use Twig_Extension;
10
11
/**
12
 * Twig extensions for Seo
13
 */
14
class SeoTwigExtension extends Twig_Extension
15
{
16
    /**
17
     * @var EntityManager
18
     */
19
    protected $em;
20
21
    /**
22
     * Website title defined in your parameters
23
     *
24
     * @var string
25
     */
26
    private $websiteTitle;
27
28
    /**
29
     * Saves querying the db multiple times, if you happen to use any of the defined
30
     * functions more than once in your templates
31
     *
32
     * @var array
33
     */
34
    private $seoCache = [];
35
36
    /**
37
     * @param EntityManager $em
38
     */
39
    public function __construct(EntityManager $em)
40
    {
41
        $this->em = $em;
42
    }
43
44
    /**
45
     * Returns a list of functions to add to the existing list.
46
     *
47
     * @return array An array of functions
48
     */
49
    public function getFunctions()
50
    {
51
        return array(
52
            new \Twig_SimpleFunction('render_seo_metadata_for', array($this, 'renderSeoMetadataFor'), array('is_safe' => array('html'), 'needs_environment' => true)),
53
            new \Twig_SimpleFunction('get_seo_for', array($this, 'getSeoFor')),
54
            new \Twig_SimpleFunction('get_title_for', array($this, 'getTitleFor')),
55
            new \Twig_SimpleFunction('get_title_for_page_or_default', array($this, 'getTitleForPageOrDefault')),
56
            new \Twig_SimpleFunction('get_absolute_url', array($this, 'getAbsoluteUrl')),
57
            new \Twig_SimpleFunction('get_image_dimensions', array($this, 'getImageDimensions')),
58
        );
59
    }
60
61
    /**
62
     * Validates the $url value as URL (according to » http://www.faqs.org/rfcs/rfc2396), optionally with required components.
63
     * It will just return the url if it's valid. If it starts with '/', the $host will be prepended.
64
     *
65
     * @param string $url
66
     * @param string $host
67
     *
68
     * @return string
69
     */
70
    public function getAbsoluteUrl($url, $host = null)
71
    {
72
        $validUrl = filter_var($url, FILTER_VALIDATE_URL);
73
        $host = rtrim($host, '/');
74
75
        if (!$validUrl === false) {
76
            // The url is valid
77
            return $url;
78
        } else {
79
            // Prepend with $host if $url starts with "/"
80
            if ($url[0] == '/') {
81
                return $url = $host.$url;
82
            }
83
84
            return false;
85
        }
86
    }
87
88
    /**
89
     * @param AbstractPage $entity
90
     *
91
     * @return Seo
92
     */
93
    public function getSeoFor(AbstractPage $entity)
94
    {
95
        $key = md5(get_class($entity).$entity->getId());
96
97
        if (!array_key_exists($key, $this->seoCache)) {
98
            $seo = $this->em->getRepository('KunstmaanSeoBundle:Seo')->findOrCreateFor($entity);
99
            $this->seoCache[$key] = $seo;
100
        }
101
102
        return $this->seoCache[$key];
103
    }
104
105
    /**
106
     * The first value that is not null or empty will be returned.
107
     *
108
     * @param AbstractPage $entity the entity for which you want the page title
109
     *
110
     * @return string The page title. Will look in the SEO meta first, then the NodeTranslation, then the page.
111
     */
112
    public function getTitleFor(AbstractPage $entity)
113
    {
114
        $arr = array();
115
116
        $arr[] = $this->getSeoTitle($entity);
117
118
        $arr[] = $entity->getTitle();
119
120
        return $this->getPreferredValue($arr);
121
    }
122
123
    /**
124
     * @param AbstractPage $entity
125
     * @param null|string  $default if given we'll return this text if no SEO title was found
126
     *
127
     * @return string
128
     */
129
    public function getTitleForPageOrDefault(AbstractPage $entity = null, $default = null)
130
    {
131
        if (is_null($entity)) {
132
            return $default;
133
        }
134
135
        $arr = array();
136
137
        $arr[] = $this->getSeoTitle($entity);
138
139
        $arr[] = $default;
140
141
        $arr[] = $entity->getTitle();
142
143
        return $this->getPreferredValue($arr);
144
    }
145
146
    /**
147
     * @param \Twig_Environment $environment
148
     * @param AbstractEntity    $entity      The entity
149
     * @param mixed             $currentNode The current node
150
     * @param string            $template    The template
151
     *
152
     * @return string
153
     */
154
    public function renderSeoMetadataFor(\Twig_Environment $environment, AbstractEntity $entity, $currentNode = null, $template = 'KunstmaanSeoBundle:SeoTwigExtension:metadata.html.twig')
155
    {
156
        $seo = $this->getSeoFor($entity);
157
        $template = $environment->loadTemplate($template);
158
159
        return $template->render(
160
            array(
161
                'seo' => $seo,
162
                'entity' => $entity,
163
                'currentNode' => $currentNode,
164
            )
165
        );
166
    }
167
168
    /**
169
     * @param array $values
170
     *
171
     * @return string
172
     */
173
    protected function getPreferredValue(array $values)
174
    {
175
        foreach ($values as $v) {
176
            if (!is_null($v) && !empty($v)) {
177
                return $v;
178
            }
179
        }
180
181
        return '';
182
    }
183
184
    /**
185
     * @param AbstractPage $entity
186
     *
187
     * @return null|string
188
     */
189
    private function getSeoTitle(AbstractPage $entity = null)
190
    {
191
        if (is_null($entity)) {
192
            return null;
193
        }
194
195
        $seo = $this->getSeoFor($entity);
196
        if (!is_null($seo)) {
197
            $title = $seo->getMetaTitle();
198
            if (!empty($title)) {
199
                return str_replace('%websitetitle%', $this->getWebsiteTitle(), $title);
200
            }
201
        }
202
203
        return null;
204
    }
205
206
    /**
207
     * Gets the Website title defined in your parameters.
208
     *
209
     * @return string
210
     */
211
    public function getWebsiteTitle()
212
    {
213
        return $this->websiteTitle;
214
    }
215
216
    /**
217
     * Sets the Website title defined in your parameters.
218
     *
219
     * @param string $websiteTitle the website title
220
     *
221
     * @return self
222
     */
223
    public function setWebsiteTitle($websiteTitle)
224
    {
225
        $this->websiteTitle = $websiteTitle;
226
227
        return $this;
228
    }
229
230
    /**
231
     * @param $src
232
     *
233
     * @return array|null
0 ignored issues
show
Consider making the return type a bit more specific; maybe use null|array.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
234
     */
235
    public function getImageDimensions($src)
236
    {
237
        try {
238
            list($width, $height) = getimagesize($src);
239
        } catch (\Exception $e) {
240
            return null;
241
        }
242
243
        return array('width' => $width, 'height' => $height);
244
    }
245
}
246