Validate any requires element arcs

@param XBRL_Types $types
@return boolean
185997
private function validateRequiresElementArcs( XBRL_Types &$types )
	{

		$arcs = $this->getInstanceTaxonomy()->getRequireElementsList();
		if ( ! $arcs ) return true;

		foreach ( $arcs as $from => $targets )
		{
			// echo "$from";

			// If the $from exists then the $to exists
			$parts = parse_url( $from );
			if ( ! isset( $parts['path'] ) || ! isset( $parts['fragment'] ) ) continue;

			$fromTaxonomy = $this->getInstanceTaxonomy()->getTaxonomyForXSD( $parts['path'] );
			if ( ! $fromTaxonomy )
			{
				$this->log()->instance_validation( "5.2.6.2.4", "The taxonomy of the source does not exist in the DTS",
					array(
						'from' => $from,
					)
				);
				continue;
			}

			$fromElement = $fromTaxonomy->getElementById( $parts['fragment'] );
			if ( ! $fromElement )
			{
				$this->log()->instance_validation( "5.2.6.2.4", "The concept of the source does not exist in the DTS",
					array(
						'from' => $from,
					)
				);
				continue;
			}

			// Look for the fact in the instance document
			$fromFact = $this->getElement( $fromElement['id'] );

			// If the $from does not exist there is noting else to do
			if ( ! $fromFact ) continue;

			foreach ( $targets as $target => $details )
			{
				// echo " -> $target\n";

				$parts = parse_url( $target );
				if ( ! isset( $parts['path'] ) || ! isset( $parts['fragment'] ) ) continue;

				$toTaxonomy = $this->getInstanceTaxonomy()->getTaxonomyForXSD( $parts['path'] );
				if ( ! $toTaxonomy )
				{
					$this->log()->instance_validation( "5.2.6.2.4", "The taxonomy of the target does not exist in the DTS",
						array(
							'from' => $from,
						)
					);
					continue;
				}

				$toElement = $toTaxonomy->getElementById( $parts['fragment'] );
				if ( ! $toElement )
				{
					$this->log()->instance_validation( "5.2.6.2.4", "The concept of the target does not exist in the DTS",
						array(
							'to' => $to,
						)
					);
					continue;
				}

				// Look for the fact in the instance document
				$toFact = $this->getElement( $toElement['id'] );

				// If the $from does not exist there is noting else to do
				if ( $toFact ) continue;

				// The $from exist but the $to does not so report the error.
				$this->log()->instance_validation( "5.2.6.2.4", "The required source fact exists but the target one does not exist.",
					array(
						'from' => $from,
						'to' => $target,
					)
				);

			}
		}
	}
1261933
private function validateFacts( $elements, $parent, &$types, &$prefixes )
	{
		$instanceTaxonomy = $this->getInstanceTaxonomy();
		$primaryItems = $instanceTaxonomy->getDefinitionPrimaryItems( false );

		foreach ( $elements as $factKey => $fact )
		{
			$drsHypercubes = false;

			foreach ( $fact as $entryKey => $entry )
			{
				// This function will return an empty array if there is no primary item or if the primary item is not
				// associated with any hypercubes.  Otherwise it will contain summary information about the dimensional
				// validation of the primary item.  If the dimensional validation fails it means the fact is not
				// associated with any hypercubes valid for the fact context.
				$primaryItem = isset( $primaryItems[ $entry['label'] ] ) ? $primaryItems[ $entry['label'] ] : false;
				if ( $primaryItem && ! $drsHypercubes )
				{
					$drsHypercubes = $this->getInstanceTaxonomy()->getPrimaryItemDRS( $primaryItem );
				}

				$dimensionalValidation = $this->validateElementEntry( $entry, $factKey, $parent, $types, $prefixes, $primaryItem, $drsHypercubes );
			}
		}
	}
672880
public function haveAllRequiredAttributes( array $attributes ) : bool
   {

      foreach ( $this->_attributes as $attribute )
      {
         if ( ! $attribute->isRequired() )
         {
            continue;
         }
         if ( ! isset( $attributes[ $attribute->getName() ] ) )
         {
            if ( $attribute->hasValueMissedLink() && $attribute->getValueMissedLink()->isValid() )
            {
               continue;
            }
            return false;
         }
      }

      return true;

   }
