Passed
Push — v1 ( ac69b6...2a5986 )
by Andrew
08:08 queued 05:31
created

TypogrifyService::wordLimit()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 3
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Typogrify plugin for Craft CMS 3.x
4
 *
5
 * Typogrify prettifies your web typography by preventing ugly quotes and
6
 * 'widows' and more
7
 *
8
 * @link      https://nystudio107.com/
9
 * @copyright Copyright (c) 2017 nystudio107
10
 */
11
12
namespace nystudio107\typogrify\services;
13
14
use nystudio107\typogrify\Typogrify;
15
16
use Michelf\SmartyPants;
17
18
use Stringy\Stringy;
19
20
use Craft;
21
use craft\base\Component;
22
23
use yii\helpers\Inflector;
24
25
/**
26
 * @author    nystudio107
27
 * @package   Typogrify
28
 * @since     1.0.0
29
 */
30
class TypogrifyService extends Component
31
{
32
    // Public Methods
33
    // =========================================================================
34
35
    /**
36
     * @var \PHP_Typography\PHP_Typography
37
     */
38
    public $phpTypography;
39
40
    /**
41
     * @var \PHP_Typography\Settings
42
     */
43
    public $phpTypographySettings;
44
45
    // Public Methods
46
    // =========================================================================
47
48
    /**
49
     * @inheritdoc
50
     */
51
    public function init()
52
    {
53
        parent::init();
54
55
        // Create a new phpTypographySettings instance
56
        $this->phpTypographySettings = new \PHP_Typography\Settings();
57
58
        // Create a new PhpTypography instance
59
        $this->phpTypography = new \PHP_Typography\PHP_Typography();
60
61
        // Apply our default settings
62
        $settings = Typogrify::$plugin->getSettings();
63
        if ($settings !== false) {
0 ignored issues
show
introduced by
The condition $settings !== false is always true.
Loading history...
64
            $settingsArray = $settings->toArray();
65
            foreach ($settingsArray as $key => $value) {
66
                $this->phpTypographySettings->{$key}($value);
67
            }
68
        }
69
    }
70
71
    /**
72
     * Typogrify applies a veritable kitchen sink of typographic treatments to
73
     * beautify your web typography
74
     *
75
     * @param string $text    The text or HTML fragment to process
76
     * @param bool   $isTitle Optional. If the HTML fragment is a title.
77
     *                        Default false
78
     *
79
     * @return string The processed HTML
80
     */
81
    public function typogrify($text, $isTitle = false)
82
    {
83
        if (empty($text)) {
84
            return '';
85
        }
86
87
        $result = $this->phpTypography->process($text, $this->phpTypographySettings, $isTitle);
88
89
        return $result;
90
    }
91
92
    /**
93
     * Typogrify applies a veritable kitchen sink of typographic treatments to
94
     * beautify your web typography but in a way that is appropriate for RSS
95
     * (or similar) feeds -- i.e. excluding processes that may cause issues in
96
     * contexts with limited character set intelligence.
97
     *
98
     * @param string $text    The text or HTML fragment to process
99
     * @param bool   $isTitle Optional. If the HTML fragment is a title.
100
     *                        Default false
101
     *
102
     * @return string The processed HTML
103
     */
104
    public function typogrifyFeed($text, $isTitle = false)
105
    {
106
        if (empty($text)) {
107
            return '';
108
        }
109
110
        $result = $this->phpTypography->process_feed($text, $this->phpTypographySettings, $isTitle);
111
112
        return $result;
113
    }
114
115
    /**
116
     * @param string $text
117
     *
118
     * @return string
119
     */
120
    public function smartypants($text)
121
    {
122
        if (empty($text)) {
123
            return '';
124
        }
125
126
        return SmartyPants::defaultTransform($text);
127
    }
128
129
    /**
130
     * Truncates the string to a given length. If $substring is provided, and
131
     * truncating occurs, the string is further truncated so that the substring
132
     * may be appended without exceeding the desired length.
133
     *
134
     * @param  string $string    The string to truncate
135
     * @param  int    $length    Desired length of the truncated string
136
     * @param  string $substring The substring to append if it can fit
137
     *
138
     * @return string with the resulting $str after truncating
139
     */
140
    public function truncate($string, $length, $substring = '…'): string
141
    {
142
        $result = $string;
143
144
        if (!empty($string)) {
145
            $string = strip_tags($string);
146
            $result = (string)Stringy::create($string)->truncate($length, $substring);
147
        }
148
149
        return $result;
150
    }
151
152
    /**
153
     * Truncates the string to a given length, while ensuring that it does not
154
     * split words. If $substring is provided, and truncating occurs, the
155
     * string is further truncated so that the substring may be appended without
156
     * exceeding the desired length.
157
     *
158
     * @param  string $string    The string to truncate
159
     * @param  int    $length    Desired length of the truncated string
160
     * @param  string $substring The substring to append if it can fit
161
     *
162
     * @return string with the resulting $str after truncating
163
     */
164
    public function truncateOnWord($string, $length, $substring = '…'): string
165
    {
166
        $result = $string;
167
168
        if (!empty($string)) {
169
            $string = strip_tags($string);
170
            $result = (string)Stringy::create($string)->safeTruncate($length, $substring);
171
        }
172
173
        return $result;
174
    }
175
176
    /**
177
     * Creates a Stringy object and assigns both string and encoding properties
178
     * the supplied values. $string is cast to a string prior to assignment,
179
     * and if
180
     * $encoding is not specified, it defaults to mb_internal_encoding(). It
181
     * then returns the initialized object. Throws an InvalidArgumentException
182
     * if the first argument is an array or object without a __toString method.
183
     *
184
     * @param  string $string   The string initialize the Stringy object with
185
     * @param  string $encoding The character encoding
186
     *
187
     * @return Stringy
188
     */
189
    public function stringy($string = '', $encoding = null)
190
    {
191
        return Stringy::create($string, $encoding);
192
    }
193
194
    /**
195
     * Formats the value in bytes as a size in human readable form for example
196
     * `12 KB`.
197
     *
198
     * This is the short form of [[asSize]].
199
     *
200
     * If [[sizeFormatBase]] is 1024, [binary
201
     * prefixes](http://en.wikipedia.org/wiki/Binary_prefix)
202
     * (e.g. kibibyte/KiB, mebibyte/MiB, ...) are used in the formatting
203
     * result.
204
     *
205
     * @param string|int|float $bytes    value in bytes to be formatted.
206
     * @param int              $decimals the number of digits after the decimal
207
     *                                   point.
208
     *
209
     * @return string the formatted result.
210
     */
211
    public function humanFileSize($bytes, $decimals = 1): string
212
    {
213
        $oldSize = Craft::$app->formatter->sizeFormatBase;
214
        Craft::$app->formatter->sizeFormatBase = 1000;
215
        $result = Craft::$app->formatter->asShortSize($bytes, $decimals);
216
        Craft::$app->formatter->sizeFormatBase = $oldSize;
217
218
        return $result;
219
    }
220
221
    /**
222
     * Represents the value as duration in human readable format.
223
     *
224
     * @param \DateInterval|string|int $value the value to be formatted.
225
     *                                        Acceptable formats:
226
     *                                        - [DateInterval
227
     *                                        object](http://php.net/manual/ru/class.dateinterval.php)
228
     *                                        - integer - number of seconds.
229
     *                                        For example: value `131`
230
     *                                        represents `2 minutes, 11
231
     *                                        seconds`
232
     *                                        - ISO8601 duration format. For
233
     *                                        example, all of these values
234
     *                                        represent `1 day, 2 hours, 30
235
     *                                        minutes` duration:
236
     *                                        `2015-01-01T13:00:00Z/2015-01-02T13:30:00Z`
237
     *                                        - between two datetime values
238
     *                                        `2015-01-01T13:00:00Z/P1D2H30M` -
239
     *                                        time interval after datetime
240
     *                                        value
241
     *                                        `P1D2H30M/2015-01-02T13:30:00Z` -
242
     *                                        time interval before datetime
243
     *                                        value
244
     *                                        `P1D2H30M` - simply a date
245
     *                                        interval
246
     *                                        `P-1D2H30M` - a negative date
247
     *                                        interval (`-1 day, 2 hours, 30
248
     *                                        minutes`)
249
     *
250
     * @return string the formatted duration.
251
     */
252
    public function humanDuration($value)
253
    {
254
        return Craft::$app->formatter->asDuration($value);
255
    }
256
257
    /**
258
     * Formats the value as the time interval between a date and now in human
259
     * readable form.
260
     *
261
     * This method can be used in three different ways:
262
     *
263
     * 1. Using a timestamp that is relative to `now`.
264
     * 2. Using a timestamp that is relative to the `$referenceTime`.
265
     * 3. Using a `DateInterval` object.
266
     *
267
     * @param int|string|\DateTime|\DateInterval $value         the value to be
268
     *                                                          formatted. The
269
     *                                                          following types
270
     *                                                          of value are
271
     *                                                          supported:
272
     *
273
     * - an integer representing a UNIX timestamp
274
     * - a string that can be [parsed to create a DateTime
275
     * object](http://php.net/manual/en/datetime.formats.php). The timestamp is
276
     * assumed to be in [[defaultTimeZone]] unless a time zone is explicitly
277
     * given.
278
     * - a PHP [DateTime](http://php.net/manual/en/class.datetime.php) object
279
     * - a PHP DateInterval object (a positive time interval will refer to the
280
     * past, a negative one to the future)
281
     *
282
     * @param int|string|\DateTime               $referenceTime if specified
283
     *                                                          the value is
284
     *                                                          used as a
285
     *                                                          reference time
286
     *                                                          instead of
287
     *                                                          `now` when
288
     *                                                          `$value` is not
289
     *                                                          a
290
     *                                                          `DateInterval`
291
     *                                                          object.
292
     *
293
     * @return string the formatted result.
294
     */
295
    public function humanRelativeTime($value, $referenceTime = null)
296
    {
297
        return Craft::$app->formatter->asRelativeTime($value, $referenceTime);
298
    }
299
300
    /**
301
     * Converts number to its ordinal English form
302
     * For example, converts 13 to 13th, 2 to 2nd
303
     *
304
     * @param int $number
305
     *
306
     * @return string
307
     */
308
    public function ordinalize(int $number): string
309
    {
310
        return Inflector::ordinalize($number);
311
    }
312
313
    /**
314
     * Converts a word to its plural form
315
     * For example, 'apple' will become 'apples', and 'child' will become
316
     * 'children'
317
     *
318
     * @param string $word
319
     * @param int    $number
320
     *
321
     * @return string
322
     */
323
    public function pluralize(string $word, int $number = 2): string
324
    {
325
        return abs($number) === 1 ? $word : Inflector::pluralize($word);
326
    }
327
328
    /**
329
     * Converts a word to its singular form
330
     * For example, 'apples' will become 'apple', and 'children' will become
331
     * 'child'
332
     *
333
     * @param string $word
334
     * @param int    $number
335
     *
336
     * @return string
337
     */
338
    public function singularize(string $word, int $number = 1): string
339
    {
340
        return abs($number) === 1 ? Inflector::singularize($word) : $word;
341
    }
342
343
    /**
344
     * Returns transliterated version of a string
345
     * For example, 获取到 どちら Українська: ґ,є, Српска: ђ, њ, џ! ¿Español?
346
     * will be transliterated to huo qu dao dochira Ukrainsʹka: g,e, Srpska: d,
347
     * n, d! ¿Espanol?
348
     *
349
     * @param string $string
350
     * @param null   $transliterator
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $transliterator is correct as it would always require null to be passed?
Loading history...
351
     *
352
     * @return string
353
     */
354
    public function transliterate(string $string, $transliterator = null): string
355
    {
356
        return Inflector::transliterate($string, $transliterator);
357
    }
358
359
     /**
360
     * Limits a string by word count. If $substring is provided, and truncating occurs, the
361
     * string is further truncated so that the substring may be appended without
362
     * exceeding the desired length.
363
     *
364
     * @param string $string
365
     * @param int    $length
366
     * @param string $substring
367
     *
368
     * @return string
369
     */
370
    public function wordLimit(string $string, int $length, string $substring = '…'): string
371
    {
372
        $words = preg_split("/[\s]+/", strip_tags($string) );
373
        return implode(" ", array_slice($words, 0, $length) ) . $substring;
0 ignored issues
show
Bug introduced by
It seems like $words can also be of type false; however, parameter $array of array_slice() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

373
        return implode(" ", array_slice(/** @scrutinizer ignore-type */ $words, 0, $length) ) . $substring;
Loading history...
374
    }
375
}
376