Prepare a Drawer to visualize section associations

@param  Section $section The current Section object
@throws InvalidArgumentException
@throws Exception
435679
private function prepareAssociationsDrawer($section)
    {
        $entry_id = (!is_null($this->_context['entry_id'])) ? $this->_context['entry_id'] : null;
        $show_entries = Symphony::Configuration()->get('association_maximum_rows', 'symphony');

        if (is_null($entry_id) && !isset($_GET['prepopulate']) || is_null($show_entries) || $show_entries == 0) {
            return;
        }

        $parent_associations = SectionManager::fetchParentAssociations($section->get('id'), true);
        $child_associations = SectionManager::fetchChildAssociations($section->get('id'), true);
        $content = null;
        $drawer_position = 'vertical-right';

        /**
         * Prepare Associations Drawer from an Extension
         *
         * @since Symphony 2.3.3
         * @delegate PrepareAssociationsDrawer
         * @param string $context
         * '/publish/'
         * @param integer $entry_id
         *  The entry ID or null
         * @param array $parent_associations
         *  Array of Sections
         * @param array $child_associations
         *  Array of Sections
         * @param string $drawer_position
         *  The position of the Drawer, defaults to `vertical-right`. Available
         *  values of `vertical-left, `vertical-right` and `horizontal`
         */
        Symphony::ExtensionManager()->notifyMembers('PrepareAssociationsDrawer', '/publish/', array(
            'entry_id' => $entry_id,
            'parent_associations' => &$parent_associations,
            'child_associations' => &$child_associations,
            'content' => &$content,
            'drawer-position' => &$drawer_position
        ));

        // If there are no associations, return now.
        if (
            (is_null($parent_associations) || empty($parent_associations))
            &&
            (is_null($child_associations) || empty($child_associations))
        ) {
            return;
        }

        if (!($content instanceof XMLElement)) {
            $content = new XMLElement('div', null, array('class' => 'content'));
            $content->setSelfClosingTag(false);

            // backup global sorting
            $sorting = EntryManager::getFetchSorting();

            // Process Parent Associations
            if (!is_null($parent_associations) && !empty($parent_associations)) {
                $title = new XMLElement('h2', __('Linked to') . ':', array('class' => 'association-title'));
                $content->appendChild($title);

                foreach ($parent_associations as $as) {
                    if (empty($as['parent_section_field_id'])) {
                        continue;
                    }
                    if ($field = FieldManager::fetch($as['parent_section_field_id'])) {
                        // Get the related section
                        $parent_section = SectionManager::fetch($as['parent_section_id']);

                        if (!($parent_section instanceof Section)) {
                            continue;
                        }

                        // set global sorting for associated section
                        EntryManager::setFetchSorting(
                            $parent_section->getSortingField(),
                            $parent_section->getSortingOrder()
                        );

                        if (isset($_GET['prepopulate'])) {
                            $prepopulate_field = key($_GET['prepopulate']);
                        }

                        // get associated entries if entry exists,
                        if ($entry_id) {
                            $relation_field = FieldManager::fetch($as['child_section_field_id']);
                            $entry_ids = $relation_field->findParentRelatedEntries($as['parent_section_field_id'], $entry_id);

                            // get prepopulated entry otherwise
                        } elseif (isset($_GET['prepopulate']) && is_array($_GET['prepopulate']) && isset($_GET['prepopulate'][$as['child_section_field_id']])) {
                            $entry_ids = array(intval($_GET['prepopulate'][$as['child_section_field_id']]));
                        } else {
                            $entry_ids = array();
                        }

                        // Use $schema for perf reasons
                        $schema = array($field->get('element_name'));
                        $where = (!empty($entry_ids)) ? sprintf(' AND `e`.`id` IN (%s)', implode(', ', $entry_ids)) : null;
                        $entries = (!empty($entry_ids) || isset($_GET['prepopulate']) && $field->get('id') === $prepopulate_field)
                            ? EntryManager::fetchByPage(1, $as['parent_section_id'], $show_entries, $where, null, false, false, true, $schema)
                            : array();
                        $has_entries = !empty($entries) && $entries['total-entries'] != 0;

                        // Create link
                        $link = SYMPHONY_URL . '/publish/' . $as['handle'] . '/';
                        $aname = General::sanitize($as['name']);
                        if ($has_entries) {
                            $aname .= ' <span>(' . $entries['total-entries'] . ')</span>';
                        }
                        $a = new XMLElement('a', $aname, array(
                            'class' => 'association-section',
                            'href' => $link,
                            'title' => strip_tags($aname),
                        ));

                        if (!$has_entries) {
                            unset($field);
                            continue;
                        }

                        $element = new XMLElement('section', null, array('class' => 'association parent'));
                        $header = new XMLElement('header');
                        $header->appendChild(new XMLElement('p', $a->generate()));
                        $element->appendChild($header);

                        $ul = new XMLElement('ul', null, array(
                            'class' => 'association-links',
                            'data-section-id' => $as['child_section_id'],
                            'data-association-ids' => implode(', ', $entry_ids)
                        ));

                        foreach ($entries['records'] as $e) {
                            // let the field create the mark up
                            $li = $field->prepareAssociationsDrawerXMLElement($e, $as);
                            // add it to the unordered list
                            $ul->appendChild($li);
                        }

                        $element->appendChild($ul);
                        $content->appendChild($element);
                        unset($field);
                    }
                }
            }

            // Process Child Associations
            if (!is_null($child_associations) && !empty($child_associations)) {
                $title = new XMLElement('h2', __('Links in') . ':', array('class' => 'association-title'));
                $content->appendChild($title);

                foreach ($child_associations as $as) {
                    // Get the related section
                    $child_section = SectionManager::fetch($as['child_section_id']);

                    if (!($child_section instanceof Section)) {
                        continue;
                    }

                    // set global sorting for associated section
                    EntryManager::setFetchSorting(
                        $child_section->getSortingField(),
                        $child_section->getSortingOrder()
                    );

                    // Get the visible field instance (using the sorting field, this is more flexible than visibleColumns())
                    // Get the link field instance
                    $visible_field   = current($child_section->fetchVisibleColumns());
                    $relation_field  = FieldManager::fetch($as['child_section_field_id']);

                    $entry_ids = $relation_field->findRelatedEntries($entry_id, $as['parent_section_field_id']);

                    $schema = $visible_field ? array($visible_field->get('element_name')) : array();
                    $where = sprintf(' AND `e`.`id` IN (%s)', implode(', ', $entry_ids));

                    $entries = (!empty($entry_ids)) ? EntryManager::fetchByPage(1, $as['child_section_id'], $show_entries, $where, null, false, false, true, $schema) : array();
                    $has_entries = !empty($entries) && $entries['total-entries'] != 0;

                    // Build the HTML of the relationship
                    $element = new XMLElement('section', null, array('class' => 'association child'));
                    $header = new XMLElement('header');

                    // Get the search value for filters and prepopulate
                    $filter = '';
                    $prepopulate = '';
                    $entry = current(EntryManager::fetch($entry_id));
                    if ($entry) {
                        $search_value = $relation_field->fetchAssociatedEntrySearchValue(
                            $entry->getData($as['parent_section_field_id']),
                            $as['parent_section_field_id'],
                            $entry_id
                        );
                        if (is_array($search_value)) {
                            $search_value = $entry_id;
                        }
                        $filter = '?filter[' . $relation_field->get('element_name') . ']=' . $search_value;
                        $prepopulate = '?prepopulate[' . $as['child_section_field_id'] . ']=' . $search_value;
                    }

                    // Create link with filter or prepopulate
                    $link = SYMPHONY_URL . '/publish/' . $as['handle'] . '/' . $filter;
                    $aname = General::sanitize($as['name']);
                    if ($has_entries) {
                        $aname .= ' <span>(' . $entries['total-entries'] . ')</span>';
                    }
                    $a = new XMLElement('a', $aname, array(
                        'class' => 'association-section',
                        'href' => $link,
                        'title' => strip_tags($aname),
                    ));

                    // Create new entries
                    $create = new XMLElement('a', __('New'), array(
                        'class' => 'button association-new',
                        'href' => SYMPHONY_URL . '/publish/' . $as['handle'] . '/new/' . $prepopulate
                    ));

                    // Display existing entries
                    if ($has_entries) {
                        $header->appendChild(new XMLElement('p', $a->generate()));

                        $ul = new XMLElement('ul', null, array(
                            'class' => 'association-links',
                            'data-section-id' => $as['child_section_id'],
                            'data-association-ids' => implode(', ', $entry_ids)
                        ));

                        foreach ($entries['records'] as $key => $e) {
                            // let the first visible field create the mark up
                            if ($visible_field) {
                                $li = $visible_field->prepareAssociationsDrawerXMLElement($e, $as, $prepopulate);
                            }
                            // or use the system:id if no visible field exists.
                            else {
                                $li = Field::createAssociationsDrawerXMLElement($e->get('id'), $e, $as, $prepopulate);
                            }

                            // add it to the unordered list
                            $ul->appendChild($li);
                        }

                        $element->appendChild($ul);

                        // If we are only showing 'some' of the entries, then show this on the UI
                        if ($entries['total-entries'] > $show_entries) {
                            $pagination = new XMLElement('li', null, array(
                                'class' => 'association-more',
                                'data-current-page' => '1',
                                'data-total-pages' => ceil($entries['total-entries'] / $show_entries),
                                'data-total-entries' => $entries['total-entries']
                            ));
                            $counts = new XMLElement('a', __('Show more entries'), array(
                                'href' => $link
                            ));

                            $pagination->appendChild($counts);
                            $ul->appendChild($pagination);
                        }

                        // No entries
                    } else {
                        $element->setAttribute('class', 'association child empty');
                        $header->appendChild(new XMLElement('p', __('No links in %s', array($a->generate()))));
                    }

                    $header->appendChild($create);
                    $element->prependChild($header);
                    $content->appendChild($element);
                }
            }

            // reset global sorting
            EntryManager::setFetchSorting(
                $sorting->field,
                $sorting->direction
            );
        }

        $drawer = Widget::Drawer('section-associations', __('Show Associations'), $content);
        $this->insertDrawer($drawer, $drawer_position, 'prepend');
    }
