1+ <?php
2+
3+ declare (strict_types=1 );
4+ /**
5+ * SPDX-FileCopyrightText: 2025 LibreCode coop and contributors
6+ * SPDX-License-Identifier: AGPL-3.0-or-later
7+ */
8+
9+ namespace OCA \Libresign \Migration ;
10+
11+ use Closure ;
12+ use OCP \DB \ISchemaWrapper ;
13+ use OCP \DB \QueryBuilder \IQueryBuilder ;
14+ use OCP \DB \Types ;
15+ use OCP \Files \AppData \IAppDataFactory ;
16+ use OCP \Files \IAppData ;
17+ use OCP \IDBConnection ;
18+ use OCP \Migration \IOutput ;
19+ use OCP \Migration \SimpleMigrationStep ;
20+
21+ class Version16002Date20251230120000 extends SimpleMigrationStep {
22+ protected IAppData $ appData ;
23+
24+ public function __construct (
25+ private IDBConnection $ connection ,
26+ private IAppDataFactory $ appDataFactory ,
27+ ) {
28+ $ this ->appData = $ appDataFactory ->get ('libresign ' );
29+ }
30+
31+ #[\Override]
32+ public function preSchemaChange (IOutput $ output , Closure $ schemaClosure , array $ options ): void {
33+ $ this ->backupUserElementTable ();
34+ }
35+
36+ #[\Override]
37+ public function changeSchema (IOutput $ output , Closure $ schemaClosure , array $ options ): ?ISchemaWrapper {
38+ /** @var ISchemaWrapper $schema */
39+ $ schema = $ schemaClosure ();
40+ $ changed = false ;
41+
42+ if ($ schema ->hasTable ('libresign_user_element ' )) {
43+ $ table = $ schema ->getTable ('libresign_user_element ' );
44+ if (!$ table ->hasColumn ('node_id ' )) {
45+ $ table ->addColumn ('node_id ' , Types::BIGINT , [
46+ 'notnull ' => false ,
47+ 'unsigned ' => true ,
48+ ]);
49+ $ changed = true ;
50+ }
51+
52+ if ($ table ->hasColumn ('file_id ' )) {
53+ $ table ->dropColumn ('file_id ' );
54+ $ changed = true ;
55+ }
56+ }
57+
58+ return $ changed ? $ schema : null ;
59+ }
60+
61+ private function backupUserElementTable (): void {
62+ $ qb = $ this ->connection ->getQueryBuilder ();
63+ $ qb ->select ('* ' )
64+ ->from ('libresign_user_element ' )
65+ ->orderBy ('id ' );
66+
67+ $ cursor = $ qb ->executeQuery ();
68+ $ row = $ cursor ->fetch ();
69+ if (!$ row ) {
70+ $ cursor ->closeCursor ();
71+ return ;
72+ }
73+
74+ $ folder = $ this ->appData ->getFolder ('/ ' );
75+ $ file = $ folder ->newFile ('backup-table-libresign_user_element_Version16002Date20251230120000.csv ' );
76+ $ fp = $ file ->write ();
77+
78+ fputcsv ($ fp , array_keys ($ row ));
79+ fputcsv ($ fp , $ row );
80+ while ($ row = $ cursor ->fetch ()) {
81+ fputcsv ($ fp , $ row );
82+ }
83+
84+ fclose ($ fp );
85+ $ cursor ->closeCursor ();
86+ }
87+
88+ private function restoreNodeIdsFromBackup (): void {
89+ $ folder = $ this ->appData ->getFolder ('/ ' );
90+ $ filename = 'backup-table-libresign_user_element_Version16002Date20251230120000.csv ' ;
91+ if (!$ folder ->fileExists ($ filename )) {
92+ return ;
93+ }
94+
95+ $ file = $ folder ->getFile ($ filename );
96+ $ handle = $ file ->read ();
97+ if ($ handle === false ) {
98+ return ;
99+ }
100+
101+ $ header = fgetcsv ($ handle );
102+ if ($ header === false ) {
103+ fclose ($ handle );
104+ return ;
105+ }
106+
107+ $ columnIndex = array_flip ($ header );
108+ if (!isset ($ columnIndex ['id ' ]) || !isset ($ columnIndex ['file_id ' ])) {
109+ fclose ($ handle );
110+ return ;
111+ }
112+
113+ while (($ row = fgetcsv ($ handle )) !== false ) {
114+ if (!isset ($ row [$ columnIndex ['id ' ]])) {
115+ continue ;
116+ }
117+
118+ $ userElementId = (int ) $ row [$ columnIndex ['id ' ]];
119+ $ nodeId = $ row [$ columnIndex ['file_id ' ]] ?? null ;
120+ if ($ nodeId === null || $ nodeId === '' ) {
121+ continue ;
122+ }
123+
124+ $ qb = $ this ->connection ->getQueryBuilder ();
125+ $ qb ->update ('libresign_user_element ' )
126+ ->set ('node_id ' , $ qb ->createNamedParameter ((int ) $ nodeId , IQueryBuilder::PARAM_INT ))
127+ ->where ($ qb ->expr ()->eq ('id ' , $ qb ->createNamedParameter ($ userElementId , IQueryBuilder::PARAM_INT )));
128+
129+ $ qb ->executeStatement ();
130+ }
131+
132+ fclose ($ handle );
133+ }
134+
135+ #[\Override]
136+ public function postSchemaChange (IOutput $ output , Closure $ schemaClosure , array $ options ): void {
137+ $ this ->restoreNodeIdsFromBackup ();
138+ }
139+
140+ }
0 commit comments