Validate the HRef
@param SimpleXMLElement $xlinkAttributes
@param string $linkbaseName
@param array $locatorParts An array of url parts
@param string $linkbaseUrl
@return boolean
334435
private function validateLocator( $xlinkAttributes, $linkbaseName, $locatorParts, $linkbaseUrl )
	{
		$result = true;

		// $href = (string) $xlinkAttributes->href;
		// $parts = parse_url( $href );
		if ( ! isset( $locatorParts['path'] ) )
		{
			if ( ! isset( $locatorParts['fragment'] ) )
			{
				$this->log()->taxonomy_validation( "3.5.3.7.2", "The href of the locator is not valid",
					array(
						'linkbase' => $linkbaseName,
						'href' => $href,
					)
				);

				return false;
			}

			// The locator points to a reference that has already been loaded.  Just check that it has.
			$result = isset( $this->linkbaseIds[ basename( $linkbaseUrl ) ][ trim( $locatorParts['fragment'], '#' ) ] );
			return $result;
		}

		if ( XBRL::endsWith( $locatorParts['path'], '.xml' ) )
		{
			// //BMS 2018-05-04 Dont think this is necessary.  Copied to retrieveLocator for now
			// // It's a linkbase reference
			// if ( isset( $this->linkbaseIds[ basename( $locatorParts['path'] ) ] ) )
			// {
			// 	return true;
			// }
            //
			// $linkbaseRef = array(
			// 	'type' => (string) $xlinkAttributes->type,
			// 	// BMS 2017-10-27 This makes the linkbase relative to the location of the schema file which is not correct
			// 	// 'href' => XBRL::resolve_path( $taxonomy->getSchemaLocation(), $href ),
			// 	'href' => XBRL::resolve_path( $this->schemaLocation, $locatorParts['path'] ),
			// 	'role' => XBRL_Constants::$anyLinkbaseRef,
			// 	'arcrole' => \XBRL_Constants::$arcRoleLinkbase,
			// 	'title' => '',
			// 	'base' => '',
			// );
            //
			// $this->processPresentationLinkbase( $linkbaseRef );
			// $this->processLabelLinkbase( $linkbaseRef );
			// $this->processDefinitionLinkbase( $linkbaseRef );
			// $this->processCalculationLinkbase( $linkbaseRef );
			// $this->processReferenceLinkbase( $linkbaseRef );
			// // Handle custom linkbases
			// $this->processCustomLinkbaseArcRoles( $linkbaseRef );

			return true;
		}

		/**
		 * @var XBRL $taxonomy
		 */
		$taxonomy = basename( $locatorParts['path'] ) == $this->getTaxonomyXSD()
			? $this
			// BMS 2019-01-26 Changed to explicity use the basename as getTaxonomyForXSD no longer will
			: $this->getTaxonomyForXSD( basename( $locatorParts['path'] ) );

		if ( ! $taxonomy )
		{
			// If the linkbase is 'labelLink' look in the labels
			if ( $linkbaseName == 'labelLink' )
			{
				$labelsHref =& $this->context->labels[ XBRL_Constants::$defaultLinkRole ]['labelshref'];
				if ( ! isset( $labelsHref[ basename( $locatorParts['path'] ) ] ) ||
					 ! isset( $labelsHref[ basename( $locatorParts['path'] ) ][ $locatorParts['fragment'] ] ) )
				{
					$result = false;
				}
			}
			else
			{
				// Look for the taxonomy and include its contents in the DTS
				$xsd = $this->resolve_path( $this->getSchemaLocation(), $href );
				$xsd = strpos( $xsd, '#' ) ? strstr( $xsd, '#', true ) : $xsd;

				$taxonomy = XBRL::withTaxonomy( $xsd );
				// $taxonomy = $this->getTaxonomyForXSD( $xsd );
			}
		}

		if ( empty( $locatorParts['fragment'] ) )
		{
			return $result;
		}

		if ( $taxonomy )
		{
			// BMS 2018-04-16	This is required by the XBRL 2.1 specification (see test 2012 V-02)
			$element =& $taxonomy->getElementById( $locatorParts['fragment'] );
			if ( ! $element &&
				 ! isset( $taxonomy->roleTypeIds[ $locatorParts['fragment'] ] ) &&
				 ! isset( $taxonomy->arcroleTypeIds[ $locatorParts['fragment'] ] ) &&
				 ! $taxonomy->context->types->getTypeById( $locatorParts['fragment'], $taxonomy->getPrefix() )
			)
			{

				$this->log()->taxonomy_validation( "3.5.3.9.2", "The id of the locator does not exist in the DTS",
					array(
						'href' => basename( $linkbaseUrl ),
						'linkbase' => $linkbaseName,
					)
				);
				$result = false;
			}
		}
		else
		{
			$this->log()->taxonomy_validation( "3.5.3.7.2", "The document of the locator does not exist in the DTS",
				array(
					'href' => $locatorParts['path'],
					'linkbase' => $linkbaseName,
				)
			);
			$result = false;
		}

		return $result;
	}
