dolibarr 22.0.5
buildzip.php
1#!/usr/bin/env php -d memory_limit=256M
2<?php
22/*
23 The goal of that php CLI script is to make zip package of your module
24 as an alternative to web "build zip" or "perl script makepack"
25*/
26
27// ============================================= configuration
28
34$listOfModuleContent = [
35 'admin',
36 'ajax',
37 'backport',
38 'class',
39 'css',
40 'COPYING',
41 'core',
42 'img',
43 'js',
44 'langs',
45 'lib',
46 'sql',
47 'tpl',
48 '*.md',
49 '*.json',
50 '*.php',
51 'modulebuilder.txt',
52];
53
59$exclude_list = [
60 '/^.git$/',
61 '/.*js.map/',
62 '/DEV.md/'
63];
64
65// ============================================= end of configuration
66
72function detectModule()
73{
74 $name = $version = "";
75 $tab = glob("core/modules/mod*.class.php");
76 if (count($tab) == 0) {
77 echo "[fail] Error on auto detect data : there is no mod*.class.php file into core/modules dir\n";
78 exit(-1);
79 }
80 if (count($tab) == 1) {
81 $file = $tab[0];
82 $pattern = "/.*mod(?<mod>.*)\.class\.php/";
83 if (preg_match_all($pattern, $file, $matches)) {
84 $name = strtolower(reset($matches['mod']));
85 }
86
87 echo "extract data from $file\n";
88 if (!file_exists($file) || $name == "") {
89 echo "[fail] Error on auto detect data\n";
90 exit(-2);
91 }
92 } else {
93 echo "[fail] Error there is more than one mod*.class.php file into core/modules dir\n";
94 exit(-3);
95 }
96
97 //extract version from file
98 $contents = file_get_contents($file);
99 $pattern = "/^.*this->version\s*=\s*'(?<version>.*)'\s*;.*\$/m";
100
101 // search, and store all matching occurrences in $matches
102 if (preg_match_all($pattern, $contents, $matches)) {
103 $version = reset($matches['version']);
104 }
105
106 if (version_compare($version, '0.0.1', '>=') != 1) {
107 echo "[fail] Error auto extract version fail\n";
108 exit(-4);
109 }
110
111 echo "module name = $name, version = $version\n";
112 return [(string) $name, (string) $version];
113}
114
122function delTree($dir)
123{
124 $files = array_diff(scandir($dir), array('.', '..'));
125 foreach ($files as $file) {
126 (is_dir("$dir/$file")) ? delTree("$dir/$file") : secureUnlink("$dir/$file");
127 }
128 return rmdir($dir);
129}
130
131
140function secureUnlink($path)
141{
142 if (file_exists($path)) {
143 if (unlink($path)) {
144 //then check if really deleted
145 clearstatcache();
146 if (file_exists($path)) { // @phpstan-ignore-line
147 echo "[fail] unlink of $path fail !\n";
148 exit(-5);
149 }
150 } else {
151 echo "[fail] unlink of $path fail !\n";
152 exit(-6);
153 }
154 }
155 return true;
156}
157
165function mkdirAndCheck($path)
166{
167 if (mkdir($path)) {
168 clearstatcache();
169 if (is_dir($path)) {
170 return true;
171 }
172 }
173 echo "[fail] Error on $path (mkdir)\n";
174 exit(7);
175}
176
184function is_excluded($filename)
185{
186 global $exclude_list;
187 $count = 0;
188 $notused = preg_filter($exclude_list, '1', $filename, -1, $count);
189 if ($count > 0) {
190 echo " - exclude $filename\n";
191 return true;
192 }
193 return false;
194}
195
204function rcopy($src, $dst)
205{
206 if (is_dir($src)) {
207 // Make the destination directory if not exist
208 mkdirAndCheck($dst);
209 // open the source directory
210 $dir = opendir($src);
211
212 // Loop through the files in source directory
213 while ($file = readdir($dir)) {
214 if (($file != '.') && ($file != '..')) {
215 if (is_dir($src . '/' . $file)) {
216 // Recursively calling custom copy function
217 // for sub directory
218 if (!rcopy($src . '/' . $file, $dst . '/' . $file)) {
219 return false;
220 }
221 } else {
222 if (!is_excluded($file)) {
223 if (!copy($src . '/' . $file, $dst . '/' . $file)) {
224 return false;
225 }
226 }
227 }
228 }
229 }
230 closedir($dir);
231 } elseif (is_file($src)) {
232 if (!is_excluded($src)) {
233 if (!copy($src, $dst)) {
234 return false;
235 }
236 }
237 }
238 return true;
239}
240
251function zipDir($folder, &$zip, $root = "")
252{
253 foreach (new \DirectoryIterator($folder) as $f) {
254 if ($f->isDot()) {
255 continue;
256 } //skip . ..
257 $src = $folder . '/' . $f;
258 $dst = substr($f->getPathname(), strlen($root));
259 if ($f->isDir()) {
260 if ($zip->addEmptyDir($dst)) {
261 if (zipDir($src, $zip, $root)) {
262 continue;
263 } else {
264 return false;
265 }
266 } else {
267 return false;
268 }
269 }
270 if ($f->isFile()) {
271 if (! $zip->addFile($src, $dst)) {
272 return false;
273 }
274 }
275 }
276 return true;
277}
278
283list($mod, $version) = detectModule();
284$outzip = sys_get_temp_dir() . "/module_" . $mod . "-" . $version . ".zip";
285if (file_exists($outzip)) {
286 secureUnlink($outzip);
287}
288
289//copy all sources into system temp directory
290$tmpdir = tempnam(sys_get_temp_dir(), $mod . "-module");
291secureUnlink($tmpdir);
292mkdirAndCheck($tmpdir);
293$dst = $tmpdir . "/" . $mod;
294mkdirAndCheck($dst);
295
296foreach ($listOfModuleContent as $moduleContent) {
297 foreach (glob($moduleContent) as $entry) {
298 if (!rcopy($entry, $dst . '/' . $entry)) {
299 echo "[fail] Error on copy " . $entry . " to " . $dst . "/" . $entry . "\n";
300 echo "Please take time to analyze the problem and fix the bug\n";
301 exit(-8);
302 }
303 }
304}
305
306$z = new ZipArchive();
307$z->open($outzip, ZIPARCHIVE::CREATE);
308zipDir($tmpdir, $z, $tmpdir . '/');
309$z->close();
310delTree($tmpdir);
311if (file_exists($outzip)) {
312 echo "[success] module archive is ready : $outzip ...\n";
313} else {
314 echo "[fail] build zip error\n";
315 exit(-9);
316}