1+ #!/usr/bin/env php
2+ <?php
3+
4+ declare (strict_types=1 );
5+
6+ use Doctrine \ORM \EntityManager ;
7+ use Light \Blog \Entity \Post ;
8+
9+ chdir (__DIR__ . '/../ ' );
10+
11+ require 'vendor/autoload.php ' ;
12+
13+ $ templatesDir = 'src/Blog/templates/page/blog-resource ' ;
14+ $ uploadsDir = 'public/uploads ' ;
15+ $ articleDir = $ uploadsDir . '/article ' ;
16+ $ limit = null ;
17+
18+ if (isset ($ argv [1 ])) {
19+ if (! ctype_digit ($ argv [1 ]) || (int ) $ argv [1 ] < 1 ) {
20+ fwrite (STDERR , sprintf ("Invalid file limit '%s'. Expected a positive integer.%s " , $ argv [1 ], PHP_EOL ));
21+ exit (1 );
22+ }
23+ $ limit = (int ) $ argv [1 ];
24+ }
25+
26+ if (! is_dir ($ templatesDir )) {
27+ fwrite (STDERR , sprintf ("Directory '%s' not found%s " , $ templatesDir , PHP_EOL ));
28+ exit (1 );
29+ }
30+
31+ $ container = require 'config/container.php ' ;
32+ $ entityManager = $ container ->get (EntityManager::class);
33+ $ postRepository = $ entityManager ->getRepository (Post::class);
34+
35+ /**
36+ * Index every file currently under public/uploads (excluding the
37+ * uploads/article destination tree) by basename, so we can locate the
38+ * source file for each image referenced from a template.
39+ *
40+ * @return array<string, string>
41+ */
42+ function indexUploadSources (string $ uploadsDir , string $ articleDir ): array
43+ {
44+ $ index = [];
45+
46+ $ iterator = new RecursiveIteratorIterator (
47+ new RecursiveDirectoryIterator ($ uploadsDir , FilesystemIterator::SKIP_DOTS )
48+ );
49+
50+ foreach ($ iterator as $ file ) {
51+ if (! $ file ->isFile ()) {
52+ continue ;
53+ }
54+
55+ $ path = $ file ->getPathname ();
56+ if (str_starts_with ($ path , $ articleDir . '/ ' )) {
57+ continue ;
58+ }
59+
60+ $ basename = $ file ->getFilename ();
61+ if (! isset ($ index [$ basename ])) {
62+ $ index [$ basename ] = $ path ;
63+ }
64+ }
65+
66+ return $ index ;
67+ }
68+
69+ $ sourceIndex = indexUploadSources ($ uploadsDir , $ articleDir );
70+
71+ // Matches the filename in: asset('uploads/article/' ~ article.id ~ '/filename.ext')
72+ $ pattern = '/~\s*article\.id\s*~\s* \'\/([^ \']+) \'/ ' ;
73+
74+ $ filesProcessed = 0 ;
75+ $ dirsCreated = 0 ;
76+ $ imagesCopied = 0 ;
77+ $ imagesMissing = 0 ;
78+
79+ $ templateIterator = new RecursiveIteratorIterator (
80+ new RecursiveDirectoryIterator ($ templatesDir , FilesystemIterator::SKIP_DOTS )
81+ );
82+
83+ foreach ($ templateIterator as $ file ) {
84+ if ($ limit !== null && $ filesProcessed >= $ limit ) {
85+ break ;
86+ }
87+
88+ if (! $ file ->isFile () || $ file ->getExtension () !== 'twig ' ) {
89+ continue ;
90+ }
91+
92+ $ path = $ file ->getPathname ();
93+ $ slug = preg_replace ('/\.html\.twig$/ ' , '' , $ file ->getFilename ());
94+ $ contents = file_get_contents ($ path );
95+ if ($ contents === false ) {
96+ continue ;
97+ }
98+
99+ preg_match_all ($ pattern , $ contents , $ matches );
100+ $ filenames = array_unique ($ matches [1 ] ?? []);
101+ if ($ filenames === []) {
102+ continue ;
103+ }
104+
105+ $ post = $ postRepository ->findOneBy (['slug ' => $ slug ]);
106+ if ($ post === null ) {
107+ printf ("No Post found for slug '%s' (%s), skipping%s " , $ slug , $ path , PHP_EOL );
108+ continue ;
109+ }
110+
111+ $ filesProcessed ++;
112+
113+ $ targetDir = $ articleDir . '/ ' . $ post ->getId ()->toString ();
114+ if (! is_dir ($ targetDir )) {
115+ if (! mkdir ($ targetDir , 0775 , true ) && ! is_dir ($ targetDir )) {
116+ fwrite (STDERR , sprintf ("Failed to create directory '%s'%s " , $ targetDir , PHP_EOL ));
117+ continue ;
118+ }
119+ $ dirsCreated ++;
120+ }
121+
122+ foreach ($ filenames as $ filename ) {
123+ $ targetPath = $ targetDir . '/ ' . $ filename ;
124+ if (file_exists ($ targetPath )) {
125+ continue ;
126+ }
127+
128+ if (! isset ($ sourceIndex [$ filename ])) {
129+ printf ("Source image '%s' not found for %s%s " , $ filename , $ path , PHP_EOL );
130+ $ imagesMissing ++;
131+ continue ;
132+ }
133+
134+ if (! copy ($ sourceIndex [$ filename ], $ targetPath )) {
135+ fwrite (STDERR , sprintf ("Failed to copy '%s' to '%s'%s " , $ sourceIndex [$ filename ], $ targetPath , PHP_EOL ));
136+ continue ;
137+ }
138+
139+ $ imagesCopied ++;
140+ }
141+ }
142+
143+ printf (
144+ "Done. %d template%s processed, %d director%s created, %d image%s copied, %d missing.%s " ,
145+ $ filesProcessed ,
146+ $ filesProcessed === 1 ? '' : 's ' ,
147+ $ dirsCreated ,
148+ $ dirsCreated === 1 ? 'y ' : 'ies ' ,
149+ $ imagesCopied ,
150+ $ imagesCopied === 1 ? '' : 's ' ,
151+ $ imagesMissing ,
152+ PHP_EOL
153+ );
0 commit comments