Completed
Push — master ( bb78ee...c605bd )
by Daniel
03:22
created

CommonLibLocale::setVisibleOnHoverLanguages()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 18
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 18
rs 9.2
cc 4
eloc 13
nc 6
nop 1
1
<?php
2
3
/**
4
 *
5
 * The MIT License (MIT)
6
 *
7
 * Copyright (c) 2015 Daniel Popiniuc
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a copy
10
 * of this software and associated documentation files (the "Software"), to deal
11
 * in the Software without restriction, including without limitation the rights
12
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
 * copies of the Software, and to permit persons to whom the Software is
14
 * furnished to do so, subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included in all
17
 * copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25
 * SOFTWARE.
26
 *
27
 */
28
29
namespace danielgp\common_lib;
30
31
/**
32
 * Usefull functions to support multi-language feedback
33
 *
34
 * @author Daniel Popiniuc
35
 */
36
trait CommonLibLocale
37
{
38
39
    protected $commonLibFlags = null;
40
    protected $tCmnLb         = null;
41
42
    private function getCommonLocaleFolder()
43
    {
44
        $pathes     = explode(DIRECTORY_SEPARATOR, __DIR__);
45
        $pathDepth  = count($pathes);
46
        $localePath = [];
47
        foreach ($pathes as $key => $value) {
48
            if ($key < ($pathDepth - 1)) {
49
                $localePath[] = $value;
50
            }
51
        }
52
        return implode(DIRECTORY_SEPARATOR, $localePath);
53
    }
54
55
    /**
56
     * Stores given language or default one into global session variable
57
     *
58
     * @return NOTHING
59
     */
60
    private function handleLanguageIntoSession()
0 ignored issues
show
Coding Style introduced by
handleLanguageIntoSession uses the super-global variable $_GET which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
handleLanguageIntoSession uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
61
    {
62
        $this->settingsCommonLib();
63
        if (isset($_GET['lang'])) {
64
            $_SESSION['lang'] = filter_var($_GET['lang'], FILTER_SANITIZE_STRING);
65
        } elseif (!isset($_SESSION['lang'])) {
66
            $_SESSION['lang'] = $this->commonLibFlags['default_language'];
67
        }
68
        /* to avoid potential language injections from other applications that do not applies here */
69
        if (!in_array($_SESSION['lang'], array_keys($this->commonLibFlags['available_languages']))) {
70
            $_SESSION['lang'] = $this->commonLibFlags['default_language'];
71
        }
72
    }
73
74
    /**
75
     * Takes care of instatiation of localization libraries
76
     * used within current module for multi-languages support
77
     *
78
     * @return NOTHING
79
     */
80
    private function handleLocalizationCommon()
0 ignored issues
show
Coding Style introduced by
handleLocalizationCommon uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
81
    {
82
        $this->handleLanguageIntoSession();
83
        $localizationFile = $this->getCommonLocaleFolder() . '/locale/'
84
                . $_SESSION['lang'] . '/LC_MESSAGES/'
85
                . $this->commonLibFlags['localization_domain']
86
                . '.mo';
87
        $extrClass        = new \Gettext\Extractors\Mo();
88
        $translations     = $extrClass->fromFile($localizationFile);
89
        $this->tCmnLb     = new \Gettext\Translator();
90
        $this->tCmnLb->loadTranslations($translations);
91
    }
92
93
    /**
94
     * Central function to deal with multi-language messages
95
     *
96
     * @param string $localizedStringCode
97
     * @return string
98
     */
99
    protected function lclMsgCmn($localizedStringCode)
100
    {
101
        if (is_null($this->commonLibFlags)) {
102
            $this->settingsCommonLib();
103
            $this->handleLocalizationCommon();
104
        }
105
        return $this->tCmnLb->gettext($localizedStringCode);
106
    }
107
108
    protected function lclMsgCmnNumber($singularString, $pluralString, $numberToEvaluate)
109
    {
110
        if (is_null($this->commonLibFlags)) {
111
            $this->settingsCommonLib();
112
            $this->handleLocalizationCommon();
113
        }
114
        return $this->tCmnLb->ngettext($singularString, $pluralString, $numberToEvaluate);
115
    }
116
117
    protected function setNumberFormat($content, $features = null)
118
    {
119
        $features = $this->setNumberFormatFeatures($features);
120
        $fmt      = new \NumberFormatter($features['locale'], $features['style']);
121
        $fmt->setAttribute(\NumberFormatter::MIN_FRACTION_DIGITS, $features['MinFractionDigits']);
122
        $fmt->setAttribute(\NumberFormatter::MAX_FRACTION_DIGITS, $features['MaxFractionDigits']);
123
        return $fmt->format($content);
124
    }
125
126
    private function setNumberFormatFeatures($features)
0 ignored issues
show
Coding Style introduced by
setNumberFormatFeatures uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
127
    {
128
        if (is_null($features)) {
129
            $features = [
130
                'locale'            => $_SESSION['lang'],
131
                'style'             => \NumberFormatter::DECIMAL,
132
                'MinFractionDigits' => 0,
133
                'MaxFractionDigits' => 0,
134
            ];
135
        }
136
        if (!isset($features['locale'])) {
137
            $features['locale'] = $_SESSION['lang'];
138
        }
139
        if (!isset($features['style'])) {
140
            $features['style'] = \NumberFormatter::DECIMAL;
141
        }
142
        return $features;
143
    }
144
145
    /**
146
     * Create an upper right box with choices for languages
147
     * (requires flag-icon.min.css to be loaded)
148
     * (makes usage of custom class "upperRightBox" and id = "visibleOnHover", provided here as scss file)
149
     *
150
     * @param array $aAvailableLanguages
151
     * @return string
152
     */
153
    protected function setUpperRightBoxLanguages($aAvailableLanguages)
0 ignored issues
show
Coding Style introduced by
setUpperRightBoxLanguages uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
154
    {
155
        $this->handleLanguageIntoSession();
156
        return '<div class="upperRightBox">'
157
                . '<div style="text-align:right;">'
158
                . '<span class="flag-icon flag-icon-' . strtolower(substr($_SESSION['lang'], -2))
159
                . '" style="margin-right:2px;">&nbsp;</span>'
160
                . $aAvailableLanguages[$_SESSION['lang']]
161
                . '</div><!-- default Language -->'
162
                . $this->setVisibleOnHoverLanguages($aAvailableLanguages)
163
                . '</div><!-- upperRightBox end -->';
164
    }
165
166
    private function setVisibleOnHoverLanguages($aAvailableLanguages)
0 ignored issues
show
Coding Style introduced by
setVisibleOnHoverLanguages uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
setVisibleOnHoverLanguages uses the super-global variable $_SESSION which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
167
    {
168
        $linkWithoutLanguage = '';
169
        if (isset($_REQUEST)) {
170
            $linkWithoutLanguage = $this->setArrayToStringForUrl('&amp;', $_REQUEST, ['lang']) . '&amp;';
0 ignored issues
show
Bug introduced by
It seems like setArrayToStringForUrl() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
171
        }
172
        $sReturn[] = '<div id="visibleOnHover">';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$sReturn was never initialized. Although not strictly required by PHP, it is generally a good practice to add $sReturn = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
173
        foreach ($aAvailableLanguages as $key => $value) {
174
            if ($_SESSION['lang'] !== $key) {
175
                $sReturn[] = '<a href="?' . $linkWithoutLanguage . 'lang=' . $key . '" style="display:block;">'
176
                        . '<span class="flag-icon flag-icon-' . strtolower(substr($key, -2))
177
                        . '" style="margin-right:2px;">&nbsp;</span>'
178
                        . $value . '</a>';
179
            }
180
        }
181
        $sReturn[] = '</div><!-- visibleOnHover end -->';
182
        return implode('', $sReturn);
183
    }
184
185
    /**
186
     * Settings
187
     *
188
     * @return NOTHING
189
     */
190
    private function settingsCommonLib()
191
    {
192
        $this->commonLibFlags = [
193
            'available_languages' => [
194
                'en_US' => 'US English',
195
                'ro_RO' => 'Română',
196
                'it_IT' => 'Italiano',
197
            ],
198
            'default_language'    => 'en_US',
199
            'localization_domain' => 'common-locale'
200
        ];
201
    }
202
}
203