Check the select and as
{@inheritDoc}
@see \XBRL\Formulas\Resources\Resource::validate()
@param VariableSet $variableSet
@param XmlNamespaceManager $nsMgr
762900
public function validate( $variableSet, $nsMgr )
	{
		try
		{
			if ( isset( $this->select ) && ! empty( $this->select ) )
			{
				$expression = XPath2Expression::Compile( $this->select, $nsMgr );
				$this->selectXPath2expression = $expression;
			}

			return true;
		}
		catch ( \Exception $ex )
		{
			\XBRL_Log::getInstance()->formula_validation( "General variable", "Failed to compile select expression",
				array(
					'select' => $this->select,
					'error' => $ex instanceof XPath2Exception ? $ex->ErrorCode : get_class( $ex ),
					'reason' => $ex->getMessage()
				)
			);
		}
	}
494423
protected function validate( $xmlElement )
	{
		$errors	= array();
		foreach( $xmlElement->getDocNamespaces() as $prefix => $namespace )
		{
			$prefix	= $prefix ? $prefix : "atom";
			$xmlElement->registerXPathNamespace( $prefix, $namespace );
		}
		$key	= "//atom:feed/";
		if( !count( $xmlElement->xpath( $key.'atom:author' ) ) )
			foreach( $xmlElement->entry as $entry )
				if( !$entry->author )
					$errors[]	= "feed_author";
		if( count( $xmlElement->xpath( $key.'atom:generator' ) ) > 1 )
			$errors[]	= "feed_generator";
		if( count( $xmlElement->xpath( $key.'atom:icon' ) ) > 1 )
			$errors[]	= "feed_icon";
		if( count( $xmlElement->xpath( $key.'atom:logo' ) ) > 1 )
			$errors[]	= "feed_logo";
		if( count( $xmlElement->xpath( $key.'atom:id' ) ) != 1 )
			$errors[]	= "feed_id";
		if( count( $xmlElement->xpath( $key.'atom:rights' ) ) > 1 )
			$errors[]	= "feed_rights";
		if( count( $xmlElement->xpath( $key.'atom:subtitle' ) ) > 1 )
			$errors[]	= "feed_subtitle";
		if( count( $xmlElement->xpath( $key.'atom:title' ) ) != 1 )
			$errors[]	= "feed_title";
		if( count( $xmlElement->xpath( $key.'atom:updated' ) ) != 1 )
			$errors[]	= "feed_updated";
		$ids	= array();
		foreach( $xmlElement->xpath( $key.'atom:link[@rel="alternate"]' ) as $link )
		{
			$id	= "";
			if( $link->hasAttribute( 'type' ) )
				$id	= $link->getAttribute( 'type' );
			if( $link->hasAttribute( 'hreflang' ) )
				$id	.= "_".$link->getAttribute( 'hreflang');
			if( in_array( $id, $ids ) )
			{
				$errors[]	= "feed_link_unique";
				break;
			}
			$ids[]	= $id;
		}

		$numberEntries	= count( $xmlElement->xpath( $key.'atom:entry' ) );
		for( $i=1; $i<=$numberEntries; $i++ )
		{
			$key	= "//atom:feed/atom:entry[$i]/";
			if( !count( $xmlElement->xpath( $key.'atom:author' ) ) && !count( $xmlElement->xpath( '//atom:feed/atom:author' ) ) )
				$errors[]	= "entry_author";
			if( count( $xmlElement->xpath( $key.'atom:content' ) ) > 1 )
				$errors[]	= "entry_content";
			if( count( $xmlElement->xpath( $key.'atom:id' ) ) != 1 )
				$errors[]	= "entry_id";
			if( !count( $xmlElement->xpath( $key.'atom:content' ) ) && !count( $xmlElement->xpath( $key.'atom:link[@rel="alternate"]' ) ) )
				$errors[]	= "entry_link_alt";
			if( count( $xmlElement->xpath( $key.'atom:published' ) ) > 1 )
				$errors[]	= "entry_published";
			if( count( $xmlElement->xpath( $key.'atom:rights' ) ) > 1 )
				$errors[]	= "entry_rights";
			if( count( $xmlElement->xpath( $key.'atom:source' ) ) > 1 )
				$errors[]	= "entry_source";
			if( count( $xmlElement->xpath( $key.'atom:summary' ) ) > 1 )
				$errors[]	= "entry_summary";
			if( count( $xmlElement->xpath( $key.'atom:title' ) ) != 1 )
				$errors[]	= "entry_title";
			if( count( $xmlElement->xpath( $key.'atom:updated' ) ) != 1 )
				$errors[]	= "entry_updated";

			$keys	= array();
			foreach( $xmlElement->xpath( $key.'atom:link[@rel="alternate"]' ) as $link )
			{
				$key	= "";
				if( $link->hasAttribute( 'type' ) )
					$key	= $link->getAttribute( 'type' );
				if( $link->hasAttribute( 'hreflang' ) )
					$key	.= "_".$link->getAttribute( 'hreflang');
				if( in_array( $key, $keys ) )
				{
					$errors[]	= "entry_link_unique";
					break;
				}
				$keys[]	= $key;
			}
		}
		$this->errors	= $errors;

	}