1123046
protected function hasValidValues(array $values, Type $type): bool
    {
        foreach ($values as $value) {
            if (
                null !== $value
                && Type::BUILTIN_TYPE_INT === $type->getBuiltinType()
                && false === filter_var($value, FILTER_VALIDATE_INT)
            ) {
                return false;
            }
        }

        return true;
    }
732670
private static function required_params_exist( $type, $data ) {

		$required = [ 'name', 'slug' ];

		if ( 'submenu' === $type ) {
			array_push( $required, 'parent' );
		}

		foreach ( $required as $field ) {
			if ( ! isset( $data[ $field ] ) || empty( $data[ $field ] ) ) {
				return false;
			}
		}

		return true;
	}
120569
public static function getValidType($type, $xsdTypesPath = null, $fallback = null)
    {
        return XsdTypes::instance($xsdTypesPath)->isXsd(str_replace('[]', '', $type)) ? $fallback : $type;
    }
1014868
private function validateXLinkArcrole( $linkbase, $value )
	{
		if ( ! XBRL::isValidating() ) return true;

		if ( $value == XBRL_Constants::$arcRoleConceptLabel ) return true;

		return $this->reportXLinkArcTypeError( "3.5.3.9.4", $linkbase, $value );
	}
887529
public function isValid(array $attributes, $rules = 'rules')
    {
        //validator
        $validator = $this->factory->make($attributes, static::${$rules});

        //passes validation
        if (!$validator->fails()) {
            return true;
        }

        //set errors
        $this->errors = $validator->getMessageBag();

        //return
        return false;
    }
1314150
public function setRequiredPropertyTypes(string $property, $types)
    {
        $this->required[$property] = $types;
        $this->requiredTypes[$property] = $types;

        return $this;
    }
531648
public function hasDifferentDynamicType($types)
    {
        $number = 0;
        foreach ($types as $type) {
            if (isset($this->dynamicTypes[$type])) {
                ++$number;
            }
        }

        return 0 == $number;
    }
135094
public function isValid($vals)
    {
        $fields = $this->getFields();
        if (!Arr::iterable($fields)) {
            return true;
        }

        $result = true;

        // validate each field
        foreach ($fields as $k => $field) {
            // check if required
            if ($this->isRequired($field)) {
                if (!array_key_exists($k, $vals)
                        || is_null($vals[$k])
                        || $vals[$k] === ''
                        || $vals[$k] === false
                        || ($field['type'] === 'checkbox' && empty($vals[$k]))
                    ) {
                    $result = false;
                    $this->_messages[$k] = $this->getFieldRequiredMessage($k);
                    continue;
                }
            }

            // check maxlength
            if (array_key_exists('maxlength', $field)) {
                if (strlen($vals[$k]) > $field['maxlength']) {
                    $result = false;
                    $this->_messages[$k] = 'Value too long';
                    continue;
                }
            }

            // after this point, we're only checking values based on type
            if (!array_key_exists($k, $vals)) {
                continue;
            }
            if (!array_key_exists('type', $field)) {
                continue;
            }
 
            // Select
            if ($field['type'] === 'select') {
                if (!array_key_exists($vals[$k], $field['options'])) {
                    $result = false;
                    $this->_messages[$k] = 'Invalid option';
                }
                continue;
            }

            // Email
            if ($field['type'] === 'email') {
                if (!filter_var($vals[$k], FILTER_VALIDATE_EMAIL)) {
                    $result = false;
                    $this->_messages[$k] = 'Invalid email address';
                }
                continue;
            }

            // URL
            if ($field['type'] === 'url') {
                if (!filter_var($vals[$k], FILTER_VALIDATE_URL)) {
                    $result = false;
                    $this->_messages[$k] = 'Invalid URL';
                }
                continue;
            }

            // Color
            // http://www.w3.org/TR/html-markup/input.color.html#input.color.attrs.value
            if ($field['type'] === 'color') {
                if (!preg_match('/^#[0-9a-f]{6}$/i', $vals[$k])) {
                    $result = false;
                    $this->_messages[$k] = 'Invalid color';
                }
                continue;
            }
        }
        return $result;
    }
598297
public static function isTuple( $taxonomy_element, $types = null )
	{
		if ( $types == null ) $types = XBRL_Types::getInstance();

		return isset( $taxonomy_element['substitutionGroup'] ) &&
		$types->resolveToSubstitutionGroup( $taxonomy_element['substitutionGroup'], array( XBRL_Constants::$xbrliTuple ) );
	}
785596
public function validateXDTElements( &$types, $id, $name, $element)
	{
		if ( isset( $element['substitutionGroup'] ) )
		{
			// Dimensional items MUST abstract
			if ( $types->resolveToSubstitutionGroup( $element['substitutionGroup'], array( XBRL_Constants::$xbrldtHypercubeItem ) ) )
			{
				// If $element[substitutionGroup] is not xbrldt:hypercubeItem make sure any missing attributes are available
				$element = $this->getCompleteDescendantElement( $element, $types );

				if ( ! isset( $element['abstract'] ) || ! $element['abstract'] )
				{
					$this->log()->dimension_validation(
						"2.2.1",
						"An element that is in the substitution group of the xbrldt:hypercubeItem element is not abstract.",
						array(
							'name' => $name,
							'schema' => $this->getSchemaLocation(),
							'error' => 'xbrldte:HypercubeElementIsNotAbstractError',
						)
					);
				}
			}
			else if ( $types->resolveToSubstitutionGroup( $element['substitutionGroup'], array( XBRL_Constants::$xbrldtDimensionItem ) ) )
			{
				// If $element[substitutionGroup] is not xbrldt:dimensionItem make sure any missing attributes are available
				$element = $this->getCompleteDescendantElement( $element, $types );

				if ( ! isset( $element['abstract'] ) || ! $element['abstract'] )
				{
					$this->log()->dimension_validation(
						"2.5.1",
						"An element that is in the substitution group of the xbrldt:dimensionalItem element is not abstract.",
						array(
							'name' => $name,
							'schema' => $this->getSchemaLocation(),
							'error' => '',
						)
					);
				}
			}
		}

		// Check the typedDomainRef attribute if one exists
		if ( isset( $element['typedDomainRef'] ) )
		{
			if ( ! $types->resolveToSubstitutionGroup( $element['substitutionGroup'], array( XBRL_Constants::$xbrldtDimensionItem ) ) )
			{
				$this->log()->dimension_validation(
					"2.5.1",
					"An element with a typedDomainRef attribute MUST be in the substitution group xbrldt:dimensionalItem",
					array(
						'name' => $name,
						'schema' => $this->getSchemaLocation(),
						'error' => 'xbrldte:TypedDomainRefError',
					)
				);
			}

			$parts = explode( "#", $element['typedDomainRef'] );
			if ( count( $parts ) != 2 )
			{
				$this->log()->dimension_validation(
					"2.5.2.1.1",
					"The typedDomainRef value is not a valid URI.",
					array(
						'typedDomainRef' => "'{$element['typedDomainRef']}'",
						'schema' => $this->getSchemaLocation(),
						'error' => 'xbrldte:TypedDimensionURIError',
					)
				);
			}
			else
			{
				$taxonomy = $this;

				// If there is a domain in the reference it must be part of the DTS
				if ( ! empty( $parts[0] ) )
				{
					$taxonomy = $this->getTaxonomyForXSD( $parts[0] );

					if ( ! $taxonomy )
					{
						$this->log()->dimension_validation(
							"2.5.2.1.1",
							"The typedDomainRef references a domain that is not part of the DTS",
							array(
								'typedDomainRef' => "'{$element['typedDomainRef']}'",
								'schema' => $this->getSchemaLocation(),
								'error' => 'xbrldte:OutOfDTSSchemaError',
							)
						);
					}
				}

				if ( empty( $parts[1] ) )
				{
					$this->log()->dimension_validation(
						"2.5.2.1.1",
						"The typedDomainRef value does not include a fragment",
						array(
							'typedDomainRef' => "'{$element['typedDomainRef']}'",
							'schema' => $this->getSchemaLocation(),
							'error' => 'xbrldte:TypedDimensionURIError',
						)
					);
				}
				else if ( $taxonomy )
				{
					// Check to see that the fragment is valid
					$typedDomainElement = $taxonomy->getElementById( $parts[1] );

					if ( ! $typedDomainElement )
					{
						// Check to see if this is missing or to a type
						$type = $types->getTypeById( $parts[1], $this->getPrefix() );

						if ( $type )
						{
							$this->log()->dimension_validation(
								"2.5.2.1.1",
								"The typedDomainRef references a type defintition",
								array(
									'typedDomainRef' => "'{$element['typedDomainRef']}'",
									'schema' => $this->getSchemaLocation(),
									'error' => 'xbrldte:TypedDimensionError',
								)
							);
						}
						else
						{
							$this->log()->dimension_validation(
								"2.5.2.1.1",
								"The typedDomainRef references a domain that is not part of the DTS",
								array(
									'typedDomainRef' => "'{$element['typedDomainRef']}'",
									'schema' => $this->getSchemaLocation(),
									'error' => 'xbrldte:OutOfDTSSchemaError',
								)
							);
						}

					} else if ( isset( $typedDomainElement['abstract'] ) && $typedDomainElement['abstract'] )
					{
						$this->log()->dimension_validation(
							"2.5.2.1.1",
							"The typedDomainRef reference is to an abstract element",
							array(
								'typedDomainRef' => "'{$element['typedDomainRef']}'",
								'schema' => $this->getSchemaLocation(),
								'error' => 'xbrldte:TypedDimensionError',
							)
						);
					}
				}

			}
		}

	}
