• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

AJenbo / agcms / 21420560247

28 Jan 2026 12:59AM UTC coverage: 52.306% (-1.4%) from 53.72%
21420560247

push

github

AJenbo
Bump phpunit/phpunit from 9.6.11 to 9.6.33 in /application

Bumps [phpunit/phpunit](https://github.com/sebastianbergmann/phpunit) from 9.6.11 to 9.6.33.
- [Release notes](https://github.com/sebastianbergmann/phpunit/releases)
- [Changelog](https://github.com/sebastianbergmann/phpunit/blob/9.6.33/ChangeLog-9.6.md)
- [Commits](https://github.com/sebastianbergmann/phpunit/compare/9.6.11...9.6.33)

---
updated-dependencies:
- dependency-name: phpunit/phpunit
  dependency-version: 9.6.33
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>

3039 of 5810 relevant lines covered (52.31%)

12.21 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.38
/application/inc/Models/Page.php
1
<?php
2

3
namespace App\Models;
4

5
use App\Exceptions\Exception;
6
use App\Services\DbService;
7
use App\Services\OrmService;
8

9
class Page extends AbstractRenderable implements InterfaceRichText
10
{
11
    use HasIcon;
12

13
    /** Table name in database. */
14
    public const TABLE_NAME = 'sider';
15

16
    // Backed by DB
17

18
    /** @var string Stock keeping unit. */
19
    private string $sku = '';
20

21
    /** @var int Latest save time. */
22
    private int $timeStamp;
23

24
    /** @var string Page keywords, coma seporated. */
25
    private string $keywords = '';
26

27
    /** @var string HTML body. */
28
    private string $html = '';
29

30
    /** @var string Short text description. */
31
    private string $excerpt = '';
32

33
    /** @var ?int Id of requirement page. */
34
    private ?int $requirementId;
35

36
    /** @var ?int Id of brand. */
37
    private ?int $brandId;
38

39
    /** @var int Current price. */
40
    private int $price = 0;
41

42
    /** @var int Previous price. */
43
    private int $oldPrice = 0;
44

45
    /** @var int What type of price is the current (from, specific). */
46
    private int $priceType = 0;
47

48
    /** @var int What type of price is the previous (from, specific). */
49
    private int $oldPriceType = 0;
50

51
    public function __construct(array $data = [])
52
    {
53
        $this->iconId = intOrNull($data['icon_id'] ?? null);
31✔
54
        $this->setSku(valstring($data['sku']))
31✔
55
            ->setTimeStamp(valint($data['timestamp'] ?? 0))
31✔
56
            ->setKeywords(valstring($data['keywords']))
31✔
57
            ->setExcerpt(valstring($data['excerpt']))
31✔
58
            ->setRequirementId(intOrNull($data['requirement_id']))
31✔
59
            ->setBrandId(intOrNull($data['brand_id']))
31✔
60
            ->setPrice(valint($data['price']))
31✔
61
            ->setOldPrice(valint($data['old_price']))
31✔
62
            ->setPriceType(valint($data['price_type']))
31✔
63
            ->setOldPriceType(valint($data['old_price_type']))
31✔
64
            ->setHtml(valstring($data['html']))
31✔
65
            ->setTitle(valstring($data['title']))
31✔
66
            ->setId(intOrNull($data['id'] ?? null));
31✔
67
    }
68

69
    public static function mapFromDB(array $data): array
70
    {
71
        return [
31✔
72
            'id'             => $data['id'],
31✔
73
            'sku'            => $data['varenr'],
31✔
74
            'timestamp'      => strtotime($data['dato']) + app(DbService::class)->getTimeOffset(),
31✔
75
            'title'          => $data['navn'],
31✔
76
            'keywords'       => $data['keywords'],
31✔
77
            'html'           => $data['text'],
31✔
78
            'excerpt'        => $data['beskrivelse'],
31✔
79
            'icon_id'        => $data['icon_id'],
31✔
80
            'requirement_id' => $data['krav'],
31✔
81
            'brand_id'       => $data['maerke'],
31✔
82
            'price'          => $data['pris'],
31✔
83
            'old_price'      => $data['for'],
31✔
84
            'price_type'     => $data['fra'],
31✔
85
            'old_price_type' => $data['burde'],
31✔
86
        ];
31✔
87
    }
88

89
    /**
90
     * Delete page and it's relations.
91
     */
92
    public function delete(): bool
93
    {
94
        $db = app(DbService::class);
1✔
95

96
        // Forget affected tables, though alter indivitual deletes will forget most
97
        $db->addLoadedTable('list_rows');
1✔
98
        $db->query('DELETE FROM `list_rows` WHERE `link` = ' . $this->getId());
1✔
99
        foreach ($this->getTables() as $table) {
1✔
100
            $table->delete();
1✔
101
        }
102

103
        // parent::delete will forget any binding and accessory relationship
104
        $db->addLoadedTable('bind');
1✔
105
        $db->query('DELETE FROM `bind` WHERE side = ' . $this->getId());
1✔
106
        $db->addLoadedTable('tilbehor');
1✔
107
        $db->query('DELETE FROM `tilbehor` WHERE side = ' . $this->getId() . ' OR tilbehor =' . $this->getId());
1✔
108

109
        return parent::delete();
1✔
110
    }
111

112
    // Getters and setters
113

114
    /**
115
     * Set the Stock Keeping Unit identifyer.
116
     *
117
     * @return $this
118
     */
119
    public function setSku(string $sku): self
120
    {
121
        $this->sku = $sku;
31✔
122

123
        return $this;
31✔
124
    }
125

126
    /**
127
     * Get the Stock Keeping Unity.
128
     */
129
    public function getSku(): string
130
    {
131
        return $this->sku;
21✔
132
    }
133

134
    /**
135
     * Set the last modefied time stamp.
136
     *
137
     * @return $this
138
     */
139
    public function setTimeStamp(int $timeStamp): self
140
    {
141
        $this->timeStamp = $timeStamp;
31✔
142

143
        return $this;
31✔
144
    }
145

146
    /**
147
     * Get last modefied.
148
     */
149
    public function getTimeStamp(): int
150
    {
151
        return $this->timeStamp;
8✔
152
    }
153

154
    /**
155
     * @param string $keywords Comma seporated
156
     *
157
     * @return $this
158
     */
159
    public function setKeywords(string $keywords): self
160
    {
161
        $this->keywords = $keywords;
31✔
162

163
        return $this;
31✔
164
    }
165

166
    public function getKeywords(): string
167
    {
168
        return $this->keywords;
×
169
    }
170

171
    /**
172
     * @return $this
173
     */
174
    public function setHtml(string $html): InterfaceRichText
175
    {
176
        $this->html = $html;
31✔
177

178
        return $this;
31✔
179
    }
180

181
    /**
182
     * Get the HTML body.
183
     */
184
    public function getHtml(): string
185
    {
186
        return $this->html;
5✔
187
    }
188

189
    /**
190
     * Set the breaf description.
191
     *
192
     * @return $this
193
     */
194
    public function setExcerpt(string $excerpt): self
195
    {
196
        $this->excerpt = $excerpt;
31✔
197

198
        return $this;
31✔
199
    }
200

201
    /**
202
     * Get the short description.
203
     */
204
    public function getExcerpt(): string
205
    {
206
        if (!$this->excerpt) {
7✔
207
            $excerpt = preg_replace(['/</', '/>/', '/\s+/'], [' <', '> ', ' '], $this->html);
7✔
208
            if (null === $excerpt) {
7✔
209
                throw new Exception('preg_replace failed');
×
210
            }
211
            $excerpt = strip_tags($excerpt);
7✔
212
            $excerpt = preg_replace('/\s+/', ' ', $excerpt);
7✔
213
            if (null === $excerpt) {
7✔
214
                throw new Exception('preg_replace failed');
×
215
            }
216

217
            return stringLimit($excerpt, 100);
7✔
218
        }
219

220
        return $this->excerpt;
×
221
    }
222

223
    /**
224
     * Check if an except has been entered manually.
225
     */
226
    public function hasExcerpt(): bool
227
    {
228
        return (bool)$this->excerpt;
×
229
    }
230

231
    /**
232
     * @return $this
233
     */
234
    public function setRequirementId(?int $requirementId): self
235
    {
236
        $this->requirementId = $requirementId;
31✔
237

238
        return $this;
31✔
239
    }
240

241
    /**
242
     * @return $this
243
     */
244
    public function setBrandId(?int $brandId): self
245
    {
246
        $this->brandId = $brandId;
31✔
247

248
        return $this;
31✔
249
    }
250

251
    /**
252
     * Set the price.
253
     *
254
     * @return $this
255
     */
256
    public function setPrice(int $price): self
257
    {
258
        $this->price = $price;
31✔
259

260
        return $this;
31✔
261
    }
262

263
    /**
264
     * Get the price.
265
     */
266
    public function getPrice(): int
267
    {
268
        return $this->price;
21✔
269
    }
270

271
    /**
272
     * Set the old price.
273
     *
274
     * @param int $oldPrice The previous price
275
     *
276
     * @return $this
277
     */
278
    public function setOldPrice(int $oldPrice): self
279
    {
280
        $this->oldPrice = $oldPrice;
31✔
281

282
        return $this;
31✔
283
    }
284

285
    /**
286
     * Get the previous price.
287
     */
288
    public function getOldPrice(): int
289
    {
290
        return $this->oldPrice;
12✔
291
    }
292

293
    /**
294
     * Set the price type.
295
     *
296
     * @return $this
297
     */
298
    public function setPriceType(int $priceType): self
299
    {
300
        $this->priceType = $priceType;
31✔
301

302
        return $this;
31✔
303
    }
304

305
    /**
306
     * Get the price Type.
307
     */
308
    public function getPriceType(): int
309
    {
310
        return $this->priceType;
4✔
311
    }
312

313
    /**
314
     * Set the type of the privious price.
315
     *
316
     * @return $this
317
     */
318
    public function setOldPriceType(int $oldPriceType): self
319
    {
320
        $this->oldPriceType = $oldPriceType;
31✔
321

322
        return $this;
31✔
323
    }
324

325
    /**
326
     * Get the previous price Type.
327
     */
328
    public function getOldPriceType(): int
329
    {
330
        return $this->oldPriceType;
4✔
331
    }
332

333
    // General methods
334

335
    /**
336
     * Get the url slug.
337
     */
338
    public function getSlug(): string
339
    {
340
        return 'side' . $this->getId() . '-' . cleanFileName($this->getTitle()) . '.html';
21✔
341
    }
342

343
    /**
344
     * Get canonical url for this entity.
345
     *
346
     * @param null|Category $category Category to base the url on
347
     */
348
    public function getCanonicalLink(?Category $category = null): string
349
    {
350
        $url = '/';
21✔
351
        if (!$category || !$this->isInCategory($category)) {
21✔
352
            $category = $this->getPrimaryCategory();
12✔
353
        }
354
        if ($category) {
21✔
355
            $url = $category->getCanonicalLink();
21✔
356
        }
357

358
        return $url . $this->getSlug();
21✔
359
    }
360

361
    /**
362
     * Check if the page i attached to a given category.
363
     */
364
    public function isInCategory(Category $category): bool
365
    {
366
        $db = app(DbService::class);
17✔
367

368
        $db->addLoadedTable('bind');
17✔
369

370
        return (bool)$db->fetchOne(
17✔
371
            '
17✔
372
            SELECT kat FROM `bind`
373
            WHERE side = ' . $this->getId() . '
17✔
374
            AND kat = ' . $category->getId()
17✔
375
        );
17✔
376
    }
377

378
    /**
379
     * Get the primery category for this page.
380
     */
381
    public function getPrimaryCategory(): ?Category
382
    {
383
        return app(OrmService::class)->getOneByQuery(Category::class, $this->getCategoriesQuery());
23✔
384
    }
385

386
    /**
387
     * Get all categories.
388
     *
389
     * @return Category[]
390
     */
391
    public function getCategories(): array
392
    {
393
        return app(OrmService::class)->getByQuery(Category::class, $this->getCategoriesQuery());
2✔
394
    }
395

396
    /**
397
     * Generate the query for getting all categories where this page is linke.
398
     */
399
    private function getCategoriesQuery(): string
400
    {
401
        app(DbService::class)->addLoadedTable('bind');
23✔
402

403
        return 'SELECT * FROM `kat` WHERE id IN (SELECT kat FROM `bind` WHERE side = ' . $this->getId() . ')';
23✔
404
    }
405

406
    /**
407
     * Add the page to a given category.
408
     */
409
    public function addToCategory(Category $category): void
410
    {
411
        app(DbService::class)->query(
×
412
            'INSERT INTO `bind` (`side`, `kat`) VALUES (' . $this->getId() . ', ' . $category->getId() . ')'
×
413
        );
×
414
        app(OrmService::class)->forgetByQuery(self::class, $this->getCategoriesQuery());
×
415
    }
416

417
    /**
418
     * Remove the page form a given cateogory.
419
     */
420
    public function removeFromCategory(Category $category): void
421
    {
422
        app(DbService::class)->query('DELETE FROM `bind` WHERE `side` = ' . $this->getId() . ' AND `kat` = ' . $category->getId());
×
423
        app(OrmService::class)->forgetByQuery(self::class, $this->getCategoriesQuery());
×
424
    }
425

426
    /**
427
     * Add a page as an accessory.
428
     */
429
    public function addAccessory(self $accessory): void
430
    {
431
        app(DbService::class)->query(
×
432
            '
×
433
            INSERT IGNORE INTO `tilbehor` (`side`, `tilbehor`)
434
            VALUES (' . $this->getId() . ', ' . $accessory->getId() . ')'
×
435
        );
×
436

437
        app(OrmService::class)->forgetByQuery(self::class, $this->getAccessoryQuery());
×
438
    }
439

440
    /**
441
     * Remove an accessory from the page.
442
     */
443
    public function removeAccessory(self $accessory): void
444
    {
445
        app(DbService::class)->query(
×
446
            'DELETE FROM `tilbehor` WHERE side = ' . $this->getId() . ' AND tilbehor = ' . $accessory->getId()
×
447
        );
×
448

449
        app(OrmService::class)->forgetByQuery(self::class, $this->getAccessoryQuery());
×
450
    }
451

452
    /**
453
     * Get accessory pages.
454
     *
455
     * @return Page[]
456
     */
457
    public function getAccessories(): array
458
    {
459
        return app(OrmService::class)->getByQuery(self::class, $this->getAccessoryQuery());
5✔
460
    }
461

462
    /**
463
     * Get presentable accessories.
464
     *
465
     * @return Page[]
466
     */
467
    public function getActiveAccessories(): array
468
    {
469
        $accessories = [];
5✔
470
        foreach ($this->getAccessories() as $accessory) {
5✔
471
            if (!$accessory->isInactive()) {
×
472
                $accessories[] = $accessory;
×
473
            }
474
        }
475

476
        return $accessories;
5✔
477
    }
478

479
    /**
480
     * Get query for finding accessories.
481
     */
482
    private function getAccessoryQuery(): string
483
    {
484
        app(DbService::class)->addLoadedTable('tilbehor');
5✔
485

486
        return '
5✔
487
            SELECT * FROM sider
488
            WHERE id IN (SELECT tilbehor FROM tilbehor WHERE side = ' . $this->getId() . ') ORDER BY navn ASC';
5✔
489
    }
490

491
    /**
492
     * Get tabels.
493
     *
494
     * @return Table[]
495
     */
496
    public function getTables(): array
497
    {
498
        return app(OrmService::class)->getByQuery(
6✔
499
            Table::class,
6✔
500
            'SELECT * FROM `lists` WHERE page_id = ' . $this->getId()
6✔
501
        );
6✔
502
    }
503

504
    /**
505
     * Check if there is a product table attached to this page.
506
     */
507
    public function hasProductTable(): bool
508
    {
509
        foreach ($this->getTables() as $table) {
2✔
510
            if ($table->hasPrices()) {
1✔
511
                return true;
1✔
512
            }
513
        }
514

515
        return false;
1✔
516
    }
517

518
    /**
519
     * Get product brand.
520
     */
521
    public function getBrand(): ?Brand
522
    {
523
        $brand = null;
8✔
524
        if (null !== $this->brandId) {
8✔
525
            $brand = app(OrmService::class)->getOne(Brand::class, $this->brandId);
5✔
526
        }
527

528
        return $brand;
8✔
529
    }
530

531
    /**
532
     * Get product requirement.
533
     */
534
    public function getRequirement(): ?Requirement
535
    {
536
        $requirement = null;
5✔
537
        if (null !== $this->requirementId) {
5✔
538
            $requirement = app(OrmService::class)->getOne(Requirement::class, $this->requirementId);
×
539
        }
540

541
        return $requirement;
5✔
542
    }
543

544
    /**
545
     * Is the product not on the website.
546
     */
547
    public function isInactive(): bool
548
    {
549
        $category = $this->getPrimaryCategory();
18✔
550
        if ($category) {
18✔
551
            return $category->isInactive();
18✔
552
        }
553

554
        return true;
×
555
    }
556

557
    // ORM related functions
558

559
    public function getDbArray(): array
560
    {
561
        $this->setTimeStamp(time());
×
562

563
        $db = app(DbService::class);
×
564

565
        return [
×
566
            'dato'        => $db->getNowValue(),
×
567
            'navn'        => $db->quote($this->title),
×
568
            'keywords'    => $db->quote($this->keywords),
×
569
            'text'        => $db->quote($this->html),
×
570
            'varenr'      => $db->quote($this->sku),
×
571
            'beskrivelse' => $db->quote($this->excerpt),
×
572
            'icon_id'     => null !== $this->iconId ? (string)$this->iconId : 'NULL',
×
573
            'krav'        => null !== $this->requirementId ? (string)$this->requirementId : 'NULL',
×
574
            'maerke'      => null !== $this->brandId ? (string)$this->brandId : 'NULL',
×
575
            'pris'        => (string)$this->price,
×
576
            'for'         => (string)$this->oldPrice,
×
577
            'fra'         => (string)$this->priceType,
×
578
            'burde'       => (string)$this->oldPriceType,
×
579
        ];
×
580
    }
581
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc