GithubHelp home page GithubHelp logo

prismicio-community / php-kit Goto Github PK

View Code? Open in Web Editor NEW
106.0 23.0 81.0 1.52 MB

Community maintained development kit for Prismic and the PHP language

Home Page: https://prismic.io

License: Other

PHP 100.00%
php

php-kit's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

php-kit's Issues

Api::get is slow

Even when the API data is cached, Api::get is slow. It's taking around 200ms for me at the moment. This seems like madness given that no actual requests are being made.

I narrowed it down and a significant chunk of this time is spent on the defaultHttpAdapter() function.

I believe it is slower since #69 was merged. I wonder if this could be mitigated if using a particular HTTP adapter rather than the default one? Perhaps you can weigh in, @robinvdvleuten?

Symfony 3.2 compatibility

Hi, the version constraint on the symfony/event-dispatcher component isn't working with Symfony 3.2.

Here's the composer output:

composer require prismic/php-sdk
Using version ^3.1 for prismic/php-sdk
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Installation request for prismic/php-sdk ^3.1 -> satisfiable by prismic/php-sdk[3.1.0].
    - Conclusion: remove symfony/symfony v3.2.1
    - Conclusion: don't install symfony/symfony v3.2.1
    - prismic/php-sdk 3.1.0 requires symfony/event-dispatcher ~3.1.4 -> satisfiable by symfony/event-dispatcher[v3.1.4, v3.1.5, v3.1.6, v3.1.7, v3.1.8].
    - don't install symfony/event-dispatcher v3.1.4|don't install symfony/symfony v3.2.1
    - don't install symfony/event-dispatcher v3.1.5|don't install symfony/symfony v3.2.1
    - don't install symfony/event-dispatcher v3.1.6|don't install symfony/symfony v3.2.1
    - don't install symfony/event-dispatcher v3.1.7|don't install symfony/symfony v3.2.1
    - don't install symfony/event-dispatcher v3.1.8|don't install symfony/symfony v3.2.1
    - Installation request for symfony/symfony (locked at v3.2.1) -> satisfiable by symfony/symfony[v3.2.1].


Installation failed, reverting ./composer.json to its original content.

Is there anything that has to require the 3.1 version of the component? Could I submit a PR that changes it to a ^3.1 constraint? Symfony probably won't break anything until 4.x, see here: http://symfony.com/doc/current/contributing/code/bc.html

Better caching

Every time the ref changes, all the cached queries become invalid. This is far from ideal, especially for large sites with large numbers of unique queries. (For one of our sites, Edmonton Tourism, we get around this by prefetching every single document, and caching "fake" result sets for queries for each separate document, each group of documents by mask, each document by category if they're categorized, and so on. This is really wasteful but the site is far, far faster because of it.)

It would be very nice if documents could be cached separately and reused without refetching if they have not been changed (even if the ref has changed). For example if document A has been updated but B, C and D haven't, and they were all previously fetched and cached, it would be nice if only document A had to be fetched again rather than the cached copies of B, C and D being deemed invalid since they were fetched with an older ref.

Is this in the realm of possibility?

I can imagine how to separately cache documents -- that'd be easy enough.

If the API then allowed for only the IDs of matching documents to be returned for a given query, along with the ref at which they were last updated, these two could make up the cache keys for each document. The SDK could then look in the cache for those it still has -- these are still fresh and should not be modified. It then makes a second request to Prismic for all the other results, receives them and populates the cache.

Does such a "last updated ref" exist, per document, and can it be retrieved?

This could be overridden of course to simply get all full results, for instance if the developer knows the cache is empty or close to empty at this point.

It'd then be possible to precache all documents, without literally grabbing all data for all documents each time we get a webhook. (Webhooks don't include the specific IDs of documents which have changed -- it'd be nice if they had this too.)

I have a lot more thoughts on this, but this should be enough to get a discussion started.

LinkResolver class usage

How is the LinkResolver abstract class supposed to be used? I have tried passing a closure as $linkResolver to asHtml on some structured text and this works, but for more nicely structured code I would have thought it'd make sense to write my own resolver class. I've tried this:

class Resolver extends \Prismic\LinkResolver {
    public function resolve($documentLink) {
        return '/' . $documentLink->getType() . '/' . $documentLink->getSlug();
    }
}
...
$resolver = new Resolver;
var_dump($results[0]->get('content-page.post')->asHtml($resolver);

and I'm getting an error on StructuredText.php line 175 saying "Function name must be a string", where it tries to do $url = $linkResolver ? $linkResolver($span->getLink()) : '';

Invalid argument supplied for foreach() in Prismic/WithFragments.php:642

$api = Api::get("https://abc123.prismic.io/api/v2");
$response = $api->query(Predicates::at('document.tags', ['foo']));

Results in:

Warning: Invalid argument supplied for foreach()  in /abc123/vendor/prismic/php-sdk/src/Prismic/WithFragments.php on line 642

This occurs when I add a Key Text field to a repeatable type. When I pause execution I see the following JSON from the API:

title => array(1),
summary => array(1),
slug => "privacy-policy"
body => array(2)

The issue is that slug is expect to be an array, not a string. And it's this field which is Key Text field. I'm using v3.4.2 of the PHP SDK

Release Preview?

I've integrated the php-kit into my project. I'm able to pull the content from prismic, what I'm unable to figure it out is how can I get the preview working on my site like shown below:

image

Any advise ?

API data cache time

At https://github.com/prismicio/php-kit/blob/179a83363ef6c2fa120f5e2c90e5e24045eb776b/src/Prismic/Api.php#L330 the API data is cached for 5 units.

At https://github.com/prismicio/php-kit/blob/179a83363ef6c2fa120f5e2c90e5e24045eb776b/src/Prismic/Cache/CacheInterface.php#L43 the documentation for $ttl doesn't specify what the unit is.

At https://github.com/prismicio/php-kit/blob/179a83363ef6c2fa120f5e2c90e5e24045eb776b/src/Prismic/Cache/DefaultCache.php#L43 the $ttl variable is used as is and passed to apc_store, which interprets it as seconds.

  1. Please document in the interface that it means seconds, if that is indeed intended, or fix the logic if minutes were intended.
  2. Is caching the API data for as little as 5 seconds really intended? The request to get the API data is currently taking ~1 second for me on a test repository, and the thought of every five seconds every request until the value is recached taking 1 second longer than usual is unacceptable.
  3. Whether 5 seconds was intended or not, can you make that a default and have it configurable rather than hardcoded?

(edit: change links to point to source code as it was when ticket was originally opened)

Symfony 3 Compatibility

Hello,

I tried to install prismic on a Laravel 5.2 project, but it looks that Prismic is not compatible with Symfony 3.

This is the terminal message:

Your requirements could not be resolved to an installable set of packages.

  Problem 1
    - Installation request for prismic/php-sdk ^2.0 -> satisfiable by prismic/php-sdk[2.0.0].
    - Conclusion: remove symfony/event-dispatcher v3.0.6
    - Conclusion: don't install symfony/event-dispatcher v3.0.6
    - prismic/php-sdk 2.0.0 requires symfony/event-dispatcher ~2.0 -> satisfiable by symfony/event-dispatcher[2.0.4, 2.0.5, 2.0.6, 2.0.7, v2.0.10, v2.0.12, v2.0.13, v2.0.14, v2.0.15, v2.0.16, v2.0.17, v2.0.18, v2.0.19, v2.0.20, v2.0.21, v2.0.22, v2.0.23, v2.0.24, v2.0.25, v2.0.9, v2.1.0, v2.1.1, v2.1.10, v2.1.11, v2.1.12, v2.1.13, v2.1.2, v2.1.3, v2.1.4, v2.1.5, v2.1.6, v2.1.7, v2.1.8, v2.1.9, v2.2.0, v2.2.1, v2.2.10, v2.2.11, v2.2.2, v2.2.3, v2.2.4, v2.2.5, v2.2.6, v2.2.7, v2.2.8, v2.2.9, v2.3.0, v2.3.1, v2.3.10, v2.3.11, v2.3.12, v2.3.13, v2.3.14, v2.3.15, v2.3.16, v2.3.17, v2.3.18, v2.3.19, v2.3.2, v2.3.20, v2.3.21, v2.3.22, v2.3.23, v2.3.24, v2.3.25, v2.3.26, v2.3.27, v2.3.28, v2.3.29, v2.3.3, v2.3.30, v2.3.31, v2.3.32, v2.3.33, v2.3.34, v2.3.35, v2.3.36, v2.3.37, v2.3.38, v2.3.39, v2.3.4, v2.3.40, v2.3.41, v2.3.5, v2.3.6, v2.3.7, v2.3.8, v2.3.9, v2.4.0, v2.4.1, v2.4.10, v2.4.2, v2.4.3, v2.4.4, v2.4.5, v2.4.6, v2.4.7, v2.4.8, v2.4.9, v2.5.0, v2.5.1, v2.5.10, v2.5.11, v2.5.12, v2.5.2, v2.5.3, v2.5.4, v2.5.5, v2.5.6, v2.5.7, v2.5.8, v2.5.9, v2.6.0, v2.6.1, v2.6.10, v2.6.11, v2.6.12, v2.6.13, v2.6.2, v2.6.3, v2.6.4, v2.6.5, v2.6.6, v2.6.7, v2.6.8, v2.6.9, v2.7.0, v2.7.1, v2.7.10, v2.7.11, v2.7.12, v2.7.13, v2.7.2, v2.7.3, v2.7.4, v2.7.5, v2.7.6, v2.7.7, v2.7.8, v2.7.9, v2.8.0, v2.8.1, v2.8.2, v2.8.3, v2.8.4, v2.8.5, v2.8.6].
    - Can only install one of: symfony/event-dispatcher[v2.6.10, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.6.11, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.6.12, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.6.13, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.6.7, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.6.8, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.6.9, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.7.0, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.7.1, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.7.10, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.7.11, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.7.12, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.7.13, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.7.2, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.7.3, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.7.4, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.7.5, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.7.6, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.7.7, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.7.8, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.7.9, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.8.0, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.8.1, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.8.2, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.8.3, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.8.4, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.8.5, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.8.6, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[2.0.4, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[2.0.5, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[2.0.6, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[2.0.7, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.0.10, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.0.12, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.0.13, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.0.14, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.0.15, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.0.16, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.0.17, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.0.18, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.0.19, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.0.20, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.0.21, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.0.22, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.0.23, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.0.24, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.0.25, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.0.9, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.1.0, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.1.1, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.1.10, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.1.11, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.1.12, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.1.13, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.1.2, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.1.3, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.1.4, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.1.5, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.1.6, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.1.7, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.1.8, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.1.9, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.2.0, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.2.1, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.2.10, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.2.11, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.2.2, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.2.3, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.2.4, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.2.5, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.2.6, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.2.7, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.2.8, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.2.9, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.0, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.1, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.10, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.11, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.12, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.13, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.14, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.15, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.16, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.17, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.18, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.19, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.2, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.20, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.21, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.22, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.23, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.24, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.25, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.26, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.27, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.28, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.29, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.3, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.30, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.31, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.32, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.33, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.34, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.35, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.36, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.37, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.38, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.39, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.4, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.40, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.41, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.5, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.6, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.7, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.8, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.3.9, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.4.0, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.4.1, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.4.10, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.4.2, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.4.3, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.4.4, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.4.5, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.4.6, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.4.7, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.4.8, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.4.9, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.5.0, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.5.1, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.5.10, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.5.11, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.5.12, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.5.2, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.5.3, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.5.4, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.5.5, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.5.6, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.5.7, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.5.8, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.5.9, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.6.0, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.6.1, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.6.2, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.6.3, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.6.4, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.6.5, v3.0.6].
    - Can only install one of: symfony/event-dispatcher[v2.6.6, v3.0.6].
    - Installation request for symfony/event-dispatcher (locked at v3.0.6) -> satisfiable by symfony/event-dispatcher[v3.0.6].


Installation failed, reverting ./composer.json to its original content.

Thank you

CacheInterface methods' documentation don't specify return value

I notice that DefaultCache returns the return value of the various APC functions used when running set, delete and clear but that the value to be returned is not documented in the interface. I'm implementing the interface and therefore don't know if I'll be complying by returning nothing -- perhaps some internal Prismic method expects a return value from these methods.

Allow either closure or LinkResolver object for $linkResolver

The documentation at https://developers.prismic.io/documentation/UjBe8bGIJ3EKtgBZ/api-documentation is now misleading. It's only in Javascript obviously but it suggests that a closure can be passed as $linkResolver, which is not possible since this PHP library tries to run $linkResolver->resolve() in certain places, and if #19 is accepted that'll be one more place where a closure is not accepted.

You could allow either a closure or a LinkResolver object by checking using the is_callable function.

API query always uses master ref

Hi,

Not sure if I'm missing something or not but I've been playing around with getting the preview functionality working and been digging into the code and looking at the query() function within Api.php line 432. It begins by trying to set the $ref and if it cannot find either the preview or experiment cookies it sets the master()->getRef(). But then in line 444 it doesn't use the above mentioned $ref it gets the master:

$form = $this->forms()->everything->ref($this->master()->getRef());

If I change the code (for testing only of course) to the below then my previewing works perfect.

$form = $this->forms()->everything->ref($ref);

Any help would be appreciated.

Regards,
MAt

orderings(), pageSize(), page(), if relevant

To be added in the SearchForm class.

Not sure if it's relevant, depending on whether the language allows to generate them dynamically or not.

Note: this can be worked around through set("orderings", "[my.value.position]") for now

PREVIEW_COOKIE constant is not autoload-friendly

The PREVIEW_COOKIE constant in the Api.php file is in the Prismic namespace but not within the Api class. So it's available at Prismic\PREVIEW_COOKIE, but only if the api.php file has been loaded, which in some cases is only if the autoloader has tried to find the Prismic\Api class.

So in some cases I'm getting an "undefined constant" error.

Perhaps it would could live inside the Api class instead, or somewhere else which can be autoloaded, like a class just meant as a container for constants?

Add "Return JSON" flag to `SearchForm::submit()` method

Since your php-kit has no sort of caching ability (and it shouldn't), I think it would be nice to provide the ability to return simply JSON when submitting a Search Form. This would allow the user to cache the results, and then pass them into SearchForm::parse() when they need them in a usable format. I can create the pull-request for this, but I wanted to get your thoughts on it beforehand.

Attributes missing in slices with linked documents

I'm having some issues with slices and document links. In my slices I have a reference to another custom type.

This is how i fetch from API:

$api = $prismic->get_api();
$page = $api->getByUID('pages', $uid, ['fetchLinks' => 'product.product_name, product.producer, product.price, product.description, product.systembolaget_link, product.product_image']);

Which gives the following result:

object(stdClass)#119 (12) {
  ["id"]=>
  string(16) "WZYBVygAAPRQNb4q"
  ["uid"]=>
  string(8) "products"
  ["type"]=>
  string(5) "pages"
  ["href"]=>
  string(142) "https://carlwine.prismic.io/api/v1/documents/search?ref=WZYYbigAAPRQNiPt&q=%5B%5B%3Ad+%3D+at%28document.id%2C+%22WZYBVygAAPRQNb4q%22%29+%5D%5D"
  ["tags"]=>
  array(0) {
  }
  ["first_publication_date"]=>
  string(24) "2017-08-17T20:50:14+0000"
  ["last_publication_date"]=>
  string(24) "2017-08-17T21:57:08+0000"
  ["slugs"]=>
  array(1) {
    [0]=>
    string(8) "products"
  }
  ["linked_documents"]=>
  NULL
  ["lang"]=>
  string(5) "sv-se"
  ["alternate_languages"]=>
  array(0) {
  }
  ["data"]=>
  object(stdClass)#112 (1) {
    ["pages"]=>
    object(stdClass)#117 (2) {
      ["title"]=>
      object(stdClass)#114 (2) {
        ["type"]=>
        string(14) "StructuredText"
        ["value"]=>
        array(1) {
          [0]=>
          object(stdClass)#113 (3) {
            ["type"]=>
            string(8) "heading1"
            ["text"]=>
            string(8) "Products"
            ["spans"]=>
            array(0) {
            }
          }
        }
      }
      ["body"]=>
      object(stdClass)#100 (2) {
        ["type"]=>
        string(9) "SliceZone"
        ["value"]=>
        array(3) {
          [0]=>
          object(stdClass)#120 (5) {
            ["type"]=>
            string(5) "Slice"
            ["slice_type"]=>
            string(7) "product"
            ["slice_label"]=>
            NULL
            ["repeat"]=>
            array(2) {
              [0]=>
              object(stdClass)#115 (1) {
                ["product"]=>
                object(stdClass)#122 (2) {
                  ["type"]=>
                  string(13) "Link.document"
                  ["value"]=>
                  object(stdClass)#123 (2) {
                    ["document"]=>
                    object(stdClass)#124 (6) {
                      ["id"]=>
                      string(16) "WZX99SgAAPRTNa8T"
                      ["type"]=>
                      string(7) "product"
                      ["tags"]=>
                      array(0) {
                      }
                      ["lang"]=>
                      string(5) "sv-se"
                      ["slug"]=>
                      string(37) "morellino-docg-poggio-valente-riserva"
                      ["data"]=>
                      object(stdClass)#125 (1) {
                        ["product"]=>
                        object(stdClass)#126 (5) {
                          ["product_name"]=>
                          array(1) {
                            [0]=>
                            object(stdClass)#127 (3) {
                              ["type"]=>
                              string(8) "heading1"
                              ["text"]=>
                              string(37) "Morellino DOCG Poggio Valente Riserva"
                              ["spans"]=>
                              array(0) {
                              }
                            }
                          }
                          ["description"]=>
                          array(1) {
                            [0]=>
                            object(stdClass)#128 (3) {
                              ["type"]=>
                              string(9) "paragraph"
                              ["text"]=>
                              string(277) "Ruby red with light garnet red reflections. In the nose we feel red fruit aromas which  reminds also of the Macchia Mediterranea perfumes. This wine is characterized by a remarkably elegant structure, well integrated tannins, full body pleasantly fresh, persistent  aftertaste."
                              ["spans"]=>
                              array(0) {
                              }
                            }
                          }
                          ["price"]=>
                          array(1) {
                            [0]=>
                            object(stdClass)#129 (3) {
                              ["type"]=>
                              string(8) "heading1"
                              ["text"]=>
                              string(3) "318"
                              ["spans"]=>
                              array(0) {
                              }
                            }
                          }
                          ["producer"]=>
                          array(1) {
                            [0]=>
                            object(stdClass)#130 (3) {
                              ["type"]=>
                              string(8) "heading1"
                              ["text"]=>
                              string(19) "Fattoria Le Pupille"
                              ["spans"]=>
                              array(0) {
                              }
                            }
                          }
                          ["product_image"]=>
                          object(stdClass)#131 (2) {
                            ["type"]=>
                            string(5) "Image"
                            ["value"]=>
                            object(stdClass)#132 (2) {
                              ["main"]=>
                              object(stdClass)#133 (4) {
                                ["dimensions"]=>
                                object(stdClass)#134 (2) {
                                  ["width"]=>
                                  int(190)
                                  ["height"]=>
                                  int(694)
                                }
                                ["alt"]=>
                                NULL
                                ["copyright"]=>
                                NULL
                                ["url"]=>
                                string(104) "https://prismic-io.s3.amazonaws.com/carlwine/d634c6bd9c9af313e0d943bb9f3a0ecda1c5013b_poggio_valente.jpg"
                              }
                              ["views"]=>
                              object(stdClass)#135 (0) {
                              }
                            }
                          }
                        }
                      }
                    }
                    ["isBroken"]=>
                    bool(false)
                  }
                }
              }
              [1]=>
              object(stdClass)#136 (1) {
                ["product"]=>
                object(stdClass)#137 (2) {
                  ["type"]=>
                  string(13) "Link.document"
                  ["value"]=>
                  object(stdClass)#138 (2) {
                    ["document"]=>
                    object(stdClass)#139 (6) {
                      ["id"]=>
                      string(16) "WZX_ZygAAPRQNbWQ"
                      ["type"]=>
                      string(7) "product"
                      ["tags"]=>
                      array(0) {
                      }
                      ["lang"]=>
                      string(5) "sv-se"
                      ["slug"]=>
                      string(30) "prosecco-merotto-graziano-brut"
                      ["data"]=>
                      object(stdClass)#140 (1) {
                        ["product"]=>
                        object(stdClass)#141 (5) {
                          ["product_name"]=>
                          array(1) {
                            [0]=>
                            object(stdClass)#142 (3) {
                              ["type"]=>
                              string(8) "heading1"
                              ["text"]=>
                              string(30) "Prosecco Merotto Graziano Brut"
                              ["spans"]=>
                              array(0) {
                              }
                            }
                          }
                          ["description"]=>
                          array(1) {
                            [0]=>
                            object(stdClass)#143 (3) {
                              ["type"]=>
                              string(9) "paragraph"
                              ["text"]=>
                              string(281) "Its perfume is Fine and intense, with immediately obvious notes of white fruits and citrus alongside pleasant floral sensations softened by a mineral flourish. Taste is wonderfully fresh and elegantly tangy with good volume and balance providing an overall sense of great pleasure."
                              ["spans"]=>
                              array(0) {
                              }
                            }
                          }
                          ["price"]=>
                          array(1) {
                            [0]=>
                            object(stdClass)#144 (3) {
                              ["type"]=>
                              string(8) "heading1"
                              ["text"]=>
                              string(3) "179"
                              ["spans"]=>
                              array(0) {
                              }
                            }
                          }
                          ["producer"]=>
                          array(1) {
                            [0]=>
                            object(stdClass)#145 (3) {
                              ["type"]=>
                              string(8) "heading1"
                              ["text"]=>
                              string(7) "Merotto"
                              ["spans"]=>
                              array(0) {
                              }
                            }
                          }
                          ["product_image"]=>
                          object(stdClass)#146 (2) {
                            ["type"]=>
                            string(5) "Image"
                            ["value"]=>
                            object(stdClass)#147 (2) {
                              ["main"]=>
                              object(stdClass)#148 (4) {
                                ["dimensions"]=>
                                object(stdClass)#149 (2) {
                                  ["width"]=>
                                  int(385)
                                  ["height"]=>
                                  int(864)
                                }
                                ["alt"]=>
                                NULL
                                ["copyright"]=>
                                NULL
                                ["url"]=>
                                string(105) "https://prismic-io.s3.amazonaws.com/carlwine/adbf0c734e2d721b54def2068219db96dd061c6b_cuvee-fondatore.jpg"
                              }
                              ["views"]=>
                              object(stdClass)#150 (0) {
                              }
                            }
                          }
                        }
                      }
                    }
                    ["isBroken"]=>
                    bool(false)
                  }
                }
              }
            }
            ["non-repeat"]=>
            object(stdClass)#151 (0) {
            }
          }
          [1]=>
          object(stdClass)#152 (5) {
            ["type"]=>
            string(5) "Slice"
            ["slice_type"]=>
            string(4) "text"
            ["slice_label"]=>
            NULL
            ["repeat"]=>
            array(2) {
              [0]=>
              object(stdClass)#153 (1) {
                ["text"]=>
                object(stdClass)#154 (2) {
                  ["type"]=>
                  string(14) "StructuredText"
                  ["value"]=>
                  array(1) {
                    [0]=>
                    object(stdClass)#155 (3) {
                      ["type"]=>
                      string(9) "paragraph"
                      ["text"]=>
                      string(14) "Hejsan, hejsan"
                      ["spans"]=>
                      array(0) {
                      }
                    }
                  }
                }
              }
              [1]=>
              object(stdClass)#156 (1) {
                ["text"]=>
                object(stdClass)#157 (2) {
                  ["type"]=>
                  string(14) "StructuredText"
                  ["value"]=>
                  array(1) {
                    [0]=>
                    object(stdClass)#158 (3) {
                      ["type"]=>
                      string(9) "paragraph"
                      ["text"]=>
                      string(6) "Hopsan"
                      ["spans"]=>
                      array(0) {
                      }
                    }
                  }
                }
              }
            }
            ["non-repeat"]=>
            object(stdClass)#159 (0) {
            }
          }
          [2]=>
          object(stdClass)#160 (5) {
            ["type"]=>
            string(5) "Slice"
            ["slice_type"]=>
            string(19) "non_repeatable_text"
            ["slice_label"]=>
            NULL
            ["repeat"]=>
            array(1) {
              [0]=>
              object(stdClass)#161 (0) {
              }
            }
            ["non-repeat"]=>
            object(stdClass)#162 (1) {
              ["text"]=>
              object(stdClass)#163 (2) {
                ["type"]=>
                string(4) "Text"
                ["value"]=>
                string(6) "Hejsan"
              }
            }
          }
        }
      }
    }
  }
}

