Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
EnumType
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 4
90
0.00% covered (danger)
0.00%
0 / 1
 getSQLDeclaration
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
30
 makeEnumTypeSql
0.00% covered (danger)
0.00%
0 / 8
0.00% covered (danger)
0.00%
0 / 1
6
 formatValues
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 getName
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3namespace Wikimedia\Rdbms\DBAL;
4
5use Doctrine\DBAL\Platforms\AbstractPlatform;
6use Doctrine\DBAL\Platforms\MySQLPlatform;
7use Doctrine\DBAL\Platforms\PostgreSQLPlatform;
8use Doctrine\DBAL\Platforms\SQLitePlatform;
9use Doctrine\DBAL\Types\Type;
10use InvalidArgumentException;
11
12/**
13 * Custom handling for ENUM datatype
14 *
15 * NOTE: Use of this type is discouraged unless necessary. Please use
16 * alternative types where possible. See T119173 for the RFC discussion
17 * about this type and potential alternatives.
18 *
19 * @see https://phabricator.wikimedia.org/T119173
20 */
21class EnumType extends Type {
22    public const ENUM = 'mwenum';
23
24    /**
25     * Gets the SQL declaration snippet for an ENUM column
26     *
27     * @param mixed[] $column Column definition
28     * @param AbstractPlatform $platform
29     *
30     * @return string
31     */
32    public function getSQLDeclaration( array $column, AbstractPlatform $platform ): string {
33        // SQLite does not support ENUM type
34        if ( $platform instanceof SQLitePlatform ) {
35            return 'TEXT';
36        }
37
38        // PostgreSQL does support but needs custom handling.
39        // This just returns a string name that references the
40        // actual ENUM which will be created by CREATE TYPE command
41        // If 'fixed' option is not passed, this field will use TEXT
42        if ( $platform instanceof PostgreSQLPlatform ) {
43            if ( !$column['fixed'] ) {
44                return 'TEXT';
45            }
46
47            return strtoupper( $column['name'] . '_enum' );
48        }
49
50        if ( $platform instanceof MySQLPlatform ) {
51            $enumValues = $this->formatValues( $column['enum_values'] );
52            return "ENUM( $enumValues )";
53        }
54    }
55
56    /**
57     * Gets the sql portion to create ENUM for Postgres table column
58     *
59     * @param mixed[] $column
60     * @param AbstractPlatform $platform
61     *
62     * @see MWPostgreSqlPlatform::_getCreateTableSQL()
63     * @throws \InvalidArgumentException
64     * @return string
65     */
66    public function makeEnumTypeSql( $column, $platform ): string {
67        if ( !( $platform instanceof PostgreSQLPlatform ) ) {
68            throw new InvalidArgumentException(
69                __METHOD__ . ' can only be called on Postgres platform'
70            );
71        }
72
73        $enumName = strtoupper( $column['name'] . '_enum' );
74        $enumValues = $this->formatValues( $column['enum_values'] );
75        $typeSql = "\n\nCREATE TYPE $enumName AS ENUM( $enumValues )";
76
77        return $typeSql;
78    }
79
80    /**
81     * Get the imploded values suitable for pushing directly into ENUM();
82     *
83     * @param string[] $values
84     * @return string
85     */
86    public function formatValues( $values ): string {
87        $values = implode( "','", $values );
88        $enumValues = "'" . $values . "'";
89
90        return $enumValues;
91    }
92
93    public function getName(): string {
94        return self::ENUM;
95    }
96}