Skip to content

Resolver relies on getPrimaryResourceIdentifier() being unique for each schema #11

Open

Description

@JanTvrdik

Resolver relies e.g. in registerSchema on getPrimaryResourceIdentifier being unique for each schema however when Validator::validate is called without the third argument, the getPrimaryResourceIdentifier() returns empty string every time.

My guess is that we must either make the 3rd parameter of Validator::validate required or generate primary resource identifier differently (maybe random?) when empty Uri is passed.

Activity

  1. JanTvrdik commented on Apr 10, 2016

    @JanTvrdik
    ContributorAuthor

    Maybe we can just put sth like this to Validator::validate

    if ($schemaUri === '') {
        $schemaUri = '/schema/' . md5(spl_object_hash($schema));
    }
  2. stefk commented on Apr 10, 2016

    @stefk
    Owner

    Unless a $ref pointing to another document is encountered, we never leave the current schema, so it's expected to get always the same identifier (here the empty string) and the same schema from the cache. If an external $ref is met, the identifier returned by getPrimaryResourceIdentifier() must be different. Isn't this the case? Can you provide a schema illustrating the issue?

  3. JanTvrdik commented on Apr 10, 2016

    @JanTvrdik
    ContributorAuthor

    I guess you're right. The registerSchema behavior is wrong (relying on uniqueness of primary resource identifier even when it's empty string), but resolve does never actually read those schemas with empty identifier so it never actually breaks anything.

    Therefore the best solution would likely be to just ignore empty identifiers in registerSchema as caching them is both wrong and pointless.

    $id = $uri->getPrimaryResourceIdentifier();
    if ($id !== '' && !isset($this->schemas[$id])) {
        $this->schemas[$id] = $schema;
    }
  4. added a commit that references this issue on Apr 10, 2016
    a8c6109
  5. stefk commented on Apr 10, 2016

    @stefk
    Owner

    The registerSchema behavior is wrong (relying on uniqueness of primary resource identifier even when it's empty string)

    I don't agree. The empty string is also a valid identifier. It's unique and will always denote the document from which we started, in case no path/url was provided.

    resolve does never actually read those schemas

    It will when a solution will be provided for #6.

  6. JanTvrdik commented on Apr 10, 2016

    @JanTvrdik
    ContributorAuthor

    The collision with #6 is a good observation.

    It's unique and will always denote the document from which we started

    When you call validate with schema A without URL and then validate with schema B without URL, references such as {"$ref": "#"} in schema B would resolve against schema A.

  7. stefk commented on Apr 10, 2016

    @stefk
    Owner

    You're right, and actually even for #6, the schema should probably be taken from $stack and not $schemas, so we can safely exclude the empty string as you suggested.

  8. JanTvrdik commented on Apr 10, 2016

    @JanTvrdik
    ContributorAuthor

    What about implementing check in registerSchema to prevent accidental overrides

    public function registerSchema(stdClass $schema, Uri $uri)
    {
        $identifier = $uri->getPrimaryResourceIdentifier();
    
        if ($identifier === '') {
            // ignore        
        } elseif (!isset($this->schemas[$identifier])) {
            $this->schemas[$identifier] = $schema;
        } elseif ($this->schemas[$identifier] != $schema) { // intentionally ==, instead of ===
            throw new \LogicException('Different schema is already registered with given URI.');
        }
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions