class/Field.php
<?php declare(strict_types=1);
namespace XoopsModules\Songlist;
use function base64_decode;
use function base64_encode;
/**
* @copyright copyright © 2000 XOOPS.org
*/
class Field extends \XoopsObject
{
public $field_id;
public $cids;
public $field_type;
public $field_valuetype;
public $field_name;
public $field_title;
public $field_description;
public $field_required; //0 = no, 1 = yes
public $field_maxlength;
public $field_weight;
public $field_default;
public $field_notnull;
public $field_edit;
public $field_show;
public $field_config;
public $field_options;
public function __construct()
{
$this->initVar('field_id', \XOBJ_DTYPE_INT, null);
$this->initVar('cids', \XOBJ_DTYPE_ARRAY, [0 => '0'], true);
$this->initVar('field_type', \XOBJ_DTYPE_TXTBOX);
$this->initVar('field_valuetype', \XOBJ_DTYPE_INT, null, true);
$this->initVar('field_name', \XOBJ_DTYPE_TXTBOX, null, true);
$this->initVar('field_title', \XOBJ_DTYPE_TXTBOX);
$this->initVar('field_description', \XOBJ_DTYPE_TXTAREA);
$this->initVar('field_required', \XOBJ_DTYPE_INT, 0); //0 = no, 1 = yes
$this->initVar('field_maxlength', \XOBJ_DTYPE_INT, 0);
$this->initVar('field_weight', \XOBJ_DTYPE_INT, 0);
$this->initVar('field_default', \XOBJ_DTYPE_TXTAREA, '');
$this->initVar('field_notnull', \XOBJ_DTYPE_INT, 1);
$this->initVar('field_edit', \XOBJ_DTYPE_INT, 0);
$this->initVar('field_show', \XOBJ_DTYPE_INT, 0);
$this->initVar('field_config', \XOBJ_DTYPE_INT, 0);
$this->initVar('field_options', \XOBJ_DTYPE_ARRAY, []);
}
/**
* Extra treatment dealing with non latin encoding
* Tricky solution
* @param string $key
* @param mixed $value
* @param bool $not_gpc
*/
public function setVar($key, $value, $not_gpc = false): void
{
if ('field_options' === $key && \is_array($value)) {
foreach (\array_keys($value) as $idx) {
$value[$idx] = base64_encode($value[$idx]);
}
}
parent::setVar($key, $value, $not_gpc);
}
/**
* @param string $key
* @param string $format
* @return mixed
*/
public function getVar($key, $format = 's')
{
$value = parent::getVar($key, $format);
if ('field_options' === $key && !empty($value)) {
foreach (\array_keys($value) as $idx) {
$value[$idx] = base64_decode($value[$idx], true);
}
}
return $value;
}
/**
* Returns a {@link XoopsFormElement} for editing the value of this field
*
* @param \XoopsUser $user {@link XoopsUser} object to edit the value of
* @param ObjectsProfile $profile {@link ObjectsProfile} object to edit the value of
*
* @return \XoopsFormCheckBox|\XoopsFormDhtmlTextArea|\XoopsFormEditor|\XoopsFormLabel|\XoopsFormRadio|\XoopsFormRadioYN|\XoopsFormSelect|\XoopsFormSelectGroup|\XoopsFormSelectLang|\XoopsFormSelectTimezone|\XoopsFormText|\XoopsFormTextArea|\XoopsFormTextDateSelect|\XoopsModules\Songlist\XoopsFormDatetime \XoopsFormDhtmlTextArea|\\XoopsFormEditor|\\XoopsFormLabel|\\XoopsFormSelect|\\XoopsFormText|\\XoopsFormTextArea
*/
public function getEditElement($user, $profile)
{
$value = \in_array($this->getVar('field_name'), $this->getPostVars(), true) ? $user->getVar($this->getVar('field_name'), 'e') : $profile->getVar($this->getVar('field_name'), 'e');
if (null === $value) {
$value = $this->getVar('field_default');
}
$caption = $this->getVar('field_title');
$caption = \defined($caption) ? \constant($caption) : $caption;
$name = $this->getVar('field_name', 'e');
$options = $this->getVar('field_options');
if (\is_array($options)) {
//asort($options);
foreach (\array_keys($options) as $key) {
$optval = \defined($options[$key]) ? \constant($options[$key]) : $options[$key];
$optkey = \defined((string)$key) ? \constant($key) : $key;
unset($options[$key]);
$options[$optkey] = $optval;
}
}
require_once $GLOBALS['xoops']->path('class/xoopsformloader.php');
switch ($this->getVar('field_type')) {
default:
case 'autotext':
//autotext is not for editing
$element = new \XoopsFormLabel($caption, $this->getOutputValue($user, $profile));
break;
case 'textbox':
$element = new \XoopsFormText($caption, $name, 35, $this->getVar('field_maxlength'), $value);
break;
case 'textarea':
$element = new \XoopsFormTextArea($caption, $name, $value, 4, 30);
break;
case 'dhtml':
$element = new \XoopsFormDhtmlTextArea($caption, $name, $value, 10, 30);
break;
case 'editor':
$editor_config['name'] = $name;
$editor_config['editor'] = $GLOBALS['songlistModuleConfig']['editor'];
$editor_config['value'] = $value;
$editor_config['width'] = $GLOBALS['songlistModuleConfig']['editor_width'];
$editor_config['height'] = $GLOBALS['songlistModuleConfig']['editor_height'];
$element = new \XoopsFormEditor($caption, $name, $editor_config);
break;
case 'select':
$element = new \XoopsFormSelect($caption, $name, $value);
// If options do not include an empty element, then add a blank option to prevent any default selection
if (!\array_key_exists('', $options)) {
$element->addOption('', \_NONE);
//trabis
if (1 == $this->getVar('field_required')) {
$eltmsg = empty($caption) ? \sprintf(\_FORM_ENTER, $name) : \sprintf(\_FORM_ENTER, $caption);
$eltmsg = \str_replace('"', '\"', \stripslashes($eltmsg));
$element->customValidationCode[] = "\nvar hasSelected = false; var selectBox = myform.{$name};"
. "for (i = 0; i < selectBox.options.length; i++ ) { if ( selectBox.options[i].selected === true && selectBox.options[i].value != '' ) { hasSelected = true; break; } }"
. "if ( !hasSelected ) { window.alert(\"{$eltmsg}\"); selectBox.focus(); return false; }";
}
}
$element->addOptionArray($options);
break;
case 'select_multi':
$element = new \XoopsFormSelect($caption, $name, $value, 5, true);
$element->addOptionArray($options);
break;
case 'radio':
$element = new \XoopsFormRadio($caption, $name, $value);
$element->addOptionArray($options);
break;
case 'checkbox':
$element = new \XoopsFormCheckBox($caption, $name, $value);
$element->addOptionArray($options);
break;
case 'yesno':
$element = new \XoopsFormRadioYN($caption, $name, $value);
break;
case 'group':
$element = new \XoopsFormSelectGroup($caption, $name, true, $value);
break;
case 'group_multi':
$element = new \XoopsFormSelectGroup($caption, $name, true, $value, 5, true);
break;
case 'language':
$element = new \XoopsFormSelectLang($caption, $name, $value);
break;
case 'date':
$element = new \XoopsFormTextDateSelect($caption, $name, 15, $value);
break;
case 'longdate':
$element = new \XoopsFormTextDateSelect($caption, $name, 15, \str_replace('-', '/', $value));
break;
case 'datetime':
$element = new XoopsFormDatetime($caption, $name, 15, $value);
break;
case 'list':
$element = new \XoopsFormSelect($caption, $name, $value, 1, $options[0]);
break;
case 'timezone':
$element = new \XoopsFormSelectTimezone($caption, $name, $value);
$element->setExtra("style='width: 280px;'");
break;
case 'rank':
$element = new \XoopsFormSelect($caption, $name, $value);
require_once $GLOBALS['xoops']->path('class/xoopslists.php');
$ranks = \XoopsLists::getUserRankList();
$element->addOption(0, '--------------');
$element->addOptionArray($ranks);
break;
case 'theme':
$element = new \XoopsFormSelect($caption, $name, $value);
$element->addOption('0', \_AM_SONGLIST_OBJS_MF_SITEDEFAULT);
$handle = \opendir(XOOPS_THEME_PATH . '/');
$dirlist = [];
while (false !== ($file = \readdir($handle))) {
if (\is_dir(XOOPS_THEME_PATH . '/' . $file) && !\preg_match('/^[.]{1,2}$/', $file) && 'cvs' !== \mb_strtolower($file)) {
if (\file_exists(XOOPS_THEME_PATH . '/' . $file . '/theme.tpl') && \in_array($file, $GLOBALS['xoopsConfig']['theme_set_allowed'], true)) {
$dirlist[$file] = $file;
}
}
}
\closedir($handle);
if (!empty($dirlist)) {
\asort($dirlist);
$element->addOptionArray($dirlist);
}
break;
}
if ('' != $this->getVar('field_description')) {
$element->setDescription($this->getVar('field_description'));
}
return $element;
}
/**
* Returns a {@link XoopsFormElement} for editing the value of this field
* @return \\XoopsFormLabel|\\XoopsFormSelect|\\XoopsFormText|\\XoopsFormTextArea
* @internal param XoopsUser $user <a href='psi_element://XoopsUser'>XoopsUser</a> object to edit the value of object to edit the value of
* @internal param ObjectsProfile $profile <a href='psi_element://ObjectsProfile'>ObjectsProfile</a> object to edit the value of object to edit the value of
*/
public function getSearchElement()
{
$caption = $this->getVar('field_title');
$caption = \defined($caption) ? \constant($caption) : $caption;
$name = $this->getVar('field_name', 'e');
$options = $this->getVar('field_options');
if (\is_array($options)) {
//asort($options);
foreach (\array_keys($options) as $key) {
$optval = \defined($options[$key]) ? \constant($options[$key]) : $options[$key];
$optkey = \defined($key) ? \constant($key) : $key;
unset($options[$key]);
$options[$optkey] = $optval;
}
}
require_once $GLOBALS['xoops']->path('class/xoopsformloader.php');
switch ($this->getVar('field_type')) {
default:
case 'autotext':
//autotext is not for editing
$element = new \XoopsFormLabel($caption, $this->getOutputValue($user, $profile));
break;
case 'textbox':
$element = new \XoopsFormText($caption, $name, 35, $this->getVar('field_maxlength'), $value);
break;
case 'textarea':
$element = new \XoopsFormTextArea($caption, $name, $value, 4, 30);
break;
case 'dhtml':
$element = new \XoopsFormText($caption, $name, 35, 255, $value);
break;
case 'select':
$element = new \XoopsFormSelect($caption, $name, $value);
// If options do not include an empty element, then add a blank option to prevent any default selection
if (!\array_key_exists('', $options)) {
$element->addOption('', \_NONE);
//trabis
if (1 == $this->getVar('field_required')) {
$eltmsg = empty($caption) ? \sprintf(\_FORM_ENTER, $name) : \sprintf(\_FORM_ENTER, $caption);
$eltmsg = \str_replace('"', '\"', \stripslashes($eltmsg));
$element->customValidationCode[] = "\nvar hasSelected = false; var selectBox = myform.{$name};"
. "for (i = 0; i < selectBox.options.length; i++ ) { if ( selectBox.options[i].selected === true && selectBox.options[i].value != '' ) { hasSelected = true; break; } }"
. "if ( !hasSelected ) { window.alert(\"{$eltmsg}\"); selectBox.focus(); return false; }";
}
//end
}
$element->addOptionArray($options);
break;
case 'editor':
$element = new \XoopsFormText($caption, $name, 35, 255, $value);
break;
case 'select_multi':
$element = new \XoopsFormSelect($caption, $name, $value, 5, true);
$element->addOptionArray($options);
break;
case 'radio':
$element = new \XoopsFormRadio($caption, $name, $value);
$element->addOptionArray($options);
break;
case 'checkbox':
$element = new \XoopsFormCheckBox($caption, $name, $value);
$element->addOptionArray($options);
break;
case 'yesno':
$element = new \XoopsFormRadioYN($caption, $name, $value);
break;
case 'group':
$element = new \XoopsFormSelectGroup($caption, $name, true, $value);
break;
case 'group_multi':
$element = new \XoopsFormSelectGroup($caption, $name, true, $value, 5, true);
break;
case 'language':
$element = new \XoopsFormSelectLang($caption, $name, $value);
break;
case 'date':
$element = new \XoopsFormTextDateSelect($caption, $name, 15, $value);
break;
case 'longdate':
$element = new \XoopsFormTextDateSelect($caption, $name, 15, \str_replace('-', '/', $value));
break;
case 'datetime':
$element = new XoopsFormDatetime($caption, $name, 15, $value);
break;
case 'list':
$element = new \XoopsFormSelect($caption, $name, $value, 1, $options[0]);
break;
case 'timezone':
$element = new \XoopsFormSelectTimezone($caption, $name, $value);
$element->setExtra("style='width: 280px;'");
break;
case 'rank':
$element = new \XoopsFormSelect($caption, $name, $value);
require_once $GLOBALS['xoops']->path('class/xoopslists.php');
$ranks = \XoopsLists::getUserRankList();
$element->addOption(0, '--------------');
$element->addOptionArray($ranks);
break;
case 'theme':
$element = new \XoopsFormSelect($caption, $name, $value);
$element->addOption('0', \_AM_SONGLIST_OBJS_MF_SITEDEFAULT);
$handle = \opendir(XOOPS_THEME_PATH . '/');
$dirlist = [];
while (false !== ($file = \readdir($handle))) {
if (\is_dir(XOOPS_THEME_PATH . '/' . $file) && !\preg_match('/^[.]{1,2}$/', $file) && 'cvs' !== \mb_strtolower($file)) {
if (\file_exists(XOOPS_THEME_PATH . '/' . $file . '/theme.tpl') && \in_array($file, $GLOBALS['xoopsConfig']['theme_set_allowed'], true)) {
$dirlist[$file] = $file;
}
}
}
\closedir($handle);
if (!empty($dirlist)) {
\asort($dirlist);
$element->addOptionArray($dirlist);
}
break;
}
if ('' != $this->getVar('field_description')) {
$element->setDescription($this->getVar('field_description'));
}
return $element;
}
/**
* Returns a value for output of this field
*
* @param \XoopsUser $user {@link XoopsUser} object to get the value of
* @param ObjectsProfile $profile object to get the value of
*
* @return mixed
**/
public function getOutputValue($user, $profile)
{
\xoops_loadLanguage('modinfo', 'objects');
$value = \in_array($this->getVar('field_name'), $this->getPostVars(), true) ? $user->getVar($this->getVar('field_name')) : $profile->getVar($this->getVar('field_name'));
switch ($this->getVar('field_type')) {
default:
case 'textbox':
if ('url' === $this->getVar('field_name') && '' != $value) {
return '<a href="' . \formatURL($value) . '" rel="external">' . $value . '</a>';
}
return $value;
case 'editor':
case 'textarea':
case 'dhtml':
case 'theme':
case 'language':
case 'list':
return $value;
case 'select':
case 'radio':
$options = $this->getVar('field_options');
if (isset($options[$value])) {
$value = \htmlspecialchars(\defined($options[$value]) ? \constant($options[$value]) : $options[$value], \ENT_QUOTES | \ENT_HTML5);
} else {
$value = '';
}
return $value;
case 'select_multi':
case 'checkbox':
$options = $this->getVar('field_options');
$ret = [];
if (\count($options) > 0) {
foreach (\array_keys($options) as $key) {
if (\in_array($key, $value, true)) {
$$ret[$key] = \htmlspecialchars(\defined($options[$key]) ? \constant($options[$key]) : $options[$key], \ENT_QUOTES | \ENT_HTML5);
}
}
}
return $ret;
case 'group':
//change to retrieve groups and return name of group
return $value;
case 'group_multi':
//change to retrieve groups and return array of group names
return '';
case 'longdate':
//return YYYY/MM/DD format - not optimal as it is not using local date format, but how do we do that
//when we cannot convert it to a UNIX timestamp?
return \str_replace('-', '/', $value);
case 'date':
return \formatTimestamp($value, 's');
case 'datetime':
if (!empty($value)) {
return \formatTimestamp($value, 'm');
}
return $value = \_MI_SONGLIST_DATENOTSET;
case 'autotext':
$value = $user->getVar($this->getVar('field_name'), 'n'); //autotext can have HTML in it
$value = \str_replace('{X_UID}', $user->getVar('uid'), $value);
$value = \str_replace('{X_URL}', XOOPS_URL, $value);
$value = \str_replace('{X_UNAME}', $user->getVar('uname'), $value);
return $value;
case 'rank':
$userrank = $user->rank();
$user_rankimage = '';
if (isset($userrank['image']) && '' != $userrank['image']) {
$user_rankimage = '<img src="' . XOOPS_UPLOAD_URL . '/' . $userrank['image'] . '" alt="' . $userrank['title'] . '"><br>';
}
return $user_rankimage . $userrank['title'];
case 'yesno':
return $value ? \_YES : \_NO;
case 'timezone':
require_once $GLOBALS['xoops']->path('class/xoopslists.php');
$timezones = \XoopsLists::getTimeZoneList();
$value = empty($value) ? '0' : (string)$value;
return $timezones[\str_replace('.0', '', $value)];
}
}
/**
* Returns a value ready to be saved in the database
*
* @param mixed $value Value to format
*
* @return mixed
*/
public function getValueForSave($value)
{
switch ($this->getVar('field_type')) {
default:
case 'textbox':
case 'textarea':
case 'dhtml':
case 'yesno':
case 'timezone':
case 'theme':
case 'language':
case 'list':
case 'select':
case 'radio':
case 'select_multi':
case 'checkbox':
case 'group':
case 'group_multi':
case 'longdate':
return $value;
case 'date':
if ('' != $value) {
return \strtotime((string)$value);
}
return $value;
case 'datetime':
if (!empty($value)) {
return \strtotime($value['date'] ?? '') + (int)$value['time'];
}
return $value;
}
}
/**
* Get names of user variables
*
* @return array
*/
public function getPostVars(): array
{
$objectsHandler = \XoopsModules\Songlist\Helper::getInstance()->getHandler('Extras');
return $objectsHandler->getPostVars();
}
}