666484
public function section($section, $position = null)
    {
        if (is_string($section)) {
            $section = new FormSection($section);
        }

        return null !== $position ? $this->insert($section, $position) : $this->push($section);
    }
1027393
protected function extendSection($section, $content)
    {
        if (isset($this->sections[$section])) {
            $content = str_replace(static::parentPlaceholder($section), $content, $this->sections[$section]);
        }

        $this->sections[$section] = $content;
    }
1160184
public function setSectionsMode($mode) {
		if (! in_array($mode, [
			self::SECTIONS_LOCALE,
			self::SECTIONS_DOMAIN,
			self::SECTIONS_IGNORE
		], true)) {
			throw new InvalidParameter('Unknown mode of sections treatment: "' . $mode . '"');
		}
		
		$this->sectionsMode = $mode;
		
		return $this;
	}
596254
public function removeEntry( $entry, $section = NULL )
	{
		if( !$section )
			$section	= $this->getSectionOfEntry( $entry );
		$index	= $this->getIndex( $entry, $section );
		if( $index === FALSE )
			throw new InvalidArgumentException( 'Entry "'.$entry.'" not found in Section "'.$section.'".' );
		unset( $this->list[$section][$index] );
	}
844423
public function setSection(\Coral\ContentBundle\Entity\Section $section)
    {
        $this->section = $section;

        return $this;
    }
