Exponential 5.x Kernel 7.5.40 Exponential New Stack (Symfony-based) Kernel — PHP Class Reference

UpdateFieldAlwaysAvailableFlagCommand.php
Go to the documentation of this file.
1 <?php
2
7 namespace eZ\Bundle\EzPublishMigrationBundle\Command\LegacyStorage;
8
9 use eZ\Publish\Core\Persistence\Database\SelectQuery;
10 use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
11 use Symfony\Component\Console\Input\InputInterface;
12 use Symfony\Component\Console\Output\OutputInterface;
13 use Symfony\Component\Console\Input\InputArgument;
14 use Symfony\Component\Console\Input\InputOption;
15 use Symfony\Component\Console\Helper\ProgressBar;
16 use Symfony\Component\Console\Formatter\OutputFormatterStyle;
17 use Symfony\Component\Console\Question\ConfirmationQuestion;
18 use PDO;
19
20 class UpdateFieldAlwaysAvailableFlagCommand extends ContainerAwareCommand
21 {
22 protected function configure()
23 {
24 $this
25 ->setName('ezpublish:update:legacy_storage_fix_fields_always_available_flag')
26 ->setDescription('Fixes always available flag on Content fields')
27 ->addArgument(
28 'bulk_count',
29 InputArgument::OPTIONAL,
30 'Number of Content processed at once',
31 100
32 )
33 ->addOption(
34 'dry-run',
35 null,
36 InputOption::VALUE_NONE,
37 'Execute a dry run'
38 )
39 ->setHelp(
40 <<<EOT
41 The command <info>%command.name%</info> fixes always available flag on Content
42 fields in Legacy Storage Engine database.
43
44 This will process only fields of the current version of the always available Content
45 where found that fields in multiple languages have always available flag set.
46
47 Provided the patch that fixes the cause of the problem has been applied, this
48 command can be executed on a live database.
49
50 <warning>To avoid surprises you are advised to create a backup or execute a dry
51 run before proceeding with the actual update.</warning>
52
53 Since this command can potentially run for a very long time, to avoid memory
54 exhaustion run it in production environment using <info>--env=prod</info> switch.
55
56 EOT
57 );
58 }
59
60 protected function execute(InputInterface $input, OutputInterface $output)
61 {
62 $bulkCount = $input->getArgument('bulk_count');
63 $dryRun = $input->getOption('dry-run');
64
66 $databaseHandler = $this->getContainer()->get('ezpublish.connection');
67
68 $warningStyle = new OutputFormatterStyle('red');
69 $output->getFormatter()->setStyle('warning', $warningStyle);
70 $output->writeln($this->getProcessedHelp());
71
72 $query = $databaseHandler->createSelectQuery();
73 $subQuery = $query->subSelect();
74 $this->initSelectQuery($subQuery);
75 $query
76 ->select($query->expr->count('*'))
77 ->from($query->alias($subQuery, 't1'));
78 $stmt = $query->prepare();
79 $stmt->execute();
80 $totalCount = $stmt->fetchColumn();
81
82 $output->writeln(
83 [
84 'Found total of Content objects for update: ' . $totalCount,
85 '',
86 ]
87 );
88
89 if ($totalCount == 0) {
90 $output->writeln('Nothing to process, exiting.');
91
92 return;
93 }
94
95 $helper = $this->getHelper('question');
96 $question = new ConfirmationQuestion(
97 '<question>Are you sure you want to proceed?</question> ',
98 false
99 );
100
101 if (!$helper->ask($input, $output, $question)) {
102 $output->writeln('');
103
104 return;
105 }
106
107 $query = $databaseHandler->createSelectQuery();
108 $this->initSelectQuery($query);
109
110 $passCount = ceil($totalCount / $bulkCount);
111
112 $progress = new ProgressBar($output, $totalCount);
113 $progress->setFormat(
114 ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%'
115 );
116
117 $output->writeln('');
118 $progress->start();
119
120 for ($pass = 0; $pass <= $passCount; ++$pass) {
121 $rows = $this->loadData($query, $bulkCount, $pass);
122
123 foreach ($rows as $row) {
124 $this->updateAlwaysAvailableFlag(
125 $output,
126 $progress,
127 $row['id'],
128 $row['current_version'],
129 $row['initial_language_id'],
130 $dryRun
131 );
132
133 $progress->advance();
134 }
135 }
136
137 $progress->finish();
138
139 $output->writeln('');
140 }
141
151 protected function loadData(SelectQuery $query, $bulkCount, $pass)
152 {
153 $query->limit($bulkCount, $pass * $bulkCount);
154
155 $stmt = $query->prepare();
156 $stmt->execute();
157
158 return $stmt->fetchAll(PDO::FETCH_ASSOC);
159 }
160
166 protected function initSelectQuery(SelectQuery $query)
167 {
169 $databaseHandler = $this->getContainer()->get('ezpublish.connection');
170
171 $query
172 ->select(
173 $databaseHandler->quoteColumn('id', 'ezcontentobject'),
174 $databaseHandler->quoteColumn('current_version', 'ezcontentobject'),
175 $databaseHandler->quoteColumn('initial_language_id', 'ezcontentobject'),
176 $query->expr->count('distinct ezcontentobject_attribute.language_code')
177 )
178 ->from('ezcontentobject')
179 ->innerJoin(
180 $databaseHandler->quoteTable('ezcontentobject_attribute'),
181 $query->expr->lAnd(
182 $query->expr->eq(
183 $databaseHandler->quoteColumn('id', 'ezcontentobject'),
184 $databaseHandler->quoteColumn(
185 'contentobject_id',
186 'ezcontentobject_attribute'
187 )
188 ),
189 $query->expr->eq(
190 $databaseHandler->quoteColumn('current_version', 'ezcontentobject'),
191 $databaseHandler->quoteColumn('version', 'ezcontentobject_attribute')
192 ),
193 // Join only with fields marked as always available
194 $query->expr->gt(
195 $query->expr->bitAnd(
196 $databaseHandler->quoteColumn(
197 'language_id',
198 'ezcontentobject_attribute'
199 ),
200 $query->bindValue(1, null, PDO::PARAM_INT)
201 ),
202 $query->bindValue(0, null, PDO::PARAM_INT)
203 )
204 )
205 )
206 ->where(
207 $query->expr->lAnd(
208 // Content is always available
209 $query->expr->gt(
210 $query->expr->bitAnd(
211 $databaseHandler->quoteColumn('language_mask', 'ezcontentobject'),
212 $query->bindValue(1, null, PDO::PARAM_INT)
213 ),
214 $query->bindValue(0, null, PDO::PARAM_INT)
215 ),
216 // Content exists in more than one language
217 $query->expr->neq(
218 $query->expr->bitAnd(
219 $query->expr->bitAnd(
220 $databaseHandler->quoteColumn('language_mask', 'ezcontentobject'),
221 $query->bindValue(-2, null, PDO::PARAM_INT)
222 ),
223 $query->expr->sub(
224 $query->expr->bitAnd(
225 $databaseHandler->quoteColumn(
226 'language_mask',
227 'ezcontentobject'
228 ),
229 $query->bindValue(-2, null, PDO::PARAM_INT)
230 ),
231 $query->bindValue(1, null, PDO::PARAM_INT)
232 )
233 ),
234 $query->bindValue(0, null, PDO::PARAM_INT)
235 )
236 )
237 )
238 ->groupBy($databaseHandler->quoteColumn('id', 'ezcontentobject'))
239 // Remove Content with fields marked as always available in only one language
240 ->having(
241 $query->expr->gt(
242 $query->expr->count('distinct ezcontentobject_attribute.language_code'),
243 $query->bindValue(1, null, PDO::PARAM_INT)
244 )
245 );
246 }
247
258 protected function updateAlwaysAvailableFlag(
259 OutputInterface $output,
260 ProgressBar $progress,
261 $contentId,
262 $versionNo,
263 $mainLanguageId,
264 $dryRun
265 ) {
266 if ($dryRun) {
267 goto output;
268 }
269
271 $databaseHandler = $this->getContainer()->get('ezpublish.connection');
272
273 // Remove always available flag from all fields not in main language
275 $query = $databaseHandler->createUpdateQuery();
276 $query
277 ->update($databaseHandler->quoteTable('ezcontentobject_attribute'))
278 ->set(
279 $databaseHandler->quoteColumn('language_id'),
280 $query->expr->bitAnd($databaseHandler->quoteColumn('language_id'), -2)
281 )
282 ->where(
283 $query->expr->lAnd(
284 $query->expr->eq(
285 $databaseHandler->quoteColumn('contentobject_id'),
286 $query->bindValue($contentId, null, PDO::PARAM_INT)
287 ),
288 $query->expr->eq(
289 $databaseHandler->quoteColumn('version'),
290 $query->bindValue($versionNo, null, PDO::PARAM_INT)
291 ),
292 $query->expr->eq(
293 $query->expr->bitAnd(
294 $databaseHandler->quoteColumn('language_id'),
295 $query->bindValue($mainLanguageId, null, PDO::PARAM_INT)
296 ),
297 $query->bindValue(0, null, PDO::PARAM_INT)
298 )
299 )
300 )
301 ->prepare()
302 ->execute();
303
304 // Set always available flag on fields in main language
305 $query = $databaseHandler->createUpdateQuery();
306 $query
307 ->update($databaseHandler->quoteTable('ezcontentobject_attribute'))
308 ->set(
309 $databaseHandler->quoteColumn('language_id'),
310 $query->expr->bitOr($databaseHandler->quoteColumn('language_id'), 1)
311 )
312 ->where(
313 $query->expr->lAnd(
314 $query->expr->eq(
315 $databaseHandler->quoteColumn('contentobject_id'),
316 $query->bindValue($contentId, null, PDO::PARAM_INT)
317 ),
318 $query->expr->eq(
319 $databaseHandler->quoteColumn('version'),
320 $query->bindValue($versionNo, null, PDO::PARAM_INT)
321 ),
322 $query->expr->gt(
323 $query->expr->bitAnd(
324 $databaseHandler->quoteColumn('language_id'),
325 $query->bindValue($mainLanguageId, null, PDO::PARAM_INT)
326 ),
327 $query->bindValue(0, null, PDO::PARAM_INT)
328 )
329 )
330 )
331 ->prepare()
332 ->execute();
333
334 output:
335
336 $progress->clear();
337
338 $output->write("\r");
339 $output->writeln(
340 "Updated fields for Content '{$contentId}' in version '{$versionNo}'"
341 );
342 $output->write("\r");
343
344 $progress->display();
345 }
346 }
eZ\Bundle\EzPublishMigrationBundle\Command\LegacyStorage\UpdateFieldAlwaysAvailableFlagCommand
Definition: UpdateFieldAlwaysAvailableFlagCommand.php:21
eZ\Bundle\EzPublishMigrationBundle\Command\LegacyStorage\UpdateFieldAlwaysAvailableFlagCommand\loadData
loadData(SelectQuery $query, $bulkCount, $pass)
Loads data for the given $pass.
Definition: UpdateFieldAlwaysAvailableFlagCommand.php:151
eZ\Bundle\EzPublishMigrationBundle\Command\LegacyStorage\UpdateFieldAlwaysAvailableFlagCommand\configure
configure()
Definition: UpdateFieldAlwaysAvailableFlagCommand.php:22
eZ\Publish\Core\Persistence\Database\Query\prepare
prepare()
eZ\Publish\Core\Persistence\Database\Query\bindValue
bindValue($value, $placeHolder=null, $type=PDO::PARAM_STR)
Binds the value $value to the specified variable name $placeHolder.
eZ\Publish\Core\Persistence\Database\SelectQuery
Definition: SelectQuery.php:16
eZ\Publish\Core\Persistence\Database\SelectQuery\where
where()
Adds a where clause with logical expressions to the query.
eZ\Publish\Core\Persistence\Database\SelectQuery\limit
limit($limit, $offset='')
Returns SQL that limits the result set.
eZ\Publish\Core\Persistence\Database\SelectQuery\select
select()
Opens the query and selects which columns you want to return with the query.
eZ\Bundle\EzPublishMigrationBundle\Command\LegacyStorage
Definition: CleanUpRelationTypeEqZeroCommand.php:7
Copyright © 1998 – 2026 7x. All rights reserved. Licensed under the GNU GPLv2+.