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

heimrichhannot / contao-utils-bundle / 14448877395

14 Apr 2025 02:57PM UTC coverage: 79.026%. First build
14448877395

Pull #94

github

ericges
refactor StaticUrlUtil.php doc
Pull Request #94: Url Util Improvements

60 of 65 new or added lines in 5 files covered. (92.31%)

1104 of 1397 relevant lines covered (79.03%)

3.54 hits per line

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

50.82
/src/EntityFinder/EntityFinderHelper.php
1
<?php
2

3
/*
4
 * Copyright (c) 2022 Heimrich & Hannot GmbH
5
 *
6
 * @license LGPL-3.0-or-later
7
 */
8

9
namespace HeimrichHannot\UtilsBundle\EntityFinder;
10

11
use Contao\ContentModel;
12
use Contao\CoreBundle\Framework\ContaoFramework;
13
use Contao\Database;
14
use Contao\Model;
15
use Contao\Model\Collection;
16
use Contao\ModuleModel;
17
use Contao\Validator;
18
use Doctrine\DBAL\Connection;
19
use HeimrichHannot\UtilsBundle\Util\Utils;
20
use ValueError;
21

22
class EntityFinderHelper
23
{
24
    public function __construct(
25
        private readonly Utils           $utils,
26
        private readonly ContaoFramework $framework,
27
        private readonly Connection      $connection,
28
    )
29
    {
30
    }
2✔
31

32
    /**
33
     * Search within serialized array fields of the model entity.
34
     *
35
     * @param string $type   Module type
36
     * @param string $field  Field with serialized data
37
     * @param array  $values Values to search for in serialized data field
38
     *
39
     * @throws \Exception
40
     */
41
    public function findModulesByTypeAndSerializedValue(string $type, string $field, array $values): ?Collection
42
    {
43
        $blobQuery = $this->utils->database()->createWhereForSerializedBlob(ModuleModel::getTable().'.'.$field, $values);
1✔
44
        $columns = [$blobQuery->createOrWhere()];
1✔
45
        $values = $blobQuery->values;
1✔
46

47
        $columns[] = ModuleModel::getTable().'.type=?';
1✔
48
        $values[] = $type;
1✔
49

50
        return $this->framework->getAdapter(ModuleModel::class)->findBy($columns, $values);
1✔
51
    }
52

53
        /**
54
     * Find frontend modules by insert inserttags like insert_module oder insert_article.
55
     *
56
     * @param string $type The module type
57
     * @param string $field The tl_module field
58
     * @param string $inserttag The inserttag to search for, for example insert_module
59
     * @param int $id The element id to search for, for example the module id (as used in {{insert_module::1}}, would be 1 in this case)
60
     * @return array The found module ids
61
     * @throws \Exception
62
     */
63
    public function findModulesByInserttag(string $type, string $field, string $inserttag, int $id): array
64
    {
65
        if (!Validator::isAlias($field)) {
×
66
            throw new \Exception('Invalid field name '.$field.'given.');
×
67
        }
68
        if (!Validator::isAlias($inserttag)) {
×
69
            throw new \Exception('Invalid inserttag '.$inserttag.'given.');
×
70
        }
71
        $result = Database::getInstance()
×
72
            ->prepare("SELECT id FROM tl_module
×
73
                        WHERE type=?
74
                        AND (
75
                            $field LIKE '%{{".$inserttag."::".$id."}}%'
×
76
                            OR $field LIKE '%{{".$inserttag."::".$id."::%')")
×
77
            ->execute($type);
×
78

79
        return $result->fetchEach('id');
×
80
    }
81

82

83
    /**
84
     * Find content elements by insert inserttags like insert_module oder insert_article.
85
     *
86
     * @param string $type The element type
87
     * @param string $field The tl_content field
88
     * @param string $inserttag The inserttag to search for, for example insert_module
89
     * @param int $id The element id to search for, for example the module id (as used in {{insert_module::1}}, would be 1 in this case)
90
     * @return array<ContentModel> The found content element ids
91
     * @throws \Exception
92
     */
93
    public function findContentElementByInserttag(string $type, string $field, string $inserttag, int $id): array
94
    {
95
        if (!Validator::isAlias($field)) {
×
96
            throw new \Exception('Invalid field name '.$field.'given.');
×
97
        }
98
        if (!Validator::isAlias($inserttag)) {
×
99
            throw new \Exception('Invalid inserttag '.$inserttag.'given.');
×
100
        }
101
        $result = Database::getInstance()
×
102
            ->prepare("SELECT id FROM tl_content
×
103
                        WHERE type=?
104
                        AND (
105
                            $field LIKE '%{{".$inserttag."::".$id."}}%'
×
106
                            OR $field LIKE '%{{".$inserttag."::".$id."::%')")
×
107
            ->execute($type);
×
108

109
        return $result->fetchEach('id');
×
110
    }
111

112
    /**
113
     * @throws \Doctrine\DBAL\Exception
114
     */
115
    public function fetchModelOrData(string $table, int|string $idOrAlias): ?Model
116
    {
117
        /** @var class-string<Model> $modelClass */
118
        $modelClass = $this->framework->getAdapter(Model::class)->getClassFromTable($table);
1✔
119

120
        if (!$modelClass || !class_exists($modelClass)) {
1✔
121
            if (!$this->connection->createSchemaManager()->tablesExist([$table])) {
1✔
122
                return null;
1✔
123
            }
124
            if (is_string($idOrAlias)) {
1✔
125
                $result = $this->connection->executeQuery("SELECT * FROM $table WHERE alias=?", [$idOrAlias]);
1✔
126
                if ($result->rowCount() === 0) {
1✔
127
                    return null;
1✔
128
                }
129
                return $this->anonymousModel($table, $result->fetchAssociative());
1✔
130
            }
131
            if (is_numeric($idOrAlias)) {
1✔
132
                if ($idOrAlias != (int) $idOrAlias) {
1✔
133
                    return null;
×
134
                }
135

136
                $result = $this->connection->executeQuery("SELECT * FROM $table WHERE id=?", [(int)$idOrAlias]);
1✔
137
                if ($result->rowCount() === 0) {
1✔
138
                    return null;
1✔
139
                }
140
                return $this->anonymousModel($table, $result->fetchAssociative());
1✔
141
            }
142
        }
143

144
        return $this->framework->getAdapter($modelClass)->findByIdOrAlias($idOrAlias);
1✔
145
    }
146

147
    private function anonymousModel(string $table, array $data): Model
148
    {
149
        return new class($table, $data) extends Model {
1✔
150
            protected static $strTable;
151

152
            protected $blnPreventSaving = true;
153

154
            /** @noinspection PhpMissingParentConstructorInspection */
155
            public function __construct(string $table, array $data = [])
156
            {
157
                static::$strTable = $table;
1✔
158
                $this->setRow($data);
1✔
159
            }
160

161
            public function __get($strKey)
162
            {
NEW
163
                if ($strKey === 'strTable')
×
164
                {
NEW
165
                    return static::$strTable;
×
166
                }
167

NEW
168
                return parent::__get($strKey);
×
169
            }
170

171
            public function __set($strKey, $varValue)
172
            {
NEW
173
                if ($strKey === 'strTable')
×
174
                {
NEW
175
                    throw new ValueError('Cannot set strTable property non-statically');
×
176
                }
177

178
                if (isset($this->arrData[$strKey]) && $this->arrData[$strKey] === $varValue)
×
179
                {
180
                    return;
×
181
                }
182

183
                $this->arrData[$strKey] = $varValue;
×
184
            }
185

186
            public function setRow(array $arrData)
187
            {
188
                foreach ($arrData as $k => $v)
1✔
189
                {
190
                    if (static::isJoinedField($k))
1✔
191
                    {
192
                        unset($arrData[$k]);
×
193
                    }
194
                }
195

196
                $this->arrData = $arrData;
1✔
197

198
                return $this;
1✔
199
            }
200
        };
1✔
201
    }
202
}
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

© 2025 Coveralls, Inc