509534
public function setComment( $key, $comment, $section = NULL )
	{
		if( $this->usesSections() )
		{
			if( !$this->hasProperty( $key, $section ) )
				throw new InvalidArgumentException( 'Key "'.$key.'" is not existing in Section "'.$section.'".' );
			$this->comments[$section][$key] = $comment;
		}
		else
		{
			if( !$this->hasProperty( $key ) )
				throw new InvalidArgumentException( 'Key "'.$key.'" is not existing' );
			$this->comments[$key] = $comment;
		}
		return is_int( $this->write() );
	}
337956
public function make_section_globals($section) {
		if(!is_null($section) && strlen($section) && in_array($section, $this->get_valid_sections())) {
			foreach($this->fullConfig[$section] as $k=>$parsedValue) {
				//TODO: implement option to set a section/value as a GLOBAL
				$GLOBALS[$k] = $parsedValue;
			}
		}
		else {
			throw InvalidArgumentException("non-existent section, '". $section ."'");
		}
	}
893986
protected function startSection($section, $content = '')
    {
        if ($content === '') {
            if (ob_start()) {
                $this->scope->sectionStack[] = $section; //push
            }
        }
        else {
            $this->storeSection($section, $content);
        }
    }
1205078
public function mapSection($section, $className)
    {
        if (false === class_exists($className)) {
            throw new \InvalidArgumentException('This section class does not exist');
        } elseif (false === is_a($className, 'Supervisor\Configuration\Section', true)) {
            throw new \InvalidArgumentException('This section class must implement Supervisor\Configuration\Section');
        }

        $this->sectionMap[$section] = $className;
    }
1214600
public function delete(string $section, string $key) : bool
    {
        if ($section === '') {
            throw new \InvalidArgumentException('Arg \'section\' cannot be empty.');
        }
        if (isset($this->map[$section])) {
            if ($this->arrayAccess[$section]) {
                unset($this->map[$section][$key]);
            }
            else {
                unset($this->map[$section]->{$key});
            }
        }
        return true;
    }
353098
public function make_section_constants($section) {
		if(!is_null($section) && strlen($section) && in_array($section, $this->get_valid_sections())) {
			foreach($this->fullConfig[$section] as $k=>$parsedValue) {
				//TODO: implement option to set a section/value as a CONSTANT
				$constantName = $k;
				if(!defined($constantName)) {
					define($constantName, $parsedValue);
				}
				
				$constantPlusSection = preg_replace('~\-~', '_', $section) .'-'. $constantName;
				if(!defined($constantPlusSection)) {
					define($constantPlusSection, $parsedValue);
				}
			}
		}
		else {
			throw new InvalidArgumentException("non-existent section, '". $section ."'");
		}
	}
1075140
public function placeToSections(array $componentsBySections)
    {
        foreach ($componentsBySections as $section => $children) {
            if (!is_array($children)) {
                throw new InvalidArgumentException(
                    'Wrong argument format for Layout::placeToSections. Array of components for each section expected.'
                );
            }
            $this->section($section)->addChildren($children);
        }
        return $this;
    }
195050
public function removeSection( $section )
	{
		if( !$this->usesSections() )
			throw new RuntimeException( 'Sections are disabled' );
		if( !$this->hasSection( $section ) )
			throw new InvalidArgumentException( 'Section "'.$section.'" is not existing' );
		$index	= array_search( $section, $this->sections);
		unset( $this->sections[$index] );
		return is_int( $this->write() );
	}
1231240
public void addTickLabelSection(final Section SECTION) {
        if (null == SECTION) return;
        tickLabelSections.add(SECTION);
        Collections.sort(tickLabelSections, new SectionComparator());
        fireUpdateEvent(REDRAW_EVENT);
    }
310269
public function setSectionIdentifier($sectionIdentifier)
    {
        if (Format::isIdentifier($sectionIdentifier) || empty($sectionIdentifier)) {
            $this->sectionIdentifier = $sectionIdentifier;
        } else {
            $msg = "'${sectionIndentifier}' is not a valid QTI Identifier.";
            throw new InvalidArgumentException($msg);
        }
    }
10833
public function addEntry( $entry, $section )
	{
		if( isset( $this->list[$section] ) && is_array( $this->list[$section] ) && in_array( $entry, $this->list[$section] ) )
			throw new InvalidArgumentException( 'Entry "'.$entry.'" is already in Section "'.$section.'".' );
		$this->list[$section][] = $entry;
	}