So all the attributes of the linked documents are there. So everything is fine for now. Moving on to the template:

$prismic = $WPGLOBAL['prismic'];
$page = $WPGLOBAL['page'];

$slices = $page->getSliceZone('pages.body')->getSlices();
foreach ($slices as $slice) {
    switch ($slice->getSliceType()) {
        case 'product':
            foreach ($slice->getItems()->getArray() as $product) {
              var_dump($product);
            }
            break;
    }
}

This is where it breaks. The $product variable only contains the attribute product.product_image:

object(Prismic\Fragment\GroupDoc)#168 (1) {
  ["fragments":"Prismic\WithFragments":private]=>
  array(1) {
    ["product"]=>
    object(Prismic\Fragment\Link\DocumentLink)#167 (8) {
      ["id":"Prismic\Fragment\Link\DocumentLink":private]=>
      string(16) "WZX99SgAAPRTNa8T"
      ["type":"Prismic\Fragment\Link\DocumentLink":private]=>
      string(7) "product"
      ["tags":"Prismic\Fragment\Link\DocumentLink":private]=>
      array(0) {
      }
      ["slug":"Prismic\Fragment\Link\DocumentLink":private]=>
      string(37) "morellino-docg-poggio-valente-riserva"
      ["lang":"Prismic\Fragment\Link\DocumentLink":private]=>
      string(5) "sv-se"
      ["isBroken":"Prismic\Fragment\Link\DocumentLink":private]=>
      bool(false)
      ["fragments":"Prismic\WithFragments":private]=>
      array(1) {
        ["product.product_image"]=>
        object(Prismic\Fragment\Image)#166 (2) {
          ["main":"Prismic\Fragment\Image":private]=>
          object(Prismic\Fragment\ImageView)#165 (6) {
            ["url":"Prismic\Fragment\ImageView":private]=>
            string(104) "https://prismic-io.s3.amazonaws.com/carlwine/d634c6bd9c9af313e0d943bb9f3a0ecda1c5013b_poggio_valente.jpg"
            ["alt":"Prismic\Fragment\ImageView":private]=>
            NULL
            ["copyright":"Prismic\Fragment\ImageView":private]=>
            NULL
            ["width":"Prismic\Fragment\ImageView":private]=>
            int(190)
            ["height":"Prismic\Fragment\ImageView":private]=>
            int(694)
            ["link":"Prismic\Fragment\ImageView":private]=>
            NULL
          }
          ["views":"Prismic\Fragment\Image":private]=>
          array(0) {
          }
        }
      }
      ["uid"]=>
      NULL
    }
  }
}
object(Prismic\Fragment\GroupDoc)#172 (1) {
  ["fragments":"Prismic\WithFragments":private]=>
  array(1) {
    ["product"]=>
    object(Prismic\Fragment\Link\DocumentLink)#171 (8) {
      ["id":"Prismic\Fragment\Link\DocumentLink":private]=>
      string(16) "WZX_ZygAAPRQNbWQ"
      ["type":"Prismic\Fragment\Link\DocumentLink":private]=>
      string(7) "product"
      ["tags":"Prismic\Fragment\Link\DocumentLink":private]=>
      array(0) {
      }
      ["slug":"Prismic\Fragment\Link\DocumentLink":private]=>
      string(30) "prosecco-merotto-graziano-brut"
      ["lang":"Prismic\Fragment\Link\DocumentLink":private]=>
      string(5) "sv-se"
      ["isBroken":"Prismic\Fragment\Link\DocumentLink":private]=>
      bool(false)
      ["fragments":"Prismic\WithFragments":private]=>
      array(1) {
        ["product.product_image"]=>
        object(Prismic\Fragment\Image)#170 (2) {
          ["main":"Prismic\Fragment\Image":private]=>
          object(Prismic\Fragment\ImageView)#169 (6) {
            ["url":"Prismic\Fragment\ImageView":private]=>
            string(105) "https://prismic-io.s3.amazonaws.com/carlwine/adbf0c734e2d721b54def2068219db96dd061c6b_cuvee-fondatore.jpg"
            ["alt":"Prismic\Fragment\ImageView":private]=>
            NULL
            ["copyright":"Prismic\Fragment\ImageView":private]=>
            NULL
            ["width":"Prismic\Fragment\ImageView":private]=>
            int(385)
            ["height":"Prismic\Fragment\ImageView":private]=>
            int(864)
            ["link":"Prismic\Fragment\ImageView":private]=>
            NULL
          }
          ["views":"Prismic\Fragment\Image":private]=>
          array(0) {
          }
        }
      }
      ["uid"]=>
      NULL
    }
  }
}