481047
protected function getInvalidLinkError($scheme, $target, $anchorName = null)
    {
        $url = "$scheme://$target" . ($anchorName ? '#' . $anchorName : '');

        switch ($scheme) {
            case 'eznode':
                return sprintf('Invalid link "%s": target node cannot be found', $url);
            case 'ezobject':
                return sprintf('Invalid link "%s": target object cannot be found', $url);
            default:
                throw new InvalidArgumentException($scheme, "Given scheme '{$scheme}' is not supported.");
        }
    }
921714
private static function hasAttributesFromUriPath($url, $path, &$attributes)
    {
        $i     = 0;
        $match = true;
        $path  = explode('/', $path);

        foreach ($path as $j => $segment) {
            if (isset($url[$i])) {
                if ($segment !== $url[$i]) {
                    self::extractAttributesFromSegment($url, $path, $i, $j, $segment, $attributes);
                }

                $i++;
                continue;
            }
            elseif ( ! preg_match('/{[\w]+\?}/', $segment)) {
                // No optional parameters but no more $url given this route does not match the url
                $match = false;
                break;
            }
        }

        if (isset($url[$i + 1]))
            $match = false;

        return $match;
    }
406996
private function annotationRel(array $annotations, LinkType $link, ResourceObject $current) : ResourceObject
    {
        /* @noinspection LoopWhichDoesNotLoopInspection */
        foreach ($annotations as $annotation) {
            if ($annotation->rel !== $link->key) {
                continue;
            }
            $uri = uri_template($annotation->href, $current->body);
            $rel = $this->factory->newInstance($uri);
            /* @noinspection UnnecessaryParenthesesInspection */
            $request = new Request($this->invoker, $rel, Request::GET, (new Uri($uri))->query);

            return $this->invoker->invoke($request);
        }

        throw new LinkRelException("rel:{$link->key} class:" . get_class($current), 500);
    }
102808
public function link($url, $name, $position="BL", $attributes=array())
    {
        $base = str_replace(Request::path(),'',strtok(Request::fullUrl(),'?'));
        $match_url = str_replace($base, '/', strtok($url,'?'));
        if (Request::path()!= $match_url) {
            $url = Persistence::get($match_url, parse_url($url, PHP_URL_QUERY));
        }


        $attributes = array_merge(array("class"=>"btn btn-default"), $attributes);
        $this->button_container[$position][] =  HTML::link($url, $name, $attributes);
        $this->links[] = $url;

        return $this;
    }
403347
public function getRawLinkAttributes($extraAttributes = null) {
    $url = $this->getUrl();
    if (is_null($url)) {
      return null;
    }

    $attributes = [ 'href' => $url ];

    $ariaLabel = $this->getAriaLabel();
    if (!empty($ariaLabel)) {
      $attributes['arial-label'] = $ariaLabel;
    }

    $target = $this->getTarget();
    if (!empty($target)) {
      $attributes['target'] = $target;

      if ($target === '_blank' && $this->linkField->autoNoReferrer) {
        $attributes['rel'] = 'noopener noreferrer';
      }
    }

    $title = $this->getTitle();
    if (!empty($title)) {
      $attributes['title'] = $title;
    }

    if (is_array($extraAttributes)) {
      $attributes = $extraAttributes + $attributes;
    }

    return $attributes;
  }
587211
public function tags($baseUrl, $attributes)
    {
        $html = '';
        foreach($this->files as $file)
        {
            $file = $baseUrl . str_replace($this->publicPath, '', $file);
            $html .= $this->tag($file, $attributes);
        }

        return $html;
    }
285323
protected void processLinkTag(LinkTag tag) {

        processLink(tag, ATTRIBUTE_HREF, CmsRelationType.valueOf(tag.getTagName()));
    }
109402
public static function isStandardResourceOrExtLinkElement( $namespaceURI, $localName )
	{
		return 	$namespaceURI == self::$standardPrefixes[ STANDARD_PREFIX_LINK ] &&
				isset( self::$standardLinkElements[ $localName ] ) ||
				qnameNsLocalName( $namespaceURI, $localName )->equals( self::qnameNS( self::$ixRelationship ) );
	}
