Passed
Pull Request — develop (#37)
by Andrew
05:00
created

Recipe::getServes()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Recipe plugin for Craft CMS 3.x
4
 *
5
 * A comprehensive recipe FieldType for Craft CMS that includes metric/imperial
6
 * conversion, portion calculation, and JSON-LD microdata support
7
 *
8
 * @link      https://nystudio107.com
0 ignored issues
show
Coding Style introduced by
The tag in position 1 should be the @copyright tag
Loading history...
9
 * @copyright Copyright (c) 2017 nystudio107
0 ignored issues
show
Coding Style introduced by
@copyright tag must contain a year and the name of the copyright holder
Loading history...
10
 */
0 ignored issues
show
Coding Style introduced by
PHP version not specified
Loading history...
Coding Style introduced by
Missing @category tag in file comment
Loading history...
Coding Style introduced by
Missing @package tag in file comment
Loading history...
Coding Style introduced by
Missing @author tag in file comment
Loading history...
Coding Style introduced by
Missing @license tag in file comment
Loading history...
11
12
namespace nystudio107\recipe\models;
13
14
use nystudio107\recipe\helpers\Json;
15
use nystudio107\recipe\helpers\PluginTemplate;
16
use nystudio107\seomatic\Seomatic;
0 ignored issues
show
Bug introduced by
The type nystudio107\seomatic\Seomatic was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
17
use nystudio107\seomatic\models\MetaJsonLd;
0 ignored issues
show
Bug introduced by
The type nystudio107\seomatic\models\MetaJsonLd was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
18
19
use Craft;
20
use craft\base\Model;
21
use craft\helpers\StringHelper;
22
use craft\helpers\Template;
23
use craft\validators\ArrayValidator;
24
25
use Twig\Markup;
26
27
/**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
28
 * @author    nystudio107
0 ignored issues
show
Coding Style introduced by
Tag value for @author tag indented incorrectly; expected 2 spaces but found 4
Loading history...
Coding Style introduced by
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
Coding Style introduced by
The tag in position 1 should be the @package tag
Loading history...
29
 * @package   Recipe
0 ignored issues
show
Coding Style introduced by
Tag value for @package tag indented incorrectly; expected 1 spaces but found 3
Loading history...
30
 * @since     1.0.0
0 ignored issues
show
Coding Style introduced by
The tag in position 3 should be the @author tag
Loading history...
Coding Style introduced by
Tag value for @since tag indented incorrectly; expected 3 spaces but found 5
Loading history...
31
 */
0 ignored issues
show
Coding Style introduced by
Missing @category tag in class comment
Loading history...
Coding Style introduced by
Missing @license tag in class comment
Loading history...
Coding Style introduced by
Missing @link tag in class comment
Loading history...
32
class Recipe extends Model
33
{
34
    // Constants
35
    // =========================================================================
36
37
    const SEOMATIC_PLUGIN_HANDLE = 'seomatic';
38
    const MAIN_ENTITY_KEY = 'mainEntityOfPage';
39
40
    const US_RDA = [
41
        'calories' => 2000,
42
        'carbohydrateContent' => 275,
43
        'cholesterolContent' => 300,
44
        'fatContent' => 78,
45
        'fiberContent' => 28,
46
        'proteinContent' => 50,
47
        'saturatedFatContent' => 20,
48
        'sodiumContent' => 2300,
49
        'sugarContent' => 50,
50
    ];
51
52
    // Mapping to convert any of the incorrect plural values
53
    const NORMALIZE_PLURALS = [
54
        'tsps' => 'tsp',
55
        'tbsps' => 'tbsp',
56
        'flozs' => 'floz',
57
        'cups' => 'cups',
58
        'ozs' => 'oz',
59
        'lbs' => 'lb',
60
        'mls' => 'ml',
61
        'ls' => 'l',
62
        'mgs' => 'mg',
63
        'gs' => 'g',
64
        'kg' => 'kg',
65
    ];
66
67
    // Public Properties
68
    // =========================================================================
69
70
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
71
     * @var string
72
     */
73
    public $name;
74
75
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
76
     * @var string
77
     */
78
    public $description;
79
80
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
81
     * @var string
82
     */
83
    public $recipeCategory;
84
85
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
86
     * @var string
87
     */
88
    public $recipeCuisine;
89
90
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
91
     * @var string
92
     */
93
    public $skill = 'intermediate';
94
95
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
96
     * @var int
97
     */
98
    public $serves = 1;
99
100
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
101
     * @var string
102
     */
103
    public $servesUnit = '';
104
105
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
106
     * @var array
107
     */
108
    public $ingredients = [];
109
110
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
111
     * @var array
112
     */
113
    public $directions = [];
114
115
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
116
     * @var array
117
     */
118
    public $equipment = [];
119
120
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
121
     * @var int
122
     */
123
    public $imageId = 0;
124
125
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
126
     * @var int
127
     */
128
    public $prepTime;
129
130
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
131
     * @var int
132
     */
133
    public $cookTime;
134
135
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
136
     * @var int
137
     */
138
    public $totalTime;
139
140
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
141
     * @var array
142
     */
143
    public $ratings = [];
144
145
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
146
     * @var string
147
     */
148
    public $servingSize;
149
150
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
151
     * @var int
152
     */
153
    public $calories;
154
155
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
156
     * @var int
157
     */
158
    public $carbohydrateContent;
159
160
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
161
     * @var int
162
     */
163
    public $cholesterolContent;
164
165
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
166
     * @var int
167
     */
168
    public $fatContent;
169
170
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
171
     * @var int
172
     */
173
    public $fiberContent;
174
175
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
176
     * @var int
177
     */
178
    public $proteinContent;
179
180
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
181
     * @var int
182
     */
183
    public $saturatedFatContent;
184
185
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
186
     * @var int
187
     */
188
    public $sodiumContent;
189
190
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
191
     * @var int
192
     */
193
    public $sugarContent;
194
195
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
196
     * @var int
197
     */
198
    public $transFatContent;
199
200
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
201
     * @var int
202
     */
203
    public $unsaturatedFatContent;
204
205
    // Public Methods
206
    // =========================================================================
207
208
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
209
     * @inheritdoc
210
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
211
    public function init()
212
    {
213
        parent::init();
214
        // Fix any of the incorrect plural values
215
        if (!empty($this->ingredients)) {
216
            foreach ($this->ingredients as &$row) {
217
                if (!empty($row['units']) && !empty(self::NORMALIZE_PLURALS[$row['units']])) {
218
                    $row['units'] = self::NORMALIZE_PLURALS[$row['units']];
219
                }
220
            }
221
            unset($row);
222
        }
223
    }
224
225
    /**
0 ignored issues
show
Coding Style introduced by
Missing short description in doc comment
Loading history...
226
     * @inheritdoc
227
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
228
    public function rules()
229
    {
230
        return [
231
            ['name', 'string'],
232
            ['name', 'default', 'value' => ''],
233
            ['description', 'string'],
234
            ['recipeCategory', 'string'],
235
            ['recipeCuisine', 'string'],
236
            ['skill', 'string'],
237
            ['serves', 'integer'],
238
            ['imageId', 'integer'],
239
            ['prepTime', 'integer'],
240
            ['cookTime', 'integer'],
241
            ['totalTime', 'integer'],
242
            ['servingSize', 'string'],
243
            ['calories', 'integer'],
244
            ['carbohydrateContent', 'integer'],
245
            ['cholesterolContent', 'integer'],
246
            ['fatContent', 'integer'],
247
            ['fiberContent', 'integer'],
248
            ['proteinContent', 'integer'],
249
            ['saturatedFatContent', 'integer'],
250
            ['sodiumContent', 'integer'],
251
            ['sugarContent', 'integer'],
252
            ['transFatContent', 'integer'],
253
            ['unsaturatedFatContent', 'integer'],
254
            [
255
                [
256
                    'ingredients',
257
                    'directions',
258
                    'equipment',
259
                ],
260
                ArrayValidator::class,
261
            ],
262
263
        ];
264
    }
265
266
    /**
267
     * Return the JSON-LD Structured Data for this recipe
268
     *
269
     * @return array
270
     */
271
    public function getRecipeJSONLD(): array
272
    {
273
        $recipeJSONLD = [
274
            'context' => 'http://schema.org',
275
            'type' => 'Recipe',
276
            'name' => $this->name,
277
            'image' => $this->getImageUrl(),
278
            'description' => $this->description,
279
            'recipeCategory' => $this->recipeCategory,
280
            'recipeCuisine' => $this->recipeCuisine,
281
            'recipeYield' => $this->getServes(),
282
            'recipeIngredient' => $this->getIngredients('imperial', 0, false),
283
            'recipeInstructions' => $this->getDirections(false),
284
            'tool' => $this->getEquipment(false),
285
        ];
286
        $recipeJSONLD = array_filter($recipeJSONLD);
287
288
        $nutrition = [
289
            'type' => 'NutritionInformation',
290
            'servingSize' => $this->servingSize,
291
            'calories' => $this->calories,
292
            'carbohydrateContent' => $this->carbohydrateContent,
293
            'cholesterolContent' => $this->cholesterolContent,
294
            'fatContent' => $this->fatContent,
295
            'fiberContent' => $this->fiberContent,
296
            'proteinContent' => $this->proteinContent,
297
            'saturatedFatContent' => $this->saturatedFatContent,
298
            'sodiumContent' => $this->sodiumContent,
299
            'sugarContent' => $this->sugarContent,
300
            'transFatContent' => $this->transFatContent,
301
            'unsaturatedFatContent' => $this->unsaturatedFatContent,
302
        ];
303
        $nutrition = array_filter($nutrition);
304
        $recipeJSONLD['nutrition'] = $nutrition;
305
        if (count($recipeJSONLD['nutrition']) === 1) {
306
            unset($recipeJSONLD['nutrition']);
307
        }
308
        $aggregateRating = $this->getAggregateRating();
309
        if ($aggregateRating) {
310
            $aggregateRatings = [
311
                'type' => 'AggregateRating',
312
                'ratingCount' => $this->getRatingsCount(),
313
                'bestRating' => '5',
314
                'worstRating' => '1',
315
                'ratingValue' => $aggregateRating,
316
            ];
317
            $aggregateRatings = array_filter($aggregateRatings);
318
            $recipeJSONLD['aggregateRating'] = $aggregateRatings;
319
320
            $reviews = [];
321
            foreach ($this->ratings as $rating) {
322
                $review = [
323
                    'type' => 'Review',
324
                    'author' => $rating['author'],
325
                    'name' => $this->name . ' ' . Craft::t('recipe', 'Review'),
326
                    'description' => $rating['review'],
327
                    'reviewRating' => [
328
                        'type' => 'Rating',
329
                        'bestRating' => '5',
330
                        'worstRating' => '1',
331
                        'ratingValue' => $rating['rating'],
332
                    ],
333
                ];
334
                $reviews[] = $review;
335
            }
336
            $reviews = array_filter($reviews);
337
            $recipeJSONLD['review'] = $reviews;
338
        }
339
340
        if ($this->prepTime) {
341
            $recipeJSONLD['prepTime'] = 'PT' . $this->prepTime . 'M';
342
        }
343
        if ($this->cookTime) {
344
            $recipeJSONLD['cookTime'] = 'PT' . $this->cookTime . 'M';
345
        }
346
        if ($this->totalTime) {
347
            $recipeJSONLD['totalTime'] = 'PT' . $this->totalTime . 'M';
348
        }
349
350
        return $recipeJSONLD;
351
    }
352
353
    /**
354
     * Create the SEOmatic MetaJsonLd object for this recipe
355
     *
356
     * @param bool $add
0 ignored issues
show
Coding Style introduced by
Doc comment for parameter $add does not match actual variable name $key
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
357
     * @param null $key
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $key is correct as it would always require null to be passed?
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Doc comment for parameter $key does not match actual variable name $add
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
358
     * @return null|MetaJsonLd
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
359
     */
360
    public function createRecipeMetaJsonLd($key = null, bool $add = true)
361
    {
362
        $result = null;
363
        if (Craft::$app->getPlugins()->getPlugin(self::SEOMATIC_PLUGIN_HANDLE)) {
364
            $seomatic = Seomatic::getInstance();
365
            if ($seomatic !== null) {
366
                $recipeJson = $this->getRecipeJSONLD();
367
                // If we're adding the MetaJsonLd to the container, and no key is provided, give it a random key
368
                if ($add && $key === null) {
369
                    try {
370
                        $key = StringHelper::UUID();
371
                    } catch (\Exception $e) {
372
                        // That's okay
373
                    }
374
                }
375
                if ($key !== null) {
376
                    $recipeJson['key'] = $key;
377
                }
378
                // If the key is `mainEntityOfPage` add in the URL
379
                if ($key === self::MAIN_ENTITY_KEY) {
380
                    $mainEntity = Seomatic::$plugin->jsonLd->get(self::MAIN_ENTITY_KEY);
381
                    if ($mainEntity) {
382
                        $recipeJson[self::MAIN_ENTITY_KEY] = $mainEntity[self::MAIN_ENTITY_KEY];
383
                    }
384
                }
385
386
                $result = Seomatic::$plugin->jsonLd->create(
387
                    $recipeJson,
388
                    $add
389
                );
390
            }
391
        }
392
393
        return $result;
394
    }
395
396
    /**
397
     * Render the JSON-LD Structured Data for this recipe
398
     *
399
     * @param bool $raw
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
400
     *
401
     * @return string|\Twig_Markup
402
     */
403
    public function renderRecipeJSONLD($raw = true)
404
    {
405
        return $this->renderJsonLd($this->getRecipeJSONLD(), $raw);
406
    }
407
408
    /**
409
     * Get the URL to the recipe's image
410
     *
411
     * @param null $transform
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Documentation Bug introduced by
Are you sure the doc-type for parameter $transform is correct as it would always require null to be passed?
Loading history...
412
     *
413
     * @return null|string
414
     */
415
    public function getImageUrl($transform = null)
416
    {
417
        $result = '';
418
        if (isset($this->imageId) && $this->imageId) {
419
            $image = Craft::$app->getAssets()->getAssetById($this->imageId[0]);
420
            if ($image) {
421
                $result = $image->getUrl($transform);
422
            }
423
        }
424
425
        return $result;
426
    }
427
428
    /**
429
     * Render the Nutrition Facts template
430
     *
431
     * @param array $rda
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 2 spaces but found 1
Loading history...
432
     * @return Markup
0 ignored issues
show
Coding Style introduced by
Tag @return cannot be grouped with parameter tags in a doc comment
Loading history...
433
     */
434
    public function renderNutritionFacts(array $rda = self::US_RDA): Markup {
0 ignored issues
show
Coding Style introduced by
Opening brace should be on a new line
Loading history...
435
        return PluginTemplate::renderPluginTemplate(
436
            'recipe-nutrition-facts',
437
            [
438
                'value' => $this,
439
                'rda' => $rda,
440
            ]
441
        );
442
    }
443
444
    /**
445
     * Get all of the ingredients for this recipe
446
     *
447
     * @param string $outputUnits
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
448
     * @param int    $serving
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
449
     * @param bool   $raw
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
450
     *
451
     * @return array
452
     */
453
    public function getIngredients($outputUnits = 'imperial', $serving = 0, $raw = true): array
454
    {
455
        $result = [];
456
457
        if (!empty($this->ingredients)) {
458
            foreach ($this->ingredients as $row) {
459
                $convertedUnits = '';
460
                $ingredient = '';
461
                if ($row['quantity']) {
462
                    // Multiply the quantity by how many servings we want
463
                    $multiplier = 1;
464
                    if ($serving > 0) {
465
                        $multiplier = $serving / $this->serves;
466
                    }
467
                    $quantity = $row['quantity'] * $multiplier;
468
                    $originalQuantity = $quantity;
469
470
                    // Do the imperial->metric units conversion
471
                    if ($outputUnits === 'imperial') {
472
                        switch ($row['units']) {
473
                            case 'ml':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 24 spaces, found 28
Loading history...
474
                                $convertedUnits = 'tsp';
475
                                $quantity *= 0.2;
476
                                break;
477
                            case 'l':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 24 spaces, found 28
Loading history...
478
                                $convertedUnits = 'cups';
479
                                $quantity *= 4.2;
480
                                break;
481
                            case 'mg':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 24 spaces, found 28
Loading history...
482
                                $convertedUnits = 'oz';
483
                                $quantity *= 0.000035274;
484
                                break;
485
                            case 'g':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 24 spaces, found 28
Loading history...
486
                                $convertedUnits = 'oz';
487
                                $quantity *= 0.035274;
488
                                break;
489
                            case 'kg':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 24 spaces, found 28
Loading history...
490
                                $convertedUnits = 'lb';
491
                                $quantity *= 2.2046226218;
492
                                break;
493
                        }
494
                    }
495
                    // Do the metric->imperial units conversion
496
                    if ($outputUnits === 'metric') {
497
                        switch ($row['units']) {
498
                            case 'tsp':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 24 spaces, found 28
Loading history...
499
                                $convertedUnits = 'ml';
500
                                $quantity *= 4.929;
501
                                break;
502
                            case 'tbsp':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 24 spaces, found 28
Loading history...
503
                                $convertedUnits = 'ml';
504
                                $quantity *= 14.787;
505
                                break;
506
                            case 'floz':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 24 spaces, found 28
Loading history...
507
                                $convertedUnits = 'ml';
508
                                $quantity *= 29.574;
509
                                break;
510
                            case 'cups':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 24 spaces, found 28
Loading history...
511
                                $convertedUnits = 'l';
512
                                $quantity *= 0.236588;
513
                                break;
514
                            case 'oz':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 24 spaces, found 28
Loading history...
515
                                $convertedUnits = 'g';
516
                                $quantity *= 28.3495;
517
                                break;
518
                            case 'lb':
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 24 spaces, found 28
Loading history...
519
                                $convertedUnits = 'kg';
520
                                $quantity *= 0.45359237;
521
                                break;
522
                        }
523
524
                        $quantity = round($quantity, 1);
525
                    }
526
527
                    // Convert units to nice fractions
528
                    $quantity = $this->convertToFractions($quantity);
529
530
                    $ingredient .= $quantity;
531
532
                    if ($row['units']) {
533
                        $units = $row['units'];
534
                        if ($convertedUnits) {
535
                            $units = $convertedUnits;
536
                        }
537
                        if ($originalQuantity <= 1) {
538
                            $units = rtrim($units);
539
                            $units = rtrim($units, 's');
540
                        }
541
                        $ingredient .= ' ' . $units;
542
                    }
543
                }
544
                if ($row['ingredient']) {
545
                    $ingredient .= ' ' . $row['ingredient'];
546
                }
547
                if ($raw) {
548
                    $ingredient = Template::raw($ingredient);
549
                }
550
                $result[] = $ingredient;
551
            }
552
        }
553
554
        return $result;
555
    }
556
557
    /**
558
     * Convert decimal numbers into fractions
559
     *
560
     * @param $quantity
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
561
     *
562
     * @return string
563
     */
564
    private function convertToFractions($quantity)
0 ignored issues
show
Coding Style introduced by
Private method name "Recipe::convertToFractions" must be prefixed with an underscore
Loading history...
565
    {
566
        $whole = floor($quantity);
567
        // Round the mantissa so we can do a floating point comparison without
568
        // weirdness, per: https://www.php.net/manual/en/language.types.float.php#113703
569
        $fraction = round($quantity - $whole, 3);
570
        switch ($fraction) {
571
            case 0:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
572
                $fraction = '';
573
                break;
574
            case 0.25:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
575
                $fraction = ' &frac14;';
576
                break;
577
            case 0.33:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
578
                $fraction = ' &frac13;';
579
                break;
580
            case 0.66:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
581
                $fraction = ' &frac23;';
582
                break;
583
            case 0.165:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
584
                $fraction = ' &frac16;';
585
                break;
586
            case 0.5:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
587
                $fraction = ' &frac12;';
588
                break;
589
            case 0.75:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
590
                $fraction = ' &frac34;';
591
                break;
592
            case 0.125:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
593
                $fraction = ' &#x215B;';
594
                break;
595
            case 0.375:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
596
                $fraction = ' &#x215C;';
597
                break;
598
            case 0.625:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
599
                $fraction = ' &#x215D;';
600
                break;
601
            case 0.875:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
602
                $fraction = ' &#x215E;';
603
                break;
604
            default:
0 ignored issues
show
Coding Style introduced by
Line indented incorrectly; expected 8 spaces, found 12
Loading history...
605
                $precision = 1;
606
                $pnum = round($fraction, $precision);
607
                $denominator = 10 ** $precision;
608
                $numerator = $pnum * $denominator;
609
                $fraction = ' <sup>'
610
                    .$numerator
611
                    . '</sup>&frasl;<sub>'
612
                    .$denominator
613
                    . '</sub>';
614
                break;
615
        }
616
        if ($whole == 0) {
617
            $whole = '';
618
        }
619
620
        return $whole.$fraction;
621
    }
622
623
    /**
624
     * Get all of the directions for this recipe
625
     *
626
     * @param bool $raw
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
627
     *
628
     * @return array
629
     */
630
    public function getDirections($raw = true)
631
    {
632
        $result = [];
633
        if (!empty($this->directions)) {
634
            foreach ($this->directions as $row) {
635
                $direction = $row['direction'];
636
                if ($raw) {
637
                    $direction = Template::raw($direction);
638
                }
639
                $result[] = $direction;
640
            }
641
        }
642
643
        return $result;
644
    }
645
646
    /**
647
     * Get all of the equipment for this recipe
648
     *
649
     * @param bool $raw
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
650
     *
651
     * @return array
652
     */
653
    public function getEquipment($raw = true)
654
    {
655
        $result = [];
656
        if (!empty($this->equipment)) {
657
            foreach ($this->equipment as $row) {
658
                $equipment = $row['equipment'];
659
                if ($raw) {
660
                    $equipment = Template::raw(equipment);
0 ignored issues
show
Bug introduced by
The constant nystudio107\recipe\models\equipment was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
661
                }
662
                $result[] = $equipment;
663
            }
664
        }
665
666
        return $result;
667
    }
668
669
    /**
670
     * Get the aggregate rating from all of the ratings
671
     *
672
     * @return float|int|string
673
     */
674
    public function getAggregateRating()
675
    {
676
        $result = 0;
677
        $total = 0;
678
        if (isset($this->ratings) && !empty($this->ratings)) {
679
            foreach ($this->ratings as $row) {
680
                $result += $row['rating'];
681
                $total++;
682
            }
683
            $result /= $total;
684
        } else {
685
            $result = '';
686
        }
687
688
        return $result;
689
    }
690
691
    /**
692
     * Get the total number of ratings
693
     *
694
     * @return int
695
     */
696
    public function getRatingsCount(): int
697
    {
698
        return count($this->ratings);
699
    }
700
701
    /**
702
     * Returns concatenated serves with its unit
703
     */
0 ignored issues
show
Coding Style introduced by
Missing @return tag in function comment
Loading history...
704
    public function getServes(): string
705
    {
706
        if(!empty($this->servesUnit)) {
0 ignored issues
show
Coding Style introduced by
Expected "if (...) {\n"; found "if(...) {\n"
Loading history...
707
            return $this->serves . ' ' . $this->servesUnit;
708
        } else {
709
            return $this->serves;
710
        }
711
    }
712
713
    // Private Methods
714
    // =========================================================================
715
716
    /**
717
     * Renders a JSON-LD representation of the schema
718
     *
719
     * @param      $json
0 ignored issues
show
Coding Style introduced by
Tag value for @param tag indented incorrectly; expected 1 spaces but found 6
Loading history...
Coding Style introduced by
Missing parameter comment
Loading history...
720
     * @param bool $raw
0 ignored issues
show
Coding Style introduced by
Missing parameter comment
Loading history...
721
     *
722
     * @return string|\Twig_Markup
723
     */
724
    private function renderJsonLd($json, $raw = true)
0 ignored issues
show
Coding Style introduced by
Private method name "Recipe::renderJsonLd" must be prefixed with an underscore
Loading history...
725
    {
726
        $linebreak = '';
727
728
        // If `devMode` is enabled, make the JSON-LD human-readable
729
        if (Craft::$app->getConfig()->getGeneral()->devMode) {
730
            $linebreak = PHP_EOL;
731
        }
732
733
        // Render the resulting JSON-LD
734
        $result = '<script type="application/ld+json">'
735
            .$linebreak
736
            .Json::encode($json)
737
            .$linebreak
738
            .'</script>';
739
740
        if ($raw === true) {
741
            $result = Template::raw($result);
742
        }
743
744
        return $result;
745
    }
746
}
747