correctly bail out on non-existing INI file
[pharext/pharext] / src / pharext / Task / Activate.php
1 <?php
2
3 namespace pharext\Task;
4
5 use pharext\Exception;
6 use pharext\ExecCmd;
7 use pharext\Task;
8 use pharext\Tempfile;
9
10 /**
11 * PHP INI activation
12 */
13 class Activate implements Task
14 {
15 /**
16 * @var string
17 */
18 private $cwd;
19
20 /**
21 * @var array
22 */
23 private $inis;
24
25 /**
26 * @var string
27 */
28 private $type;
29
30 /**
31 * @var string
32 */
33 private $php_config;
34
35 /**
36 * @var string
37 */
38 private $sudo;
39
40 /**
41 * @param string $cwd working directory
42 * @param array $inis custom INI or list of loaded/scanned INI files
43 * @param string $type extension or zend_extension
44 * @param string $prefix install prefix, e.g. /usr/local
45 * @param string $common_name PHP programs common name, e.g. php5
46 * @param string $sudo sudo command
47 * @throws \pharext\Exception
48 */
49 public function __construct($cwd, array $inis, $type = "extension", $prefix = null, $common_name = "php", $sudo = null) {
50 $this->cwd = $cwd;
51 $this->type = $type;
52 $this->sudo = $sudo;
53 if (!$this->inis = $inis) {
54 throw new Exception("No PHP INIs given");
55 }
56 $cmd = $common_name . "-config";
57 if (isset($prefix)) {
58 $cmd = $prefix . "/bin/" . $cmd;
59 }
60 $this->php_config = $cmd;
61 }
62
63 /**
64 * @param bool $verbose
65 * @return boolean false, if extension was already activated
66 */
67 public function run($verbose = false) {
68 if ($verbose !== false) {
69 printf("Running INI activation ...\n");
70 }
71 $extension = basename(current(glob("{$this->cwd}/modules/*.so")));
72
73 if ($this->type === "zend_extension") {
74 $pattern = preg_quote((new ExecCmd($this->php_config))->run(["--extension-dir"])->getOutput() . "/$extension", "/");
75 } else {
76 $pattern = preg_quote($extension, "/");
77 }
78
79 foreach ($this->inis as $file) {
80 if ($verbose) {
81 printf("Checking %s ...\n", $file);
82 }
83 if (!file_exists($file)) {
84 throw new Exception(sprintf("INI file '%s' does not exist", $file));
85 }
86 $temp = new Tempfile("phpini");
87 foreach (file($file) as $line) {
88 if (preg_match("/^\s*{$this->type}\s*=\s*[\"']?{$pattern}[\"']?\s*(;.*)?\$/", $line)) {
89 return false;
90 }
91 fwrite($temp->getStream(), $line);
92 }
93 }
94
95 /* not found; append to last processed file, which is the main by default */
96 if ($verbose) {
97 printf("Activating in %s ...\n", $file);
98 }
99 fprintf($temp->getStream(), $this->type . "=%s\n", $extension);
100 $temp->closeStream();
101
102 $path = $temp->getPathname();
103 $stat = stat($file);
104
105 // owner transfer
106 $ugid = sprintf("%d:%d", $stat["uid"], $stat["gid"]);
107 $cmd = new ExecCmd("chown", $verbose);
108 if (isset($this->sudo)) {
109 $cmd->setSu($this->sudo);
110 }
111 $cmd->run([$ugid, $path]);
112
113 // permission transfer
114 $perm = decoct($stat["mode"] & 0777);
115 $cmd = new ExecCmd("chmod", $verbose);
116 if (isset($this->sudo)) {
117 $cmd->setSu($this->sudo);
118 }
119 $cmd->run([$perm, $path]);
120
121 // rename
122 $cmd = new ExecCmd("mv", $verbose);
123 if (isset($this->sudo)) {
124 $cmd->setSu($this->sudo);
125 }
126 $cmd->run([$path, $file]);
127
128 if ($verbose) {
129 printf("Replaced %s ...\n", $file);
130 }
131
132 return true;
133 }
134 }