Fixed Behat+SS coding conventions

This commit is contained in:
Ingo Schommer 2013-11-15 17:38:37 +01:00
parent 1166991d49
commit fc6d1ac12b

View File

@ -3,16 +3,16 @@
namespace SilverStripe\BehatExtension\Context; namespace SilverStripe\BehatExtension\Context;
use Behat\Behat\Context\ClosuredContextInterface, use Behat\Behat\Context\ClosuredContextInterface,
Behat\Behat\Context\TranslatedContextInterface, Behat\Behat\Context\TranslatedContextInterface,
Behat\Behat\Context\BehatContext, Behat\Behat\Context\BehatContext,
Behat\Behat\Context\Step, Behat\Behat\Context\Step,
Behat\Behat\Event\StepEvent, Behat\Behat\Event\StepEvent,
Behat\Behat\Event\FeatureEvent, Behat\Behat\Event\FeatureEvent,
Behat\Behat\Event\ScenarioEvent, Behat\Behat\Event\ScenarioEvent,
Behat\Behat\Exception\PendingException, Behat\Behat\Exception\PendingException,
Behat\Mink\Driver\Selenium2Driver, Behat\Mink\Driver\Selenium2Driver,
Behat\Gherkin\Node\PyStringNode, Behat\Gherkin\Node\PyStringNode,
Behat\Gherkin\Node\TableNode; Behat\Gherkin\Node\TableNode;
// PHPUnit // PHPUnit
require_once 'PHPUnit/Autoload.php'; require_once 'PHPUnit/Autoload.php';
@ -23,518 +23,500 @@ require_once 'PHPUnit/Framework/Assert/Functions.php';
*/ */
class FixtureContext extends BehatContext class FixtureContext extends BehatContext
{ {
protected $context; protected $context;
/** /**
* @var \FixtureFactory * @var \FixtureFactory
*/ */
protected $fixtureFactory; protected $fixtureFactory;
/** /**
* @var String Absolute path where file fixtures are located. * @var String Absolute path where file fixtures are located.
* These will automatically get copied to their location * These will automatically get copied to their location
* declare through the 'Given a file "..."' step defition. * declare through the 'Given a file "..."' step defition.
*/ */
protected $filesPath; protected $filesPath;
/** /**
* @var String Tracks all files and folders created from fixtures, for later cleanup. * @var String Tracks all files and folders created from fixtures, for later cleanup.
*/ */
protected $createdFilesPaths = array(); protected $createdFilesPaths = array();
public function __construct(array $parameters) public function __construct(array $parameters) {
{ $this->context = $parameters;
$this->context = $parameters; }
}
public function getSession($name = null) public function getSession($name = null) {
{ return $this->getMainContext()->getSession($name);
return $this->getMainContext()->getSession($name); }
}
/** /**
* @return \FixtureFactory * @return \FixtureFactory
*/ */
public function getFixtureFactory() { public function getFixtureFactory() {
if(!$this->fixtureFactory) { if(!$this->fixtureFactory) {
$this->fixtureFactory = \Injector::inst()->create('FixtureFactory', 'FixtureContextFactory'); $this->fixtureFactory = \Injector::inst()->create('FixtureFactory', 'FixtureContextFactory');
} }
return $this->fixtureFactory; return $this->fixtureFactory;
} }
/** /**
* @param \FixtureFactory $factory * @param \FixtureFactory $factory
*/ */
public function setFixtureFactory(\FixtureFactory $factory) { public function setFixtureFactory(\FixtureFactory $factory) {
$this->fixtureFactory = $factory; $this->fixtureFactory = $factory;
} }
/** /**
* @param String * @param String
*/ */
public function setFilesPath($path) { public function setFilesPath($path) {
$this->filesPath = $path; $this->filesPath = $path;
} }
/** /**
* @return String * @return String
*/ */
public function getFilesPath() { public function getFilesPath() {
return $this->filesPath; return $this->filesPath;
} }
/** /**
* @BeforeScenario @database-defaults * @BeforeScenario @database-defaults
*/ */
public function beforeDatabaseDefaults(ScenarioEvent $event) public function beforeDatabaseDefaults(ScenarioEvent $event) {
{ \SapphireTest::empty_temp_db();
\SapphireTest::empty_temp_db(); \DB::getConn()->quiet();
\DB::getConn()->quiet(); $dataClasses = \ClassInfo::subclassesFor('DataObject');
$dataClasses = \ClassInfo::subclassesFor('DataObject'); array_shift($dataClasses);
array_shift($dataClasses); foreach ($dataClasses as $dataClass) {
foreach ($dataClasses as $dataClass) { \singleton($dataClass)->requireDefaultRecords();
\singleton($dataClass)->requireDefaultRecords(); }
} }
}
/** /**
* @AfterScenario * @AfterScenario
*/ */
public function afterResetDatabase(ScenarioEvent $event) public function afterResetDatabase(ScenarioEvent $event) {
{ \SapphireTest::empty_temp_db();
\SapphireTest::empty_temp_db(); }
}
/** /**
* @AfterScenario * @AfterScenario
*/ */
public function afterResetAssets(ScenarioEvent $event) public function afterResetAssets(ScenarioEvent $event) {
{ if (is_array($this->createdFilesPaths)) {
if (is_array($this->createdFilesPaths)) { $createdFiles = array_reverse($this->createdFilesPaths);
$createdFiles = array_reverse($this->createdFilesPaths); foreach ($createdFiles as $path) {
foreach ($createdFiles as $path) { if (is_dir($path)) {
if (is_dir($path)) { \Filesystem::removeFolder($path);
\Filesystem::removeFolder($path); } else {
} else { @unlink($path);
@unlink($path); }
} }
} }
} }
}
/** /**
* Example: Given a "page" "Page 1" * Example: Given a "page" "Page 1"
* *
* @Given /^(?:(an|a|the) )"(?<type>[^"]+)" "(?<id>[^"]+)"$/ * @Given /^(?:(an|a|the) )"(?<type>[^"]+)" "(?<id>[^"]+)"$/
*/ */
public function stepCreateRecord($type, $id) public function stepCreateRecord($type, $id) {
{ $class = $this->convertTypeToClass($type);
$class = $this->convertTypeToClass($type); if($class == 'File' || is_subclass_of($class, 'File')) {
if($class == 'File' || is_subclass_of($class, 'File')) { $fields = $this->prepareAsset($class, $id);
$fields = $this->prepareAsset($class, $id); } else {
} else { $fields = array();
$fields = array(); }
} $this->fixtureFactory->createObject($class, $id, $fields);
$this->fixtureFactory->createObject($class, $id, $fields); }
}
/** /**
* Example: Given a "page" "Page 1" has the "content" "My content" * Example: Given a "page" "Page 1" has the "content" "My content"
* *
* @Given /^(?:(an|a|the) )"(?<type>[^"]+)" "(?<id>[^"]+)" has (?:(an|a|the) )"(?<field>.*)" "(?<value>.*)"$/ * @Given /^(?:(an|a|the) )"(?<type>[^"]+)" "(?<id>[^"]+)" has (?:(an|a|the) )"(?<field>.*)" "(?<value>.*)"$/
*/ */
public function stepCreateRecordHasField($type, $id, $field, $value) public function stepCreateRecordHasField($type, $id, $field, $value) {
{ $class = $this->convertTypeToClass($type);
$class = $this->convertTypeToClass($type); $fields = $this->convertFields(
$fields = $this->convertFields( $class,
$class, array($field => $value)
array($field => $value) );
); $this->fixtureFactory->createObject($class, $id, $fields);
$this->fixtureFactory->createObject($class, $id, $fields); }
}
/** /**
* Example: Given a "page" "Page 1" with "URL"="page-1" and "Content"="my page 1" * Example: Given a "page" "Page 1" with "URL"="page-1" and "Content"="my page 1"
* *
* @Given /^(?:(an|a|the) )"(?<type>[^"]+)" "(?<id>[^"]+)" with (?<data>.*)$/ * @Given /^(?:(an|a|the) )"(?<type>[^"]+)" "(?<id>[^"]+)" with (?<data>.*)$/
*/ */
public function stepCreateRecordWithData($type, $id, $data) public function stepCreateRecordWithData($type, $id, $data) {
{ $class = $this->convertTypeToClass($type);
$class = $this->convertTypeToClass($type); preg_match_all(
preg_match_all( '/"(?<key>[^"]+)"\s*=\s*"(?<value>[^"]+)"/',
'/"(?<key>[^"]+)"\s*=\s*"(?<value>[^"]+)"/', $data,
$data, $matches
$matches );
); $fields = $this->convertFields(
$fields = $this->convertFields( $class,
$class, array_combine($matches['key'], $matches['value'])
array_combine($matches['key'], $matches['value']) );
); if($class == 'File' || is_subclass_of($class, 'File')) {
if($class == 'File' || is_subclass_of($class, 'File')) { $fields = $this->prepareAsset($class, $id, $fields);
$fields = $this->prepareAsset($class, $id, $fields); }
} $this->fixtureFactory->createObject($class, $id, $fields);
$this->fixtureFactory->createObject($class, $id, $fields); }
}
/** /**
* Example: And the "page" "Page 2" has the following data * Example: And the "page" "Page 2" has the following data
* | Content | <blink> | * | Content | <blink> |
* | My Property | foo | * | My Property | foo |
* | My Boolean | bar | * | My Boolean | bar |
* *
* @Given /^(?:(an|a|the) )"(?<type>[^"]+)" "(?<id>[^"]+)" has the following data$/ * @Given /^(?:(an|a|the) )"(?<type>[^"]+)" "(?<id>[^"]+)" has the following data$/
*/ */
public function stepCreateRecordWithTable($type, $id, $null, TableNode $fieldsTable) public function stepCreateRecordWithTable($type, $id, $null, TableNode $fieldsTable) {
{ $class = $this->convertTypeToClass($type);
$class = $this->convertTypeToClass($type); // TODO Support more than one record
// TODO Support more than one record $fields = $this->convertFields($class, $fieldsTable->getRowsHash());
$fields = $this->convertFields($class, $fieldsTable->getRowsHash()); if($class == 'File' || is_subclass_of($class, 'File')) {
if($class == 'File' || is_subclass_of($class, 'File')) { $fields = $this->prepareAsset($class, $id, $fields);
$fields = $this->prepareAsset($class, $id, $fields); }
} $this->fixtureFactory->createObject($class, $id, $fields);
$this->fixtureFactory->createObject($class, $id, $fields); }
}
/** /**
* Example: Given the "page" "Page 1.1" is a child of the "page" "Page1" * Example: Given the "page" "Page 1.1" is a child of the "page" "Page1"
* *
* @Given /^(?:(an|a|the) )"(?<type>[^"]+)" "(?<id>[^"]+)" is a (?<relation>[^\s]*) of (?:(an|a|the) )"(?<relationType>[^"]+)" "(?<relationId>[^"]+)"/ * @Given /^(?:(an|a|the) )"(?<type>[^"]+)" "(?<id>[^"]+)" is a (?<relation>[^\s]*) of (?:(an|a|the) )"(?<relationType>[^"]+)" "(?<relationId>[^"]+)"/
*/ */
public function stepUpdateRecordRelation($type, $id, $relation, $relationType, $relationId) public function stepUpdateRecordRelation($type, $id, $relation, $relationType, $relationId) {
{ $class = $this->convertTypeToClass($type);
$class = $this->convertTypeToClass($type); $relationClass = $this->convertTypeToClass($relationType);
$relationClass = $this->convertTypeToClass($relationType);
$obj = $this->fixtureFactory->get($class, $id);
$obj = $this->fixtureFactory->get($class, $id); if(!$obj) $obj = $this->fixtureFactory->createObject($class, $id);
if(!$obj) $obj = $this->fixtureFactory->createObject($class, $id);
$relationObj = $this->fixtureFactory->get($relationClass, $relationId);
$relationObj = $this->fixtureFactory->get($relationClass, $relationId); if(!$relationObj) $relationObj = $this->fixtureFactory->createObject($relationClass, $relationId);
if(!$relationObj) $relationObj = $this->fixtureFactory->createObject($relationClass, $relationId);
switch($relation) {
switch($relation) { case 'parent':
case 'parent': $relationObj->ParentID = $obj->ID;
$relationObj->ParentID = $obj->ID; $relationObj->write();
$relationObj->write(); break;
break; case 'child':
case 'child': $obj->ParentID = $relationObj->ID;
$obj->ParentID = $relationObj->ID; $obj->write();
$obj->write(); break;
break; default:
default: throw new \InvalidArgumentException(sprintf(
throw new \InvalidArgumentException(sprintf( 'Invalid relation "%s"', $relation
'Invalid relation "%s"', $relation ));
)); }
} }
}
/** /**
* Example: Given the "page" "Page 1" is not published * Example: Given the "page" "Page 1" is not published
* *
* @Given /^(?:(an|a|the) )"(?<type>[^"]+)" "(?<id>[^"]+)" is (?<state>[^"]*)$/ * @Given /^(?:(an|a|the) )"(?<type>[^"]+)" "(?<id>[^"]+)" is (?<state>[^"]*)$/
*/ */
public function stepUpdateRecordState($type, $id, $state) public function stepUpdateRecordState($type, $id, $state) {
{ $class = $this->convertTypeToClass($type);
$class = $this->convertTypeToClass($type); $obj = $this->fixtureFactory->get($class, $id);
$obj = $this->fixtureFactory->get($class, $id); if(!$obj) {
if(!$obj) { throw new \InvalidArgumentException(sprintf(
throw new \InvalidArgumentException(sprintf( 'Can not find record "%s" with identifier "%s"',
'Can not find record "%s" with identifier "%s"', $type,
$type, $id
$id ));
)); }
}
switch($state) { switch($state) {
case 'published': case 'published':
$obj->publish('Stage', 'Live'); $obj->publish('Stage', 'Live');
break; break;
case 'not published': case 'not published':
case 'unpublished': case 'unpublished':
$oldMode = \Versioned::get_reading_mode(); $oldMode = \Versioned::get_reading_mode();
\Versioned::reading_stage('Live'); \Versioned::reading_stage('Live');
$clone = clone $obj; $clone = clone $obj;
$clone->delete(); $clone->delete();
\Versioned::reading_stage($oldMode); \Versioned::reading_stage($oldMode);
break; break;
case 'deleted': case 'deleted':
$obj->delete(); $obj->delete();
break; break;
default: default:
throw new \InvalidArgumentException(sprintf( throw new \InvalidArgumentException(sprintf(
'Invalid state: "%s"', $state 'Invalid state: "%s"', $state
)); ));
} }
} }
/** /**
* Accepts YAML fixture definitions similar to the ones used in SilverStripe unit testing. * Accepts YAML fixture definitions similar to the ones used in SilverStripe unit testing.
* *
* Example: Given there are the following member records: * Example: Given there are the following member records:
* member1: * member1:
* Email: member1@test.com * Email: member1@test.com
* member2: * member2:
* Email: member2@test.com * Email: member2@test.com
* *
* @Given /^there are the following ([^\s]*) records$/ * @Given /^there are the following ([^\s]*) records$/
*/ */
public function stepThereAreTheFollowingRecords($dataObject, PyStringNode $string) public function stepThereAreTheFollowingRecords($dataObject, PyStringNode $string) {
{ $yaml = array_merge(array($dataObject . ':'), $string->getLines());
$yaml = array_merge(array($dataObject . ':'), $string->getLines()); $yaml = implode("\n ", $yaml);
$yaml = implode("\n ", $yaml);
// Save fixtures into database // Save fixtures into database
// TODO Run prepareAsset() for each File and Folder record // TODO Run prepareAsset() for each File and Folder record
$yamlFixture = new \YamlFixture($yaml); $yamlFixture = new \YamlFixture($yaml);
$yamlFixture->writeInto($this->getFixtureFactory()); $yamlFixture->writeInto($this->getFixtureFactory());
} }
/** /**
* Example: Given a "member" "Admin" belonging to "Admin Group" * Example: Given a "member" "Admin" belonging to "Admin Group"
* *
* @Given /^(?:(an|a|the) )"member" "(?<id>[^"]+)" belonging to "(?<groupId>[^"]+)"$/ * @Given /^(?:(an|a|the) )"member" "(?<id>[^"]+)" belonging to "(?<groupId>[^"]+)"$/
*/ */
public function stepCreateMemberWithGroup($id, $groupId) public function stepCreateMemberWithGroup($id, $groupId) {
{ $group = $this->fixtureFactory->get('Group', $groupId);
$group = $this->fixtureFactory->get('Group', $groupId); if(!$group) $group = $this->fixtureFactory->createObject('Group', $groupId);
if(!$group) $group = $this->fixtureFactory->createObject('Group', $groupId);
$member = $this->fixtureFactory->createObject('Member', $id);
$member = $this->fixtureFactory->createObject('Member', $id); $member->Groups()->add($group);
$member->Groups()->add($group); }
}
/** /**
* Example: Given a "member" "Admin" belonging to "Admin Group" with "Email"="test@test.com" * Example: Given a "member" "Admin" belonging to "Admin Group" with "Email"="test@test.com"
* *
* @Given /^(?:(an|a|the) )"member" "(?<id>[^"]+)" belonging to "(?<groupId>[^"]+)" with (?<data>.*)$/ * @Given /^(?:(an|a|the) )"member" "(?<id>[^"]+)" belonging to "(?<groupId>[^"]+)" with (?<data>.*)$/
*/ */
public function stepCreateMemberWithGroupAndData($id, $groupId, $data) public function stepCreateMemberWithGroupAndData($id, $groupId, $data) {
{ $class = 'Member';
$class = 'Member'; preg_match_all(
preg_match_all( '/"(?<key>[^"]+)"\s*=\s*"(?<value>[^"]+)"/',
'/"(?<key>[^"]+)"\s*=\s*"(?<value>[^"]+)"/', $data,
$data, $matches
$matches );
); $fields = $this->convertFields(
$fields = $this->convertFields( $class,
$class, array_combine($matches['key'], $matches['value'])
array_combine($matches['key'], $matches['value']) );
);
$group = $this->fixtureFactory->get('Group', $groupId);
$group = $this->fixtureFactory->get('Group', $groupId); if(!$group) $group = $this->fixtureFactory->createObject('Group', $groupId);
if(!$group) $group = $this->fixtureFactory->createObject('Group', $groupId);
$member = $this->fixtureFactory->createObject($class, $id, $fields); $member = $this->fixtureFactory->createObject($class, $id, $fields);
$member->Groups()->add($group); $member->Groups()->add($group);
} }
/** /**
* Example: Given a "group" "Admin" with permissions "Access to 'Pages' section" and "Access to 'Files' section" * Example: Given a "group" "Admin" with permissions "Access to 'Pages' section" and "Access to 'Files' section"
* *
* @Given /^(?:(an|a|the) )"group" "(?<id>[^"]+)" (?:(with|has)) permissions (?<permissionStr>.*)$/ * @Given /^(?:(an|a|the) )"group" "(?<id>[^"]+)" (?:(with|has)) permissions (?<permissionStr>.*)$/
*/ */
public function stepCreateGroupWithPermissions($id, $permissionStr) public function stepCreateGroupWithPermissions($id, $permissionStr) {
{ // Convert natural language permissions to codes
// Convert natural language permissions to codes preg_match_all('/"([^"]+)"/', $permissionStr, $matches);
preg_match_all('/"([^"]+)"/', $permissionStr, $matches); $permissions = $matches[1];
$permissions = $matches[1]; $codes = \Permission::get_codes(false);
$codes = \Permission::get_codes(false);
$group = $this->fixtureFactory->get('Group', $id); $group = $this->fixtureFactory->get('Group', $id);
if(!$group) $group = $this->fixtureFactory->createObject('Group', $id); if(!$group) $group = $this->fixtureFactory->createObject('Group', $id);
foreach($permissions as $permission) { foreach($permissions as $permission) {
$found = false; $found = false;
foreach($codes as $code => $details) { foreach($codes as $code => $details) {
if( if(
$permission == $code $permission == $code
|| $permission == $details['name'] || $permission == $details['name']
) { ) {
\Permission::grant($group->ID, $code); \Permission::grant($group->ID, $code);
$found = true; $found = true;
} }
} }
if(!$found) { if(!$found) {
throw new \InvalidArgumentException(sprintf( throw new \InvalidArgumentException(sprintf(
'No permission found for "%s"', $permission 'No permission found for "%s"', $permission
)); ));
} }
} }
} }
/** /**
* Navigates to a record based on its identifier set during fixture creation, * Navigates to a record based on its identifier set during fixture creation,
* using its RelativeLink() method to map the record to a URL. * using its RelativeLink() method to map the record to a URL.
* Example: Given I go to the "page" "My Page" * Example: Given I go to the "page" "My Page"
* *
* @Given /^I go to (?:(an|a|the) )"(?<type>[^"]+)" "(?<id>[^"]+)"/ * @Given /^I go to (?:(an|a|the) )"(?<type>[^"]+)" "(?<id>[^"]+)"/
*/ */
public function stepGoToNamedRecord($type, $id) { public function stepGoToNamedRecord($type, $id) {
$class = $this->convertTypeToClass($type); $class = $this->convertTypeToClass($type);
$record = $this->fixtureFactory->get($class, $id); $record = $this->fixtureFactory->get($class, $id);
if(!$record) { if(!$record) {
throw new \InvalidArgumentException(sprintf( throw new \InvalidArgumentException(sprintf(
'Cannot resolve reference "%s", no matching fixture found', 'Cannot resolve reference "%s", no matching fixture found',
$id $id
)); ));
} }
if(!$record->hasMethod('RelativeLink')) { if(!$record->hasMethod('RelativeLink')) {
throw new \InvalidArgumentException('URL for record cannot be determined, missing RelativeLink() method'); throw new \InvalidArgumentException('URL for record cannot be determined, missing RelativeLink() method');
} }
$this->getSession()->visit($this->getMainContext()->locatePath($record->RelativeLink())); $this->getSession()->visit($this->getMainContext()->locatePath($record->RelativeLink()));
} }
/** /**
* Checks that a file or folder exists in the webroot. * Checks that a file or folder exists in the webroot.
* Example: There should be a file "assets/Uploads/test.jpg" * Example: There should be a file "assets/Uploads/test.jpg"
* *
* @Then /^there should be a (?<type>(file|folder) )"(?<path>[^"]*)"/ * @Then /^there should be a (?<type>(file|folder) )"(?<path>[^"]*)"/
*/ */
public function stepThereShouldBeAFileOrFolder($type, $path) public function stepThereShouldBeAFileOrFolder($type, $path) {
{ assertFileExists($this->joinPaths(BASE_PATH, $path));
assertFileExists($this->joinPaths(BASE_PATH, $path)); }
}
/** /**
* Replaces fixture references in values with their respective database IDs, * Replaces fixture references in values with their respective database IDs,
* with the notation "=><class>.<identifier>". Example: "=>Page.My Page". * with the notation "=><class>.<identifier>". Example: "=>Page.My Page".
* *
* @Transform /^([^"]+)$/ * @Transform /^([^"]+)$/
*/ */
public function lookupFixtureReference($string) public function lookupFixtureReference($string) {
{ if(preg_match('/^=>/', $string)) {
if(preg_match('/^=>/', $string)) { list($className, $identifier) = explode('.', preg_replace('/^=>/', '', $string), 2);
list($className, $identifier) = explode('.', preg_replace('/^=>/', '', $string), 2); $id = $this->fixtureFactory->getId($className, $identifier);
$id = $this->fixtureFactory->getId($className, $identifier); if(!$id) {
if(!$id) { throw new \InvalidArgumentException(sprintf(
throw new \InvalidArgumentException(sprintf( 'Cannot resolve reference "%s", no matching fixture found',
'Cannot resolve reference "%s", no matching fixture found', $string
$string ));
)); }
} return $id;
return $id; } else {
} else { return $string;
return $string; }
} }
}
/** /**
* @Given /^(?:(an|a|the) )"(?<type>[^"]*)" "(?<id>[^"]*)" was (?<mod>(created|last edited)) "(?<time>[^"]*)"$/ * @Given /^(?:(an|a|the) )"(?<type>[^"]*)" "(?<id>[^"]*)" was (?<mod>(created|last edited)) "(?<time>[^"]*)"$/
*/ */
public function aRecordWasLastEditedRelative($type, $id, $mod, $time) { public function aRecordWasLastEditedRelative($type, $id, $mod, $time) {
$class = $this->convertTypeToClass($type); $class = $this->convertTypeToClass($type);
$fields = array(); $fields = array();
$record = $this->fixtureFactory->createObject($class, $id, $fields); $record = $this->fixtureFactory->createObject($class, $id, $fields);
$date = date("Y-m-d H:i:s",strtotime($time)); $date = date("Y-m-d H:i:s",strtotime($time));
$table = \ClassInfo::baseDataClass(get_class($record)); $table = \ClassInfo::baseDataClass(get_class($record));
$field = ($mod == 'created') ? 'Created' : 'LastEdited'; $field = ($mod == 'created') ? 'Created' : 'LastEdited';
\DB::query(sprintf( \DB::query(sprintf(
'UPDATE "%s" SET "%s" = \'%s\' WHERE "ID" = \'%d\'', 'UPDATE "%s" SET "%s" = \'%s\' WHERE "ID" = \'%d\'',
$table, $table,
$field, $field,
$date, $date,
$record->ID $record->ID
)); ));
// Support for Versioned extension, by checking for a "Live" stage // Support for Versioned extension, by checking for a "Live" stage
if(\DB::getConn()->hasTable($table . '_Live')) { if(\DB::getConn()->hasTable($table . '_Live')) {
\DB::query(sprintf( \DB::query(sprintf(
'UPDATE "%s_Live" SET "%s" = \'%s\' WHERE "ID" = \'%d\'', 'UPDATE "%s_Live" SET "%s" = \'%s\' WHERE "ID" = \'%d\'',
$table, $table,
$field, $field,
$date, $date,
$record->ID $record->ID
)); ));
} }
} }
protected function prepareAsset($class, $identifier, $data = null) { protected function prepareAsset($class, $identifier, $data = null) {
if(!$data) $data = array(); if(!$data) $data = array();
$relativeTargetPath = (isset($data['Filename'])) ? $data['Filename'] : $identifier; $relativeTargetPath = (isset($data['Filename'])) ? $data['Filename'] : $identifier;
$relativeTargetPath = preg_replace('/^' . ASSETS_DIR . '/', '', $relativeTargetPath); $relativeTargetPath = preg_replace('/^' . ASSETS_DIR . '/', '', $relativeTargetPath);
$targetPath = $this->joinPaths(ASSETS_PATH, $relativeTargetPath); $targetPath = $this->joinPaths(ASSETS_PATH, $relativeTargetPath);
$sourcePath = $this->joinPaths($this->getFilesPath(), basename($relativeTargetPath)); $sourcePath = $this->joinPaths($this->getFilesPath(), basename($relativeTargetPath));
// Create file or folder on filesystem // Create file or folder on filesystem
if($class == 'Folder' || is_subclass_of($class, 'Folder')) { if($class == 'Folder' || is_subclass_of($class, 'Folder')) {
$parent = \Folder::find_or_make($relativeTargetPath); $parent = \Folder::find_or_make($relativeTargetPath);
} else { } else {
if(!file_exists($sourcePath)) { if(!file_exists($sourcePath)) {
throw new \InvalidArgumentException(sprintf( throw new \InvalidArgumentException(sprintf(
'Source file for "%s" cannot be found in "%s"', 'Source file for "%s" cannot be found in "%s"',
$targetPath, $targetPath,
$sourcePath $sourcePath
)); ));
} }
$parent = \Folder::find_or_make(dirname($relativeTargetPath)); $parent = \Folder::find_or_make(dirname($relativeTargetPath));
copy($sourcePath, $targetPath); copy($sourcePath, $targetPath);
} }
$data['Filename'] = $this->joinPaths(ASSETS_DIR, $relativeTargetPath); $data['Filename'] = $this->joinPaths(ASSETS_DIR, $relativeTargetPath);
if(!isset($data['Name'])) $data['Name'] = basename($relativeTargetPath); if(!isset($data['Name'])) $data['Name'] = basename($relativeTargetPath);
$data['ParentID'] = $parent->ID; $data['ParentID'] = $parent->ID;
$this->createdFilesPaths[] = $targetPath; $this->createdFilesPaths[] = $targetPath;
return $data; return $data;
} }
/** /**
* Converts a natural language class description to an actual class name. * Converts a natural language class description to an actual class name.
* Respects {@link DataObject::$singular_name} variations. * Respects {@link DataObject::$singular_name} variations.
* Example: "redirector page" -> "RedirectorPage" * Example: "redirector page" -> "RedirectorPage"
* *
* @param String * @param String
* @return String Class name * @return String Class name
*/ */
protected function convertTypeToClass($type) protected function convertTypeToClass($type) {
{ $type = trim($type);
$type = trim($type);
// Try direct mapping // Try direct mapping
$class = str_replace(' ', '', ucwords($type)); $class = str_replace(' ', '', ucwords($type));
if(class_exists($class) || !($class == 'DataObject' || is_subclass_of($class, 'DataObject'))) { if(class_exists($class) || !($class == 'DataObject' || is_subclass_of($class, 'DataObject'))) {
return $class; return $class;
} }
// Fall back to singular names // Fall back to singular names
foreach(array_values(\ClassInfo::subclassesFor('DataObject')) as $candidate) { foreach(array_values(\ClassInfo::subclassesFor('DataObject')) as $candidate) {
if(singleton($candidate)->singular_name() == $type) return $candidate; if(singleton($candidate)->singular_name() == $type) return $candidate;
} }
throw new \InvalidArgumentException(sprintf( throw new \InvalidArgumentException(sprintf(
'Class "%s" does not exist, or is not a subclass of DataObjet', 'Class "%s" does not exist, or is not a subclass of DataObjet',
$class $class
)); ));
} }
/** /**
* Updates an object with values, resolving aliases set through * Updates an object with values, resolving aliases set through
* {@link DataObject->fieldLabels()}. * {@link DataObject->fieldLabels()}.
* *
* @param String Class name * @param String Class name
* @param Array Map of field names or aliases to their values. * @param Array Map of field names or aliases to their values.
* @return Array Map of actual object properties to their values. * @return Array Map of actual object properties to their values.
*/ */
protected function convertFields($class, $fields) { protected function convertFields($class, $fields) {
$labels = singleton($class)->fieldLabels(); $labels = singleton($class)->fieldLabels();
foreach($fields as $fieldName => $fieldVal) { foreach($fields as $fieldName => $fieldVal) {
if(array_key_exists($fieldName, $labels)) { if(array_key_exists($fieldName, $labels)) {
unset($fields[$fieldName]); unset($fields[$fieldName]);
$fields[$labels[$fieldName]] = $fieldVal; $fields[$labels[$fieldName]] = $fieldVal;
} }
} }
return $fields; return $fields;
} }
protected function joinPaths() { protected function joinPaths() {
$args = func_get_args(); $args = func_get_args();
$paths = array(); $paths = array();
foreach($args as $arg) $paths = array_merge($paths, (array)$arg); foreach($args as $arg) $paths = array_merge($paths, (array)$arg);
foreach($paths as &$path) $path = trim($path, '/'); foreach($paths as &$path) $path = trim($path, '/');
if (substr($args[0], 0, 1) == '/') $paths[0] = '/' . $paths[0]; if (substr($args[0], 0, 1) == '/') $paths[0] = '/' . $paths[0];
return join('/', $paths); return join('/', $paths);
} }
} }