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

nette / di / 6739042234

02 Nov 2023 10:31PM UTC coverage: 93.846% (+41.8%) from 52.037%
6739042234

push

github

dg
Option 'class' is allowed again

Partially reverts commit 046f89cc3.

1 of 1 new or added line in 1 file covered. (100.0%)

2257 of 2405 relevant lines covered (93.85%)

0.94 hits per line

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

87.5
/src/DI/ContainerLoader.php
1
<?php
2

3
/**
4
 * This file is part of the Nette Framework (https://nette.org)
5
 * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
6
 */
7

8
declare(strict_types=1);
9

10
namespace Nette\DI;
11

12
use Nette;
13

14

15
/**
16
 * DI container loader.
17
 */
18
class ContainerLoader
19
{
20
        use Nette\SmartObject;
21

22
        /** @var bool */
23
        private $autoRebuild = false;
24

25
        /** @var string */
26
        private $tempDirectory;
27

28

29
        public function __construct(string $tempDirectory, bool $autoRebuild = false)
1✔
30
        {
31
                $this->tempDirectory = $tempDirectory;
1✔
32
                $this->autoRebuild = $autoRebuild;
1✔
33
        }
1✔
34

35

36
        /**
37
         * @param  callable  $generator  function (Nette\DI\Compiler $compiler): string|null
38
         * @param  mixed  $key
39
         */
40
        public function load(callable $generator, $key = null): string
1✔
41
        {
42
                $class = $this->getClassName($key);
1✔
43
                if (!class_exists($class, false)) {
1✔
44
                        $this->loadFile($class, $generator);
1✔
45
                }
46

47
                return $class;
1✔
48
        }
49

50

51
        /**
52
         * @param  mixed  $key
53
         */
54
        public function getClassName($key): string
55
        {
56
                return 'Container_' . substr(md5(serialize($key)), 0, 10);
1✔
57
        }
58

59

60
        private function loadFile(string $class, callable $generator): void
1✔
61
        {
62
                $file = "$this->tempDirectory/$class.php";
1✔
63
                if (!$this->isExpired($file) && (@include $file) !== false) { // @ file may not exist
1✔
64
                        return;
1✔
65
                }
66

67
                Nette\Utils\FileSystem::createDir($this->tempDirectory);
1✔
68

69
                $handle = @fopen("$file.lock", 'c+'); // @ is escalated to exception
1✔
70
                if (!$handle) {
1✔
71
                        throw new Nette\IOException(sprintf("Unable to create file '%s.lock'. %s", $file, Nette\Utils\Helpers::getLastError()));
×
72
                } elseif (!@flock($handle, LOCK_EX)) { // @ is escalated to exception
1✔
73
                        throw new Nette\IOException(sprintf("Unable to acquire exclusive lock on '%s.lock'. %s", $file, Nette\Utils\Helpers::getLastError()));
×
74
                }
75

76
                if (!is_file($file) || $this->isExpired($file, $updatedMeta)) {
1✔
77
                        if (isset($updatedMeta)) {
1✔
78
                                $toWrite["$file.meta"] = $updatedMeta;
×
79
                        } else {
80
                                [$toWrite[$file], $toWrite["$file.meta"]] = $this->generate($class, $generator);
1✔
81
                        }
82

83
                        foreach ($toWrite as $name => $content) {
1✔
84
                                if (file_put_contents("$name.tmp", $content) !== strlen($content) || !rename("$name.tmp", $name)) {
1✔
85
                                        @unlink("$name.tmp"); // @ - file may not exist
×
86
                                        throw new Nette\IOException(sprintf("Unable to create file '%s'.", $name));
×
87
                                } elseif (function_exists('opcache_invalidate')) {
1✔
88
                                        @opcache_invalidate($name, true); // @ can be restricted
1✔
89
                                }
90
                        }
91
                }
92

93
                if ((@include $file) === false) { // @ - error escalated to exception
1✔
94
                        throw new Nette\IOException(sprintf("Unable to include '%s'.", $file));
×
95
                }
96
                flock($handle, LOCK_UN);
1✔
97
        }
1✔
98

99

100
        private function isExpired(string $file, ?string &$updatedMeta = null): bool
1✔
101
        {
102
                if ($this->autoRebuild) {
1✔
103
                        $meta = @unserialize((string) file_get_contents("$file.meta")); // @ - file may not exist
1✔
104
                        $orig = $meta[2] ?? null;
1✔
105
                        return empty($meta[0])
1✔
106
                                || DependencyChecker::isExpired(...$meta)
1✔
107
                                || ($orig !== $meta[2] && $updatedMeta = serialize($meta));
1✔
108
                }
109

110
                return false;
1✔
111
        }
112

113

114
        /** @return array of (code, file[]) */
115
        protected function generate(string $class, callable $generator): array
1✔
116
        {
117
                $compiler = new Compiler;
1✔
118
                $compiler->setClassName($class);
1✔
119
                $code = $generator(...[&$compiler]) ?: $compiler->compile();
1✔
120
                return [
121
                        "<?php\n$code",
1✔
122
                        serialize($compiler->exportDependencies()),
1✔
123
                ];
124
        }
125
}
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