4 use Civi\Test\CiviEnvBuilder\CallbackStep
;
5 use Civi\Test\CiviEnvBuilder\ExtensionStep
;
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 an extension (based on its name).
56 * @return \CiviEnvBuilder
58 public function ext($name) {
59 return $this->addStep(new ExtensionStep($name));
63 * Require an extension (based on its directory).
66 * @return \CiviEnvBuilder
67 * @throws \CRM_Extension_Exception_ParseException
69 public function extDir($dir) {
70 while ($dir && dirname($dir) !== $dir && !file_exists("$dir/info.xml")) {
73 if (file_exists("$dir/info.xml")) {
74 $info = \CRM_Extension_Info
::loadFromFile("$dir/info.xml");
77 return $this->addStep(new ExtensionStep($name));
80 protected function assertValid() {
81 foreach ($this->steps
as $step) {
82 if (!$step->isValid()) {
83 throw new RuntimeException("Found invalid step: " . var_dump($step, 1));
91 protected function getTargetSignature() {
92 if ($this->targetSignature
=== NULL) {
94 foreach ($this->steps
as $step) {
95 $buf .= $step->getSig();
97 $this->targetSignature
= md5($buf);
100 return $this->targetSignature
;
106 protected function getSavedSignature() {
107 $liveSchemaRev = NULL;
108 $pdo = \Civi\Test
::pdo();
109 $pdoStmt = $pdo->query(sprintf(
110 "SELECT rev FROM %s.civitest_revs WHERE name = %s",
111 \Civi\Test
::dsn('database'),
112 $pdo->quote($this->name
)
114 foreach ($pdoStmt as $row) {
115 $liveSchemaRev = $row['rev'];
117 return $liveSchemaRev;
121 * @param $newSignature
123 protected function setSavedSignature($newSignature) {
124 $pdo = \Civi\Test
::pdo();
126 'INSERT INTO %s.civitest_revs (name,rev) VALUES (%s,%s) '
127 . 'ON DUPLICATE KEY UPDATE rev = %s;',
128 \Civi\Test
::dsn('database'),
129 $pdo->quote($this->name
),
130 $pdo->quote($newSignature),
131 $pdo->quote($newSignature)
134 if (\Civi\Test
::execute($query) === FALSE) {
135 throw new RuntimeException("Failed to flag schema version: $query");
140 * Determine if the schema is correct. If necessary, destroy and recreate.
145 public function apply($force = FALSE) {
146 $dbName = \Civi\Test
::dsn('database');
147 $query = "USE {$dbName};"
148 . "CREATE TABLE IF NOT EXISTS civitest_revs (name VARCHAR(64) PRIMARY KEY, rev VARCHAR(64));";
150 if (\Civi\Test
::execute($query) === FALSE) {
151 throw new \
RuntimeException("Failed to flag schema version: $query");
154 $this->assertValid();
156 if (!$force && $this->getSavedSignature() === $this->getTargetSignature()) {
159 foreach ($this->steps
as $step) {
162 $this->setSavedSignature($this->getTargetSignature());