Completed
Push — 5.0 ( a48099...63af02 )
by
unknown
11:33
created

TranslatorBundle/Service/Translator/Translator.php (1 issue)

Labels
Severity

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\TranslatorBundle\Service\Translator;
4
5
use Doctrine\Common\Collections\ArrayCollection;
6
use Kunstmaan\TranslatorBundle\Entity\Translation;
7
use Symfony\Bundle\FrameworkBundle\Translation\Translator as SymfonyTranslator;
8
9
/**
10
 * Translator
11
 */
12
class Translator extends SymfonyTranslator
13
{
14
15
    private $translationRepository;
16
17
    /**
18
     * Resource Cacher
19
     * @var Kunstmaan\TranslatorBundle\Service\Translator\ResourceCacher
20
     */
21
    private $resourceCacher;
22
23
    /**
24
     * @var \Symfony\Component\HttpFoundation\Request
25
     */
26
    protected $request;
27
28
    /**
29
     * Add resources from the database
30
     * So the translator knows where to look (first) for specific translations
31
     * This function will also look if these resources are loaded from the stash or from the cache
32
     */
33
    public function addDatabaseResources()
34
    {
35
        if ($this->addResourcesFromCacher() === false) {
36
            $this->addResourcesFromDatabaseAndCacheThem();
37
        }
38
    }
39
    
40
    /**
41
     * {@inheritdoc}
42
     */
43
    public function warmUp($cacheDir)
44
    {
45
        return;
46
    }
47
48
    /**
49
     * Add resources to the Translator from the cache
50
     */
51
    public function addResourcesFromCacher()
52
    {
53
        $resources = $this->resourceCacher->getCachedResources(false);
54
55
        if ($resources !== false) {
56
            $this->addResources($resources);
57
58
            return true;
59
        }
60
61
        return false;
62
    }
63
64
    /**
65
     * Add resources from the stash and cache them
66
     *
67
     * @param boolean $cacheResources cache resources after retrieving them from the stasher
68
     */
69
    public function addResourcesFromDatabaseAndCacheThem($cacheResources = true)
70
    {
71
        try {
72
            $resources = $this->translationRepository->getAllDomainsByLocale();
73
            $this->addResources($resources);
74
75
            if ($cacheResources === true) {
76
                $this->resourceCacher->cacheResources($resources);
77
            }
78
        } catch (\Exception $ex){
79
            // don't load if the database doesn't work
80
        }
81
    }
82
83
    /**
84
     * Add resources to the Translator
85
     * Resources is an array[0] => array('name' => 'messages', 'locale' => 'en')
86
     * Where name is the domain of the domain
87
     *
88
     * @param array $resources
89
     */
90
    public function addResources($resources)
91
    {
92
        foreach ($resources as $resource) {
93
            $this->addResource('database', 'DB', $resource['locale'], $resource['name']);
94
        }
95
    }
96
97
    /**
98
     * {@inheritdoc}
99
     */
100
    protected function loadCatalogue($locale)
101
    {
102
103
        if ($this->options['debug'] === true) {
104
            $this->options['cache_dir'] = null; // disable caching for debug
105
        }
106
107
        return parent::loadCatalogue($locale);
108
    }
109
110
    public function trans($id, array $parameters = array(), $domain = 'messages', $locale = null)
111
    {
112
        if (!$this->request = $this->container->get('request_stack')->getCurrentRequest()) {
113
            return parent::trans($id, $parameters, $domain, $locale);
114
        }
115
116
        $showTranslationsSource = $this->request->get('transSource');
117
        if ($showTranslationsSource !== null) {
118
            $trans = sprintf('%s (%s)', $id, $domain);
119
        } else {
120
            $trans = parent::trans($id, $parameters, $domain, $locale);
121
        }
122
123
        $this->profileTranslation($id, $parameters, $domain, $locale, $trans);
124
125
        return $trans;
126
    }
127
128
    public function profileTranslation($id, $parameters, $domain, $locale, $trans)
129
    {
130
131
        if (!$this->request || $this->container->getParameter('kuma_translator.profiler') === false) {
0 ignored issues
show
It seems like you code against a concrete implementation and not the interface Psr\Container\ContainerInterface as the method getParameter() does only exist in the following implementations of said interface: Container14\ProjectServiceContainer, ProjectServiceContainer, Symfony\Component\Depend...urationContainerBuilder, Symfony\Component\DependencyInjection\Container, Symfony\Component\Depend...ection\ContainerBuilder, Symfony\Component\Depend...\NoConstructorContainer, Symfony\Component\Depend...tainers\CustomContainer, Symfony\Component\Depend...ProjectServiceContainer, Symfony\Component\Depend...ProjectServiceContainer, Symfony_DI_PhpDumper_Test_Almost_Circular_Private, Symfony_DI_PhpDumper_Test_Almost_Circular_Public, Symfony_DI_PhpDumper_Test_Base64Parameters, Symfony_DI_PhpDumper_Test_EnvParameters, Symfony_DI_PhpDumper_Test_Legacy_Privates, Symfony_DI_PhpDumper_Test_Rot13Parameters, Symfony_DI_PhpDumper_Test_Uninitialized_Reference.

Let’s take a look at an example:

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

class MyUser implements 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 implementation 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 interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
132
            return;
133
        }
134
135
        if ($locale === null) {
136
            $locale = $this->request->get('_locale');
137
        }
138
139
        $translation = new Translation;
140
        $translation->setKeyword($id);
141
        $translation->setDomain($domain);
142
        $translation->setLocale($locale);
143
        $translation->setText($trans);
144
145
        $translationCollection = $this->request->request->get('usedTranslations');
146
147
        if (!$translationCollection instanceof \Doctrine\Common\Collections\ArrayCollection) {
148
            $translationCollection = new ArrayCollection;
149
        }
150
151
        $translationCollection->set($domain . $id . $locale, $translation);
152
153
        $this->request->request->set('usedTranslations', $translationCollection);
154
155
    }
156
157
    public function getTranslationRepository()
158
    {
159
        return $this->translationRepository;
160
    }
161
162
    public function setTranslationRepository($translationRepository)
163
    {
164
        $this->translationRepository = $translationRepository;
165
    }
166
167
    public function setResourceCacher($resourceCacher)
168
    {
169
        $this->resourceCacher = $resourceCacher;
170
    }
171
172
173
}
174