-
Notifications
You must be signed in to change notification settings - Fork 824
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b13b657
commit 44c7ac1
Showing
8 changed files
with
205 additions
and
122 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
<?php | ||
|
||
namespace SilverStripe\ORM\FieldType; | ||
|
||
use SilverStripe\Core\ClassInfo; | ||
use SilverStripe\Core\Config\Config; | ||
use SilverStripe\ORM\DataObject; | ||
|
||
trait DBClassNameTrait | ||
{ | ||
/** | ||
* Base classname of class to enumerate. | ||
* If 'DataObject' then all classes are included. | ||
* If empty, then the baseClass of the parent object will be used | ||
* | ||
* @var string|null | ||
*/ | ||
protected $baseClass = null; | ||
|
||
/** | ||
* Parent object | ||
* | ||
* @var DataObject|null | ||
*/ | ||
protected $record = null; | ||
|
||
private static $index = true; | ||
|
||
/** | ||
* Create a new DBClassName field | ||
* | ||
* @param string $name Name of field | ||
* @param string|null $baseClass Optional base class to limit selections | ||
* @param array $options Optional parameters for this DBField instance | ||
*/ | ||
public function __construct($name = null, $baseClass = null, $options = []) | ||
{ | ||
$this->setBaseClass($baseClass); | ||
parent::__construct($name, null, null, $options); | ||
} | ||
|
||
/** | ||
* Get the base dataclass for the list of subclasses | ||
* | ||
* @return string | ||
*/ | ||
public function getBaseClass() | ||
{ | ||
// Use explicit base class | ||
if ($this->baseClass) { | ||
return $this->baseClass; | ||
} | ||
// Default to the basename of the record | ||
$schema = DataObject::getSchema(); | ||
if ($this->record) { | ||
return $schema->baseDataClass($this->record); | ||
} | ||
// During dev/build only the table is assigned | ||
$tableClass = $schema->tableClass($this->getTable()); | ||
if ($tableClass && ($baseClass = $schema->baseDataClass($tableClass))) { | ||
return $baseClass; | ||
} | ||
// Fallback to global default | ||
return DataObject::class; | ||
} | ||
|
||
/** | ||
* Get the base name of the current class | ||
* Useful as a non-fully qualified CSS Class name in templates. | ||
* | ||
* @return string|null | ||
*/ | ||
public function getShortName() | ||
{ | ||
$value = $this->getValue(); | ||
if (empty($value) || !ClassInfo::exists($value)) { | ||
return null; | ||
} | ||
return ClassInfo::shortName($value); | ||
} | ||
|
||
/** | ||
* Assign the base class | ||
* | ||
* @param string $baseClass | ||
* @return $this | ||
*/ | ||
public function setBaseClass($baseClass) | ||
{ | ||
$this->baseClass = $baseClass; | ||
return $this; | ||
} | ||
|
||
/** | ||
* Get list of classnames that should be selectable | ||
* | ||
* @return array | ||
*/ | ||
public function getEnum() | ||
{ | ||
$classNames = ClassInfo::subclassesFor($this->getBaseClass()); | ||
$dataobject = strtolower(DataObject::class); | ||
unset($classNames[$dataobject]); | ||
return array_values($classNames ?? []); | ||
} | ||
|
||
public function setValue($value, $record = null, $markChanged = true) | ||
{ | ||
parent::setValue($value, $record, $markChanged); | ||
|
||
if ($record instanceof DataObject) { | ||
$this->record = $record; | ||
} | ||
|
||
return $this; | ||
} | ||
|
||
private function getDefaultClassName() | ||
{ | ||
// Allow classes to set default class | ||
$baseClass = $this->getBaseClass(); | ||
$defaultClass = Config::inst()->get($baseClass, 'default_classname'); | ||
if ($defaultClass && class_exists($defaultClass ?? '')) { | ||
return $defaultClass; | ||
} | ||
|
||
// Fallback to first option | ||
$subClassNames = $this->getEnum(); | ||
return reset($subClassNames); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<?php | ||
|
||
namespace SilverStripe\ORM\FieldType; | ||
|
||
use SilverStripe\ORM\FieldType\DBVarchar; | ||
|
||
/** | ||
* An alternative to DBClassName that stores the class name as a varchar instead of an enum | ||
* This will use more disk space, though will prevent issues with long dev/builds on | ||
* very large database tables when a ALTER TABLE queries are required to update the enum. | ||
* | ||
* Use the following config to use this class in your project: | ||
* | ||
* ``` | ||
* SilverStripe\ORM\DataObject: | ||
* fixed_fields: | ||
* ClassName: DBClassNameVarchar | ||
* ``` | ||
*/ | ||
class DBClassNameVarchar extends DBVarchar | ||
{ | ||
use DBClassNameTrait; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<?php | ||
|
||
namespace SilverStripe\ORM\Tests; | ||
|
||
use SilverStripe\Core\Config\Config; | ||
use SilverStripe\ORM\DataObject; | ||
use SilverStripe\ORM\FieldType\DBClassNameVarchar; | ||
use SilverStripe\ORM\FieldType\DBVarchar; | ||
use SilverStripe\ORM\Tests\DataObjectSchemaTest\HasFields; | ||
|
||
/** | ||
* These unit tests test will change DBClassName to a varchar column | ||
* and then test that the tests in DataObjectSchemaTest still pass | ||
* | ||
* There's also a test that a ClassName of an arbitary DataObject is a Varchar | ||
*/ | ||
class DBClassNameVarcharTest extends DataObjectSchemaTest | ||
{ | ||
public function setup(): void | ||
{ | ||
parent::setup(); | ||
$fixedFields = Config::inst()->get(DataObject::class, 'fixed_fields'); | ||
$fixedFields['ClassName'] = 'DBClassNameVarchar'; | ||
Config::modify()->set(DataObject::class, 'fixed_fields', $fixedFields); | ||
} | ||
|
||
public function testVarcharType(): void | ||
{ | ||
/** @var DataObject $obj */ | ||
$obj = HasFields::create(); | ||
$class = get_class($obj->dbObject('ClassName')); | ||
$this->assertSame(DBClassNameVarchar::class, $class); | ||
$this->assertTrue(is_a($class, DBVarchar::class, true)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters