Skip to content

Instantly share code, notes, and snippets.

@66Ton99
Last active August 29, 2015 14:02
Show Gist options
  • Save 66Ton99/c4891b193ba5e430170e to your computer and use it in GitHub Desktop.
Save 66Ton99/c4891b193ba5e430170e to your computer and use it in GitHub Desktop.
DataBundle with Enums
<?php
namespace MyNamespace;
use Symfony\Component\HttpKernel\Bundle\Bundle;
use Doctrine\DBAL\Types\Type;
class DataBundle extends Bundle
{
/**
* @var bool
*/
protected static $isLoaded = false;
/**
* {@inheritdoc}
*/
public function boot()
{
if (!static::$isLoaded) { // TODO find better way
static::$isLoaded = true;
Type::addType('ContractStatus', 'MyNamespace\Enum\ContractStatus');
$databasePlatform = $this->container->get('doctrine')
->getManager()
->getConnection()
->getDatabasePlatform();
$databasePlatform->registerDoctrineTypeMapping('enum', 'string');
}
}
}
<?php
namespace MyNamespace\Entity;
use MyNamespace\Enum\ContractStatus;
class ContractEntity
{
/**
* @ORM\Column(name="id", type="bigint")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* @ORM\Column(
* type="ContractStatus",
* options={
* "default"="pending"
* }
* )
* TODO solve default values problem!
*/
protected $status = ContractStatus::PENDING;
/**
* Get id
*
* @return integer
*/
public function getId()
{
return $this->id;
}
/**
* Set status
*
* @param string $status
* @return Unit
*/
public function setStatus($status = ContractStatus::PENDING)
{
$this->status = $status;
return $this;
}
/**
* Get status
*
* @return string
*/
public function getStatus()
{
return $this->status;
}
}
<?php
namespace MyNamespace;
use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;
/**
* Base Enum class
*
* @author Ton Sharp <66ton99@gmail.com>
*/
abstract class Enum extends Type
{
/**
* Titles cache
*
* @var array
*/
private static $cachedTitles = array();
/**
* Specific titles
*
* @var array
*/
protected static $titles = array();
/**
* Pointer to the translator function
*
* @var callback
*/
protected static $translator;
/**
* @return array
*/
public static function all()
{
$reflection = static::getRC();
$buffer = $reflection->getConstants();
foreach (array($reflection->getParentClass()) + $reflection->getInterfaces() as $fill) {
$buffer = array_diff_key($buffer, $fill->getConstants());
}
return $buffer;
}
/**
* Values
*
* @return array
*/
public static function values()
{
return array_values(static::all());
}
/**
* Keys
*
* @return array
*/
public static function keys()
{
return array_keys(static::all());
}
/**
* Translated titles
*
* @return array
*/
public static function cachedTitles($sort = false, $isTitlesAsKeys = false)
{
$class = get_called_class();
if (!empty(self::$cachedTitles[$class]) && null !== self::$cachedTitles[$class]) {
return self::$cachedTitles[$class];
}
$titles = array();
foreach (static::values() as $val) {
if (!empty(static::$titles[$val])) {
$title = static::$titles[$val];
} else {
$title = ucfirst(str_replace('_', ' ', $val));
}
if ($isTitlesAsKeys) {
$titles[$title] = $title;
} else {
$titles[$val] = $title;
}
}
$titles = array_map(self::getTranslator(), $titles);
if ($sort) {
asort($titles);
}
return self::$cachedTitles[$class] = $titles;
}
/**
* Translated title
*
* @var string|int $value - on '' & null will return default value
*
* @return string
*/
public static function title($value)
{
$titles = static::cachedTitles();
if ('' === $value || null === $value) {
$value = static::defautVal();
}
static::throwsInvalid($value);
return $titles[$value];
}
/**
* Check value
*
* @param string|int $value
*
* @return bool
*/
public static function isValid($value)
{
return in_array($value, static::all(), false);
}
/**
* Check value with exception on fail
*
* @param mixed $value
*
* @throws \InvalidArgumentException if the value does not valid for the enum type
*
* @return void
*/
public static function throwsInvalid($value)
{
if (!static::isValid($value)) {
throw new \InvalidArgumentException(
sprintf(
'The enum type `%s` does not contains value `%s` . Possible values are `%s`',
get_called_class(),
var_export($value, true),
static::implode('`, `')
)
);
}
}
/**
* Implode all values to the string separated by $separator
*
* @param string $separator
*
* @return string
*/
public static function implode($separator = "','")
{
return "'" . implode($separator, static::values()) . "'";
}
/**
* Set translator callback function
*
* @param callback $translator
*
* @return void
*/
public static function setTranslator($translator)
{
self::$translator = $translator;
}
/**
* Get translator function
*
* @return callback
*/
public static function getTranslator()
{
if (false == self::$translator) {
self::$translator = function ($title) {
return $title;
};
}
return self::$translator;
}
/**
* Get reflection class
*
* @return \ReflectionClass
*/
protected static function getRC()
{
return new \ReflectionClass(get_called_class());
}
/**
* Search in titles
*
* @param string $needle
*
* @return array - of keys
*/
public static function search($needle)
{
$return = array();
foreach (static::cachedTitles() as $key => $val) {
if (false !== stristr($val, $needle)) {
$return[] = $key;
}
}
return $return;
}
/**
* Get default values by default it is first element
*
* @return string
*/
public static function defaultValue()
{
$values = (static::values());
return array_shift($values);
}
/**
* {@inheritdoc}
*/
public function getSqlDeclaration(array $fieldDeclaration, AbstractPlatform $platform)
{
return "ENUM(" . static::implode() . ") COMMENT '(DC2Type:" . $this->getName() . ")'";
}
/**
* {@inheritdoc}
*/
public function convertToPHPValue($value, AbstractPlatform $platform)
{
return $value;
}
/**
* {@inheritdoc}
*/
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
static::throwsInvalid($value);
return $value;
}
/**
* {@inheritdoc}
*/
public function getName()
{
return substr(get_called_class(), strrpos(get_called_class(), '\\') + 1);
}
}
<?php
namespace MyNamespace\Enum;
use MyNamespace\Enum;
class ContractStatus extends \CreditJeeves\CoreBundle\Enum
{
/**
* @var string
*/
const PENDING = 'pending';
/**
* @var string
*/
const INVITE = 'invite';
/**
* @var string
*/
const APPROVED = 'approved';
/**
* @var string
*/
const CURRENT = 'current';
/**
* @var string
*/
const FINISHED = 'finished';
/**
* @var string
*/
const DELETED = 'deleted';
}
@66Ton99
Copy link
Author

66Ton99 commented Jun 17, 2014

This solution have problems with migration-diff method - it does not recognise it and mark always as changed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment