2
2
3
3
namespace PHPStan \DependencyInjection ;
4
4
5
+ use DirectoryIterator ;
5
6
use Nette \DI \Config \Loader ;
6
7
use Nette \DI \Container as OriginalNetteContainer ;
7
8
use Nette \DI \ContainerLoader ;
8
9
use PHPStan \File \CouldNotReadFileException ;
10
+ use PHPStan \File \CouldNotWriteFileException ;
11
+ use PHPStan \File \FileReader ;
12
+ use PHPStan \File \FileWriter ;
9
13
use function array_keys ;
14
+ use function count ;
10
15
use function error_reporting ;
16
+ use function explode ;
17
+ use function implode ;
18
+ use function in_array ;
19
+ use function is_dir ;
20
+ use function is_file ;
11
21
use function restore_error_handler ;
12
22
use function set_error_handler ;
13
23
use function sha1_file ;
24
+ use function sprintf ;
25
+ use function str_ends_with ;
26
+ use function substr ;
27
+ use function time ;
28
+ use function trim ;
29
+ use function unlink ;
14
30
use const E_USER_DEPRECATED ;
15
31
use const PHP_RELEASE_VERSION ;
16
32
use const PHP_VERSION_ID ;
@@ -21,7 +37,7 @@ final class Configurator extends \Nette\Bootstrap\Configurator
21
37
/** @var string[] */
22
38
private array $ allConfigFiles = [];
23
39
24
- public function __construct (private LoaderFactory $ loaderFactory )
40
+ public function __construct (private LoaderFactory $ loaderFactory, private bool $ journalContainer )
25
41
{
26
42
parent ::__construct ();
27
43
}
@@ -59,10 +75,104 @@ public function loadContainer(): string
59
75
$ this ->staticParameters ['debugMode ' ],
60
76
);
61
77
62
- return $ loader ->load (
78
+ $ className = $ loader ->load (
63
79
[$ this , 'generateContainer ' ],
64
80
[$ this ->staticParameters , array_keys ($ this ->dynamicParameters ), $ this ->configs , PHP_VERSION_ID - PHP_RELEASE_VERSION , NeonAdapter::CACHE_KEY , $ this ->getAllConfigFilesHashes ()],
65
81
);
82
+
83
+ if ($ this ->journalContainer ) {
84
+ $ this ->journal ($ className );
85
+ }
86
+
87
+ return $ className ;
88
+ }
89
+
90
+ private function journal (string $ currentContainerClassName ): void
91
+ {
92
+ $ directory = $ this ->getContainerCacheDirectory ();
93
+ if (!is_dir ($ directory )) {
94
+ return ;
95
+ }
96
+
97
+ $ journalFile = $ directory . '/container.journal ' ;
98
+ if (!is_file ($ journalFile )) {
99
+ try {
100
+ FileWriter::write ($ journalFile , sprintf ("%s:%d \n" , $ currentContainerClassName , time ()));
101
+ } catch (CouldNotWriteFileException ) {
102
+ // pass
103
+ }
104
+
105
+ return ;
106
+ }
107
+
108
+ try {
109
+ $ journalContents = FileReader::read ($ journalFile );
110
+ } catch (CouldNotReadFileException ) {
111
+ return ;
112
+ }
113
+
114
+ $ journalLines = explode ("\n" , trim ($ journalContents ));
115
+ $ linesToWrite = [];
116
+ $ usedInTheLastWeek = [];
117
+ $ now = time ();
118
+ $ currentAlreadyInTheJournal = false ;
119
+ foreach ($ journalLines as $ journalLine ) {
120
+ if ($ journalLine === '' ) {
121
+ continue ;
122
+ }
123
+ $ journalLineParts = explode (': ' , $ journalLine );
124
+ if (count ($ journalLineParts ) !== 2 ) {
125
+ return ;
126
+ }
127
+ $ className = $ journalLineParts [0 ];
128
+ $ containerLastUsedTime = (int ) $ journalLineParts [1 ];
129
+
130
+ $ week = 3600 * 24 * 7 ;
131
+
132
+ if ($ containerLastUsedTime + $ week >= $ now ) {
133
+ $ usedInTheLastWeek [] = $ className ;
134
+ }
135
+
136
+ if ($ currentContainerClassName !== $ className ) {
137
+ $ linesToWrite [] = sprintf ('%s:%d ' , $ className , $ containerLastUsedTime );
138
+ continue ;
139
+ }
140
+
141
+ $ linesToWrite [] = sprintf ('%s:%d ' , $ currentContainerClassName , $ now );
142
+ $ currentAlreadyInTheJournal = true ;
143
+ }
144
+
145
+ if (!$ currentAlreadyInTheJournal ) {
146
+ $ linesToWrite [] = sprintf ('%s:%d ' , $ currentContainerClassName , $ now );
147
+ $ usedInTheLastWeek [] = $ currentContainerClassName ;
148
+ }
149
+
150
+ try {
151
+ FileWriter::write ($ journalFile , implode ("\n" , $ linesToWrite ) . "\n" );
152
+ } catch (CouldNotWriteFileException ) {
153
+ return ;
154
+ }
155
+
156
+ foreach (new DirectoryIterator ($ directory ) as $ fileInfo ) {
157
+ if ($ fileInfo ->isDot ()) {
158
+ continue ;
159
+ }
160
+ $ fileName = $ fileInfo ->getFilename ();
161
+ if ($ fileName === 'container.journal ' ) {
162
+ continue ;
163
+ }
164
+ if (!str_ends_with ($ fileName , '.php ' )) {
165
+ continue ;
166
+ }
167
+ $ fileClassName = substr ($ fileName , 0 , -4 );
168
+ if (in_array ($ fileClassName , $ usedInTheLastWeek , true )) {
169
+ continue ;
170
+ }
171
+ $ basePathname = $ fileInfo ->getPathname ();
172
+ @unlink ($ basePathname );
173
+ @unlink ($ basePathname . '.lock ' );
174
+ @unlink ($ basePathname . '.meta ' );
175
+ }
66
176
}
67
177
68
178
public function createContainer (bool $ initialize = true ): OriginalNetteContainer
0 commit comments