LinkResolver -- don't add <a> tag when resolve returns null?

It might be useful for the HTML renderer not to print the <a> tag at all (only its contents) if the LinkResolver's resolve method (or the closure) returns null (or false or something), rather than having an <a href=""> tag when a link can't be made for whatever reason.

It'd be more useful again to be able to change the tag which is used (a <span class="broken-link"> or something, perhaps) in certain cases, rather than being limited to only changing the href.

Just an idea, since if a link is broken at the moment I can raise a warning but am otherwise stuck with an <a href="">click here to whatever</a> element. Something for the "someday" list, perhaps.

PSR-6 ?

Are there any plans to replace default APC cache with PSR-6 soon?

Introduce an abstract PrismicDataModel

Hello,

The prismicio API is built on top of the magic method __get. It will be better to have proper getter and not relying on this feature. I guess this has been done to respect other api.

So in order to avoid duplicated code, it will be great to have a parent PrismicDataModel object to include this code. This will required to change property visibility from private to protected

<?php

abstract class PrismicDataModel 
{
    public function __get($property)
    {
        if (!property_exists($this, $property)) {
            throw new \RuntimeException(sprintf('The property %s on %s does not exist', $property, get_class($this));
        }

      return $this->$property;
    }
} 

Trying to get urlencoded URL during preview

I had a pair of exceptions logged today when our client tried to preview a document on their production site. We're using php-kit 1.5.12 at the moment.

The exception was:

The url "https%3A%2F%2Fmyrepository.prismic.io%2Fpreviews%2FpnXiQQFUif96wtGW" is not valid.

Coming from http-adapter, via the $response = $this->getHttpAdapter()->get($token); line of the previewSession method of Api.php.

The value of $token was the urlencoded URL as shown in the error message.

I'd submit a patch decoding the token in the preview method before trying to get it, but I'm not sure it's a bug here; perhaps it's a new bug in your server-side application instead. Please advise.

More efficient way to $doc->get($doc->getType() . '.field_name')

I find that I'm doing a lot of $doc->get($doc->getType() . '.field_name') for various field names, and all the equivalents (`->getHtml' etc).

Writing it this way (with $doc->getType() in there) is good because I can more easily reuse code where the documents have different types but with common property names, but it is messy.

Are there cases when a document has properties directly from a different document type? If not, what's the point in namespacing on the document type at all?

If there is a good reason, then I wonder if it'd be possible to provide some method which is a shortcut to the above? Shame if that means duplicating it for all the different getters (getHtml, getImage, getText, ...), but it'd make my code a whole lot more concise.

dateBefore predicate issue

The dateBefore predicate sometimes gives incorrect results.

In my case I have a timestamp field with the following data:
screen shot 2017-06-01 at 16 24 05

When I do a query using the following predicate
Predicates::dateBefore( {path}, new DateTime('2017-01-03'))
it does not return the document above, which I would expect it to.

The following will return the document correctly:
Predicates::dateBefore( {path}, '2017-01-03')

Therefore, I suspect that the conversion to a Timestamp needs to be fixed to account for time zones.

I'm also assuming that this needs to be done as well for the dateAfter and dateBetween predicates.

Add phpdoc on functions

You should add phpdocs on all functions.

If you are using phpstorm, press "inspect code" and check the PHPDoc section ... once the basic phpdoc comments are generated, you can fix convention using phpfixer and then tweak type definition.

Unit Tests Failing

The Unit tests are failing because it seems that the test repository has been killed off:

curl -I https://lesbonneschoses.cdn.prismic.io/api
HTTP/1.1 301 Moved Permanently
Location: https://prismic.io/docs/examples/blog

Build failed: Erroneous data format for unserializing 'Mock_Response_f64b4cda'

The build is failed on the PHP kit these days, and I can't seem to figure out why.

Here is what the failure looks like: https://travis-ci.org/prismicio/php-kit/jobs/28044938

Surprisingly it fails with PHP 5.4 and 5.5, but not PHP 5.3. Even more surprising: it doesn't fail on my machine, which runs PHP 5.4.

The first commit on which it failed is that one, but it doesn't seem to contain anything fishy.

Unless somebody has time for it before, I'll dive into this seriously tomorrow.

getStructuredText throwing errors

When trying to use the getStructuredText function, I'm encountering this error:

Argument 2 passed to Prismic\Fragment\StructuredText::insertSpans() must be of the type array, null given, 
called in vendor/prismic/php-sdk/src/Prismic/Fragment/StructuredText.php on line 277 

The line in question is here:

$content = StructuredText::insertSpans($block->getText(), $block->getSpans(), $linkResolver);

Which in turn comes down to the TextBlock.php class. Seems like forcing the $spans class variable to default to a null fixes the problem inside the Fragment\Block\TextBlock class:

private $spans = array();

but I can't say whether that's the correct way to handle this.

Get SliceZone by sliceType

Is there a way to get a Slice from a document's SliceZone by referencing the sliceType field?

Looking at the code, the only obvious way I see to get to a particular slice in a zone is to reference it by array element. However, this has proven to not be reliable as adding a new slice to a Content Type changes the array element indexing.

In my case, I was developing a new Content Type. I had the Content Type set with one slice in the SliceZone. After a bit of development we decided to add a second slice. This action broke the pages that used this Content Type because the new slice became element '0' in the SliceZone's Slices array. This happening in development isn't that big of a deal, but if the situation arises that we want to modify a Content Type that has live, production content, it would be a real problem if referencing the slices by array index broke pages.

Is it possible to do something like $page->getSliceZone('my_type.field')->getSliceByType('my_type'); ?

As it currently is, the only way I can find to get to the slices is to do $page->getSliceZone('my_type.field')[0], which, as I said, doesn't seem to be reliable.

This seems like it would be an easy thing to implement. If this indeed isn't currently available, I'm happy to do a PR for it, but I wanted to make sure I wasn't missing something, and to also find out if there is a specific reason this isn't currently available.

Thanks.

Loosen version requirement for egeloen/http-adapter

Currently the version of egeloen/http-adapter is locked specifically to 0.6.0, which prevents installing newer versions of Guzzle.

