Completed
Push — master ( 9cb1ed...7bb711 )
by Lachezar
02:12
created

App::getOptions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
1
<?php
0 ignored issues
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 14 and the first side effect is on line 6.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
3
namespace demo\browser;
4
5
//import composer autoload file
6
require_once dirname(__DIR__) . implode(DIRECTORY_SEPARATOR, ['.', '..', 'vendor', 'autoload.php']);
7
8
use PassGenerator\Generator;
9
10
/**
11
 * @author Lachezar Mihaylov <[email protected]>
12
 * @license https://github.com/lmihaylov2512/pass-generator/blob/master/LICENSE.md MIT License
13
 */
14
class App
15
{
16
    /**
17
     * @var integer whether the app is in debug mode
18
     */
19
    const DEBUG_MODE = 0;
20
    
21
    /**
22
     * @var array options with title and description
23
     */
24
    protected static $options = [
25
        'upperCase' => [
26
            'title' => 'upper case',
27
            'desc' => 'use alphabet upper letters [A-Z]',
28
        ],
29
        'lowerCase' => [
30
            'title' => 'lower case',
31
            'desc' => 'use alphabet lower letters [a-z]',
32
        ],
33
        'digits' => [
34
            'title' => 'digits',
35
            'desc' => 'all numbers [0-9]',
36
        ],
37
        'special' => [
38
            'title' => 'special',
39
            'desc' => 'special symbols ~, !, @, #, ...'
40
        ],
41
        'brackets' => [
42
            'title' => 'brackets',
43
            'desc' => 'all kind of brackets (, ), {, }, [, ]',
44
        ],
45
        'minus' => [
46
            'title' => 'minus',
47
            'desc' => 'minus sign -',
48
        ],
49
        'underline' => [
50
            'title' => 'underline',
51
            'desc' => 'underline sign _',
52
        ],
53
        'space' => [
54
            'title' => 'space',
55
            'desc' => 'space character \' \'',
56
        ],
57
    ];
58
    /**
59
     * @var Generator password generator instance
60
     */
61
    protected static $generator;
62
    
63
    /**
64
     * Check whether the current request is ajax.
65
     * 
66
     * @return boolean the result from checking
67
     */
68
    public static function isAjaxRequest()
0 ignored issues
show
Coding Style introduced by
isAjaxRequest uses the super-global variable $_SERVER 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...
69
    {
70
        return !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';
71
    }
72
    
73
    /**
74
     * Return post variable, if exists, or specific default value.
75
     * 
76
     * @param mixed $default default value, if post doesn't exist
77
     * @return mixed
78
     */
79
    public static function getPost($default = null)
0 ignored issues
show
Coding Style introduced by
getPost uses the super-global variable $_POST 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...
80
    {
81
        return isset($_POST) ? $_POST : $default;
82
    }
83
    
84
    /**
85
     * Get all options array.
86
     * 
87
     * @return array options array
88
     */
89
    public static function getOptions()
90
    {
91
        return static::$options;
92
    }
93
    
94
    /**
95
     * Create password generator, if necessary and return it.
96
     * 
97
     * @return Generator password generator instance
98
     */
99
    public static function getGenerator()
100
    {
101
        if (static::$generator === null) {
102
            static::$generator = new Generator();
103
        }
104
        return static::$generator;
105
    }
106
    
107
    /**
108
     * If is ajax request and post exists, generate password and cancel script execution.
109
     * 
110
     * @return void
111
     */
112
    public static function run()
113
    {
114
        if (static::isAjaxRequest() && ($data = static::getPost()) !== null) {
115
            foreach ($data as $option => $value) {
116
                static::getGenerator()->$option = $value;
117
            }
118
            
119
            die(static::getGenerator()->generate());
0 ignored issues
show
Coding Style Compatibility introduced by
The method run() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
120
        }
121
    }
122
}
123
124
//run the app
125
App::run();
126
127
?>
128
<!DOCTYPE html>
129
<html>
130
<head>
131
    <meta charset="utf-8" />
132
    <meta name="viewport" content="width=device-width, initial-scale=1" />
133
    <title>Demo password generator</title>
134
    <link href="./assets/bootstrap/css/<?= App::DEBUG_MODE ? 'bootstrap.css' : 'bootstrap.min.css' ?>" rel="stylesheet" />
135
    <style>.margin-top-20{margin-top:20px}.loader{border:4px solid #eee;border-top:4px solid #337ab7;border-radius:50%;width:32px;height:32px;animation:spin 2s linear infinite;display:inline-block;vertical-align:middle}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}</style>
136
</head>
137
<body>
138
    <nav class="navbar navbar-default">
139
        <div class="container-fluid">
140
            <div class="navbar-header">
141
                <a href="https://packagist.org/packages/lmihaylov/pass-generator" class="navbar-brand" target="_blank">Pass-Generator</a>
142
            </div>
143
        </div>
144
    </nav>
145
    <div class="container">
146
        <div class="row">
147
            <div class="col-lg-8 col-lg-offset-2">
148
                <div class="panel panel-default">
149
                    <div class="panel-body">
150
                        <div class="row">
151
                            <div class="col-lg-12">
152
                                <div class="input-group">
153
                                    <span class="input-group-addon">Password length</span>
154
                                    <input type="text" class="form-control" placeholder="Password length" value="<?= App::getGenerator()->length ?>" id="input-length">
155
                                    <span class="input-group-btn">
156
                                        <button class="btn btn-primary" type="button" id="btn-generate">Generate</button>
157
                                    </span>
158
                                </div>
159
                                <div id="password-output" class="well lead hide margin-top-20"></div>
160
                                <div class="list-group margin-top-20">
161
                                    <?php foreach (App::getOptions() as $group => $option): ?>
162
                                    <a href="#" class="list-group-item<?= App::getGenerator()->$group ? ' active' : '' ?>" data-option="<?= $group ?>">
163
                                        <h4 class="list-group-item-heading"><span class="glyphicon glyphicon-<?= App::getGenerator()->$group ? 'ok' : 'remove' ?>" aria-hidden="true"></span> <?= $option['title'] ?></h4>
164
                                        <p class="list-group-item-text"><?= $option['desc'] ?></p>
165
                                    </a>
166
                                    <?php endforeach; ?>
167
                                </div>
168
                            </div>
169
                        </div>
170
                    </div>
171
                </div>
172
            </div>
173
        </div>
174
    </div>
175
    <script src="./assets/jquery/<?= App::DEBUG_MODE ? 'jquery.js' : 'jquery.min.js' ?>"></script>
176
    <script>
177
        (function (w, d, $) {
178
            //attach click event handler on list elements
179
            $('.list-group > a').on('click', function (e) {
180
                e.preventDefault();
181
                var isActive = $(this).hasClass('active');
182
                
183
                if (isActive) {
184
                    $(this).toggleClass('active').find('span.glyphicon').removeClass('glyphicon-ok').addClass('glyphicon-remove');
185
                } else {
186
                    $(this).toggleClass('active').find('span.glyphicon').removeClass('glyphicon-remove').addClass('glyphicon-ok');
187
                }
188
            });
189
190
            //attach event handler on generate button for generating a new password string
191
            $('#btn-generate').on('click', function (e) {
192
                var data = { length: $('#input-length').val() };
193
194
                //prepare request data
195
                $('#password-output').html('<span class="loader"></span> Generating...').removeClass('hide');
196
                $('.list-group-item').each(function () {
197
                    data[$(this).data('option')] = $(this).hasClass('active') ? '1' : '';
198
                });
199
                
200
                $.ajax({
201
                    type: 'POST',
202
                    data: data,
203
                    success: function (res) {
204
                        $('#password-output').html(res === '' ? 'Please choose the at least one or more symbols types' : res);
205
                    }
206
                });
207
            });
208
        })(window, document, jQuery);
209
    </script>
210
</body>
211
</html>
212