Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 109
0.00% covered (danger)
0.00%
0 / 11
CRAP
0.00% covered (danger)
0.00%
0 / 1
profilefield_base_migration
0.00% covered (danger)
0.00%
0 / 109
0.00% covered (danger)
0.00%
0 / 11
420
0.00% covered (danger)
0.00%
0 / 1
 effectively_installed
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 update_schema
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 revert_schema
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 update_data
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
2
 revert_data
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
2
 create_custom_field
0.00% covered (danger)
0.00%
0 / 26
0.00% covered (danger)
0.00%
0 / 1
12
 create_language_entries
0.00% covered (danger)
0.00%
0 / 13
0.00% covered (danger)
0.00%
0 / 1
12
 delete_custom_profile_field_data
0.00% covered (danger)
0.00%
0 / 10
0.00% covered (danger)
0.00%
0 / 1
2
 get_custom_profile_field_id
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
2
 convert_user_field_to_custom_field
0.00% covered (danger)
0.00%
0 / 27
0.00% covered (danger)
0.00%
0 / 1
30
 get_insert_sql_array
0.00% covered (danger)
0.00%
0 / 4
0.00% covered (danger)
0.00%
0 / 1
6
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*/
13
14namespace phpbb\db\migration;
15
16abstract class profilefield_base_migration extends container_aware_migration
17{
18    protected $profilefield_name;
19
20    protected $profilefield_database_type;
21
22    protected $profilefield_data;
23
24    /**
25    * Language data should be in array -> each language_data in separate key
26    * array(
27    *    array(
28    *        'option_id'    => value,
29    *        'field_type'    => value,
30    *        'lang_value'    => value,
31    *    ),
32    *    array(
33    *        'option_id'    => value,
34    *        'field_type'    => value,
35    *        'lang_value'    => value,
36    *    ),
37    * )
38    */
39    protected $profilefield_language_data;
40
41    protected $user_column_name;
42
43    private $profile_row;
44
45    public function effectively_installed()
46    {
47        return $this->db_tools->sql_column_exists($this->table_prefix . 'profile_fields_data', 'pf_' . $this->profilefield_name);
48    }
49
50    public function update_schema()
51    {
52        return array(
53            'add_columns'    => array(
54                $this->table_prefix . 'profile_fields_data'            => array(
55                    'pf_' . $this->profilefield_name        => $this->profilefield_database_type,
56                ),
57            ),
58        );
59    }
60
61    public function revert_schema()
62    {
63        return array(
64            'drop_columns'    => array(
65                $this->table_prefix . 'profile_fields_data'            => array(
66                    'pf_' . $this->profilefield_name,
67                ),
68            ),
69        );
70    }
71
72    public function update_data()
73    {
74        return array(
75            array('custom', array(array($this, 'create_custom_field'))),
76            array('custom', array(array($this, 'convert_user_field_to_custom_field'))),
77        );
78    }
79
80    public function revert_data()
81    {
82        return array(
83            array('custom', array(array($this, 'delete_custom_profile_field_data'))),
84        );
85    }
86
87    public function create_custom_field()
88    {
89        $sql = 'SELECT MAX(field_order) as max_field_order
90            FROM ' . PROFILE_FIELDS_TABLE;
91        $result = $this->db->sql_query($sql);
92        $max_field_order = (int) $this->db->sql_fetchfield('max_field_order');
93        $this->db->sql_freeresult($result);
94
95        $sql_ary = array_merge($this->profilefield_data, array(
96            'field_order'            => $max_field_order + 1,
97        ));
98
99        $sql = 'INSERT INTO ' . PROFILE_FIELDS_TABLE . ' ' . $this->db->sql_build_array('INSERT', $sql_ary);
100        $this->db->sql_query($sql);
101        $field_id = (int) $this->db->sql_nextid();
102
103        $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, PROFILE_LANG_TABLE);
104
105        $sql = 'SELECT lang_id
106            FROM ' . LANG_TABLE;
107        $result = $this->db->sql_query($sql);
108        $lang_name = (strpos($this->profilefield_name, 'phpbb_') === 0) ? strtoupper(substr($this->profilefield_name, 6)) : strtoupper($this->profilefield_name);
109        while ($lang_id = (int) $this->db->sql_fetchfield('lang_id'))
110        {
111            $insert_buffer->insert(array(
112                'field_id'                => (int) $field_id,
113                'lang_id'                => (int) $lang_id,
114                'lang_name'                => $lang_name,
115                'lang_explain'            => '',
116                'lang_default_value'    => '',
117            ));
118        }
119        $this->db->sql_freeresult($result);
120
121        $insert_buffer->flush();
122    }
123
124    /**
125    * Create Custom profile fields languguage entries
126    */
127    public function create_language_entries()
128    {
129        $field_id = $this->get_custom_profile_field_id();
130
131        $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, PROFILE_FIELDS_LANG_TABLE);
132
133        $sql = 'SELECT lang_id
134            FROM ' . LANG_TABLE;
135        $result = $this->db->sql_query($sql);
136        while ($lang_id = (int) $this->db->sql_fetchfield('lang_id'))
137        {
138            foreach ($this->profilefield_language_data as $language_data)
139            {
140                $insert_buffer->insert(array_merge(array(
141                    'field_id'    => (int) $field_id,
142                    'lang_id'    => (int) $lang_id,
143                ), $language_data));
144            }
145        }
146        $this->db->sql_freeresult($result);
147
148        $insert_buffer->flush();
149    }
150
151    /**
152    * Clean database when reverting the migration
153    */
154    public function delete_custom_profile_field_data()
155    {
156        $field_id = $this->get_custom_profile_field_id();
157
158        $sql = 'DELETE FROM ' . PROFILE_FIELDS_TABLE . '
159            WHERE field_id = ' . (int) $field_id;
160        $this->db->sql_query($sql);
161
162        $sql = 'DELETE FROM ' . PROFILE_LANG_TABLE . '
163            WHERE field_id = ' . (int) $field_id;
164        $this->db->sql_query($sql);
165
166        $sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . '
167            WHERE field_id = ' . (int) $field_id;
168        $this->db->sql_query($sql);
169    }
170
171    /**
172    * Get custom profile field id
173    * @return    int    custom profile filed id
174    */
175    public function get_custom_profile_field_id()
176    {
177        $sql = 'SELECT field_id
178            FROM ' . PROFILE_FIELDS_TABLE . "
179            WHERE field_name = '" . $this->profilefield_name . "'";
180        $result = $this->db->sql_query($sql);
181        $field_id = (int) $this->db->sql_fetchfield('field_id');
182        $this->db->sql_freeresult($result);
183
184        return $field_id;
185    }
186
187    /**
188    * @param    int            $start        Start of staggering step
189    * @return    int|null    int start of the next step, null if the end was reached
190    */
191    public function convert_user_field_to_custom_field($start)
192    {
193        $insert_buffer = new \phpbb\db\sql_insert_buffer($this->db, $this->table_prefix . 'profile_fields_data');
194        $limit = 250;
195        $converted_users = 0;
196        $start = $start ?: 0;
197
198        $sql = 'SELECT user_id, ' . $this->user_column_name . '
199            FROM ' . $this->table_prefix . 'users
200            WHERE ' . $this->user_column_name . " <> ''
201            ORDER BY user_id";
202        $result = $this->db->sql_query_limit($sql, $limit, $start);
203
204        while ($row = $this->db->sql_fetchrow($result))
205        {
206            $converted_users++;
207
208            $cp_data = array(
209                'pf_' . $this->profilefield_name        => $row[$this->user_column_name],
210            );
211
212            $sql = 'UPDATE ' . $this->table_prefix . 'profile_fields_data
213                SET ' . $this->db->sql_build_array('UPDATE', $cp_data) . '
214                WHERE user_id = ' . (int) $row['user_id'];
215            $this->db->sql_query($sql);
216
217            if (!$this->db->sql_affectedrows())
218            {
219                $cp_data['user_id'] = (int) $row['user_id'];
220                $cp_data = array_merge($this->get_insert_sql_array(), $cp_data);
221                $insert_buffer->insert($cp_data);
222            }
223        }
224        $this->db->sql_freeresult($result);
225
226        $insert_buffer->flush();
227
228        if ($converted_users < $limit)
229        {
230            // No more users left, we are done...
231            return null;
232        }
233
234        return $start + $limit;
235    }
236
237    protected function get_insert_sql_array()
238    {
239        if ($this->profile_row === null)
240        {
241            /* @var $manager \phpbb\profilefields\manager */
242            $manager = $this->container->get('profilefields.manager');
243            $this->profile_row = $manager->build_insert_sql_array(array());
244        }
245
246        return $this->profile_row;
247    }
248}