/** * @return array w/ pagination links */ protected function doRender() { $pagination = $this->getPayload('subject'); $current_page_url = $this->url_generator->generateUrl(null); $url_parameters = ArrayToolkit::getUrlQueryInRequestFormat($current_page_url); unset($url_parameters['offset']); // offset is not needed when page is used (see validator) $current_page_url = $this->url_generator->generateUrl(null, $url_parameters); $curie = $this->getOption('curie'); $translation_domain = $this->getOption('translation_domain', 'application.ui'); $links = ['self' => ['href' => $current_page_url]]; if (!$pagination->isFirstPage()) { $links['first'] = ['href' => $this->url_generator->generateUrl(null, array_merge($url_parameters, ['offset' => 0])), 'title' => $this->translator->translate('pager.first_page.title', $translation_domain)]; } if ($pagination->hasPrevPage()) { $links['prev'] = ['href' => $this->url_generator->generateUrl(null, array_merge($url_parameters, ['offset' => $pagination->getPrevPageOffset()])), 'title' => $this->translator->translate('pager.prev_page.title', $translation_domain)]; } if ($pagination->hasNextPage()) { $links['next'] = ['href' => $this->url_generator->generateUrl(null, array_merge($url_parameters, ['offset' => $pagination->getNextPageOffset()])), 'title' => $this->translator->translate('pager.next_page.title', $translation_domain)]; } if (!$pagination->isLastPage()) { $links['last'] = ['href' => $this->url_generator->generateUrl(null, array_merge($url_parameters, ['offset' => $pagination->getLastPageOffset()])), 'title' => $this->translator->translate('pager.last_page.title', $translation_domain)]; } if ($pagination->getNumberOfPages() > 1) { $link_name = empty($curie) ? 'jumpToPage' : $curie . ':jumpToPage'; $links[$link_name] = ['href' => $this->url_generator->generateUrl(null), 'templated' => true, 'title' => $this->translator->translate('pager.jump_to_page.title', $translation_domain)]; } return $links; }
protected function getTemplateParameters() { $params = parent::getDefaultTemplateParameters(); $resource = $this->getPayload('subject'); $parent_attribute = $resource->getType()->getParentAttribute(); $group_parts = (array) $this->getOption('group_parts', []); $params['grouped_base_path'] = ArrayToolkit::flattenToArrayPath($group_parts); $params['is_embed_template'] = $this->getOption('is_embed_template', false); $params['has_parent_attribute'] = $parent_attribute !== null; $params['html_attributes'] = $this->getOption('html_attributes', []); $params['image_disabled'] = $this->getOption('image_disabled', false); $params['resource'] = $resource->toNative(); $params['is_new'] = !$resource->hasValue('identifier'); $params['css'] = $this->getOption('css', ''); $params = array_replace_recursive($this->lookupViewTemplate(), $params); if ($this->hasOption('view_template_name')) { // use view_template $params['rendered_fields'] = $this->getRenderedFields($resource, $params['view_template']); $params['css'] .= $params['is_new'] ? ' hb-glance--empty' : null; } else { // get default values if (!$params['image_disabled']) { $image = $this->getGlanceImage($resource, $params['view_template']); $params['image_width'] = $this->getOption('image_width', $image['width']); $params['image_height'] = $this->getOption('image_height', $image['height']); $params['image_url'] = $image['location']; } $params['title'] = $this->getGlanceTitle($resource, $params['view_template']); $params['description'] = $this->getGlanceDescription($resource, $params['view_template']); } return $params; }
protected function getTemplateParameters() { $entity = $this->getPayload('subject'); $group_parts = (array) $this->getOption('group_parts', []); $parent_attribute = $entity->getType()->getParentAttribute(); $params = parent::getTemplateParameters(); $params['has_parent_attribute'] = $parent_attribute !== null; $params['grouped_base_path'] = ArrayToolkit::flattenToArrayPath($group_parts); $params['resource'] = $entity->toArray(); $params['entity_type'] = $entity->getType()->getPrefix(); $params['is_embed_template'] = $this->getOption('is_embed_template', false); $params['is_new'] = !$entity->hasValue('identifier'); // when entity is part of a list (embed or reference) $params['add_item_to_parent_list_allowed'] = $this->getOption('add_item_to_parent_list_allowed', true); // custom title+decription per-embedded-item in an EntityList attribute if (!$entity->getType()->isRoot()) { $params['embed_item_title'] = $this->getOption('entity_title', 'entity_title'); $params['embed_item_description'] = $this->getOption('entity_description', 'entity_description'); } $params = array_replace_recursive($this->lookupViewTemplate(), $params); $params['rendered_fields'] = $this->getRenderedFields($entity, $params['view_template']); if ($entity instanceof ProjectionInterface && $entity->getWorkflowState()) { $params['rendered_resource_activities'] = $this->getResourceActivities($entity); } return $params; }
protected function processLocalFileSetting(array $local_setting_info) { $settings = []; $file_path = AgaviConfig::get('core.local_config_dir') . '/' . $local_setting_info['path']; if (!is_readable($file_path)) { throw new RuntimeError('Unable to read local config file at: ' . $file_path); } if ($local_setting_info['type'] === 'yaml') { $yaml_string = file_get_contents($file_path); if (!$yaml_string) { throw new Exception('Failed to read local configuration at: ' . $file_path); } try { $yaml_parser = new Parser(); $settings = $yaml_parser->parse($yaml_string); } catch (Exception $parse_error) { throw new RuntimeError('Failed to parse yaml for local config file: ' . $file_path . PHP_EOL . 'Error: ' . $parse_error->getMessage()); } } elseif ($local_setting_info['type'] === 'json') { $json_string = file_get_contents($file_path); if (!$json_string) { throw new Exception('Failed to read local configuration at: ' . $file_path); } $settings = json_decode($json_string, true); if (json_last_error() !== JSON_ERROR_NONE) { throw new RuntimeError('Failed to parse json from file "' . $file_path . '": ' . json_last_error_msg()); } } else { throw new RuntimeError('Only "yaml" or "json" are supported for "type" setting of local configs.'); } if (!isset($local_setting_info['settings']['flatten']) || $local_setting_info['settings']['flatten'] === true) { $settings = ArrayToolkit::flatten($settings); } return $settings; }
protected function getTemplateParameters() { $params = parent::getTemplateParameters(); $original_activity_map = $this->getPayload('subject'); if ($original_activity_map->isEmpty()) { return $params; } $hidden_activity_names = (array) $this->getOption('hidden_activity_names', []); // remove all activities that are excluded via config/settings $activity_map = $original_activity_map->filter(function ($activity) use($hidden_activity_names) { if (in_array($activity->getName(), $hidden_activity_names)) { return false; } return true; }); if ($activity_map->isEmpty()) { return $params; } // determine which of the remaining activities should be the primary/current one $default_activity_name = $this->getOption('default_activity_name', ''); if (!$activity_map->hasKey($default_activity_name)) { $default_activity_name = $activity_map->getKeys()[0]; } $rendered_activities = []; foreach ($activity_map as $activity) { $name = $activity->getName(); if (in_array($name, $hidden_activity_names) && $name !== $default_activity_name) { continue; // don't render activities that should not be displayed } $additional_payload = ['subject' => $activity]; // workflow activities need an 'resource' to generate the url correctly if ($this->hasPayload('resource')) { $additional_payload['resource'] = $this->payload->get('resource'); } elseif ($this->hasPayload('module')) { $additional_payload['module'] = $this->payload->get('module'); } $rendered_activities[$name] = $this->renderer_service->renderSubject($activity, $this->output_format, $this->config, $additional_payload); } // put default activity to top as that should be the primary activity ArrayToolkit::moveToTop($rendered_activities, $default_activity_name); $params['rendered_activities'] = $rendered_activities; return $params; }
protected function getTemplateParameters() { $params = parent::getTemplateParameters(); $pagination = $this->getPayload('subject'); $params = array_merge($params, $pagination->toArray()); $current_page_url = $this->url_generator->generateUrl(null); $current_url_parameters = ArrayToolkit::getUrlQueryInRequestFormat($current_page_url); unset($current_url_parameters['offset']); // offset is not needed when page is used (see validator) $url_parameters = (array) $this->getOption('url_parameters', []); $url_parameters = array_merge($current_url_parameters, $url_parameters); // we add all query parameters of the current URL as hidden GET form inputs to not lose any state on submit $params['url_parameters'] = $url_parameters; $params['current_page_url'] = $this->url_generator->generateUrl(null, $url_parameters); $params['first_page_url'] = $this->url_generator->generateUrl(null, array_merge($url_parameters, ['offset' => 0])); $params['last_page_url'] = $this->url_generator->generateUrl(null, array_merge($url_parameters, ['offset' => $pagination->getLastPageOffset()])); $params['next_page_url'] = $this->url_generator->generateUrl(null, array_merge($url_parameters, ['offset' => $pagination->getNextPageOffset()])); $params['prev_page_url'] = $this->url_generator->generateUrl(null, array_merge($url_parameters, ['offset' => $pagination->getPrevPageOffset()])); $params['number_of_pages'] = $pagination->getNumberOfPages(); return $params; }
/** * Merges the given second array over the first one similar to the PHP internal * array_merge_recursive method, but does not change scalar values into arrays * when duplicate keys occur. * * @param array $first first or default array * @param array $second array to merge over the first array * * @return array merged result with scalar values still being scalar */ public static function mergeSettings(array &$first, array &$second) { return ArrayToolkit::mergeScalarSafe($first, $second); }
protected function getPayloadPath($attribute_value_path) { $path_parts = explode('.', $attribute_value_path); if ($base = (string) $this->getBase()) { array_unshift($path_parts, $base); } return ArrayToolkit::flattenToArrayPath($path_parts); }
public function __toString() { return sprintf('STORED QUERY: SEARCH %s PARAMS %s %s %s', $this->name, http_build_query(ArrayToolkit::flatten($this->parameters), '', ', '), isset($this->limit) ? 'LIMIT ' . $this->limit : '', isset($this->offset) ? 'OFFSET ' . $this->offset : ''); }
/** * Creates and returns an AgaviLoggerMessage instance. To return a * different class set the default_message_class parameter in the * for the logger_manager entry in the factories.xml file. * * The log message parts need to be either strings, arrays or objects * implementing __toString(). Instances of the following classes are * treated in a special way automatically: * - Exception * - Honeybee\Infrastructure\Domain\Type - name of module * - Honeybee\Infrastructure\Domain\Model - uuid of resource * - AgaviValidationManager - messages of all incidents * - DateTime - ISO-8601 representation * * @see self::getAsString() * * If the log message consists of exactly two parts while the first is a * string and the second an associative array it is used as a PSR-3 * compatible call and templating with the given context array according to * PSR-3 via {placeholders} is supported. This usage still includes getting * supported known types as strings. The given Agavi log level is being * converted to a PSR-3 compatible log level and the given scope is added * as a parameter to the message. * * @param int $log_level Agavi log level to use * @param string $scope name for the scope to use * @param mixed $log_message_parts string or object to log or array that contains log message parts * ($log_message_parts or its array entries need to be of known types or implement __toString()) * * @return AgaviLoggerMessage * * @throws InvalidArgumentException if __toString() is not callable on a log message part object */ public function createLoggerMessage($log_level, $scope = self::DEFAULT_MESSAGE_SCOPE, $log_message_parts = "") { $text_message_parts = array(); $class_name = $this->getDefaultMessageClass(); $logger_message = new $class_name(); $logger_message->setLevel($log_level); $logger_message->setParameter('scope', trim($scope)); // might be a PSR-3 compatible log call with templated message and context array if (2 === count($log_message_parts) && is_string($log_message_parts[0]) && is_array($log_message_parts[1]) && ArrayToolkit::isAssoc($log_message_parts[1]) && false !== strpos($log_message_parts[0], '{')) { $logger_message->setParameter('psr3.context', $log_message_parts[1]); $logger_message->setLevel(Logger::getAgaviLogLevel($log_level)); $logger_message->setMessage(Psr3Logger::replacePlaceholders($log_message_parts[0], $log_message_parts[1])); if (isset($log_message_parts[1]['scope'])) { $logger_message->setParameter('scope', $log_message_parts[1]['scope']); } return $logger_message; } $text = ''; if (is_array($log_message_parts)) { // analyse log_message_parts to get nicely formatted strings for known classes etc. $text_message_parts = array(); foreach ($log_message_parts as $log_message_part) { $text_message_parts[] = self::getAsString($log_message_part); } $text = implode(' ', $text_message_parts); } else { $text = self::getAsString($log_message_parts); } $logger_message->setMessage($text); return $logger_message; }
public function testAllInArray() { $this->assertTrue(ArrayToolkit::allInArray(['c', 'a', 'b'], ['a', 'b', 'c'])); $this->assertTrue(ArrayToolkit::allInArray(['c', 'a', 'b'], ['a', 'b', 'c', 'd'])); $this->assertFalse(ArrayToolkit::allInArray(['c', 'a', 'b'], ['a', 'd', 'c'])); }
/** * @return array of render settings merged over renderer config */ protected function getOptions() { $config = $this->config->toArray(); $settings = $this->settings->toArray(); return ArrayToolkit::mergeScalarSafe($config, $settings); }
public function __toString() { return sprintf('CUSTOM QUERY: SEARCH %s PARAMS %s %s %s', substr(static::CLASS, strrpos(static::CLASS, '\\') + 1), http_build_query(ArrayToolkit::flatten($this->parameters), '', ', '), isset($this->limit) ? 'LIMIT ' . $this->limit : '', isset($this->offset) ? 'OFFSET ' . $this->offset : ''); }
protected function getTemplateParameters() { $params = parent::getTemplateParameters(); $original_activity_map = $this->getPayload('subject'); if ($original_activity_map->isEmpty()) { return $params; } $hidden_activity_names = (array) $this->getOption('hidden_activity_names', []); // remove all activities that are excluded via config/settings $activity_map = $original_activity_map->filter(function ($activity) use($hidden_activity_names) { if (in_array($activity->getName(), $hidden_activity_names)) { return false; } return true; }); if ($activity_map->isEmpty()) { return $params; } // determine which of the remaining activities should be the primary/current one $default_activity_name = $this->getOption('default_activity_name', ''); if (!$activity_map->hasKey($default_activity_name)) { $default_activity_name = $activity_map->getKeys()[0]; } $default_activity = $activity_map->getItem($default_activity_name); $default_activity_label = $default_activity->getLabel(); if (empty($default_activity_label)) { $default_activity_label = sprintf('%s.label', $default_activity->getName()); } $dropdown_label = $this->_($this->getOption('dropdown_label', $default_activity_label)); $rendered_activities = []; foreach ($activity_map as $activity) { $name = $activity->getName(); if (in_array($name, $hidden_activity_names) && $name !== $default_activity_name) { continue; // don't render activities that should not be displayed } $additional_payload = ['subject' => $activity]; // workflow activities need an 'resource' or 'module' to generate the url correctly, leaky abstraction \o/ if ($this->hasPayload('resource')) { $additional_payload['resource'] = $this->payload->get('resource'); } elseif ($this->hasPayload('module')) { $additional_payload['module'] = $this->payload->get('module'); } // retrieve config for specific activity $specific_activity_options_key = 'activity.' . $activity->getName(); $default_config = $this->getOption($specific_activity_options_key, new Settings()); $activity_renderer_config = $this->view_config_service->getRendererConfig($this->getOption('view_scope'), $this->output_format, $specific_activity_options_key, $default_config->toArray()); // propagate subset of activitymap options to activities $activity_map_option_propagated_keys = array_flip(['as_dropdown', 'as_list', 'default_activity_name', 'emphasized', 'toggle_disabled', 'view_scope']); $options = $this->getOptions(); $activity_map_propagated_options = array_intersect_key($options, $activity_map_option_propagated_keys); $rendered_activities[$name] = $this->renderer_service->renderSubject($activity, $this->output_format, $activity_renderer_config, $additional_payload, new Settings(['activity_map_options' => $activity_map_propagated_options])); } // put default activity to top as that should be the primary activity ArrayToolkit::moveToTop($rendered_activities, $default_activity_name); $params['name'] = $this->getOption('name'); $params['tag'] = $this->getOption('tag'); $params['html_attributes'] = $this->getOption('html_attributes'); $default_css = 'activity-map'; $params['css'] = $this->getOption('css', $default_css); $params['emphasized'] = $this->getOption('emphasized', false); $params['trigger_id'] = $this->getOption('trigger_id'); $params['trigger_css'] = $this->getOption('trigger_css'); $params['trigger_html_attributes'] = $this->getOption('trigger_html_attributes'); $params['toggle_content'] = $this->getOption('toggle_content'); $params['toggle_css'] = $this->getOption('css'); $params['toggle_html_attributes'] = $this->getOption('toggle_html_attributes'); $params['default_activity_rels'] = []; // when it's a list or splitbutton => rendered default activity is being used as "label" $default_label = $dropdown_label; if (!$this->getOption('as_dropdown', false)) { $default_label = $rendered_activities[$default_activity_name]; // @todo Should default-activity rels be used just when a replacement default content/label is not provided? $params['default_activity_rels'] = $this->getOption('default_activity_rels', $default_activity->getRels()); } $params['default_content'] = $this->getOption('default_content', $default_label); $params['default_css'] = $this->getOption('default_css'); $params['default_html_attributes'] = $this->getOption('default_html_attributes'); // don't render primary activity in (more) activities list when no dropdown label was given // thus, when a dropdown_label was specified the (more) activities are ALL activities if (!$this->getOption('dropdown_label', false)) { if (!$this->getOption('as_list')) { // when as_list is given, then don't remove, as ALL should be shown unset($rendered_activities[$default_activity_name]); } } $params['more_css'] = $this->getOption('more_css'); $params['more_html_attributes'] = $this->getOption('more_html_attributes'); $params['more_activities'] = $this->getOption('more_activities', $rendered_activities); $params['toggle_disabled'] = $this->getOption('toggle_disabled', false); if (!count($params['more_activities'])) { $params['toggle_disabled'] = true; } return $params; }
protected function getGroupedInputFieldName() { $entity_type = $this->attribute->getType(); $group_parts = $this->getOption('group_parts', []); if ($group_parts instanceof SettingsInterface) { $group_parts = $group_parts->toArray(); } elseif (!is_array($group_parts)) { throw new RuntimeError('Invalid value type given for "group_parts" option. Only arrays are supported here.'); } $value_path = $this->getOption('attribute_value_path'); $field_specific_group_parts = explode('.', $this->attribute->getPath()); if (!empty($value_path)) { $value_path_group_parts = explode('.', $value_path); $calc_index = 1; foreach ($value_path_group_parts as $actual_idx => $value_path_group_part) { if ($calc_index % 2 === 0) { if (preg_match('/[\\w\\*]+\\[(\\d+)\\]/', $value_path_group_part, $matches)) { $group_parts[] = $matches[1]; } else { throw new RuntimeError(sprintf('Invalid attribute_value_path "%s" given to renderer "%s" for field "%s".' . ' Missing expected embed index within path specification.', $value_path, static::CLASS, $this->attribute->getPath())); } } else { $group_parts[] = $value_path_group_part; } $calc_index++; } } else { if ($this->attribute->getType()->isRoot()) { $group_parts = array_merge($group_parts, explode('.', $this->attribute->getPath())); } else { $group_parts[] = $this->attribute->getName(); } } return ArrayToolkit::flattenToArrayPath($group_parts); }
public static function filterEmptyPayloadComingFromFiles(HandlesFileInterface $attribute, array $payload) { $filtered_payload = []; foreach ($payload as $image_data) { if (isset($image_data['[{@= index @}]'])) { continue; } $value = ArrayToolkit::filterEmptyValues($image_data); if (!empty($value)) { $filtered_payload[] = $value; } } return $filtered_payload; }