358472
public function validate( $variableSet, $nsMgr )
	{
		if ( ! $this->name )
		{
			\XBRL_Log::getInstance()->formula_validation( 'Custom function', 'Custom function name is not defined', array(
				'error' => 'xbrlve:noNameForCustomFunction'
			) );
			return false;
		}

		$qname = $this->getQName();

		if ( $qname->namespaceURI == \XBRL_Constants::$standardPrefixes[ STANDARD_PREFIX_FUNCTION_INSTANCE ] )
		{
			\XBRL_Log::getInstance()->formula_validation( 'Custom function', 'Custom function name has a namespace reserved for functions in the function registry (xfi)', array(
				'signature' => $qname->prefix . ":" . $qname->localName,
				'error' => 'xbrlve:noProhibitedNamespaceForCustomFunction'
			) );
		}

		if ( $this->output )
		{
			$outputQName = qname( $this->output, $nsMgr->getNamespaces() );
			if ( $outputQName && ! \XBRL::startsWith( $this->output, "xs:" ) && $outputQName->namespaceURI != \XBRL_Constants::$standardPrefixes[ STANDARD_PREFIX_SCHEMA ] )
			{
				\XBRL_Log::getInstance()->formula_validation( 'Custom function', 'Custom function outut type is not valid', array(
					'type' => $this->output ? $this->output : "missing",
					'error' => 'xbrlve:invalidDatatypeInCustomFunctionSignature'
				) );
			}
		}

		return true;
	}
1221064
public function Bind( $name, $ns, $arity )
	{
		/**
		 * @var XPathFunctionDef $res
		 */
		$res;
		// Also check if XPath 2010 function $namespace is used, and if yes, try older version.
		$namespaces = array_unique( array( $ns, XmlReservedNs::xPathFunc ) );
		foreach ( array( $ns /* , XmlReservedNs::xPathFunc */ ) as $ns )
		{
			if ( ! isset( $this->_funcTable[ $ns ][ $name ][ $arity ] ) )
			{
				if ( ! isset( $this->_funcTable[ $ns ][ $name ][ -1 ] ) ) continue;
				{
					$arity = -1;
				}
			}

			return $this->_funcTable[ $ns ][ $name ][ $arity ]['def'];
		}

		return null;
	}
