Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
44.44% covered (danger)
44.44%
20 / 45
25.00% covered (danger)
25.00%
1 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
table_helper
44.44% covered (danger)
44.44%
20 / 45
25.00% covered (danger)
25.00%
1 / 4
141.91
0.00% covered (danger)
0.00%
0 / 1
 convert_column_data
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
1
 resolve_dbms_specific_options
84.21% covered (warning)
84.21%
16 / 19
0.00% covered (danger)
0.00%
0 / 1
11.48
 get_default_column_option
0.00% covered (danger)
0.00%
0 / 21
0.00% covered (danger)
0.00%
0 / 1
182
 __construct
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2/**
3 *
4 * This file is part of the phpBB Forum Software package.
5 *
6 * @copyright (c) phpBB Limited <https://www.phpbb.com>
7 * @license GNU General Public License, version 2 (GPL-2.0)
8 *
9 * For full copyright and license information, please see
10 * the docs/CREDITS.txt file.
11 *
12 */
13namespace phpbb\db\doctrine;
14
15use InvalidArgumentException;
16
17class table_helper
18{
19    /**
20     * Converts phpBB's column representation to Doctrine's representation.
21     *
22     * @param array $column_data Column data.
23     *
24     * @return array<string, array> A pair of type and array of column options.
25     * @psalm-return array{string, array}
26     */
27    public static function convert_column_data(array $column_data, string $dbms_layer): array
28    {
29        $options = self::resolve_dbms_specific_options($column_data, $dbms_layer);
30        list($type, $opts) = type_converter::convert($column_data[0], $dbms_layer);
31        $options = array_merge($options, $opts);
32        return [$type, $options];
33    }
34
35    /**
36     * Resolve DBMS specific options in column data.
37     *
38     * @param array  $column_data Original column data.
39     * @param string $dbms_layer  DBMS layer name.
40     *
41     * @return array Doctrine column options.
42     */
43    private static function resolve_dbms_specific_options(array $column_data, string $dbms_layer): array
44    {
45        $doctrine_options = [];
46
47        if (is_array($column_data[1]))
48        {
49            $column_data[1] = self::get_default_column_option($column_data[1], $dbms_layer);
50        }
51
52        if (!is_null($column_data[1]))
53        {
54            $doctrine_options['default'] = $column_data[1];
55            $doctrine_options['notnull'] = true;
56        }
57        else
58        {
59            $doctrine_options['notnull'] = false;
60        }
61
62        $non_string_pattern = '/^[a-z]*(?:int|decimal|bool|timestamp)(?::[0-9]+)?$/';
63        if ($dbms_layer === 'oracle'
64            && !preg_match($non_string_pattern, strtolower($column_data[0]))
65            && array_key_exists('default', $doctrine_options)
66            && $doctrine_options['default'] === '')
67        {
68            // Not null is true by default and Oracle does not allow empty strings in not null columns
69            $doctrine_options['notnull'] = false;
70        }
71
72        if (isset($column_data[2]))
73        {
74            if ($column_data[2] === 'auto_increment')
75            {
76                $doctrine_options['autoincrement'] = true;
77            }
78            else if ($dbms_layer === 'mysql' && $column_data[2] === 'true_sort')
79            {
80                $doctrine_options['platformoptions']['collation'] = 'utf8_unicode_ci';
81            }
82        }
83
84        return $doctrine_options;
85    }
86
87    /**
88     * Returns the DBMS specific default value for a column definition.
89     *
90     * @param array  $default_options Database specific default value options.
91     * @param string $dbms_layer      Name of the DBMS layer.
92     *
93     * @return mixed Default value for the current DBMS.
94     *
95     * @throws InvalidArgumentException When `$schema_name` contains an invalid legacy DBMS name.
96     */
97    private static function get_default_column_option(array $default_options, string $dbms_layer)
98    {
99        switch ($dbms_layer)
100        {
101            case 'mysql':
102                return array_key_exists('mysql_41', $default_options)
103                    ? $default_options['mysql_41']
104                    : $default_options['default'];
105            case 'oracle':
106                return array_key_exists('oracle', $default_options)
107                    ? $default_options['oracle']
108                    : $default_options['default'];
109            case 'postgresql':
110                return array_key_exists('postgres', $default_options)
111                    ? $default_options['postgres']
112                    : $default_options['default'];
113            case 'mssql':
114                return array_key_exists('mssqlnative', $default_options)
115                    ? $default_options['mssqlnative']
116                    : (array_key_exists('mssql', $default_options) ? $default_options['mssql'] : $default_options['default']);
117            case 'sqlite':
118                return array_key_exists('sqlite3', $default_options)
119                    ? $default_options['sqlite3']
120                    : $default_options['default'];
121            default:
122                throw new InvalidArgumentException('Invalid schema name.');
123        }
124    }
125
126    /**
127     * Private constructor. Call methods of table_helper statically.
128     */
129    private function __construct()
130    {
131    }
132}