1: <?php
2: /*
3: You may not change or alter any portion of this comment or credits
4: of supporting developers from this source code or any supporting source code
5: which is considered copyrighted (c) material of the original comment or credit authors.
6:
7: This program is distributed in the hope that it will be useful,
8: but WITHOUT ANY WARRANTY; without even the implied warranty of
9: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10: */
11:
12: namespace Xoops\Core;
13:
14: use Symfony\Component\Process\Process;
15: use Symfony\Component\Process\PhpExecutableFinder;
16: use Symfony\Component\Process\PhpProcess;
17:
18: /**
19: * ComposerUtility
20: *
21: * @category Xoops\Core\ComposerUtility
22: * @package ComposerUtility
23: * @author Richard Griffith <richard@geekwright.com>
24: * @copyright 2014 XOOPS Project (http://xoops.org)
25: * @license GNU GPL 2 or later (http://www.gnu.org/licenses/gpl-2.0.html)
26: * @version Release: 1.0
27: * @link http://xoops.org
28: * @since 2.6.0
29: */
30: class ComposerUtility
31: {
32: private $output = array();
33: private $exe = null;
34: private $exeOptions = ' --no-ansi --no-interaction ';
35: private $errors = array();
36:
37: /**
38: * __construct
39: */
40: public function __construct()
41: {
42:
43: }
44:
45: /**
46: * composerExecute - execute a command using composer
47: *
48: * @param string $command_line command to pass to composer, i.e. 'update'
49: *
50: * @return boolean true on success, false if command failed or could not execute
51: */
52: public function composerExecute($command_line)
53: {
54: $this->output = array();
55: $this->errors = array();
56:
57: $options = ' ' . trim($this->exeOptions) . ' ';
58:
59: if (empty($this->exe)) {
60: $exeFinder = new PhpExecutableFinder();
61: $foundExe = $exeFinder->find();
62: if ($foundExe) {
63: $this->exe = $foundExe . ' composer.phar';
64: } else {
65: $this->errors[] = 'Cannot find PHP executable';
66: return false;
67: }
68: }
69:
70: if (!chdir(\XoopsBaseConfig::get('lib-path'))) {
71: $this->errors[] = 'Cannot change directory to lib-path';
72: return false;
73: }
74:
75: set_time_limit(300); // don't want this script to timeout;
76: $command = $this->exe . $options . $command_line;
77: putenv('COMPOSER_HOME=' . \XoopsBaseConfig::get('var-path').'/composer');
78: $process = new Process($command);
79: //$process->setEnv(array('COMPOSER_HOME' => \XoopsBaseConfig::get('var-path').'/composer'));
80: $process->setTimeout(120);
81: try {
82: $process->run(
83: function ($type, $buffer) use (&$errors, &$output) {
84: if ('err' === $type) {
85: $errors[] = $buffer;
86: } else {
87: $this->output[] = $buffer;
88: }
89: }
90: );
91: } catch (\Exception $e) {
92: $errors[] = $e->getMessage();
93: }
94:
95: if ($process->isSuccessful()) {
96: return true;
97: } else {
98: $this->errors[] = 'Failed: ' . $command;
99: $this->errors[] = sprintf(
100: "Process exit code: %s, '%s'",
101: $process->getExitCode(),
102: $process->getExitCodeText()
103: );
104: }
105: return false;
106: }
107:
108: /**
109: * getLastOutput - return output from last composerExecute()
110: *
111: * @return array
112: */
113: public function getLastOutput()
114: {
115: return $this->output;
116: }
117:
118: /**
119: * getLastError - return errors from last composerExecute()
120: *
121: * @return array
122: */
123: public function getLastError()
124: {
125: return $this->errors;
126: }
127:
128: /**
129: * setComposerExe - set a specific executable for Composer
130: *
131: * By default symfony/process looks for a PHP executable, and it is passed an
132: * argument of a local copy of composer.phar. This method allows an override
133: * for these defaults to be specified. Invoke this method before composerExecute().
134: *
135: * @param string $overrideExe command line to invoke composer
136: *
137: * @return void
138: */
139: public function setComposerExe($overrideExe)
140: {
141: $this->exe = $overrideExe;
142: }
143: }
144: