5
* Copyright (c) 2002-2010, Sebastian Bergmann <sb@sebastian-bergmann.de>.
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
12
* * Redistributions of source code must retain the above copyright
13
* notice, this list of conditions and the following disclaimer.
15
* * Redistributions in binary form must reproduce the above copyright
16
* notice, this list of conditions and the following disclaimer in
17
* the documentation and/or other materials provided with the
20
* * Neither the name of Sebastian Bergmann nor the names of his
21
* contributors may be used to endorse or promote products derived
22
* from this software without specific prior written permission.
24
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35
* POSSIBILITY OF SUCH DAMAGE.
39
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
40
* @copyright 2002-2010 Sebastian Bergmann <sb@sebastian-bergmann.de>
41
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
42
* @link http://www.phpunit.de/
43
* @since File available since Release 3.1.4
46
require_once 'PHPUnit/Framework.php';
47
require_once 'PHPUnit/Util/Metrics/Project.php';
48
require_once 'PHPUnit/Util/Class.php';
49
require_once 'PHPUnit/Util/CodeCoverage.php';
50
require_once 'PHPUnit/Util/Filesystem.php';
51
require_once 'PHPUnit/Util/Filter.php';
53
PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
60
* @author Sebastian Bergmann <sb@sebastian-bergmann.de>
61
* @copyright 2002-2010 Sebastian Bergmann <sb@sebastian-bergmann.de>
62
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
63
* @version Release: 3.4.14
64
* @link http://www.phpunit.de/
65
* @since Class available since Release 3.1.4
67
class PHPUnit_Util_Log_CodeCoverage_Database
78
* @throws PDOException
80
public function __construct(PDO $dbh)
86
* Stores code coverage information.
88
* @param PHPUnit_Framework_TestResult $result
89
* @param integer $runId
90
* @param integer $revision
91
* @param string $commonPath
93
public function storeCodeCoverage(PHPUnit_Framework_TestResult $result, $runId, $revision, $commonPath = '')
95
$codeCoverage = $result->getCodeCoverageInformation(FALSE);
96
$summary = PHPUnit_Util_CodeCoverage::getSummary($codeCoverage);
97
$files = array_keys($summary);
98
$projectMetrics = new PHPUnit_Util_Metrics_Project($files, $summary);
99
$storedClasses = array();
101
if (empty($commonPath)) {
102
$commonPath = PHPUnit_Util_Filesystem::getCommonPath($files);
105
$this->dbh->beginTransaction();
107
foreach ($files as $fileName) {
108
$shortenedFileName = str_replace($commonPath, '', $fileName);
110
$fileMetrics = $projectMetrics->getFile($fileName);
111
$lines = $fileMetrics->getLines();
112
$hash = md5_file($fileName);
114
$stmt = $this->dbh->prepare(
117
WHERE code_file_name = :shortenedFileName
118
AND revision = :revision;'
121
$stmt->bindParam(':shortenedFileName', $shortenedFileName, PDO::PARAM_STR);
122
$stmt->bindParam(':revision', $revision, PDO::PARAM_INT);
126
$fileId = (int)$stmt->fetchColumn();
132
$stmt = $this->dbh->prepare(
133
'INSERT INTO code_file
134
(code_file_name, code_full_file_name,
135
code_file_md5, revision)
136
VALUES(:shortenedFileName, :fullFileName,
140
$stmt->bindParam(':shortenedFileName', $shortenedFileName, PDO::PARAM_STR);
141
$stmt->bindParam(':fullFileName', $fileName, PDO::PARAM_STR);
142
$stmt->bindParam(':hash', $hash, PDO::PARAM_STR);
143
$stmt->bindParam(':revision', $revision, PDO::PARAM_INT);
146
$fileId = $this->dbh->lastInsertId();
148
$stmt = $this->dbh->prepare(
149
'INSERT INTO code_class
150
(code_file_id, code_class_name,
151
code_class_start_line, code_class_end_line)
152
VALUES(:fileId, :className, :startLine, :endLine);'
155
foreach ($fileMetrics->getClasses() as $classMetrics) {
156
$className = $classMetrics->getClass()->getName();
157
$classStartLine = $classMetrics->getClass()->getStartLine();
158
$classEndLine = $classMetrics->getClass()->getEndLine();
160
$stmt->bindParam(':fileId', $fileId, PDO::PARAM_INT);
161
$stmt->bindParam(':className', $className, PDO::PARAM_STR);
162
$stmt->bindParam(':startLine', $classStartLine, PDO::PARAM_INT);
163
$stmt->bindParam(':endLine', $classEndLine, PDO::PARAM_INT);
166
$classId = $this->dbh->lastInsertId();
167
$storedClasses[$className] = $classId;
169
$stmt2 = $this->dbh->prepare(
170
'INSERT INTO code_method
171
(code_class_id, code_method_name,
172
code_method_start_line, code_method_end_line)
173
VALUES(:classId, :methodName, :startLine, :endLine);'
176
foreach ($classMetrics->getMethods() as $methodMetrics) {
177
$methodName = $methodMetrics->getMethod()->getName();
178
$methodStartLine = $methodMetrics->getMethod()->getStartLine();
179
$methodEndLine = $methodMetrics->getMethod()->getEndLine();
181
$stmt2->bindParam(':classId', $classId, PDO::PARAM_INT);
182
$stmt2->bindParam(':methodName', $methodName, PDO::PARAM_STR);
183
$stmt2->bindParam(':startLine', $methodStartLine, PDO::PARAM_INT);
184
$stmt2->bindParam(':endLine', $methodEndLine, PDO::PARAM_INT);
191
$stmt = $this->dbh->prepare(
192
'INSERT INTO code_line
193
(code_file_id, code_line_number, code_line,
195
VALUES(:fileId, :lineNumber, :line, :covered);'
200
foreach ($lines as $line) {
203
if (isset($summary[$fileName][$i])) {
204
if (is_int($summary[$fileName][$i])) {
205
$covered = $summary[$fileName][$i];
211
$stmt->bindParam(':fileId', $fileId, PDO::PARAM_INT);
212
$stmt->bindParam(':lineNumber', $i, PDO::PARAM_INT);
213
$stmt->bindParam(':line', $line, PDO::PARAM_STR);
214
$stmt->bindParam(':covered', $covered, PDO::PARAM_INT);
221
$stmt = $this->dbh->prepare(
222
'INSERT INTO metrics_file
223
(run_id, code_file_id, metrics_file_coverage,
224
metrics_file_loc, metrics_file_cloc, metrics_file_ncloc,
225
metrics_file_loc_executable, metrics_file_loc_executed)
226
VALUES(:runId, :fileId, :coverage, :loc, :cloc, :ncloc,
227
:locExecutable, :locExecuted);'
230
$fileCoverage = $fileMetrics->getCoverage();
231
$fileLoc = $fileMetrics->getLoc();
232
$fileCloc = $fileMetrics->getCloc();
233
$fileNcloc = $fileMetrics->getNcloc();
234
$fileLocExecutable = $fileMetrics->getLocExecutable();
235
$fileLocExecuted = $fileMetrics->getLocExecuted();
237
$stmt->bindParam(':runId', $runId, PDO::PARAM_INT);
238
$stmt->bindParam(':fileId', $fileId, PDO::PARAM_INT);
239
$stmt->bindParam(':coverage', $fileCoverage);
240
$stmt->bindParam(':loc', $fileLoc, PDO::PARAM_INT);
241
$stmt->bindParam(':cloc', $fileCloc, PDO::PARAM_INT);
242
$stmt->bindParam(':ncloc', $fileNcloc, PDO::PARAM_INT);
243
$stmt->bindParam(':locExecutable', $fileLocExecutable, PDO::PARAM_INT);
244
$stmt->bindParam(':locExecuted', $fileLocExecuted, PDO::PARAM_INT);
247
$stmtSelectFunctionId = $this->dbh->prepare(
248
'SELECT code_function_id
249
FROM code_file, code_function
250
WHERE code_function.code_file_id = code_file.code_file_id
251
AND code_file.revision = :revision
252
AND code_function.code_function_name = :functionName;'
255
$stmtInsertFunction = $this->dbh->prepare(
256
'INSERT INTO metrics_function
257
(run_id, code_function_id, metrics_function_coverage,
258
metrics_function_loc, metrics_function_loc_executable, metrics_function_loc_executed,
259
metrics_function_ccn, metrics_function_crap, metrics_function_npath)
260
VALUES(:runId, :functionId, :coverage, :loc,
261
:locExecutable, :locExecuted, :ccn, :crap, :npath);'
264
$stmtSelectClassId = $this->dbh->prepare(
265
'SELECT code_class_id
266
FROM code_file, code_class
267
WHERE code_class.code_file_id = code_file.code_file_id
268
AND code_file.revision = :revision
269
AND code_class.code_class_name = :className;'
272
$stmtInsertClass = $this->dbh->prepare(
273
'INSERT INTO metrics_class
274
(run_id, code_class_id, metrics_class_coverage,
275
metrics_class_loc, metrics_class_loc_executable, metrics_class_loc_executed,
276
metrics_class_aif, metrics_class_ahf,
277
metrics_class_cis, metrics_class_csz, metrics_class_dit,
278
metrics_class_impl, metrics_class_mif, metrics_class_mhf,
279
metrics_class_noc, metrics_class_pf, metrics_class_vars,
280
metrics_class_varsnp, metrics_class_varsi,
281
metrics_class_wmc, metrics_class_wmcnp, metrics_class_wmci)
282
VALUES(:runId, :classId, :coverage, :loc, :locExecutable,
283
:locExecuted, :aif, :ahf, :cis, :csz, :dit, :impl,
284
:mif, :mhf, :noc, :pf, :vars, :varsnp, :varsi,
285
:wmc, :wmcnp, :wmci);'
288
$stmtSelectMethodId = $this->dbh->prepare(
289
'SELECT code_method_id
290
FROM code_file, code_class, code_method
291
WHERE code_class.code_file_id = code_file.code_file_id
292
AND code_class.code_class_id = code_method.code_class_id
293
AND code_file.revision = :revision
294
AND code_class.code_class_name = :className
295
AND code_method.code_method_name = :methodName;'
298
$stmtInsertMethod = $this->dbh->prepare(
299
'INSERT INTO metrics_method
300
(run_id, code_method_id, metrics_method_coverage,
301
metrics_method_loc, metrics_method_loc_executable, metrics_method_loc_executed,
302
metrics_method_ccn, metrics_method_crap, metrics_method_npath)
303
VALUES(:runId, :methodId, :coverage, :loc,
304
:locExecutable, :locExecuted, :ccn, :crap, :npath);'
307
foreach ($fileMetrics->getFunctions() as $functionMetrics) {
308
$functionName = $functionMetrics->getFunction()->getName();
310
$stmtSelectFunctionId->bindParam(':functionName', $functionName, PDO::PARAM_STR);
311
$stmtSelectFunctionId->bindParam(':revision', $revision, PDO::PARAM_INT);
312
$stmtSelectFunctionId->execute();
314
$functionId = (int)$stmtSelectFunctionId->fetchColumn();
315
$stmtSelectFunctionId->closeCursor();
317
$functionCoverage = $functionMetrics->getCoverage();
318
$functionLoc = $functionMetrics->getLoc();
319
$functionLocExecutable = $functionMetrics->getLocExecutable();
320
$functionLocExecuted = $functionMetrics->getLocExecuted();
321
$functionCcn = $functionMetrics->getCCN();
322
$functionCrap = $functionMetrics->getCrapIndex();
323
$functionNpath = $functionMetrics->getNPath();
325
$stmtInsertFunction->bindParam(':runId', $runId, PDO::PARAM_INT);
326
$stmtInsertFunction->bindParam(':functionId', $functionId, PDO::PARAM_INT);
327
$stmtInsertFunction->bindParam(':coverage', $functionCoverage);
328
$stmtInsertFunction->bindParam(':loc', $functionLoc, PDO::PARAM_INT);
329
$stmtInsertFunction->bindParam(':locExecutable', $functionLocExecutable, PDO::PARAM_INT);
330
$stmtInsertFunction->bindParam(':locExecuted', $functionLocExecuted, PDO::PARAM_INT);
331
$stmtInsertFunction->bindParam(':ccn', $functionCcn, PDO::PARAM_INT);
332
$stmtInsertFunction->bindParam(':crap', $functionCrap);
333
$stmtInsertFunction->bindParam(':npath', $functionNpath, PDO::PARAM_INT);
334
$stmtInsertFunction->execute();
337
foreach ($fileMetrics->getClasses() as $classMetrics) {
338
$className = $classMetrics->getClass()->getName();
340
$stmtSelectClassId->bindParam(':className', $className, PDO::PARAM_STR);
341
$stmtSelectClassId->bindParam(':revision', $revision, PDO::PARAM_INT);
342
$stmtSelectClassId->execute();
344
$classId = (int)$stmtSelectClassId->fetchColumn();
345
$stmtSelectClassId->closeCursor();
347
$classCoverage = $classMetrics->getCoverage();
348
$classLoc = $classMetrics->getLoc();
349
$classLocExecutable = $classMetrics->getLocExecutable();
350
$classLocExecuted = $classMetrics->getLocExecuted();
351
$classAif = $classMetrics->getAIF();
352
$classAhf = $classMetrics->getAHF();
353
$classCis = $classMetrics->getCIS();
354
$classCsz = $classMetrics->getCSZ();
355
$classDit = $classMetrics->getDIT();
356
$classImpl = $classMetrics->getIMPL();
357
$classMif = $classMetrics->getMIF();
358
$classMhf = $classMetrics->getMHF();
359
$classNoc = $classMetrics->getNOC();
360
$classPf = $classMetrics->getPF();
361
$classVars = $classMetrics->getVARS();
362
$classVarsnp = $classMetrics->getVARSnp();
363
$classVarsi = $classMetrics->getVARSi();
364
$classWmc = $classMetrics->getWMC();
365
$classWmcnp = $classMetrics->getWMCnp();
366
$classWmci = $classMetrics->getWMCi();
368
$stmtInsertClass->bindParam(':runId', $runId, PDO::PARAM_INT);
369
$stmtInsertClass->bindParam(':classId', $classId, PDO::PARAM_INT);
370
$stmtInsertClass->bindParam(':coverage', $classCoverage);
371
$stmtInsertClass->bindParam(':loc', $classLoc, PDO::PARAM_INT);
372
$stmtInsertClass->bindParam(':locExecutable', $classLocExecutable, PDO::PARAM_INT);
373
$stmtInsertClass->bindParam(':locExecuted', $classLocExecuted, PDO::PARAM_INT);
374
$stmtInsertClass->bindParam(':aif', $classAif);
375
$stmtInsertClass->bindParam(':ahf', $classAhf);
376
$stmtInsertClass->bindParam(':cis', $classCis, PDO::PARAM_INT);
377
$stmtInsertClass->bindParam(':csz', $classCsz, PDO::PARAM_INT);
378
$stmtInsertClass->bindParam(':dit', $classDit, PDO::PARAM_INT);
379
$stmtInsertClass->bindParam(':impl', $classImpl, PDO::PARAM_INT);
380
$stmtInsertClass->bindParam(':mif', $classMif);
381
$stmtInsertClass->bindParam(':mhf', $classMhf);
382
$stmtInsertClass->bindParam(':noc', $classNoc, PDO::PARAM_INT);
383
$stmtInsertClass->bindParam(':pf', $classPf);
384
$stmtInsertClass->bindParam(':vars', $classVars, PDO::PARAM_INT);
385
$stmtInsertClass->bindParam(':varsnp', $classVarsnp, PDO::PARAM_INT);
386
$stmtInsertClass->bindParam(':varsi', $classVarsi, PDO::PARAM_INT);
387
$stmtInsertClass->bindParam(':wmc', $classWmc, PDO::PARAM_INT);
388
$stmtInsertClass->bindParam(':wmcnp', $classWmcnp, PDO::PARAM_INT);
389
$stmtInsertClass->bindParam(':wmci', $classWmci, PDO::PARAM_INT);
390
$stmtInsertClass->execute();
392
foreach ($classMetrics->getMethods() as $methodMetrics) {
393
$methodName = $methodMetrics->getMethod()->getName();
395
$stmtSelectMethodId->bindParam(':className', $className, PDO::PARAM_STR);
396
$stmtSelectMethodId->bindParam(':methodName', $methodName, PDO::PARAM_STR);
397
$stmtSelectMethodId->bindParam(':revision', $revision, PDO::PARAM_INT);
398
$stmtSelectMethodId->execute();
400
$methodId = (int)$stmtSelectMethodId->fetchColumn();
401
$stmtSelectMethodId->closeCursor();
403
$methodCoverage = $methodMetrics->getCoverage();
404
$methodLoc = $methodMetrics->getLoc();
405
$methodLocExecutable = $methodMetrics->getLocExecutable();
406
$methodLocExecuted = $methodMetrics->getLocExecuted();
407
$methodCcn = $methodMetrics->getCCN();
408
$methodCrap = $methodMetrics->getCrapIndex();
409
$methodNpath = $methodMetrics->getNPath();
411
$stmtInsertMethod->bindParam(':runId', $runId, PDO::PARAM_INT);
412
$stmtInsertMethod->bindParam(':methodId', $methodId, PDO::PARAM_INT);
413
$stmtInsertMethod->bindParam(':coverage', $methodCoverage);
414
$stmtInsertMethod->bindParam(':loc', $methodLoc, PDO::PARAM_INT);
415
$stmtInsertMethod->bindParam(':locExecutable', $methodLocExecutable, PDO::PARAM_INT);
416
$stmtInsertMethod->bindParam(':locExecuted', $methodLocExecuted, PDO::PARAM_INT);
417
$stmtInsertMethod->bindParam(':ccn', $methodCcn, PDO::PARAM_INT);
418
$stmtInsertMethod->bindParam(':crap', $methodCrap);
419
$stmtInsertMethod->bindParam(':npath', $methodNpath, PDO::PARAM_INT);
420
$stmtInsertMethod->execute();
424
unset($stmtSelectFunctionId);
425
unset($stmtInsertFunction);
426
unset($stmtSelectClassId);
427
unset($stmtInsertClass);
428
unset($stmtSelectMethodId);
429
unset($stmtInsertMethod);
431
$stmt = $this->dbh->prepare(
432
'SELECT code_line_id, code_line_covered
434
WHERE code_file_id = :fileId
435
AND code_line_number = :lineNumber;'
438
$stmt2 = $this->dbh->prepare(
440
SET code_line_covered = :lineCovered
441
WHERE code_line_id = :lineId;'
444
$stmt3 = $this->dbh->prepare(
445
'INSERT INTO code_coverage
446
(test_id, code_line_id)
447
VALUES(:testId, :lineId);'
450
for ($lineNumber = 1; $lineNumber <= $fileLoc; $lineNumber++) {
451
$coveringTests = PHPUnit_Util_CodeCoverage::getCoveringTests(
452
$codeCoverage, $fileName, $lineNumber
455
if (is_array($coveringTests)) {
456
$stmt->bindParam(':fileId', $fileId, PDO::PARAM_INT);
457
$stmt->bindParam(':lineNumber', $lineNumber, PDO::PARAM_INT);
460
$codeLineId = (int)$stmt->fetchColumn(0);
461
$oldCoverageFlag = (int)$stmt->fetchColumn(1);
462
$newCoverageFlag = isset($summary[$fileName][$lineNumber]) ? 1 : 0;
464
if (($oldCoverageFlag == 0 && $newCoverageFlag != 0) ||
465
($oldCoverageFlag < 0 && $newCoverageFlag > 0)) {
466
$stmt2->bindParam(':lineCovered', $newCoverageFlag, PDO::PARAM_INT);
467
$stmt2->bindParam(':lineId', $codeLineId, PDO::PARAM_INT);
471
foreach ($coveringTests as $test) {
472
$stmt3->bindParam(':testId', $test->__db_id, PDO::PARAM_INT);
473
$stmt3->bindParam(':lineId', $codeLineId, PDO::PARAM_INT);
484
$stmt = $this->dbh->prepare(
485
'SELECT code_method.code_method_id
486
FROM code_class, code_method
487
WHERE code_class.code_class_id = code_method.code_class_id
488
AND code_class.code_class_name = :className
489
AND code_method.code_method_name = :methodName;'
492
$stmt2 = $this->dbh->prepare(
494
SET code_method_id = :methodId
495
WHERE test_id = :testId;'
498
foreach ($result->topTestSuite() as $test) {
499
if ($test instanceof PHPUnit_Framework_TestCase) {
500
$className = get_class($test);
501
$methodName = $test->getName();
503
$stmt->bindParam(':className', $className, PDO::PARAM_STR);
504
$stmt->bindParam(':methodName', $methodName, PDO::PARAM_STR);
507
$methodId = (int)$stmt->fetchColumn();
508
$stmt->closeCursor();
510
$stmt2->bindParam(':methodId', $methodId, PDO::PARAM_INT);
511
$stmt2->bindParam(':testId', $test->__db_id, PDO::PARAM_INT);
519
$stmt = $this->dbh->prepare(
520
'INSERT INTO metrics_project
521
(run_id, metrics_project_cls, metrics_project_clsa,
522
metrics_project_clsc, metrics_project_roots,
523
metrics_project_leafs, metrics_project_interfs,
524
metrics_project_maxdit)
525
VALUES(:runId, :cls, :clsa, :clsc, :roots, :leafs,
529
$cls = $projectMetrics->getCLS();
530
$clsa = $projectMetrics->getCLSa();
531
$clsc = $projectMetrics->getCLSc();
532
$interfs = $projectMetrics->getInterfs();
533
$roots = $projectMetrics->getRoots();
534
$leafs = $projectMetrics->getLeafs();
535
$maxDit = $projectMetrics->getMaxDit();
537
$stmt->bindParam(':runId', $runId, PDO::PARAM_INT);
538
$stmt->bindParam(':cls', $cls, PDO::PARAM_INT);
539
$stmt->bindParam(':clsa', $clsa, PDO::PARAM_INT);
540
$stmt->bindParam(':clsc', $clsc, PDO::PARAM_INT);
541
$stmt->bindParam(':roots', $roots, PDO::PARAM_INT);
542
$stmt->bindParam(':leafs', $leafs, PDO::PARAM_INT);
543
$stmt->bindParam(':interfs', $interfs, PDO::PARAM_INT);
544
$stmt->bindParam(':maxdit', $maxDit, PDO::PARAM_INT);
549
$stmt = $this->dbh->prepare(
551
SET code_class_parent_id = :parentClassId
552
WHERE code_class_id = :classId;'
555
$stmt2 = $this->dbh->prepare(
556
'SELECT code_class.code_class_id as code_class_id
557
FROM code_class, code_file
558
WHERE code_class.code_file_id = code_file.code_file_id
559
AND code_file.revision = :revision
560
AND code_class.code_class_name = :parentClassName;'
563
foreach ($storedClasses as $className => $classId) {
564
$class = new ReflectionClass($className);
565
$parentClass = $class->getParentClass();
567
if ($parentClass !== FALSE) {
568
$parentClassName = $parentClass->getName();
571
if (isset($storedClasses[$parentClassName])) {
572
$parentClassId = $storedClasses[$parentClassName];
574
$stmt2->bindParam(':parentClassName', $parentClassName, PDO::PARAM_STR);
575
$stmt2->bindParam(':revision', $revision, PDO::PARAM_INT);
578
$parentClassId = (int)$stmt2->fetchColumn();
579
$stmt2->closeCursor();
582
if ($parentClassId > 0) {
583
$stmt->bindParam(':classId', $classId, PDO::PARAM_INT);
584
$stmt->bindParam(':parentClassId', $parentClassId, PDO::PARAM_INT);
593
$this->dbh->commit();
b'\\ No newline at end of file'