egeloen/http-adapter has been updated to support Guzzle 6, but the specific version of 0.6.0 does not have this support. Loosening this requirement to "~0.6.0" would allow updating to 0.8.

problem with prismicio oauth

Hi,

We are using a prismicio oauth. The problem is that it doesn't work for newly created users (it was verified that it works ok on one old account). When I login it doesn't redirect me to my website. I can not find any support link on prismic.io.

In chrome inspector I see this
application.js:1633NOT FOUND /settings/authorizations/confirm?client_id=clientID&redirect_uri=http%3A%2F%2Fsomeapp.ngrok.io%2Fapp_dev.php%2Foauth%2Fcallback&scope=master%2Breleases&code=someCode/

Best regards,
Michal

@barrycarton

(apc "bug") Caching impossible on ubuntu precise

Problem

Although it makes total sense to cache object forever, the native apc_store function returns false (not the problem - see below) when ttl is [50 years] - as it is the case when you consume the prismic api. Works perfectly well when ttl is [10 years]. This is not a bug but might be a very wispread standard issue nontheless.

Solution

Since it is a pure contingency I think it's a design decision and it is up to you to tell me how to circumvent this problem. As per official documentation It seems that setting the ttl to 0 would achieve the same result in a safer way :

TTL allocation takes place here :
https://github.com/prismicio/php-kit/blob/master/src/Prismic/SearchForm.php#L259

&Acirc;

Hi There,
I wonder if someone faced the same issue or could point us in the right direction here...

Imagine situation where content writer enters following on the page content in prismic:

£34.01

once the content is fetched via php-sdk it comes as:

&amp;Acirc;&amp;pound;34.01

after using html_entity_decode() we still get

£34.01

we could use

str_replace("&amp;Acirc;", "", $content)

but it seems to be happening for other special chars as well like ™ ® ©

Despite promiss, immutables objects returned by SearchForm are not cached

Obviously, there is something wrong here: https://github.com/prismicio/php-kit/blob/master/src/Prismic/SearchForm.php#L233

You could add to https://github.com/prismicio/php-kit/blob/master/tests/Prismic/LesBonnesChosesTest.php a small test to assess this:

public function testImmutableObjectCache()
    {
      $api = Api::get(self::$testRepository);
      $masterRef = $api->master()->getRef();
      $results1 = $api->forms()->everything->ref($masterRef)->submit();
      // Sorry for the next line since there is no access to the $url property used to build the http query and used as cache key 
      // we had to harcode it here. There is certainly a more elegant way to test this 
      \apc_store('http://lesbonneschoses.prismic.io/api/documents/search?page=1&pageSize=20&ref=UkL0hcuvzYUANCrm', 'coucou', 1000);
      $results2 = $api->forms()->everything->ref($masterRef)->submit();
      $this->assertTrue(json_encode($results1) != json_encode($results2));
    }

Does it make any sense? We are happy to discuss this further or try a pull request if it is not obvious.
Cheers,

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.