221899
private function validateVariableSets( $taxonomy, $contextParameters )
	{
		// Variable sets are headed by a formula or assertion
		$variableSets = $taxonomy->getGenericResource( 'variableset', null );

		if ( $variableSets )
		foreach ( $variableSets as $index => $variableSet )
		{
			$variableSetResource = $variableSet['variableset'];

			// Workout the class for this variable set resource
			$element = $variableSetResource[ "{$variableSetResource['type']}Type" ];
			$variableSetClassName = '\\XBRL\\Formulas\\Resources\\' .
				Formulas::$formulaElements[ $element ]['part'] .
				( isset( Formulas::$formulaElements[ $element ]['className'] )
					? Formulas::$formulaElements[ $element ]['className']
					: ucfirst( $element )
				);
			if ( is_null( $variableSetClassName ) )
			{
				$this->log->err( "Variable set sub-type '{$variableSetResource['type']}Type' is not valid" );
				return false;
			}

			// Create the instance and store it
			/** @var VariableSet $variableSetInstance */
			unset( $variableSetInstance );
			$variableSetInstance = $variableSetClassName::fromArray( $variableSetResource );
			$variableSetInstance->instanceName = $this->instanceQName; // Set a default. It may be overridden by an instance arc
			$variableSetInstance->xbrlTaxonomy = $taxonomy;
			$variableSetInstance->extendedLinkRoleUri = $variableSet['roleUri'];
			$variableSetInstance->linkbase = $variableSet['linkbase'];

			$this->variableSets[ "{$variableSet['roleUri']}#{$variableSet['resourceName']}" ][] =& $variableSetInstance;

			$linkbaseInfo = $taxonomy->getLinkbase( $variableSet['linkbase'] );
			if ( $linkbaseInfo )
			{
				$this->addNamespaces( array( $linkbaseInfo['namespaces'] ) );
			}

			$this->validateLabels( $taxonomy, $variableSetInstance, $taxonomy->getDefaultLanguage() );

			$this->validateParameters( $taxonomy, $contextParameters, $variableSetInstance );

			// Find all variables related to this variable set
			$instanceArcs = $taxonomy->getGenericArc( XBRL_Constants::$arcRoleFormulaInstance, $variableSet['roleUri'], $variableSet['resourceName'], $variableSetInstance->path, $variableSetInstance->linkbase );
			foreach ( $instanceArcs as $instanceArc )
			{
				if ( $instanceArc['from'] != $variableSetInstance->label ) continue;
				// Look for the instance resource
				if ( ! isset( $this->instanceQNames[ $instanceArc['label'] ] ) ) continue;
				$variableSetInstance->instanceName = $this->instanceQNames[ $instanceArc['label'] ];
			}

			// Find all variables related to this variable set
			$variableSetArcs = $taxonomy->getGenericArc( XBRL_Constants::$arcRoleVariableSet, $variableSet['roleUri'], $variableSet['resourceName'], $variableSetInstance->path /* , $variableSetInstance->linkbase */ );
			$variableResources = array();

			foreach ( $variableSetArcs as $arcIndex => $variableSetArc )
			{
				if ( $variableSetArc['fromlinkbase'] != $variableSetInstance->linkbase ) continue;
				if ( $variableSetInstance->path != $variableSetArc['frompath'] ) continue;

				$result = $taxonomy->getGenericResource( 'variable', null, function( $roleUri, $linkbase, $variableSetName, $index, $resource ) use( &$variableResources, $variableSetArc )
				{
					// This test is probably redundant because I believe $variableSetName is the same as $variableSetArc['label']
					if ( /* $linkbase == $variableSetArc['tolinkbase'] && */ $resource['path'] == $variableSetArc['topath'] && $variableSetName == $variableSetArc['label'] )
					{
						$resource['name'] = $variableSetArc['name'];
						$resource['linkbase'] = $linkbase;
						$variableResources[ $variableSetName ][] = $resource;
					}

					return true;
				}, $variableSetArc['toRoleUri'], $variableSetArc['to'], $variableSetArc['tolinkbase'] );
			}

			// Process each located variable resource
			foreach ( $variableResources as $variableLabel => $variableResourceSet )
			{
				foreach ( $variableResourceSet as $variableResource )
				{
					// if ( $variableSetInstance->path != $variableResource['path'] )
					// 	continue;

					if ( $variableResource['variableType'] == 'parameter' )
					{
						// Find the parameter with label $variableResource['label']. This becomes
						// the parameter with qname $variableResource['name']
						$resourceQName = new QName( $variableResource['name']['originalPrefix'], $variableResource['name']['namespace'], $variableResource['name']['name'] );
						foreach ( $this->parameterQnames as $qname => $parameter )
						{
							if ( $parameter->label == $variableResource['label'] )
							{
								// BMS 2018-03-23 One test too many
								// if ( $qname == $resourceQName->clarkNotation() )
								{
									$variableSetInstance->parameters[ $resourceQName->clarkNotation() ] = $this->parameterQnames[ $qname ];
								}
								break;
							}
						}

						continue;
					}

					$variableClassName = '\\XBRL\\Formulas\\Resources\\' .
						Formulas::$formulaElements[ $variableResource['variableType'] ]['part'] .
						( isset( Formulas::$formulaElements[ $variableResource['variableType'] ]['className'] )
							? Formulas::$formulaElements[ $variableResource['variableType'] ]['className']
							: ucfirst( $variableResource['variableType'] )
						);

					if ( is_null( $variableClassName ) )
					{
						$this->log->formula_validation( "Variables", "Invalid variable type",
							array(
								'variable type' => $resource['variableType'],
							)
						);
						return false;
					}

					/** @var \XBRL\Formulas\Resources\Variables\Variable $variable */
					$variable = $variableClassName::fromArray( $variableResource );
					$variable->extendedLinkRoleUri = $variableResource['linkRoleUri'];

					// Add labels
					$this->validateLabels( $taxonomy, $variable, $taxonomy->getDefaultLanguage() );

					// Instances
					// Find all instances related to this variable.  The variable-instance
					// arcs are back-to-front as the arcrole name suggests so get all the
					// arcs and find a suitable one if it exists
					$instanceArcs = $taxonomy->getGenericArc( XBRL_Constants::$arcRoleInstanceVariable, $variable->extendedLinkRoleUri, null, $variable->path, null, $variable->linkbase );
					foreach ( $instanceArcs as $instanceArc )
					{
						if ( $instanceArc['to'] != $variable->label ) continue;
						// Look for the arc source among the valid instance qnames
						if ( ! isset( $this->instanceQNames[ $instanceArc['from'] ] ) ) continue;

						$variable->instanceSourceQName = $this->instanceQNames[ $instanceArc['from'] ];
						break;
					}

					if ( is_null( $variable->instanceSourceQName ) )
					{
						$variable->instanceSourceQName = $this->instanceQNames['standard-input-instance'];
					}

					if ( ! $variableSetInstance->AddVariable( $variable ) )
					{
						return false;
					}

					// This is necessary because $variable is used as a reference.
					// Without this subsequent variables replace earlier ones.
					unset( $variable );
				}
			}

			// BMS 2018-01-25 Moved these here so they can be checked when all variables have been created in case there are interdependencies
			foreach ( $variableSetInstance->variablesByQName as $qname => $variable )
			{
				// Time to pull in the filters for fact variables (general variables do not have filters)
				if ( $variable instanceof FactVariable && ! $this->validateFilters( $taxonomy, XBRL_Constants::$arcRoleVariableFilter, $variable, $variableSetInstance ) )
				{
					return false;
				}

				if ( ! $variable->validate( $variableSetInstance, $this->nsMgr ) )
				{
					return false;
				}

			}

			// Pull in any group filters
			// if ( ! $this->validateGroupFilters( $variableSetInstance ) )
			if ( ! $this->validateFilters( $taxonomy, XBRL_Constants::$arcRoleVariableSetFilter, $variableSetInstance, $variableSetInstance ) )
			{
				return false;
			}

			// Check variable scopes for visible variables
			if ( ! $this->validateVariableScopes( $taxonomy, $variableSetInstance ) )
			{
				return false;
			}

			// Now the variables are known validate the formula
			if ( ! $variableSetInstance->validate( null, $this->nsMgr ) )
			{
				return false;
			}

			$variableSetInstance->validateMessages( $taxonomy->getDefaultLanguage() );

			// The variable refs MUST either refer to variables or parameters
			$variableSetRefs = $variableSetInstance->getVariableRefs();

			foreach ( $variableSetRefs as $qname => $variableSetRefQName )
			{
				// Look for a variable with this name
				if ( ! is_null( $variableSetRefQName ) && isset( $variableSetInstance->variablesByQName[ $variableSetRefQName->clarkNotation() ] ) )
				{
					continue;
				}

				if ( ! is_null( $variableSetRefQName ) && isset( $variableSetInstance->parameters[ $variableSetRefQName->clarkNotation() ] ) )
				{
					// Parameters do not contribute the definition of the dependency tree
					unset( $variableSetRefs[ $qname ] );
					continue;
				}

				// BMS 2018-02-27 See note above with the same date about a line commented out
				// Could be a reference to a global parameter.  If so, add the global parameter.
				if ( isset( $this->parameterQnames[ $variableSetRefQName->clarkNotation() ] ) )
				{
					// Parameters do not contribute the definition of the dependency tree
					$variableSetInstance->parameters[ $variableSetRefQName->clarkNotation() ] = $this->parameterQnames[ $variableSetRefQName->clarkNotation() ];
					unset( $variableSetRefs[ $qname ] );
					continue;
				}

				// Could be a reference to scope dependency
				if ( isset( $variableSetInstance->scopeDependencies[ $variableSetRefQName->clarkNotation() ] ) )
				{
					unset( $variableSetRefs[ $qname ] );
					continue;
				}
				// Are variable references that are not not exist as variables or parameters in the variable set
				unset( $variableSetRefs[ $qname ] );
				$this->log->formula_validation( "Variable set", "Variable reference does not not exist as a variable or parameter in the variable set",
					array(
						'reference' => (string)$variableSetRefQName,
						'error' => 'xbrlve:unresolvedDependency'
					)
				);
			}

			// Create a variables dependency tree
			$variableRefs = array();
			foreach ( $variableSetInstance->variablesByQName as $qname => $variable )
			{
				$variableRefs[ $qname ] = array();
				foreach ( $variable->getVariableRefs() as $variableRefQName )
				{
					// If this is not a reference to a variable ignore because non-variable,
					// such as parameters, do not affect the dependency
					if ( isset( $variableSetInstance->variablesByQName[ $variableRefQName->clarkNotation() ] ) )
					{
						$variableRefs[ $qname ][] = $variableRefQName;
					}
				}
			}

			// Create a hierarchy from the remainder.
			$hierarchy = array();
			$roots = array();

			foreach ( $variableRefs as $dependent => $users )
			{
				if ( ! count( $users ) )
				{
					if ( ! isset( $roots[ $dependent ] ) )
					{
						$roots[ $dependent ] = array();
					}

					if ( ! isset( $hierarchy[ $dependent ] ) )
					{
						$hierarchy[ $dependent ] = array();
					}

					continue;
				}

				foreach ( $users as /** @var QName $userQName */ $userQName )
				{
					$user = $userQName->clarkNotation();

					if ( ! isset( $hierarchy[ $user ] ) )
					{
						$roots[ $user ] = array();
					}

					if ( isset( $roots[ $dependent ] ) )
					{
						unset( $roots[ $dependent ] );
					}

					if ( ! isset( $hierarchy[ $dependent ] ) )
					{
						$hierarchy[ $dependent ] = array();
					}

					$hierarchy[ $user ][ $dependent ] =& $hierarchy[ $dependent ];
				}
			}

			// If there are nodes but no roots then there is a cyclic problem
			if ( $hierarchy && ! $roots )
			{
				$links = array();
				foreach ( $variableRefs as $dependent => $users )
				{
					foreach ( $users as /** @var QName $userQName */ $userQName )
					{
						$user = $userQName->clarkNotation();
						$links[] = "{$userQName->clarkNotation()}->$dependent";
					}
				}

				$this->log->formula_validation( "Variables", "There is a cyclic dependency between the variable references",
					array(
						'variables' => implode( ", ", $links ),
						'error' => 'xbrlve:cyclicDependencies',
					)
				);

				return false;
			}

			$variableSetInstance->variableOrderHierarchy = array_intersect_key( $hierarchy, $roots );

			// check existence assertion @test variable dependencies (not including precondition references)

	        // check messages variable dependencies

	        // check preconditions
			if ( ! $this->validatePreconditions( $taxonomy, $variableSetInstance ) )
			{
				// return false;
			}

			unset( $variableSetInstance );
		}

		// Make sure formulas are executed in the correct order if there are scope dependencies
		$scopeDependencies = array();
		foreach ( $this->variableSets as $variableSetInstances )
		{
			foreach ( $variableSetInstances as $variableSetInstance )
			{
				$toVariableSetKey = "{$variableSetInstance->extendedLinkRoleUri}#{$variableSetInstance->label}";

				if ( $variableSetInstance->scopeDependencies )
				{
					foreach ( $variableSetInstance->scopeDependencies as $qname => $scopeDependency )
					{
						$fromVariableSetKey = "{$scopeDependency['fromRoleUri']}#{$scopeDependency['from']}";

						if ( ! isset( $this->variableSets[ $fromVariableSetKey ] ) )
						{
							$this->log->formula_validation( "variable sets", "The scope dependency formula does not exist",
								array(
									'from formula' => $scopeDependency['from'],
									'to formula' => '$variableSetInstance->label',
									'error' => 'xbrlve:dependentFormulaNotFound'
								)
							);
						}

						$scopeDependencyVariableSet = $this->variableSets[ $fromVariableSetKey ];

						if ( ! ( ( $variableSetInstance instanceof Formula && $scopeDependencyVariableSet[0] instanceof Formula ) ||
								 ( get_class( $variableSetInstance ) == get_class( $scopeDependencyVariableSet[0] ) )
							   )
						)
						{
							$this->log->formula_validation( "variable sets", "The variable set type of the source and target must be the same (formula or one of the assertion type)",
								array(
									'from formula' => $scopeDependency['from'],
									'to formula' => '$variableSetInstance->label',
									'error' => 'xbrlvarscopee:conflictingVariableSet types'
								)
							);
						}

						if ( $variableSetInstance->aspectModel != $scopeDependencyVariableSet[0]->aspectModel )
						{
							$this->log->formula_validation( "variable sets", "The aspect models of the formulas linked by a scope dependency are different",
								array(
									'from formula' => $scopeDependency['from'],
									'to formula' => $variableSetInstance->label,
									'error' => 'xbrlvarscopee:conflictingAspectModels'
								)
							);
						}

						if ( $variableSetInstance->instanceName != $scopeDependencyVariableSet[0]->instanceName )
						{
							$this->log->formula_validation( "variable sets", "The instancs of the scope source and target must be the same",
								array(
									'from formula' => $scopeDependency['from'],
									'to formula' => $variableSetInstance->label,
									'error' => 'xbrlvarscopee:differentInstances'
								)
							);
						}

						$scopeDependencies[ $toVariableSetKey ][] = $fromVariableSetKey;
					}
				}
				else
				{
					// Just add the variable set
					$scopeDependencies[ $toVariableSetKey ] = array();
				}
			}
		}

		// Create a hierarchy of the formulas.
		$hierarchy = array();
		$roots = array();

		foreach ( $scopeDependencies as $dependent => $users )
		{
			if ( ! count( $users ) )
			{
				if ( ! isset( $roots[ $dependent ] ) )
				{
					$roots[ $dependent ] = array();
				}

				if ( ! isset( $hierarchy[ $dependent ] ) )
				{
					$hierarchy[ $dependent ] = array();
				}

				continue;
			}

			foreach ( $users as $user )
			{
				// $user = $userQName->clarkNotation();

				if ( ! isset( $hierarchy[ $user ] ) )
				{
					$roots[ $user ] = array();
				}

				if ( isset( $roots[ $dependent ] ) )
				{
					unset( $roots[ $dependent ] );
				}

				if ( ! isset( $hierarchy[ $dependent ] ) )
				{
					$hierarchy[ $dependent ] = array();
				}

				$hierarchy[ $user ][ $dependent ] =& $hierarchy[ $dependent ];
			}
		}

		// If there are nodes but no roots then there is a cyclic problem
		if ( $hierarchy && ! $roots )
		{
			$links = array();
			foreach ( $variableRefs as $dependent => $users )
			{
				foreach ( $users as /** @var QName $userQName */ $userQName )
				{
					$user = $userQName->clarkNotation();
					$links[] = "{$userQName->clarkNotation()}->$dependent";
				}
			}

			$this->log->formula_validation( "Variables", "There is a cyclic dependency between the formula scope variable references",
				array(
					'variables' => implode( ", ", $links ),
					'error' => 'xbrlve:cyclicDependencies',
				)
			);

			return false;
		}

		$orderedVariables = array();
		$flatten = function( $hierarchy, $parent = null ) use ( &$flatten, &$orderedVariables )
		{
			// $results = array();
			$parents[] = $parent;
			foreach ( $hierarchy as $variable => $dependents )
			{
				// If the variable already exists, remove and re-add so it is appended (moved down the list)
				if ( isset( $orderedVariables[ $variable ] ) )
				{
					$parents = array_merge( $parents, $orderedVariables[ $variable ] );
					unset( $orderedVariables[ $variable ] );
				}
				$orderedVariables[ $variable ] = $parents;
				if ( ! count( $dependents ) ) continue;
				$flatten( $dependents, $variable );
			}
			// return $results;
		};

		$flatten( array_intersect_key( $hierarchy, $roots ) );

		unset( $variableSetInstance );

		// foreach ( $this->variableSets as $variableSetInstances )
		foreach ( $orderedVariables as $formulaQName => $x )
		{
			if ( ! isset( $this->variableSets[ $formulaQName ] ) )
			{
				$this->log->formula_validation( "variables sets", "The dependent formula does not exist",
					array(
						'formula' => $variableSetInstance->label,
						'error' => 'xbrlve:missingFormula'
					)
				);
			}

			$variableSetInstances = $this->variableSets[ $formulaQName ];

			foreach ( $variableSetInstances as $variableSetInstance )
			{
		        // check for variable sets referencing fact or general variables
		        if ( $variableSetInstance->scopeDependencies )
		        {
		        	// Access the variable set containing the scope variable
		        	foreach ( $variableSetInstance->scopeDependencies as $scopeVariableQName => $scopeDependency )
		        	{
						$fromVariableSetKey = "{$scopeDependency['fromRoleUri']}#{$scopeDependency['from']}";
						$scopeVariableSetInstances = $this->variableSets[ $fromVariableSetKey ];

						// Allow for many
						foreach ( $scopeVariableSetInstances as $scopeVariableSetInstance )
						{
							// Copy the evaluation result(s) and the variable binding(s)to this instance
							if ( $variableSetInstance instanceof Formula )
							{
								// Begin by removing any ScopeVariable variables.  These were added to get by the variable set validation.
								foreach ( $variableSetInstance->variablesByQName as $variableQName => $variable )
								{
									if ( ! $variable instanceof ScopeVariable || ! is_null( $variable->binding ) ) continue;
									unset( $variableSetInstance->variablesByQName[ $variableQName ] );
									// Also remove from the variable order list
									unset( $variableSetInstance->variableOrderHierarchy[ $variableQName ] );
								}

								// Now create a variable for the scope variable fact
								$variable = new ScopeVariable();
								$variable->label = $scopeVariableQName;
								$variable->extendedLinkRoleUri = $scopeVariableSetInstance->extendedLinkRoleUri;
								$variable->name = $scopeDependency['name'];
								// Add the variable
								$variableSetInstance->variablesByQName[ $scopeVariableQName ] = $variable;
								// add a reference to the variable to the beginning of the list of
								// order variables so it is processed before any others
								$variableSetInstance->variableOrderHierarchy = array_reverse( $variableSetInstance->variableOrderHierarchy, true );
								$variableSetInstance->variableOrderHierarchy[ $scopeVariableQName ] = array();
								$variableSetInstance->variableOrderHierarchy = array_reverse( $variableSetInstance->variableOrderHierarchy, true );

								// Create a binding for each result
								if ( $variableSetInstance->evaluationResults )
								{
									$variableSetInstance->evaluationResults = array_merge( $variableSetInstance->evaluationResults, $scopeVariableSetInstance->evaluationResults );
								}
								else
								{
									$variableSetInstance->evaluationResults = $scopeVariableSetInstance->evaluationResults;
								}

								$binding = new ScopeVariableBinding( $scopeVariableSetInstance->xbrlInstance, $variable );

								// Create an iterator from the facts
								if ( $scopeVariableSetInstance->evaluationResults )
								{
									// Only take evaluation results generated by the source variable set
									$items = array_filter( $variableSetInstance->evaluationResults,
										function( $evaluationResult ) use( $scopeDependency )
										{
											return $evaluationResult['variableSet'] == $scopeDependency['from'];
										}
									);
									$facts = DocumentOrderNodeIterator::fromItemset( $items );
									$binding->facts = $facts;
								}

								$variable->binding = $binding;
				        		// $variableSetInstance->factVariableBindings[ $variableQName ] = $binding;
				        	}
				        	else
				        	{
				        		// TODO
				        	}
						}
		        	}
		        }

				// Evaluate the variable set
				if ( ! $this->evaluate( $variableSetInstance ) )
				{
					return false;
				}
			}
		}

		if ( $this->formulaFactsContainer )
		{
			$document = $this->formulaFactsContainer->generateInstanceDocument( $this->instances[ $this->instanceQName->clarkNotation() ], $this->nsMgr );
		}

		return true;
	}
