source: spip-zone/_plugins_/migrateur/dev-by-http/class/Client/Action/SyncDirectory.php @ 88474

Last change on this file since 88474 was 88474, checked in by marcimat@…, 5 years ago

On permet de transmettre une option de 'test' sur la synchronisation de fichier, qui liste des différence, mais ne fait pas d'action.

Exemple :

<pre>
'mig_sync' => ["Synchroniser le répertoire IMG", [

"repertoire" => "IMG",
"test" => true

]],
</pre>

File size: 4.5 KB
Line 
1<?php
2
3namespace SPIP\Migrateur\Client\Action;
4
5
6
7class SyncDirectory extends ActionBase {
8
9
10        private $directory = ''; // IMG
11        private $path = '';      // chemin/vers/IMG
12        private $test = false;
13
14
15        public function run($data = null) {
16
17                if (is_array($data)) {
18                        $data += array(
19                                'repertoire' => '',
20                                'test' => false
21                        );
22                        $this->directory = $data['repertoire'];
23                        $this->test = $data['test'];
24                } else {
25                        $this->directory = $data;
26                }
27
28                if (!$this->directory) {
29                        return "Aucun répertoire indiqué.";
30                }
31
32                $this->log_run("Sync Répertoire <em>$this->directory</em>" . ($this->test ? " [Test]" : ""));
33
34                // calcul du chemin complet
35                $path = rtrim($this->directory, '/') . DIRECTORY_SEPARATOR;
36                $this->path = $this->destination->dir . DIRECTORY_SEPARATOR . $path;
37                unset($path);
38
39
40                spip_timer('list');
41                $localFiles = $this->destination->getFileList($this->directory);
42                $t = spip_timer('list');
43                $n = count($localFiles);
44                if ($n > 1) {
45                        $this->log("$n fichiers locaux avant synchro. ($t)");
46                } else {
47                        $this->log("$n fichier local avant synchro. ($t)");
48                }
49
50                $data = array(
51                        'directory' => $this->directory,
52                        'files' => $localFiles,
53                );
54
55                spip_timer('list');
56                $reponse = $this->client->ask('SyncDirectory', $data, 'json');
57                $t = spip_timer('list');
58
59                if (empty($reponse['message']['data']['files'])) {
60                        return $reponse;
61                }
62
63                $files = $reponse['message']['data']['files'];
64                $this->log("Réception de la liste des fichiers ($t)");
65                $this->log("- " . count($files['new']) . " nouveaux fichiers");
66                $this->log("- " . count($files['updated']) . " à mettre à jour");
67                $this->log("- " . count($files['deleted']) . " à supprimer");
68                $this->log("Estimation des transferts : " . $reponse['message']['data']['downloadSize']);
69
70                // en mode test, on ne fait pas de modifications.
71                if (!$this->test) {
72                        $this->delete($files['deleted']);
73                        $this->download($files['new'] + $files['updated']);
74                }
75
76                return $reponse;
77        }
78
79
80        /**
81         * Supprime tous les fichiers indiqués
82         *
83         * @paraam array $files Liste des fichiers
84        **/
85        private function delete($files) {
86                if (count($files)) {
87                        $this->log_run("Suppression de " . count($files) . " fichier(s)");
88                        foreach ($files as $filePath => $info) {
89                                unlink($this->path . DIRECTORY_SEPARATOR . $filePath);
90                        }
91                }
92        }
93
94        /**
95         * Télécharge tous les fichiers indiqués
96         *
97         * Comme on vérifie que le fichier reçu est correct, on demande
98         * à calculer les sha256 des fichiers à télécharger.
99         *
100         * On en demande pour 100Mo ou 100 fichiers car ces calculs peuvent
101         * être un peu long
102         *
103         * @paraam array $files Liste des fichiers
104        **/
105        private function download($files) {
106                if (count($files)) {
107                        $this->log_run("Téléchargement de " . count($files) . " fichier(s)");
108
109                        $nb = $size = 0;
110                        $slice = array();
111
112                        foreach ($files as $filePath => $info) {
113                                $nb++;
114                                $size += $info[0];
115                                $slice[$filePath] = $info;
116                                unset($files[$filePath]);
117
118                                if ($nb >= 100 OR $size >= 100*1000*1000) {
119                                        if (!$this->downloadSlice($slice)) {
120                                                return false;
121                                        }
122                                        $size = $nb = 0;
123                                        $slice = array();
124                                }
125                        }
126
127                        // le reste
128                        if (count($slice)) {
129                                return $this->downloadSlice($slice);
130                        }
131                }
132
133                return true;
134        }
135
136
137        /**
138         * Télécharge tous les fichiers indiqués
139         *
140         * Demande la liste des hash des fichiers indiqués,
141         * puis les télécharge un par un et vérifie les hash.
142         *
143         * @paraam array $files Liste des fichiers
144         * @return bool true si OK
145        **/
146        private function downloadSlice($files) {
147                if (!$files) {
148                        return false;
149                }
150                if (!$files = $this->getHash($files)) {
151                        return false;
152                }
153
154                foreach ($files as $filePath => $info) {
155                        $reponse = $this->client->action('GetFile', array(
156                                'fichier' => $this->directory . DIRECTORY_SEPARATOR. $filePath,
157                                'hash' => $info[2],
158                        ));
159
160                        if (!$reponse) {
161                                migrateur_log("Échec de récupération du fichier");
162                                return false;
163                        }
164
165                        // update modified time to match server
166                        touch($this->path . DIRECTORY_SEPARATOR. $filePath, $info[1]);
167                }
168
169                return true;
170        }
171
172
173
174        /**
175         * Récupère les hash de tous les fichiers indiqués
176         *
177         * @paraam array $files Liste des fichiers
178         * @return array|false
179         *    - Liste filePath => hash
180         *    - false si erreur.
181        **/
182        private function getHash($files) {
183                $this->log_run("Demande de hash pour " . count($files) . " fichiers");
184                $data = array(
185                        'directory' => $this->directory,
186                        'files' => $files
187                );
188                $reponse = $this->client->ask('HashFiles', $data, 'json');
189
190                if (!is_array($reponse)) {
191                        return false;
192                }
193
194                return $reponse['message']['data']['files'];
195        }
196
197}
Note: See TracBrowser for help on using the repository browser.