968314
public function gatherElementsFromType( $type )
	{
		if ( is_string( $type ) )
		{
			$type = $this->getType( $type );
		}

		if ( ! is_array( $type ) ) return false;

		$elements = array();

		foreach ( array( 'elements', 'sequence', 'choice', 'group' ) as $typeComponent )
		{
			if ( ! isset( $type[ $typeComponent ] ) )
			{
				continue;
			}

			foreach ( $type[ $typeComponent ] as $id => $element )
			{
				if ( $id == 'restrictionType')
				{
					continue;
				}

				if ( $id == 'elements' )
				{
					$elements += $element;
					continue;
				}

				$result = $this->gatherElementsFromType( $element );
				if ( ! $result )
				{
					$elements[ "{$element['prefix']}:{$element['name']}" ] = $element;
				}

				$elements += $result;
			}

		}

		return $elements;
	}
15727
public function mergeTypes( $types )
	{
		$this->types			= array_merge( $this->types, $types['types'] );
		$this->attributes		= array_merge( $this->attributes, $types['attributes'] );
		$this->attributeGroups	= array_merge( $this->attributeGroups, $types['attributeGroups'] );
		$this->elements			= array_merge( $this->elements, $types['elements'] );
		$this->processedSchemas	= array_merge( $this->processedSchemas, $types['processedSchemas'] );
		if ( isset( $types['typeIds'] ) )
		{
			$this->typeIds		= array_merge( $this->typeIds, $types['typeIds'] );
		}

		// Prevent re-loading base types
		$this->baseTypesLoaded = true;

		return true;
	}
776104
private static function xequalElementType( $types, $localName, $prefix )
	{
		$element = $types->getElement( $localName, $prefix );
		if ( ! $element || ! isset( $element['types'] ) || ! count( $element['types'] ) ) return XBRL_Equality::$EQUALITY_TYPE_STRING;

		return XBRL_Equality::xEqualComparisonType( array( 'type' => $element['types'][0] ), $types);
	}
829664
private function validateGeneralSpecial( XBRL_Types &$types )
	{
		$roles =& $this->getInstanceTaxonomy()->getGeneralSpecialRoleRefs();

		/* ---------------------------------------------------------
		 * Look for directed cycles
		 * ---------------------------------------------------------
		 */

		/**
		 * Examine the arcs recursively to look for directed cycles.
		 * If there are directed cyles then the $alias of an arc will appear in the list of $parents
		 *
		 * @var function $detectDirected
		 * @param string $source
		 * @param array $parents
		 * @return bool
		 */
		$detectDirected = function( $roleKey, $source, $parents = array() ) use( &$detectDirected, &$roles )
		{
			foreach ( $roles[ $roleKey ]['rules'][ $source ] as $target => $details )
			{
				if ( $target == $source || in_array( $target, $parents ) )
				{
					XBRL_Log::getInstance()->instance_validation( "5.2.6.2.1", "The general special arcs contain directed cycles",
						array(
							'path' => implode( '->', array_merge( $parents, array( $target ) ) ),
						)
					);
					return true;
				}

				if ( ! isset( $roles[ $roleKey ]['rules'][ $target ] ) ) continue;

				if ( $detectDirected( $roleKey, $target, array_merge( $parents, array( $source ) ) ) ) return true;
			}

			return false;
		};

		foreach ( $roles as $roleKey => $role )
		{
			if ( ! isset( $role['rules'] ) ) continue;

			foreach ( $role['rules'] as $from => $items )
			{
				if ( $detectDirected( $roleKey, $from ) )
				{
					break;
				}
			}
		}

	}