1204220
private function evaluate( $variableSet )
	{
		if ( ! $this->canEvaluate ) return;
		if ( isset( $variableSet->evaluated ) ) return true;

		// Process the variables in hierarchy order
		// $variableSet->parameters =& $this->parameterQnames;
		$variableSet->nsMgr = $this->nsMgr;
		$variableSet->xbrlInstance = $this->instances[ $this->instanceQName->clarkNotation() ];
		if ( $variableSet->evaluate() )
		{
			// If the variable set is a formula then add a facts container
			if ( $variableSet instanceof Formula )
			{
				if ( is_null( $this->formulaFactsContainer ) ) $this->formulaFactsContainer = new GeneratedFacts();
				$variableSet->factsContainer = $this->formulaFactsContainer;
			}

			$variableSet->ProcessEvaluationResult( $this->log );

			// If the variable set is a formula recover the facts container
			if ( $variableSet instanceof Formula )
			{
				// This is probably redundant because the container instance will be passed to the variable set by reference
				$this->formulaFactsContainer = $variableSet->factsContainer;
			}
		}

		$variableSet->evaluated = true;

		return true;
	}
319353
private function containsWrongRefs(Resource $res, string $namespace): bool {
        foreach ($res->propertyUris() as $prop) {
            if ($prop == RC::idProp()) {
                continue;
            }
            foreach ($res->allResources($prop) as $val) {
                $valUri   = $val->getUri();
                $inNmsp   = strpos($valUri, $namespace) === 0;
                $isAcdhId = $this->fedora->isAcdhId($valUri);
                if ($val->isBNode() || ($inNmsp && !$isAcdhId)) {
                    return true;
                }
            }
        }
        return false;
    }
669963
public static function GetNamespaceUriForPrefix( $context, $prefix, $nav )
	{
		$ns  = "";
		if ( $prefix instanceof  Undefined || $prefix . "" == "" )
		{
			$ns = $nav->getNamespaceURI();
		}
		else
		{
			/**
			 * @var XmlNamespaceManager $nsmgr
			 */
		    $nsmgr = new XmlNamespaceManager();
		    ExtFuncs::ScanLocalNamespaces( $nsmgr, $nav->CloneInstance(), false );
		    $ns = $nsmgr->lookupNamespace( $prefix . "" );
		}
		return is_null( $ns )
			? Undefined::getValue()
			: new AnyUriValue( $ns );
	}
336560
public function validate( $variableSet, $nsMgr )
	{
		if ( $this->qnameExpressions )
		{
			foreach ( $this->qnameExpressions as $qnameExpression )
			{
				try
				{
					$xpath2Expression = XPath2Expression::Compile( $qnameExpression, $nsMgr );
					if ( parent::checkForCoverXFIFunctionUse( $qnameExpression, $xpath2Expression ) )
					{
						return false;
					}
					$this->qnameXPath2Expressions[] = $xpath2Expression;
				}
				catch ( \Exception $ex )
				{
					\XBRL_Log::getInstance()->formula_validation( "Concept name filter", "Failed to compile qname expression",
						array(
							'qname expression' => $qnameExpression,
							'error' => $ex instanceof XPath2Exception ? $ex->ErrorCode : get_class( $ex ),
							'reason' => $ex->getMessage()
						)
					);
					return false;
				}
			}
		}

		return true;
	}
900851
protected function validateNamespace($namespace)
    {
        switch ($namespace) {
            case 'ns:DNS':
                return Uuid::NAMESPACE_DNS;
                break;
            case 'ns:URL':
                return Uuid::NAMESPACE_URL;
                break;
            case 'ns:OID':
                return Uuid::NAMESPACE_OID;
                break;
            case 'ns:X500':
                return Uuid::NAMESPACE_X500;
                break;
        }

        if (Uuid::isValid($namespace)) {
            return $namespace;
        }

        throw new Exception(
            'Invalid namespace. '
            . 'May be either a UUID in string representation or an identifier '
            . 'for internally pre-defined namespace UUIDs (currently known '
            . 'are "ns:DNS", "ns:URL", "ns:OID", and "ns:X500").'
        );
    }
61019
final public function set($varname, $value = NULL, $namespace = 'default')
    {
        //stores a value to a varname in a namespace of this session
        $session = $this;

        if (!isset($namespace) || empty($namespace)) {
            //@TODO Throw an exception, we need a name or use the default;
            throw new Exception("Cannot set new Session variable to unknown '{$namespace}' namespace");
            return false;
        }


        //If we don't have a registry to that namespace;
        if (!isset($session->registry[$namespace])) {
            //Create it;
            $registry = new Registry($namespace);
            $session->registry[$namespace] = $registry;
        }

        //echo $namespace;
        //@TODO, check if the regitry is not locked before adding
        if (!$session->isLocked($namespace)) {
            $registry = $session->getNamespace($namespace);
            $registry->set($varname, $value);
        }
        //If auth is locked

        return $session;
    }
