Spaces:
No application file
No application file
| namespace Mautic\CoreBundle\Event; | |
| use Mautic\CoreBundle\Helper\BuilderTokenHelper; | |
| use Symfony\Component\Process\Exception\InvalidArgumentException; | |
| use Symfony\Contracts\EventDispatcher\Event; | |
| class BuilderEvent extends Event | |
| { | |
| protected $slotTypes = []; | |
| protected $sections = []; | |
| protected $tokens = []; | |
| protected $abTestWinnerCriteria = []; | |
| /** | |
| * @var string|string[] | |
| */ | |
| protected string|array $tokenFilterText; | |
| protected string $tokenFilterTarget; | |
| public function __construct( | |
| protected $translator, | |
| protected $entity = null, | |
| protected $requested = 'all', | |
| protected string $tokenFilter = '' | |
| ) { | |
| $this->tokenFilterTarget = (str_starts_with($tokenFilter, '{@')) ? 'label' : 'token'; | |
| $this->tokenFilterText = str_replace(['{@', '{', '}'], '', $tokenFilter); | |
| $this->tokenFilter = ('label' == $this->tokenFilterTarget) ? $this->tokenFilterText : str_replace('{@', '{', $tokenFilter); | |
| } | |
| /** | |
| * @param int $priority | |
| */ | |
| public function addSlotType($key, $header, $icon, $content, $form, $priority = 0, array $params = []): void | |
| { | |
| $this->slotTypes[$key] = [ | |
| 'header' => $this->translator->trans($header), | |
| 'icon' => $icon, | |
| 'content' => $content, | |
| 'params' => $params, | |
| 'form' => $form, | |
| 'priority' => $priority, | |
| ]; | |
| } | |
| /** | |
| * Get slot types. | |
| * | |
| * @return array | |
| */ | |
| public function getSlotTypes() | |
| { | |
| $sort = ['priority' => [], 'header' => []]; | |
| foreach ($this->slotTypes as $k => $v) { | |
| $sort['priority'][$k] = $v['priority']; | |
| $sort['header'][$k] = $v['header']; | |
| } | |
| array_multisort($sort['priority'], SORT_DESC, $sort['header'], SORT_ASC, $this->slotTypes); | |
| foreach ($this->slotTypes as $i => $slot) { | |
| $slot['header'] = str_replace(' ', '<br />', $slot['header']); | |
| $this->slotTypes[$i] = $slot; | |
| } | |
| return $this->slotTypes; | |
| } | |
| public function addSection($key, $header, $icon, $content, $form, $priority = 0): void | |
| { | |
| $this->sections[$key] = [ | |
| 'header' => $this->translator->trans($header), | |
| 'icon' => $icon, | |
| 'content' => $content, | |
| 'form' => $form, | |
| 'priority' => $priority, | |
| ]; | |
| } | |
| /** | |
| * Get slot types. | |
| * | |
| * @return array | |
| */ | |
| public function getSections() | |
| { | |
| $sort = ['priority' => [], 'header' => []]; | |
| foreach ($this->sections as $k => $v) { | |
| $sort['priority'][$k] = $v['priority']; | |
| $sort['header'][$k] = $v['header']; | |
| } | |
| array_multisort($sort['priority'], SORT_DESC, $sort['header'], SORT_ASC, $this->sections); | |
| return $this->sections; | |
| } | |
| /** | |
| * Get list of AB Test winner criteria. | |
| */ | |
| public function getAbTestWinnerCriteria(): array | |
| { | |
| uasort( | |
| $this->abTestWinnerCriteria, | |
| fn ($a, $b): int => strnatcasecmp( | |
| $a['group'], | |
| $b['group'] | |
| ) | |
| ); | |
| $array = ['criteria' => $this->abTestWinnerCriteria]; | |
| $choices = []; | |
| foreach ($this->abTestWinnerCriteria as $k => $c) { | |
| $choices[$c['group']][$c['label']] = $k; | |
| } | |
| $array['choices'] = $choices; | |
| return $array; | |
| } | |
| /** | |
| * Adds an A/B test winner criteria option. | |
| * | |
| * @param string $key - a unique identifier; it is recommended that it be namespaced i.e. lead.points | |
| * @param array{ | |
| * group: string, | |
| * label: string, | |
| * event: string, | |
| * formType?: string, | |
| * formTypeOptions?: string | |
| * } $criteria Can contain the following keys: | |
| * - group - (required) translation string to group criteria by in the dropdown select list | |
| * - label - (required) what to display in the list | |
| * - event - (required) event class constant that will receieve the DetermineWinnerEvent for further handling. E.g. `HelloWorldEvents::ON_DETERMINE_PLANET_VISIT_WINNER` | |
| * - formType - (optional) name of the form type SERVICE for the criteria | |
| * - formTypeOptions - (optional) array of options to pass to the formType service | |
| */ | |
| public function addAbTestWinnerCriteria($key, array $criteria): void | |
| { | |
| if (array_key_exists($key, $this->abTestWinnerCriteria)) { | |
| throw new InvalidArgumentException("The key, '$key' is already used by another criteria. Please use a different key."); | |
| } | |
| // check for required keys | |
| $this->verifyCriteria( | |
| ['group', 'label', 'event'], | |
| $criteria | |
| ); | |
| // translate the group | |
| $criteria['group'] = $this->translator->trans($criteria['group']); | |
| $this->abTestWinnerCriteria[$key] = $criteria; | |
| } | |
| private function verifyCriteria(array $keys, array $criteria): void | |
| { | |
| foreach ($keys as $k) { | |
| if (!array_key_exists($k, $criteria)) { | |
| throw new InvalidArgumentException("The key, '$k' is missing."); | |
| } | |
| } | |
| } | |
| /** | |
| * @param bool $convertToLinks | |
| */ | |
| public function addTokens(array $tokens, $convertToLinks = false): void | |
| { | |
| if ($convertToLinks) { | |
| array_walk($tokens, function (&$val, $key): void { | |
| $val = 'a:'.$val; | |
| }); | |
| } | |
| $this->tokens = array_merge($this->tokens, $tokens); | |
| } | |
| public function addToken($key, $value): void | |
| { | |
| $this->tokens[$key] = $value; | |
| } | |
| /** | |
| * Get token array. | |
| * | |
| * @return array | |
| */ | |
| public function getTokens($withBC = true) | |
| { | |
| if (false === $withBC) { | |
| $tokens = []; | |
| foreach ($this->tokens as $key => $value) { | |
| if (!str_starts_with($key, '{leadfield')) { | |
| $tokens[$key] = $value; | |
| } | |
| } | |
| return $tokens; | |
| } | |
| return $this->tokens; | |
| } | |
| /** | |
| * Check if tokens have been requested. | |
| * Pass in string or array of tokens to filter against if filterType == token. | |
| * | |
| * @param string|array|null $tokenKeys | |
| */ | |
| public function tokensRequested($tokenKeys = null): bool | |
| { | |
| if ($requested = $this->getRequested('tokens')) { | |
| if (!empty($this->tokenFilter) && 'token' == $this->tokenFilterTarget) { | |
| if (!is_array($tokenKeys)) { | |
| $tokenKeys = [$tokenKeys]; | |
| } | |
| $found = false; | |
| foreach ($tokenKeys as $token) { | |
| if (0 === stripos($token, $this->tokenFilter)) { | |
| $found = true; | |
| break; | |
| } | |
| } | |
| if (!$found) { | |
| $requested = false; | |
| } | |
| } | |
| } | |
| return $requested; | |
| } | |
| /** | |
| * Get text of the search filter. | |
| */ | |
| public function getTokenFilter(): array | |
| { | |
| return [ | |
| 'target' => $this->tokenFilterTarget, | |
| 'filter' => $this->tokenFilterText, | |
| ]; | |
| } | |
| /** | |
| * Simple token filtering. | |
| * | |
| * @param array $tokens array('token' => 'label') | |
| * | |
| * @return array | |
| */ | |
| public function filterTokens($tokens) | |
| { | |
| $filter = $this->tokenFilter; | |
| if (empty($filter)) { | |
| return $tokens; | |
| } | |
| if ('label' == $this->tokenFilterTarget) { | |
| // Do a search against the label | |
| $tokens = array_filter( | |
| $tokens, | |
| fn ($v): bool => 0 === stripos($v, $filter) | |
| ); | |
| } else { | |
| // Do a search against the token | |
| $found = array_filter( | |
| array_keys($tokens), | |
| fn ($k): bool => 0 === stripos($k, $filter) | |
| ); | |
| $tokens = array_intersect_key($tokens, array_flip($found)); | |
| } | |
| return $tokens; | |
| } | |
| /** | |
| * Add tokens from a BuilderTokenHelper. | |
| * | |
| * @param string $labelColumn | |
| * @param string $valueColumn | |
| * @param bool $convertToLinks If true, the tokens will be converted to links | |
| */ | |
| public function addTokensFromHelper( | |
| BuilderTokenHelper $tokenHelper, | |
| $tokens, | |
| $labelColumn = 'name', | |
| $valueColumn = 'id', | |
| $convertToLinks = false | |
| ): void { | |
| $tokens = $this->getTokensFromHelper($tokenHelper, $tokens, $labelColumn, $valueColumn); | |
| if (null == $tokens) { | |
| $tokens = []; | |
| } | |
| $this->addTokens( | |
| $tokens, | |
| $convertToLinks | |
| ); | |
| } | |
| /** | |
| * Get tokens from a BuilderTokenHelper. | |
| * | |
| * @return array|void | |
| */ | |
| public function getTokensFromHelper(BuilderTokenHelper $tokenHelper, $tokens, $labelColumn = 'name', $valueColumn = 'id') | |
| { | |
| return $tokenHelper->getTokens( | |
| $tokens, | |
| 'label' == $this->tokenFilterTarget ? $this->tokenFilterText : '', | |
| $labelColumn, | |
| $valueColumn | |
| ); | |
| } | |
| /** | |
| * Check if AB Test Winner Criteria has been requested. | |
| */ | |
| public function abTestWinnerCriteriaRequested(): bool | |
| { | |
| return $this->getRequested('abTestWinnerCriteria'); | |
| } | |
| /** | |
| * Check if Slot types has been requested. | |
| */ | |
| public function slotTypesRequested(): bool | |
| { | |
| return $this->getRequested('slotTypes'); | |
| } | |
| /** | |
| * Check if Sections has been requested. | |
| */ | |
| public function sectionsRequested(): bool | |
| { | |
| return $this->getRequested('sections'); | |
| } | |
| protected function getRequested($type): bool | |
| { | |
| if (is_array($this->requested)) { | |
| return in_array($type, $this->requested); | |
| } | |
| return $this->requested == $type || 'all' == $this->requested; | |
| } | |
| } | |