Core  3.2
PHP API documentation
 All Data Structures Namespaces Files Functions Variables Pages
Class.Dcp_Utils_WStart.php
Go to the documentation of this file.
1 <?php
2 /*
3  * @author Anakeen
4  * @package FDL
5 */
6 
7 namespace Dcp\Utils;
8 
10  public function wstart_stdout($msg);
11  public function wstart_stderr($msg);
12 }
13 
15 {
16 };
17 
19 {
20  public function wstart_stdout($msg)
21  {
22  return;
23  }
24  public function wstart_stderr($msg)
25  {
26  return;
27  }
28 }
29 
31 {
32  /**
33  * @var WStartStdioInterface
34  */
35  protected $stdio = null;
36  protected $verbose = false;
37  protected $contextRoot = false;
38 
39  public function __construct($contextRoot)
40  {
41  $this->setVerbose(false);
42  $this->setStdio(new WStartDefaultStdio());
44  }
45  protected function setContextRoot($contextRoot)
46  {
47  if (!is_string($contextRoot) || strlen($contextRoot) <= 0) {
48  throw new WStartException(sprintf("contextRoot must not be empty."));
49  }
50  if (!is_dir($contextRoot)) {
51  throw new WStartException(sprintf("contextRoot '%s' is not a directory.", $contextRoot));
52  }
53  if (!is_readable($contextRoot)) {
54  throw new WStartException(sprintf("contextRoot '%s' is not readable.", $contextRoot));
55  }
56  if (!is_writable($contextRoot)) {
57  throw new WStartException(sprintf("contextRoot '%s' is not writable.", $contextRoot));
58  }
59  if (($realContextRoot = realpath($contextRoot)) === false) {
60  throw new WStartException(sprintf("could not get real path from contextRoot '%s'.", $contextRoot));
61  }
62  $this->contextRoot = $realContextRoot;
63  }
64  /**
65  * Scan given directory and delete dead symlinks (i.e. symlinks pointing to non-existing files)
66  *
67  * @param string $dir
68  * @throws WStartException
69  */
70  public function deleteDeadLinks($dir)
71  {
72  if (($dh = opendir($dir)) === false) {
73  throw new WStartException(sprintf("Error opening directory '%s'.", $dir));
74  }
75  while (($file = readdir($dh)) !== false) {
76  if ($file == '.' || $file == '..') {
77  continue;
78  }
79  $absLink = $this->absolutize($dir . DIRECTORY_SEPARATOR . $file);
80  if (!is_link($absLink)) {
81  continue;
82  }
83  $target = readlink($absLink);
84  if ($target === false) {
85  continue;
86  }
87  if (substr($target, 0, 1) != '/') {
88  $target = dirname($absLink) . DIRECTORY_SEPARATOR . $target;
89  }
90  if (file_exists($target)) {
91  continue;
92  }
93  $this->verbose(2, sprintf("Deleting link '%s' to non-existing file '%s'.\n", $absLink, $target));
94  if (unlink($absLink) === false) {
95  closedir($dh);
96  throw new WStartException(sprintf("Error deleting dead symlink '%s' to '%s'.", $absLink, $target));
97  }
98  }
99  closedir($dh);
100  }
101  /**
102  * Link files from source dir to destination dir.
103  *
104  * @param string $sourceDir Source dir from which files are to be linked
105  * @param string $destDir Destination dir to which the symlinks will be created
106  * @param array $linked List of conflicting/duplicates files (i.e. source files with the same name)
107  * @throws WStartException
108  */
109  public function linkFiles($sourceDir, $destDir, &$linked = array())
110  {
111  $this->verbose(2, sprintf("Processing files from '%s'.\n", $sourceDir));
112  if (($dh = opendir($this->absolutize($sourceDir))) === false) {
113  throw new WStartException(sprintf("Error opening directory '%s'.", $this->absolutize($sourceDir)));
114  }
115  while (($file = readdir($dh)) !== false) {
116  if ($file == '.' || $file == '..') {
117  continue;
118  }
119  $relSourceFile = $this->relativize($sourceDir . DIRECTORY_SEPARATOR . $file);
120  $absSourceFile = $this->absolutize($relSourceFile);
121  if (!is_file($absSourceFile) && !is_dir($absSourceFile)) {
122  continue;
123  }
124  $relTarget = '..' . DIRECTORY_SEPARATOR . $relSourceFile;
125  $absLink = $this->absolutize($destDir . DIRECTORY_SEPARATOR . basename($relSourceFile));
126  if (!isset($linked[$absLink])) {
127  $linked[$absLink] = array();
128  }
129  if (is_link($absLink)) {
130  $source = readlink($absLink);
131  if ($source !== false && $source == $relTarget) {
132  $linked[$absLink][] = $relTarget;
133  continue;
134  }
135  if (unlink($absLink) === false) {
136  closedir($dh);
137  throw new WStartException(sprintf("Error removing symlink '%s'.", $absLink));
138  }
139  }
140  $this->verbose(2, sprintf("Linking '%s' to '%s'.\n", $relTarget, $absLink));
141  if (symlink($relTarget, $absLink) === false) {
142  closedir($dh);
143  throw new WStartException(sprintf("Error symlinking '%s' to '%s'.", $relTarget, $absLink));
144  }
145  $linked[$absLink][] = $relTarget;
146  }
147  closedir($dh);
148  }
149  /**
150  * Create a directory if it does not already exists...
151  *
152  * @param string $dir
153  * @throws WStartException
154  */
155  protected function mkdir($dir)
156  {
157  if (is_dir($dir)) {
158  return;
159  }
160  if (mkdir($dir) === false) {
161  throw new WStartException(sprintf("Error creating directory '%s'.", $dir));
162  }
163  }
164  /**
165  * Remove files matching the specified regex in the given directory
166  *
167  * @param $dir
168  * @param $regex
169  * @throws WStartException
170  */
171  protected function removeFilesByRegex($dir, $regex)
172  {
173  if (($dh = opendir($dir)) === false) {
174  throw new WStartException(sprintf("Error opening directory '%s'.", $dir));
175  }
176  while (($file = readdir($dh)) !== false) {
177  if ($file == '.' || $file == '..') {
178  continue;
179  }
180  $ret = preg_match($regex, $file);
181  if ($ret === false) {
182  closedir($dh);
183  throw new WStartException(sprintf("Malformed regex pattern '%s'.", $regex));
184  }
185  if ($ret === 0) {
186  continue;
187  }
188  $this->verbose(2, sprintf("Removing '%s'.\n", $dir . DIRECTORY_SEPARATOR . $file));
189  if (unlink($dir . DIRECTORY_SEPARATOR . $file) == false) {
190  closedir($dh);
191  throw new WStartException(sprintf("Error removing file '%s'.", $file));
192  }
193  }
194  closedir($dh);
195  }
196  /**
197  * Returns surdirs containing a specific subdir
198  *
199  * @param $subdir
200  * @return string[] list of dir/subdir relative to contextRoot
201  */
202  public function getSubDirs($subdir)
203  {
204  $appImagesDirs = array();
205  if (($dh = opendir($this->contextRoot)) === false) {
206  return $appImagesDirs;
207  }
208  while (($elmt = readdir($dh)) !== false) {
209  if ($elmt == '.' || $elmt == '..') {
210  continue;
211  }
212  if ($elmt === 'supervisor') {
213  continue;
214  }
215  if (!is_dir($this->absolutize($elmt))) {
216  continue;
217  }
218  if (!is_dir($this->absolutize($elmt . DIRECTORY_SEPARATOR . $subdir))) {
219  continue;
220  }
221  $appImagesDirs[] = $elmt . DIRECTORY_SEPARATOR . $subdir;
222  }
223  closedir($dh);
224  return $appImagesDirs;
225  }
226  public function getImagesDirs()
227  {
228  return $this->getSubDirs('Images');
229  }
230  public function getDocsDirs()
231  {
232  return $this->getSubDirs('Docs');
233  }
234  protected function debug($msg)
235  {
236  $this->stdio->wstart_stderr($msg);
237  }
238  /**
239  * Print a message with the specified verbose level.
240  *
241  * @param $level
242  * @param $msg
243  */
244  protected function verbose($level, $msg)
245  {
246  if ($this->verbose <= 0) {
247  return;
248  }
249  if ($level <= $this->verbose) {
250  $this->stdio->wstart_stdout($msg);
251  }
252  }
253  /**
254  * @param int $verbose Verbose level (e.g. 1, 2, etc.)
255  * @return bool
256  */
257  public function setVerbose($verbose)
258  {
259  $previous = $this->verbose;
260  $this->verbose = (int)$verbose;
261  return $previous;
262  }
263  /**
264  * @param $stdio
265  * @return WStartStdioInterface
266  * @throws WStartException
267  */
268  public function setStdio($stdio)
269  {
270  if (!is_a($stdio, '\Dcp\Utils\WStartStdioInterface')) {
271  throw new WStartException(sprintf("Wrong class for stdioInterface: %s", get_class($stdio)));
272  }
273  $previous = $this->stdio;
274  $this->stdio = $stdio;
275  return $previous;
276  }
277  /**
278  * Compute absolute path from context's root
279  *
280  * - If the file is relative, then the absolute path is computed relative to the context's root.
281  * - If the file is already in a absolute form, then their current absolute form is used.
282  *
283  * @param $file
284  * @return string
285  */
286  public function absolutize($file)
287  {
288  if (substr($file, 0, 1) != '/') {
289  $file = $this->contextRoot . DIRECTORY_SEPARATOR . $file;
290  }
291  return $file;
292  }
293  /**
294  * Compute relative path from context's root
295  *
296  * - If the file is already in a relative form, then their current relative form is used.
297  * - If the file is absolute and located under the context'root, then the relative path from the context's root is
298  * used.
299  * - If the file is absolute and located outside the context's root, then an exception is thrown.
300  *
301  * @param $file
302  * @return string
303  * @throws WStartException
304  */
305  public function relativize($file)
306  {
307  if (substr($file, 0, 1) != '/') {
308  return $file;
309  }
310  if ($file == $this->contextRoot) {
311  return '.';
312  }
313  if (strpos($file, $this->contextRoot . DIRECTORY_SEPARATOR) === 0) {
314  $file = substr($file, strlen($this->contextRoot . DIRECTORY_SEPARATOR));
315  if ($file == '') {
316  $file = '.';
317  }
318  return $file;
319  }
320  throw new WStartException(sprintf("Could not relativize '%s' to '%s'.", $file, $this->contextRoot));
321  }
322  /**
323  * @param $file
324  * @param $callback
325  * @throws WStartException
326  */
327  public function sedFile($file, $callback)
328  {
329  if (($perms = fileperms($file)) === false) {
330  throw new WStartException(sprintf("Error reading permissions for '%s'.", $file));
331  }
332  $content = file_get_contents($file);
333  if ($content === false) {
334  throw new WStartException(sprintf("Error reading content from '%s'.", $file));
335  }
336  $content = call_user_func_array($callback, array(
337  $content
338  ));
339  $tmpFile = tempnam(getTmpDir() , 'sedFile');
340  if ($tmpFile === false) {
341  throw new WStartException(sprintf("Error creating temporary file."));
342  }
343  if (file_put_contents($tmpFile, $content) === false) {
344  unlink($tmpFile);
345  throw new WStartException(sprintf("Error writing content to temporary file '%s'.", $tmpFile));
346  }
347  if (rename($tmpFile, $file) === false) {
348  unlink($tmpFile);
349  throw new WStartException(sprintf("Error renaming '%s' to '%s'.", $tmpFile, $file));
350  }
351  /* Replicate original rights with extended rights */
352  $perms = $perms & 07777;
353  if (chmod($file, $perms) === false) {
354  throw new WStartException(sprintf("Error applying permissions '%o' to '%s'.", $perms, $file));
355  }
356  }
357 }
358 
359 class WStart extends WStartInternals
360 {
361  /**
362  *
363  */
364  public function clearAutoloadCache()
365  {
366  $this->verbose(1, sprintf("[+] Re-generating class autoloader.\n"));
367  require_once sprintf('%s/WHAT/classAutoloader.php', $this->contextRoot);
369  $this->verbose(1, sprintf("[+] Done.\n"));
370  }
371  /**
372  * @throws WStartException
373  */
374  public function imageAndDocsLinks()
375  {
376  $this->verbose(1, sprintf("[+] Re-generating Images and Docs symlinks.\n"));
377  $linked = array();
378  /* Images */
379  $imagesDir = $this->absolutize('Images');
380  $this->mkdir($imagesDir);
381  $dirs = $this->getImagesDirs();
382  foreach ($dirs as $dir) {
383  $this->linkFiles($dir, $imagesDir, $linked);
384  }
385  $this->deleteDeadLinks($imagesDir);
386  /* Docs */
387  $docsDir = $this->absolutize('Docs');
388  $this->mkdir($docsDir);
389  $dirs = $this->getDocsDirs();
390  foreach ($dirs as $dir) {
391  $this->linkFiles($dir, $this->contextRoot . DIRECTORY_SEPARATOR . 'Docs', $linked);
392  }
393  $this->deleteDeadLinks($docsDir);
394  /* Check for conflicts */
395  foreach ($linked as $link => $targetList) {
396  if (count($targetList) <= 1) {
397  continue;
398  }
399  $targets = join(', ', $targetList);
400  $this->debug(sprintf("WARNING: symlink '%s' has multiple targets: %s\n", $link, $targets));
401  }
402  $this->verbose(1, sprintf("[+] Done.\n"));
403  }
404  /**
405  * @throws WStartException
406  */
407  public function clearFileCache()
408  {
409  $this->verbose(1, sprintf("[+] Clearing cached content.\n"));
410  $cacheDir = $this->absolutize('var' . DIRECTORY_SEPARATOR . 'cache' . DIRECTORY_SEPARATOR . 'image');
411  $this->removeFilesByRegex($cacheDir, '/(?:png|gif|xml|src)$/');
412  $this->verbose(1, sprintf("[+] Done.\n"));
413  }
414  /**
415  * @throws WStartException
416  */
417  public function refreshJsVersion()
418  {
419  $this->verbose(1, sprintf("[+] Incrementing WVERSION.\n"));
420  $cmd = sprintf("%s/wsh.php --api=refreshjsversion 2>&1", escapeshellarg($this->contextRoot));
421  exec($cmd, $output, $ret);
422  if ($ret !== 0) {
423  $this->debug(join("\n", $output) . "\n");
424  throw new WStartException(sprintf("Error executing '%s'.", $cmd));
425  }
426  $this->verbose(1, sprintf("[+] Done.\n"));
427  }
428  /**
429  * @throws WStartException
430  */
431  public function configureDbConnect()
432  {
433  $this->verbose(1, sprintf("[+] Configuring CORE_DBCONNECT.\n"));
434  require_once sprintf('%s/WHAT/Lib.Common.php', $this->contextRoot);
435  $CORE_DBCONNECT = getParam('CORE_DBCONNECT');
436  if ($CORE_DBCONNECT == 'persistent') {
437  $this->sedFile($this->absolutize('WHAT/Lib.Common.php') , function ($content)
438  {
439  return preg_replace('/\bpg_connect\b/', 'pg_pconnect', $content);
440  });
441  } else {
442  $this->sedFile($this->absolutize('WHAT/Lib.Common.php') , function ($content)
443  {
444  return preg_replace('/\bpg_pconnect\b/', 'pg_connect', $content);
445  });
446  }
447  $this->verbose(1, sprintf("[+] Done.\n"));
448  }
449  /**
450  * @throws WStartException
451  */
452  public function style()
453  {
454  $this->verbose(1, sprintf("[+] Recomputing style assets.\n"));
455  $cmd = sprintf("%s/wsh.php --api=setStyle 2>&1", escapeshellarg($this->contextRoot));
456  exec($cmd, $output, $ret);
457  if ($ret !== 0) {
458  $this->debug(join("\n", $output) . "\n");
459  throw new WStartException(sprintf("Error executing '%s'.", $cmd));
460  }
461  $this->verbose(1, sprintf("[+] Done.\n"));
462  }
463  /**
464  * @throws WStartException
465  */
466  public function unStop()
467  {
468  $this->verbose(1, sprintf("[+] Removing maintenance mode.\n"));
469  $maintenanceFile = $this->absolutize('maintenance.lock');
470  if (is_file($maintenanceFile)) {
471  if (unlink($maintenanceFile) === false) {
472  throw new WStartException(sprintf("Error removing file '%s'.", $maintenanceFile));
473  }
474  }
475  $this->verbose(1, sprintf("[+] Done.\n"));
476  }
477  /**
478  * @throws WStartException
479  * @throws \Dcp\Db\Exception
480  */
481  public function reapplyDatabaseParameters()
482  {
483  require_once 'WHAT/Lib.Common.php';
484  require_once 'WHAT/autoload.php';
485 
486  $this->verbose(1, sprintf("[+] Reapplying database parameters.\n"));
487  if (($err = simpleQuery('', 'SELECT current_database()', $dbName, true, true, false)) !== '') {
488  throw new WStartException(sprintf("Error getting current database name: %s", $err));
489  }
490  $paramList = array(
491  'DateStyle' => 'ISO, DMY',
492  'standard_conforming_strings' => 'off'
493  );
494  foreach ($paramList as $paramName => $paramValue) {
495  $sql = sprintf("ALTER DATABASE %s SET %s = %s", pg_escape_identifier($dbName) , pg_escape_identifier($paramName) , pg_escape_literal($paramValue));
496  if (($err = simpleQuery('', $sql, $res, true, true, false)) !== '') {
497  throw new WStartException(sprintf("Error setting '%s' = '%s' on database '%s': %s", $paramName, $paramValue, $dbName, $err));
498  }
499  }
500  $this->verbose(1, sprintf("[+] Done.\n"));
501  }
502 }
Exception class use exceptionCode to identifiy correctly exception.
Definition: exceptions.php:19
$ret
$file
foreach($argv as $arg) $cmd
linkFiles($sourceDir, $destDir, &$linked=array())
getParam($name, $def="")
must be in core or global type
Definition: Lib.Common.php:193
getTmpDir($def= '/tmp')
Definition: Lib.Common.php:150
$dir
Definition: resizeimg.php:144
static forceRegenerate()
simpleQuery($dbaccess, $query, &$result=array(), $singlecolumn=false, $singleresult=false, $useStrict=null)
Definition: Lib.Common.php:484
if($file) if($subject==""&&$file) if($subject=="") $err
← centre documentaire © anakeen