4 use Civi\Test\CiviEnvBuilder\CallbackStep
;
5 use Civi\Test\CiviEnvBuilder\ExtensionsStep
;
6 use Civi\Test\CiviEnvBuilder\SqlFileStep
;
7 use Civi\Test\CiviEnvBuilder\SqlStep
;
8 use Civi\Test\CiviEnvBuilder\StepInterface
;
12 * Class CiviEnvBuilder
14 * Provides a fluent interface for tracking a set of steps.
15 * By computing and storing a signature for the list steps, we can
16 * determine whether to (a) do nothing with the list or (b)
17 * reapply all the steps.
19 class CiviEnvBuilder
{
22 private $steps = array();
26 * A digest of the values in $steps.
28 private $targetSignature = NULL;
30 public function __construct($name) {
34 public function addStep(StepInterface
$step) {
35 $this->targetSignature
= NULL;
36 $this->steps
[] = $step;
40 public function callback($callback, $signature = NULL) {
41 return $this->addStep(new CallbackStep($callback, $signature));
44 public function sql($sql) {
45 return $this->addStep(new SqlStep($sql));
48 public function sqlFile($file) {
49 return $this->addStep(new SqlFileStep($file));
53 * Require that an extension be installed.
55 * @param string|array $names
56 * One or more extension names. You may use a wildcard '*'.
59 public function install($names) {
60 return $this->addStep(new ExtensionsStep('install', $names));
64 * Require an extension be installed (identified by its directory).
67 * The current test directory. We'll search for info.xml to
68 * see what this extension is.
70 * @throws \CRM_Extension_Exception_ParseException
72 public function installMe($dir) {
73 return $this->addStep(new ExtensionsStep('install', $this->whoAmI($dir)));
77 * Require an extension be uninstalled.
79 * @param string|array $names
80 * One or more extension names. You may use a wildcard '*'.
83 public function uninstall($names) {
84 return $this->addStep(new ExtensionsStep('uninstall', $names));
88 * Require an extension be uninstalled (identified by its directory).
91 * The current test directory. We'll search for info.xml to
92 * see what this extension is.
94 * @throws \CRM_Extension_Exception_ParseException
96 public function uninstallMe($dir) {
97 return $this->addStep(new ExtensionsStep('uninstall', $this->whoAmI($dir)));
100 protected function assertValid() {
101 foreach ($this->steps
as $step) {
102 if (!$step->isValid()) {
103 throw new RuntimeException("Found invalid step: " . var_dump($step, 1));
111 protected function getTargetSignature() {
112 if ($this->targetSignature
=== NULL) {
114 foreach ($this->steps
as $step) {
115 $buf .= $step->getSig();
117 $this->targetSignature
= md5($buf);
120 return $this->targetSignature
;
126 protected function getSavedSignature() {
127 $liveSchemaRev = NULL;
128 $pdo = \Civi\Test
::pdo();
129 $pdoStmt = $pdo->query(sprintf(
130 "SELECT rev FROM %s.civitest_revs WHERE name = %s",
131 \Civi\Test
::dsn('database'),
132 $pdo->quote($this->name
)
134 foreach ($pdoStmt as $row) {
135 $liveSchemaRev = $row['rev'];
137 return $liveSchemaRev;
141 * @param $newSignature
143 protected function setSavedSignature($newSignature) {
144 $pdo = \Civi\Test
::pdo();
146 'INSERT INTO %s.civitest_revs (name,rev) VALUES (%s,%s) '
147 . 'ON DUPLICATE KEY UPDATE rev = %s;',
148 \Civi\Test
::dsn('database'),
149 $pdo->quote($this->name
),
150 $pdo->quote($newSignature),
151 $pdo->quote($newSignature)
154 if (\Civi\Test
::execute($query) === FALSE) {
155 throw new RuntimeException("Failed to flag schema version: $query");
160 * Determine if there's been a change in the preferred configuration.
161 * If the preferred-configuration matches the last test, keep it. Otherwise,
162 * destroy and recreate.
165 * Forcibly execute the build, even if the configuration hasn't changed.
166 * This will slow-down the tests, but it may be appropriate for some very sloppy
170 public function apply($force = FALSE) {
171 $dbName = \Civi\Test
::dsn('database');
172 $query = "USE {$dbName};"
173 . "CREATE TABLE IF NOT EXISTS civitest_revs (name VARCHAR(64) PRIMARY KEY, rev VARCHAR(64));";
175 if (\Civi\Test
::execute($query) === FALSE) {
176 throw new \
RuntimeException("Failed to flag schema version: $query");
179 $this->assertValid();
181 if (!$force && $this->getSavedSignature() === $this->getTargetSignature()) {
184 foreach ($this->steps
as $step) {
187 $this->setSavedSignature($this->getTargetSignature());
194 * @throws \CRM_Extension_Exception_ParseException
196 protected function whoAmI($dir) {
197 while ($dir && dirname($dir) !== $dir && !file_exists("$dir/info.xml")) {
198 $dir = dirname($dir);
200 if (file_exists("$dir/info.xml")) {
201 $info = \CRM_Extension_Info
::loadFromFile("$dir/info.xml");