EMTypograph   A
last analyzed

Complexity

Total Complexity 26

Size/Duplication

Total Lines 248
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 1

Importance

Changes 0
Metric Value
wmc 26
lcom 2
cbo 1
dl 0
loc 248
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
B get_options_list() 0 25 7
B get_option_info() 0 30 7
B do_setup() 0 26 9
A fast_apply() 0 12 2
A process() 0 5 1
1
<?php
2
/**
3
* Evgeny Muravjev Typograph, http://mdash.ru
4
* Version: 3.0 Gold Master
5
* Release Date: September 28, 2013
6
* Authors: Evgeny Muravjev & Alexander Drutsa
7
*/
8
9
namespace EMT;
10
11
/**
12
 * Class EMTypograph
13
 * @package EMT
14
 */
15
class EMTypograph extends AbstractTypograph
16
{
17
    public $trets = array(
18
        '\EMT\Tret\Quote',
19
        '\EMT\Tret\Dash',
20
        '\EMT\Tret\Symbol',
21
        '\EMT\Tret\Punctmark',
22
        '\EMT\Tret\Number',
23
        '\EMT\Tret\Space',
24
        '\EMT\Tret\Abbr',
25
        '\EMT\Tret\Nobr',
26
        '\EMT\Tret\Date',
27
        '\EMT\Tret\OptAlign',
28
        '\EMT\Tret\Etc',
29
        '\EMT\Tret\Text'
30
    );
31
32
    protected $group_list  = array(
33
        'Quote'     => true,
34
        'Dash'      => true,
35
        'Nobr'      => true,
36
        'Symbol'    => true,
37
        'Punctmark' => true,
38
        'Number'    => true,
39
        'Date'      => true,
40
        'Space'     => true,
41
        'Abbr'      => true,
42
        'OptAlign'  => true,
43
        'Text'      => true,
44
        'Etc'       => true,
45
    );
46
    protected $all_options = array(
47
48
        'Quote.quotes' => array( 'description' => 'Расстановка «кавычек-елочек» первого уровня', 'selector' => "Quote.*quote" ),
49
        'Quote.quotation' => array( 'description' => 'Внутренние кавычки-лапки', 'selector' => "Quote", 'setting' => 'no_bdquotes', 'reversed' => true ),
50
51
        'Dash.to_libo_nibud' => 'direct',
52
        'Dash.iz_za_pod' => 'direct',
53
        'Dash.ka_de_kas' => 'direct',
54
55
        'Nobr.super_nbsp' => 'direct',
56
        'Nobr.nbsp_in_the_end' => 'direct',
57
        'Nobr.phone_builder' => 'direct',
58
        'Nobr.ip_address' => 'direct',
59
        'Nobr.spaces_nobr_in_surname_abbr' => 'direct',
60
        'Nobr.nbsp_celcius' => 'direct',
61
        'Nobr.hyphen_nowrap_in_small_words' => 'direct',
62
        'Nobr.hyphen_nowrap' => 'direct',
63
        'Nobr.nowrap' => array('description' => 'Nobr (по умолчанию) & nowrap', 'disabled' => true, 'selector' => '*', 'setting' => 'nowrap' ),
64
65
        'Symbol.tm_replace'     => 'direct',
66
        'Symbol.r_sign_replace' => 'direct',
67
        'Symbol.copy_replace' => 'direct',
68
        'Symbol.apostrophe' => 'direct',
69
        'Symbol.degree_f' => 'direct',
70
        'Symbol.arrows_symbols' => 'direct',
71
        'Symbol.no_inches' => array( 'description' => 'Расстановка дюйма после числа', 'selector' => "Quote", 'setting' => 'no_inches', 'reversed' => true ),
72
73
        'Punctmark.auto_comma' => 'direct',
74
        'Punctmark.hellip' => 'direct',
75
        'Punctmark.fix_pmarks' => 'direct',
76
        'Punctmark.fix_excl_quest_marks' => 'direct',
77
        'Punctmark.dot_on_end' => 'direct',
78
79
        'Number.minus_between_nums' => 'direct',
80
        'Number.minus_in_numbers_range' => 'direct',
81
        'Number.auto_times_x' => 'direct',
82
        'Number.simple_fraction' => 'direct',
83
        'Number.math_chars' => 'direct',
84
        //'Number.split_number_to_triads' => 'direct',
85
        'Number.thinsp_between_number_triads' => 'direct',
86
        'Number.thinsp_between_no_and_number' => 'direct',
87
        'Number.thinsp_between_sect_and_number' => 'direct',
88
89
        'Date.years' => 'direct',
90
        'Date.mdash_month_interval' => 'direct',
91
        'Date.nbsp_and_dash_month_interval' => 'direct',
92
        'Date.nobr_year_in_date' => 'direct',
93
94
        'Space.many_spaces_to_one' => 'direct',
95
        'Space.clear_percent' => 'direct',
96
        'Space.clear_before_after_punct' => array( 'description' => 'Удаление пробелов перед и после знаков препинания в предложении', 'selector' => 'Space.remove_space_before_punctuationmarks'),
97
        'Space.autospace_after' => array( 'description' => 'Расстановка пробелов после знаков препинания', 'selector' => 'Space.autospace_after_*'),
98
        'Space.bracket_fix' => array( 'description' => 'Удаление пробелов внутри скобок, а также расстановка пробела перед скобками',
99
                'selector' => array('Space.nbsp_before_open_quote', 'Punctmark.fix_brackets')),
100
101
        'Abbr.nbsp_money_abbr' => 'direct',
102
        'Abbr.nobr_vtch_itd_itp' => 'direct',
103
        'Abbr.nobr_sm_im' => 'direct',
104
        'Abbr.nobr_acronym' => 'direct',
105
        'Abbr.nobr_locations' => 'direct',
106
        'Abbr.nobr_abbreviation' => 'direct',
107
        'Abbr.ps_pps' => 'direct',
108
        'Abbr.nbsp_org_abbr' => 'direct',
109
        'Abbr.nobr_gost' => 'direct',
110
        'Abbr.nobr_before_unit_volt' => 'direct',
111
        'Abbr.nbsp_before_unit' => 'direct',
112
113
        'OptAlign.all' => array( 'description' => 'Inline стили или CSS', 'hide' => true, 'selector' => 'OptAlign.*'),
114
        'OptAlign.oa_oquote' => 'direct',
115
        'OptAlign.oa_obracket_coma' => 'direct',
116
        'OptAlign.oa_oquote_extra' => 'direct',
117
        'OptAlign.layout' => array( 'description' => 'Inline стили или CSS' ),
118
119
        'Text.paragraphs' => 'direct',
120
        'Text.auto_links' => 'direct',
121
        'Text.email' => 'direct',
122
        'Text.breakline' => 'direct',
123
        'Text.no_repeat_words' => 'direct',
124
125
        //'Etc.no_nbsp_in_nobr' => 'direct',
126
        'Etc.unicode_convert' => array('description' => 'Преобразовывать html-сущности в юникод', 'selector' => '*', 'setting' => 'dounicode' , 'disabled' => true),
127
128
    );
129
130
    /**
131
     * Получить список имеющихся опций
132
     *
133
     * @return array
134
     *               all    - полный список
135
     *               group  - сгруппрованный по группам
136
     */
137
    public function get_options_list()
138
    {
139
        $arr['all'] = array();
0 ignored issues
show
Coding Style Comprehensibility introduced by
$arr was never initialized. Although not strictly required by PHP, it is generally a good practice to add $arr = 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...
140
        $bygroup = array();
141
        foreach ($this->all_options as $opt => $op) {
142
            $arr['all'][$opt] = $this->get_option_info($opt);
143
            $x = explode(".",$opt);
144
            $bygroup[$x[0]][] = $opt;
145
        }
146
        $arr['group'] = array();
147
        foreach ($this->group_list as $group => $ginfo) {
148
            if ($ginfo === true) {
149
                $tret = $this->get_tret($group);
150
                if($tret) $info['title'] = $tret->title; else $info['title'] = "Не определено";
0 ignored issues
show
Coding Style Comprehensibility introduced by
$info was never initialized. Although not strictly required by PHP, it is generally a good practice to add $info = 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...
151
            } else {
152
                $info = $ginfo;
153
            }
154
            $info['name'] = $group;
0 ignored issues
show
Bug introduced by
The variable $info does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
155
            $info['options'] = array();
156
            if(is_array($bygroup[$group])) foreach($bygroup[$group] as $opt) $info['options'][] = $opt;
157
            $arr['group'][] = $info;
158
        }
159
160
        return $arr;
161
    }
162
163
    /**
164
     * Получить информацию о настройке
165
     *
166
     * @param  string      $key
167
     * @return array|false
168
     */
169
    protected function get_option_info($key)
170
    {
171
        if (!isset($this->all_options[$key])) {
172
            return false;
173
        }
174
175
        if (is_array($this->all_options[$key])) {
176
            return $this->all_options[$key];
177
        }
178
179
        if (($this->all_options[$key] == "direct") || ($this->all_options[$key] == "reverse")) {
180
            $pa = explode(".", $key);
181
            $tret_pattern = $pa[0];
182
            $tret = $this->get_tret($tret_pattern);
183
184
            if (!$tret) {
185
                return false;
186
            }
187
188
            if (!isset($tret->rules[$pa[1]])) {
189
                return false;
190
            }
191
            $array = $tret->rules[$pa[1]];
192
            $array['way'] = $this->all_options[$key];
193
194
            return $array;
195
        }
196
197
        return false;
198
    }
199
200
    /**
201
     * Установка одной метанастройки
202
     *
203
     * @param string $name
204
     * @param mixed  $value
205
     */
206
    public function do_setup($name, $value)
207
    {
208
        if (!isset($this->all_options[$name])) {
209
            return;
210
        }
211
212
        // эта настрока связана с правилом ядра
213
        if (is_string($this->all_options[$name])) {
214
            $this->set($name, "active", $value );
215
216
            return ;
217
        }
218
        if (is_array($this->all_options[$name])) {
219
            if (isset($this->all_options[$name]['selector'])) {
220
                $settingname = "active";
221
                if(isset($this->all_options[$name]['setting'])) $settingname = $this->all_options[$name]['setting'];
222
                $this->set($this->all_options[$name]['selector'], $settingname, $value);
223
            }
224
        }
225
226
        if ($name == "OptAlign.layout") {
227
            if($value == "style") $this->set_tag_layout(Util::LAYOUT_STYLE);
228
            if($value == "class") $this->set_tag_layout(Util::LAYOUT_CLASS);
229
        }
230
231
    }
232
233
    /**
234
     * Запустить типограф со стандартными параметрами
235
     *
236
     * @param  string $text
237
     * @param  array  $options
238
     * @return string
239
     */
240
    public static function fast_apply($text, $options = null)
241
    {
242
        $obj = new self();
243
244
        if (is_array($options)) {
245
            $obj->setup($options);
246
        }
247
248
        $obj->set_text($text);
249
250
        return $obj->apply();
251
    }
252
253
    /**
254
     * @param string $text
255
     * @return string
256
     */
257
    public function process($text)
258
    {
259
        $this->set_text($text);
260
        return $this->apply();
261
    }
262
}
263