105655
public static function buildSitemap( $links, $baseUrl = "" )
	{
		$root	= new XML_DOM_Node( "urlset" );
		$root->setAttribute( 'xmlns', "http://www.google.com/schemas/sitemap/0.84" );
		foreach( $links as $link )
		{
			$child	= new XML_DOM_Node( "url" );
			$loc	= new XML_DOM_Node( "loc", $baseUrl.$link );
			$child->addChild( $loc );
			$root->addChild( $child );
		}
		$builder	= new XML_DOM_Builder();
		return $builder->build( $root );
	}
830408
private function setAsLink($name, $link)
    {
        if ($name === 'meta') {
            $this->set($name, $this->create('Meta', $link));

            return;
        }

        // every link must be an URL
        if (! is_string($link)) {
            throw new ValidationException('Every link attribute has to be a string, "' . gettype($link) . '" given.');
        }

        $this->set($name, strval($link));
    }
1351574
private function reportMissingArcAttribute( $section, $attributeName, $linkbase ) {
		$this->reportMissingXLinkAttribute( $section, "Arcs MUST include required XLink attributes", $attributeName, $linkbase );
		return false;
	}
279542
public function link($url, $title, $attributes = [])
    {
        $attributes['href'] = $url;
        $tag = new Tag('a', $attributes);
        $tag->setText($title);
        return $tag;
    }
678521
private function createLinkbaseRefList()
	{
		$linkbaseBase = (string)$this->xbrlDocument->attributes( XBRL_Constants::$standardPrefixes[ STANDARD_PREFIX_XML ] )->base;

		$nodes = $this->xbrlDocument->children( XBRL_Constants::$standardPrefixes[ STANDARD_PREFIX_SCHEMA ] );
		if ( property_exists( $nodes, 'annotation' ) )
		{
			$annotations = $nodes->annotation;
			foreach( $annotations as $annotation )
			{
				$base = $linkbaseBase;
				$base .= (string)$annotation->attributes( XBRL_Constants::$standardPrefixes[ STANDARD_PREFIX_XML ] )->base;
				if ( property_exists( $annotation, 'appinfo' ) )
				{
					$appInfo = $annotation->appinfo;

					$base .= (string)$appInfo->attributes( XBRL_Constants::$standardPrefixes[ STANDARD_PREFIX_XML ] )->base;
					$linkbaseRefs = $appInfo->children( XBRL_Constants::$standardPrefixes[ STANDARD_PREFIX_LINK ] )->linkbaseRef;

					foreach ( $linkbaseRefs as $linkbaseRefskey => $linkbaseRef )
					{
						$xlinkAttributes = $linkbaseRef->attributes( XBRL_Constants::$standardPrefixes[ STANDARD_PREFIX_XLINK ] );
						$attributes = $linkbaseRef->attributes( XBRL_Constants::$standardPrefixes[ STANDARD_PREFIX_XML ] );

						$role = (string) $xlinkAttributes->role;

						if ( empty( $role ) ) $role = XBRL_Constants::$anyLinkbaseRef;

						$base .= (string) $attributes->base;
						// BMS 2018-04-24 The base should include all the separators is needs
						// if ( ! empty( $base ) && ! XBRL::endsWith( $base, '/' ) )
						// {
						//	$base .= '/';
						// }

						if ( $base )
						{
							$parts = array_filter( explode( "/", $base ), function( $part) { return $part != '.'; } );
							// This pair of instructions removes any existing terminating node
							// such as x/y/z so that only x/y remains.  /x/y/z/ will not be changed
							array_pop( $parts );
							array_push( $parts, "" );
							$base = implode( "/", $parts );
						}

						$linkbaseRef = array(
							'type' => (string) $xlinkAttributes->type,
							'href' => XBRL::resolve_path( $this->schemaLocation, (string) $xlinkAttributes->href ),
							'role' => $role,
							'arcrole' => (string) $xlinkAttributes->arcrole,
							'title' => (string) $xlinkAttributes->title,
							'base' => $base,
						);

						$this->linkbaseTypes[ $role ][] = $linkbaseRef;
					}

					$linkbases = $appInfo->children( XBRL_Constants::$standardPrefixes[ STANDARD_PREFIX_LINK ] )->linkbase;

					foreach ( $linkbases as $linkbaseskey => $linkbase )
					{
						// TODO
					}
				}
			}
		}

	}
