Verzeichnisstruktur phpBB-3.3.15


Veröffentlicht
28.08.2024

So funktioniert es


Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück

Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis.
Auf den Verzeichnisnamen klicken, dies zeigt nur das Verzeichnis mit Inhalt an

(Beispiel Datei-Icons)

Auf das Icon klicken um den Quellcode anzuzeigen

manager.php

Zuletzt modifiziert: 02.04.2025, 15:02 - Dateigröße: 22.50 KiB


001  <?php
002  /**
003   *
004   * This file is part of the phpBB Forum Software package.
005   *
006   * @copyright (c) phpBB Limited <https://www.phpbb.com>
007   * @license GNU General Public License, version 2 (GPL-2.0)
008   *
009   * For full copyright and license information, please see
010   * the docs/CREDITS.txt file.
011   *
012   */
013   
014  namespace phpbb\profilefields;
015   
016  /**
017   * Custom Profile Fields (CPF) manager.
018   */
019  class manager
020  {
021      /** @var \phpbb\auth\auth */
022      protected $auth;
023   
024      /** @var \phpbb\config\db_text */
025      protected $config_text;
026   
027      /** @var \phpbb\db\driver\driver_interface */
028      protected $db;
029   
030      /** @var \phpbb\db\tools\tools */
031      protected $db_tools;
032   
033      /** @var \phpbb\event\dispatcher_interface */
034      protected $dispatcher;
035   
036      /** @var \phpbb\language\language */
037      protected $language;
038   
039      /** @var \phpbb\log\log */
040      protected $log;
041   
042      /** @var \phpbb\request\request */
043      protected $request;
044   
045      /** @var \phpbb\template\template */
046      protected $template;
047   
048      /** @var \phpbb\di\service_collection */
049      protected $type_collection;
050   
051      /** @var \phpbb\user */
052      protected $user;
053   
054      /** @var string Profile fields table */
055      protected $fields_table;
056   
057      /** @var string Profile fields data table */
058      protected $fields_data_table;
059   
060      /** @var string Profile fields data (options) table */
061      protected $fields_data_lang_table;
062   
063      /** @var string Profile fields language table */
064      protected $fields_lang_table;
065   
066      /** @var array Users custom profile fields cache */
067      protected $profile_cache = [];
068   
069      /**
070       * Construct
071       *
072       * @param \phpbb\auth\auth                    $auth                    Auth object
073       * @param \phpbb\config\db_text                $config_text            Config_text object
074       * @param \phpbb\db\driver\driver_interface    $db                        Database object
075       * @param \phpbb\db\tools\tools                $db_tools                Database tools object
076       * @param \phpbb\event\dispatcher_interface    $dispatcher                Event dispatcher object
077       * @param \phpbb\language\language            $language                Language object
078       * @param \phpbb\log\log                    $log                    Log object
079       * @param \phpbb\request\request            $request                Request object
080       * @param \phpbb\template\template            $template                Template object
081       * @param \phpbb\di\service_collection        $type_collection        CPF Type collection
082       * @param \phpbb\user                        $user                    User object
083       * @param string                            $fields_table            CPF Table
084       * @param string                            $fields_data_table        CPF Data table
085       * @param string                            $fields_data_lang_table    CPF Data language table
086       * @param string                            $fields_lang_table        CPF Language table
087       */
088      public function __construct(
089          \phpbb\auth\auth $auth,
090          \phpbb\config\db_text $config_text,
091          \phpbb\db\driver\driver_interface $db,
092          \phpbb\db\tools\tools $db_tools,
093          \phpbb\event\dispatcher_interface $dispatcher,
094          \phpbb\language\language $language,
095          \phpbb\log\log $log,
096          \phpbb\request\request $request,
097          \phpbb\template\template $template,
098          \phpbb\di\service_collection $type_collection,
099          \phpbb\user $user,
100          $fields_table,
101          $fields_data_table,
102          $fields_data_lang_table,
103          $fields_lang_table
104      )
105      {
106          $this->auth                = $auth;
107          $this->config_text        = $config_text;
108          $this->db                = $db;
109          $this->db_tools            = $db_tools;
110          $this->dispatcher        = $dispatcher;
111          $this->language            = $language;
112          $this->log                = $log;
113          $this->request            = $request;
114          $this->template            = $template;
115          $this->type_collection    = $type_collection;
116          $this->user                = $user;
117   
118          $this->fields_table                = $fields_table;
119          $this->fields_data_table        = $fields_data_table;
120          $this->fields_data_lang_table    = $fields_data_lang_table;
121          $this->fields_lang_table        = $fields_lang_table;
122      }
123   
124      /**
125       * Assign editable fields to template.
126       *
127       * Called by ucp_profile and ucp_register.
128       *
129       * @param string    $mode        The mode (profile|register)
130       * @param int        $lang_id    The language identifier
131       * @return void
132       */
133      public function generate_profile_fields($mode, $lang_id)
134      {
135          $sql_where = '';
136   
137          switch ($mode)
138          {
139              case 'register':
140                  // If the field is required we show it on the registration page
141                  $sql_where .= ' AND f.field_show_on_reg = 1';
142              break;
143   
144              case 'profile':
145                  // Show hidden fields to moderators/admins
146                  if (!$this->auth->acl_gets('a_', 'm_') && !$this->auth->acl_getf_global('m_'))
147                  {
148                      $sql_where .= ' AND f.field_show_profile = 1';
149                  }
150              break;
151   
152              default:
153                  trigger_error('NO_MODE', E_USER_ERROR);
154              break;
155          }
156   
157          $has_required = false;
158   
159          $sql = 'SELECT l.*, f.*
160              FROM ' . $this->fields_lang_table . ' l,
161                  ' . $this->fields_table . ' f
162              WHERE l.field_id = f.field_id
163                  AND f.field_active = 1
164                  AND l.lang_id = ' . (int) $lang_id
165              . $sql_where . '
166              ORDER BY f.field_order ASC';
167          $result = $this->db->sql_query($sql);
168          while ($row = $this->db->sql_fetchrow($result))
169          {
170              /** @var \phpbb\profilefields\type\type_interface $profile_field */
171              $profile_field = $this->type_collection[$row['field_type']];
172   
173              $has_required = $has_required || $row['field_required'];
174   
175              $this->template->assign_block_vars('profile_fields', [
176                  'FIELD'            => $profile_field->process_field_row('change', $row),
177                  'FIELD_ID'        => $profile_field->get_field_ident($row),
178                  'LANG_NAME'        => $this->language->lang($row['lang_name']),
179                  'LANG_EXPLAIN'    => $this->language->lang($row['lang_explain']),
180                  'S_REQUIRED'    => (bool) $row['field_required'],
181              ]);
182          }
183          $this->db->sql_freeresult($result);
184   
185          $this->template->assign_var('PROFILE_FIELDS_REQUIRED', $has_required);
186      }
187   
188      /**
189       * Build profile cache, used for display.
190       *
191       * @return void
192       */
193      protected function build_cache()
194      {
195          $this->profile_cache = [];
196   
197          // Display hidden/no_view fields for admin/moderator
198          $sql_where = !$this->auth->acl_gets('a_', 'm_') && !$this->auth->acl_getf_global('m_') ? ' AND f.field_hide = 0' : '';
199   
200          $sql = 'SELECT l.*, f.*
201              FROM ' . $this->fields_lang_table . ' l,
202                  ' . $this->fields_table . ' f
203              WHERE l.field_id = f.field_id
204                  AND f.field_active = 1
205                  AND f.field_no_view = 0
206                  AND l.lang_id = ' . $this->user->get_iso_lang_id()
207              . $sql_where . '
208              ORDER BY f.field_order ASC';
209          $result = $this->db->sql_query($sql);
210          while ($row = $this->db->sql_fetchrow($result))
211          {
212              $this->profile_cache[$row['field_ident']] = $row;
213          }
214          $this->db->sql_freeresult($result);
215      }
216   
217      /**
218       * Submit profile field for validation.
219       *
220       * @param string    $mode        The mode (profile|register)
221       * @param int        $lang_id    The language identifier
222       * @param array        $cp_data    Custom profile field data
223       * @param array        $cp_error    Custom profile field errors
224       */
225      public function submit_cp_field($mode, $lang_id, &$cp_data, &$cp_error)
226      {
227          $sql_where = '';
228   
229          switch ($mode)
230          {
231              case 'register':
232                  // If the field is required we show it on the registration page
233                  $sql_where .= ' AND f.field_show_on_reg = 1';
234              break;
235   
236              case 'profile':
237                  // Show hidden fields to moderators/admins
238                  if (!$this->auth->acl_gets('a_', 'm_') && !$this->auth->acl_getf_global('m_'))
239                  {
240                      $sql_where .= ' AND f.field_show_profile = 1';
241                  }
242              break;
243   
244              default:
245                  trigger_error('NO_MODE', E_USER_ERROR);
246              break;
247          }
248   
249          $sql = 'SELECT l.*, f.*
250              FROM ' . $this->fields_lang_table . ' l,
251                  ' . $this->fields_table . ' f
252              WHERE l.field_id = f.field_id
253                  AND f.field_active = 1
254                  AND l.lang_id = ' . (int) $lang_id
255              . $sql_where . '
256              ORDER BY f.field_order';
257          $result = $this->db->sql_query($sql);
258          while ($row = $this->db->sql_fetchrow($result))
259          {
260              /** @var \phpbb\profilefields\type\type_interface $profile_field */
261              $profile_field = $this->type_collection[$row['field_type']];
262              $cp_data['pf_' . $row['field_ident']] = $profile_field->get_profile_field($row);
263   
264              /**
265               * Replace Emoji and other 4bit UTF-8 chars not allowed by MySQL
266               * with their Numeric Character Reference's Hexadecimal notation.
267               */
268              if (is_string($cp_data['pf_' . $row['field_ident']]))
269              {
270                  $cp_data['pf_' . $row['field_ident']] = utf8_encode_ucr($cp_data['pf_' . $row['field_ident']]);
271              }
272   
273              $check_value = $cp_data['pf_' . $row['field_ident']];
274   
275              if (($cp_result = $profile_field->validate_profile_field($check_value, $row)) !== false)
276              {
277                  // If the result is not false, it's an error message
278                  $cp_error[] = $cp_result;
279              }
280          }
281          $this->db->sql_freeresult($result);
282      }
283   
284      /**
285       * Update profile field data directly.
286       *
287       * @param int        $user_id        The user identifier
288       * @param array        $cp_data        Custom profile field data
289       */
290      public function update_profile_field_data($user_id, $cp_data)
291      {
292          if (empty($cp_data))
293          {
294              return;
295          }
296   
297          $sql = 'UPDATE ' . $this->fields_data_table . '
298              SET ' . $this->db->sql_build_array('UPDATE', $cp_data) . '
299              WHERE user_id = ' . (int) $user_id;
300          $this->db->sql_query($sql);
301   
302          if (!$this->db->sql_affectedrows())
303          {
304              $cp_data = $this->build_insert_sql_array($cp_data);
305              $cp_data['user_id'] = (int) $user_id;
306   
307              $sql = 'INSERT INTO ' . $this->fields_data_table . $this->db->sql_build_array('INSERT', $cp_data);
308              $this->db->sql_query($sql);
309          }
310      }
311   
312      /**
313       * Generate the template arrays in order to display the column names.
314       *
315       * @param string    $restrict_option    Restrict the published fields to a certain profile field option
316       * @return array                        Returns an array with the template variables type,
317       *                                         name and explain for the fields to display
318       */
319      public function generate_profile_fields_template_headlines($restrict_option = '')
320      {
321          if (empty($this->profile_cache))
322          {
323              $this->build_cache();
324          }
325   
326          $tpl_fields = [];
327   
328          // Go through the fields in correct order
329          foreach ($this->profile_cache as $field_ident => $field_data)
330          {
331              if ($restrict_option && !$field_data[$restrict_option])
332              {
333                  continue;
334              }
335   
336              /** @var \phpbb\profilefields\type\type_interface $profile_field */
337              $profile_field = $this->type_collection[$field_data['field_type']];
338   
339              $tpl_fields[] = [
340                  'PROFILE_FIELD_IDENT'    => $field_ident,
341                  'PROFILE_FIELD_TYPE'    => $field_data['field_type'],
342                  'PROFILE_FIELD_NAME'    => $profile_field->get_field_name($field_data['lang_name']),
343                  'PROFILE_FIELD_EXPLAIN'    => $this->language->lang($field_data['lang_explain']),
344              ];
345          }
346   
347          $profile_cache = $this->profile_cache;
348   
349          /**
350           * Event to modify template headlines of the generated profile fields
351           *
352           * @event core.generate_profile_fields_template_headlines
353           * @var string    restrict_option    Restrict the published fields to a certain profile field option
354           * @var array    tpl_fields        Array with template data fields
355           * @var array    profile_cache    A copy of the profile cache to make additional checks
356           * @since 3.1.6-RC1
357           */
358          $vars = ['restrict_option', 'tpl_fields', 'profile_cache'];
359          extract($this->dispatcher->trigger_event('core.generate_profile_fields_template_headlines', compact($vars)));
360          unset($profile_cache);
361   
362          return $tpl_fields;
363      }
364   
365      /**
366       * Grab the user specific profile fields data.
367       *
368       * @param int|array    $user_ids    Single user id or an array of ids
369       * @return array                Users profile fields data
370       */
371      public function grab_profile_fields_data($user_ids = 0)
372      {
373          if (empty($this->profile_cache))
374          {
375              $this->build_cache();
376          }
377   
378          if (empty($user_ids))
379          {
380              return [];
381          }
382   
383          $user_ids = (array) $user_ids;
384   
385          $sql = 'SELECT *
386              FROM ' . $this->fields_data_table . '
387              WHERE ' . $this->db->sql_in_set('user_id', array_map('intval', $user_ids));
388          $result = $this->db->sql_query($sql);
389          $rowset = $this->db->sql_fetchrowset($result);
390          $this->db->sql_freeresult($result);
391   
392          $field_data = array_column($rowset, null, 'user_id');
393   
394          /**
395           * Event to modify profile fields data retrieved from the database
396           *
397           * @event core.grab_profile_fields_data
398           * @var array    user_ids        Single user id or an array of ids
399           * @var array    field_data        Array with profile fields data
400           * @since 3.1.0-b3
401           */
402          $vars = ['user_ids', 'field_data'];
403          extract($this->dispatcher->trigger_event('core.grab_profile_fields_data', compact($vars)));
404   
405          $user_fields = [];
406   
407          // Go through the fields in correct order
408          foreach (array_keys($this->profile_cache) as $used_ident)
409          {
410              foreach ($field_data as $user_id => $row)
411              {
412                  $user_fields[$user_id][$used_ident]['value'] = $row['pf_' . $used_ident];
413                  $user_fields[$user_id][$used_ident]['data'] = $this->profile_cache[$used_ident];
414              }
415   
416              foreach ($user_ids as $user_id)
417              {
418                  if (!isset($user_fields[$user_id][$used_ident]))
419                  {
420                      $user_fields[$user_id][$used_ident]['value'] = '';
421                      $user_fields[$user_id][$used_ident]['data'] = $this->profile_cache[$used_ident];
422                  }
423              }
424          }
425   
426          return $user_fields;
427      }
428   
429      /**
430       * Generate the user's profile fields data for the template.
431       *
432       * @param array        $profile_row        Array with users profile field data
433       * @param bool        $use_contact_fields    Should we display contact fields as such?
434       *                                         This requires special treatments:
435       *                                         (links should not be parsed in the values, and more)
436       * @return array                        The user's profile fields data
437       */
438      public function generate_profile_fields_template_data($profile_row, $use_contact_fields = true)
439      {
440          // $profile_row == $user_fields[$row['user_id']];
441          $tpl_fields = [
442              'row'        => [],
443              'blockrow'    => [],
444          ];
445   
446          /**
447           * Event to modify data of the generated profile fields, before the template assignment loop
448           *
449           * @event core.generate_profile_fields_template_data_before
450           * @var array    profile_row            Array with users profile field data
451           * @var array    tpl_fields            Array with template data fields
452           * @var bool    use_contact_fields    Should we display contact fields as such?
453           * @since 3.1.0-b3
454           */
455          $vars = ['profile_row', 'tpl_fields', 'use_contact_fields'];
456          extract($this->dispatcher->trigger_event('core.generate_profile_fields_template_data_before', compact($vars)));
457   
458          foreach ($profile_row as $ident => $ident_ary)
459          {
460              /** @var \phpbb\profilefields\type\type_interface $profile_field */
461              $profile_field = $this->type_collection[$ident_ary['data']['field_type']];
462   
463              $value = $profile_field->get_profile_value($ident_ary['value'], $ident_ary['data']);
464              $value_raw = $profile_field->get_profile_value_raw($ident_ary['value'], $ident_ary['data']);
465   
466              if ($value === null)
467              {
468                  continue;
469              }
470   
471              $field_desc = '';
472              $contact_url = '';
473              $ident_upper = strtoupper($ident);
474   
475              if ($use_contact_fields && $ident_ary['data']['field_is_contact'])
476              {
477                  $value = $profile_field->get_profile_contact_value($ident_ary['value'], $ident_ary['data']);
478                  $field_desc = $this->language->lang($ident_ary['data']['field_contact_desc']);
479   
480                  if (strpos($field_desc, '%s') !== false)
481                  {
482                      $field_desc = sprintf($field_desc, $value);
483                  }
484   
485                  if (strpos($ident_ary['data']['field_contact_url'], '%s') !== false)
486                  {
487                      $contact_url = sprintf($ident_ary['data']['field_contact_url'], $value);
488                  }
489              }
490   
491              $tpl_fields['row'] += [
492                  "PROFILE_{$ident_upper}_IDENT"        => $ident,
493                  "PROFILE_{$ident_upper}_VALUE"        => $value,
494                  "PROFILE_{$ident_upper}_VALUE_RAW"    => $value_raw,
495                  "PROFILE_{$ident_upper}_CONTACT"    => $contact_url,
496                  "PROFILE_{$ident_upper}_DESC"        => $field_desc,
497                  "PROFILE_{$ident_upper}_TYPE"        => $ident_ary['data']['field_type'],
498                  "PROFILE_{$ident_upper}_NAME"        => $this->language->lang($ident_ary['data']['lang_name']),
499                  "PROFILE_{$ident_upper}_EXPLAIN"    => $this->language->lang($ident_ary['data']['lang_explain']),
500   
501                  "S_PROFILE_{$ident_upper}_CONTACT"    => $ident_ary['data']['field_is_contact'],
502                  "S_PROFILE_{$ident_upper}"            => true,
503              ];
504   
505              $tpl_fields['blockrow'][] = [
506                  'PROFILE_FIELD_IDENT'        => $ident,
507                  'PROFILE_FIELD_VALUE'        => $value,
508                  'PROFILE_FIELD_VALUE_RAW'    => $value_raw,
509                  'PROFILE_FIELD_CONTACT'        => $contact_url,
510                  'PROFILE_FIELD_DESC'        => $field_desc,
511                  'PROFILE_FIELD_TYPE'        => $ident_ary['data']['field_type'],
512                  'PROFILE_FIELD_NAME'        => $this->language->lang($ident_ary['data']['lang_name']),
513                  'PROFILE_FIELD_EXPLAIN'        => $this->language->lang($ident_ary['data']['lang_explain']),
514   
515                  'S_PROFILE_CONTACT'            => $ident_ary['data']['field_is_contact'],
516                  "S_PROFILE_{$ident_upper}"    => true,
517              ];
518          }
519   
520          /**
521           * Event to modify template data of the generated profile fields
522           *
523           * @event core.generate_profile_fields_template_data
524           * @var array    profile_row        Array with users profile field data
525           * @var array    tpl_fields        Array with template data fields
526           * @var bool    use_contact_fields    Should we display contact fields as such?
527           * @since 3.1.0-b3
528           */
529          $vars = ['profile_row', 'tpl_fields', 'use_contact_fields'];
530          extract($this->dispatcher->trigger_event('core.generate_profile_fields_template_data', compact($vars)));
531   
532          return $tpl_fields;
533      }
534   
535      /**
536       * Build array for the custom profile fields table.
537       *
538       * @param array        $cp_data        Custom profile field data
539       * @return array                    Custom profile field data for SQL usage
540       */
541      public function build_insert_sql_array($cp_data)
542      {
543          $prefix = 'pf_';
544          $length = strlen($prefix);
545          $not_in = [];
546   
547          foreach ($cp_data as $key => $null)
548          {
549              $not_in[] = strncmp($key, $prefix, $length) === 0 ? substr($key, $length) : $key;
550          }
551   
552          $sql = 'SELECT f.field_type, f.field_ident, f.field_default_value, l.lang_default_value
553              FROM ' . $this->fields_lang_table . ' l,
554                  ' . $this->fields_table . ' f
555              WHERE l.field_id = f.field_id
556                  AND l.lang_id = ' . $this->user->get_iso_lang_id() .
557                  (!empty($not_in) ? ' AND ' . $this->db->sql_in_set('f.field_ident', $not_in, true) : '');
558          $result = $this->db->sql_query($sql);
559          while ($row = $this->db->sql_fetchrow($result))
560          {
561              /** @var \phpbb\profilefields\type\type_interface $profile_field */
562              $profile_field = $this->type_collection[$row['field_type']];
563              $cp_data[$prefix . $row['field_ident']] = $profile_field->get_default_field_value($row);
564          }
565          $this->db->sql_freeresult($result);
566   
567          return $cp_data;
568      }
569   
570      /**
571       * Disable all profile fields of a certain type.
572       *
573       * This should be called when an extension which has profile field types is disabled
574       * so that all those profile fields are hidden and do not cause errors.
575       *
576       * @param string    $type_name        Type identifier of the profile fields
577       */
578      public function disable_profilefields($type_name)
579      {
580          // Get the list of active profile fields of this type
581          $profile_fields = $this->list_profilefields($type_name, true);
582   
583          // If no profile fields affected, then nothing to do
584          if (empty($profile_fields))
585          {
586              return;
587          }
588   
589          // Update the affected profile fields to "inactive"
590          $sql = 'UPDATE ' . $this->fields_table . '
591              SET field_active = 0
592              WHERE field_active = 1
593                  AND ' . $this->db->sql_in_set('field_id', array_keys($profile_fields));
594          $this->db->sql_query($sql);
595   
596          // Save modified information into a config_text field to recover on enable
597          $this->config_text->set($type_name . '.saved', json_encode($profile_fields));
598   
599          // Log activity
600          foreach ($profile_fields as $field_ident)
601          {
602              $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_PROFILE_FIELD_DEACTIVATE', time(), [$field_ident]);
603          }
604      }
605   
606      /**
607       * Purge all profile fields of a certain type.
608       *
609       * This should be called when an extension which has profile field types is purged
610       * so that all those profile fields are removed.
611       *
612       * @param string    $type_name        Type identifier of the profile fields
613       */
614      public function purge_profilefields($type_name)
615      {
616          // Remove the information saved on disable in a config_text field, not needed any longer
617          $this->config_text->delete($type_name . '.saved');
618   
619          // Get the list of all profile fields of this type
620          $profile_fields = $this->list_profilefields($type_name);
621   
622          // If no profile fields exist, then nothing to do
623          if (empty($profile_fields))
624          {
625              return;
626          }
627   
628          $this->db->sql_transaction('begin');
629   
630          // Delete entries from all profile field definition tables
631          $where = $this->db->sql_in_set('field_id', array_keys($profile_fields));
632          $this->db->sql_query('DELETE FROM ' . $this->fields_table . ' WHERE ' . $where);
633          $this->db->sql_query('DELETE FROM ' . $this->fields_data_lang_table . ' WHERE ' . $where);
634          $this->db->sql_query('DELETE FROM ' . $this->fields_lang_table . ' WHERE ' . $where);
635   
636          // Drop columns from the Profile Fields data table
637          foreach ($profile_fields as $field_ident)
638          {
639              $this->db_tools->sql_column_remove($this->fields_data_table, 'pf_' . $field_ident);
640          }
641   
642          // Reset the order of the remaining fields
643          $order = 0;
644   
645          $sql = 'SELECT *
646              FROM ' . $this->fields_table . '
647              ORDER BY field_order';
648          $result = $this->db->sql_query($sql);
649          while ($row = $this->db->sql_fetchrow($result))
650          {
651              $order++;
652   
653              if ($row['field_order'] != $order)
654              {
655                  $sql = 'UPDATE ' . $this->fields_table . "
656                      SET field_order = $order
657                      WHERE field_id = {$row['field_id']}";
658                  $this->db->sql_query($sql);
659              }
660          }
661          $this->db->sql_freeresult($result);
662   
663          $this->db->sql_transaction('commit');
664   
665          // Log activity
666          foreach ($profile_fields as $field_ident)
667          {
668              $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_PROFILE_FIELD_REMOVED', time(), [$field_ident]);
669          }
670      }
671   
672      /**
673       * Enable the profile fields of a certain type.
674       *
675       * This should be called when an extension which has profile field types that was disabled is re-enabled
676       * so that all those profile fields that were disabled are enabled again.
677       *
678       * @param string    $type_name        Type identifier of the profile fields
679       */
680      public function enable_profilefields($type_name)
681      {
682          // Read the modified information saved on disable from a config_text field to recover values
683          $profile_fields = $this->config_text->get($type_name . '.saved');
684   
685          // If nothing saved, then nothing to do
686          if (empty($profile_fields))
687          {
688              return;
689          }
690   
691          $profile_fields = (array) json_decode($profile_fields, true);
692   
693          // Restore the affected profile fields to "active"
694          $sql = 'UPDATE ' . $this->fields_table . '
695              SET field_active = 1
696              WHERE field_active = 0
697                  AND ' . $this->db->sql_in_set('field_id', array_keys($profile_fields));
698          $this->db->sql_query($sql);
699   
700          // Remove the information saved in the config_text field, not needed any longer
701          $this->config_text->delete($type_name . '.saved');
702   
703          // Log activity
704          foreach ($profile_fields as $field_ident)
705          {
706              $this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_PROFILE_FIELD_ACTIVATE', time(), [$field_ident]);
707          }
708      }
709   
710      /**
711       * Get list of profile fields of a certain type, if any
712       *
713       * @param string    $type_name        Type identifier of the profile fields
714       * @param bool        $active            True to limit output to active profile fields, false for all
715       * @return array                    Array with profile field ids as keys and idents as values
716       */
717      private function list_profilefields($type_name, $active = false)
718      {
719          // Get list of profile fields affected by this operation, if any
720          $sql = 'SELECT field_id, field_ident
721              FROM ' . $this->fields_table . "
722              WHERE field_type = '" . $this->db->sql_escape($type_name) . "'" .
723              ($active ? ' AND field_active = 1' : '');
724          $result = $this->db->sql_query($sql);
725          $rowset = $this->db->sql_fetchrowset($result);
726          $this->db->sql_freeresult($result);
727   
728          return array_column($rowset, 'field_ident', 'field_id');
729      }
730  }
731