diff --git a/.github/workflows/check-branch.yml b/.github/workflows/check-branch.yml new file mode 100644 index 00000000..1e2d24a5 --- /dev/null +++ b/.github/workflows/check-branch.yml @@ -0,0 +1,20 @@ +name: 'Check Branch' + +on: + pull_request: + +jobs: + check_branch: + runs-on: ubuntu-latest + steps: + - name: Comment PR + if: github.base_ref == 'master' && github.head_ref != 'next' + uses: thollander/actions-comment-pull-request@v2 + with: + message: | + We regret to inform you that you are currently not able to merge your changes into the master branch due to restrictions applied by our SRE team. To proceed with merging your changes, we kindly request that you create a pull request from the next branch. Our team will then review the changes and work with you to ensure a successful merge into the master branch. + - name: Check branch + if: github.base_ref == 'master' && github.head_ref != 'next' + run: | + echo "ERROR: We regret to inform you that you are currently not able to merge your changes into the master branch due to restrictions applied by our SRE team. To proceed with merging your changes, we kindly request that you create a pull request from the next branch. Our team will then review the changes and work with you to ensure a successful merge into the master branch." + exit 1 \ No newline at end of file diff --git a/.github/workflows/jira.yml b/.github/workflows/jira.yml new file mode 100644 index 00000000..5ddf87a6 --- /dev/null +++ b/.github/workflows/jira.yml @@ -0,0 +1,28 @@ +name: Create JIRA ISSUE +on: + pull_request: + types: [opened] +jobs: + security: + if: ${{ github.actor == 'dependabot[bot]' || github.actor == 'snyk-bot' || contains(github.event.pull_request.head.ref, 'snyk-fix-') || contains(github.event.pull_request.head.ref, 'snyk-upgrade-')}} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Login into JIRA + uses: atlassian/gajira-login@master + env: + JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }} + JIRA_USER_EMAIL: ${{ secrets.JIRA_USER_EMAIL }} + JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }} + - name: Create a JIRA Issue + id: create + uses: atlassian/gajira-create@master + with: + project: ${{ secrets.JIRA_PROJECT }} + issuetype: ${{ secrets.JIRA_ISSUE_TYPE }} + summary: | + ${{ github.event.pull_request.title }} + description: | + PR: ${{ github.event.pull_request.html_url }} + + fields: "${{ secrets.JIRA_FIELDS }}" diff --git a/.github/workflows/sca-scan.yml b/.github/workflows/sca-scan.yml new file mode 100644 index 00000000..7bbb29cd --- /dev/null +++ b/.github/workflows/sca-scan.yml @@ -0,0 +1,15 @@ +name: Source Composition Analysis Scan +on: + pull_request: + types: [opened, synchronize, reopened] +jobs: + security: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Run Snyk to check for vulnerabilities + uses: snyk/actions/php@master + env: + SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} + with: + args: --fail-on=all diff --git a/.gitignore b/.gitignore new file mode 100755 index 00000000..041dc5af --- /dev/null +++ b/.gitignore @@ -0,0 +1,19 @@ +.vscode/ +.idea/ +composer.phar +composer.lock +vendor/ +test/report.html +test/AssetsTestReport.html +test/Assetsreport.html +test/EntryTestReport.html +test/Entryreport.html +test/Entriesreport.html +test/ImageTransformreport.html +examples/index.php +.DS_Store +tmp/ +test/result.json +stdout +build +cache \ No newline at end of file diff --git a/.talismanrc b/.talismanrc new file mode 100644 index 00000000..8a09f761 --- /dev/null +++ b/.talismanrc @@ -0,0 +1,3 @@ +fileignoreconfig: +- filename: test/REST.php + checksum: 975e995f6196587e33e246c66b366aa99f9a79cb3fd44366f7ab6134495f2201 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..28097c85 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,185 @@ + +## CHANGELOG + +------------------------------------------------ +## Version 2.4.0 +###### Date: 13-May-2024 +### Enhancement + - GCP support implementation +------------------------------------------------ +## Version 2.3.4 +###### Date: 30-Aug-2023 +### Enhancement + - PHP version 8.2 support + +------------------------------------------------ +## Version 2.3.3 +###### Date: 31-Mar-2023 +### Enhancement + - add support for include_metada for PHP SDK + - set default region to 'us' + - Issue while fetching the entry using PHP SDK + +------------------------------------------------ +## Version 2.3.2 +###### Date: 01-Feb-2023 +### Enhancement + - Live preview reference entry extra field issue resolved + +------------------------------------------------ +## Version 2.3.1 +###### Date: 09-Sep-2022 +### Enhancement + - Reference update within entry support added in live preview. + +------------------------------------------------ +## Version 2.3.0 +###### Date: 17-Aug-2022 +### New Feature + - Http request proxy support + - Retry request on failure + +------------------------------------------------ +## Version 2.2.1 +###### Date: 14-Jan-2022 +### Bug Fix + - Host bug for live preview resolved + +------------------------------------------------ +## Version 2.2.0 +###### Date: 08-Dec-2021 +### New Feature + - Live Preview feature added + +------------------------------------------------ + +## Version 2.1.1 +###### Date: 16-Jul-2021 +### New Feature + - Utils SDK package update to support Json RTE to Html Parsing + +------------------------------------------------ + +## Version 2.1.0 +###### Date: 06-Apr-2021 +### Enhancement + - includeEmbeddedItems function added in Entry and Query Module + - Utils SDK support added in SDK + +------------------------------------------------ + +## Version 2.0.0 +###### Date: 02-Apr-2021 +### New Feature + - Sync API support added +### Enhancement + - Added PSR 4 Standardized implementation. + +------------------------------------------------ + +## Version 1.8.1 +###### Date: 17-Mar-2021 +### Bug Fix +- Updated addQuery method to pass non encoded Json to Query object +- Removed parameter check on functions those pass default values. + +------------------------------------------------ + +## Version 1.8.0 +###### Date: 5-Dec-2020 +### New Feature + - Entry + - Added support for function 'includeFallback' + - Query + - Added support for function 'includeFallback' + +------------------------------------------------ + +## Version 1.7.0 +###### Date: 27-Oct-2020 +### New Feature + - Packagist support added + +------------------------------------------------ + +## Version 1.6.1 +###### Date: 08-May-2020 +### Bug + - Stack api key and access token moved to header +------------------------------------------------ + +## Version 1.6.0 +###### Date: 04-Mar-2020 +### Bug + - Issue in Asset for conflict in name of Query function has been resolved, Updated BaseQuery function name to addQuery. + +------------------------------------------------ + +## Version 1.5.1 +###### Date: 17-Feb-2020 +### Bug + - Query array passing issue resolved + +------------------------------------------------ + +## Version 1.5.0 +###### Date: 21-Nov-2019 +### New Feature + - Region support added + +------------------------------------------------ + +## Version 1.4.0 +###### Date: 18-Nov-2019 +### Enhancement + - Stack + - Added support for function 'getContentType' + - ContentType + - updated function 'fetch' + - Query + - Added support for function 'includeContentType' + +------------------------------------------------ + +## Version 1.3.0 +###### Date: 02-Aug-2019 +### Enhancement + - Query and Entry + - 'includeReferenceContentTypeUID' method includes the content type UIDs of the referenced entries returned in the response. + +------------------------------------------------ + +## Version 1.2.1 +###### Date: 25-May-2019 +### Bug + - Made changes in helper file for fetching proper data on language query + +------------------------------------------------ + +## Version 1.2.1 +###### Date: 19-Sept-2018 +### Bug + - Replaced the createError method with New method contentstackcreateError. + +------------------------------------------------ + +## Version 1.2.0 +###### Date: 21-Dec-2017 +### Enhancement + - Entry + - 'addparam' method added + - Query + - 'addparam' method added + - Asset + - 'addparam' method added + +------------------------------------------------ + +## Version 1.1.0 +###### Date: 09-Nov-2017 +### Enhancement + - Image Optimisation support added +### Deprecated + - Deprecated includeSchema and added includeContentType in query + +------------------------------------------------ \ No newline at end of file diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 00000000..07739234 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1 @@ +* @contentstack/security-admin \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100755 index 00000000..30b216ff --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2012-2024 Contentstack (http://app.contentstack.com). All Rights Reserved + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 46936207..31254059 --- a/README.md +++ b/README.md @@ -1,2 +1,160 @@ -# contentstack-php -PHP SDK for Built.io Contentstack - Content Delivery API +[![Contentstack](https://www.contentstack.com/docs/static/images/contentstack.png)](https://www.contentstack.com/) + +## PHP SDK for Contentstack + +Contentstack is a headless CMS with an API-first approach. It is a CMS that developers can use to build powerful cross-platform applications in their favorite languages. Build your application frontend, and Contentstack will take care of the rest. [Read More](https://www.contentstack.com/). + +Contentstack provides PHP SDK to build application on top of PHP. Given below is the detailed guide and helpful resources to get started with our PHP SDK. + + +### Prerequisite + +You need PHP version >= 5.5.0 or later installed to use the Contentstack PHP SDK. + +### Setup and Installation + +#### Install the library using [Composer](https://packagist.org/packages/contentstack/contentstack): +To use the PHP SDK, you need to perform the following steps: + + composer require contentstack/contentstack + +To initialize the SDK, you will need to specify the API Key, Delivery Token, and Environment Name of your stack. + +```php +use Contentstack\Contentstack; +$stack = Contentstack::Stack(API_KEY, DELIVERY_TOKEN, ENV_NAME); +``` +For Setting the European Region: +If you want to set and use European region, refer to the code below: + +```php +use Contentstack\Contentstack; +use Contentstack\ContentstackRegion; +$stack = Contentstack::Stack(API_KEY, DELIVERY_TOKEN, ENV_NAME, array('region'=> ContentstackRegion.EU)); +``` +#### Download and install library: +To use the PHP SDK, you need to perform the following steps: + +1. [Download](https://www.contentstack.com/docs/platforms/php/php_sdk_latest) the PHP SDK +2. Create `dependencies` folder in your project directory +3. Move this downloaded zip file to a `dependencies` folder +4. Download the [MabeEnum](https://github.com/marc-mabe/php-enum) +5. Create `marc-mabe` folder inside the `dependencies` folder +6. Move the `php-enum` folder inside the `marc-mabe` folder + +To initialize the SDK, you will need to specify the API Key, Delivery Token, and Environment Name of your stack. + +```php +include_once __DIR__ . '/dependencies/contentstack/index.php'; +use Contentstack\Contentstack; +$stack = Contentstack::Stack(API_KEY, DELIVERY_TOKEN, ENV_NAME); +``` + + +### Key Concepts for using Contentstack + +#### Stack + +A stack is like a container that holds the content of your app. Learn more about [Stacks](https://www.contentstack.com/docs/guide/stack). + +#### Content Type + +Content type lets you define the structure or blueprint of a page or a section of your digital property. It is a form-like page that gives Content Managers an interface to input and upload content. [Read more](https://www.contentstack.com/docs/guide/content-types). + +#### Entry + +An entry is the actual piece of content created using one of the defined content types. Learn more about [Entries](https://www.contentstack.com/docs/guide/content-management#working-with-entries). + +#### Asset + +Assets refer to all the media files (images, videos, PDFs, audio files, and so on) uploaded to Contentstack. These files can be used in multiple entries. Read more about [Assets](https://www.contentstack.com/docs/guide/content-management#working-with-assets). + +#### Environment + +A publishing environment corresponds to one or more deployment servers or a content delivery destination where the entries need to be published. Learn how to work with [Environments](https://www.contentstack.com/docs/guide/environments). + + + +### Contentstack PHP SDK: 5-minute Quickstart + +#### Initializing your SDK +Install the library using [Composer](https://packagist.org/packages/contentstack/contentstack): + + composer require contentstack/contentstack + + +To initialize the SDK, you will need to specify the API Key, Delivery Token, and Environment Name of your stack. + +```php +use Contentstack\Contentstack; +$stack = Contentstack::Stack(API_KEY, DELIVERY_TOKEN, ENV_NAME); +``` + +To get the API credentials mentioned above, log in to your Contentstack account and then in your top panel navigation, go to Settings > Stack to view the API Key and Delivery Token. + + + +#### Querying content from your stack + +To find all entries of a content type, use the query given below: + +```php +$result = $stack->ContentType(CONTENT_TYPE_UID)->Query()->toJSON()->includeCount()->includeContentType()->find(); +// $result[0] - array of entries +// $result[1] - content type +// $result[2] - count of the entries +``` + +To fetch a specific entry from a content type, use the following query: + +```php +$result = $stack->ContentType(CONTENT_TYPE_UID)->Entry(ENTRY_UID)->toJSON()->fetch(); +// $result - entry object +``` + +### Advanced Queries + +You can query for content types, entries, assets and more using our PHP API Reference. + +[PHP API Reference Doc](https://www.contentstack.com/docs/platforms/php/api-reference/) + + + +### Working with Images + +We have introduced Image Delivery APIs that let you retrieve images and then manipulate and optimize them for your digital properties. It lets you perform a host of other actions such as crop, trim, resize, rotate, overlay, and so on. + +For example, if you want to crop an image (with width as 300 and height as 400), you simply need to append query parameters at the end of the image URL, such as, https://images.contentstack.io/v3/assets/blteae40eb499811073/bltc5064f36b5855343/59e0c41ac0eddd140d5a8e3e/download?crop=300,400. There are several more parameters that you can use for your images. + +[Read Image Delivery API documentation](https://www.contentstack.com/docs/apis/image-delivery-api/). + +You can use the Image Delivery API functions in this SDK as well. Here are a few examples of its usage in the SDK. + +// set the image quality to 100. + +```php +$imageUrl = $stack->imageTransform(imageUrl, array('quality' => 100)); +``` + +// resize the image by specifying width and height. + +```php +$imageUrl = $stack->imageTransform(imageUrl, array( + 'width' => 100, + 'height' => 100 +)); +``` + +// enable auto optimization for the image. + +```php +$imageUrl = $stack->imageTransform(imageUrl, array('auto' => 'webp')); +``` + + +### Helpful Links + +- [Contentstack Website](https://www.contentstack.com) +- [Official Documentation](https://www.contentstack.com/docs) +- [Content Delivery API Docs](https://www.contentstack.com/docs/apis/content-delivery-api/) + diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..b5fe070e --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,27 @@ +## Security + +Contentstack takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations. + +If you believe you have found a security vulnerability in any Contentstack-owned repository, please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Send email to [security@contentstack.com](mailto:security@contentstack.com). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +[https://www.contentstack.com/trust/](https://www.contentstack.com/trust/) diff --git a/composer.json b/composer.json new file mode 100644 index 00000000..3c999aaf --- /dev/null +++ b/composer.json @@ -0,0 +1,40 @@ +{ + "name": "contentstack/contentstack", + "description": "Contentstack is a headless CMS with an API-first approach that puts content at the centre. It is designed to simplify the process of publication by separating code from content.", + "type": "library", + "license": "MIT", + "keywords": [ + "Contentstack", "api" + ], + "authors": [ + { + "name": "Contentstack", + "homepage": "https://www.contentstack.com/", + "role": "Owner" + }, + { + "name": "Uttam K Ukkoji", + "email": "uttamukkoji@gmail.com", + "role": "Developer" + } + ], + "autoload": { + "psr-4": { + "Contentstack\\": "src/" + }, + "files": ["src/Support/helper.php"] + }, + "require-dev": { + "phpunit/phpunit": "^10.0", + "phpunit/php-code-coverage": "^10.0", + "code-lts/doctum": "^5.3" + }, + "scripts": { + "generate:docs": "vendor/bin/doctum.php update ./config.php", + "test": "vendor/bin/phpunit" + }, + "require": { + "php" : ">=5.5.0", + "contentstack/utils": "^1.0" + } +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 00000000..999e04e3 --- /dev/null +++ b/composer.lock @@ -0,0 +1,3518 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "486121208ea31ca3385722fa6aee0fe2", + "packages": [ + { + "name": "contentstack/utils", + "version": "v1.2.0", + "source": { + "type": "git", + "url": "https://github.com/contentstack/contentstack-utils-php.git", + "reference": "7e16e8bd5a247e75ea6ff1969339c5405f2cd71f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/contentstack/contentstack-utils-php/zipball/7e16e8bd5a247e75ea6ff1969339c5405f2cd71f", + "reference": "7e16e8bd5a247e75ea6ff1969339c5405f2cd71f", + "shasum": "" + }, + "require": { + "marc-mabe/php-enum": "^4.7.0", + "php": ">=7.2" + }, + "require-dev": { + "phpunit/php-code-coverage": "^9.0", + "phpunit/phpunit": "^9.3", + "squizlabs/php_codesniffer": "^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-4": { + "Contentstack\\Utils\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Contentstack", + "email": "support@contentstack.com", + "homepage": "https://www.contentstack.com", + "role": "Owner" + }, + { + "name": "Uttam K Ukkoji", + "email": "uttam.ukkoji@contentstack.com", + "role": "Developer" + } + ], + "description": "Contentstack is a headless CMS with an API-first approach that puts content at the centre. It is designed to simplify the process of publication by separating code from content.", + "homepage": "https://github.com/contentstack/contentstack-utils-php", + "keywords": [ + "Contentstack", + "utils" + ], + "support": { + "issues": "https://github.com/contentstack/contentstack-utils-php/issues", + "source": "https://github.com/contentstack/contentstack-utils-php/tree/v1.2.0" + }, + "time": "2023-06-27T15:07:37+00:00" + }, + { + "name": "marc-mabe/php-enum", + "version": "v4.7.0", + "source": { + "type": "git", + "url": "https://github.com/marc-mabe/php-enum.git", + "reference": "3da42cc1daceaf98c858e56f59d1ccd52b011fdc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/marc-mabe/php-enum/zipball/3da42cc1daceaf98c858e56f59d1ccd52b011fdc", + "reference": "3da42cc1daceaf98c858e56f59d1ccd52b011fdc", + "shasum": "" + }, + "require": { + "ext-reflection": "*", + "php": "^7.1 | ^8.0" + }, + "require-dev": { + "phpbench/phpbench": "^0.16.10 || ^1.0.4", + "phpstan/phpstan": "^1.3.1", + "phpunit/phpunit": "^7.5.20 | ^8.5.22 | ^9.5.11", + "vimeo/psalm": "^4.17.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.6-dev", + "dev-3.x": "3.2-dev" + } + }, + "autoload": { + "psr-4": { + "MabeEnum\\": "src/" + }, + "classmap": [ + "stubs/Stringable.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Marc Bennewitz", + "email": "dev@mabe.berlin", + "homepage": "https://mabe.berlin/", + "role": "Lead" + } + ], + "description": "Simple and fast implementation of enumerations with native PHP", + "homepage": "https://github.com/marc-mabe/php-enum", + "keywords": [ + "enum", + "enum-map", + "enum-set", + "enumeration", + "enumerator", + "enummap", + "enumset", + "map", + "set", + "type", + "type-hint", + "typehint" + ], + "support": { + "issues": "https://github.com/marc-mabe/php-enum/issues", + "source": "https://github.com/marc-mabe/php-enum/tree/v4.7.0" + }, + "time": "2022-04-19T02:21:46+00:00" + } + ], + "packages-dev": [ + { + "name": "code-lts/cli-tools", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/code-lts/cli-tools.git", + "reference": "321f8046dc1070259bb01a25942e93779378e6a8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/code-lts/cli-tools/zipball/321f8046dc1070259bb01a25942e93779378e6a8", + "reference": "321f8046dc1070259bb01a25942e93779378e6a8", + "shasum": "" + }, + "require": { + "ondram/ci-detector": "^4.0", + "php": "^7.1 || ^8.0", + "symfony/console": "~3.4|~4.3|^5|^6" + }, + "require-dev": { + "phpstan/phpstan": "^1.4.6", + "phpunit/phpunit": "^7 || ^8 || ^9", + "wdes/coding-standard": "^3.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "CodeLts\\CliTools\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MPL-2.0" + ], + "authors": [ + { + "name": "William Desportes", + "email": "williamdes@wdes.fr", + "homepage": "https://william.wdes.fr" + }, + { + "name": "Ondřej Mirtes", + "email": "ondrej@mirtes.cz", + "homepage": "https://ondrej.mirtes.cz" + } + ], + "description": "CLI tools to manage output errors formatting for junit, checkstyle, teamcity, gitlab and github error formats", + "homepage": "https://github.com/code-lts/cli-tools", + "keywords": [ + "checkstyle", + "cli", + "formatters", + "github", + "gitlab", + "junit", + "teamcity" + ], + "support": { + "email": "williamdes@wdes.fr", + "issues": "https://github.com/code-lts/cli-tools/issues", + "source": "https://github.com/code-lts/cli-tools" + }, + "time": "2022-02-18T20:34:03+00:00" + }, + { + "name": "code-lts/doctum", + "version": "v5.5.2", + "source": { + "type": "git", + "url": "https://github.com/code-lts/doctum.git", + "reference": "42561708b76a5dccdf3684729c9d1453db78e8a5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/code-lts/doctum/zipball/42561708b76a5dccdf3684729c9d1453db78e8a5", + "reference": "42561708b76a5dccdf3684729c9d1453db78e8a5", + "shasum": "" + }, + "require": { + "code-lts/cli-tools": "^1.4.0", + "erusev/parsedown": "^1.7", + "nikic/php-parser": "^4.10", + "php": "^7.2.20 || ^8.0", + "phpdocumentor/reflection-docblock": "~5.3", + "symfony/console": "~3.4|~4.3|^5|^6", + "symfony/filesystem": "~3.4|~4.3|^5|^6", + "symfony/finder": "~3.4|~4.3|^5|^6", + "symfony/process": "~3.4|~4.3|^5|^6", + "symfony/yaml": "~3.4|~4.3|^5|^6", + "twig/twig": "^3.0", + "wdes/php-i18n-l10n": "^4.0" + }, + "require-dev": { + "phpstan/phpstan": "^1.4.6", + "phpstan/phpstan-phpunit": "^1", + "phpunit/phpunit": "^7 || ^8 || ^9", + "wdes/coding-standard": "^3.3.1" + }, + "bin": [ + "bin/doctum.php" + ], + "type": "application", + "extra": { + "branch-alias": { + "dev-main": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "Doctum\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "William Desportes", + "email": "williamdes@wdes.fr" + } + ], + "description": "Doctum, a PHP API documentation generator. Fork of Sami", + "homepage": "https://github.com/code-lts/doctum", + "keywords": [ + "generator", + "phpdoc" + ], + "support": { + "email": "williamdes@wdes.fr", + "issues": "https://github.com/code-lts/doctum/issues", + "source": "https://github.com/code-lts/doctum" + }, + "funding": [ + { + "url": "https://github.com/sponsors/williamdes", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/code-lts/doctum", + "type": "tidelift" + } + ], + "time": "2023-03-12T13:27:49+00:00" + }, + { + "name": "doctrine/deprecations", + "version": "v1.1.1", + "source": { + "type": "git", + "url": "https://github.com/doctrine/deprecations.git", + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/doctrine/deprecations/zipball/612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", + "reference": "612a3ee5ab0d5dd97b7cf3874a6efe24325efac3", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "doctrine/coding-standard": "^9", + "phpstan/phpstan": "1.4.10 || 1.10.15", + "phpstan/phpstan-phpunit": "^1.0", + "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", + "psalm/plugin-phpunit": "0.18.4", + "psr/log": "^1 || ^2 || ^3", + "vimeo/psalm": "4.30.0 || 5.12.0" + }, + "suggest": { + "psr/log": "Allows logging deprecations via PSR-3 logger implementation" + }, + "type": "library", + "autoload": { + "psr-4": { + "Doctrine\\Deprecations\\": "lib/Doctrine/Deprecations" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively for packages.", + "homepage": "https://www.doctrine-project.org/", + "support": { + "issues": "https://github.com/doctrine/deprecations/issues", + "source": "https://github.com/doctrine/deprecations/tree/v1.1.1" + }, + "time": "2023-06-03T09:27:29+00:00" + }, + { + "name": "erusev/parsedown", + "version": "1.7.4", + "source": { + "type": "git", + "url": "https://github.com/erusev/parsedown.git", + "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/erusev/parsedown/zipball/cb17b6477dfff935958ba01325f2e8a2bfa6dab3", + "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35" + }, + "type": "library", + "autoload": { + "psr-0": { + "Parsedown": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Emanuil Rusev", + "email": "hello@erusev.com", + "homepage": "http://erusev.com" + } + ], + "description": "Parser for Markdown.", + "homepage": "http://parsedown.org", + "keywords": [ + "markdown", + "parser" + ], + "support": { + "issues": "https://github.com/erusev/parsedown/issues", + "source": "https://github.com/erusev/parsedown/tree/1.7.x" + }, + "time": "2019-12-30T22:54:17+00:00" + }, + { + "name": "myclabs/deep-copy", + "version": "1.11.1", + "source": { + "type": "git", + "url": "https://github.com/myclabs/DeepCopy.git", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "reference": "7284c22080590fb39f2ffa3e9057f10a4ddd0e0c", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "conflict": { + "doctrine/collections": "<1.6.8", + "doctrine/common": "<2.13.3 || >=3,<3.2.2" + }, + "require-dev": { + "doctrine/collections": "^1.6.8", + "doctrine/common": "^2.13.3 || ^3.2.2", + "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" + }, + "type": "library", + "autoload": { + "files": [ + "src/DeepCopy/deep_copy.php" + ], + "psr-4": { + "DeepCopy\\": "src/DeepCopy/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Create deep copies (clones) of your objects", + "keywords": [ + "clone", + "copy", + "duplicate", + "object", + "object graph" + ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.1" + }, + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", + "type": "tidelift" + } + ], + "time": "2023-03-08T13:26:56+00:00" + }, + { + "name": "nikic/php-parser", + "version": "v4.17.1", + "source": { + "type": "git", + "url": "https://github.com/nikic/PHP-Parser.git", + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "reference": "a6303e50c90c355c7eeee2c4a8b27fe8dc8fef1d", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "php": ">=7.0" + }, + "require-dev": { + "ircmaxell/php-yacc": "^0.0.7", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0 || ^9.0" + }, + "bin": [ + "bin/php-parse" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.9-dev" + } + }, + "autoload": { + "psr-4": { + "PhpParser\\": "lib/PhpParser" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Nikita Popov" + } + ], + "description": "A PHP parser written in PHP", + "keywords": [ + "parser", + "php" + ], + "support": { + "issues": "https://github.com/nikic/PHP-Parser/issues", + "source": "https://github.com/nikic/PHP-Parser/tree/v4.17.1" + }, + "time": "2023-08-13T19:53:39+00:00" + }, + { + "name": "ondram/ci-detector", + "version": "4.1.0", + "source": { + "type": "git", + "url": "https://github.com/OndraM/ci-detector.git", + "reference": "8a4b664e916df82ff26a44709942dfd593fa6f30" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/OndraM/ci-detector/zipball/8a4b664e916df82ff26a44709942dfd593fa6f30", + "reference": "8a4b664e916df82ff26a44709942dfd593fa6f30", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0" + }, + "require-dev": { + "ergebnis/composer-normalize": "^2.2", + "lmc/coding-standard": "^1.3 || ^2.1", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0.5", + "phpstan/phpstan": "^0.12.58", + "phpstan/phpstan-phpunit": "^0.12.16", + "phpunit/phpunit": "^7.1 || ^8.0 || ^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "OndraM\\CiDetector\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ondřej Machulda", + "email": "ondrej.machulda@gmail.com" + } + ], + "description": "Detect continuous integration environment and provide unified access to properties of current build", + "keywords": [ + "CircleCI", + "Codeship", + "Wercker", + "adapter", + "appveyor", + "aws", + "aws codebuild", + "azure", + "azure devops", + "azure pipelines", + "bamboo", + "bitbucket", + "buddy", + "ci-info", + "codebuild", + "continuous integration", + "continuousphp", + "devops", + "drone", + "github", + "gitlab", + "interface", + "jenkins", + "pipelines", + "sourcehut", + "teamcity", + "travis" + ], + "support": { + "issues": "https://github.com/OndraM/ci-detector/issues", + "source": "https://github.com/OndraM/ci-detector/tree/4.1.0" + }, + "time": "2021-04-14T09:16:52+00:00" + }, + { + "name": "phar-io/manifest", + "version": "2.0.3", + "source": { + "type": "git", + "url": "https://github.com/phar-io/manifest.git", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/manifest/zipball/97803eca37d319dfa7826cc2437fc020857acb53", + "reference": "97803eca37d319dfa7826cc2437fc020857acb53", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-phar": "*", + "ext-xmlwriter": "*", + "phar-io/version": "^3.0.1", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" + }, + "time": "2021-07-20T11:28:43+00:00" + }, + { + "name": "phar-io/version", + "version": "3.2.1", + "source": { + "type": "git", + "url": "https://github.com/phar-io/version.git", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + }, + { + "name": "Sebastian Heuer", + "email": "sebastian@phpeople.de", + "role": "Developer" + }, + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "Developer" + } + ], + "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, + "time": "2022-02-21T01:04:05+00:00" + }, + { + "name": "phpdocumentor/reflection-common", + "version": "2.2.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionCommon.git", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "reference": "1d01c49d4ed62f25aa84a747ad35d5a16924662b", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jaap van Otterdijk", + "email": "opensource@ijaap.nl" + } + ], + "description": "Common reflection classes used by phpdocumentor to reflect the code structure", + "homepage": "http://www.phpdoc.org", + "keywords": [ + "FQSEN", + "phpDocumentor", + "phpdoc", + "reflection", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, + "time": "2020-06-27T09:03:43+00:00" + }, + { + "name": "phpdocumentor/reflection-docblock", + "version": "5.3.0", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/622548b623e81ca6d78b721c5e029f4ce664f170", + "reference": "622548b623e81ca6d78b721c5e029f4ce664f170", + "shasum": "" + }, + "require": { + "ext-filter": "*", + "php": "^7.2 || ^8.0", + "phpdocumentor/reflection-common": "^2.2", + "phpdocumentor/type-resolver": "^1.3", + "webmozart/assert": "^1.9.1" + }, + "require-dev": { + "mockery/mockery": "~1.3.2", + "psalm/phar": "^4.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" + } + ], + "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" + }, + "time": "2021-10-19T17:43:47+00:00" + }, + { + "name": "phpdocumentor/type-resolver", + "version": "1.7.3", + "source": { + "type": "git", + "url": "https://github.com/phpDocumentor/TypeResolver.git", + "reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419", + "reference": "3219c6ee25c9ea71e3d9bbaf39c67c9ebd499419", + "shasum": "" + }, + "require": { + "doctrine/deprecations": "^1.0", + "php": "^7.4 || ^8.0", + "phpdocumentor/reflection-common": "^2.0", + "phpstan/phpdoc-parser": "^1.13" + }, + "require-dev": { + "ext-tokenizer": "*", + "phpbench/phpbench": "^1.2", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8", + "phpstan/phpstan-phpunit": "^1.1", + "phpunit/phpunit": "^9.5", + "rector/rector": "^0.13.9", + "vimeo/psalm": "^4.25" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-1.x": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "phpDocumentor\\Reflection\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Mike van Riel", + "email": "me@mikevanriel.com" + } + ], + "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.7.3" + }, + "time": "2023-08-12T11:01:26+00:00" + }, + { + "name": "phpmyadmin/twig-i18n-extension", + "version": "v4.0.1", + "source": { + "type": "git", + "url": "https://github.com/phpmyadmin/twig-i18n-extension.git", + "reference": "c0d0dd171cd1c7733bf152fd44b61055843df052" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpmyadmin/twig-i18n-extension/zipball/c0d0dd171cd1c7733bf152fd44b61055843df052", + "reference": "c0d0dd171cd1c7733bf152fd44b61055843df052", + "shasum": "" + }, + "require": { + "php": "^7.1 || ^8.0", + "twig/twig": "^1.42.3|^2.0|^3.0" + }, + "require-dev": { + "phpmyadmin/coding-standard": "^3.0.0", + "phpmyadmin/motranslator": "^5.2", + "phpstan/phpstan": "^0.12.66", + "phpunit/phpunit": "^7 || ^8 || ^9" + }, + "type": "library", + "autoload": { + "psr-4": { + "PhpMyAdmin\\Twig\\Extensions\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "The phpMyAdmin Team", + "email": "developers@phpmyadmin.net", + "homepage": "https://www.phpmyadmin.net/team/" + } + ], + "description": "Internationalization support for Twig via the gettext library", + "keywords": [ + "gettext", + "i18n" + ], + "support": { + "issues": "https://github.com/phpmyadmin/twig-i18n-extension/issues", + "source": "https://github.com/phpmyadmin/twig-i18n-extension" + }, + "time": "2021-06-10T15:53:38+00:00" + }, + { + "name": "phpstan/phpdoc-parser", + "version": "1.23.1", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "846ae76eef31c6d7790fac9bc399ecee45160b26" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/846ae76eef31c6d7790fac9bc399ecee45160b26", + "reference": "846ae76eef31c6d7790fac9bc399ecee45160b26", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^4.15", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.23.1" + }, + "time": "2023-08-03T16:32:59+00:00" + }, + { + "name": "phpunit/php-code-coverage", + "version": "10.1.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-code-coverage.git", + "reference": "be1fe461fdc917de2a29a452ccf2657d325b443d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/be1fe461fdc917de2a29a452ccf2657d325b443d", + "reference": "be1fe461fdc917de2a29a452ccf2657d325b443d", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-libxml": "*", + "ext-xmlwriter": "*", + "nikic/php-parser": "^4.15", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-text-template": "^3.0", + "sebastian/code-unit-reverse-lookup": "^3.0", + "sebastian/complexity": "^3.0", + "sebastian/environment": "^6.0", + "sebastian/lines-of-code": "^2.0", + "sebastian/version": "^4.0", + "theseer/tokenizer": "^1.2.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.1" + }, + "suggest": { + "ext-pcov": "PHP extension that provides line coverage", + "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.1-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", + "homepage": "https://github.com/sebastianbergmann/php-code-coverage", + "keywords": [ + "coverage", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-07-26T13:45:28+00:00" + }, + { + "name": "phpunit/php-file-iterator", + "version": "4.0.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-file-iterator.git", + "reference": "5647d65443818959172645e7ed999217360654b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/5647d65443818959172645e7ed999217360654b6", + "reference": "5647d65443818959172645e7ed999217360654b6", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "FilterIterator implementation that filters files based on a list of suffixes.", + "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", + "keywords": [ + "filesystem", + "iterator" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.0.2" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-05-07T09:13:23+00:00" + }, + { + "name": "phpunit/php-invoker", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-invoker.git", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "ext-pcntl": "*", + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-pcntl": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Invoke callables with a timeout", + "homepage": "https://github.com/sebastianbergmann/php-invoker/", + "keywords": [ + "process" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-invoker/issues", + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:56:09+00:00" + }, + { + "name": "phpunit/php-text-template", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-text-template.git", + "reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/9f3d3709577a527025f55bcf0f7ab8052c8bb37d", + "reference": "9f3d3709577a527025f55bcf0f7ab8052c8bb37d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Simple template engine.", + "homepage": "https://github.com/sebastianbergmann/php-text-template/", + "keywords": [ + "template" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-text-template/issues", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:56:46+00:00" + }, + { + "name": "phpunit/php-timer", + "version": "6.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/php-timer.git", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Utility class for timing", + "homepage": "https://github.com/sebastianbergmann/php-timer/", + "keywords": [ + "timer" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:57:52+00:00" + }, + { + "name": "phpunit/phpunit", + "version": "10.3.2", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/phpunit.git", + "reference": "0dafb1175c366dd274eaa9a625e914451506bcd1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0dafb1175c366dd274eaa9a625e914451506bcd1", + "reference": "0dafb1175c366dd274eaa9a625e914451506bcd1", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-json": "*", + "ext-libxml": "*", + "ext-mbstring": "*", + "ext-xml": "*", + "ext-xmlwriter": "*", + "myclabs/deep-copy": "^1.10.1", + "phar-io/manifest": "^2.0.3", + "phar-io/version": "^3.0.2", + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.1.1", + "phpunit/php-file-iterator": "^4.0", + "phpunit/php-invoker": "^4.0", + "phpunit/php-text-template": "^3.0", + "phpunit/php-timer": "^6.0", + "sebastian/cli-parser": "^2.0", + "sebastian/code-unit": "^2.0", + "sebastian/comparator": "^5.0", + "sebastian/diff": "^5.0", + "sebastian/environment": "^6.0", + "sebastian/exporter": "^5.0", + "sebastian/global-state": "^6.0.1", + "sebastian/object-enumerator": "^5.0", + "sebastian/recursion-context": "^5.0", + "sebastian/type": "^4.0", + "sebastian/version": "^4.0" + }, + "suggest": { + "ext-soap": "To be able to generate mocks based on WSDL files" + }, + "bin": [ + "phpunit" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "10.3-dev" + } + }, + "autoload": { + "files": [ + "src/Framework/Assert/Functions.php" + ], + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "The PHP Unit Testing framework.", + "homepage": "https://phpunit.de/", + "keywords": [ + "phpunit", + "testing", + "xunit" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "security": "https://github.com/sebastianbergmann/phpunit/security/policy", + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.3.2" + }, + "funding": [ + { + "url": "https://phpunit.de/sponsors.html", + "type": "custom" + }, + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", + "type": "tidelift" + } + ], + "time": "2023-08-15T05:34:23+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "sebastian/cli-parser", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/cli-parser.git", + "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/efdc130dbbbb8ef0b545a994fd811725c5282cae", + "reference": "efdc130dbbbb8ef0b545a994fd811725c5282cae", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for parsing CLI options", + "homepage": "https://github.com/sebastianbergmann/cli-parser", + "support": { + "issues": "https://github.com/sebastianbergmann/cli-parser/issues", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:58:15+00:00" + }, + { + "name": "sebastian/code-unit", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit.git", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the PHP code units", + "homepage": "https://github.com/sebastianbergmann/code-unit", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit/issues", + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:58:43+00:00" + }, + { + "name": "sebastian/code-unit-reverse-lookup", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Looks up which function or method a line of code belongs to", + "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:59:15+00:00" + }, + { + "name": "sebastian/comparator", + "version": "5.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/comparator.git", + "reference": "2db5010a484d53ebf536087a70b4a5423c102372" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2db5010a484d53ebf536087a70b4a5423c102372", + "reference": "2db5010a484d53ebf536087a70b4a5423c102372", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@2bepublished.at" + } + ], + "description": "Provides the functionality to compare PHP values for equality", + "homepage": "https://github.com/sebastianbergmann/comparator", + "keywords": [ + "comparator", + "compare", + "equality" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-08-14T13:18:12+00:00" + }, + { + "name": "sebastian/complexity", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/complexity.git", + "reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/e67d240970c9dc7ea7b2123a6d520e334dd61dc6", + "reference": "e67d240970c9dc7ea7b2123a6d520e334dd61dc6", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.10", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for calculating the complexity of PHP code units", + "homepage": "https://github.com/sebastianbergmann/complexity", + "support": { + "issues": "https://github.com/sebastianbergmann/complexity/issues", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T06:59:47+00:00" + }, + { + "name": "sebastian/diff", + "version": "5.0.3", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/diff.git", + "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/912dc2fbe3e3c1e7873313cc801b100b6c68c87b", + "reference": "912dc2fbe3e3c1e7873313cc801b100b6c68c87b", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0", + "symfony/process": "^4.2 || ^5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Kore Nordmann", + "email": "mail@kore-nordmann.de" + } + ], + "description": "Diff implementation", + "homepage": "https://github.com/sebastianbergmann/diff", + "keywords": [ + "diff", + "udiff", + "unidiff", + "unified diff" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.0.3" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-05-01T07:48:21+00:00" + }, + { + "name": "sebastian/environment", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/environment.git", + "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/43c751b41d74f96cbbd4e07b7aec9675651e2951", + "reference": "43c751b41d74f96cbbd4e07b7aec9675651e2951", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "suggest": { + "ext-posix": "*" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Provides functionality to handle HHVM/PHP environments", + "homepage": "https://github.com/sebastianbergmann/environment", + "keywords": [ + "Xdebug", + "environment", + "hhvm" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-04-11T05:39:26+00:00" + }, + { + "name": "sebastian/exporter", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/exporter.git", + "reference": "f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0", + "reference": "f3ec4bf931c0b31e5b413f5b4fc970a7d03338c0", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Volker Dusch", + "email": "github@wallbash.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + }, + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Provides the functionality to export PHP variables for visualization", + "homepage": "https://www.github.com/sebastianbergmann/exporter", + "keywords": [ + "export", + "exporter" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:06:49+00:00" + }, + { + "name": "sebastian/global-state", + "version": "6.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/global-state.git", + "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/7ea9ead78f6d380d2a667864c132c2f7b83055e4", + "reference": "7ea9ead78f6d380d2a667864c132c2f7b83055e4", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "ext-dom": "*", + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "6.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Snapshotting of global state", + "homepage": "http://www.github.com/sebastianbergmann/global-state", + "keywords": [ + "global state" + ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-07-19T07:19:23+00:00" + }, + { + "name": "sebastian/lines-of-code", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/lines-of-code.git", + "reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/17c4d940ecafb3d15d2cf916f4108f664e28b130", + "reference": "17c4d940ecafb3d15d2cf916f4108f664e28b130", + "shasum": "" + }, + "require": { + "nikic/php-parser": "^4.10", + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "2.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library for counting the lines of code in PHP source code", + "homepage": "https://github.com/sebastianbergmann/lines-of-code", + "support": { + "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:08:02+00:00" + }, + { + "name": "sebastian/object-enumerator", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-enumerator.git", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Traverses array structures and object graphs to enumerate all referenced objects", + "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:08:32+00:00" + }, + { + "name": "sebastian/object-reflector", + "version": "3.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/object-reflector.git", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + } + ], + "description": "Allows reflection of object attributes, including inherited and non-public ones", + "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:06:18+00:00" + }, + { + "name": "sebastian/recursion-context", + "version": "5.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/recursion-context.git", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712", + "reference": "05909fb5bc7df4c52992396d0116aed689f93712", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "5.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de" + }, + { + "name": "Jeff Welch", + "email": "whatthejeff@gmail.com" + }, + { + "name": "Adam Harvey", + "email": "aharvey@php.net" + } + ], + "description": "Provides functionality to recursively process PHP variables", + "homepage": "https://github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:05:40+00:00" + }, + { + "name": "sebastian/type", + "version": "4.0.0", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/type.git", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "phpunit/phpunit": "^10.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Collection of value objects that represent the types of the PHP type system", + "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-03T07:10:45+00:00" + }, + { + "name": "sebastian/version", + "version": "4.0.1", + "source": { + "type": "git", + "url": "https://github.com/sebastianbergmann/version.git", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "4.0-dev" + } + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Sebastian Bergmann", + "email": "sebastian@phpunit.de", + "role": "lead" + } + ], + "description": "Library that helps with managing the version number of Git-hosted PHP projects", + "homepage": "https://github.com/sebastianbergmann/version", + "support": { + "issues": "https://github.com/sebastianbergmann/version/issues", + "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" + }, + "funding": [ + { + "url": "https://github.com/sebastianbergmann", + "type": "github" + } + ], + "time": "2023-02-07T11:34:05+00:00" + }, + { + "name": "symfony/console", + "version": "v6.3.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/eca495f2ee845130855ddf1cf18460c38966c8b6", + "reference": "eca495f2ee845130855ddf1cf18460c38966c8b6", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-mbstring": "~1.0", + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^5.4|^6.0" + }, + "conflict": { + "symfony/dependency-injection": "<5.4", + "symfony/dotenv": "<5.4", + "symfony/event-dispatcher": "<5.4", + "symfony/lock": "<5.4", + "symfony/process": "<5.4" + }, + "provide": { + "psr/log-implementation": "1.0|2.0|3.0" + }, + "require-dev": { + "psr/log": "^1|^2|^3", + "symfony/config": "^5.4|^6.0", + "symfony/dependency-injection": "^5.4|^6.0", + "symfony/event-dispatcher": "^5.4|^6.0", + "symfony/lock": "^5.4|^6.0", + "symfony/process": "^5.4|^6.0", + "symfony/var-dumper": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Console\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Eases the creation of beautiful and testable command line interfaces", + "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command-line", + "console", + "terminal" + ], + "support": { + "source": "https://github.com/symfony/console/tree/v6.3.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-08-16T10:10:12+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/7c3aff79d10325257a001fcf92d991f24fc967cf", + "reference": "7c3aff79d10325257a001fcf92d991f24fc967cf", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-05-23T14:45:45+00:00" + }, + { + "name": "symfony/filesystem", + "version": "v6.3.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", + "reference": "edd36776956f2a6fcf577edb5b05eb0e3bdc52ae", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-mbstring": "~1.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides basic utilities for the filesystem", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/filesystem/tree/v6.3.1" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-06-01T08:30:39+00:00" + }, + { + "name": "symfony/finder", + "version": "v6.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/finder.git", + "reference": "9915db259f67d21eefee768c1abcf1cc61b1fc9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/finder/zipball/9915db259f67d21eefee768c1abcf1cc61b1fc9e", + "reference": "9915db259f67d21eefee768c1abcf1cc61b1fc9e", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "require-dev": { + "symfony/filesystem": "^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Finder\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Finds files and directories via an intuitive fluent interface", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/finder/tree/v6.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-07-31T08:31:44+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/5bbc823adecdae860bb64756d639ecfec17b050a", + "reference": "5bbc823adecdae860bb64756d639ecfec17b050a", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-ctype": "*" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "support": { + "source": "https://github.com/symfony/polyfill-ctype/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-intl-grapheme", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-grapheme.git", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/511a08c03c1960e08a883f4cffcacd219b758354", + "reference": "511a08c03c1960e08a883f4cffcacd219b758354", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Grapheme\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's grapheme_* functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "grapheme", + "intl", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-intl-normalizer", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-normalizer.git", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "reference": "19bd1e4fcd5b91116f14d8533c57831ed00571b6", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Intl\\Normalizer\\": "" + }, + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's Normalizer class and related functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "intl", + "normalizer", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.27.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "reference": "8ad114f6b39e2c98a8b0e3bd907732c207c2b534", + "shasum": "" + }, + "require": { + "php": ">=7.1" + }, + "provide": { + "ext-mbstring": "*" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "1.27-dev" + }, + "thanks": { + "name": "symfony/polyfill", + "url": "https://github.com/symfony/polyfill" + } + }, + "autoload": { + "files": [ + "bootstrap.php" + ], + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "support": { + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.27.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2022-11-03T14:55:06+00:00" + }, + { + "name": "symfony/process", + "version": "v6.3.4", + "source": { + "type": "git", + "url": "https://github.com/symfony/process.git", + "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/process/zipball/0b5c29118f2e980d455d2e34a5659f4579847c54", + "reference": "0b5c29118f2e980d455d2e34a5659f4579847c54", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Process\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Executes commands in sub-processes", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/process/tree/v6.3.4" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-08-07T10:39:22+00:00" + }, + { + "name": "symfony/service-contracts", + "version": "v3.3.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/service-contracts.git", + "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", + "reference": "40da9cc13ec349d9e4966ce18b5fbcd724ab10a4", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "psr/container": "^2.0" + }, + "conflict": { + "ext-psr": "<1.1|>=2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-main": "3.4-dev" + }, + "thanks": { + "name": "symfony/contracts", + "url": "https://github.com/symfony/contracts" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\Service\\": "" + }, + "exclude-from-classmap": [ + "/Test/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to writing services", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "support": { + "source": "https://github.com/symfony/service-contracts/tree/v3.3.0" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-05-23T14:45:45+00:00" + }, + { + "name": "symfony/string", + "version": "v6.3.2", + "source": { + "type": "git", + "url": "https://github.com/symfony/string.git", + "reference": "53d1a83225002635bca3482fcbf963001313fb68" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/string/zipball/53d1a83225002635bca3482fcbf963001313fb68", + "reference": "53d1a83225002635bca3482fcbf963001313fb68", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-intl-grapheme": "~1.0", + "symfony/polyfill-intl-normalizer": "~1.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/translation-contracts": "<2.5" + }, + "require-dev": { + "symfony/error-handler": "^5.4|^6.0", + "symfony/http-client": "^5.4|^6.0", + "symfony/intl": "^6.2", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^5.4|^6.0" + }, + "type": "library", + "autoload": { + "files": [ + "Resources/functions.php" + ], + "psr-4": { + "Symfony\\Component\\String\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way", + "homepage": "https://symfony.com", + "keywords": [ + "grapheme", + "i18n", + "string", + "unicode", + "utf-8", + "utf8" + ], + "support": { + "source": "https://github.com/symfony/string/tree/v6.3.2" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-07-05T08:41:27+00:00" + }, + { + "name": "symfony/yaml", + "version": "v6.3.3", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "e23292e8c07c85b971b44c1c4b87af52133e2add" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/e23292e8c07c85b971b44c1c4b87af52133e2add", + "reference": "e23292e8c07c85b971b44c1c4b87af52133e2add", + "shasum": "" + }, + "require": { + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "symfony/console": "<5.4" + }, + "require-dev": { + "symfony/console": "^5.4|^6.0" + }, + "bin": [ + "Resources/bin/yaml-lint" + ], + "type": "library", + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Loads and dumps YAML files", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/yaml/tree/v6.3.3" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2023-07-31T07:08:24+00:00" + }, + { + "name": "theseer/tokenizer", + "version": "1.2.1", + "source": { + "type": "git", + "url": "https://github.com/theseer/tokenizer.git", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/theseer/tokenizer/zipball/34a41e998c2183e22995f158c581e7b5e755ab9e", + "reference": "34a41e998c2183e22995f158c581e7b5e755ab9e", + "shasum": "" + }, + "require": { + "ext-dom": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": "^7.2 || ^8.0" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Arne Blankerts", + "email": "arne@blankerts.de", + "role": "Developer" + } + ], + "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + }, + "funding": [ + { + "url": "https://github.com/theseer", + "type": "github" + } + ], + "time": "2021-07-28T10:34:58+00:00" + }, + { + "name": "twig/twig", + "version": "v3.7.0", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "5cf942bbab3df42afa918caeba947f1b690af64b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/5cf942bbab3df42afa918caeba947f1b690af64b", + "reference": "5cf942bbab3df42afa918caeba947f1b690af64b", + "shasum": "" + }, + "require": { + "php": ">=7.2.5", + "symfony/polyfill-ctype": "^1.8", + "symfony/polyfill-mbstring": "^1.3" + }, + "require-dev": { + "psr/container": "^1.0|^2.0", + "symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Twig\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Twig Team", + "role": "Contributors" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "https://twig.symfony.com", + "keywords": [ + "templating" + ], + "support": { + "issues": "https://github.com/twigphp/Twig/issues", + "source": "https://github.com/twigphp/Twig/tree/v3.7.0" + }, + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/twig/twig", + "type": "tidelift" + } + ], + "time": "2023-07-26T07:16:09+00:00" + }, + { + "name": "wdes/php-i18n-l10n", + "version": "v4.0.0", + "source": { + "type": "git", + "url": "https://github.com/wdes/php-I18n-L10n.git", + "reference": "f64b9ca054a5204a48a88dc38aeb7c6dae2f4df5" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/wdes/php-I18n-L10n/zipball/f64b9ca054a5204a48a88dc38aeb7c6dae2f4df5", + "reference": "f64b9ca054a5204a48a88dc38aeb7c6dae2f4df5", + "shasum": "" + }, + "require": { + "php": "^7.2.9 || ^8.0", + "phpmyadmin/twig-i18n-extension": "^4.0", + "twig/twig": "^3" + }, + "require-dev": { + "phpstan/phpstan": "^0.12", + "phpunit/phpunit": "^7 || ^8 || ^9", + "wdes/coding-standard": "^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Wdes\\phpI18nL10n\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MPL-2.0" + ], + "authors": [ + { + "name": "William Desportes", + "email": "williamdes@wdes.fr" + } + ], + "description": "PHP library/api to provide Internationalisation and Localisation", + "homepage": "https://github.com/wdes/php-I18n-l10n", + "keywords": [ + "composer-package", + "gettext", + "i18n", + "l10n", + "library", + "mo", + "pot-generator", + "twig" + ], + "support": { + "email": "williamdes@wdes.fr", + "issues": "https://github.com/wdes/php-I18n-l10n/issues", + "source": "https://github.com/wdes/php-I18n-l10n" + }, + "time": "2021-03-31T13:51:25+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=5.5.0" + }, + "platform-dev": [], + "plugin-api-version": "2.3.0" +} diff --git a/config.php b/config.php new file mode 100644 index 00000000..f6fc74c8 --- /dev/null +++ b/config.php @@ -0,0 +1,4 @@ + + + Contentstack PHP SDK + + +

Welcome to Contentstack PHP SDK

+ + +getContentTypes('{"include_snippet_schema": "false"}'); + // $result = $stack->ContentType('first_ct')->Query()->toJSON()->find(); + // $result = $stack->ContentType('a')->Fetch(); + // $result = $stack->ContentType('a')->Query()->includeSchema()->toJSON()->find(); + // $result = $stack->ContentType('ctwithallfields')->Query()->addParam('include_dimensions', true)->toJSON()->find(); + // $result = $stack->ContentType('a')->Entry('blta07130f8b344b260')->includeContentType()->toJSON()->fetch(); + $result = $stack->Assets()->Query()->includeFallback()->toJSON()->find(); + //$result = $stack->Assets('blt9b5825dd804a9067')->addParam('include_dimension', 'true')->fetch(); + Utility::debug(($result)); + +} catch(Exception $e) { + echo "Message : ".$e->getMessage(); // returns message -> API -> error_message + echo "Code : ".$e->getCode(); // returns number -> API -> error_code + echo "Errors : ".print_r($e->getErrors()); // returns array -> API -> errors +} diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 00000000..8940b595 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + test + + + + + + + + + + src + + + diff --git a/src/Config/index.php b/src/Config/index.php new file mode 100644 index 00000000..d1c05321 --- /dev/null +++ b/src/Config/index.php @@ -0,0 +1,28 @@ + + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ +namespace Contentstack\Config; + +// Domain relevant constants +define('HOST', 'cdn.contentstack.io'); +define('PROTOCOL', 'https'); +define('VERSION', '/v3'); +define('PORT', 443); + +// URL's relevant constants +define('CONTENT_TYPES', '/content_types/'); +define('ENTRIES', '/entries/'); +define('ASSETS', '/assets/'); +define('ENVIRONMENTS', '/environments/'); +define('SYNC', '/stacks/sync/'); diff --git a/src/Contentstack.php b/src/Contentstack.php new file mode 100755 index 00000000..8ac41b41 --- /dev/null +++ b/src/Contentstack.php @@ -0,0 +1,75 @@ + + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + */ +namespace Contentstack; + +use Contentstack\Stack\Stack; +use Contentstack\Utils\Utils; +use Contentstack\Utils\Model\Option; + + +/** + * Contentstack abstract class to provide access to Stack Object + * + * @category PHP + * @package Contentstack + * @author Uttam K Ukkoji + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + */ +#[\AllowDynamicProperties] +abstract class Contentstack +{ + /** + * Static method for the Stack constructor + * + * @param string $api_key : Contentstack Stack API KEY. + * @param string $access_token : Contentstack Stack ACCESS TOKEN. + * @param string $environment : Environment Name. + * @param array $config : Stack Configuration to provide region. + * @param ContentstackRegion $region : Region name of Contentstack. (default region 'us') + * + * @return Stack + * */ + + public static function Stack($api_key = '', + $access_token = '', + $environment = '', + $config = array('region'=> 'us', 'branch'=> '', 'live_preview' => array('enable' => false, 'host' => 'api.contentstack.io')) + ) { + return new Stack($api_key, $access_token, $environment, $config); + } + + public static function renderContent(string $content, Option $option): string + { + return Utils::renderContent($content, $option); + } + + public static function renderContents(array $contents, Option $option): array + { + return Utils::renderContents($contents, $option); + } + + public static function jsonToHtml(object $content, Option $option): string + { + return Utils::jsonToHtml($content, $option); + } + + public static function jsonArrayToHtml(array $contents, Option $option): array + { + return Utils::jsonArrayToHtml($contents, $option); + } +} \ No newline at end of file diff --git a/src/ContentstackRegion.php b/src/ContentstackRegion.php new file mode 100755 index 00000000..bf99ea99 --- /dev/null +++ b/src/ContentstackRegion.php @@ -0,0 +1,35 @@ + + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ +namespace Contentstack; + +/** + * Contentstack Regions + * + * @category PHP + * @package Contentstack + * @author Uttam K Ukkoji + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ +class ContentstackRegion +{ + const EU= "eu"; + const US= "us"; + const AZURE_NA= "azure-na"; + const AZURE_EU= "azure-eu"; + const GCP_NA= "gcp-na"; +} \ No newline at end of file diff --git a/src/Error/CSException.php b/src/Error/CSException.php new file mode 100755 index 00000000..639f3803 --- /dev/null +++ b/src/Error/CSException.php @@ -0,0 +1,86 @@ + + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ + +namespace Contentstack\Error; + +/** + * CSException + * CSException Class is used to wrap the REST API error + * + * @category PHP + * @package Contentstack + * @author Uttam K Ukkoji + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ +#[\AllowDynamicProperties] +class CSException extends \Exception +{ + var $error_message; + var $error_code; + var $http_code; + /** + * CSException Class to initalize your ContentType + * + * @param string $error - Error message + * @param Stack $http_code - Erro code + * */ + function __construct($error, $http_code = 412) + { + $error = json_decode($error, true); + $this->error_message = ( + isset( + $error['error_message'] + ) + ) ? + $error['error_message'] : + "It seems Contentstack is behaving badly. + Please contact support@contentstack.io."; + + $this->error_code = ( + isset($error['error_code']) + ) ? + $error['error_code'] : null; + $this->errors = ( + isset($error['errors']) + ) ? $error['errors'] : + array(); + $this->http_code = $http_code; + parent::__construct($this->error_message, $this->error_code, null); + } + + /** + * To get http status_code of the current exception + * + * @return HttpCode|string + * */ + function getStatusCode() + { + return $this->http_code; + } + + /** + * Returns error details of current exception + * + * @return error|array + * */ + function getErrors() + { + return $this->errors; + } +} \ No newline at end of file diff --git a/src/Stack/Assets.php b/src/Stack/Assets.php new file mode 100755 index 00000000..101f21a0 --- /dev/null +++ b/src/Stack/Assets.php @@ -0,0 +1,88 @@ + + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ +namespace Contentstack\Stack; + +require_once __DIR__ . "/../Support/helper.php"; + +use Contentstack\Stack\ContentType\Query; +use Contentstack\Stack\BaseQuery; +use Contentstack\Support\Utility; + +/** + * Assets refer to all the media files (images, videos, PDFs, + * audio files, and so on) uploaded in your Contentstack + * repository for future use. + * + * @category PHP + * @package Contentstack + * @author Uttam K Ukkoji + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ +#[\AllowDynamicProperties] +class Assets extends BaseQuery +{ + + var $operation; + var $assetUid = ''; + var $stack = ''; + var $type = ''; + + + /** + * Assets constructor + * + * @param string $asset_uid - valid asset uid relevent to configured stack + * @param Stack $stack - valid stack configured details + * */ + public function __construct($asset_uid = '', $stack = '') + { + if ($asset_uid == '') { + $this->stack = $stack; + $this->type = 'assets'; + } else { + $stack->type = 'asset'; + $this->assetUid = $asset_uid; + parent::__construct($stack, $this); + } + } + + /** + * Query object to create the "Query" on the specified ContentType + * + * @return Query + * */ + public function Query() + { + return new Query($this, $this->type); + } + + + /** + * Fetch the specified assets + * + * @return Request + * */ + public function fetch() + { + $this->operation = __FUNCTION__; + return Utility::contentstackRequest($this->stack, $this, 'asset'); + } +} + diff --git a/src/Stack/BaseQuery.php b/src/Stack/BaseQuery.php new file mode 100755 index 00000000..b63d5b66 --- /dev/null +++ b/src/Stack/BaseQuery.php @@ -0,0 +1,1015 @@ + + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ + +namespace Contentstack\Stack; +use Contentstack\Support\Utility; + +require_once __DIR__ . "/../Support/helper.php"; + +/** + * BaseQuery + * Base Class where all the Queries will be created + * + * @category PHP + * @package Contentstack + * @author Uttam K Ukkoji + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ +#[\AllowDynamicProperties] +abstract class BaseQuery +{ + var $subQuery; + /** + * BaseQuery constructor + * + * @param string $data - data for query + * @param string $parent - parent of query + * */ + public function __construct($data = '', $parent = '') + { + + if ($data->type === 'assets') { + $this->assets = $data; + $this->queryObject = $parent; + $this->queryObject->_query = array(); + $this->subQuery = array(); + + } elseif ($data->type === 'asset') { + $this->stack = $data; + $this->queryObject = $parent; + $this->queryObject->_query = array(); + $this->subQuery = array(); + } else { + $this->contentType = $data; + $this->queryObject = $parent; + $this->queryObject->_query = array(); + $this->subQuery = array(); + } + } + + /** + * To transform the Result object to server response content + * + * @example //Converting response array to JSON format + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('CONTENT_TYPE_UID')->Query()->toJSON()->find(); + * + * @return JSON + * */ + public function toJSON() + { + $this->json_translate = true; + return $this->queryObject; + } + + /** + * To exclude the fields from the result set + * + * @param string $level - + * @param array $field_uids - field uids as array + * + * @example In the Product content type, if we need to retrieve the data of entries of all the + * other fields except the Price in USD parameter, you can send the parameter as: + * + * except(string $level = 'BASE', array $field_uids = array()) + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Entry('CONTENTTYPE_UID')->toJSON()->except('BASE',array('price'))->fetch(); + * + * + * @return Query + * */ + public function except($level = 'BASE', $field_uids = array()) + { + if ($field_uids && is_array($field_uids)) { + $this->queryObject->_query = call_user_func( + 'contentstackProjection', + 'except', + $this->queryObject->_query, + $level, + $field_uids + ); + return $this->queryObject; + } + throw contentstackCreateError('field_uids must be an array'); + } + + /** + * To project the fields in the result set + * + * @param string $level - + * @param array $field_uids - field uids as array + * + * @example In the Product content type, if we need to retrieve the data of only the Price in USD + * parameter of all the entries, you can send the parameter as: + * + * only(string $level = 'BASE', array $field_uids = array()) + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Entry(' ')->toJSON()->only('BASE',array('price'))->fetch(); + * + * @return Query|Entry + * */ + public function only($level = 'BASE', $field_uids = array()) + { + if ($field_uids && is_array($field_uids)) { + $this->queryObject->_query = call_user_func( + 'contentstackProjection', + 'only', + $this->queryObject->_query, + $level, + $field_uids + ); + return $this->queryObject; + } + throw contentstackCreateError('field_uids must be an array'); + } + + /** + * To include reference(s) of other content type in entries + * + * @param $field_uids - array of reference field uids + * + * @example //In the Product content type, there is a reference field called Categories, which refers entries of another content type. Let’s assume that you had + * created an entry for the Product content type, and the value selected in the Categories field was ‘Mobiles’. If you fetch the entry using + * the ‘Get a Single Entry’ API request, you would get all the details of the entry in the response, but the value against the Categories field + * would be UID of the referenced entry (i.e., UID of the ‘Mobiles’ entry in this case). + * + * //In order to fetch the details of the entry used in the Categories reference field, you need to + * //use the include[] parameter in the following manner: + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $results = $stack->ContentType('product')->Query()->toJSON()->includeReference(array('categories'))->find(); + * + * @return Query + * */ + public function includeReference($field_uids = array()) + { + if ($field_uids && is_array($field_uids)) { + $this->queryObject->_query = call_user_func( + 'contentstackReferences', + 'include', + $this->queryObject->_query, + $field_uids + ); + return $this->queryObject; + } + throw contentstackCreateError('field_uids must be an array'); + } + + /** + * To search the given string in the entries + * + * @deprecated since verion 2.2.0 + * @param $search - string to be search in entries + * + * @example In the Product content type, you have a entry text 'contentstack' in your content type, and you want to retrieve all the entries within this content type that have + * values for this field anywhere with 'contentstack'. + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->search('contentstack')->find(); + * + * @return Query + * */ + public function search($search = '') + { + $this->queryObject->_query = call_user_func( + 'contentstackSearch', + 'typeahead', + $this->queryObject->_query, + $search + ); + return $this->queryObject; + } + + /** + * To perform the regular expression test on the specified field + * + * @param $field_uid - field on which the regular + * expression test is going to perform + * @param $regex - Regular Expression Object + * + * @example In the Product content type, you have a field named Color ("uid":"color") in your content type, and you want to retrieve all the entries within this content type that have + * values for this field starting with 'Bl'. + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->regex('color','^B1')->find(); + * + * Now, in order to perform a case-insensitive search, you can use the $options key to specify any regular expressions options: + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->regex('color','^B1','i')->find(); + * + * @return Query + * */ + public function regex() + { + $this->subQuery = call_user_func_array( + 'contentstackRegexp', + array( + '$regex', + $this->subQuery, + func_get_args() + ) + ); + return $this->queryObject; + } + + /** + * Logical AND queries are pushed + * + * @param $query - Query Object or plain json object + * + * @example Let’s say you want to retrieve entries in which the Title field is set to 'Redmi Note + * 3' and the Color field is 'Gold'. The query to be used for such a case would be: + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $query1 = $stack->ContentType('product')->Query()->where('title', 'Redmi Note 3'); + * $query2 = $stack->ContentType('product')->Query()->where('color', 'Gold'); + * $entries = $stack->ContentType('product')->Query()->logicalAND($query1, $query2)->toJSON()->find(); + * + * @return Query + * */ + public function logicalAND() + { + $this->subQuery = call_user_func( + 'contentstackLogical', + '$and', + $this->subQuery, + func_get_args() + ); + return $this->queryObject; + } + + /** + * Logical OR queries are pushed + * + * @param $query - Query Object or plain json object + * + * @example Let’s say you want to retrieve entries in which either the value for the Color field is 'Gold' or 'Black'. + * The query to be used for such a case would be: + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $query1 = $stack->ContentType('product')->Query()->where('color', 'Black'); + * $query2 = $stack->ContentType('product')->Query()->where('color', 'Gold'); + * $entries = $stack->ContentType('product')->Query()->logicalOR($query1, $query2)->toJSON()->find(); + * + * @return Query + * */ + public function logicalOR() + { + $this->subQuery = call_user_func( + 'contentstackLogical', + '$or', + $this->subQuery, + func_get_args() + ); + return $this->queryObject; + } + + /** + * To sort the entries in ascending order of the specified field + * + * @param $field_uid - field uid to be sorted + * + * @example In the Product content type, if you wish to sort the entries with respect to their prices in ascending order. + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->ascending('price')->find(); + * + * @return Query + * */ + public function ascending($field_uid = '') + { + $this->queryObject->_query = call_user_func( + 'contentstackSorting', + 'asc', + $this->queryObject->_query, + $field_uid + ); + return $this->queryObject; + } + + /** + * To sort the entries in descending order of the specified field + * + * @param $field_uid - field uid to be sorted + * + * @example In the Product content type, if you wish to sort the entries with respect to their prices in descending order. + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->descending('price')->find(); + * + * @return Query + * */ + public function descending($field_uid = '') + { + $this->queryObject->_query = call_user_func( + 'contentstackSorting', + 'desc', + $this->queryObject->_query, + $field_uid + ); + return $this->queryObject; + } + + /** + * To check field doesn't exists + * + * @param $field_uid - field uid against the + * value not existence is checked + * + * @example In the Product content type, if we need to retrieve the data of entries of all the other fields except the Price in USD parameter. + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->notExists('price')->find(); + * + * @return Query + * */ + public function notExists($field_uid = '') + { + $this->subQuery = call_user_func( + 'contentstackExistence', + '$exists', + $this->subQuery, + $field_uid, + false + ); + return $this->queryObject; + } + + /** + * To check field exists + * + * @param $field_uid - field uid against the + * value existence is checked + * + * @example In the Product content type, if we need to retrieve the data of only the Price in USD parameter of all the entries. + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->exists('price')->find(); + * + * @return Query + * */ + public function exists($field_uid = '') + { + $this->subQuery = call_user_func( + 'contentstackExistence', + '$exists', + $this->subQuery, + $field_uid, + true + ); + return $this->queryObject; + } + + /** + * To include fallback content if specified locale content is not publish. + * + * @example + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->includeFallback()->find(); + * + * @return Query + */ + public function includeFallback() + { + $this->queryObject->_query = call_user_func( + 'contentstackAddBoolean', + 'include_fallback', + $this->queryObject->_query + ); + + return $this->queryObject; + } + + /** + * To include branch of publish content. + * + * @example + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->includeBranch()->find(); + * + * @return Query + */ + public function includeBranch() + { + $this->queryObject->_query = call_user_func( + 'contentstackAddBoolean', + 'include_branch', + $this->queryObject->_query + ); + + return $this->queryObject; + } + + /** + * To include schema along with entries + * + * @deprecated since verion 1.1.0 + * @Alternate includeContentType + * + * @example + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->includeSchema()->find(); + * + * @return Query + * */ + public function includeSchema() + { + $this->queryObject->_query = call_user_func( + 'contentstackAddBoolean', + 'include_schema', + $this->queryObject->_query + ); + + return $this->queryObject; + } + + /** + * This method includes the content type UIDs of + * the referenced entries returned in the response. + * + * @example + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->includeReferenceContentTypeUID()->find(); + * + * @return Query + * */ + public function includeReferenceContentTypeUID() + { + $this->queryObject->_query = call_user_func( + 'contentstackAddBoolean', + 'include_reference_content_type_uid', + $this->queryObject->_query + ); + return $this->queryObject; + } + + /** + * To include content_type along with entries + * + * @example + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->includeContentType()->find(); + * + * @return Query + * */ + public function includeContentType() + { + $this->queryObject->_query = call_user_func( + 'contentstackAddBoolean', + 'include_content_type', + $this->queryObject->_query + ); + return $this->queryObject; + } + + /** + * To include Embedded Items along with entries + * + * @example + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->includeEmbeddedItems()->find(); + * + * @return Query + * */ + public function includeEmbeddedItems() + { + $this->queryObject->_query = call_user_func( + 'contentstackReferences', + 'include_embedded_items', + $this->queryObject->_query, + ["BASE"] + ); + return $this->queryObject; + } + + /** + * To include the count of entries based on the results + * + * @example + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->includeCount()->find(); + * + * @return Query + * */ + public function includeCount() + { + $this->queryObject->_query = call_user_func( + 'contentstackAddBoolean', + 'include_count', + $this->queryObject->_query + ); + return $this->queryObject; + } + + /** + * To include the Metadata of entries based on the results + * + * @example + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->includeMetadata()->find(); + * + * @return Query + * */ + + + public function includeMetadata() + { + $this->queryObject->_query = call_user_func( + 'contentstackAddBoolean', + 'include_metadata', + $this->queryObject->_query + ); + return $this->queryObject; + } + + + /** + * To get only count result + * + * @example + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->count()->find(); + * + * @return Query + * */ + public function count() + { + $this->operation = __FUNCTION__; + $this->queryObject->_query = call_user_func( + 'contentstackAddBoolean', + 'count', + $this->queryObject->_query + ); + return $this->queryObject; + } + + /** + * To include the owner of entries based on the results + * + * @example + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->includeOwner()->find(); + * + * @return Query + * */ + public function includeOwner() + { + $this->queryObject->_query = call_user_func( + 'contentstackAddBoolean', + 'include_owner', + $this->queryObject->_query + ); + return $this->queryObject; + } + + /** + * To add query parameter in query + * + * @param string $key - Name of key in string + * @param string $value - Value of the key in string + * + * @example + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->addParam('include_count', 'true')->toJSON()->find(); + * + * @return Query + * */ + public function addParam($key = '', $value = '') + { + $this->queryObject->_query = call_user_func( + 'contentstackAddParam', + $key, + $this->queryObject->_query, + $value + ); + return $this->queryObject; + } + + /** + * To set the language code in the query + * + * @param $lang - Language code by default is "en-us" + * + * @example + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->language('en-us')->find(); + * + * @return Query + * */ + public function language($lang = '') + { + $this->queryObject->_query = call_user_func( + 'contentstackLanguage', + 'locale', + $this->queryObject->_query, + $lang + ); + return $this->queryObject; + } + /** + * Skip the specified number of entries from result set + * + * @param int $skip - valid number + * + * @example The skip parameter will skip a specific number of entries in the output. So, for example, if the content type contains around 12 entries + * and you want to skip the first 2 entries to get only the last 10 in the response body, you need to specify ‘2’ here. + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->skip(2)->find(); + * + * @return Query + * */ + public function skip($skip = 0) + { + $this->queryObject->_query = call_user_func( + 'contentstackPagination', + 'skip', + $this->queryObject->_query, + $skip + ); + return $this->queryObject; + } + /** + * Result set entries should have tags specified + * + * @param array $tags - array of tags you want to match in the entries tags + * + * @example + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->tags(array('Vivo','Gold'))->find(); + * + * @return Query + * */ + public function tags($tags = array()) + { + if ($tags && is_array($tags)) { + $this->queryObject->_query = call_user_func( + 'contentstackTags', + 'tags', + $this->queryObject->_query, + $tags + ); + return $this->queryObject; + } + throw contentstackCreateError('tags must be an array'); + } + + /** + * Limit the specified number of entries from result set + * + * @param int $limit - valid number + * + * @example The limit parameter will return a specific number of entries in the output. + * So for example, if the content type contains more than 100 entries and you wish to fetch only the first 2 entries, you need to specify '2' as value in this parameter. + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->limit(2)->find(); + * + * @return Query + * */ + public function limit($limit = '') + { + + $this->queryObject->_query = call_user_func( + 'contentstackPagination', + 'limit', + $this->queryObject->_query, + $limit + ); + return $this->queryObject; + } + + /** + * Query the field value from the given set of values + * + * @param string $field - field in the entry against which + * comparision needs to be done + * @param array $value - array value against which + * comparision is going to happen + * + * @example + * Example 1 - Array Equals Operator Within Group + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->containedIn('title',array('Redmi','Samsung'))->find(); + * + * + * Example 2 - Array Equals Operator Within Modular Blocks + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->containedIn("additional_info.deals.deal_name", ["Christmas Deal", "Summer Deal"])->find(); + * + * @return Query + * */ + public function containedIn($field = '', $value = array()) + { + if ($value && is_array($value)) { + $this->subQuery = call_user_func( + 'contentstackContains', + '$in', + $this->subQuery, + $field, + $value + ); + return $this->queryObject; + } + throw contentstackCreateError('value must be an array'); + } + + /** + * Query the field value other than the given set of values + * + * @param string $field - field in the entry against which + * comparision needs to be done + * @param array $value - array value against which + * comparision is going to happen + * + * @example + * Example 1 - Array Not-equals Operator Within Group + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->notContainedIn("title", ["Electronics", "Apparel"])->find(); + * + * Example 2 - Array Not-equals Operator Within Modular Blocks + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->notContainedIn("additional_info.deals.deal_name", ["Christmas Deal", "Summer Deal"]) ->find(); + * + * @return Query + * */ + public function notContainedIn($field = '', $value = array()) + { + if ($value && is_array($value)) { + $this->subQuery = call_user_func( + 'contentstackContains', + '$nin', + $this->subQuery, + $field, + $value + ); + return $this->queryObject; + } + throw contentstackCreateError('value must be an array'); + } + + /** + * Query the field which has exact value as specified + * + * @param string $key - field in the entry against which + * comparision needs to be done + * @param string $value - value against which comparision is going to happen + * + * @example In the Products content type, you have a field named Title ("uid":"title") field. If, for instance, + * you want to retrieve all the entries in which the value for the Title field is 'Redmi 3S', you can set the parameters as: + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->where('title','Redmi 3S')->find(); + * + * @return Query + * */ + public function where($key = '', $value = '') + { + if (!Utility::isEmpty($key)) { + $this->subQuery[$key] = $value; + } + return $this->queryObject; + } + + /** + * Query the field which has less value than specified one + * + * @param string $field - field in the entry against which + * comparision needs to be done + * @param string $value - value against which comparision is going to happen + * + * @example Let’s say you want to retrieve all the entries that have value of the Price in USD field set to a value that is less than but not equal to 600. You can send the parameter as: + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->lessThan('price','600')->find(); + * + * @return Query + * */ + public function lessThan($field = '', $value = '') + { + $this->subQuery = call_user_func( + 'contentstackComparision', + '$lt', + $this->subQuery, + $field, + $value + ); + return $this->queryObject; + } + + /** + * Query the field which has less or equal value than specified one + * + * @param string $field - field in the entry against which + * comparision needs to be done + * @param string $value - value against which comparision is going to happen + * + * @example Let’s say you want to retrieve all the entries that have value of the Price in USD field set to a value that is less than or equal to 146. To achieve this, send the parameter as: + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->lessThanEqualTo('price','146')->find(); + * + * @return Query + * */ + public function lessThanEqualTo($field = '', $value = '') + { + $this->subQuery = call_user_func( + 'contentstackComparision', + '$lte', + $this->subQuery, + $field, + $value + ); + return $this->queryObject; + } + + /** + * Query the field which has greater value than specified one + * + * @param string $field - field in the entry against which + * comparision needs to be done + * @param string $value - value against which comparision is going to happen + * + * @example Let’s say you want to retrieve all the entries that have value of the Price in USD field set to a value that is greater than but not equal to 146. You can send the parameter as: + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->greaterThan('price','146')->find(); + * + * @return Query + * */ + public function greaterThan($field = '', $value = '') + { + $this->subQuery = call_user_func( + 'contentstackComparision', + '$gt', + $this->subQuery, + $field, + $value + ); + return $this->queryObject; + } + + /** + * Query the field which has greater or equal value than specified one + * + * @param string $field - field in the entry against which + * comparision needs to be done + * @param string $value - value against which comparision is going to happen + * + * @example Let’s say you want to retrieve all the entries that have value of the Price in USD field set to a value that is less than and equal to 146. You can send the parameter as: + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->greaterThanEqualTo('price','146')->find(); + * + * @return Query + * */ + public function greaterThanEqualTo($field = '', $value = '') + { + $this->subQuery = call_user_func( + 'contentstackComparision', + '$gte', + $this->subQuery, + $field, + $value + ); + return $this->queryObject; + } + + /** + * Query the field which has not equal to value than specified one + * + * @param string $field - field in the entry against which + * comparision needs to be done + * @param string $value - value against which comparision is going to happen + * + * @example Let’s say you want to retrieve all the entries that have value of the Price in USD field set to a value that is not equal to 500. You can send the parameter as: + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $result = $stack->ContentType('product')->Query()->toJSON()->notEqualTo('price','500')->find(); + * + * @return Query + * */ + public function notEqualTo($field = '', $value = '') + { + $this->subQuery = call_user_func( + 'contentstackComparision', + '$ne', $this->subQuery, + $field, $value + ); + return $this->queryObject; + } + + /** + * Add Query is used to add the raw/array query to filter the entries + * + * @param array $_query - array formatted query + * + * @example + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $_set = ['vivo', 'samsung', 'redmi 3', 'apple']; + * $query1 = $stack->ContentType('product')->Query()->lessThan('title', $_set)->getQuery(); + * $_entries = $stack->ContentType('product')->Query()->addQuery($query1)->toJSON()->find(); + * + * @return Query + * */ + public function addQuery($_query = array()) + { + if ($_query && is_array($_query)) { + $this->subQuery = $_query; + return $this->queryObject; + } + throw contentstackCreateError("Provide valid query"); + } + + /** + * Get the raw/array query from the current instance of Query/Entry + * + * @example + * + * use Contentstack\Contentstack; + * $stack = Contentstack::Stack("API_KEY", "DELIVERY_TOKEN", "ENVIRONMENT"); + * $query1 = $stack->ContentType('product')->Query()->greaterThan('price', '5000')->getQuery(); + * + * @return query + * */ + public function getQuery() + { + try { + return json_decode(json_encode($this->subQuery), true); + } catch (\Exception $e) { + echo $e->getMessage(); + } + } +} \ No newline at end of file diff --git a/src/Stack/ContentType.php b/src/Stack/ContentType.php new file mode 100755 index 00000000..60690d89 --- /dev/null +++ b/src/Stack/ContentType.php @@ -0,0 +1,91 @@ + + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ + +namespace Contentstack\Stack; + +use Contentstack\Stack\ContentType\Entry; +use Contentstack\Stack\ContentType\Query; +use Contentstack\Support\Utility; +/** + * Class ContentType + * + * @category PHP + * @package Contentstack + * @author Uttam K Ukkoji + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ +#[\AllowDynamicProperties] +class ContentType +{ + + var $uid = ''; + var $stack = ''; + + /** + * ContentType + * ContentType Class to initalize your ContentType + * + * @param string $uid - valid content type uid + * @param Stack $stack - Stack Instance + * */ + public function __construct($uid = '', $stack = '') + { + $this->uid = $uid; + $this->stack = $stack; + $this->type = 'contentType'; + } + + /** + * Entry object to create the "Query" on the specified ContentType + * + * @param string $entry_uid - Entry uid to get details + * + * @return Entry + * */ + public function Entry($entry_uid = '') + { + return new Entry($entry_uid, $this); + } + + /** + * Fetch the specific contenttypes + * + * @param object $params - Parameters to fetch content + * + * @return Request + * */ + public function fetch($params = null) + { + if ($params) { + $myArray = json_decode($params, true); + $this->_query = $myArray; + } + return Utility::contentstackRequest($this->stack, $this); + } + /** + * Query object to create the "Query" on the specified ContentType + * + * @return Query + * */ + public function Query() + { + return new Query($this, $this->type); + } +} \ No newline at end of file diff --git a/src/Stack/ContentType/Entry.php b/src/Stack/ContentType/Entry.php new file mode 100755 index 00000000..d83bc6e9 --- /dev/null +++ b/src/Stack/ContentType/Entry.php @@ -0,0 +1,66 @@ + + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ + +namespace Contentstack\Stack\ContentType; + +use Contentstack\Stack\BaseQuery; +use Contentstack\Support\Utility; + +/** + * Entry + * + * @category PHP + * @package Contentstack + * @author Uttam K Ukkoji + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ +#[\AllowDynamicProperties] +class Entry extends BaseQuery +{ + var $operation; + var $_query; + var $entryUid; + var $contentType = array(); + + /** + * Entry Class to initalize your Entry + * + * @param string $entryUid - Entry to be fetched. + * @param string $contentType - contentType of Entry to be fetched. + * */ + public function __construct($entryUid = '', $contentType = '') + { + $this->entryUid = $entryUid; + parent::__construct($contentType, $this); + if (!Utility::isEmpty($entryUid)) { + return $this; + } + } + + /** + * Fetch the specified entry + * + * @return Request + * */ + public function fetch() + { + $this->operation = __FUNCTION__; + return Utility::contentstackRequest($this->contentType->stack, $this); + } +} \ No newline at end of file diff --git a/src/Stack/ContentType/Query.php b/src/Stack/ContentType/Query.php new file mode 100755 index 00000000..27b27bd9 --- /dev/null +++ b/src/Stack/ContentType/Query.php @@ -0,0 +1,84 @@ + + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ + +namespace Contentstack\Stack\ContentType; + +use Contentstack\Stack\BaseQuery; +use Contentstack\Support\Utility; + +/** + * Class Query + * + * @category PHP + * @package Contentstack + * @author Uttam K Ukkoji + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ +#[\AllowDynamicProperties] +class Query extends BaseQuery +{ + var $operation; + var $_query; + + /** + * Query Class to initalize your Query + * + * @param string $data - data for query + * @param string $type - type of query + * */ + public function __construct($data = '', $type = '') + { + $this->_query = array(); + $this->type = $type; + parent::__construct($data, $this); + } + + /** + * Get all entries based on the specified subquery + * + * @return Request + * */ + public function find() + { + $this->operation = __FUNCTION__; + if ($this->type == 'assets') { + return Utility::contentstackRequest($this->assets->stack, $this, 'assets'); + } else if ($this->type == 'contentType') { + return Utility::contentstackRequest($this->contentType->stack, $this); + } + } + + + /** + * Get single entry based on the specified subquery + * + * @deprecated since verion 1.1.0 + * + * @return Request + * */ + public function findOne() + { + $this->operation = __FUNCTION__; + $this->_query['limit'] = 1; + if ($this->type == 'assets') { + return Utility::contentstackRequest($this->assets->stack, $this, 'assets'); + } elseif ($this->type == 'contentType') { + return Utility::contentstackRequest($this->contentType->stack, $this); + } + } +} \ No newline at end of file diff --git a/src/Stack/Result.php b/src/Stack/Result.php new file mode 100755 index 00000000..2c7de795 --- /dev/null +++ b/src/Stack/Result.php @@ -0,0 +1,70 @@ + + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ +namespace Contentstack\Stack; + +/** + * Class Result + * + * @category PHP + * @package Contentstack + * @author Uttam K Ukkoji + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ +#[\AllowDynamicProperties] +class Result +{ + private $_object; + + /** + * Result constructor + * Result wrapper over the plain result for the future + * + * @param object $result - Response object + * */ + public function __construct($result = '') + { + $this->_object = $result; + + + } + + /** + * To convert result object to json + * + * @return json format of the result + * */ + public function toJSON() + { + return $this->_object; + } + + /** + * Get the keys from the object + * + * @param string $key - key whose corresponding value to be retrieved + * + * @return Value + * */ + public function get($key) + { + + return ($key && is_string($key)) ? $this->_object[$key] : null; + + } +} \ No newline at end of file diff --git a/src/Stack/Stack.php b/src/Stack/Stack.php new file mode 100755 index 00000000..c24ef04f --- /dev/null +++ b/src/Stack/Stack.php @@ -0,0 +1,364 @@ + + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ +namespace Contentstack\Stack; + +use Contentstack\Support\Utility; +use Contentstack\Stack\ContentType; +use Contentstack\Stack\Assets; + +require_once __DIR__."/../Config/index.php"; +/** + * Stack Class to initialize the provided parameter Stack + * + * @category PHP + * @package Contentstack + * @author Uttam K Ukkoji + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ +#[\AllowDynamicProperties] +class Stack +{ + /* header - array where all the headers for the request will be stored */ + var $header = array(); + /* host - Host to be used to fetch the content */ + private $host = HOST; + /* port - Port of the HOST */ + private $port = PORT; + /* protocol - Protocol to be used to fetch the content */ + private $protocol = PROTOCOL; + /* environment - Environment on which content published to be retrieved */ + private $environment; + + /** + * Constructor of the Stack + * + * @param string $api_key - API Key of Stack + * @param string $delivery_token - Delivery Token of Stack + * @param string $environment - Environment Name of Stack + * @param string $region - Region name of Contentstack. (default region 'us') + * + * */ + public function __construct( + $api_key = '', + $delivery_token = '', + $environment = '', + $config = array('region'=> 'us', 'branch'=> '', 'live_preview' => array()) + ) { + $previewHost = 'api.contentstack.io'; + if ($config && $config !== "undefined" && array_key_exists('region', $config) && $config['region'] !== "undefined" && $config['region'] !== "us" ) { + $this->host = $config['region'].'-cdn.contentstack.com'; + $previewHost = $config['region'].'-api.contentstack.com'; + } + $this->header = Utility::validateInput( + 'stack', array('api_key' => $api_key, + 'access_token' => $delivery_token, + 'environment' => $environment, + 'region' => $config['region'] ?? '', + 'branch' => $config['branch'] ?? '') + ); + $this->environment = $this->header['environment']; + unset($this->header['environment']); + $livePreview = array('enable' => false, 'host' => $previewHost); + $this->live_preview = $config['live_preview'] ? array_merge($livePreview, $config['live_preview']) : $livePreview; + $this->proxy = array_key_exists("proxy",$config) ? $config['proxy'] : array('proxy'=>array()); + $this->timeout = array_key_exists("timeout",$config) ? $config['timeout'] : '3000'; + $this->retryDelay = array_key_exists("retryDelay",$config) ? $config['retryDelay'] : '3000'; + $this->retryLimit = array_key_exists("retryLimit",$config) ? $config['retryLimit'] : '5'; + $this->errorRetry = array_key_exists("errorRetry",$config) ? $config['errorRetry'] : array('errorRetry'=>array(408, 429)); + return $this; + } + + /** + * To initialize the ContentType object from + * where the content will be fetched/retrieved. + * + * @param string $contentTypeId - valid content type + * uid relevant to configured stack + * + * @return ContentType + * */ + public function ContentType($contentTypeId = '') + { + return new ContentType($contentTypeId, $this); + } + + + /** + * Assets Class to initalize your Assets + * + * @param string $assetUid - valid asset uid relevent to configured stack + * + * @return Assets + * */ + public function Assets($assetUid = '') + { + return new Assets($assetUid, $this); + } + + + /** + * ImageTrasform function is define for image manipulation with different + * + * @param $url : Image url on which we want to manipulate. + * @param $parameters : It is an second parameter + * in which we want to place different + * manipulation key and value in array form + * + * @return string + * */ + public function ImageTrasform($url, $parameters) + { + if (is_string($url) === true && strlen($url) > 0 + && is_array($parameters) === true + && count($parameters) > 0 + ) { + $params = array(); + foreach ($parameters as $key => $value) { + array_push($params, $key . '=' .$value); + } + $params = implode("&", $params); + + $url = (strpos($url, '?') === false) + ? $url .'?'.$params: + $url .'&'.$params; + + return $url; + } else { + Utility::debug( + "Please provide valid url + and array of transformation parameters." + ); + } + } + + public function LivePreviewQuery($parameters) { + $this->live_preview['live_preview'] = $parameters['live_preview'] ?? 'init'; + $this->live_preview['content_type_uid'] = $parameters['content_type_uid'] ?? null; + $this->live_preview['entry_uid'] = $parameters['entry_uid'] ?? null; + if(array_key_exists('content_type_uid',$parameters) && array_key_exists('entry_uid',$parameters)){ + + $this->ContentType($parameters['content_type_uid'])->Entry($parameters['entry_uid'])->fetch(); + } + } + + /** + * To get the last_activity information of the + * configured environment from all the content types + * + * @return Result + * */ + public function getLastActivities() + { + $this->_query = array("only_last_activity" => "true"); + return Utility::getLastActivites($this); + } + + /** + * To set the host on stack object + * + * @param string $host - host name/ipaddress from where the content to be fetched + * + * @return Stack + * */ + public function setHost($host = '') + { + Utility::validateInput('host', $host); + $this->host = $host; + return $this; + } + /** + * This function returns host. + * + * @return string + * */ + public function getHost() + { + return $this->host; + } + /** + * This function sets protocol. + * + * @param string $protocol - protocol type + * + * @return Stack + * */ + public function setProtocol($protocol = '') + { + Utility::validateInput('protocol', $protocol); + $this->protocol = $protocol; + return $this; + } + /** + * This function return protocol type. + * + * @return string + * */ + public function getProtocol() + { + return $this->protocol; + } + /** + * This function sets Port. + * + * @param string $port - Port Number + * + * @return Stack + * */ + public function setPort($port = '') + { + Utility::validateInput('port', $port); + $this->port = $port; + return $this; + } + + /** + * This function return Port. + * + * @return string + * */ + public function getPort() + { + return $this->port; + } + + /** + * This function sets API Key. + * + * @param string $api_key - API Key + * + * @return Stack + * */ + public function setAPIKEY($api_key = '') + { + Utility::validateInput('api_key', $api_key); + $this->header['api_key'] = $api_key; + return $this; + } + /** + * This function sets Delivery Token. + * + * @param string $delivery_token - Delivery Token + * + * @return Stack + * */ + public function setDeliveryToken($delivery_token = '') + { + Utility::validateInput('access_token', $delivery_token); + $this->header['access_token'] = $delivery_token; + return $this; + } + + /** + * This function sets environment name. + * + * @param string $environment - Name of Environment + * + * @return Stack + * */ + public function setEnvironment($environment = '') + { + Utility::validateInput('environment', $environment); + $this->environment = $environment; + return $this; + } + + /** + * This function returns API Key. + * + * @return string + * */ + public function getAPIKEY() + { + return $this->header['api_key']; + } + /** + * This function returns Delivery Token. + * + * @return string + * */ + public function DeliveryToken() + { + return $this->header['access_token']; + } + /** + * This function returns environment name. + * + * @return string + * */ + public function getEnvironment() + { + return $this->environment; + } + + /** + * This function sets Branch. + * + * @param string $branch - Name of branch + * + * @return Stack + * */ + public function setBranch($branch = '') + { + Utility::validateInput('branch', $branch); + $this->header['branch'] = $branch; + return $this; + } + + /** + * This function returns Branch. + * + * @return string + * */ + public function Branch() + { + return $this->header['branch']; + } + + /** + * This call returns comprehensive information of all + * the content types available in a particular stack in your account. + * + * @param object $params - query params for getting content-type. + * + * @return Stack + * */ + public function getContentTypes($params) + { + if ($params && $params !== "undefined") { + $myArray = json_decode($params, true); + $this->_query = $myArray; + } + + return Utility::contentstackRequest($this, $this, "getcontentTypes"); + } + + /** + * Syncs your Contentstack data with your app and ensures that the data is always up-to-date by providing delta updates + * + * @param object $params - params is an object that supports ‘locale’, ‘start_date’, ‘content_type_uid’, and ‘type’ queries. + * + * @return Stack + * */ + public function sync($params) + { + if ($params && $params !== "undefined") { + $this->_query = $params; + } + return Utility::contentstackRequest($this, $this, "sync"); + } +} \ No newline at end of file diff --git a/src/Support/Utility.php b/src/Support/Utility.php new file mode 100755 index 00000000..03fe937a --- /dev/null +++ b/src/Support/Utility.php @@ -0,0 +1,558 @@ + + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ +namespace Contentstack\Support; + +use Contentstack\Error\CSException; +use Contentstack\Stack\Result; + +/** + * Utility/Helper where all the helper and utility functions will be available. + * + * @category PHP + * @package Contentstack + * @author Uttam K Ukkoji + * @author Rohit Mishra + * @copyright 2012-2021 Contentstack. All Rights Reserved + * @license https://github.com/contentstack/contentstack-php/blob/master/LICENSE.txt MIT Licence + * @link https://pear.php.net/package/contentstack + * */ +#[\AllowDynamicProperties] +class Utility +{ + /** + * Validation for all the parameters required for the SDK + * + * @param string $type - type of the value to be validated + * @param object $input - value of the respective type + * + * @return array + * */ + public static function validateInput($type = '', $input = array()) + { + $msg = ''; + try { + switch ($type) { + case 'stack' : + if ($input['region']) { + if (!(Utility::isKeySet($input, 'api_key') + && Utility::isKeySet($input, 'access_token') + && Utility::isKeySet($input, 'environment') + && Utility::isKeySet($input, 'region')) + ) { + $msg = 'Please provide valid api_key, + access_token, + environment and region'; + } + break; + } else { + if (!(Utility::isKeySet($input, 'api_key') + && Utility::isKeySet($input, 'access_token') + && Utility::isKeySet($input, 'environment')) + ) { + $msg = 'Please provide valid api_key, + access_token and environment'; + } + break; + } + + case 'port' : + if (Utility::isEmpty($input) || !is_numeric($input)) { + $msg = 'Please provide valid string for '.$type; + } + break; + case 'protocol' : + if (Utility::isEmpty($input) + || !is_string($input) + || !array_search($input, array('http', 'https')) + ) { + $msg = 'Please provide valid string for ' + .$type.' And it should be either http or https'; + } + break; + case 'host' : + case 'access_token' : + case 'environment' : + case 'api_key' : + if (Utility::isEmpty($input) || !is_string($input)) { + $msg = 'Please provide valid string for '.$type; + } + break; + } + if (!Utility::isEmpty($msg)) { + throw new \Exception($msg); + } + return $input; + } catch (\Exception $e) { + echo "Validation Exception: ".$e->getMessage(); + throw new \Exception($e->getMessage()); + } + } + + public static function isLivePreview($query) { + if ($query && isset($query->contentType)) { + return ($query->contentType->stack->live_preview['enable'] == true && array_key_exists('content_type_uid', $query->contentType->stack->live_preview) && strcmp($query->contentType->uid, $query->contentType->stack->live_preview['content_type_uid']) == 0); + } + return false; + } + + /** + * Get the domain from the current object + * + * @param Stack $query - Instance of S.tack + * + * @return String + * */ + public static function getDomain($query) + { + $stack = $query; + if ($query && isset($query->contentType)) { + $stack = $query->contentType->stack; + } + if ($query && isset($query->stack)) { + $stack = $query->stack; + } + if ($query && isset($query->assets)) { + $stack = $query->assets->stack; + } + $host = $stack->getHost(); + if (Utility::isLivePreview($query)) { + $host = $stack->live_preview['host']; + } + return $stack->getProtocol() + .'://'.$host + .':' + .$stack->getPort().VERSION; + } + + /** + * Contentstack URL method to create the url based on the request + * + * @param object $queryObject - Query Object + * @param string $type - type for url + * + * @return string + * */ + public static function contentstackUrl($queryObject = '', $type = '') + { + $URL = ''; + switch ($type) { + case 'set_environment': + if (!Utility::isLivePreview($queryObject)) { + $URL = Utility::getDomain($queryObject).ENVIRONMENTS.'' + .$queryObject->contentType->stack->getEnvironment(); + } + break; + case 'get_last_activites': + $URL = Utility::getDomain($queryObject).CONTENT_TYPES; + break; + case 'getcontentTypes': + $URL = Utility::getDomain($queryObject).CONTENT_TYPES; + break; + case 'asset': + $URL = Utility::getDomain($queryObject).ASSETS.$queryObject->assetUid; + break; + case 'assets': + $URL = Utility::getDomain($queryObject).ASSETS; + break; + case 'sync': + $URL = Utility::getDomain($queryObject).SYNC; + break; + default: + $URL = Utility::getDomain($queryObject).CONTENT_TYPES + .$queryObject->contentType->uid.ENTRIES; + if (isset($queryObject->entryUid)) { + $URL.=$queryObject->entryUid; + } + } + + $queryParams = Utility::generateQueryParams($queryObject); + return $URL.'?'.$queryParams; + + } + + /** + * Header transformation as it required format + * + * @param array $query - input headers in key value pair + * + * @return array + * */ + public static function headers($query = '') + { + $headers = array(); + if ($query) { + if (isset($query->header)) { + $headers = $query->header; + } elseif ($query && isset($query->stack)) { + $headers = $query->stack->header; + } elseif ($query && isset($query->contentType)) { + $headers = $query->contentType->stack->header; + } else { + $headers = $query->assets->stack->header; + } + } + return $headers; + } + + /** + * POST formatted query for the API server + * + * @param array $query - Query array + * + * @return json + * */ + public static function generateQuery($query = array()) + { + $result = array(); + if (isset($query->contentType)) { + $query->_query['environment'] = $query->contentType + ->stack->getEnvironment(); + $subQuery = array(); + if (count($query->subQuery) > 0) { + $subQuery['query'] = json_encode($query->subQuery); + } + + $include_schema = array_search( + 'include_schema', + array_keys($query->_query) + ); + $include_content_type = array_search( + 'include_content_type', + array_keys($query->_query) + ); + + if ($include_schema < $include_content_type) { + foreach ($query->_query as $key => $value) { + if ($key == 'include_schema') { + unset($query->_query['include_schema']); + $query->_query["include_schema"] = "true"; + } + } + } + + $result = array_merge($query->_query, $subQuery); + } elseif (isset($query->stack)) { + $query->_query['environment'] = $query->stack->getEnvironment(); + $result = array_merge($result, $query->_query); + + } elseif (isset($query->assets)) { + $query->_query['environment'] = $query->assets->stack->getEnvironment(); + $subQuery = array(); + if (count($query->subQuery) > 0) { + $subQuery['query'] = json_encode($query->subQuery); + } + $result = array_merge($query->_query, $subQuery); + } else { + $query->_query['environment'] = $query->getEnvironment(); + $result = array_merge($result, $query->_query); + } + return $result; + } + + /** + * Sending the GET requests with all the parameters in POST as well as GET + * + * @param array $query - Query array + * + * @return QueryParameters + * */ + public static function generateQueryParams($query = array()) + { + $result = Utility::generateQuery($query); + return http_build_query($result); + } + + /** + * Wrap Result + * + * @param object $result - Response content + * @param object $queryObject - Query object + * + * @return ResultWrapped Object + * */ + public static function wrapResult($result = '', $queryObject = '') + { + $result = $wrapper = json_decode($result, true); + if ($result && $queryObject && isset($queryObject->operation)) { + $flag = (isset($queryObject->json_translate) + && $queryObject->json_translate); + switch ($queryObject->operation) { + case 'findOne': + if (Utility::isKeySet($result, 'entries') + && count($result['entries']) > 0 + ) { + $wrapper = ($flag) ? $result['entries'][0] : + new Result( + $result['entries'][0] + ); + } else { + $wrapper = json_encode( + array( + "error_code" => 119, + "error_message" => "The requested entry doesn't exists" + ) + ); + } + break; + case 'fetch': + if (Utility::isKeySet($result, 'entry')) { + $wrapper = (!$flag) ? + new Result( + $result['entry'] + ) + : $result['entry']; + } elseif (Utility::isKeySet($result, 'asset')) { + $wrapper = (!$flag) ? + new Result( + $result['asset'] + ) + : $result['asset']; + } elseif (Utility::isKeySet($result, 'schema')) { + array_push($wrapper, $result['schema']); + } elseif (Utility::isKeySet($result, 'content_type')) { + array_push($wrapper, $result['content_type']); + } + break; + case 'find': + $wrapper = array(); + if (Utility::isKeySet($result, 'entries')) { + if (!is_numeric($result['entries'])) { + for ($i = 0, + $_i = count($result['entries']); + $i < $_i && !$flag; $i++) { + $result['entries'][$i] = new Result( + $result['entries'][$i] + ); + } + } + array_push($wrapper, $result['entries']); + } + if (Utility::isKeySet($result, 'assets')) { + if (!is_numeric($result['assets'])) { + for ($i = 0, + $_i = count($result['assets']); + $i < $_i && !$flag; $i++ + ) { + $result['assets'][$i] = new Result( + $result['assets'][$i] + ); + } + } + array_push($wrapper, $result['assets']); + } + + if (Utility::isKeySet($result, 'schema')) { + array_push($wrapper, $result['schema']); + } + if (Utility::isKeySet($result, 'content_type')) { + array_push($wrapper, $result['content_type']); + } + if (Utility::isKeySet($result, 'count')) { + array_push($wrapper, $result['count']); + } + break; + } + } + return $wrapper; + } + + /** + * Contentstack request to the API server based on the data + * + * @param object $queryObject - Query Object + * @param object $type - type of request + * + * @return Result + * */ + public static function contentstackRequest($stack, $queryObject = '', $type = '', $count = 0) + { + $server_output = ''; + STATIC $live_response_decode = ''; + STATIC $entry_uid = ''; + STATIC $content_type_uid = ''; + + $retryDelay = $stack->retryDelay; + $retryLimit = $stack->retryLimit; + $errorRetry = $stack->errorRetry; + if ($queryObject) { + if (Utility::isLivePreview($queryObject)) { + $queryObject->_query['live_preview'] = ($queryObject->contentType->stack->live_preview['live_preview'] ?? 'init'); + } + $http = curl_init(Utility::contentstackUrl($queryObject, $type)); + + // setting the HTTP Headers + $Headers = Utility::headers($queryObject); + + $request_headers = array(); + $request_headers[] = 'x-user-agent: contentstack-php/2.3.1'; + $request_headers[] = 'api_key: '.$Headers["api_key"]; + if (Utility::isLivePreview($queryObject)) { + $request_headers[] = 'authorization: '.$queryObject->contentType->stack->live_preview['management_token'] ; + }else { + $request_headers[] = 'access_token: '.$Headers["access_token"]; + } + if ($Headers["branch"] !== '' && $Headers["branch"] !== "undefined") { + $request_headers[] = 'branch: '.$Headers["branch"]; + } + + $proxy_details = $stack->proxy; + $timeout = $stack->timeout; + + curl_setopt($http, CURLOPT_HTTPHEADER, $request_headers); + + curl_setopt($http, CURLOPT_HEADER, false); + // setting the GET request + curl_setopt($http, CURLOPT_CUSTOMREQUEST, "GET"); + // receive server response ... + curl_setopt($http, CURLOPT_RETURNTRANSFER, true); + // set the cURL time out + curl_setopt($http, CURLOPT_TIMEOUT_MS, $timeout); + + if(array_key_exists("url",$proxy_details) && array_key_exists("port",$proxy_details)){ + if($proxy_details['url'] != '' && $proxy_details['port'] != '') { + + // Set the proxy IP + curl_setopt($http, CURLOPT_PROXY, $proxy_details['url']); + // Set the port + curl_setopt($http, CURLOPT_PROXYPORT, $proxy_details['port']); + + if(array_key_exists("username",$proxy_details) && array_key_exists("password",$proxy_details)){ + if($proxy_details['username'] != '' && $proxy_details['password'] != '') { + + $proxyauth = $proxy_details['username'].":".$proxy_details['password']; + // Set the username and password + curl_setopt($http, CURLOPT_PROXYUSERPWD, $proxyauth); + + } + } + } + } + + $response = curl_exec($http); + // status code extraction + $httpcode = curl_getinfo($http, CURLINFO_HTTP_CODE); + + // close the curl + curl_close($http); + + if(in_array($httpcode,$errorRetry)){ + if($count < $retryLimit){ + $retryDelay = round($retryDelay/1000); //converting retry_delay from milliseconds into seconds + sleep($retryDelay); //sleep method requires time in seconds + $count += 1; + return Utility::contentstackRequest($stack, $queryObject, $type, $count); + } + } else { + if ($httpcode > 199 && $httpcode < 300) { + if (!Utility::isLivePreview($queryObject)) { + $result = json_decode($response, true); + Utility::to_render_content($result, $entry_uid, $live_response_decode); + $response = json_encode($result, true); + + } + else + { + $entry_uid = $queryObject->entryUid; + $content_type_uid = $queryObject->contentType->uid; + $response_decode = json_decode($response, true); + if (Utility::isKeySet($response_decode, 'entry')) { + $live_response_decode = $response_decode['entry']; + } + else{ + $live_response_decode = $response_decode; + } + } + // wrapper the server result + $response = Utility::wrapResult($response, $queryObject); + } + else{ + throw new CSException($response, $httpcode); + } + } + } + + return $response; + } + + + public static function to_render_content(&$resp, $entry_uid, $live_response_decode ){ + if (is_array($resp)) { + if(array_key_exists('uid', $resp) && $resp['uid'] == $entry_uid){ + $resp = $live_response_decode; + }else + { + foreach ($resp as $key => $value) { + Utility::to_render_content($resp[$key], $entry_uid, $live_response_decode); + } + } + } + } + + + /** + * Validate the key is set or not + * + * @param array $input - input + * @param string $key - key to check + * + * @return boolean + * */ + public static function isKeySet($input = array(), $key = '') + { + return ($key && isset($input[$key])) ? true : false; + } + + /** + * Validate the String + * + * @param object $input - object to check for empty + * + * @return boolean + * */ + public static function isEmpty($input) + { + return (empty($input)); + } + + /** + * Get Last activities + * + * @param object $queryObject - query object + * + * @return object + * */ + public static function getLastActivites($queryObject) + { + return request($queryObject, 'get_last_activites'); + } + + /** + * DEBUGGING MESSAGE + * + * @param object $input - object to debug + * @param boolean $exit - to exit on debug + * + * @return object + * */ + public static function debug($input, $exit = false) + { + echo "
";
+            print_r($input);
+        echo "
"; + if ($exit) { + exit(); + } + } +} \ No newline at end of file diff --git a/src/Support/helper.php b/src/Support/helper.php new file mode 100755 index 00000000..04a08384 --- /dev/null +++ b/src/Support/helper.php @@ -0,0 +1,307 @@ + 2) { + return $stack[3]['function']; + } + return $stack[0]['function']; + } +} + +if(!function_exists('contentstackCreateError')) { + /* + * Create exception object based on messages + * @param + * string|msg - Exception message to be delivered + * @return Exception + * */ + function contentstackCreateError($msg = '') { + if(!Utility::isEmpty($msg)) return new Exception($msg); + } +} + +if (!function_exists('contentstackSearch')) { + /* + * search + * search + * @param + * $operator - query operator + * $query - Query object + * $value - value to be search + * @return $query + * */ + function contentstackSearch($operator = '', $query = array(), $value = '') { + if(!(!Utility::isEmpty($value) && is_string($value))) + throw contentstackCreateError('Invalid input for "'.contentstackGetFunctionName().'". String value expected.'); + $query[$operator] = $value; + return $query; + } +} + +if (!function_exists('contentstackReferences')) { + /* + * contentstackReferences + * contentstackReferences + * @param + * $query - Query object + * $values - array of fields to be included in the result set + * @return $query + * */ + function contentstackReferences($operator = '', $query = array(), $value = array()) { + if(!is_array($value)) + throw contentstackCreateError('Invalid input for includeReferences. Array expected.'); + $query[$operator] = $value; + return $query; + } +} + +if (!function_exists('contentstackProjection')) { + /* + * projection + * projection + * @param + * $query - Query object + * $values - array of fields to be included in the result set + * @return $query + * */ + function contentstackProjection($operator = '', $query = array(), $level = 'BASE', $value = array()) { + if(is_array($level)) { + $value = $level; + $level = 'BASE'; + } + if(!(!Utility::isEmpty($level) && is_string($level) && is_array($value))) throw contentstackCreateError('Invalid Input'); + if(!Utility::isKeySet($query, $operator)) $query[$operator] = array(); + if(!Utility::isKeySet($query[$operator], $level)) $query[$operator][$level] = array(); + $query[$operator][$level] = array_merge($query[$operator][$level], $value); + return $query; + } +} + +if (!function_exists('contentstackRegexp')) { + /* + * contentstackRegexp + * contentstackRegexp + * @param + * $operator - query operator + * $query - Query object + * $key - key of the query + * $value - value to be set against key + * $options - options for the regular expression + * @return $query + * */ + function contentstackRegexp($operator = '', $query = array(), $values = array()) { + if(count($values) === 2 || count($values) === 3) { + if(Utility::isEmpty($values[0]) && Utility::isEmpty($values[1]) && is_string($values[0]) && is_string($values[1])) + throw contentstackCreateError('Invalid input for regex.Key must be string and value must be valid RegularExpression'); + if(isset($values[2]) && !(is_string($values[2]) && strlen($values[2]) > 0)) { + throw contentstackCreateError('Invalid options for regex. Please provide the valid options'); + } + $query[$values[0]] = array($operator => $values[1]); + if(isset($values[2])) + $query[$values[0]]['$options'] = $values[2]; + return $query; + } else { + throw contentstackCreateError('Invalid input for regex. At least 2 or maximum 3 arguments are required.'); + } + } +} + +if (!function_exists('contentstackTags')) { + /* + * contentstackTags + * contentstackTags + * @param + * $operator - query operator + * $query - Query object + * $value - array of tags + * @return $query + * */ + function contentstackTags($operator = '', $query = array(), $value = '') { + if(!(is_array($value) && count($value) > 0)) + throw contentstackCreateError('Invalid input for tags.Value must be valid array of tags'); + $query[$operator] = $value; + return $query; + } +} + + +if (!function_exists('contentstackComparision')) { + /* + * comparision + * comparision + * @param + * $operator - query operator + * $query - Query object + * $key - key of the query + * $value - value to be set against key + * @return $query + * */ + function contentstackComparision($operator = '', $query = array(), $key = '', $value = '') { + if(!(!Utility::isEmpty($key) && is_string($key) && !Utility::isEmpty($value))) + throw contentstackCreateError('Invalid input for "'.contentstackGetFunctionName().'". Key must be string and value should be valid not empty.'); + $query[$key] = array($operator => $value); + return $query; + } +} + +if (!function_exists('contentstackLogical')) { + /* + * logical + * logical operations + * @param + * $operator - query operator + * $query - Query object + * $value - array of Query object or json query + * @return $query + * @ignore + * */ + function contentstackLogical($operator = '', $query = array(), $value = array()) { + if(!(is_array($value) && count($value) > 0)) + throw contentstackCreateError('Invalid input for "'.contentstackGetFunctionName().'". At least one Query or array object is expected'); + foreach($value as $key => $_qry) { + if(!Utility::isKeySet($query, $operator)) $query[$operator] = array(); + if($_qry instanceof \Contentstack\Stack\BaseQuery) + array_push($query[$operator], $_qry->subQuery); + else if(is_array($_qry)) + array_push($query[$operator], $_qry); + else { + unset($query[$operator]); + throw contentstackCreateError('Query objects are expected as arguments'); + } + } + return $query; + } +} + +if (!function_exists('contentstackContains')) { + /* + * contains + * contains + * @param + * $operator - query operator + * $query - Query object + * $key - key of the query + * $value - array of value to be set against key + * @return $query + * */ + function contentstackContains($operator = '', $query = array(), $key = '', $value = array()) { + if (!(!Utility::isEmpty($key) && is_string($key) && is_array($value))) + throw contentstackCreateError('Invalid input for "'.contentstackGetFunctionName().'". Key should be string and value must be array.'); + $query[$key] = array($operator => $value); + return $query; + } +} + +if (!function_exists('contentstackPagination')) { + /* + * pagination + * Creates the skip and limit parameters + * @param + * $operator - key of the query + * $query - Query object + * $value - value to be set against key + * @return $query + * */ + function contentstackPagination($operator = '', $query = array(), $value = '') { + if (!(!Utility::isEmpty($value) && is_numeric($value))) + throw contentstackCreateError('Invalid input for "'.contentstackGetFunctionName().'", it should be Numeric.'); + $query[$operator] = $value; + return $query; + } +} + +if (!function_exists('contentstackLanguage')) { + /* + * language + * Set the locale on the Query + * @param + * $operator - key of the query + * $query - Query object + * $value - value to be set against key + * @return $query + * */ + function contentstackLanguage($operator = '', $query = array(), $value = '') { + + if (!(!Utility::isEmpty($value) && is_string($value))) + throw contentstackCreateError('Invalid input for "'.contentstackGetFunctionName().'", it should be String.'); + $query[$operator] = $value; + return $query; + } +} + +if (!function_exists('contentstackSorting')) { + /* + * sort + * sort the field based on the query + * @param + * $operator - key of the query + * $query - Query object + * $field_uid - field_uid which is to be use for sorting + * @return $query + * */ + function contentstackSorting($operator = '', $query = array(), $key = '') { + if (!(!Utility::isEmpty($key) && is_string($key))) + throw contentstackCreateError('Invalid input for "'.contentstackGetFunctionName().'". Value should be valid field in entry'); + $query[$operator] = $key; + return $query; + } +} + +if (!function_exists('contentstackAddBoolean')) { + /* + * addBoolean + * Set the boolean parameter on the Query + * @param + * $operator - key of the query + * $query - Query object + * $value - value to be set against key + * @return $query + * */ + function contentstackAddBoolean($operator = '', $query = array()) { + $query[$operator] = 'true'; + return $query; + } +} + +if (!function_exists('contentstackAddParam')) { + /* + * AddParam + * Set the locale on the Query + * @param + * $operator - key of the query + * $query - Query object + * $value - value to be set against key + * @return $query + * */ + function contentstackAddParam($key = '', $query = array(), $value = '') { + $query[$key] = $value; + return $query; + } +} + +if (!function_exists('contentstackExistence')) { + /* + * existence + * Set the boolean parameter on the Query + * @param + * $operator - $operator of the query + * $query - Query object + * $key - field_uid against which query to be checked + * $value - value to be set against key + * @return $query + * */ + function contentstackExistence($operator = '', $query = array(), $key = '', $value = false) { + if (!(!Utility::isEmpty($key) && is_string($key))) + throw contentstackCreateError('Invalid input for "'.contentstackGetFunctionName().'". Key should be valid String field uid'); + $query[$key] = array($operator => $value); + return $query; + } +} \ No newline at end of file diff --git a/test/AssetsTest.php b/test/AssetsTest.php new file mode 100755 index 00000000..5198642b --- /dev/null +++ b/test/AssetsTest.php @@ -0,0 +1,415 @@ +getAPIKEY(), self::$rest->getAccessToken(), self::$rest->getEnvironmentName()); + if (self::$rest->getHost() !== NULL) { + self::$Stack->setHost(self::$rest->getHost()); + } + } + /* + * Tear Down after the test suites executes + */ + public static function tearDownAfterClass() : void{ + if(ENV !== 'TEST_LOCAL') { + // self::$rest->deleteStack(); + } + } + + public function testAssetsFind() { + $_assets = self::$Stack->Assets()->Query()->toJSON()->find(); + $this->assertArrayHasKey(0, $_assets); + $this->assertTrue(checkAssetsSorting($_assets[0])); + } + + public function testAssetsFetch() { + $_object = self::$Stack->Assets()->Query()->toJSON()->find(); + $_title = $_object[0][0]['title']; + $_uid = $_object[0][0]['uid']; + $_asset = self::$Stack->Assets($_uid)->fetch(); + $this->assertEquals($_asset->get('title'), $_title); + } + + public function testAssetsFindSkip() { + $_assets1 = self::$Stack->Assets()->Query()->toJSON()->find(); + $this->assertArrayHasKey(0, $_assets1); + $assets_count = count($_assets1[0]); + $this->assertTrue((count($_assets1[0]) === $assets_count)); + $skip = 1; + $_assets = self::$Stack->Assets()->Query()->toJSON()->skip($skip)->find(); + $this->assertArrayHasKey(0, $_assets); + $this->assertTrue((count($_assets[0]) === $assets_count - $skip)); + $this->assertTrue(checkAssetsSorting($_assets[0])); + $this->assertEquals($_assets[0], array_slice($_assets1[0], $skip)); + } + + public function testAssetsFindSkipLimit() { + $_assets1 = self::$Stack->Assets()->Query()->toJSON()->find(); + $this->assertArrayHasKey(0, $_assets1); + $limit = 2; + $skip = 1; + $_assets = self::$Stack->Assets()->Query()->toJSON()->skip($skip)->limit($limit)->find(); + $this->assertArrayHasKey(0, $_assets); + $this->assertTrue((count($_assets[0]) === $limit)); + $this->assertTrue(checkAssetsSorting($_assets[0])); + $this->assertEquals($_assets[0], array_slice($_assets1[0], $skip, $limit)); + } + + public function testAssetsFindLimit() { + $limit = 1; + $_assets = self::$Stack->Assets()->Query()->toJSON()->limit($limit)->find(); + $this->assertArrayHasKey(0, $_assets); + $this->assertTrue((count($_assets[0])) === $limit); + $this->assertTrue(checkAssetsSorting($_assets[0])); + } + + public function testAssetsAddParam() { + $_assets = self::$Stack->Assets()->Query()->addParam('include_dimension', 'true')->toJSON()->find(); + $this->assertTrue(array_key_exists('dimension', $_assets[0][0])); + } + + + public function testAssetsFindCount() { + $_assets = self::$Stack->Assets()->Query()->toJSON()->count()->find(); + $assets = self::$Stack->Assets()->Query()->toJSON()->find(); + $assets_count = count($assets[0]); + $this->assertArrayHasKey(0, $_assets); + $this->assertTrue(($_assets[0]) === $assets_count); + } + + public function testIncludeFallback() { + $testArray = array("a"=>"en-us", "b" => "hi-in"); + $_assets = self::$Stack->Assets()->Query()->toJSON()->language("hi-in")->includeFallback()->find(); + $this->assertEquals(count($_assets[0]), 3); + for($i = 0; $i < count($_assets[0]); $i++) { + $this->assertContains($_assets[0][$i]["publish_details"]["locale"], $testArray); + } + } + + public function testWithoutIncludeFallback() { + $_assets = self::$Stack->Assets()->Query()->toJSON()->language("hi-in")->find(); + $this->assertArrayHasKey(0, $_assets); + $this->assertEquals(count($_assets[0]), 1); + for($i = 0; $i < count($_assets[0]); $i++) { + $this->assertEquals($_assets[0][$i]["publish_details"]["locale"], "hi-in"); + } + } + + public function testAssetsFindIncludeCount() { + $_assets = self::$Stack->Assets()->Query()->toJSON()->includeCount()->find(); + $assets = self::$Stack->Assets()->Query()->toJSON()->find(); + $assets_count = count($assets[0]); + $this->assertArrayHasKey(0, $_assets); + $this->assertArrayHasKey(1, $_assets); + $this->assertTrue((count($_assets[0]) === $assets_count)); + if(($_assets[1]) > 0 ) { + $this->assertTrue(($_assets[1] === $assets_count)); + } else { + $this->assertTrue(('0')); + } + } + + public function testAssetsFindWhere() { + $_assets = self::$Stack->Assets()->Query()->toJSON()->find(); + $_assetsUid = $_assets[0][0]['uid']; + $assets = self::$Stack->Assets()->Query()->toJSON()->where('uid', $_assetsUid)->find(); + $this->assertArrayHasKey(0, $assets); + $this->assertArrayHasKey(0, $assets[0]); + $this->assertTrue(($assets[0][0]['uid'] === $_assetsUid)); + } + + public function testAssetsFindContainedIn() { + $_set = ['image/jpeg', 'image/jpg']; + $assets = self::$Stack->Assets()->Query()->toJSON()->containedIn('content_type', $_set)->find(); + $this->assertArrayHasKey(0, $assets); + if(count($assets[0]) !== 0){ + foreach ($assets[0] as $key => $val) { + $this->assertTrue((array_search($assets[0][$key]['content_type'], $_set) !== false)); + } + } else { + $this->assertTrue('0'); + } + } + + public function testAssetsFindNotContainedIn() { + $_set = ['image/jpg']; + $assets= self::$Stack->Assets()->Query()->toJSON()->notContainedIn('content_type', $_set)->find(); + $this->assertArrayHasKey(0, $assets); + if(count($assets[0]) !== 0){ + foreach ($assets[0] as $key => $val) { + $this->assertTrue((array_search($assets[0][$key]['content_type'], $_set) === false)); + } + } else { + $this->assertTrue('0'); + } + } + + public function testAssetsFindAscending() { + $field = 'created_at'; + $_assets = self::$Stack->Assets()->Query()->toJSON()->ascending('created_at')->find(); + $assets = self::$Stack->Assets()->Query()->toJSON()->find(); + $assets_count = count($assets[0]); + $this->assertArrayHasKey(0, $_assets); + $this->assertTrue((count($_assets[0]) === $assets_count)); + $this->assertTrue(checkassetsSorting($_assets[0], $field, 'asc')); + } + + public function testAssetsFindDescending() { + $field = 'created_at'; + $_assets = self::$Stack->Assets()->Query()->toJSON()->descending('created_at')->find(); + $assets = self::$Stack->Assets()->Query()->toJSON()->find(); + $assets_count = count($assets[0]); + $this->assertArrayHasKey(0, $_assets); + $this->assertTrue((count($_assets[0]) === $assets_count)); + $this->assertTrue(checkassetsSorting($_assets[0], $field, 'desc')); + } + + public function testAssetsFindLessThan() { + $_set = 7575; + $assets = self::$Stack->Assets()->Query()->toJSON()->lessThan('file_size', $_set)->find(); + $this->assertArrayHasKey(0, $assets); + if(count($assets[0]) !== 0){ + foreach ($assets[0] as $key => $val) { + $this->assertTrue(($assets[0][$key]['file_size'] < $_set)); + } + } else { + $this->assertTrue('0'); + } + } + + public function testAssetsFindLessThanEqualTo() { + $_set = 12000; + $assets = self::$Stack->Assets()->Query()->toJSON()->lessThanEqualTo('file_size', $_set)->find(); + $this->assertArrayHasKey(0, $assets); + if(count($assets[0]) !== 0) { + foreach ($assets[0] as $key => $val) { + //$this->assertTrue(($assets[0][$key]['file_size'] <= $_set)); + } + } else { + $this->assertTrue('0'); + } + } + + public function testAssetsFindGreaterThan() { + $_set = 12; + $assets = self::$Stack->Assets()->Query()->toJSON()->greaterThan('file_size', $_set)->find(); + $this->assertArrayHasKey(0, $assets); + if(count($assets[0]) !== 0) { + foreach ($assets[0] as $key => $val) { + $this->assertTrue(($assets[0][$key]['file_size'] > $_set)); + } + } else { + $this->assertTrue('0'); + } + } + + + public function testAssetsFindGreaterThanEqualTo() { + $_set = 7575; + $assets = self::$Stack->Assets()->Query()->toJSON()->greaterThanEqualTo('file_size', $_set)->find(); + $this->assertArrayHasKey(0, $assets); + if(count($assets[0]) !== 0) { + foreach ($assets[0] as $key => $val) { + $this->assertTrue(($assets[0][$key]['file_size'] >= $_set)); + } + } else { + $this->assertTrue('0'); + } + } + + public function testAssetsFindNotEqualTo() { + $_set = 7575; + $_assets = self::$Stack->Assets()->Query()->toJSON()->find(); + $_assets_count = count($_assets[0]) - 1; + $assets = self::$Stack->Assets()->Query()->toJSON()->notEqualTo('file_size', $_set)->find(); + $this->assertArrayHasKey(0, $assets); + // $this->assertTrue((count($assets[0]) === $_assets_count)); + foreach ($assets[0] as $key => $val) { + $this->assertTrue(($assets[0][$key]['file_size'] !== $_set)); + } + } + + public function testAssetsFindExists() { + $_assets = self::$Stack->Assets()->Query()->toJSON()->find(); + $_assets_count = count($_assets[0]); + $assets = self::$Stack->Assets()->Query()->toJSON()->exists('title')->find(); + $this->assertArrayHasKey(0, $assets); + $this->assertTrue((count($assets[0]) === $_assets_count)); + if(count($_assets[0]) !== 0) { + foreach ($assets[0] as $key => $val) { + $this->assertTrue(isset($assets[0][$key]['title'])); + } + } else { + $this->assertTrue('0'); + } + } + + public function testAssetsFindNotExists() { + $_assets = self::$Stack->Assets()->Query()->toJSON()->find(); + $_assets_count = count($_assets[0]); + $assets = self::$Stack->Assets()->Query()->toJSON()->notExists('title')->find(); + $this->assertArrayHasKey(0, $assets); + $this->assertFalse((count($assets[0]) === $_assets_count)); + } + + + public function testAssetsFindLogicalOrQueryObject() { + $_value = 7575; + $query1 = self::$Stack->Assets()->Query()->greaterThan('file_size', $_value); + $query2 = self::$Stack->Assets()->Query()->lessThan('file_size', $_value); + $assets = self::$Stack->Assets()->Query()->logicalOR($query1, $query2)->toJSON()->find(); + $this->assertArrayHasKey(0, $assets); + $this->assertTrue(checkAssetsSorting($assets[0])); + } + + public function testAssetsFindLogicalOrRawQuery() { + $_value = 7575; + $query1 = self::$Stack->Assets()->Query()->greaterThan('file_size', $_value)->getQuery(); + $query2 = self::$Stack->Assets()->Query()->lessThan('file_size', $_value)->getQuery(); + $assets = self::$Stack->Assets()->Query()->logicalOR($query1, $query2)->toJSON()->find(); + $this->assertArrayHasKey(0, $assets); + $this->assertTrue(checkAssetsSorting($assets[0])); + } + + public function testAssetsFindLogicalAndQueryObject() { + $_value = 6161; + $_value2 = 15000; + $query1 = self::$Stack->Assets()->Query()->greaterThanEqualTo('file_size', $_value); + + $query2 = self::$Stack->Assets()->Query()->lessThanEqualTo('file_size', $_value2); + $assets = self::$Stack->Assets()->Query()->logicalAND($query1, $query2)->toJSON()->find(); + + $this->assertArrayHasKey(0, $assets); + $this->assertTrue(checkAssetsSorting($assets[0])); + } + + public function testAssetsFindLogicalAndRawQuery() { + $_value = 6161; + $_value2 = 15000; + $query1 = self::$Stack->Assets()->Query()->greaterThanEqualTo('file_size', $_value); + $query2 = self::$Stack->Assets()->Query()->lessThanEqualTo('file_size', $_value2); + $assets = self::$Stack->Assets()->Query()->logicalAND($query1, $query2)->toJSON()->find(); + $this->assertArrayHasKey(0, $assets); + $this->assertTrue(checkAssetsSorting($assets[0])); + } + + public function testAssetsFindOnlyDefault() { + $_assets = self::$Stack->Assets()->Query()->only('BASE', array('title', 'updated_at'))->toJSON()->find(); + $_assets_count = self::$Stack->Assets()->Query()->toJSON()->find(); + $this->assertArrayHasKey(0, $_assets); + $this->assertTrue((count($_assets[0]) === count($_assets_count[0]))); + $this->assertTrue(checkAssetsSorting($_assets[0])); + $flag = true; + for($i = 0; $i < count($_assets[0]); $i++) { + $flag = $flag && (count(array_keys($_assets[0][$i])) === 6 && isset($_assets[0][$i]['updated_at']) && isset($_assets[0][$i]['filename']) && isset($_assets[0][$i]['ACL']) && isset($_assets[0][$i]['title']) && isset($_assets[0][$i]['uid'])); + } + $this->assertTrue($flag); + } + + public function testAssetsFindRegEx() { + $regexp = "[0-9]"; + $_assets = self::$Stack->Assets()->Query()->regex('title', $regexp)->toJSON()->find(); + $this->assertArrayHasKey(0, $_assets); + $this->assertTrue(checkassetsSorting($_assets[0])); + $flag = true; + for($i = 0; $i < count($_assets[0]); $i++) { + $flag = $flag && (preg_match("/{$regexp}/", $_assets[0][$i]['title'])); + } + $this->assertTrue($flag); + } + + public function testAssetsFindRegE1xWithOpt() { + $regexp = "[0-9]"; + $opts = "i"; + $_assets = self::$Stack->Assets()->Query()->includeCount()->regex('title', $regexp, $opts)->toJSON()->find(); + $this->assertArrayHasKey(0, $_assets); + $this->assertTrue(checkassetsSorting($_assets[0])); + $flag = true; + for($i = 0; $i < count($_assets[0]); $i++) { + $flag = $flag && (preg_match("/{$regexp}/{$opts}", $_assets[0][$i]['title'])); + } + $this->assertTrue($flag); + } + + public function testAssetsFindTags() { + $_assets = self::$Stack->Assets()->Query()->tags(array('tag-1'))->toJSON()->find(); + $this->assertArrayHasKey(0, $_assets); + $this->assertTrue(checkassetsSorting($_assets[0])); + $flag = true; + for($i = 0; $i < count($_assets[0]); $i++) { + $flag = $flag && (!array_search('tag-1', $_assets[0][$i]['tags'])); + } + $this->assertTrue($flag); + } + + public function testAssetsFindExceptBaseDefault() { + $_assets = self::$Stack->Assets()->Query()->except('BASE', array('title'))->toJSON()->find(); + $this->assertArrayHasKey(0, $_assets); + $_assets_count = self::$Stack->Assets()->Query()->toJSON()->find(); + $this->assertTrue((count($_assets[0]) === count($_assets_count[0]))); + $this->assertTrue(checkAssetsSorting($_assets[0])); + $flag = true; + for($i = 0; $i < count($_assets[0]); $i++) { + $flag = $flag && (!array_search('title', array_keys($_assets[0][$i]))); + } + $this->assertTrue($flag); + } + + public function testAssetsFindOnlyBaseDefault() { + $_assets = self::$Stack->Assets()->Query()->only('BASE', array('title', 'updated_at'))->toJSON()->find(); + $this->assertArrayHasKey(0, $_assets); + $assets = self::$Stack->Assets()->Query()->toJSON()->find(); + $assets_count = count($assets[0]); + $this->assertTrue((count($_assets[0]) === $assets_count)); + $this->assertTrue(checkAssetsSorting($_assets[0])); + $flag = true; + for($i = 0; $i < count($_assets[0]); $i++) { + $flag = $flag && (count(array_keys($_assets[0][$i])) === 6 && isset($_assets[0][$i]['updated_at']) && isset($_assets[0][$i]['filename']) && isset($_assets[0][$i]['ACL']) && isset($_assets[0][$i]['title']) && isset($_assets[0][$i]['uid'])); + } + $this->assertTrue($flag); + } + + public function testAssetsFindExceptDefault() { + $_assets = self::$Stack->Assets()->Query()->except('BASE',array('boolean'))->toJSON()->find(); + $this->assertArrayHasKey(0, $_assets); + $assets = self::$Stack->Assets()->Query()->toJSON()->find(); + $assets_count = count($assets[0]); + $this->assertTrue((count($_assets[0]) === $assets_count)); + $this->assertTrue(checkAssetsSorting($_assets[0])); + $flag = true; + for($i = 0; $i < count($_assets[0]); $i++) { + $flag = $flag && (!array_search('boolean', array_keys($_assets[0][$i]))); + } + $this->assertTrue($flag); + } + + public function testAssetsFindSearch() { + $_assets = self::$Stack->Assets()->Query()->search('image/jpeg')->language('en-us')->toJSON()->find(); + $this->assertArrayHasKey(0, $_assets); + // $assets = self::$Stack->Assets()->Query()->toJSON()->find(); + // $assets_count = count($assets[0]); + $this->assertTrue((count($_assets[0]) === 2)); + $this->assertTrue(checkAssetsSorting($_assets[0])); + $flag = true; + for($i = 0; $i < count($_assets[0]); $i++) { + $flag = $flag && (!strpos(json_encode($_assets[0][$i]), 'image/jpeg')); + } + $this->assertTrue($flag); + } + +} \ No newline at end of file diff --git a/test/EntriesTest.php b/test/EntriesTest.php new file mode 100755 index 00000000..a5ab7490 --- /dev/null +++ b/test/EntriesTest.php @@ -0,0 +1,512 @@ +getAPIKEY(), self::$rest->getAccessToken(), self::$rest->getEnvironmentName()); + if (self::$rest->getHost() !== NULL) { + self::$Stack->setHost(self::$rest->getHost()); + } + self::$LivePreviewStack = Contentstack::Stack(self::$rest->getAPIKEY(), self::$rest->getAccessToken(), self::$rest->getEnvironmentName(), array('live_preview' => array( + 'enable'=> true, + 'host' => 'preview.contentstack.com', + 'management_token' => 'token' + ))); + + } + /* + * Tear Down after the test suites executes + */ + public static function tearDownAfterClass() : void { + if(ENV !== 'TEST_LOCAL') { + self::$rest->deleteStack(); + } + } + + public function testJsonRTE () { + $jsonObject = json_decode('{ "uid":"0d7fd", "_version":13, "attrs":{ }, "children":[{"type":"p","attrs":{},"uid":"0a1b5676aa510e5a","children":[{"text":"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed condimentum iaculis magna in vehicula. Vestibulum vitae convallis lacus. Praesent a diam iaculis turpis rhoncus faucibus. Aliquam sed pulvinar sem."}]}],"type":"doc"}'); + $result = Contentstack::jsonToHtml($jsonObject, new Option()); + $this->assertEquals('

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed condimentum iaculis magna in vehicula. Vestibulum vitae convallis lacus. Praesent a diam iaculis turpis rhoncus faucibus. Aliquam sed pulvinar sem.