305591
public static function ScanLocalNamespaces( $nsmgr, $node, $recursive )
	{
		if ( $node->getNodeType() != XPathNodeType::Element )
		{
			if ( $recursive )
			{
				/**
				 * @var XPathNavigator $parent
				 */
				$parent = $node->CloneInstance();
				if ( $parent->MoveToParent() )
				{
					ExtFuncs::ScanLocalNamespaces( $nsmgr, $parent, $recursive );
					return;
				}
			}
		}

		$defaultNS = false;
		$prefix = $node->getPrefix();
		$ns = $node->getNamespaceURI();
		$nsmgr->PushScope();
		if ( $node->MoveToFirstNamespace( XPathNamespaceScope::All ) )
		{
			do
			{
				$nsmgr->addNamespace( $node->getName(), $node->getValue() );
				if ( $node->getName() == $prefix )
				{
					$defaultNS = true;
				}
			}
			while ( $node->MoveToNextNamespace( XPathNamespaceScope::All ) );
		}
		if ( ! $defaultNS && $ns != "" )
		{
			$nsmgr->AddNamespace( $prefix, $ns );
		}

		return;

	}
442071
public function partitionFacts( $variableSet )
	{
		if ( ! $this->var->bindAsSequence ) return;

		$groups = array();

		// This is a bit belt-and-braces but just to be sure
		if ( $this->facts instanceof XPath2NodeIterator )
		{
			$groups[] = $this->facts->CloneInstance();
		}
		else if ( is_array( $this->facts ) )
		{
			$groups[] = DocumentOrderNodeIterator::fromItemset( $this->facts, true );
		}
		else
		{
			$groups[] = DocumentOrderNodeIterator::fromItemset( array( $this->facts ) );
		}

		$this->facts = DocumentOrderNodeIterator::fromItemset( $groups );
	}
