<?php namespace MailPoet\CustomFields; if (!defined('ABSPATH')) exit; use InvalidArgumentException; use MailPoet\Entities\CustomFieldEntity; class ApiDataSanitizer { const ERROR_MANDATORY_ARGUMENT_MISSING = 1001; const ERROR_MANDATORY_ARGUMENT_WRONG_TYPE = 1002; const ERROR_PARAMS_WRONG_TYPE = 1003; const ERROR_INVALID_TYPE = 1004; const ERROR_INVALID_VALIDATE = 1005; const ERROR_CHECKBOX_WRONG_VALUES_COUNT = 1006; const ERROR_INVALID_DATE_FORMAT = 1007; const ERROR_INVALID_DATE_TYPE = 1008; const ERROR_NO_VALUES = 1009; const ERROR_NO_VALUE = 1010; public function sanitize(array $data = []) { $this->checkMandatoryStringParameter($data, 'name'); $this->checkMandatoryStringParameter($data, 'type'); $this->checkParamsType($data); return [ 'name' => $data['name'], 'type' => strtolower($data['type']), 'params' => $this->sanitizeParams($data), ]; } private function checkMandatoryStringParameter(array $data, $parameterName) { if (empty($data[$parameterName])) { // translators: %s is the name of the missing argument. throw new InvalidArgumentException(sprintf(__('Mandatory argument "%s" is missing', 'mailpoet'), $parameterName), self::ERROR_MANDATORY_ARGUMENT_MISSING); } if (!is_string($data[$parameterName])) { // translators: %s is the name of the malformed argument. throw new InvalidArgumentException(sprintf(__('Mandatory argument "%s" has to be string', 'mailpoet'), $parameterName), self::ERROR_MANDATORY_ARGUMENT_WRONG_TYPE); } } private function checkParamsType($data) { if (isset($data['params']) && !is_array($data['params'])) { throw new InvalidArgumentException(sprintf(__('Params has to be array', 'mailpoet')), self::ERROR_PARAMS_WRONG_TYPE); } } private function sanitizeParams($data) { $data['params'] = isset($data['params']) ? $data['params'] : []; $result = []; $result['required'] = $this->getRequired($data['params']); $result['label'] = $this->getLabel($data); return $result + $this->getExtraParams($data); } private function getLabel($data) { if (empty($data['params']['label'])) { return $data['name']; } else { return $data['params']['label']; } } private function getRequired($params) { if (isset($params['required']) && $params['required']) { return '1'; } return ''; } private function getExtraParams($data) { $type = strtolower($data['type']); if (in_array($type, [CustomFieldEntity::TYPE_TEXT, CustomFieldEntity::TYPE_TEXTAREA], true)) { return $this->getExtraParamsForText($data['params']); } if (in_array($type, [CustomFieldEntity::TYPE_RADIO, CustomFieldEntity::TYPE_SELECT], true)) { return $this->getExtraParamsForSelect($data['params']); } if ($type === CustomFieldEntity::TYPE_CHECKBOX) { return $this->getExtraParamsForCheckbox($data['params']); } if ($type === CustomFieldEntity::TYPE_DATE) { return $this->getExtraParamsForDate($data['params']); } // translators: %s is the name of the type. throw new InvalidArgumentException(sprintf(__('Invalid type "%s"', 'mailpoet'), $type), self::ERROR_INVALID_TYPE); } private function getExtraParamsForText($params) { if (isset($params['validate'])) { $validate = trim(strtolower($params['validate'])); if (in_array($validate, ['number', 'alphanum', 'phone'], true)) { return ['validate' => $validate]; } throw new InvalidArgumentException(__('Validate parameter is not valid', 'mailpoet'), self::ERROR_INVALID_VALIDATE); } return []; } private function getExtraParamsForCheckbox($params) { if (empty($params['values']) || count($params['values']) > 1) { throw new InvalidArgumentException(__('You need to pass exactly one value for checkbox', 'mailpoet'), self::ERROR_CHECKBOX_WRONG_VALUES_COUNT); } $value = reset($params['values']); return ['values' => [$this->sanitizeValue($value)]]; } private function getExtraParamsForDate($params) { $dateType = (isset($params['date_type']) ? $params['date_type'] : 'year_month_day' ); $inputDateFormat = (isset($params['date_format']) ? $params['date_format'] : '' ); switch ($dateType) { case 'year_month_day': if (!in_array($inputDateFormat, ['MM/DD/YYYY', 'DD/MM/YYYY', 'YYYY/MM/DD'], true)) { throw new InvalidArgumentException(__('Invalid date_format for year_month_day', 'mailpoet'), self::ERROR_INVALID_DATE_FORMAT); } $dateFormat = $inputDateFormat; break; case 'year_month': if (!in_array($inputDateFormat, ['YYYY/MM', 'MM/YY'], true)) { throw new InvalidArgumentException(__('Invalid date_format for year_month', 'mailpoet'), self::ERROR_INVALID_DATE_FORMAT); } $dateFormat = $inputDateFormat; break; case 'month': $dateFormat = 'MM'; break; case 'year': $dateFormat = 'YYYY'; break; case 'day': $dateFormat = 'DD'; break; default: throw new InvalidArgumentException(__('Invalid value for date_type', 'mailpoet'), self::ERROR_INVALID_DATE_TYPE); } return [ 'date_type' => $dateType, 'date_format' => $dateFormat, ]; } private function getExtraParamsForSelect($params) { if (empty($params['values'])) { throw new InvalidArgumentException(__('You need to pass some values for this type', 'mailpoet'), self::ERROR_NO_VALUES); } $values = []; foreach ($params['values'] as $value) { $values[] = $this->sanitizeValue($value); } return ['values' => $values]; } private function sanitizeValue($value) { if (empty($value['value'])) { throw new InvalidArgumentException(__('Value cannot be empty', 'mailpoet'), self::ERROR_NO_VALUE); } $result = ['value' => $value['value']]; if (isset($value['is_checked']) && $value['is_checked']) { $result['is_checked'] = '1'; } else { $result['is_checked'] = ''; } return $result; } }