', $result); + } + public function testFind() { + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertTrue((count($_entries[0]) === ENTRY_COUNT)); + $this->assertTrue(checkEntriesSorting($_entries[0])); + for($i = 0; $i < count($_entries[0]); $i++) { + if ($_entries[0][$i]['title'] === 'CB1-10') { + self::$_uid = $_entries[0][$i]['uid']; + } + } + } + public function testLivePreviewEntry () { + $_entry = self::$LivePreviewStack->ContentType(CT_ContentType)->Entry(self::$_uid)->toJSON()->fetch(); + + $this->assertEquals($_entry['title'], 'CB1-10'); + } + + public function testLivePreviewEntrywithQuery () { + try { + self::$LivePreviewStack->livePreviewQuery(array('content_type_uid' => CT_ContentType)); + $_entry = self::$LivePreviewStack->ContentType(CT_ContentType)->Entry(self::$_uid)->toJSON()->fetch(); + } catch (Exception $e) { + $this->assertTrue(true); + } + } + + public function testFetch() { + $_entry = self::$Stack->ContentType(CT_ContentType)->Entry(self::$_uid)->toJSON()->fetch(); + + $this->assertEquals($_entry['title'], 'CB1-10'); + } + + public function testAddParam() { + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->addParam('include_count', 'true')->toJSON()->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertArrayHasKey(1, $_entries); + $this->assertTrue((count($_entries[0]) === ENTRY_COUNT)); + $this->assertTrue(($_entries[1] === ENTRY_COUNT)); + } + + public function testFindSkip() { + $_entries1 = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->find(); + $this->assertArrayHasKey(0, $_entries1); + $this->assertTrue((count($_entries1[0]) === ENTRY_COUNT)); + $skip = 1; + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->skip($skip)->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertTrue((count($_entries[0]) === ENTRY_COUNT - $skip)); + $this->assertTrue(checkEntriesSorting($_entries[0])); + $this->assertEquals($_entries[0], array_slice($_entries1[0], $skip)); + } + + public function testFindLimit() { + $limit = 1; + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->limit($limit)->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertTrue((count($_entries[0]) === $limit)); + $this->assertTrue(checkEntriesSorting($_entries[0])); + } + + public function testFindLanguage() { + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->language('en-us')->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertTrue(checkEntriesSorting($_entries[0])); + } + + public function testFindSkipLimit() { + $_entries1 = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->find(); + $this->assertArrayHasKey(0, $_entries1); + $this->assertTrue((count($_entries1[0]) === ENTRY_COUNT)); + $limit = 4; + $skip = 1; + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->skip($skip)->limit($limit)->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertTrue((count($_entries[0]) === $limit)); + $this->assertTrue(checkEntriesSorting($_entries[0])); + $this->assertEquals($_entries[0], array_slice($_entries1[0], $skip, $limit)); + } + + public function testFindCount() { + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->count()->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertTrue(($_entries[0] === ENTRY_COUNT)); + } + + public function testFindIncludeCount() { + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->includeCount()->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertArrayHasKey(1, $_entries); + $this->assertTrue((count($_entries[0]) === ENTRY_COUNT)); + $this->assertTrue(($_entries[1] === ENTRY_COUNT)); + } + + public function testIncludeFallback() { + $testArray = array("a"=>"en-us", "b" => "hi-in"); + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->language("hi-in")->includeFallback()->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertEquals(count($_entries[0]), ENTRY_COUNT); + for($i = 0; $i < count($_entries[0]); $i++) { + $this->assertContains($_entries[0][$i]["publish_details"]["locale"], $testArray); + } + } + + public function testWithoutIncludeFallback() { + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->language("hi-in")->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertEquals(count($_entries[0]), 1); + for($i = 0; $i < count($_entries[0]); $i++) { + $this->assertEquals($_entries[0][$i]["publish_details"]["locale"], "hi-in"); + } + } + + public function testFindIncludeSchema() { + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->includeSchema()->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertArrayHasKey(0, $_entries); + $this->assertTrue((count($_entries[0]) === ENTRY_COUNT)); + $this->assertTrue(checkEntriesSorting($_entries[0])); + // $this->assertTrue((count($_entries[1]) === count(self::$rest->get('content_types')[1]['schema']))); + } + + public function testFindIncludeContentType() { + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->includeContentType()->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertArrayHasKey(1, $_entries); + $this->assertTrue((count($_entries[0]) === ENTRY_COUNT)); + $this->assertTrue(checkEntriesSorting($_entries[0])); + $this->assertTrue($_entries[1]['uid'] === CT_ContentType); + } + + public function testFindIncludeEmbeddedItems() { + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->includeEmbeddedItems()->find(); + for($i = 0; $i < count($_entries[0]); $i++) { + if (array_key_exists('rich_text_editor', $_entries[0][$i])) { + $embedded = Contentstack::renderContent($_entries[0][$i]["rich_text_editor"], new Option($_entries[0][$i])); + } + } + $this->assertArrayHasKey(0, $_entries); + + } + public function testFindIncludeReferenceContentTypeUID() { + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->includeReferenceContentTypeUID()->find(); + $_flag = "false"; + $this->assertArrayHasKey(0, $_entries); + for($i = 0; $i < count($_entries[0]); $i++) { + if(count($_entries[0][$i]["reference"]) > 0 && $_entries[0][$i]["reference"][0]['_content_type_uid'] !== NULL) { + $_flag = "true"; + } + } + $this->assertTrue($_flag === "true"); + } + + public function testFindIncludeContentTypeIncludeCount() { + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->includeCount()->includeContentType()->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertArrayHasKey(1, $_entries); + $this->assertArrayHasKey(2, $_entries); + $this->assertTrue((count($_entries[0]) === ENTRY_COUNT)); + $this->assertTrue(checkEntriesSorting($_entries[0])); + $this->assertTrue($_entries[1]['uid'] === CT_ContentType); + $this->assertTrue($_entries[2] === ENTRY_COUNT); + } + + public function testFindIncludeSchemaIncludeCount() { + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->includeCount()->includeSchema()->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertArrayHasKey(1, $_entries); + $this->assertArrayHasKey(2, $_entries); + $this->assertTrue((count($_entries[0]) === ENTRY_COUNT)); + $this->assertTrue(checkEntriesSorting($_entries[0])); + //$this->assertTrue((count($_entries[1]) === count(self::$rest->get('content_types')[1]['schema']))); + $this->assertTrue(($_entries[2]) === ENTRY_COUNT); + } + + public function testFindWhere() { + $entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->where('title', 'CB1-1')->find(); + $this->assertArrayHasKey(0, $entries); + $this->assertArrayHasKey(0, $entries[0]); + $this->assertTrue(($entries[0][0]['title'] === 'CB1-1')); + } + + public function testFindContainedIn() { + $_set = [8, 9, 10, 11]; + $_actualCount = (count($_set) - 1); + $entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->containedIn('number1', $_set)->find(); + $this->assertArrayHasKey(0, $entries); + $this->assertTrue((count($entries[0]) === $_actualCount)); + foreach ($entries[0] as $key => $val) { + $this->assertTrue((array_search($entries[0][$key]['number1'], $_set) !== false)); + } + } + + public function testFindNotContainedIn() { + $_set = [8, 9, 10, 11]; + $_actualCount = ENTRY_COUNT - (count($_set) - 1); + $entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->notContainedIn('number1', $_set)->find(); + $this->assertArrayHasKey(0, $entries); + $this->assertTrue((count($entries[0]) === $_actualCount)); + foreach ($entries[0] as $key => $val) { + $this->assertTrue((array_search($entries[0][$key]['number1'], $_set) === false)); + } + } + + public function testFindLessThan() { + $_set = 8; + $_actualCount = 7; + $entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->lessThan('group.number', $_set)->find(); + $this->assertArrayHasKey(0, $entries); + $this->assertTrue((count($entries[0]) === $_actualCount)); + foreach ($entries[0] as $key => $val) { + $this->assertTrue(($entries[0][$key]['group']['number'] < $_set)); + } + } + + public function testFindLessThanEqualTo() { + $_actualCount = $_set = 8; + $entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->lessThanEqualTo('group.number', $_set)->find(); + $this->assertArrayHasKey(0, $entries); + $this->assertTrue((count($entries[0]) === $_actualCount)); + foreach ($entries[0] as $key => $val) { + $this->assertTrue(($entries[0][$key]['group']['number'] <= $_set)); + } + } + + public function testFindGreaterThan() { + $_set = 8; + $_actualCount = ENTRY_COUNT - $_set; + $entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->greaterThan('group.number', $_set)->find(); + $this->assertArrayHasKey(0, $entries); + $this->assertTrue((count($entries[0]) === $_actualCount)); + foreach ($entries[0] as $key => $val) { + $this->assertTrue(($entries[0][$key]['group']['number'] > $_set)); + } + } + + public function testFindGreaterThanEqualTo() { + $_set = 8; + $_actualCount = (ENTRY_COUNT - $_set) + 1; + $entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->greaterThanEqualTo('group.number', $_set)->find(); + $this->assertArrayHasKey(0, $entries); + $this->assertTrue((count($entries[0]) === $_actualCount)); + foreach ($entries[0] as $key => $val) { + $this->assertTrue(($entries[0][$key]['group']['number'] >= $_set)); + } + } + + public function testFindNotEqualTo() { + $_set = 5; + $_actualCount = ENTRY_COUNT - 1; + $entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->notEqualTo('group.number', $_set)->find(); + $this->assertArrayHasKey(0, $entries); + $this->assertTrue((count($entries[0]) === $_actualCount)); + foreach ($entries[0] as $key => $val) { + $this->assertTrue(($entries[0][$key]['group']['number'] !== $_set)); + } + } + + public function testFindExists() { + $_actualCount = ENTRY_COUNT; + $entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->exists('boolean')->find(); + $this->assertArrayHasKey(0, $entries); + $this->assertTrue((count($entries[0]) === $_actualCount)); + foreach ($entries[0] as $key => $val) { + $this->assertTrue(isset($entries[0][$key]['boolean'])); + } + } + + public function testFindNotExists() { + $entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->notExists('boolean')->find(); + $this->assertArrayHasKey(0, $entries); + $this->assertFalse((count($entries[0]) === ENTRY_COUNT)); + } + + public function testFindAscending() { + $field = 'created_at'; + $entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->ascending($field)->find(); + $this->assertArrayHasKey(0, $entries); + $this->assertTrue((count($entries[0]) === ENTRY_COUNT)); + $this->assertTrue(checkEntriesSorting($entries[0], $field, 'asc')); + } + + + public function testFindDescending() { + $field = 'created_at'; + $entries = self::$Stack->ContentType(CT_ContentType)->Query()->toJSON()->descending('created_at')->find(); + $this->assertArrayHasKey(0, $entries); + $this->assertTrue((count($entries[0]) === ENTRY_COUNT)); + $this->assertTrue(checkEntriesSorting($entries[0], $field, 'desc')); + } + + public function testGetContentTypes() { + $globalfield = '{"include_global_field_schema": "true"}'; + $content_type = self::$Stack->getContentTypes($globalfield); + for ($j = 0; $j < count($content_type['content_types']); $j++) + { + for($i = 0; $i < count($content_type['content_types'][$j]['schema']); $i++) { + if($content_type['content_types'][$j]['schema'][$i]['data_type'] === 'global_field') { + $flag = (isset($content_type['content_types'][$j]['schema'][$i]['schema'])); + $this->assertTrue($flag); + } + } + } + + } + + public function testFindLogicalOrQueryObject() { + $_value = 5; + $count = ENTRY_COUNT - 1; + $query1 = self::$Stack->ContentType(CT_ContentType)->Query()->greaterThan('number1', $_value); + $query2 = self::$Stack->ContentType(CT_ContentType)->Query()->lessThan('number1', $_value); + $entries = self::$Stack->ContentType(CT_ContentType)->Query()->logicalOR($query1, $query2)->toJSON()->find(); + $this->assertArrayHasKey(0, $entries); + $this->assertEquals(count($entries[0]), $count); + $this->assertTrue(checkEntriesSorting($entries[0])); + } + + public function testFindLogicalOrRawQuery() { + $_value = 5; + $count = ENTRY_COUNT - 1; + $query1 = self::$Stack->ContentType(CT_ContentType)->Query()->greaterThan('number1', $_value)->getQuery(); + $query2 = self::$Stack->ContentType(CT_ContentType)->Query()->lessThan('number1', $_value)->getQuery(); + $entries = self::$Stack->ContentType(CT_ContentType)->Query()->logicalOR($query1, $query2)->toJSON()->find(); + $this->assertArrayHasKey(0, $entries); + $this->assertEquals(count($entries[0]), $count); + $this->assertTrue(checkEntriesSorting($entries[0])); + } + + public function testFindLogicalAndQueryObject() { + $_value = 5; + $count = 1; + $query1 = self::$Stack->ContentType(CT_ContentType)->Query()->greaterThanEqualTo('number1', $_value); + $query2 = self::$Stack->ContentType(CT_ContentType)->Query()->lessThanEqualTo('number1', $_value); + $entries = self::$Stack->ContentType(CT_ContentType)->Query()->logicalAND($query1, $query2)->toJSON()->find(); + $this->assertArrayHasKey(0, $entries); + $this->assertEquals(count($entries[0]), $count); + $this->assertTrue(checkEntriesSorting($entries[0])); + } + + public function testFindLogicalAndRawQuery() { + $_value = 5; + $count = 1; + $query1 = self::$Stack->ContentType(CT_ContentType)->Query()->greaterThanEqualTo('number1', $_value); + $query2 = self::$Stack->ContentType(CT_ContentType)->Query()->lessThanEqualTo('number1', $_value); + $entries = self::$Stack->ContentType(CT_ContentType)->Query()->logicalAND($query1, $query2)->toJSON()->find(); + $this->assertArrayHasKey(0, $entries); + $this->assertEquals(count($entries[0]), $count); + $this->assertTrue(checkEntriesSorting($entries[0])); + } + + public function testFindOnlyDefault() { + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->only('BASE', array('title', 'updated_at'))->toJSON()->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertTrue((count($_entries[0]) === ENTRY_COUNT)); + $this->assertTrue(checkEntriesSorting($_entries[0])); + $flag = true; + for($i = 0; $i < count($_entries[0]); $i++) { + $flag = $flag && (count(array_keys($_entries[0][$i])) === 3 && isset($_entries[0][$i]['updated_at']) && isset($_entries[0][$i]['title']) && isset($_entries[0][$i]['uid'])); + /*$flag = $flag && (count(array_keys($_entries[0][$i])) === 4 && isset($_entries[0][$i]['url']) && isset($_entries[0][$i]['updated_at']) && isset($_entries[0][$i]['title']) && isset($_entries[0][$i]['uid']));*/ + } + $this->assertTrue($flag); + } + + public function testFindOnlyBaseDefault() { + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->only('BASE', array('title', 'updated_at'))->toJSON()->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertTrue((count($_entries[0]) === ENTRY_COUNT)); + $this->assertTrue(checkEntriesSorting($_entries[0])); + $flag = true; + for($i = 0; $i < count($_entries[0]); $i++) { + $flag = $flag && (count(array_keys($_entries[0][$i])) === 3 && isset($_entries[0][$i]['updated_at']) && isset($_entries[0][$i]['title']) && isset($_entries[0][$i]['uid'])); + /*$flag = $flag && (count(array_keys($_entries[0][$i])) === 4 && isset($_entries[0][$i]['url']) && isset($_entries[0][$i]['updated_at']) && isset($_entries[0][$i]['title']) && isset($_entries[0][$i]['uid']));*/ + } + $this->assertTrue($flag); + } + + public function testFindExceptDefault() { + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->except('BASE', array('title'))->toJSON()->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertTrue((count($_entries[0]) === ENTRY_COUNT)); + $this->assertTrue(checkEntriesSorting($_entries[0])); + $flag = true; + for($i = 0; $i < count($_entries[0]); $i++) { + $flag = $flag && (!array_search('title', array_keys($_entries[0][$i]))); + } + $this->assertTrue($flag); + } + + public function testFindExceptBaseDefault() { + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->except('BASE', array('title'))->toJSON()->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertTrue((count($_entries[0]) === ENTRY_COUNT)); + $this->assertTrue(checkEntriesSorting($_entries[0])); + $flag = true; + for($i = 0; $i < count($_entries[0]); $i++) { + $flag = $flag && (!array_search('title', array_keys($_entries[0][$i]))); + } + $this->assertTrue($flag); + } + + public function testFindExceptReference() { + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->includeReference(array('reference'))->except('reference', array('title'))->toJSON()->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertTrue((count($_entries[0]) === ENTRY_COUNT)); + $this->assertTrue(checkEntriesSorting($_entries[0])); + $flag = true; + // it is not working as "title" is also included in the result set + for($i = 0; $i < count($_entries[0]); $i++) { + for($j = 0; $j < count($_entries[0][$i]['reference']); $j++) { + $flag = $flag && (!isset($_entries[0][$i]['reference'][$j]['title'])); + } + } + $this->assertTrue($flag); + } + + public function testFindRegEx() { + $regexp = "CB1-[0-9]+"; + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->regex('title', $regexp)->toJSON()->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertTrue((count($_entries[0]) === ENTRY_COUNT)); + $this->assertTrue(checkEntriesSorting($_entries[0])); + $flag = true; + for($i = 0; $i < count($_entries[0]); $i++) { + $flag = $flag && (preg_match("/{$regexp}/", $_entries[0][$i]['title'])); + } + $this->assertTrue($flag); + } + + public function testFindRegE1xWithOpt() { + $regexp = "^cb1-[0-9]+"; + $opts = "i"; + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->includeCount()->regex('title', $regexp, $opts)->toJSON()->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertTrue((count($_entries[0]) === ENTRY_COUNT)); + $this->assertTrue(checkEntriesSorting($_entries[0])); + $flag = true; + for($i = 0; $i < count($_entries[0]); $i++) { + $flag = $flag && (preg_match("/{$regexp}/{$opts}", $_entries[0][$i]['title'])); + } + $this->assertTrue($flag); + } + + public function testFindTags() { + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->tags(array('tag-1'))->toJSON()->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertTrue((count($_entries[0]) === ENTRY_COUNT)); + $this->assertTrue(checkEntriesSorting($_entries[0])); + $flag = true; + for($i = 0; $i < count($_entries[0]); $i++) { + $flag = $flag && (!array_search('tag-1', $_entries[0][$i]['tags'])); + } + $this->assertTrue($flag); + } + + public function testFindSearch() { + $_entries = self::$Stack->ContentType(CT_ContentType)->Query()->search('CB')->toJSON()->find(); + $this->assertArrayHasKey(0, $_entries); + $this->assertTrue((count($_entries[0]) === ENTRY_COUNT)); + $this->assertTrue(checkEntriesSorting($_entries[0])); + $flag = true; + for($i = 0; $i < count($_entries[0]); $i++) { + $flag = $flag && (!strpos(json_encode($_entries[0][$i]), 'CB-')); + } + $this->assertTrue($flag); + } +} \ No newline at end of file diff --git a/test/ImageTransformTest.php b/test/ImageTransformTest.php new file mode 100755 index 00000000..9000be68 --- /dev/null +++ b/test/ImageTransformTest.php @@ -0,0 +1,75 @@ +getAPIKEY(), self::$rest->getAccessToken(), self::$rest->getEnvironmentName()); + if (self::$rest->getHost() !== NULL) { + self::$Stack->setHost(self::$rest->getHost()); + } + } + /* + * Tear Down after the test suites executes + */ + public static function tearDownAfterClass() : void { + if(ENV !== 'TEST_LOCAL') { + self::$rest->deleteStack(); + } + } + + public function testSingleParamsImageTransform() { + $_object = self::$Stack->Assets()->Query()->toJSON()->find(); + $_uid = $_object[0][0]['uid']; + $_asset = self::$Stack->Assets($_uid)->fetch(); + $_url = $_asset->get('url'); + if($_url){ + $_resizeimagetransformation = self::$Stack->ImageTrasform($_url, array('height'=> 100, 'weight'=> 100, 'disable' => 'upscale')); + $resize_data = parse_url($_resizeimagetransformation, PHP_URL_QUERY); + parse_str($resize_data, $get_array_resize); + $resize_default_array = array('height'=> 100,'weight'=> 100, 'disable' => 'upscale'); + $this->assertEquals($get_array_resize, $resize_default_array); + } + } + + public function testTwoParamsImageTransform() { + $_object = self::$Stack->Assets()->Query()->toJSON()->find(); + $_uid = $_object[0][0]['uid']; + $_asset = self::$Stack->Assets($_uid)->fetch(); + $_url = $_asset->get('url'); + if($_url){ + $_cropimagetransformation = self::$Stack->ImageTrasform($_url, array('crop'=> 100,200)); + $crop_data = parse_url($_cropimagetransformation, PHP_URL_QUERY); + parse_str($crop_data, $get_array_crop); + $crop_default_array = array('crop'=> 100,200); + $this->assertEquals($get_array_crop, $crop_default_array); + } + } + + public function testThreeParamsImageTransforma() { + $_object = self::$Stack->Assets()->Query()->toJSON()->find(); + $_uid = $_object[0][0]['uid']; + $_asset = self::$Stack->Assets($_uid)->fetch(); + $_url = $_asset->get('url'); + if($_url){ + $_resizecropimagetransformation = self::$Stack->ImageTrasform($_url, array('height'=> 100, 'weight'=> 100, 'disable' => 'upscale', 'crop'=> 100,200, 'orient'=> 2)); + $resizecrop_data = parse_url($_resizecropimagetransformation, PHP_URL_QUERY); + parse_str($resizecrop_data, $get_array_resizecrop); + $resizecrop_default_array = array('height'=> 100,'weight'=> 100, 'disable' => 'upscale', 'crop'=> 100,200, 'orient'=> 2); + $this->assertEquals($get_array_resizecrop, $resizecrop_default_array); + } + } +} \ No newline at end of file diff --git a/test/README.md b/test/README.md new file mode 100755 index 00000000..091a6bf9 --- /dev/null +++ b/test/README.md @@ -0,0 +1,34 @@ +# PHP SDK for Contentstack - Unit Testing + +## Prerequisite + - Contentstack Account + +## Install phpunit + + - [Installation](https://phpunit.de/manual/current/en/installation.html). + +## How to run? + +### Run all the test cases +``` +phpunit {FileName}.php +``` +### Run using report formatter + +``` +phpunit {FileName}.php --[tap|testdox] +``` + +### Run only specific cases + +``` +phpunit --filter {testcasename} {FileName}.php +``` +### Generate report from the test case excecution + +``` +phpunit {FileName}.php --log-junit report.xml +``` +``` +phpunit {FileName}.php --testdox-html report.html +``` \ No newline at end of file diff --git a/test/REST.php b/test/REST.php new file mode 100644 index 00000000..f9f7e62e --- /dev/null +++ b/test/REST.php @@ -0,0 +1,102 @@ +results = json_decode(fread($myfile, filesize(RESULT_PATH)), true); + fclose($myfile); + } + + /* + * Remove system keys from the values + * */ + public function sanatize($value = array()) + { + unset($value['SYS_ACL']); + unset($value['DEFAULT_ACL']); + unset($value['roles']); + return $value; + } + + /* + * Set method is used to add the variable to the private variable of current instance + * @param + * string|$key - key which will hold the value + * array|$value - value of the key + * @return null + * */ + public function set($key = '', $value = '') + { + // unset values + if (is_array($value) && isset($value[0]) && is_array($value[0])) { + foreach ($value as $k => $val) { + $val = $this->sanatize($val); + $value[$k] = $val; + } + } else { + $value = $this->sanatize($value); + } + // unset values + + // before set get the data + $tmpValue = ($this->get($key)) ? $this->get($key) : array(); + $this->results[$key] = array_merge($value, $tmpValue); + } + + /* + * Get method is used to fetch the matched key's value of current instance + * @param + * string|$key - key which will hold the value + * @return string|array|$value + * */ + public function get($key = '') + { + return ($key && isset($this->results[$key])) ? $this->results[$key] : array(); + } + + public function getAPIKEY() { + $stack = $this->get('stack'); + return $stack['api_key']; + } + + public function getAccessToken() { + $stack = $this->get('stack'); + if (gettype($stack['delivery_token']) === 'string') { + return $stack['delivery_token']; + } + return $stack['discrete_variables']['access_token']; + } + + public function getEnvironmentName() { + $stack = $this->get('stack'); + if (gettype($stack['environment']) === 'string') { + return $stack['environment']; + } + $environment = $this->get('environment'); + return $environment['name']; + } + + public function getHost() { + $host = $this->get('host'); + if (gettype($host) === 'string') { + return $host; + } + return NULL; + } +} + +function debug($input = array(), $exit = false) +{ + echo "
";
+    print_r($input);
+    echo "
"; + if ($exit) exit(); +} \ No newline at end of file diff --git a/test/SyncTest.php b/test/SyncTest.php new file mode 100644 index 00000000..2bebda8c --- /dev/null +++ b/test/SyncTest.php @@ -0,0 +1,74 @@ +getAPIKEY(), self::$rest->getAccessToken(), self::$rest->getEnvironmentName()); + if (self::$rest->getHost() !== NULL) { + self::$Stack->setHost(self::$rest->getHost()); + } + } + /* + * Tear Down after the test suites executes + */ + public static function tearDownAfterClass() : void{ + if(ENV !== 'TEST_LOCAL') { + // self::$rest->deleteStack(); + } + } + + public function testSyncInit() { + $_result = self::$Stack->sync(array('init'=> 'true')); + $this->assertEquals(18, count($_result['items'])); + $this->assertNotNull($_result['sync_token']); + $this->assertEquals(18, $_result['total_count']); + $this->assertEquals(100, $_result['limit']); + + } + + public function testSyncInitContentType() { + $_result = self::$Stack->sync(array('init'=> 'true', "content_type_uid"=> CT_ContentType)); + $this->assertEquals(11, count($_result['items'])); + $this->assertNotNull($_result['sync_token']); + $this->assertEquals(11, $_result['total_count']); + $this->assertEquals(100, $_result['limit']); + } + + public function testSyncInitLocale() { + $_result = self::$Stack->sync(array('init'=> 'true', "locale"=> 'hi-in')); + $this->assertEquals(3, count($_result['items'])); + $this->assertNotNull($_result['sync_token']); + $this->assertEquals(3, $_result['total_count']); + $this->assertEquals(100, $_result['limit']); + } + + public function testSyncInitType() { + $_result = self::$Stack->sync(array('init'=> 'true', "type"=> 'asset_published')); + $this->assertEquals(4, count($_result['items'])); + $this->assertNotNull($_result['sync_token']); + $this->assertEquals(4, $_result['total_count']); + $this->assertEquals(100, $_result['limit']); + } + + public function testSyncInitMultipleQuery() { + $_result = self::$Stack->sync(array('init'=> 'true', "type"=> 'entry_published', "locale"=> 'hi-in', "content_type_uid"=> CT_ContentType)); + $this->assertEquals(1, count($_result['items'])); + $this->assertNotNull($_result['sync_token']); + $this->assertEquals(1, $_result['total_count']); + $this->assertEquals(100, $_result['limit']); + } +} diff --git a/test/constants.php b/test/constants.php new file mode 100755 index 00000000..2df7ef2a --- /dev/null +++ b/test/constants.php @@ -0,0 +1,15 @@ += $entries[$i+1][$sortKey]); + else + $result = $result && ($entries[$i][$sortKey] <= $entries[$i+1][$sortKey]); + } + return $result; + } +} + +if (!function_exists('assetsSorting')) { + + function checkAssetsSorting($assets = array(), $sortKey = 'updated_at', $order = 'desc') { + if(count($assets) > 0){ + $result = true; + for($i = 0;$i < count($assets) - 1; $i++) { + if($order === 'desc') + $result = $result && ($assets[$i][$sortKey] >= $assets[$i+1][$sortKey]); + else + $result = $result && ($assets[$i][$sortKey] <= $assets[$i+1][$sortKey]); + } + return $result; + } else{ + return 0; + } +} +} + +if (!function_exists('sortEntries')) { + function sortEntries($entries = array(), $sortKey = 'updated_at', $order = 'desc') { + + usort($entries, create_function('$a, $b', ' + $a = $a["' . $sortKey . '"]; + $b = $b["' . $sortKey . '"]; + + if ($a == $b) { + return 0; + } + return ($a ' . ($order == 'desc' ? '>' : '<') .' $b) ? -1 : 1; + ')); + \Contentstack\Utility\debug(array_column($entries, $sortKey)); + } +} + +if (!function_exists('getResultEntries')) { + function getResultEntries($contentType = '', $index = '', $skip = 0, $limit = 9999) { + $_result = array(); + $myfile = fopen(RESULT_PATH, "r") or die("Unable to open file!"); + $results = json_decode(fread($myfile, filesize(RESULT_PATH)), true); + // skip operation + $_result = array_slice($_result, $skip, $limit); + if ($index === '') + $_result = $results['entries.'.$contentType]; + else + $_result = $results['entries.'.$contentType][$index]; + return $_result; + } +}