99
1010namespace OCA \PreviewGenerator \Command ;
1111
12- use OC \DB \Exceptions \DbalException ;
13- use OCA \PreviewGenerator \Service \NoMediaService ;
14- use OCA \PreviewGenerator \SizeHelper ;
15- use OCP \AppFramework \Db \TTransactional ;
16- use OCP \AppFramework \Utility \ITimeFactory ;
17- use OCP \DB \Exception ;
18- use OCP \Encryption \IManager ;
19- use OCP \Files \File ;
20- use OCP \Files \GenericFileException ;
21- use OCP \Files \IRootFolder ;
22- use OCP \Files \NotFoundException ;
23- use OCP \IConfig ;
24- use OCP \IDBConnection ;
25- use OCP \IPreview ;
26- use OCP \IUserManager ;
12+ use OCA \PreviewGenerator \Exceptions \EncryptionEnabledException ;
13+ use OCA \PreviewGenerator \Service \PreGenerateService ;
2714use Symfony \Component \Console \Command \Command ;
2815use Symfony \Component \Console \Input \InputInterface ;
2916use Symfony \Component \Console \Output \OutputInterface ;
3017
3118class PreGenerate extends Command {
32- use TTransactional;
33-
34- /* @return array{width: int, height: int, crop: bool} */
35- protected array $ specifications ;
36-
37- protected string $ appName ;
38- protected IUserManager $ userManager ;
39- protected IRootFolder $ rootFolder ;
40- protected IPreview $ previewGenerator ;
41- protected IConfig $ config ;
42- protected IDBConnection $ connection ;
43- protected OutputInterface $ output ;
44- protected IManager $ encryptionManager ;
45- protected ITimeFactory $ time ;
46- protected NoMediaService $ noMediaService ;
47- protected SizeHelper $ sizeHelper ;
48-
49- /**
50- * @param string $appName
51- * @param IRootFolder $rootFolder
52- * @param IUserManager $userManager
53- * @param IPreview $previewGenerator
54- * @param IConfig $config
55- * @param IDBConnection $connection
56- * @param IManager $encryptionManager
57- * @param ITimeFactory $time
58- */
59- public function __construct (string $ appName ,
60- IRootFolder $ rootFolder ,
61- IUserManager $ userManager ,
62- IPreview $ previewGenerator ,
63- IConfig $ config ,
64- IDBConnection $ connection ,
65- IManager $ encryptionManager ,
66- ITimeFactory $ time ,
67- NoMediaService $ noMediaService ,
68- SizeHelper $ sizeHelper ) {
19+ public function __construct (
20+ private readonly PreGenerateService $ preGenerateService ,
21+ ) {
6922 parent ::__construct ();
70-
71- $ this ->appName = $ appName ;
72- $ this ->userManager = $ userManager ;
73- $ this ->rootFolder = $ rootFolder ;
74- $ this ->previewGenerator = $ previewGenerator ;
75- $ this ->config = $ config ;
76- $ this ->connection = $ connection ;
77- $ this ->encryptionManager = $ encryptionManager ;
78- $ this ->time = $ time ;
79- $ this ->noMediaService = $ noMediaService ;
80- $ this ->sizeHelper = $ sizeHelper ;
8123 }
8224
8325 protected function configure (): void {
@@ -87,126 +29,10 @@ protected function configure(): void {
8729 }
8830
8931 protected function execute (InputInterface $ input , OutputInterface $ output ): int {
90- if ($ this ->encryptionManager ->isEnabled ()) {
91- $ output ->writeln ('Encryption is enabled. Aborted. ' );
92- return 1 ;
93- }
94-
95- // Set timestamp output
96- $ formatter = new TimestampFormatter ($ this ->config , $ output ->getFormatter ());
97- $ output ->setFormatter ($ formatter );
98- $ this ->output = $ output ;
99-
100- $ this ->specifications = $ this ->sizeHelper ->generateSpecifications ();
101- if ($ this ->output ->getVerbosity () > OutputInterface::VERBOSITY_VERY_VERBOSE ) {
102- $ output ->writeln ('Specifications: ' . json_encode ($ this ->specifications ));
103- }
104- $ this ->startProcessing ();
105-
106- return 0 ;
107- }
108-
109- private function startProcessing (): void {
110- while (true ) {
111- /*
112- * Get and delete the row so that if preview generation fails for some reason the next
113- * run can just continue. Wrap in transaction to make sure that one row is handled by
114- * one process only.
115- */
116- $ row = $ this ->atomic (function () {
117- $ qb = $ this ->connection ->getQueryBuilder ();
118- $ qb ->select ('* ' )
119- ->from ('preview_generation ' )
120- ->orderBy ('id ' )
121- ->setMaxResults (1 );
122- $ result = $ qb ->executeQuery ();
123- $ row = $ result ->fetch ();
124- $ result ->closeCursor ();
125-
126- if (!$ row ) {
127- return null ;
128- }
129-
130- $ qb = $ this ->connection ->getQueryBuilder ();
131- $ qb ->delete ('preview_generation ' )
132- ->where ($ qb ->expr ()->eq ('id ' , $ qb ->createNamedParameter ($ row ['id ' ])));
133- $ qb ->executeStatement ();
134-
135- return $ row ;
136- }, $ this ->connection );
137-
138-
139- if (!$ row ) {
140- break ;
141- }
142-
143- $ this ->processRow ($ row );
144- }
145- }
146-
147- private function processRow ($ row ): void {
148- //Get user
149- $ user = $ this ->userManager ->get ($ row ['uid ' ]);
150-
151- if ($ user === null ) {
152- return ;
153- }
154-
155- \OC_Util::tearDownFS ();
156- \OC_Util::setupFS ($ row ['uid ' ]);
157-
15832 try {
159- $ userFolder = $ this ->rootFolder ->getUserFolder ($ user ->getUID ());
160- $ userRoot = $ userFolder ->getParent ();
161- } catch (NotFoundException $ e ) {
162- return ;
163- }
164-
165- //Get node
166- $ nodes = $ userRoot ->getById ($ row ['file_id ' ]);
167-
168- if ($ nodes === []) {
169- return ;
170- }
171-
172- $ node = $ nodes [0 ];
173- if ($ node instanceof File) {
174- $ this ->processFile ($ node );
175- }
176- }
177-
178- private function processFile (File $ file ): void {
179- $ absPath = ltrim ($ file ->getPath (), '/ ' );
180- $ pathComponents = explode ('/ ' , $ absPath );
181- if (isset ($ pathComponents [1 ]) && $ pathComponents [1 ] === 'files_trashbin ' ) {
182- return ;
183- }
184-
185- if ($ this ->noMediaService ->hasNoMediaFile ($ file )) {
186- return ;
187- }
188-
189- if ($ this ->previewGenerator ->isMimeSupported ($ file ->getMimeType ())) {
190- if ($ this ->output ->getVerbosity () > OutputInterface::VERBOSITY_VERBOSE ) {
191- $ this ->output ->writeln ('Generating previews for ' . $ file ->getPath ());
192- }
193-
194- try {
195- $ this ->previewGenerator ->generatePreviews ($ file , $ this ->specifications );
196- } catch (NotFoundException $ e ) {
197- // Maybe log that previews could not be generated?
198- } catch (\InvalidArgumentException |GenericFileException $ e ) {
199- $ class = $ e ::class;
200- $ error = $ e ->getMessage ();
201- $ this ->output ->writeln ("<error> {$ class }: {$ error }</error> " );
202- } catch (DbalException $ e ) {
203- // Since the introduction of the oc_previews table, preview duplication caused by
204- // duplicated specifications will cause a UniqueConstraintViolationException. We can
205- // simply ignore this exception here and carry on.
206- if ($ e ->getReason () !== Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION ) {
207- throw $ e ;
208- }
209- }
33+ $ this ->preGenerateService ->preGenerate ($ output );
34+ } catch (EncryptionEnabledException $ e ) {
35+ $ output ->writeln ('<error>Encryption is enabled. Aborted.</error> ' );
21036 }
21137 }
21238}
0 commit comments