PageSeoHelper::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
1
<?php
2
3
namespace Victoire\Bundle\SeoBundle\Helper;
4
5
use Symfony\Component\PropertyAccess\PropertyAccessor;
6
use Victoire\Bundle\BusinessEntityBundle\Converter\ParameterConverter;
7
use Victoire\Bundle\BusinessEntityBundle\Helper\BusinessEntityHelper;
8
use Victoire\Bundle\BusinessPageBundle\Entity\BusinessPage;
9
use Victoire\Bundle\BusinessPageBundle\Entity\VirtualBusinessPage;
10
use Victoire\Bundle\PageBundle\Entity\BasePage;
11
use Victoire\Bundle\PageBundle\Entity\Page;
12
13
/**
14
 * The seo helper brings some seo functions for pages
15
 * ref: victoire_seo.helper.pageseo_helper.
16
 */
17
class PageSeoHelper
18
{
19
    protected $businessEntityHelper = null;
20
    protected $parameterConverter = null;
21
22
    protected $pageSeoAttributes = [
23
        'metaTitle',
24
        'metaDescription',
25
        'relAuthor',
26
        'relPublisher',
27
        'ogTitle',
28
        'ogType',
29
        'ogImage',
30
        'ogUrl',
31
        'ogDescription',
32
        'fbAdmins',
33
        'twitterCard',
34
        'twitterUrl',
35
        'twitterTitle',
36
        'twitterDescription',
37
        'twitterImage',
38
        'schemaPageType',
39
        'schemaName',
40
        'schemaDescription',
41
        'schemaImage',
42
        'metaRobotsIndex',
43
        'metaRobotsFollow',
44
        'metaRobotsAdvanced',
45
        'relCanonical',
46
        'keyword', ];
47
48
    /**
49
     * Constructor.
50
     *
51
     * @param BusinessEntityHelper $businessEntityHelper
52
     * @param ParameterConverter   $parameterConverter
53
     */
54
    public function __construct(BusinessEntityHelper $businessEntityHelper, ParameterConverter $parameterConverter)
55
    {
56
        $this->businessEntityHelper = $businessEntityHelper;
57
        $this->parameterConverter = $parameterConverter;
58
    }
59
60
    /**
61
     * Generate a seo for the page using the current entity.
62
     *
63
     * @param Page   $page
64
     * @param Entity $entity
65
     */
66
    public function updateSeoByEntity(BasePage $page, $entity)
67
    {
68
        //if no entity is provided
69
        if ($entity === null) {
70
            //we look for the entity of the page
71
            if ($page->getBusinessEntity() !== null) {
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Victoire\Bundle\PageBundle\Entity\BasePage as the method getBusinessEntity() does only exist in the following sub-classes of Victoire\Bundle\PageBundle\Entity\BasePage: Victoire\Bundle\Business...dle\Entity\BusinessPage, Victoire\Bundle\Business...ity\VirtualBusinessPage. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
72
                $entity = $page->getBusinessEntity();
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Victoire\Bundle\PageBundle\Entity\BasePage as the method getBusinessEntity() does only exist in the following sub-classes of Victoire\Bundle\PageBundle\Entity\BasePage: Victoire\Bundle\Business...dle\Entity\BusinessPage, Victoire\Bundle\Business...ity\VirtualBusinessPage. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
73
            }
74
        }
75
76
        //only if we have an entity instance
77
        if ($entity !== null) {
78
            //the page seo
79
            $pageSeo = $page->getSeo();
80
81
            //the page seo might not exist yet
82
            if ($pageSeo !== null) {
83
                $businessEntity = $this->businessEntityHelper->findByEntityInstance($entity);
84
85
                if ($businessEntity !== null) {
86
                    $businessProperties = $businessEntity->getBusinessPropertiesByType('seoable');
87
88
                    //parse the business properties
89
                    foreach ($businessProperties as $businessProperty) {
90
                        //parse of seo attributes
91
                        foreach ($this->pageSeoAttributes as $seoAttribute) {
92
                            $accessor = new PropertyAccessor();
93
                            $value = $accessor->getValue($pageSeo, $seoAttribute);
94
                            // we only update value if its a string and (if its a VBP or its a BP where value is not defined)
95
                            if (is_string($value) && ($page instanceof VirtualBusinessPage || ($page instanceof BusinessPage && $value == null))) {
96
                                $value = $this->parameterConverter->convertFromEntity(
97
                                    $value,
98
                                    $businessProperty,
99
                                    $entity
100
                                );
101
                            }
102
                            $this->setEntityAttributeValue($pageSeo, $seoAttribute, $value);
103
                        }
104
                    }
105
                }
106
            }
107
        }
108
    }
109
110
    /**
111
     * Update the value of the entity.
112
     *
113
     * @param \Victoire\Bundle\SeoBundle\Entity\PageSeo $entity
114
     * @param string                                    $field
115
     * @param string                                    $value
116
     *
117
     * @return mixed
118
     */
119
    protected function setEntityAttributeValue($entity, $field, $value)
120
    {
121
        $functionName = 'set'.ucfirst($field);
122
123
        call_user_func([$entity, $functionName], $value);
124
    }
125
}
126