79971
private function validatedPresentationLinkbasePreferredLabels()
	{
		// This test is only needed by the XBRL 2.1 conformance suite test 299
		if ( ! defined( 'CONFORMANCE_TEST_SUITE_XBRL_21') ) return;

		$roleRefs = $this->getPresentationRoleRefs();
		$step = 0;
		// Iterate over all the role refs
		foreach ( $roleRefs as $roleUri => $roleRef )
		{
			$step = "1 - $roleUri";
			// Traverse all the nodes to look for any with a preferred label
			$this->processAllNodes( $roleRef['hierarchy'], function( $node, $id ) use( $roleRef, $roleUri )
			{
				// To distinguish presentation hiearchy nodes that are periodStart or periodEnd but have the same id
				// (such as uk-gaap-pt-2004-12-01.xsd#uk-gaap-pt_NetDebtFunds) the process of creating the hierarchy
				// generates two ids with the 'periodEndLabel' or 'periodStartLabel'.  It also adds these to the
				// element index of the respective taxonomy (uk-gaap-pt-2004-12-01.xsd in this case).  Because there
				// will be no label for a manufactured id (such as uk-gaap-pt_NetDebtFundsperiodEndLabel) it's
				// necessary to lookup the manufactured element in the respective taxonmy and use the id of the element
				// array that's returned.
				$nodeTaxonomy = $this->getTaxonomyForXSD($node['label']);
				$nodeElement = $nodeTaxonomy->getelementById($node['label']);
				$nodeLabel = "{$nodeTaxonomy->getTaxonomyXSD()}#{$nodeElement['id']}";

				if ( ! isset( $node['preferredLabel'] ) ) return true;

				$step = "2 - {$node['preferredLabel']}";

				// The label should have an arc
				// BMS 2018-05-08 Labels use the default link role
				// if ( isset( $this->context->labels[ $roleUri ]['arcs'][ $node['label'] ] ) )
				// if ( isset( $this->context->labels[ \XBRL_Constants::$defaultLinkRole ]['arcs'][ $node['label'] ] ) )
				if ( isset( $this->context->labels[ \XBRL_Constants::$defaultLinkRole ]['arcs'][ $nodeLabel ] ) )
				{
					$step = "3 - {$node['label']}";

					// Create a shortcut to a sub-element
					// $labels =& $this->context->labels[ $roleUri ];
					$labels =& $this->context->labels[ \XBRL_Constants::$defaultLinkRole ];

					// Check the preferred label exists
					if ( isset( $labels['labels'][ $node['preferredLabel'] ] ) )
					{
						$step = "4";

						// Now check there is a preferred label for the arc target
						// foreach ( $labels['arcs'][ $node['label'] ] as $targetLabel => $details )
						foreach ( $labels['arcs'][ $nodeLabel ] as $targetLabel => $details )
						{
							$step = "5 - {$targetLabel}";
							// and locate the label in any lanuage
							foreach ( $labels['labels'][ $node['preferredLabel'] ] as $lang => $labelLabel )
							{
								$step = "6 - {$lang}";

								// If it exists then
								if ( isset( $labelLabel[ $targetLabel ] ) )
								{
									return true;
								}
							}
						}
					}
				}

				$this->log()->taxonomy_validation( "5.2.4.2.1", "A presentation arc preferred label role assigment is not defined as a label",
					array(
						'preferred label' => $node['preferredLabel'],
						'arc to' => $node['label']
					)
				);

			} );
		}
	}
797375
public function validateUrl($attribute, $params)
    {
        $parentParentId = (null === $this->structure) ? 0 : (int)$this->structure->parent_id;
        $parentContextId = (null === $this->structure) ? 0 : (int)$this->structure->context_id;
        if (
            $this->slug != $this->oldSlug
            || $this->parentParentId !== $parentParentId
            || $this->parentContextId !== $parentContextId
        ) {
            $url = $this->compileUrl();
            $query = self::find()
                ->select('url')
                ->innerJoin(
                    BaseStructure::tableName(),
                    'model_id = ' . BaseStructure::tableName() . '.id'
                )
                ->where([
                    'language_id' => $this->language_id,
                    'context_id' => $this->parentContextId,
                    'url' => $url
                ]);
            if (false === $this->isNewRecord) {
                $query->andWhere(['not', ['model_id' => $this->model_id]]);
            }
            $isset = $query->scalar();
            if (false !== $isset) {
                $this->addError('slug', Yii::t(
                    'dotplant.entity.structure',
                    'Value \'{value}\' already in use, please, choose another!',
                    ['value' => $this->slug]
                ));
            }
            $this->url = $url;
        }
    }
21701
function(href) {
        var node = this.createElementDefaultNS("OnlineResource");
        this.setAttributeNS(node, this.namespaces.xlink, "xlink:type", "simple");
        this.setAttributeNS(node, this.namespaces.xlink, "xlink:href", href);
        return node;
    }