357015
public function toQuery( $variableSet, $factVariableBinding )
	{
		$result = parent::toQuery( $variableSet, $factVariableBinding );
		$query = "(" . implode( " or ", $result ) . ")";
		if ( $this->complement )
		{
			$query = "not{$query}";
		}
		return $query;
	}
272217
public function validate( $variableSet, $nsMgr )
	{
		if ( isset( $this->test ) && ! empty( $this->test ) )
		{
			try
			{
				$expression = XPath2Expression::Compile( $this->test, $nsMgr );
				$this->testXPath2Expression = $expression;
			}
			catch ( Exception $ex )
			{
				\XBRL_Log::getInstance()->valueassertion_validation( "Value assertion", "Failed to compile test expression",
					array(
						'test expression' => $this->test,
						'error' => $ex instanceof XPath2Exception ? $ex->ErrorCode : get_class( $ex ),
						'reason' => $ex->getMessage()
					)
				);

				return false;
			}

		}

		return true;
	}
1134516
public function validate( $variableSet, $nsMgr )
	{
		$testExpression = function( $expressionName, $expression )
		{
			$xpath2Expression = null;

			try
			{
				$xpath2Expression = XPath2Expression::Compile( $expression, $nsMgr );
				if ( parent::checkForCoverXFIFunctionUse( $this->qnameExpression, $xpath2Expression ) )
				{
					return false;
				}
			}
			catch ( Exception $ex )
			{
				\XBRL_Log::getInstance()->formula_validation( "Concept relation filter", "Failed to compile qname expression",
					array(
						'expression name' => $expressionName,
						'qname expression' => $expression,
						'error' => $ex instanceof XPath2Exception ? $ex->ErrorCode : get_class( $ex ),
						'reason' => $ex->getMessage()
					)
				);

				return false;
			}

			return $xpath2Expression;
		};

		foreach ( $this->expressionsList as $expressionName => $details )
		{
			if ( ! $details['expression'] ) continue;
			$xpath2Expression = $testExpression( $expressionName, $details['expression'] );
			if ( ! $xpath2Expression ) continue;
			$this->${$details['expression']} = $xpath2Expression;
		}

		return true;
	}
1285917
public function getValue( $variableSet, $evaluationResult, $log )
	{
		// This is an error
		if ( ! isset( $variableSet->context ) ) return array();

		// Get context for this rule's source
		$sourceContext = $variableSet->getComponentForPath( $this->source, $variableSet->explicitDimensionsComponentPath, 'explicitMember', $evaluationResult, $this->aspectDimension, $log, $contextRef );
		$sourceContext = Dimension::contextToIndex( $sourceContext, true, $variableSet, $this->aspectDimension );

		// Get original context
		$context = $variableSet->context;

		if ( ! $variableSet->xbrlInstance->getNamespaceForPrefix( $this->dimension['originalPrefix'] ) )
		{
			$this->dimension['originalPrefix'] = $variableSet->xbrlInstance->getPrefixForNamespace( $this->dimension['namespace'] );
		}
		$dimensionQName = "{$this->dimension['originalPrefix']}:{$this->dimension['name']}";

		if ( $this->omit )
		{
			// Omit always applies to the default context
			unset( $context[ $dimensionQName ] );
		}
		else if ( $this->member )
		{
			// If a member is defined then the dimension/member is being added or updated
			if ( isset( $this->member['qname'] ) )
			{
				// Make sure the prefix is compatible with the instance document
				$qname = qname( $this->member['qname'], $variableSet->nsMgr->getNamespaces() );
				if ( ! $variableSet->xbrlInstance->getNamespaceForPrefix( $qname->prefix ) )
				{
					$qname->prefix = $variableSet->xbrlInstance->getPrefixForNamespace( $qname->namespaceURI );
				}
				$name = "{$qname->prefix}:{$qname->localName}";
				$context[ $dimensionQName ] = array( $name => $name );
			}
			else if ( $this->member['qnameExpression'] )
			{
				$vars = $evaluationResult['vars'];
				$result = $this->evaluateXPath( $variableSet, "{$this->member['qnameExpression']} cast as xs:string", $vars );

				$qname = qname( $result->getValue(), $variableSet->nsMgr->getNamespaces() );
				if ( ! $variableSet->xbrlInstance->getNamespaceForPrefix( $qname->prefix ) )
				{
					$qname->prefix = $variableSet->xbrlInstance->getPrefixForNamespace( $qname->namespaceURI );
				}
				$name = "{$qname->prefix}:{$qname->localName}";

				$context[ $dimensionQName ] = array( $name => $name );
			}
		}
		else if ( isset( $sourceContext[ $dimensionQName ] ) )
		{
			// Add any members from the source
			$context[ $dimensionQName ] = $sourceContext[ $dimensionQName ];
		}
		else
		{
			$log->formula_validation( "Explicit dimension aspect rule", "A dimension is being added but there are no members",
				array(
					'dimension' => $dimensionQName,
					'error' => 'xbrlfe:missingSAVForExplicitDimensionRule'
				)
			);
		}

		return $context;
	}