diff --git a/.babelrc b/.babelrc deleted file mode 100644 index ac7833846f2..00000000000 --- a/.babelrc +++ /dev/null @@ -1,31 +0,0 @@ -{ - "presets": [ - [ - "env", - { - "modules": false - } - ] - ], - "plugins": [ - "transform-object-rest-spread", - "transform-react-jsx" - ], - "env": { - "test": { - "presets" : [["env"]] - }, - "production": { - "plugins": [ - [ - "@wordpress/babel-plugin-makepot", - { - "output": "languages/ee-js.pot" - } - ], - "transform-object-rest-spread", - "transform-react-jsx" - ] - } - } -} \ No newline at end of file diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index a09560cc673..00000000000 --- a/.editorconfig +++ /dev/null @@ -1,42 +0,0 @@ -[*] -charset=utf-8 -end_of_line=lf -insert_final_newline=false -indent_style=space -indent_size=4 - -[{.babelrc,.stylelintrc,jest.config,.eslintrc,*.sample,*.json,*.jsb3,*.jsb2,*.bowerrc,*.js}] -indent_style=tab -indent_size=4 - -[*.feature] -indent_style=space -indent_size=2 - -[{jshint.json,*.jshintrc}] -indent_style=tab -indent_size=2 - -[{*.jscs.json,*.jscsrc}] -indent_style=tab -indent_size=2 - -[*.js.map] -indent_style=tab -indent_size=2 - -[{*.ddl,*.sql}] -indent_style=space -indent_size=2 - -[*.less] -indent_style=tab -indent_size=2 - -[*.scss] -indent_style=tab -indent_size=2 - -[{*.yaml,*.yml}] -indent_style=space -indent_size=2 \ No newline at end of file diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index c07eba8bf20..00000000000 --- a/.eslintignore +++ /dev/null @@ -1,17 +0,0 @@ -assets/dist -node_modules -acceptance_tests -admin_pages -caffeinated -core -docs -languages -modules -payment_methods -public -shortcodes -tests -ui -widgets -wp-assets -coverage \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 63eee52aa3d..00000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,28 +0,0 @@ -module.exports = { - 'extends': [ - './eslint/config.js', - 'plugin:jest/recommended', - ], - 'plugins': [ - 'wordpress', - ], - env: { - 'jest/globals': true, - }, - globals: { - wpApiSettings: true, - eejsdata: true - }, - plugins: [ - 'jest', - ], - overrides: [ - { - files: [ 'test/e2e/**/*.js' ], - globals: { - page: true, - browser: true, - }, - }, - ], -}; \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index b90482216f6..00000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,57 +0,0 @@ - - - -## Issue Overview - - - - -## Bug report or feature request? - -* [ ] Bug -* [ ] Feature -* [ ] Neither - - -## Environment Data: - -Version of EE: - -Version of WordPress: - -PHP Version: - -Browser used: - - -## Steps to Reproduce (for bugs) - - - - -## Expected Behaviour - - - - -## Current Behaviour - - - - -## Related Information: - diff --git a/.github/ISSUE_TEMPLATE/Bug_report.md b/.github/ISSUE_TEMPLATE/Bug_report.md deleted file mode 100644 index c5184890e38..00000000000 --- a/.github/ISSUE_TEMPLATE/Bug_report.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve - ---- - - - -**Describe the bug** - - -**To Reproduce** - - -**Expected behavior** - - -**Screenshots** - - -**Environment:** - - Version of Event Espresso: - - Version of WordPress: - - Browser - - PHP Version - -**Additional context** - diff --git a/.github/ISSUE_TEMPLATE/Feature_request.md b/.github/ISSUE_TEMPLATE/Feature_request.md deleted file mode 100644 index 945ef8201d1..00000000000 --- a/.github/ISSUE_TEMPLATE/Feature_request.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project - ---- - - - -**Is your feature request related to a problem? Please describe.** - - -**Describe the solution you'd like** - - -**Describe alternatives you've considered** - - -**Additional context** - diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 730759a1383..00000000000 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,23 +0,0 @@ - - - - -## Problem this Pull Request solves - - -## Why do you think these changes are needed in Event Espresso core instead of being put in an add-on? - - -## How has this been tested - - - - -## Checklist - -* [ ] I have read the documentation relating to systems affected by this pull request, see https://github.com/eventespresso/event-espresso-core/tree/master/docs -* [ ] User input is adequately validated and sanitized -* [ ] all publicly displayed strings are internationalized (usually using `esc_html__()`, see https://codex.wordpress.org/I18n_for_WordPress_Developers) -* [ ] My code is tested. -* [ ] My code follows the Event Espresso code style. -* [ ] My code has proper inline documentation. diff --git a/.github/codecov.yml b/.github/codecov.yml deleted file mode 100644 index 83f9414824c..00000000000 --- a/.github/codecov.yml +++ /dev/null @@ -1,9 +0,0 @@ -coverage: - status: - project: - default: - target: auto - threshold: 0.5% - patch: off - -comment: false \ No newline at end of file diff --git a/.github/config.yml b/.github/config.yml deleted file mode 100644 index e54e75aa079..00000000000 --- a/.github/config.yml +++ /dev/null @@ -1,15 +0,0 @@ -# Configuration for request-info - https://github.com/behaviorbot/request-info - -# *Required* Comment to reply with -requestInfoReplyComment: > - We need more info before we can work on this issue/pr. Can you elaborate please? - -# *OPTIONAL* default titles to check against for lack of descriptiveness -# MUST BE ALL LOWERCASE -requestInfoDefaultTitles: - - update readme.md - - updates - - help - -# *OPTIONAL* Label to be added to Issues and Pull Requests with insufficient information given -requestInfoLabelToAdd: status:needs-more-info \ No newline at end of file diff --git a/.github/label-sync.yml b/.github/label-sync.yml deleted file mode 100644 index 5fbc6acafdc..00000000000 --- a/.github/label-sync.yml +++ /dev/null @@ -1,296 +0,0 @@ -# github label sync configuration file for EE repos -# install `https://github.com/Xiphe/github-sync-labels-milestones` -- repositories: - - eventespresso/event-espresso-core - - eventespresso/ee4-events-calendar - - eventespresso/eea-authnet-accept - - eventespresso/eea-stripe-gateway - - eventespresso/eea-wait-lists - - eventespresso/eea-barcode-scanner - - eventespresso/eea-attendee-mover - - eventespresso/eea-wpuser-integration - - eventespresso/eea-mailchimp - - eventespresso/eea-gutenberg - - eventespresso/eea-people-addon - - eventespresso/ee4-infusionsoft - - eventespresso/ee4-promotions - - eventespresso/eea-ticketing - - eventespresso/eea-beaver-builder - - eventespresso/eea-flexible-payment-method - - eventespresso/ee4-mer - - eventespresso/eea-affiliatewp - - eventespresso/eea-payment-methods-pro - - eventespresso/eea-automated-upcoming-event-notifications - - eventespresso/eea-buddypress - - eventespresso/eea-events-blog - - eventespresso/eea-chase-orbital - - eventespresso/eea-vanco-pm - - eventespresso/eea-authnet-sim - - eventespresso/eventsmart.com-website - - eventespresso/eea-ipay88-gateway - - eventespresso/eea-calendar-table-template - - eventespresso/eea-category-accordian-template - - eventespresso/eea-events-grid-view-template - - eventespresso/eea-aim-echeck - - eventespresso/eea-braintree-gateway - - eventespresso/eea-evertec - - eventespresso/eea-ideal-mollie-gateway - - eventespresso/eea-migs-payment-method - - eventespresso/eea-payflow-pro-gateway - - eventespresso/eea-recurring-events-manager - - eventespresso/eea-events-table-template - - eventespresso/eea-social-buttons - - eventespresso/eea-paygov-payment-method - - eventespresso/eea-multisite - - eventespresso/connect-oauth-middleman - - eventespresso/eventespresso.com-website - - eventespresso/eea-transfirst-gateway - - eventespresso/eea-sage-pay-gateway - - eventespresso/eea-quickbooks-gateway - - eventespresso/eea-omise-payment-method - - eventespresso/eea-firstdata-payeezy - - eventespresso/eea-cybersource-gateway - - eventespresso/eea-chase-orbital - - eventespresso/eea-event-app-customization - - eventespresso/grunt-wp-plugin-buildmachine - milestones: [] - labels: - # status labels - - name: "status:needs-documentation" - color: 3297c3 - - name: "status:backlog" - color: 5c7145 - - name: "status:on-hold" - color: 4f4a33 - - name: "status:waiting-refresh" - color: 2460a7 - - name: "status:in-progress" - color: 93b343 - - name: "status:next" - color: 5c7145 - - name: "status:needs-testing" - color: eb4f21 - - name: "status:merge" - color: 66b3aa - - name: "status:review" - color: f7d500 - - name: "status:feedback-needed" - color: a16ec6 - - name: "status:needs-more-info" - color: e47e33 - - name: "status:add-sales-page" - color: 9ddde4 - - name: "status:duplicate" - color: a0a5a5 - previousNames: - - duplicate - - name: "status:stale" - color: a08e58 - - name: "status:unit-tests-required" - color: 9ddde4 - - name: "status:triage" - color: f06291 - previousNames: - - "triage" - - name: "status:please-fix" - color: c52e75 - - name: "status:potential-duplicate" - color: c2d800 - previousNames: - - "potential-duplicate" - # category labels - - name: "category:security" - color: abc2c1 - - name: "category:assets" - color: abc2c1 - previousNames: - - assets - - name: "category:payment-methods" - color: abc2c1 - previousNames: - - "category:payment-methods-&-gateways" - - name: "category:admin-pages" - color: abc2c1 - previousNames: - - "category:admin-pages-&-functionality" - - name: "category:spco-&-registration" - color: abc2c1 - - name: "category:core-plugin" - color: abc2c1 - - name: "category:frontend-ui-&-ux" - color: abc2c1 - - name: "category:admin-page-ui-&-ux" - color: abc2c1 - - name: "category:messaging-&-messengers" - color: abc2c1 - - name: "category:i18n" - color: abc2c1 - previousNames: - - i18n - - name: "category:templates-shortcodes-and-widgets" - color: abc2c1 - - name: "category:models-and-data-infrastructure" - color: abc2c1 - - name: "category:general" - color: abc2c1 - - name: "category:activation-installation-and-migration" - color: abc2c1 - - name: "category:wp-multi-site" - color: abc2c1 - - name: "category:3rd-party-integrations" - color: abc2c1 - - name: "category:decision-analytics" - color: abc2c1 - - name: "category:pue-uxip-and-licensing" - color: abc2c1 - - name: "category:unit-tests" - color: abc2c1 - - name: "category:forms-systems" - color: abc2c1 - - name: "category:reports-exporting-importing" - color: abc2c1 - - name: "category:user-management" - color: abc2c1 - - name: "category:accessibility" - color: abc2c1 - - name: "category:command-bus" - color: abc2c1 - previousNames: - - "category:command-bus-and-command-handlers" - - name: "category:gutenberg" - color: abc2c1 - previousNames: - - gutenberg - - name: "category:has-codebase-ticket" - color: abc2c1 - previousNames: - - has codebase ticket - - name: "category:community-contribution" - color: abc2c1 - previousNames: - - community-contribution - # priority labels - - name: "priority:critical 🔥" - color: b60205 - previousNames: - - "priority:critical" - - name: "priority:high" - color: f7d500 - - name: "priority:normal" - color: 93b343 - - name: "priority:low" - color: 9ddde4 - # type labels - - name: "type:support 🆘" - color: efefef - previousNames: - - "type:support" - - name: "type:bug 🐞" - color: efefef - previousNames: - - bug - - "type:bug" - - "type:bug 🐛" - - name: "type:build-process 🔨" - color: efefef - previousNames: - - build-process - - "type:build-process" - - name: "type:enhancement 🎉" - color: efefef - previousNames: - - enhancement - - "type:enhancement" - - name: "type:task ✅" - color: efefef - previousNames: - - "type:task" - - name: "type:feature-request 🙏" - color: efefef - previousNames: - - feature request - - "type:feature-request" - - name: "type:documentation 📖" - color: efefef - previousNames: - - documentation - - "type:documentation" - - name: "type:design 📐" - color: efefef - previousNames: - - "type:design" - - name: "type:user-proofing 🛡" - color: efefef - previousNames: - - "type:user-proofing" - - name: "type:theme/plugin-conflict 💥" - color: efefef - previousNames: - - "type:theme/plugin-conflict" - - name: "type:question ❓" - color: efefef - previousNames: - - question - - "type:question" - - name: "type:invalid 🦄" - color: efefef - previousNames: - - invalid - - "type:invalid" - - "type-invalid 🦄" - - name: "type:impacts-eventsmart" - color: 00f2ff - options: - ignoreMilestones: - - eventespresso/event-espresso-core - - eventespresso/ee4-events-calendar - - eventespresso/eea-authnet-accept - - eventespresso/eea-stripe-gateway - - eventespresso/eea-wait-lists - - eventespresso/eea-barcode-scanner - - eventespresso/eea-attendee-mover - - eventespresso/eea-wpuser-integration - - eventespresso/eea-mailchimp - - eventespresso/eea-gutenberg - - eventespresso/eea-people-addon - - eventespresso/ee4-infusionsoft - - eventespresso/ee4-promotions - - eventespresso/eea-ticketing - - eventespresso/eea-beaver-builder - - eventespresso/eea-flexible-payment-method - - eventespresso/ee4-mer - - eventespresso/eea-affiliatewp - - eventespresso/eea-payment-methods-pro - - eventespresso/eea-automated-upcoming-event-notifications - - eventespresso/eea-buddypress - - eventespresso/eea-events-blog - - eventespresso/eea-chase-orbital - - eventespresso/eea-vanco-pm - - eventespresso/eea-authnet-sim - - eventespresso/eventsmart.com-website - - eventespresso/eea-ipay88-gateway - - eventespresso/eea-calendar-table-template - - eventespresso/eea-category-accordian-template - - eventespresso/eea-events-grid-view-template - - eventespresso/eea-aim-echeck - - eventespresso/eea-braintree-gateway - - eventespresso/eea-evertec - - eventespresso/eea-ideal-mollie-gateway - - eventespresso/eea-migs-payment-method - - eventespresso/eea-payflow-pro-gateway - - eventespresso/eea-recurring-events-manager - - eventespresso/eea-events-table-template - - eventespresso/eea-social-buttons - - eventespresso/eea-paygov-payment-method - - eventespresso/eea-multisite - - eventespresso/connect-oauth-middleman - - eventespresso/eventespresso.com-website - - eventespresso/eea-transfirst-gateway - - eventespresso/eea-sage-pay-gateway - - eventespresso/eea-quickbooks-gateway - - eventespresso/eea-omise-payment-method - - eventespresso/eea-firstdata-payeezy - - eventespresso/eea-cybersource-gateway - - eventespresso/eea-chase-orbital - - eventespresso/eea-event-app-customization - - eventespresso/grunt-wp-plugin-buildmachine \ No newline at end of file diff --git a/.github/potential-duplicates.yml b/.github/potential-duplicates.yml deleted file mode 100644 index 419e9717b51..00000000000 --- a/.github/potential-duplicates.yml +++ /dev/null @@ -1,13 +0,0 @@ -# Label name and color to set, when potential duplicates are detected -issueLabel: "status:potential-duplicate" -labelColor: cfd3d7 - -# If similarity is higher than this threshold, issue will be marked as duplicate -threshold: 0.65 - -# Comment to post when potential duplicates are detected -referenceComment: > - Potential duplicates: - {{#issues}} - - [#{{ number }}] {{ title }} ({{ accuracy }}%) - {{/issues}} \ No newline at end of file diff --git a/.github/stale.yml b/.github/stale.yml deleted file mode 100644 index 34edf997444..00000000000 --- a/.github/stale.yml +++ /dev/null @@ -1,19 +0,0 @@ -# Number of days of inactivity before an issue becomes stale -daysUntilStale: 60 -# Number of days of inactivity before a stale issue is closed -daysUntilClose: 7 -# Issues with these labels will never be considered stale -exemptLabels: - - category:security - -# Label to use when marking an issue as stale -staleLabel: status:stale -# Comment to post when marking an issue as stale. Set to `false` to disable -markComment: > - This issue has been automatically marked as stale because it has not had - recent activity. It will be closed if no further activity occurs. Thank you - for your contributions. -# Comment to post when closing a stale issue. Set to `false` to disable -closeComment: > - This issue has been automatically closed because it has been stale for a - significant period of time without any activity. \ No newline at end of file diff --git a/.github/support.yml b/.github/support.yml deleted file mode 100644 index a2f91613495..00000000000 --- a/.github/support.yml +++ /dev/null @@ -1,14 +0,0 @@ -# Configuration for support-requests - https://github.com/dessant/support-requests - -# Label used to mark issues as support requests -supportLabel: category:support -# Comment to post on issues marked as support requests. Add a link -# to a support page, or set to `false` to disable -supportComment: > - We use the issue tracker exclusively for bug reports and feature requests. - However, this issue appears to be a support request. Please use our - [support forums](https://eventespresso/support/forums) to get help with the project. -# Whether to close issues marked as support requests -close: true -# Whether to lock issues marked as support requests -lock: false \ No newline at end of file diff --git a/.github/triage.yml b/.github/triage.yml deleted file mode 100644 index e2214b772a5..00000000000 --- a/.github/triage.yml +++ /dev/null @@ -1,3 +0,0 @@ -label: "status:triage" -assignee: sethshoultes -enabled: true \ No newline at end of file diff --git a/.nvmrc b/.nvmrc deleted file mode 100644 index 1a2f5bd2045..00000000000 --- a/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -lts/* \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index faae1d9c3d3..00000000000 --- a/.travis.yml +++ /dev/null @@ -1,121 +0,0 @@ -sudo: required - -language: php - -services: - - mysql - -cache: - apt: true - directories: - - $HOME/.composer/cache - - $HOME/.npm - -env: - global: - - WP_VERSION=latest WP_MULTISITE=0 - -before_install: - - nvm install && nvm use - - npm install npm -g - - | - if [[ "$SKIP_XDEBUG_REMOVE" != "true" ]]; then - cp $HOME/.phpenv/versions/$(phpenv global)/etc/conf.d/xdebug.ini /tmp - phpenv config-rm xdebug.ini - echo "xdebug removed"; - fi - -before_script: - - bash tests/bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION - - export PATH="$HOME/.composer/vendor/bin:$PATH" - - | - # Install the specified version of PHPUnit depending on the PHP version: - if [[ -n "$TRAVIS_PHP_VERSION" ]]; then - case "$TRAVIS_PHP_VERSION" in - 7.2|7.1|7.0|nightly) - echo "Using PHPUnit 6.1" - composer global require "phpunit/phpunit=6.1.*" - ;; - 5.6|5.5|5.4|5.3) - echo "Using PHPUnit 4.8" - composer global require "phpunit/phpunit=4.8.*" - ;; - 5.2) - # Do nothing, use default PHPUnit 3.6.x - echo "Using default PHPUnit, hopefully 3.6" - ;; - *) - echo "No PHPUnit version handling for PHP version $TRAVIS_PHP_VERSION" - exit 1 - ;; - esac - fi - - mysql --version - - phpunit --version - - phpenv versions - -script: npm run test-php - -jobs: - fast_finish: true - allow_failures: - - php: nightly - - php: 7.2 - env: - - PHP_LINT=1 - - PHP_LINT_WITH_WARNINGS=yes - include: - - stage: test - php: 7.2 - env: - - PHP_LINT=1 - - PHP_LINT_WITH_WARNINGS=no - script: - - composer install || exit 1 - - composer config-eventespressocs || exit 1 - - npm run lint-php:skip-warnings || exit 1 - - php: 7.2 - env: - - PHP_LINT=1 - - PHP_LINT_WITH_WARNINGS=yes - script: - - composer install || exit 1 - - composer config-eventespressocs || exit 1 - - npm run lint-php || exit 1 - - env: - - JAVASCRIPT_TESTS=1 - script: - - npm install || exit 1 - - npm run ci || exit 1 - - php: 7.2 - - php: 7.1 - - php: 7.0 - - php: 5.6 - - php: 5.5 - - php: 5.4 - # multisite - - php: 7.2 - env: WP_MULTISITE=1 - - php: 7.1 - env: WP_MULTISITE=1 - - php: 7.0 - env: WP_MULTISITE=1 - - php: 5.6 - env: WP_MULTISITE=1 - # wp 4.5 builds - - php: 5.6 - env: WP_VERSION=4.5 - - php: 5.6 - env: WP_VERSION=4.5 WP_MULTISITE=1 - - php: nightly - -notifications: - slack: - rooms: - secure: e2xmbwOoagh/rZIqUnx15HcTv5hZGxykvg8Tj0ENGi/bLcXgrEYxs2hpW+nzGggmSl22Eh+6wLRo62L0dEIIo1n+yknqDdAbVG7lmnX7Tc45JNgxWtSmAPzC3wAp0e9w1hy8HILPjYLxl0G7eXUvo3mKVRCCyD/Cyz5dDicE8tQ= - on_success: change - on_failure: always - on_start: always - template: - - "Build <%{build_url}|#%{build_number}> (<%{compare_url}|%{commit}>) of %{repository}@%{branch} by %{author} %{result} in %{duration}" - - "%{commit_message}" diff --git a/acceptance_tests/Helpers/BaseCoreAdmin.php b/acceptance_tests/Helpers/BaseCoreAdmin.php deleted file mode 100644 index 65680a468e7..00000000000 --- a/acceptance_tests/Helpers/BaseCoreAdmin.php +++ /dev/null @@ -1,84 +0,0 @@ -actor()->amOnAdminPage(CoreAdmin::adminUrl($page, $action, $additional_params)); - } - - - /** - * Helper method for returning an instance of the Actor. Intended to help with IDE fill out of methods. - * @return \EventEspressoAcceptanceTester; - */ - protected function actor() - { - /** @var \EventEspressoAcceptanceTester $this */ - return $this; - } - - - /** - * Use this to set the per page option for a list table page. - * Assumes you are on a page that has this field exposed. - * - * @param int|string $per_page_value - * @throws \Codeception\Exception\TestRuntimeException - */ - public function setPerPageOptionForScreen($per_page_value) - { - $this->actor()->click(CoreAdmin::WP_SCREEN_SETTINGS_LINK_SELECTOR); - $this->actor()->fillField(CoreAdmin::WP_SCREEN_SETTINGS_PER_PAGE_FIELD_SELECTOR, $per_page_value); - $this->actor()->click(CoreAdmin::WP_SCREEN_OPTIONS_APPLY_SETTINGS_BUTTON_SELECTOR); - $this->actor()->wait(8); - } - - - - /** - * Use this to append a given value to a wpEditor instance. - * How it works is it first switched the instance to the text (or html) view so that the textarea is exposed and - * the value is added to the text area. - * - * @param $field_reference - * @param $value - * @throws \Codeception\Exception\ElementNotFound - */ - public function appendToWPEditorField($field_reference, $value) - { - $this->actor()->click(CoreAdmin::wpEditorTextTabSelector($field_reference)); - $this->actor()->appendField(CoreAdmin::wpEditorTextAreaSelector($field_reference), $value); - } - - - /** - * Use to select and submit the given bulk action. - * @param string $bulk_action_option - */ - public function submitBulkActionOnListTable($bulk_action_option) - { - $this->actor()->selectOption( - CoreAdmin::SELECTOR_LIST_TABLE_BULK_ACTION_FIELD, - $bulk_action_option - ); - $this->actor()->click(CoreAdmin::SELECTOR_LIST_TABLE_BULK_ACTTION_APPLY); - } -} diff --git a/acceptance_tests/Helpers/Checkout.php b/acceptance_tests/Helpers/Checkout.php deleted file mode 100644 index 052511459b2..00000000000 --- a/acceptance_tests/Helpers/Checkout.php +++ /dev/null @@ -1,87 +0,0 @@ -actor()->fillField(CheckoutPage::firstNameFieldSelectorForAttendeeNumber($attendee_number, $admin), $value); - } - - /** - * @param $value - * @param int $attendee_number - * @param bool $admin Used to indicate whether we're filling out the field from the context of the admin or not. - */ - public function fillOutLastNameFieldForAttendee($value, $attendee_number = 1, $admin = false) - { - $this->actor()->fillField(CheckoutPage::lastNameFieldSelectorForAttendeeNumber($attendee_number, $admin), $value); - } - - /** - * @param $value - * @param int $attendee_number - * @param bool $admin Used to indicate whether we're filling out the field from the context of the admin or not. - */ - public function fillOutEmailFieldForAttendee($value, $attendee_number = 1, $admin = false) - { - $this->actor()->fillField(CheckoutPage::emailFieldSelectorForAttendeeNumber($attendee_number, $admin), $value); - } - - - /** - * Clicks the next registration step button. - */ - public function goToNextRegistrationStep() - { - $this->actor()->click(CheckoutPage::NEXT_STEP_BUTTON_SELECTOR); - } - - - /** - * Selects the payment option for the given payment method slug. - * - * @param string $payment_method_slug - * @param bool $verify_selected If true, this will wait for the "Important Information" info box after the - * payment option select box is complete. Otherwise its up to calling code to - * wait for whatever is needed after selecting the payment method. - */ - public function selectPaymentOptionFor($payment_method_slug = 'invoice', $verify_selected = true) - { - $this->waitForElementVisible(CheckoutPage::SELECTOR_PAYMENT_OPTIONS_CONTAINER); - $this->wait(5); - $this->actor()->selectOption( - CheckoutPage::PAYMENT_METHOD_STEP_FORM, - $payment_method_slug - ); - if ($verify_selected) { - $this->actor()->waitForText('Important information regarding your payment'); - } - } - - - /** - * Submits the payment options step form. - * Assumes the actor is in the context of the payment options SPCO step. - */ - public function submitPaymentOptionsRegistrationStepForm() - { - $this->actor()->submitForm(CheckoutPage::PAYMENT_METHOD_STEP_FORM, array()); - } - -} \ No newline at end of file diff --git a/acceptance_tests/Helpers/CountrySettingsAdmin.php b/acceptance_tests/Helpers/CountrySettingsAdmin.php deleted file mode 100644 index 1403a01cc1d..00000000000 --- a/acceptance_tests/Helpers/CountrySettingsAdmin.php +++ /dev/null @@ -1,64 +0,0 @@ -actor()->amOnAdminPage(CountrySettings::url($additional_params)); - } - - - /** - * Instructs the actor to select the given decimal places radio option. - * Assumes the actor is already on the country settings page. - * @param string $decimal_places - * @param string $country_code - */ - public function setCurrencyDecimalPlacesTo($decimal_places = '2', $country_code = 'US') - { - $this->actor()->click(CountrySettings::currencyDecimalPlacesRadioField($decimal_places, $country_code)); - } - - - /** - * Instructs the actor to select the given decimal mark radio option. - * Assumes the actor is already on the country settings page. - * @param string $decimal_mark - */ - public function setCurrencyDecimalMarkTo($decimal_mark = '.') - { - $this->actor()->click(CountrySettings::currencyDecimalMarkRadioField($decimal_mark)); - } - - - /** - * Instructs the actor to select the given thousands separator radio option. - * Assumes the actor is already on the country settings page. - * @param string $thousands_seperator - */ - public function setCurrencyThousandsSeparatorTo($thousands_seperator = ',') - { - $this->actor()->click(CountrySettings::currencyThousandsSeparatorField($thousands_seperator)); - } - - - /** - * Clicks the country settings submit button. - * Assumes the actor is on the country settings admin page. - */ - public function saveCountrySettings() - { - $this->actor()->click(CountrySettings::COUNTRY_SETTINGS_SAVE_BUTTON); - //no indicator on the page when stuff has been updated so just give a bit of time for it to finish. - $this->actor()->wait(10); - } -} \ No newline at end of file diff --git a/acceptance_tests/Helpers/EventsAdmin.php b/acceptance_tests/Helpers/EventsAdmin.php deleted file mode 100644 index e1e7cb1f012..00000000000 --- a/acceptance_tests/Helpers/EventsAdmin.php +++ /dev/null @@ -1,146 +0,0 @@ -actor()->amOnAdminPage(EventsPage::defaultEventsListTableUrl($additional_params)); - } - - - /** - * Triggers the publishing of the Event. - */ - public function publishEvent() - { - $this->actor()->scrollTo(EventsPage::EVENT_EDITOR_TITLE_FIELD_SELECTOR); - $this->actor()->wait(3); - $this->actor()->click(EventsPage::EVENT_EDITOR_PUBLISH_BUTTON_SELECTOR); - $this->actor()->waitForText('Event published.', 30); - } - - - /** - * Triggers saving the Event. - */ - public function saveEvent() - { - $this->actor()->scrollTo(EventsPage::EVENT_EDITOR_TITLE_FIELD_SELECTOR); - $this->actor()->wait(2); - $this->actor()->click(EventsPage::EVENT_EDITOR_SAVE_BUTTON_SELECTOR); - } - - - /** - * Navigates the actor to the event list table page and will attempt to edit the event for the given title. - * First this will search using the given title and then attempt to edit from the results of the search. - * - * Assumes actor is already logged in. - * @param $event_title - */ - public function amEditingTheEventWithTitle($event_title) - { - $this->amOnDefaultEventsListTablePage(); - $this->actor()->fillField(EventsPage::EVENT_LIST_TABLE_SEARCH_INPUT_SELECTOR, $event_title); - $this->actor()->click(CoreAdmin::LIST_TABLE_SEARCH_SUBMIT_SELECTOR); - $this->actor()->waitForText($event_title, 15); - $this->actor()->click(EventsPage::eventListTableEventTitleEditLinkSelectorForTitle($event_title)); - } - - - /** - * Navigates the user to the single event page (frontend view) for the given event title via clicking the "View" - * link for the event in the event list table. - * Assumes the actor is already logged in and on the Event list table page. - * - * @param string $event_title - */ - public function amOnEventPageAfterClickingViewLinkInListTableForEvent($event_title) - { - $this->actor()->moveMouseOver(EventsPage::eventListTableEventTitleEditLinkSelectorForTitle($event_title)); - $this->actor()->click(EventsPage::eventListTableEventTitleViewLinkSelectorForTitle($event_title)); - } - - - /** - * Used to retrieve the event id for the event via the list table and for the given event. - * @param string $event_title - */ - public function observeEventIdInListTableForEvent($event_title) - { - return $this->actor()->observeValueFromInputAt(EventsPage::eventListTableEventIdSelectorForTitle($event_title)); - } - - - /** - * This performs the click action on the gear icon that triggers the advanced settings view state. - * Assumes the actor is already logged in and editing an event. - * - * @param int $row_number What ticket row to toggle open/close. - */ - public function toggleAdvancedSettingsViewForTicketRow($row_number = 1) - { - $this->actor()->click(EventsPage::eventEditorTicketAdvancedDetailsSelector($row_number)); - } - - - /** - * Toggles the TKT_is_taxable checkbox for the ticket in the given row. - * Assumes the actor is already logged in and editing an event and that the advanced settings view state for that - * ticket is "open". - * - * @param int $row_number What ticket row to toggle the checkbox for. - */ - public function toggleTicketIsTaxableForTicketRow($row_number = 1) - { - $this->actor()->click(EventsPage::eventEditorTicketTaxableCheckboxSelector($row_number)); - } - - - /** - * Use to change the default registration status for the event. - * Assumes the view is already on the event editor. - * @param $registration_status - */ - public function changeDefaultRegistrationStatusTo($registration_status) - { - $this->actor()->selectOption( - EventsPage::EVENT_EDITOR_DEFAULT_REGISTRATION_STATUS_FIELD_SELECTOR, - $registration_status - ); - } - - - /** - * Use this from the context of the event editor to select the given custom template for a given message type and - * messenger. - * - * @param string $message_type_label The visible label for the message type (eg Registration Approved) - * @param string $messenger_slug The slug for the messenger (eg 'email') - * @param string $custom_template_label The visible label in the select input for the custom template you want - * selected. - */ - public function selectCustomTemplateFor($message_type_label, $messenger_slug, $custom_template_label) - { - $this->actor()->click(EventsPage::eventEditorNotificationsMetaBoxMessengerTabSelector($messenger_slug)); - $this->actor()->selectOption( - EventsPage::eventEditorNotificationsMetaBoxSelectSelectorForMessageType($message_type_label), - $custom_template_label - ); - } -} \ No newline at end of file diff --git a/acceptance_tests/Helpers/MessagesAdmin.php b/acceptance_tests/Helpers/MessagesAdmin.php deleted file mode 100644 index 593d460852b..00000000000 --- a/acceptance_tests/Helpers/MessagesAdmin.php +++ /dev/null @@ -1,303 +0,0 @@ -actor()->amOnAdminPage(MessagesPage::messageActivityListTableUrl($additional_params)); - } - - /** - * @param string $additional_params Any additional request parameters for the generated url should be included as - * a string. - */ - public function amOnDefaultMessageTemplateListTablePage($additional_params = '') - { - $this->actor()->amOnAdminPage(MessagesPage::defaultMessageTemplateListTableUrl($additional_params)); - } - - - /** - * @param string $additional_params Any additional request parameters for the generated url should be included as - * a string. - */ - public function amOnCustomMessageTemplateListTablePage($additional_params = '') - { - $this->actor()->amOnAdminPage(MessagesPage::customMessageTemplateListTableUrl($additional_params)); - } - - - /** - * Directs to message settings page - */ - public function amOnMessageSettingsPage() - { - $this->actor()->amOnAdminPage(MessagesPage::messageSettingsUrl()); - } - - - public function activateMessageTypeForMessenger($message_type_slug, $messenger_slug = 'email') - { - $this->actor()->dragAndDrop( - MessagesPage::draggableSettingsBoxSelectorForMessageTypeAndMessenger($message_type_slug, $messenger_slug), - MessagesPage::MESSAGES_SETTINGS_ACTIVE_MESSAGE_TYPES_CONTAINER_SELECTOR - ); - } - - - /** - * Assumes you are already on the list table page that has the ui for editing the template. - * @param string $message_type_slug - * @param string $context [optional] if you want to click directly to the given context in the editor - */ - public function clickToEditMessageTemplateByMessageType($message_type_slug, $context = '') - { - $this->actor()->click(MessagesPage::editMessageTemplateClassByMessageType($message_type_slug, $context)); - } - - - /** - * Use this action to verify that the count for the given text in the specified field is as expected. For example - * filling the condition of, "There should only be 1 instance of `someaddress@email.com` in all the 'to' column. - * - * @param int $expected_occurence_count - * @param string $text_to_check_for - * @param string $field - * @param string $message_type_label - * @param string $message_status - * @param string $messenger - * @param string $context - */ - public function verifyMatchingCountofTextInMessageActivityListTableFor( - $expected_occurence_count, - $text_to_check_for, - $field, - $message_type_label, - $message_status = MessagesPage::MESSAGE_STATUS_SENT, - $messenger = 'Email', - $context = 'Event Admin' - ) { - $elements = $this->actor()->grabMultiple(MessagesPage::messagesActivityListTableCellSelectorFor( - $field, - $message_type_label, - $message_status, - $messenger, - $context, - $text_to_check_for, - 0 - )); - $actual_count = count($elements); - $this->actor()->assertEquals( - $expected_occurence_count, - $actual_count, - sprintf( - 'Expected %s of the %s text for the %s field but there were actually %s counted.', - $expected_occurence_count, - $text_to_check_for, - $field, - $actual_count - ) - ); - } - - - /** - * This will create a custom message template for the given messenger and message type from the context of the - * default (global) message template list table. - * Also takes care of verifying the template was created. - * @param string $message_type_label - * @param string $messenger_label - */ - public function createCustomMessageTemplateFromDefaultFor($message_type_label, $messenger_label) - { - $this->amOnDefaultMessageTemplateListTablePage(); - $this->actor()->click( - MessagesPage::createCustomButtonForMessageTypeAndMessenger( - $message_type_label, - $messenger_label - ) - ); - $this->actor()->seeInField('#title', 'New Custom Template'); - } - - - /** - * This switches the context of the current messages template to the given reference. - * @param string $context_reference This should be the visible label for the option. - */ - public function switchContextTo($context_reference) - { - $this->actor()->selectOption(MessagesPage::MESSAGES_CONTEXT_SWITCHER_SELECTOR, $context_reference); - $this->actor()->click(MessagesPage::MESSAGES_CONTEXT_SWITCHER_BUTTON_SELECTOR); - $this->actor()->waitForText($context_reference, 10, 'h1'); - } - - - /** - * Toggles Context so its turned off or on (depending on where it started) and verifies the expected state after - * toggling. - * - * @param string $context_string What context is being switched (used for the expected state text) - * @param bool $expected_state_is_active Used to indicate whether the expected state is active (true) or inactive - * (false) - */ - public function toggleContextState($context_string, $expected_state_is_active = true) - { - $this->actor()->scrollTo(MessagesPage::MESSAGES_CONTEXT_SWITCHER_SELECTOR); - $this->actor()->click(MessagesPage::MESSAGES_CONTEXT_ACTIVE_STATE_TOGGLE); - if ($expected_state_is_active) { - $this->actor()->waitForText("The template for $context_string is currently active."); - } else { - $this->actor()->waitForText("The template for $context_string is currently inactive"); - } - } - - - /** - * Triggers saving the message template. - * @param bool $and_close Use to indicate to click the Save and Close button. - */ - public function saveMessageTemplate($and_close = false) - { - $this->actor()->scrollTo(MessagesPage::MESSAGES_CONTEXT_SWITCHER_SELECTOR); - if ($and_close) { - $this->actor()->click('Save and Close'); - } else { - $this->actor()->click('Save'); - } - $this->actor()->waitForText('successfully updated'); - } - - - /** - * This takes care of clicking the View Message icon for the given parameters. - * Assumes you are already viewing the messages activity list table. - * @param $message_type_label - * @param $message_status - * @param string $messenger - * @param string $context - * @param int $number_in_set - */ - public function viewMessageInMessagesListTableFor( - $message_type_label, - $message_status = MessagesPage::MESSAGE_STATUS_SENT, - $messenger = 'Email', - $context = 'Event Admin', - $number_in_set = 1 - ) { - $this->actor()->click(MessagesPage::messagesActivityListTableViewButtonSelectorFor( - $message_type_label, - $message_status, - $messenger, - $context, - $number_in_set - )); - } - - - /** - * Takes care of deleting a message matching the given parameters via the message activity list table. - * Assumes you are already viewing the messages activity list table. - * @param $message_type_label - * @param $message_status - * @param string $messenger - * @param string $context - * @param int $number_in_set - */ - public function deleteMessageInMessagesListTableFor( - $message_type_label, - $message_status = MessagesPage::MESSAGE_STATUS_SENT, - $messenger = 'Email', - $context = 'Event Admin', - $number_in_set = 1 - ) { - $delete_action_selector = MessagesPage::messagesActivityListTableDeleteActionSelectorFor( - $message_type_label, - $message_status, - $messenger, - $context, - $number_in_set - ); - $cell_selector = MessagesPage::messagesActivityListTableCellSelectorFor( - 'to', - $message_type_label, - $message_status, - $messenger, - $context, - '', - $number_in_set - ); - $this->actor()->scrollTo($cell_selector, 0, -30); - $this->actor()->moveMouseOver( - $cell_selector, - 5, - 5 - ); - $this->actor()->waitForElementVisible( - $delete_action_selector - ); - $this->actor()->click( - $delete_action_selector - ); - $this->actor()->waitForText('successfully deleted', 20); - } - - - /** - * Assuming you have already triggered the view modal for a single message from the context of the message activity - * list table, this will take care of validating the given text is in that window. - * @param string $text_to_view - */ - public function seeTextInViewMessageModal($text_to_view, $should_not_see = false) - { - $this->actor()->wait(2); - $this->actor()->waitForElementVisible('.ee-admin-dialog-container-inner-content'); - $this->actor()->switchToIframe('message-view-window'); - $should_not_see ? $this->actor()->dontSee($text_to_view) : $this->actor()->see($text_to_view); - $this->actor()->switchToIframe(); - } - - - /** - * This returns the value for the link at the given selector in the message modal. - * @param string $selector (any selector string accepted by WebDriver) - */ - public function observeLinkAtSelectorInMessageModal($selector) - { - $this->actor()->wait(2); - $this->actor()->waitForElementVisible('.ee-admin-dialog-container-inner-content'); - $this->actor()->switchToIframe('message-view-window'); - $link = $this->actor()->observeLinkUrlAt($selector); - $this->actor()->switchToIframe(); - return $link; - } - - - /** - * Assuming you have already triggered the view modal for a single message from the context of the message activity - * list table, this will take care of validating the given text is NOT that window. - * @param string $text_to_view - */ - public function dontSeeTextInViewMessageModal($text_to_view) - { - $this->seeTextInViewMessageModal($text_to_view, true); - } - - - public function dismissMessageModal() - { - $this->actor()->executeJs('window.dialogHelper.closeModal()'); - } -} diff --git a/acceptance_tests/Helpers/RegistrationsAdmin.php b/acceptance_tests/Helpers/RegistrationsAdmin.php deleted file mode 100644 index 8e0d05502fb..00000000000 --- a/acceptance_tests/Helpers/RegistrationsAdmin.php +++ /dev/null @@ -1,153 +0,0 @@ -actor()->checkOption( - RegistrationsAdminPage::listTableCheckBoxSelectorForRegistrationId($registration_id) - ); - } - } - - - /** - * Navigates the actor to the default registration list table page. - * @param string $additional_params - */ - public function amOnDefaultRegistrationsListTableAdminPage($additional_params = '') - { - $this->actor()->amOnAdminPage( - RegistrationsAdminPage::registrationsDefaultAdminListTableUrl($additional_params) - ); - //wait for page to fully load - $this->actor()->wait(5); - } - - - /** - * Will enter the provided value in the registration list table search field and execute a search for that value. - * @param string $search_text - */ - public function searchForRegistrationOnRegistrationListTableWithText($search_text) - { - $this->amOnDefaultRegistrationsListTableAdminPage(); - $this->actor()->fillField(RegistrationsAdminPage::SEARCH_INPUT_SELECTOR_LIST_TABLE_REGISTRATION, $search_text); - $this->actor()->click(CoreAdmin::LIST_TABLE_SEARCH_SUBMIT_SELECTOR); - $this->actor()->waitForText('Displaying search results for'); - } - - - - /** - * This will filter the registration list table to view registrations for the given event id. - * Assumption is made that you are logged into the admin but you do not need to be on the registration list table - * page. - * - * @param int $event_id The id of the event viewing registrations for. - */ - public function amViewingRegistrationsForEvent($event_id) - { - $this->actor()->amOnDefaultEventsListTablePage(); - $this->actor()->click(EventsAdmin::listTableActionLinkRegistrationsForEvent($event_id)); - $this->actor()->waitForText('Viewing registrations for the event'); - } - - - /** - * This helper will initiate registering for the given event via the backend. - * @param int $event_id The event to initiate registration for. - */ - public function amOnAdminRegistrationPageForEvent($event_id) - { - $this->actor()->amViewingRegistrationsForEvent($event_id); - $this->actor()->click(RegistrationsAdminPage::BUTTON_ADD_NEW_REGISTRATION); - $this->actor()->waitForText('Adding Registration For'); - } - - - - /** - * This clicks the View Details Link for Registration with the given Id - * @param $registration_id - */ - public function clickViewDetailsLinkForRegistrationWithId($registration_id) - { - $this->actor()->click(RegistrationsAdminPage::viewDetailsLinkSelectorForRegistrationId($registration_id)); - } - - - /** - * /** - * This assumes you are on the admin details page for a registration in EE. It selects the given status in the - * dropdown for changing registration status. - * - * @param string $status_label_or_value Either the label for the dropdown option or the value for the option. - * @param $status_label_or_value - */ - public function selectRegistrationStatusOnRegistrationDetailsPageFor($status_label_or_value) - { - $this->actor()->selectOption( - RegistrationsAdminPage::DROPDOWN_REGISTRATION_STATUS, - $status_label_or_value - ); - } - - - /** - * This selects (or deselects) the "Send Related Messages" checkbox on the Registration Details page. - * @param bool $send_related_messages - */ - public function selectSendRelatedMessagesOptionOnRegistrationDetailsPage($send_related_messages = true) - { - $send_related_messages - ? $this->actor()->selectOption( - RegistrationsAdminPage::DROPDOWN_SEND_RELATED_MESSAGES, - 'Yes' - ) - : $this->actor()->selecOption( - RegistrationsAdminPage::DROPDOWN_SEND_RELATED_MESSAGES, - 'No' - ); - } - - - - /** - * This assumes you are on the admin details page for a registration in EE. It selects the given status in the - * dropdown for changing registration status and submits the change. - * - * @param string $status_label_or_value Either the label for the dropdown option or the value for the option. - * @param bool $send_related_messages Whether or not to send related messages after changing the bulk action. - */ - public function changeRegistrationStatusOnRegistrationDetailsPageTo( - $status_label_or_value, - $send_related_messages = true - ) { - $this->actor()->selectRegistrationStatusOnRegistrationDetailsPageFor($status_label_or_value); - $this->actor()->selectSendRelatedMessagesOptionOnRegistrationDetailsPage($send_related_messages); - $this->actor()->click(RegistrationsAdminPage::BUTTON_UPDATE_REGISTRATION_STATUS); - $this->actor()->waitForText('Registration status has been set to'); - } - -} \ No newline at end of file diff --git a/acceptance_tests/Helpers/TicketSelector.php b/acceptance_tests/Helpers/TicketSelector.php deleted file mode 100644 index ebc7373d018..00000000000 --- a/acceptance_tests/Helpers/TicketSelector.php +++ /dev/null @@ -1,34 +0,0 @@ -actor()->selectOption(TicketSelectorElements::ticketOptionByEventIdSelector($event_id), $quantity); - } - - - /** - * Used to submit the ticket selection for the given event id (so this can be used on an event archive page). - * @param int|string $event_id - */ - public function submitTicketSelectionsForEventId($event_id) - { - $this->actor()->click(TicketSelectorElements::ticketSelectionSubmitSelectorByEventId($event_id)); - } -} \ No newline at end of file diff --git a/acceptance_tests/Page/Checkout.php b/acceptance_tests/Page/Checkout.php deleted file mode 100644 index faae8d9eabf..00000000000 --- a/acceptance_tests/Page/Checkout.php +++ /dev/null @@ -1,83 +0,0 @@ - "//input[@id='title']"]; - - /** - * Selector for the publish submit button in the event editor. - * @var string - */ - const EVENT_EDITOR_PUBLISH_BUTTON_SELECTOR = ['xpath'=>"//div[@id='major-publishing-actions']//input[@id='publish']"]; - - - /** - * Selector for the save button in the event editor - */ - const EVENT_EDITOR_SAVE_BUTTON_SELECTOR = ['xpath' => "//div[@id='minor-publishing-actions']//input[@id='save-post']"]; - - - /** - * @var string - */ - const EVENT_EDITOR_DEFAULT_REGISTRATION_STATUS_FIELD_SELECTOR = '#EVT_default_registration_status'; - - /** - * Selector for the view link after publishing an event. - * @var string - */ - const EVENT_EDITOR_VIEW_LINK_AFTER_PUBLISH_SELECTOR = "//span[@id='sample-permalink']/a"; - - - /** - * Selector for the ID of the event in the event editor - * @var string - */ - const EVENT_EDITOR_EVT_ID_SELECTOR = "//input[@id='post_ID']"; - - - /** - * Selector for the search input on the event list table page. - * @var string - */ - const EVENT_LIST_TABLE_SEARCH_INPUT_SELECTOR = '#toplevel_page_espresso_events-search-input'; - - - - - /** - * @param string $additional_params - * @return string - */ - public static function defaultEventsListTableUrl($additional_params = '') - { - return self::adminUrl('espresso_events', 'default', $additional_params); - } - - - /** - * The selector for the DTTname field for the given row in the event editor. - * @param int $row_number - * @return string - */ - public static function eventEditorDatetimeNameFieldSelector($row_number = 1) - { - return self::eventEditorDatetimeFieldSelectorForField('DTT_name', $row_number); - } - - - /** - * The selector for the DTT_EVT_start field for the given row in the event editor.d - * @param int $row_number - * @return string - */ - public static function eventEditorDatetimeStartDateFieldSelector($row_number = 1) - { - return self::eventEditorDatetimeFieldSelectorForField('DTT_EVT_start', $row_number); - } - - - /** - * Wrapper for getting the selector for a given field and given row of a datetime in the event editor. - * - * @param string $field_name - * @param int $row_number - * @return string - */ - public static function eventEditorDatetimeFieldSelectorForField($field_name, $row_number = 1) - { - return "//input[@id='event-datetime-$field_name-$row_number']"; - } - - - /** - * The selector for the TKT_name field for the given display row in the event editor. - * @param int $row_number - * @return string - */ - public static function eventEditorTicketNameFieldSelector($row_number = 1) - { - return self::eventEditorTicketFieldSelectorForFieldInDisplayRow('TKT_name', $row_number); - } - - - /** - * Selector for the TKT_base_price field for the given display row in the event editor. - * @param int $row_number - * @return string - */ - public static function eventEditorTicketPriceFieldSelector($row_number = 1) - { - return self::eventEditorTicketFieldSelectorForFieldInDisplayRow('TKT_base_price', $row_number); - } - - - /** - * Selector for the TKT_qty field for the given display row in the event editor. - * @param int $row_number - * @return string - */ - public static function eventEditorTicketQuantityFieldSelector($row_number = 1) - { - return self::eventEditorTicketFieldSelectorForFieldInDisplayRow('TKT_qty', $row_number); - } - - - /** - * Selector for the advanced details toggle for the ticket for the given display row in the event editor. - * @param int $row_number - * @return string - */ - public static function eventEditorTicketAdvancedDetailsSelector($row_number = 1) - { - return "//tr[@id='display-ticketrow-$row_number']//span[contains(@class, 'gear-icon')]"; - } - - - /** - * Selector for the subtotal amount for the given display row of the ticket in the event editor. - * @param int $row_number - * @return string - */ - public static function eventEditorTicketAdvancedDetailsSubtotalSelector($row_number = 1) - { - return "//span[@id='price-total-amount-$row_number']"; - } - - - /** - * Selector for the Total element for the given display row of the ticket in the event editor. - * @param int $row_number - * @return string - */ - public static function eventEditorTicketAdvancedDetailsTotalSelector($row_number = 1) - { - return "//span[@id='price-total-amount-$row_number']"; - } - - - /** - * Selector for the taxable selector for the ticket for the given display row in the event editor. - * @param int $row_number - * @return string - */ - public static function eventEditorTicketTaxableCheckboxSelector($row_number = 1) - { - return "//input[@id='edit-ticket-TKT_taxable-$row_number']"; - } - - - /** - * This returns the xpath locater for the Tax amount display container within the advanced settings view for the - * given ticket (row) and the given tax id (PRC_ID). - * - * @param int $tax_id The PRC_ID for the tax you want the locater for. Note, this defaults to the default tax - * setup on a fresh install. - * @param int $row_number What row representing the ticket you want the locator for. - * @return string - */ - public static function eventEditorTicketTaxAmountDisplayForTaxIdAndTicketRowSelector($tax_id = 2, $row_number = 1) - { - return "//span[@id='TKT-tax-amount-display-$tax_id-$row_number']"; - } - - - /** - * Wrapper for getting the selector for a given field and given display row of a ticket in the event editor. - * @param $field_name - * @param int $row_number - * @return string - */ - public static function eventEditorTicketFieldSelectorForFieldInDisplayRow($field_name, $row_number = 1) - { - return "//tr[@id='display-ticketrow-$row_number']//input[contains(@class, 'edit-ticket-$field_name')]"; - } - - - /** - * Returns the selector for the event title edit link in the events list table for the given Event Title. - * @param string $event_title - * @return string - */ - public static function eventListTableEventTitleEditLinkSelectorForTitle($event_title) - { - return "//td[contains(@class, 'column-name')]/strong/a[text()='$event_title']"; - } - - - /** - * Locator for for the ID column in the event list table for a given event title. - * @param string $event_title - * @return string - */ - public static function eventListTableEventIdSelectorForTitle($event_title) - { - return "//td[contains(@class, 'column-name')]/strong/a[text()='$event_title']" - . "//ancestor::tr/th[contains(@class, 'check-column')]/input"; - } - - - /** - * Locator for the view link in the row of an event list table for the given event title. - * @param string $event_title - * @return string - */ - public static function eventListTableEventTitleViewLinkSelectorForTitle($event_title) - { - return "//td[contains(@class, 'column-name')]/strong/a[text()='$event_title']" - . "//ancestor::td//span[@class='view']/a"; - } - - - /** - * Locator for the messenger tab in the Notifications metabox in the event editor. - * @param string $messenger_slug The slug for the messenger (it's reference slug). - * @return string - */ - public static function eventEditorNotificationsMetaBoxMessengerTabSelector($messenger_slug) - { - return "//div[@id='espresso_events_Messages_Hooks_Extend_messages_metabox_metabox']" - . "//a[@rel='ee-tab-$messenger_slug']"; - } - - - /** - * Locator for the select input within the notifications metabox. - * Note, this assumes the tab content for the related messenger is already visible. - * @param string $message_type_label The message type label (visible string in the table) you want the selector for. - * @return string - */ - public static function eventEditorNotificationsMetaBoxSelectSelectorForMessageType($message_type_label) - { - return "//div[@id='espresso_events_Messages_Hooks_Extend_messages_metabox_metabox']" - . "//table[@class='messages-custom-template-switcher']" - . "//tr/td[contains(.,'Registration Approved')]" - . "//ancestor::tr//select[contains(@class,'message-template-selector')]"; - } - - - /** - * Returns the selector for the action link to the registrations list table view filtered by the given event_id. - * Assumes one is in the context of the Events List Table - * @param int $event_id - * @return string - */ - public static function listTableActionLinkRegistrationsForEvent($event_id) - { - return "//tbody[@id='the-list']/tr/td[contains(@class, 'column-id') and contains(.,$event_id)]" - . "//ancestor::tr/td//a[div[contains(@class, 'dashicons-groups')]]"; - } -} diff --git a/acceptance_tests/Page/MessagesAdmin.php b/acceptance_tests/Page/MessagesAdmin.php deleted file mode 100644 index 171e5f7af2b..00000000000 --- a/acceptance_tests/Page/MessagesAdmin.php +++ /dev/null @@ -1,305 +0,0 @@ - 0 ? Locator::elementAt($selector, $number_in_set) : $selector; - } - - - /** - * Selector for the Create Custom button found in the message template list table. - * @param string $message_type_label - * @param string $messenger_label - * @return string - */ - public static function createCustomButtonForMessageTypeAndMessenger($message_type_label, $messenger_label) - { - $selector = "//tr/td[contains(@class, 'message_type') and text()='$message_type_label']" - . "//ancestor::tr/td[contains(@class, 'messenger') and contains(., '$messenger_label')]" - . "//ancestor::tr/td/a[@class='button button-small']"; - return $selector; - } - - - /** - * Note, this could potentially match multiple buttons in the view so the selector is intentionally restricted to - * the FIRST match (which will be the latest message sent if the table is default sorted). - * - * @param string $message_type_label The visible message type label for the row you want to match - * @param string $message_status The status of the message for the row you want to match. - * @param string $messenger The visible messenger label for the row you want to match. - * @param string $context The visible context label for the row you want to match. - * @param int $number_in_set It's possible that the given parameters could match multiple items in the - * view. This allows you to indicate which item from the set to match. - * @return string - * @throws \InvalidArgumentException - */ - public static function messagesActivityListTableViewButtonSelectorFor( - $message_type_label, - $message_status = self::MESSAGE_STATUS_SENT, - $messenger = 'Email', - $context = 'Event Admin', - $number_in_set = 1 - ) { - $selector = self::messagesActivityListTableCellSelectorFor( - 'action', - $message_type_label, - $message_status, - $messenger, - $context, - '', - $number_in_set - ); - $selector .= "/a/span[contains(@class, 'ee-message-action-link-view')" - . " and not(contains(@class, 'ee-message-action-link-view_transaction'))]"; - return $selector; - } - - - /** - * Locator for the delete action link for a message item in the message activity list table. - * Note: The link is not visible by default, so the column would need hovered over for the link to appear. - * - * @param $message_type_label - * @param string $message_status - * @param string $messenger - * @param string $context - * @param int $number_in_set - * @return string - * @throws \InvalidArgumentException - */ - public static function messagesActivityListTableDeleteActionSelectorFor( - $message_type_label, - $message_status = self::MESSAGE_STATUS_SENT, - $messenger = 'Email', - $context = 'Event Admin', - $number_in_set = 1 - ) { - $selector = self::messagesActivityListTableCellSelectorFor( - 'to', - $message_type_label, - $message_status, - $messenger, - $context, - '', - $number_in_set - ); - $selector .= "/div/span[@class='delete']/a"; - return $selector; - } - - - - /** - * Returns the input selector for a given field in the message template editor. - * Assumes one is already viewing the Message Template Editor. - * @param string $field - * @return string - */ - public static function messageInputFieldSelectorFor($field) - { - return "//div[@id='post-body']//input[@id='$field-content']"; - } - - - /** - * Wrapper for self::messageInputFieldSelectorFor('to') that takes care of getting the input for the To field. - */ - public static function messageTemplateToFieldSelector() - { - return self::messageInputFieldSelectorFor('to'); - } -} \ No newline at end of file diff --git a/acceptance_tests/Page/RegistrationsAdmin.php b/acceptance_tests/Page/RegistrationsAdmin.php deleted file mode 100644 index 1bb281ae812..00000000000 --- a/acceptance_tests/Page/RegistrationsAdmin.php +++ /dev/null @@ -1,58 +0,0 @@ -loginAsAdmin(20); -$I->amOnMessageSettingsPage(); -$I->selectOption(MessagesAdmin::GLOBAL_MESSAGES_SETTINGS_ON_REQUEST_SELECTION_SELECTOR, '1'); -$I->click(MessagesAdmin::GLOBAL_MESSAGES_SETTINGS_SUBMIT_SELECTOR); diff --git a/acceptance_tests/tests/b-TestRegistrationSummaryCept.php b/acceptance_tests/tests/b-TestRegistrationSummaryCept.php deleted file mode 100644 index 290f0160071..00000000000 --- a/acceptance_tests/tests/b-TestRegistrationSummaryCept.php +++ /dev/null @@ -1,158 +0,0 @@ -wantTo('Test that the Registration Summary Message type works as expected.'); - -//need the MER plugin active for this test (we'll deactivate it after). -$I->ensurePluginActive( - 'event-espresso-mer-multi-event-registration', - 'activated' -); - -//k now we need to make sure the registration multi-status message type is active because it isn't by default -$I->loginAsAdmin(); -$I->amOnMessageSettingsPage(); -$I->activateMessageTypeForMessenger('registration_summary'); - - -//k now we need to create a couple events to use for testing. -$I->amOnDefaultEventsListTablePage(); -$I->click(EventsAdmin::ADD_NEW_EVENT_BUTTON_SELECTOR); -$I->fillField(EventsAdmin::EVENT_EDITOR_TITLE_FIELD_SELECTOR, 'Event RSM A'); -$I->publishEvent(); -$event_a_link = $I->observeLinkUrlAt(EventsAdmin::EVENT_EDITOR_VIEW_LINK_AFTER_PUBLISH_SELECTOR); -$event_a_id = $I->observeValueFromInputAt(EventsAdmin::EVENT_EDITOR_EVT_ID_SELECTOR); - -//do another event except we'll set the default reg status to not approved. -$I->amOnDefaultEventsListTablePage(); -$I->click(EventsAdmin::ADD_NEW_EVENT_BUTTON_SELECTOR); -$I->fillField(EventsAdmin::EVENT_EDITOR_TITLE_FIELD_SELECTOR, 'Event RSM B'); -$I->changeDefaultRegistrationStatusTo(RegistrationsAdmin::REGISTRATION_STATUS_NOT_APPROVED); -$I->publishEvent(); -$event_b_link = $I->observeLinkUrlAt(EventsAdmin::EVENT_EDITOR_VIEW_LINK_AFTER_PUBLISH_SELECTOR); -$event_b_id = $I->observeValueFromInputAt(EventsAdmin::EVENT_EDITOR_EVT_ID_SELECTOR); - -$I->amOnDefaultEventsListTablePage(); -$I->click(EventsAdmin::ADD_NEW_EVENT_BUTTON_SELECTOR); -$I->fillField(EventsAdmin::EVENT_EDITOR_TITLE_FIELD_SELECTOR, 'Event RSM C'); -$I->publishEvent(); -$event_c_link = $I->observeLinkUrlAt(EventsAdmin::EVENT_EDITOR_VIEW_LINK_AFTER_PUBLISH_SELECTOR); -$event_c_id = $I->observeValueFromInputAt(EventsAdmin::EVENT_EDITOR_EVT_ID_SELECTOR); - -//k now that our events are setup lets do some registrations -$I->logOut(); -$I->amOnUrl($event_a_link); -$I->see('Event RSM A'); -$I->selectOption(TicketSelector::ticketOptionByEventIdSelector($event_a_id), '1'); -$I->click(TicketSelector::ticketSelectionSubmitSelectorByEventId($event_a_id)); -$I->waitForText('successfully added'); -$I->click('.cart-results-go-back-button'); -$I->amOnUrl($event_b_link); -$I->see('Event RSM B'); -$I->selectOption(TicketSelector::ticketOptionByEventIdSelector($event_b_id), '1'); -$I->click(TicketSelector::ticketSelectionSubmitSelectorByEventId($event_b_id)); -$I->waitForText('successfully added'); -$I->click('.cart-results-register-button'); -$I->waitForText('Personal Information'); -$I->fillOutFirstNameFieldForAttendee('RSM Tester'); -$I->fillOutLastNameFieldForAttendee('Guy'); -$I->fillOutEmailFieldForAttendee('rsm_tester@example.org'); -$I->goToNextRegistrationStep(); -$I->waitForText('Congratulations', 15); - -//now let's go to the messages list table and make sure the registration message summary is there. -$I->loginAsAdmin(); -$I->amOnMessagesActivityListTablePage(); -$I->see( - 'rsm_tester@example.org', - MessagesAdmin::messagesActivityListTableCellSelectorFor( - 'to', - 'Registration Multi-status Summary', - MessagesAdmin::MESSAGE_STATUS_SENT, - '', - 'Primary Registrant' - ) -); -$I->see( - 'admin@example.com', - MessagesAdmin::messagesActivityListTableCellSelectorFor( - 'to', - 'Registration Multi-status Summary', - MessagesAdmin::MESSAGE_STATUS_SENT - ) -); -//verify count -$I->verifyMatchingCountofTextInMessageActivityListTableFor( - 1, - 'rsm_tester@example.org', - 'to', - 'Registration Multi-status Summary', - MessagesAdmin::MESSAGE_STATUS_SENT, - 'Email', - 'Primary Registrant' -); -$I->verifyMatchingCountofTextInMessageActivityListTableFor( - 1, - 'admin@example.com', - 'to', - 'Registration Multi-status Summary' -); - -//okay now let's do some registrations for just the first event and verify that registration multi-status summary is NOT -//generated -$I->amGoingTo('Register for Event RSM A and C and verify registration multi-status message type is not used for generated message'); -$I->logOut(); -$I->amOnUrl($event_a_link); -$I->see('Event RSM A'); -$I->selectOption(TicketSelector::ticketOptionByEventIdSelector($event_a_id), '1'); -$I->click(TicketSelector::ticketSelectionSubmitSelectorByEventId($event_a_id)); -$I->waitForText('successfully added'); -$I->click('.cart-results-go-back-button'); -$I->amOnUrl($event_c_link); -$I->see('Event RSM C'); -$I->selectOption(TicketSelector::ticketOptionByEventIdSelector($event_c_id), '1'); -$I->click(TicketSelector::ticketSelectionSubmitSelectorByEventId($event_c_id)); -$I->waitForText('successfully added'); -$I->click('.cart-results-register-button'); -$I->waitForText('Personal Information'); -$I->fillOutFirstNameFieldForAttendee('RSM Tester B'); -$I->fillOutLastNameFieldForAttendee('Guy'); -$I->fillOutEmailFieldForAttendee('rsm_testerb@example.org'); -$I->goToNextRegistrationStep(); -$I->waitForText('Congratulations', 15); - -$I->amGoingTo('Visit Messages Activity List Table and verify there are no Registration Multi-Status Messages for the registrations we just did'); -$I->loginAsAdmin(); -$I->amOnMessagesActivityListTablePage(); -$I->dontSee( - 'rsm_testerb@example.org', - MessagesAdmin::messagesActivityListTableCellSelectorFor( - 'to', - 'Registration Multi-status Summary', - MessagesAdmin::MESSAGE_STATUS_SENT, - '', - 'Primary Registrant' - ) -); -//there should still only be one admin multi-status summary thing. -$I->verifyMatchingCountofTextInMessageActivityListTableFor( - 1, - 'admin@example.com', - 'to', - 'Registration Multi-status Summary' -); - -//deactivate MER plugin so its not active for future tests -$I->ensurePluginDeactivated( - 'event-espresso-mer-multi-event-registration', - 'plugins deactivated' -); \ No newline at end of file diff --git a/acceptance_tests/tests/c-TestCustomMessageTemplateCept.php b/acceptance_tests/tests/c-TestCustomMessageTemplateCept.php deleted file mode 100644 index 53082b95ec3..00000000000 --- a/acceptance_tests/tests/c-TestCustomMessageTemplateCept.php +++ /dev/null @@ -1,188 +0,0 @@ -wantTo( - 'Test that when registrations for multiple events are completed, and those events share the same custom' - . 'template, that that custom template will be used.' -); - -//need the MER plugin active for this test (we'll deactivate it after). -$I->ensurePluginActive( - 'event-espresso-mer-multi-event-registration', - 'activated' -); - -$I->loginAsAdmin(); - -$I->amGoingTo('Create two custom registration approved templates'); -$I->amGoingTo('Create first custom registration approved template.'); -$I->createCustomMessageTemplateFromDefaultFor('Registration Approved', 'Email'); -$I->appendToWPEditorField('main', $custom_template_a_label); -$I->saveMessageTemplate(); -$I->waitForText('successfully updated'); -$I->switchContextTo('Registrant'); -$I->fillField('#title', $custom_template_a_label); -$I->appendToWPEditorField('main', $custom_template_a_label); -$I->saveMessageTemplate(); -$I->waitForText('successfully updated'); - -$I->amGoingTo('Create second custom registration approved template.'); -$I->createCustomMessageTemplateFromDefaultFor('Registration Approved', 'Email'); -$I->fillField('#title', $custom_template_b_label); -$I->appendToWPEditorField('main', $custom_template_b_label); -$I->saveMessageTemplate(); -$I->waitForText('successfully updated'); -$I->switchContextTo('Registrant'); -$I->appendToWPEditorField('main', $custom_template_b_label); -$I->saveMessageTemplate(); -$I->waitForText('successfully updated'); - -$I->amGoingTo('Create three events for testing with.'); -$I->amOnDefaultEventsListTablePage(); -$I->click(EventsAdmin::ADD_NEW_EVENT_BUTTON_SELECTOR); -$I->fillField(EventsAdmin::EVENT_EDITOR_TITLE_FIELD_SELECTOR, $event_one_label); -$I->selectCustomTemplateFor('Registration Approved', 'email', $custom_template_a_label); -$I->publishEvent(); -$event_one_link = $I->observeLinkUrlAt(EventsAdmin::EVENT_EDITOR_VIEW_LINK_AFTER_PUBLISH_SELECTOR); -$event_one_id = $I->observeValueFromInputAt(EventsAdmin::EVENT_EDITOR_EVT_ID_SELECTOR); - -$I->amOnDefaultEventsListTablePage(); -$I->click(EventsAdmin::ADD_NEW_EVENT_BUTTON_SELECTOR); -$I->fillField(EventsAdmin::EVENT_EDITOR_TITLE_FIELD_SELECTOR, $event_two_label); -$I->selectCustomTemplateFor('Registration Approved', 'email', $custom_template_a_label); -$I->publishEvent(); -$event_two_link = $I->observeLinkUrlAt(EventsAdmin::EVENT_EDITOR_VIEW_LINK_AFTER_PUBLISH_SELECTOR); -$event_two_id = $I->observeValueFromInputAt(EventsAdmin::EVENT_EDITOR_EVT_ID_SELECTOR); - -$I->amOnDefaultEventsListTablePage(); -$I->click(EventsAdmin::ADD_NEW_EVENT_BUTTON_SELECTOR); -$I->fillField(EventsAdmin::EVENT_EDITOR_TITLE_FIELD_SELECTOR, $event_three_label); -$I->selectCustomTemplateFor('Registration Approved', 'email', $custom_template_b_label); -$I->publishEvent(); -$event_three_link = $I->observeLinkUrlAt(EventsAdmin::EVENT_EDITOR_VIEW_LINK_AFTER_PUBLISH_SELECTOR); -$event_three_id = $I->observeValueFromInputAt(EventsAdmin::EVENT_EDITOR_EVT_ID_SELECTOR); - - -$test_registration_details = array( - 'fname' => 'CTGuy', - 'lname' => 'Dude', - 'email' => 'ctguy_dude@example.org' -); - -$I->amGoingTo('Register for Event One and Event Two and verify Custom Template A was used.'); -$I->logOut(); -$I->amOnUrl($event_one_link); -$I->selectOption(TicketSelector::ticketOptionByEventIdSelector($event_one_id), 1); -$I->click(TicketSelector::ticketSelectionSubmitSelectorByEventId($event_one_id)); -$I->waitForText('successfully added'); -$I->click('.cart-results-go-back-button'); -$I->amOnUrl($event_two_link); -$I->selectOption(TicketSelector::ticketOptionByEventIdSelector($event_two_id), 1); -$I->click(TicketSelector::ticketSelectionSubmitSelectorByEventId($event_two_id)); -$I->waitForText('successfully added'); -$I->click('.cart-results-register-button'); -$I->waitForText('Personal Information'); -$I->fillOutFirstNameFieldForAttendee($test_registration_details['fname']); -$I->fillOutLastNameFieldForAttendee($test_registration_details['lname']); -$I->fillOutEmailFieldForAttendee($test_registration_details['email']); -$I->goToNextRegistrationStep(); -$I->waitForText('Congratulations', 15); - -//go to list table and verify -$I->loginAsAdmin(); -$I->amOnMessagesActivityListTablePage(); -$I->viewMessageInMessagesListTableFor( - 'Registration Approved', - MessagesAdmin::MESSAGE_STATUS_SENT, - 'Email', - 'Registrant' -); -$I->seeTextInViewMessageModal($custom_template_a_label); -$I->dismissMessageModal(); -$I->deleteMessageInMessagesListTableFor( - 'Registration Approved', - MessagesAdmin::MESSAGE_STATUS_SENT, - 'Email', - 'Registrant' -); - -//verify admin context -$I->viewMessageInMessagesListTableFor( - 'Registration Approved' -); -$I->seeTextInViewMessageModal($custom_template_a_label); -$I->dismissMessageModal(); -$I->deleteMessageInMessagesListTableFor('Registration Approved'); - -$I->amGoingTo('Register for Event One and Event Three and verify that global template is used.'); -$I->logOut(); -$I->amOnUrl($event_one_link); -$I->selectOption(TicketSelector::ticketOptionByEventIdSelector($event_one_id), 1); -$I->click(TicketSelector::ticketSelectionSubmitSelectorByEventId($event_one_id)); -$I->waitForText('successfully added'); -$I->click('.cart-results-go-back-button'); -$I->amOnUrl($event_three_link); -$I->selectOption(TicketSelector::ticketOptionByEventIdSelector($event_three_id), 1); -$I->click(TicketSelector::ticketSelectionSubmitSelectorByEventId($event_three_id)); -$I->waitForText('successfully added'); -$I->click('.cart-results-register-button'); -$I->waitForText('Personal Information'); -$I->fillOutFirstNameFieldForAttendee($test_registration_details['fname']); -$I->fillOutLastNameFieldForAttendee($test_registration_details['lname']); -$I->fillOutEmailFieldForAttendee($test_registration_details['email']); -$I->goToNextRegistrationStep(); -$I->waitForText('Congratulations', 15); - -//go to list table and verify -$I->loginAsAdmin(); -$I->amOnMessagesActivityListTablePage(); -$I->viewMessageInMessagesListTableFor( - 'Registration Approved', - MessagesAdmin::MESSAGE_STATUS_SENT, - 'Email', - 'Registrant' -); -$I->waitForElementVisible(MessagesAdmin::MESSAGES_LIST_TABLE_VIEW_MESSAGE_DIALOG_CONTAINER_SELECTOR); -$I->dontSeeTextInViewMessageModal($custom_template_a_label); -$I->dontSeeTextInViewMessageModal($custom_template_b_label); -$I->dismissMessageModal(); -$I->deleteMessageInMessagesListTableFor( - 'Registration Approved', - MessagesAdmin::MESSAGE_STATUS_SENT, - 'Email', - 'Registrant' -); - -//verify admin context -$I->viewMessageInMessagesListTableFor( - 'Registration Approved' -); -$I->waitForElementVisible(MessagesAdmin::MESSAGES_LIST_TABLE_VIEW_MESSAGE_DIALOG_CONTAINER_SELECTOR); -$I->dontSee($custom_template_a_label); -$I->dontSee($custom_template_b_label); -$I->dismissMessageModal(); -$I->deleteMessageInMessagesListTableFor('Registration Approved'); - - - -//deactivate MER plugin so its not active for future tests -$I->ensurePluginDeactivated( - 'event-espresso-mer-multi-event-registration', - 'plugins deactivated' -); \ No newline at end of file diff --git a/acceptance_tests/tests/d-TestEventEditorCept.php b/acceptance_tests/tests/d-TestEventEditorCept.php deleted file mode 100644 index 702f51907ea..00000000000 --- a/acceptance_tests/tests/d-TestEventEditorCept.php +++ /dev/null @@ -1,41 +0,0 @@ -wantTo('Test various features/elements in the event editor.'); -$I->amGoingTo('Test ticket total calculations via js in the ticket editor.'); -$I->loginAsAdmin(); -$I->amOnDefaultEventsListTablePage(); -$I->click(EventsAdmin::ADD_NEW_EVENT_BUTTON_SELECTOR); -$I->fillField(EventsAdmin::eventEditorTicketPriceFieldSelector(), '32.50'); -$I->toggleAdvancedSettingsViewForTicketRow(); -$I->waitForElementVisible(EventsAdmin::eventEditorTicketAdvancedDetailsSubtotalSelector()); -$I->see('$32.50', EventsAdmin::eventEditorTicketAdvancedDetailsSubtotalSelector()); -$I->toggleTicketIsTaxableForTicketRow(); -$I->see('$4.88', EventsAdmin::eventEditorTicketTaxAmountDisplayForTaxIdAndTicketRowSelector()); -$I->see('$37.38', EventsAdmin::eventEditorTicketAdvancedDetailsTotalSelector()); -$I->saveEvent(); - -$I->amGoingTo('Test the same ticket total calculations via js in the ticket editor but with this format: 1.000,00'); -$I->amOnCountrySettingsAdminPage(); -$I->setCurrencyDecimalMarkTo(','); -$I->setCurrencyThousandsSeparatorTo('.'); -$I->saveCountrySettings(); -$I->amOnDefaultEventsListTablePage(); -$I->click(EventsAdmin::ADD_NEW_EVENT_BUTTON_SELECTOR); -$I->fillField(EventsAdmin::eventEditorTicketPriceFieldSelector(), '32,50'); -$I->toggleAdvancedSettingsViewForTicketRow(); -$I->waitForElementVisible(EventsAdmin::eventEditorTicketAdvancedDetailsSubtotalSelector()); -$I->see('$32,50', EventsAdmin::eventEditorTicketAdvancedDetailsSubtotalSelector()); -$I->toggleTicketIsTaxableForTicketRow(); -$I->see('$4,88', EventsAdmin::eventEditorTicketTaxAmountDisplayForTaxIdAndTicketRowSelector()); -$I->see('$37,38', EventsAdmin::eventEditorTicketAdvancedDetailsTotalSelector()); - -//restore country settings to original -$I->saveEvent(); -$I->amOnCountrySettingsAdminPage(); -$I->setCurrencyDecimalMarkTo('.'); -$I->setCurrencyThousandsSeparatorTo(','); -$I->saveCountrySettings(); \ No newline at end of file diff --git a/acceptance_tests/tests/e-TestContextActivationToggleCept.php b/acceptance_tests/tests/e-TestContextActivationToggleCept.php deleted file mode 100644 index 992c6d3808a..00000000000 --- a/acceptance_tests/tests/e-TestContextActivationToggleCept.php +++ /dev/null @@ -1,167 +0,0 @@ -wantTo( - 'Test that the context activation toggle for turning on or off specific contexts for message sending works as' - . ' expected' -); - -$I->loginAsAdmin(); - -$I->amGoingTo('Verify the toggle for toggling state on context is visible.'); -$I->amOnDefaultMessageTemplateListTablePage(); -$I->clickToEditMessageTemplateByMessageType('registration', 'admin'); -$I->see('The template for Event Admin Recipient is currently active.'); -$I->switchContextTo('Primary Registrant'); -$I->see('The template for Primary Registrant Recipient is currently active.'); - -$I->amGoingTo('Make sure the "To" field for Primary Registrant has content'); -$I->fillField(MessagesAdmin::messageTemplateToFieldSelector(), '[PRIMARY_REGISTRANT_EMAIL]'); -$I->saveMessageTemplate(); -//verify To Field has expected content after save. -$I->seeInField(MessagesAdmin::messageTemplateToFieldSelector(), '[PRIMARY_REGISTRANT_EMAIL]'); - -$I->amGoingTo('Disable the primary registrant context.'); -$I->toggleContextState('Primary Registrant Recipient', false); -//save and verify it stuck -$I->saveMessageTemplate(); -$I->see('The template for Primary Registrant Recipient is currently inactive.'); - -$I->amGoingTo( - 'Trigger Registration Approved Messages and verify primary registrant context is excluded from sent messages.' -); -$I->amOnDefaultEventsListTablePage(); -$I->click(EventsAdmin::ADD_NEW_EVENT_BUTTON_SELECTOR); -$I->fillField(EventsAdmin::EVENT_EDITOR_TITLE_FIELD_SELECTOR, $event_label); -$I->publishEvent(); -$event_link = $I->observeLinkUrlAt(EventsAdmin::EVENT_EDITOR_VIEW_LINK_AFTER_PUBLISH_SELECTOR); -$event_id = $I->observeValueFromInputAt(EventsAdmin::EVENT_EDITOR_EVT_ID_SELECTOR); -$test_registration_details = array( - 'fname' => 'ContextTestGuy', - 'lname' => 'ContextTestDude', - 'email' => 'contexttestguy@example.org', -); -$I->logOut(); -$I->amOnUrl($event_link); -$I->selectOption(TicketSelector::ticketOptionByEventIdSelector($event_id), 1); -$I->click(TicketSelector::ticketSelectionSubmitSelectorByEventId($event_id)); -$I->waitForText('Personal Information'); -$I->fillOutFirstNameFieldForAttendee($test_registration_details['fname']); -$I->fillOutLastNameFieldForAttendee($test_registration_details['lname']); -$I->fillOutEmailFieldForAttendee($test_registration_details['email']); -$I->goToNextRegistrationStep(); -$I->waitForText('Congratulations', 15); -//go to messages list table and verify -$I->loginAsAdmin(); -$I->amOnMessagesActivityListTablePage(); -//verify registrant context -$I->see( - $test_registration_details['email'], - MessagesAdmin::messagesActivityListTableCellSelectorFor( - 'to', - 'Registration Approved', - MessagesAdmin::MESSAGE_STATUS_SENT, - '', - 'Registrant' - ) -); -$I->deleteMessageInMessagesListTableFor( - 'Registration Approved', - MessagesAdmin::MESSAGE_STATUS_SENT, - 'Email', - 'Registrant' -); -//verify admin context -$I->see( - 'admin@example.com', - MessagesAdmin::messagesActivityListTableCellSelectorFor( - 'to', - 'Registration Approved', - MessagesAdmin::MESSAGE_STATUS_SENT - ) -); -$I->deleteMessageInMessagesListTableFor( - 'Registration Approved' -); -//verify primary registrant context is NOT present. -$I->dontSee( - $test_registration_details['email'], - MessagesAdmin::messagesActivityListTableCellSelectorFor( - 'to', - 'Registration Approved', - MessagesAdmin::MESSAGE_STATUS_SENT, - '', - 'Primary Registrant' - ) -); - -$I->amGoingTo( - 'Deactivate primary registrant context for Registration Approved Message Templates and restore the "To"' - . ' field to an empty string to verify the message does not send for that context.' -); -$I->amOnDefaultMessageTemplateListTablePage(); -$I->clickToEditMessageTemplateByMessageType('registration', 'primary_attendee'); -$I->toggleContextState('Primary Registrant Recipient', true); -$I->fillField(MessagesAdmin::messageTemplateToFieldSelector(), ''); -$I->saveMessageTemplate(); -$I->see('The template for Primary Registrant Recipient is currently active.'); -//repeat frontend registration and verify we get the same results with the empty "To" field. -$I->logOut(); -$I->amOnUrl($event_link); -$I->selectOption(TicketSelector::ticketOptionByEventIdSelector($event_id), 1); -$I->click(TicketSelector::ticketSelectionSubmitSelectorByEventId($event_id)); -$I->waitForText('Personal Information'); -$I->fillOutFirstNameFieldForAttendee($test_registration_details['fname']); -$I->fillOutLastNameFieldForAttendee($test_registration_details['lname']); -$I->fillOutEmailFieldForAttendee($test_registration_details['email']); -$I->goToNextRegistrationStep(); -$I->waitForText('Congratulations', 15); -//go to messages list table and verify -$I->loginAsAdmin(); -$I->amOnMessagesActivityListTablePage(); -//verify registrant context -$I->see( - $test_registration_details['email'], - MessagesAdmin::messagesActivityListTableCellSelectorFor( - 'to', - 'Registration Approved', - MessagesAdmin::MESSAGE_STATUS_SENT, - '', - 'Registrant' - ) -); -$I->deleteMessageInMessagesListTableFor( - 'Registration Approved', - MessagesAdmin::MESSAGE_STATUS_SENT, - 'Email', - 'Registrant' -); -//verify admin context -$I->see( - 'admin@example.com', - MessagesAdmin::messagesActivityListTableCellSelectorFor( - 'to', - 'Registration Approved', - MessagesAdmin::MESSAGE_STATUS_SENT - ) -); -$I->deleteMessageInMessagesListTableFor( - 'Registration Approved' -); -//verify primary registrant context is NOT present. -$I->dontSee( - $test_registration_details['email'], - MessagesAdmin::messagesActivityListTableCellSelectorFor( - 'to', - 'Registration Approved', - MessagesAdmin::MESSAGE_STATUS_SENT, - '', - 'Primary Registrant' - ) -); \ No newline at end of file diff --git a/assets/dist/build-manifest.json b/assets/dist/build-manifest.json index 9195a361303..d83ca12bd59 100644 --- a/assets/dist/build-manifest.json +++ b/assets/dist/build-manifest.json @@ -1,19 +1,19 @@ { - "eejs.js": "ee-eejs.0027f7deea766130d950.dist.js", + "eejs.js": "ee-eejs.6fc6d91b0188c3e4ca5a.dist.js", "entrypoints": { "wp-plugins-page": { "js": [ - "ee-manifest.3b66c2f77d3b01c1b09a.dist.js", - "ee-reactVendor.814709a0f9fdbb9b2d40.dist.js", - "ee-wp-plugins-page.5d91e78c312b162c6450.dist.js" + "ee-manifest.943039ef4ea4d65fdbb9.dist.js", + "ee-reactVendor.9830cd84f7629d15e4bc.dist.js", + "ee-wp-plugins-page.5f38fda793450ad62a1c.dist.js" ], "css": [ - "ee-wp-plugins-page.18b028a8d6163577ccd1.dist.css" + "ee-wp-plugins-page.bb7453ad21f596d77c51.dist.css" ] } }, - "manifest.js": "ee-manifest.3b66c2f77d3b01c1b09a.dist.js", - "reactVendor.js": "ee-reactVendor.814709a0f9fdbb9b2d40.dist.js", - "wp-plugins-page.css": "ee-wp-plugins-page.18b028a8d6163577ccd1.dist.css", - "wp-plugins-page.js": "ee-wp-plugins-page.5d91e78c312b162c6450.dist.js" + "manifest.js": "ee-manifest.943039ef4ea4d65fdbb9.dist.js", + "reactVendor.js": "ee-reactVendor.9830cd84f7629d15e4bc.dist.js", + "wp-plugins-page.css": "ee-wp-plugins-page.bb7453ad21f596d77c51.dist.css", + "wp-plugins-page.js": "ee-wp-plugins-page.5f38fda793450ad62a1c.dist.js" } \ No newline at end of file diff --git a/assets/dist/ee-eejs.0027f7deea766130d950.dist.js b/assets/dist/ee-eejs.0027f7deea766130d950.dist.js deleted file mode 100644 index c8315313ea9..00000000000 --- a/assets/dist/ee-eejs.0027f7deea766130d950.dist.js +++ /dev/null @@ -1,2222 +0,0 @@ -this["eejs"] = -/******/ (function(modules) { // webpackBootstrap -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { -/******/ configurable: false, -/******/ enumerable: true, -/******/ get: getter -/******/ }); -/******/ } -/******/ }; -/******/ -/******/ // define __esModule on exports -/******/ __webpack_require__.r = function(exports) { -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ -/******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 0); -/******/ }) -/************************************************************************/ -/******/ ({ - -/***/ "./assets/src/eejs/index.js": -/*!**********************************!*\ - !*** ./assets/src/eejs/index.js ***! - \**********************************/ -/*! exports provided: data, i18n, exception */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "data", function() { return data; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "i18n", function() { return i18n; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "exception", function() { return exception; }); -/* harmony import */ var _wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @wordpress/i18n */ "./node_modules/@wordpress/i18n/build-module/index.js"); -/** - * WordPress imports - */ - - -/** - * Exported to the `eejs` global. - */ - -/** - * This will hold arbitrary data assigned by the Assets Registry. - * @type {{}} - */ -var data = eejsdata.data || {}; - -/** - * Wrapper around wp.i18n functionality so its exposed on the eejs global as - * eejs.i18n; - */ -var i18n = _wordpress_i18n__WEBPACK_IMPORTED_MODULE_0__; - -/** - * use this for eejs exceptions - * Usage: throw new eejs.exception('some message') - * @param {string} msg - */ -var exception = function exception(msg) { - this.message = msg; -}; - -/***/ }), - -/***/ "./node_modules/@wordpress/i18n/build-module/index.js": -/*!************************************************************!*\ - !*** ./node_modules/@wordpress/i18n/build-module/index.js ***! - \************************************************************/ -/*! exports provided: setLocaleData, getI18n, dcnpgettext, __, _x, _n, _nx, sprintf */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "setLocaleData", function() { return setLocaleData; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "getI18n", function() { return getI18n; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "dcnpgettext", function() { return dcnpgettext; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "__", function() { return __; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "_x", function() { return _x; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "_n", function() { return _n; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "_nx", function() { return _nx; }); -/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "sprintf", function() { return sprintf; }); -/* harmony import */ var babel_runtime_core_js_object_assign__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babel-runtime/core-js/object/assign */ "./node_modules/babel-runtime/core-js/object/assign.js"); -/* harmony import */ var babel_runtime_core_js_object_assign__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babel_runtime_core_js_object_assign__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var jed__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! jed */ "./node_modules/jed/jed.js"); -/* harmony import */ var jed__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(jed__WEBPACK_IMPORTED_MODULE_1__); -/* harmony import */ var memize__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! memize */ "./node_modules/memize/index.js"); -/* harmony import */ var memize__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(memize__WEBPACK_IMPORTED_MODULE_2__); - -/** - * External dependencies - */ - - - -var i18n = void 0; - -/** - * Log to console, once per message; or more precisely, per referentially equal - * argument set. Because Jed throws errors, we log these to the console instead - * to avoid crashing the application. - * - * @param {...*} args Arguments to pass to `console.error` - */ -var logErrorOnce = memize__WEBPACK_IMPORTED_MODULE_2___default()(console.error); // eslint-disable-line no-console - -/** - * Merges locale data into the Jed instance by domain. Creates a new Jed - * instance if one has not yet been assigned. - * - * @see http://messageformat.github.io/Jed/ - * - * @param {?Object} localeData Locale data configuration. - * @param {?string} domain Domain for which configuration applies. - */ -function setLocaleData() { - var localeData = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { '': {} }; - var domain = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'default'; - - if (!i18n) { - i18n = new jed__WEBPACK_IMPORTED_MODULE_1___default.a({ - domain: 'default', - locale_data: { - default: {} - } - }); - } - - i18n.options.locale_data[domain] = babel_runtime_core_js_object_assign__WEBPACK_IMPORTED_MODULE_0___default()({}, i18n.options.locale_data[domain], localeData); -} - -/** - * Returns the current Jed instance, initializing with a default configuration - * if not already assigned. - * - * @return {Jed} Jed instance. - */ -function getI18n() { - if (!i18n) { - setLocaleData(); - } - - return i18n; -} - -/** - * Wrapper for Jed's `dcnpgettext`, its most qualified function. Absorbs errors - * which are thrown as the result of invalid translation. - * - * @param {?string} domain Domain to retrieve the translated text. - * @param {?string} context Context information for the translators. - * @param {string} single Text to translate if non-plural. Used as fallback - * return value on a caught error. - * @param {?string} plural The text to be used if the number is plural. - * @param {?number} number The number to compare against to use either the - * singular or plural form. - * - * @return {string} The translated string. - */ -var dcnpgettext = memize__WEBPACK_IMPORTED_MODULE_2___default()(function () { - var domain = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'default'; - var context = arguments[1]; - var single = arguments[2]; - var plural = arguments[3]; - var number = arguments[4]; - - try { - return getI18n().dcnpgettext(domain, context, single, plural, number); - } catch (error) { - logErrorOnce('Jed localization error: \n\n' + error.toString()); - - return single; - } -}); - -/** - * Retrieve the translation of text. - * - * @see https://developer.wordpress.org/reference/functions/__/ - * - * @param {string} text Text to translate. - * @param {?string} domain Domain to retrieve the translated text. - * - * @return {string} Translated text. - */ -function __(text, domain) { - return dcnpgettext(domain, undefined, text); -} - -/** - * Retrieve translated string with gettext context. - * - * @see https://developer.wordpress.org/reference/functions/_x/ - * - * @param {string} text Text to translate. - * @param {string} context Context information for the translators. - * @param {?string} domain Domain to retrieve the translated text. - * - * @return {string} Translated context string without pipe. - */ -function _x(text, context, domain) { - return dcnpgettext(domain, context, text); -} - -/** - * Translates and retrieves the singular or plural form based on the supplied - * number. - * - * @see https://developer.wordpress.org/reference/functions/_n/ - * - * @param {string} single The text to be used if the number is singular. - * @param {string} plural The text to be used if the number is plural. - * @param {number} number The number to compare against to use either the - * singular or plural form. - * @param {?string} domain Domain to retrieve the translated text. - * - * @return {string} The translated singular or plural form. - */ -function _n(single, plural, number, domain) { - return dcnpgettext(domain, undefined, single, plural, number); -} - -/** - * Translates and retrieves the singular or plural form based on the supplied - * number, with gettext context. - * - * @see https://developer.wordpress.org/reference/functions/_nx/ - * - * @param {string} single The text to be used if the number is singular. - * @param {string} plural The text to be used if the number is plural. - * @param {number} number The number to compare against to use either the - * singular or plural form. - * @param {string} context Context information for the translators. - * @param {?string} domain Domain to retrieve the translated text. - * - * @return {string} The translated singular or plural form. - */ -function _nx(single, plural, number, context, domain) { - return dcnpgettext(domain, context, single, plural, number); -} - -/** - * Returns a formatted string. If an error occurs in applying the format, the - * original format string is returned. - * - * @param {string} format The format of the string to generate. - * @param {string[]} ...args Arguments to apply to the format. - * - * @see http://www.diveintojavascript.com/projects/javascript-sprintf - * - * @return {string} The formatted string. - */ -function sprintf(format) { - try { - for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } - - return jed__WEBPACK_IMPORTED_MODULE_1___default.a.sprintf.apply(jed__WEBPACK_IMPORTED_MODULE_1___default.a, [format].concat(args)); - } catch (error) { - logErrorOnce('Jed sprintf error: \n\n' + error.toString()); - - return format; - } -} - -/***/ }), - -/***/ "./node_modules/babel-runtime/core-js/object/assign.js": -/*!*************************************************************!*\ - !*** ./node_modules/babel-runtime/core-js/object/assign.js ***! - \*************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -module.exports = { "default": __webpack_require__(/*! core-js/library/fn/object/assign */ "./node_modules/babel-runtime/node_modules/core-js/library/fn/object/assign.js"), __esModule: true }; - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/fn/object/assign.js": -/*!*************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/fn/object/assign.js ***! - \*************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -__webpack_require__(/*! ../../modules/es6.object.assign */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/es6.object.assign.js"); -module.exports = __webpack_require__(/*! ../../modules/_core */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_core.js").Object.assign; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_a-function.js": -/*!****************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_a-function.js ***! - \****************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -module.exports = function (it) { - if (typeof it != 'function') throw TypeError(it + ' is not a function!'); - return it; -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_an-object.js": -/*!***************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_an-object.js ***! - \***************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var isObject = __webpack_require__(/*! ./_is-object */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_is-object.js"); -module.exports = function (it) { - if (!isObject(it)) throw TypeError(it + ' is not an object!'); - return it; -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_array-includes.js": -/*!********************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_array-includes.js ***! - \********************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -// false -> Array#indexOf -// true -> Array#includes -var toIObject = __webpack_require__(/*! ./_to-iobject */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-iobject.js"); -var toLength = __webpack_require__(/*! ./_to-length */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-length.js"); -var toAbsoluteIndex = __webpack_require__(/*! ./_to-absolute-index */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-absolute-index.js"); -module.exports = function (IS_INCLUDES) { - return function ($this, el, fromIndex) { - var O = toIObject($this); - var length = toLength(O.length); - var index = toAbsoluteIndex(fromIndex, length); - var value; - // Array#includes uses SameValueZero equality algorithm - // eslint-disable-next-line no-self-compare - if (IS_INCLUDES && el != el) while (length > index) { - value = O[index++]; - // eslint-disable-next-line no-self-compare - if (value != value) return true; - // Array#indexOf ignores holes, Array#includes - not - } else for (;length > index; index++) if (IS_INCLUDES || index in O) { - if (O[index] === el) return IS_INCLUDES || index || 0; - } return !IS_INCLUDES && -1; - }; -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_cof.js": -/*!*********************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_cof.js ***! - \*********************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -var toString = {}.toString; - -module.exports = function (it) { - return toString.call(it).slice(8, -1); -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_core.js": -/*!**********************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_core.js ***! - \**********************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -var core = module.exports = { version: '2.5.5' }; -if (typeof __e == 'number') __e = core; // eslint-disable-line no-undef - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_ctx.js": -/*!*********************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_ctx.js ***! - \*********************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -// optional / simple context binding -var aFunction = __webpack_require__(/*! ./_a-function */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_a-function.js"); -module.exports = function (fn, that, length) { - aFunction(fn); - if (that === undefined) return fn; - switch (length) { - case 1: return function (a) { - return fn.call(that, a); - }; - case 2: return function (a, b) { - return fn.call(that, a, b); - }; - case 3: return function (a, b, c) { - return fn.call(that, a, b, c); - }; - } - return function (/* ...args */) { - return fn.apply(that, arguments); - }; -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_defined.js": -/*!*************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_defined.js ***! - \*************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -// 7.2.1 RequireObjectCoercible(argument) -module.exports = function (it) { - if (it == undefined) throw TypeError("Can't call method on " + it); - return it; -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_descriptors.js": -/*!*****************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_descriptors.js ***! - \*****************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -// Thank's IE8 for his funny defineProperty -module.exports = !__webpack_require__(/*! ./_fails */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_fails.js")(function () { - return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7; -}); - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_dom-create.js": -/*!****************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_dom-create.js ***! - \****************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var isObject = __webpack_require__(/*! ./_is-object */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_is-object.js"); -var document = __webpack_require__(/*! ./_global */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_global.js").document; -// typeof document.createElement is 'object' in old IE -var is = isObject(document) && isObject(document.createElement); -module.exports = function (it) { - return is ? document.createElement(it) : {}; -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_enum-bug-keys.js": -/*!*******************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_enum-bug-keys.js ***! - \*******************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -// IE 8- don't enum bug keys -module.exports = ( - 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf' -).split(','); - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_export.js": -/*!************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_export.js ***! - \************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var global = __webpack_require__(/*! ./_global */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_global.js"); -var core = __webpack_require__(/*! ./_core */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_core.js"); -var ctx = __webpack_require__(/*! ./_ctx */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_ctx.js"); -var hide = __webpack_require__(/*! ./_hide */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_hide.js"); -var has = __webpack_require__(/*! ./_has */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_has.js"); -var PROTOTYPE = 'prototype'; - -var $export = function (type, name, source) { - var IS_FORCED = type & $export.F; - var IS_GLOBAL = type & $export.G; - var IS_STATIC = type & $export.S; - var IS_PROTO = type & $export.P; - var IS_BIND = type & $export.B; - var IS_WRAP = type & $export.W; - var exports = IS_GLOBAL ? core : core[name] || (core[name] = {}); - var expProto = exports[PROTOTYPE]; - var target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE]; - var key, own, out; - if (IS_GLOBAL) source = name; - for (key in source) { - // contains in native - own = !IS_FORCED && target && target[key] !== undefined; - if (own && has(exports, key)) continue; - // export native or passed - out = own ? target[key] : source[key]; - // prevent global pollution for namespaces - exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] - // bind timers to global for call from export context - : IS_BIND && own ? ctx(out, global) - // wrap global constructors for prevent change them in library - : IS_WRAP && target[key] == out ? (function (C) { - var F = function (a, b, c) { - if (this instanceof C) { - switch (arguments.length) { - case 0: return new C(); - case 1: return new C(a); - case 2: return new C(a, b); - } return new C(a, b, c); - } return C.apply(this, arguments); - }; - F[PROTOTYPE] = C[PROTOTYPE]; - return F; - // make static versions for prototype methods - })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; - // export proto methods to core.%CONSTRUCTOR%.methods.%NAME% - if (IS_PROTO) { - (exports.virtual || (exports.virtual = {}))[key] = out; - // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME% - if (type & $export.R && expProto && !expProto[key]) hide(expProto, key, out); - } - } -}; -// type bitmap -$export.F = 1; // forced -$export.G = 2; // global -$export.S = 4; // static -$export.P = 8; // proto -$export.B = 16; // bind -$export.W = 32; // wrap -$export.U = 64; // safe -$export.R = 128; // real proto method for `library` -module.exports = $export; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_fails.js": -/*!***********************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_fails.js ***! - \***********************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -module.exports = function (exec) { - try { - return !!exec(); - } catch (e) { - return true; - } -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_global.js": -/*!************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_global.js ***! - \************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 -var global = module.exports = typeof window != 'undefined' && window.Math == Math - ? window : typeof self != 'undefined' && self.Math == Math ? self - // eslint-disable-next-line no-new-func - : Function('return this')(); -if (typeof __g == 'number') __g = global; // eslint-disable-line no-undef - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_has.js": -/*!*********************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_has.js ***! - \*********************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -var hasOwnProperty = {}.hasOwnProperty; -module.exports = function (it, key) { - return hasOwnProperty.call(it, key); -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_hide.js": -/*!**********************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_hide.js ***! - \**********************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var dP = __webpack_require__(/*! ./_object-dp */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_object-dp.js"); -var createDesc = __webpack_require__(/*! ./_property-desc */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_property-desc.js"); -module.exports = __webpack_require__(/*! ./_descriptors */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_descriptors.js") ? function (object, key, value) { - return dP.f(object, key, createDesc(1, value)); -} : function (object, key, value) { - object[key] = value; - return object; -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_ie8-dom-define.js": -/*!********************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_ie8-dom-define.js ***! - \********************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -module.exports = !__webpack_require__(/*! ./_descriptors */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_descriptors.js") && !__webpack_require__(/*! ./_fails */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_fails.js")(function () { - return Object.defineProperty(__webpack_require__(/*! ./_dom-create */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_dom-create.js")('div'), 'a', { get: function () { return 7; } }).a != 7; -}); - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_iobject.js": -/*!*************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_iobject.js ***! - \*************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -// fallback for non-array-like ES3 and non-enumerable old V8 strings -var cof = __webpack_require__(/*! ./_cof */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_cof.js"); -// eslint-disable-next-line no-prototype-builtins -module.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) { - return cof(it) == 'String' ? it.split('') : Object(it); -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_is-object.js": -/*!***************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_is-object.js ***! - \***************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -module.exports = function (it) { - return typeof it === 'object' ? it !== null : typeof it === 'function'; -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_object-assign.js": -/*!*******************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_object-assign.js ***! - \*******************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - -// 19.1.2.1 Object.assign(target, source, ...) -var getKeys = __webpack_require__(/*! ./_object-keys */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_object-keys.js"); -var gOPS = __webpack_require__(/*! ./_object-gops */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_object-gops.js"); -var pIE = __webpack_require__(/*! ./_object-pie */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_object-pie.js"); -var toObject = __webpack_require__(/*! ./_to-object */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-object.js"); -var IObject = __webpack_require__(/*! ./_iobject */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_iobject.js"); -var $assign = Object.assign; - -// should work with symbols and should have deterministic property order (V8 bug) -module.exports = !$assign || __webpack_require__(/*! ./_fails */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_fails.js")(function () { - var A = {}; - var B = {}; - // eslint-disable-next-line no-undef - var S = Symbol(); - var K = 'abcdefghijklmnopqrst'; - A[S] = 7; - K.split('').forEach(function (k) { B[k] = k; }); - return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K; -}) ? function assign(target, source) { // eslint-disable-line no-unused-vars - var T = toObject(target); - var aLen = arguments.length; - var index = 1; - var getSymbols = gOPS.f; - var isEnum = pIE.f; - while (aLen > index) { - var S = IObject(arguments[index++]); - var keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S); - var length = keys.length; - var j = 0; - var key; - while (length > j) if (isEnum.call(S, key = keys[j++])) T[key] = S[key]; - } return T; -} : $assign; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_object-dp.js": -/*!***************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_object-dp.js ***! - \***************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var anObject = __webpack_require__(/*! ./_an-object */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_an-object.js"); -var IE8_DOM_DEFINE = __webpack_require__(/*! ./_ie8-dom-define */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_ie8-dom-define.js"); -var toPrimitive = __webpack_require__(/*! ./_to-primitive */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-primitive.js"); -var dP = Object.defineProperty; - -exports.f = __webpack_require__(/*! ./_descriptors */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_descriptors.js") ? Object.defineProperty : function defineProperty(O, P, Attributes) { - anObject(O); - P = toPrimitive(P, true); - anObject(Attributes); - if (IE8_DOM_DEFINE) try { - return dP(O, P, Attributes); - } catch (e) { /* empty */ } - if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!'); - if ('value' in Attributes) O[P] = Attributes.value; - return O; -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_object-gops.js": -/*!*****************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_object-gops.js ***! - \*****************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -exports.f = Object.getOwnPropertySymbols; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_object-keys-internal.js": -/*!**************************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_object-keys-internal.js ***! - \**************************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var has = __webpack_require__(/*! ./_has */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_has.js"); -var toIObject = __webpack_require__(/*! ./_to-iobject */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-iobject.js"); -var arrayIndexOf = __webpack_require__(/*! ./_array-includes */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_array-includes.js")(false); -var IE_PROTO = __webpack_require__(/*! ./_shared-key */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_shared-key.js")('IE_PROTO'); - -module.exports = function (object, names) { - var O = toIObject(object); - var i = 0; - var result = []; - var key; - for (key in O) if (key != IE_PROTO) has(O, key) && result.push(key); - // Don't enum bug & hidden keys - while (names.length > i) if (has(O, key = names[i++])) { - ~arrayIndexOf(result, key) || result.push(key); - } - return result; -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_object-keys.js": -/*!*****************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_object-keys.js ***! - \*****************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -// 19.1.2.14 / 15.2.3.14 Object.keys(O) -var $keys = __webpack_require__(/*! ./_object-keys-internal */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_object-keys-internal.js"); -var enumBugKeys = __webpack_require__(/*! ./_enum-bug-keys */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_enum-bug-keys.js"); - -module.exports = Object.keys || function keys(O) { - return $keys(O, enumBugKeys); -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_object-pie.js": -/*!****************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_object-pie.js ***! - \****************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -exports.f = {}.propertyIsEnumerable; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_property-desc.js": -/*!*******************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_property-desc.js ***! - \*******************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -module.exports = function (bitmap, value) { - return { - enumerable: !(bitmap & 1), - configurable: !(bitmap & 2), - writable: !(bitmap & 4), - value: value - }; -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_shared-key.js": -/*!****************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_shared-key.js ***! - \****************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var shared = __webpack_require__(/*! ./_shared */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_shared.js")('keys'); -var uid = __webpack_require__(/*! ./_uid */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_uid.js"); -module.exports = function (key) { - return shared[key] || (shared[key] = uid(key)); -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_shared.js": -/*!************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_shared.js ***! - \************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var global = __webpack_require__(/*! ./_global */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_global.js"); -var SHARED = '__core-js_shared__'; -var store = global[SHARED] || (global[SHARED] = {}); -module.exports = function (key) { - return store[key] || (store[key] = {}); -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-absolute-index.js": -/*!***********************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-absolute-index.js ***! - \***********************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -var toInteger = __webpack_require__(/*! ./_to-integer */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-integer.js"); -var max = Math.max; -var min = Math.min; -module.exports = function (index, length) { - index = toInteger(index); - return index < 0 ? max(index + length, 0) : min(index, length); -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-integer.js": -/*!****************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-integer.js ***! - \****************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -// 7.1.4 ToInteger -var ceil = Math.ceil; -var floor = Math.floor; -module.exports = function (it) { - return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it); -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-iobject.js": -/*!****************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-iobject.js ***! - \****************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -// to indexed object, toObject with fallback for non-array-like ES3 strings -var IObject = __webpack_require__(/*! ./_iobject */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_iobject.js"); -var defined = __webpack_require__(/*! ./_defined */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_defined.js"); -module.exports = function (it) { - return IObject(defined(it)); -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-length.js": -/*!***************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-length.js ***! - \***************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -// 7.1.15 ToLength -var toInteger = __webpack_require__(/*! ./_to-integer */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-integer.js"); -var min = Math.min; -module.exports = function (it) { - return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0; // pow(2, 53) - 1 == 9007199254740991 -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-object.js": -/*!***************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-object.js ***! - \***************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -// 7.1.13 ToObject(argument) -var defined = __webpack_require__(/*! ./_defined */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_defined.js"); -module.exports = function (it) { - return Object(defined(it)); -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-primitive.js": -/*!******************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_to-primitive.js ***! - \******************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -// 7.1.1 ToPrimitive(input [, PreferredType]) -var isObject = __webpack_require__(/*! ./_is-object */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_is-object.js"); -// instead of the ES6 spec version, we didn't implement @@toPrimitive case -// and the second argument - flag - preferred type is a string -module.exports = function (it, S) { - if (!isObject(it)) return it; - var fn, val; - if (S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val; - if (typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it))) return val; - if (!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val; - throw TypeError("Can't convert object to primitive value"); -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_uid.js": -/*!*********************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/_uid.js ***! - \*********************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports) { - -var id = 0; -var px = Math.random(); -module.exports = function (key) { - return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36)); -}; - - -/***/ }), - -/***/ "./node_modules/babel-runtime/node_modules/core-js/library/modules/es6.object.assign.js": -/*!**********************************************************************************************!*\ - !*** ./node_modules/babel-runtime/node_modules/core-js/library/modules/es6.object.assign.js ***! - \**********************************************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -// 19.1.3.1 Object.assign(target, source) -var $export = __webpack_require__(/*! ./_export */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_export.js"); - -$export($export.S + $export.F, 'Object', { assign: __webpack_require__(/*! ./_object-assign */ "./node_modules/babel-runtime/node_modules/core-js/library/modules/_object-assign.js") }); - - -/***/ }), - -/***/ "./node_modules/jed/jed.js": -/*!*********************************!*\ - !*** ./node_modules/jed/jed.js ***! - \*********************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * @preserve jed.js https://github.com/SlexAxton/Jed - */ -/* ------------ -A gettext compatible i18n library for modern JavaScript Applications - -by Alex Sexton - AlexSexton [at] gmail - @SlexAxton - -MIT License - -A jQuery Foundation project - requires CLA to contribute - -https://contribute.jquery.org/CLA/ - - - -Jed offers the entire applicable GNU gettext spec'd set of -functions, but also offers some nicer wrappers around them. -The api for gettext was written for a language with no function -overloading, so Jed allows a little more of that. - -Many thanks to Joshua I. Miller - unrtst@cpan.org - who wrote -gettext.js back in 2008. I was able to vet a lot of my ideas -against his. I also made sure Jed passed against his tests -in order to offer easy upgrades -- jsgettext.berlios.de -*/ -(function (root, undef) { - - // Set up some underscore-style functions, if you already have - // underscore, feel free to delete this section, and use it - // directly, however, the amount of functions used doesn't - // warrant having underscore as a full dependency. - // Underscore 1.3.0 was used to port and is licensed - // under the MIT License by Jeremy Ashkenas. - var ArrayProto = Array.prototype, - ObjProto = Object.prototype, - slice = ArrayProto.slice, - hasOwnProp = ObjProto.hasOwnProperty, - nativeForEach = ArrayProto.forEach, - breaker = {}; - - // We're not using the OOP style _ so we don't need the - // extra level of indirection. This still means that you - // sub out for real `_` though. - var _ = { - forEach : function( obj, iterator, context ) { - var i, l, key; - if ( obj === null ) { - return; - } - - if ( nativeForEach && obj.forEach === nativeForEach ) { - obj.forEach( iterator, context ); - } - else if ( obj.length === +obj.length ) { - for ( i = 0, l = obj.length; i < l; i++ ) { - if ( i in obj && iterator.call( context, obj[i], i, obj ) === breaker ) { - return; - } - } - } - else { - for ( key in obj) { - if ( hasOwnProp.call( obj, key ) ) { - if ( iterator.call (context, obj[key], key, obj ) === breaker ) { - return; - } - } - } - } - }, - extend : function( obj ) { - this.forEach( slice.call( arguments, 1 ), function ( source ) { - for ( var prop in source ) { - obj[prop] = source[prop]; - } - }); - return obj; - } - }; - // END Miniature underscore impl - - // Jed is a constructor function - var Jed = function ( options ) { - // Some minimal defaults - this.defaults = { - "locale_data" : { - "messages" : { - "" : { - "domain" : "messages", - "lang" : "en", - "plural_forms" : "nplurals=2; plural=(n != 1);" - } - // There are no default keys, though - } - }, - // The default domain if one is missing - "domain" : "messages", - // enable debug mode to log untranslated strings to the console - "debug" : false - }; - - // Mix in the sent options with the default options - this.options = _.extend( {}, this.defaults, options ); - this.textdomain( this.options.domain ); - - if ( options.domain && ! this.options.locale_data[ this.options.domain ] ) { - throw new Error('Text domain set to non-existent domain: `' + options.domain + '`'); - } - }; - - // The gettext spec sets this character as the default - // delimiter for context lookups. - // e.g.: context\u0004key - // If your translation company uses something different, - // just change this at any time and it will use that instead. - Jed.context_delimiter = String.fromCharCode( 4 ); - - function getPluralFormFunc ( plural_form_string ) { - return Jed.PF.compile( plural_form_string || "nplurals=2; plural=(n != 1);"); - } - - function Chain( key, i18n ){ - this._key = key; - this._i18n = i18n; - } - - // Create a chainable api for adding args prettily - _.extend( Chain.prototype, { - onDomain : function ( domain ) { - this._domain = domain; - return this; - }, - withContext : function ( context ) { - this._context = context; - return this; - }, - ifPlural : function ( num, pkey ) { - this._val = num; - this._pkey = pkey; - return this; - }, - fetch : function ( sArr ) { - if ( {}.toString.call( sArr ) != '[object Array]' ) { - sArr = [].slice.call(arguments, 0); - } - return ( sArr && sArr.length ? Jed.sprintf : function(x){ return x; } )( - this._i18n.dcnpgettext(this._domain, this._context, this._key, this._pkey, this._val), - sArr - ); - } - }); - - // Add functions to the Jed prototype. - // These will be the functions on the object that's returned - // from creating a `new Jed()` - // These seem redundant, but they gzip pretty well. - _.extend( Jed.prototype, { - // The sexier api start point - translate : function ( key ) { - return new Chain( key, this ); - }, - - textdomain : function ( domain ) { - if ( ! domain ) { - return this._textdomain; - } - this._textdomain = domain; - }, - - gettext : function ( key ) { - return this.dcnpgettext.call( this, undef, undef, key ); - }, - - dgettext : function ( domain, key ) { - return this.dcnpgettext.call( this, domain, undef, key ); - }, - - dcgettext : function ( domain , key /*, category */ ) { - // Ignores the category anyways - return this.dcnpgettext.call( this, domain, undef, key ); - }, - - ngettext : function ( skey, pkey, val ) { - return this.dcnpgettext.call( this, undef, undef, skey, pkey, val ); - }, - - dngettext : function ( domain, skey, pkey, val ) { - return this.dcnpgettext.call( this, domain, undef, skey, pkey, val ); - }, - - dcngettext : function ( domain, skey, pkey, val/*, category */) { - return this.dcnpgettext.call( this, domain, undef, skey, pkey, val ); - }, - - pgettext : function ( context, key ) { - return this.dcnpgettext.call( this, undef, context, key ); - }, - - dpgettext : function ( domain, context, key ) { - return this.dcnpgettext.call( this, domain, context, key ); - }, - - dcpgettext : function ( domain, context, key/*, category */) { - return this.dcnpgettext.call( this, domain, context, key ); - }, - - npgettext : function ( context, skey, pkey, val ) { - return this.dcnpgettext.call( this, undef, context, skey, pkey, val ); - }, - - dnpgettext : function ( domain, context, skey, pkey, val ) { - return this.dcnpgettext.call( this, domain, context, skey, pkey, val ); - }, - - // The most fully qualified gettext function. It has every option. - // Since it has every option, we can use it from every other method. - // This is the bread and butter. - // Technically there should be one more argument in this function for 'Category', - // but since we never use it, we might as well not waste the bytes to define it. - dcnpgettext : function ( domain, context, singular_key, plural_key, val ) { - // Set some defaults - - plural_key = plural_key || singular_key; - - // Use the global domain default if one - // isn't explicitly passed in - domain = domain || this._textdomain; - - var fallback; - - // Handle special cases - - // No options found - if ( ! this.options ) { - // There's likely something wrong, but we'll return the correct key for english - // We do this by instantiating a brand new Jed instance with the default set - // for everything that could be broken. - fallback = new Jed(); - return fallback.dcnpgettext.call( fallback, undefined, undefined, singular_key, plural_key, val ); - } - - // No translation data provided - if ( ! this.options.locale_data ) { - throw new Error('No locale data provided.'); - } - - if ( ! this.options.locale_data[ domain ] ) { - throw new Error('Domain `' + domain + '` was not found.'); - } - - if ( ! this.options.locale_data[ domain ][ "" ] ) { - throw new Error('No locale meta information provided.'); - } - - // Make sure we have a truthy key. Otherwise we might start looking - // into the empty string key, which is the options for the locale - // data. - if ( ! singular_key ) { - throw new Error('No translation key found.'); - } - - var key = context ? context + Jed.context_delimiter + singular_key : singular_key, - locale_data = this.options.locale_data, - dict = locale_data[ domain ], - defaultConf = (locale_data.messages || this.defaults.locale_data.messages)[""], - pluralForms = dict[""].plural_forms || dict[""]["Plural-Forms"] || dict[""]["plural-forms"] || defaultConf.plural_forms || defaultConf["Plural-Forms"] || defaultConf["plural-forms"], - val_list, - res; - - var val_idx; - if (val === undefined) { - // No value passed in; assume singular key lookup. - val_idx = 0; - - } else { - // Value has been passed in; use plural-forms calculations. - - // Handle invalid numbers, but try casting strings for good measure - if ( typeof val != 'number' ) { - val = parseInt( val, 10 ); - - if ( isNaN( val ) ) { - throw new Error('The number that was passed in is not a number.'); - } - } - - val_idx = getPluralFormFunc(pluralForms)(val); - } - - // Throw an error if a domain isn't found - if ( ! dict ) { - throw new Error('No domain named `' + domain + '` could be found.'); - } - - val_list = dict[ key ]; - - // If there is no match, then revert back to - // english style singular/plural with the keys passed in. - if ( ! val_list || val_idx > val_list.length ) { - if (this.options.missing_key_callback) { - this.options.missing_key_callback(key, domain); - } - res = [ singular_key, plural_key ]; - - // collect untranslated strings - if (this.options.debug===true) { - console.log(res[ getPluralFormFunc(pluralForms)( val ) ]); - } - return res[ getPluralFormFunc()( val ) ]; - } - - res = val_list[ val_idx ]; - - // This includes empty strings on purpose - if ( ! res ) { - res = [ singular_key, plural_key ]; - return res[ getPluralFormFunc()( val ) ]; - } - return res; - } - }); - - - // We add in sprintf capabilities for post translation value interolation - // This is not internally used, so you can remove it if you have this - // available somewhere else, or want to use a different system. - - // We _slightly_ modify the normal sprintf behavior to more gracefully handle - // undefined values. - - /** - sprintf() for JavaScript 0.7-beta1 - http://www.diveintojavascript.com/projects/javascript-sprintf - - Copyright (c) Alexandru Marasteanu - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of sprintf() for JavaScript nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL Alexandru Marasteanu BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - var sprintf = (function() { - function get_type(variable) { - return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase(); - } - function str_repeat(input, multiplier) { - for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */} - return output.join(''); - } - - var str_format = function() { - if (!str_format.cache.hasOwnProperty(arguments[0])) { - str_format.cache[arguments[0]] = str_format.parse(arguments[0]); - } - return str_format.format.call(null, str_format.cache[arguments[0]], arguments); - }; - - str_format.format = function(parse_tree, argv) { - var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length; - for (i = 0; i < tree_length; i++) { - node_type = get_type(parse_tree[i]); - if (node_type === 'string') { - output.push(parse_tree[i]); - } - else if (node_type === 'array') { - match = parse_tree[i]; // convenience purposes only - if (match[2]) { // keyword argument - arg = argv[cursor]; - for (k = 0; k < match[2].length; k++) { - if (!arg.hasOwnProperty(match[2][k])) { - throw(sprintf('[sprintf] property "%s" does not exist', match[2][k])); - } - arg = arg[match[2][k]]; - } - } - else if (match[1]) { // positional argument (explicit) - arg = argv[match[1]]; - } - else { // positional argument (implicit) - arg = argv[cursor++]; - } - - if (/[^s]/.test(match[8]) && (get_type(arg) != 'number')) { - throw(sprintf('[sprintf] expecting number but found %s', get_type(arg))); - } - - // Jed EDIT - if ( typeof arg == 'undefined' || arg === null ) { - arg = ''; - } - // Jed EDIT - - switch (match[8]) { - case 'b': arg = arg.toString(2); break; - case 'c': arg = String.fromCharCode(arg); break; - case 'd': arg = parseInt(arg, 10); break; - case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break; - case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break; - case 'o': arg = arg.toString(8); break; - case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break; - case 'u': arg = Math.abs(arg); break; - case 'x': arg = arg.toString(16); break; - case 'X': arg = arg.toString(16).toUpperCase(); break; - } - arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg); - pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' '; - pad_length = match[6] - String(arg).length; - pad = match[6] ? str_repeat(pad_character, pad_length) : ''; - output.push(match[5] ? arg + pad : pad + arg); - } - } - return output.join(''); - }; - - str_format.cache = {}; - - str_format.parse = function(fmt) { - var _fmt = fmt, match = [], parse_tree = [], arg_names = 0; - while (_fmt) { - if ((match = /^[^\x25]+/.exec(_fmt)) !== null) { - parse_tree.push(match[0]); - } - else if ((match = /^\x25{2}/.exec(_fmt)) !== null) { - parse_tree.push('%'); - } - else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(_fmt)) !== null) { - if (match[2]) { - arg_names |= 1; - var field_list = [], replacement_field = match[2], field_match = []; - if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { - field_list.push(field_match[1]); - while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') { - if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) { - field_list.push(field_match[1]); - } - else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) { - field_list.push(field_match[1]); - } - else { - throw('[sprintf] huh?'); - } - } - } - else { - throw('[sprintf] huh?'); - } - match[2] = field_list; - } - else { - arg_names |= 2; - } - if (arg_names === 3) { - throw('[sprintf] mixing positional and named placeholders is not (yet) supported'); - } - parse_tree.push(match); - } - else { - throw('[sprintf] huh?'); - } - _fmt = _fmt.substring(match[0].length); - } - return parse_tree; - }; - - return str_format; - })(); - - var vsprintf = function(fmt, argv) { - argv.unshift(fmt); - return sprintf.apply(null, argv); - }; - - Jed.parse_plural = function ( plural_forms, n ) { - plural_forms = plural_forms.replace(/n/g, n); - return Jed.parse_expression(plural_forms); - }; - - Jed.sprintf = function ( fmt, args ) { - if ( {}.toString.call( args ) == '[object Array]' ) { - return vsprintf( fmt, [].slice.call(args) ); - } - return sprintf.apply(this, [].slice.call(arguments) ); - }; - - Jed.prototype.sprintf = function () { - return Jed.sprintf.apply(this, arguments); - }; - // END sprintf Implementation - - // Start the Plural forms section - // This is a full plural form expression parser. It is used to avoid - // running 'eval' or 'new Function' directly against the plural - // forms. - // - // This can be important if you get translations done through a 3rd - // party vendor. I encourage you to use this instead, however, I - // also will provide a 'precompiler' that you can use at build time - // to output valid/safe function representations of the plural form - // expressions. This means you can build this code out for the most - // part. - Jed.PF = {}; - - Jed.PF.parse = function ( p ) { - var plural_str = Jed.PF.extractPluralExpr( p ); - return Jed.PF.parser.parse.call(Jed.PF.parser, plural_str); - }; - - Jed.PF.compile = function ( p ) { - // Handle trues and falses as 0 and 1 - function imply( val ) { - return (val === true ? 1 : val ? val : 0); - } - - var ast = Jed.PF.parse( p ); - return function ( n ) { - return imply( Jed.PF.interpreter( ast )( n ) ); - }; - }; - - Jed.PF.interpreter = function ( ast ) { - return function ( n ) { - var res; - switch ( ast.type ) { - case 'GROUP': - return Jed.PF.interpreter( ast.expr )( n ); - case 'TERNARY': - if ( Jed.PF.interpreter( ast.expr )( n ) ) { - return Jed.PF.interpreter( ast.truthy )( n ); - } - return Jed.PF.interpreter( ast.falsey )( n ); - case 'OR': - return Jed.PF.interpreter( ast.left )( n ) || Jed.PF.interpreter( ast.right )( n ); - case 'AND': - return Jed.PF.interpreter( ast.left )( n ) && Jed.PF.interpreter( ast.right )( n ); - case 'LT': - return Jed.PF.interpreter( ast.left )( n ) < Jed.PF.interpreter( ast.right )( n ); - case 'GT': - return Jed.PF.interpreter( ast.left )( n ) > Jed.PF.interpreter( ast.right )( n ); - case 'LTE': - return Jed.PF.interpreter( ast.left )( n ) <= Jed.PF.interpreter( ast.right )( n ); - case 'GTE': - return Jed.PF.interpreter( ast.left )( n ) >= Jed.PF.interpreter( ast.right )( n ); - case 'EQ': - return Jed.PF.interpreter( ast.left )( n ) == Jed.PF.interpreter( ast.right )( n ); - case 'NEQ': - return Jed.PF.interpreter( ast.left )( n ) != Jed.PF.interpreter( ast.right )( n ); - case 'MOD': - return Jed.PF.interpreter( ast.left )( n ) % Jed.PF.interpreter( ast.right )( n ); - case 'VAR': - return n; - case 'NUM': - return ast.val; - default: - throw new Error("Invalid Token found."); - } - }; - }; - - Jed.PF.extractPluralExpr = function ( p ) { - // trim first - p = p.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); - - if (! /;\s*$/.test(p)) { - p = p.concat(';'); - } - - var nplurals_re = /nplurals\=(\d+);/, - plural_re = /plural\=(.*);/, - nplurals_matches = p.match( nplurals_re ), - res = {}, - plural_matches; - - // Find the nplurals number - if ( nplurals_matches.length > 1 ) { - res.nplurals = nplurals_matches[1]; - } - else { - throw new Error('nplurals not found in plural_forms string: ' + p ); - } - - // remove that data to get to the formula - p = p.replace( nplurals_re, "" ); - plural_matches = p.match( plural_re ); - - if (!( plural_matches && plural_matches.length > 1 ) ) { - throw new Error('`plural` expression not found: ' + p); - } - return plural_matches[ 1 ]; - }; - - /* Jison generated parser */ - Jed.PF.parser = (function(){ - -var parser = {trace: function trace() { }, -yy: {}, -symbols_: {"error":2,"expressions":3,"e":4,"EOF":5,"?":6,":":7,"||":8,"&&":9,"<":10,"<=":11,">":12,">=":13,"!=":14,"==":15,"%":16,"(":17,")":18,"n":19,"NUMBER":20,"$accept":0,"$end":1}, -terminals_: {2:"error",5:"EOF",6:"?",7:":",8:"||",9:"&&",10:"<",11:"<=",12:">",13:">=",14:"!=",15:"==",16:"%",17:"(",18:")",19:"n",20:"NUMBER"}, -productions_: [0,[3,2],[4,5],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,1],[4,1]], -performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$,_$) { - -var $0 = $$.length - 1; -switch (yystate) { -case 1: return { type : 'GROUP', expr: $$[$0-1] }; -break; -case 2:this.$ = { type: 'TERNARY', expr: $$[$0-4], truthy : $$[$0-2], falsey: $$[$0] }; -break; -case 3:this.$ = { type: "OR", left: $$[$0-2], right: $$[$0] }; -break; -case 4:this.$ = { type: "AND", left: $$[$0-2], right: $$[$0] }; -break; -case 5:this.$ = { type: 'LT', left: $$[$0-2], right: $$[$0] }; -break; -case 6:this.$ = { type: 'LTE', left: $$[$0-2], right: $$[$0] }; -break; -case 7:this.$ = { type: 'GT', left: $$[$0-2], right: $$[$0] }; -break; -case 8:this.$ = { type: 'GTE', left: $$[$0-2], right: $$[$0] }; -break; -case 9:this.$ = { type: 'NEQ', left: $$[$0-2], right: $$[$0] }; -break; -case 10:this.$ = { type: 'EQ', left: $$[$0-2], right: $$[$0] }; -break; -case 11:this.$ = { type: 'MOD', left: $$[$0-2], right: $$[$0] }; -break; -case 12:this.$ = { type: 'GROUP', expr: $$[$0-1] }; -break; -case 13:this.$ = { type: 'VAR' }; -break; -case 14:this.$ = { type: 'NUM', val: Number(yytext) }; -break; -} -}, -table: [{3:1,4:2,17:[1,3],19:[1,4],20:[1,5]},{1:[3]},{5:[1,6],6:[1,7],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16]},{4:17,17:[1,3],19:[1,4],20:[1,5]},{5:[2,13],6:[2,13],7:[2,13],8:[2,13],9:[2,13],10:[2,13],11:[2,13],12:[2,13],13:[2,13],14:[2,13],15:[2,13],16:[2,13],18:[2,13]},{5:[2,14],6:[2,14],7:[2,14],8:[2,14],9:[2,14],10:[2,14],11:[2,14],12:[2,14],13:[2,14],14:[2,14],15:[2,14],16:[2,14],18:[2,14]},{1:[2,1]},{4:18,17:[1,3],19:[1,4],20:[1,5]},{4:19,17:[1,3],19:[1,4],20:[1,5]},{4:20,17:[1,3],19:[1,4],20:[1,5]},{4:21,17:[1,3],19:[1,4],20:[1,5]},{4:22,17:[1,3],19:[1,4],20:[1,5]},{4:23,17:[1,3],19:[1,4],20:[1,5]},{4:24,17:[1,3],19:[1,4],20:[1,5]},{4:25,17:[1,3],19:[1,4],20:[1,5]},{4:26,17:[1,3],19:[1,4],20:[1,5]},{4:27,17:[1,3],19:[1,4],20:[1,5]},{6:[1,7],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[1,28]},{6:[1,7],7:[1,29],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16]},{5:[2,3],6:[2,3],7:[2,3],8:[2,3],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,3]},{5:[2,4],6:[2,4],7:[2,4],8:[2,4],9:[2,4],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,4]},{5:[2,5],6:[2,5],7:[2,5],8:[2,5],9:[2,5],10:[2,5],11:[2,5],12:[2,5],13:[2,5],14:[2,5],15:[2,5],16:[1,16],18:[2,5]},{5:[2,6],6:[2,6],7:[2,6],8:[2,6],9:[2,6],10:[2,6],11:[2,6],12:[2,6],13:[2,6],14:[2,6],15:[2,6],16:[1,16],18:[2,6]},{5:[2,7],6:[2,7],7:[2,7],8:[2,7],9:[2,7],10:[2,7],11:[2,7],12:[2,7],13:[2,7],14:[2,7],15:[2,7],16:[1,16],18:[2,7]},{5:[2,8],6:[2,8],7:[2,8],8:[2,8],9:[2,8],10:[2,8],11:[2,8],12:[2,8],13:[2,8],14:[2,8],15:[2,8],16:[1,16],18:[2,8]},{5:[2,9],6:[2,9],7:[2,9],8:[2,9],9:[2,9],10:[2,9],11:[2,9],12:[2,9],13:[2,9],14:[2,9],15:[2,9],16:[1,16],18:[2,9]},{5:[2,10],6:[2,10],7:[2,10],8:[2,10],9:[2,10],10:[2,10],11:[2,10],12:[2,10],13:[2,10],14:[2,10],15:[2,10],16:[1,16],18:[2,10]},{5:[2,11],6:[2,11],7:[2,11],8:[2,11],9:[2,11],10:[2,11],11:[2,11],12:[2,11],13:[2,11],14:[2,11],15:[2,11],16:[2,11],18:[2,11]},{5:[2,12],6:[2,12],7:[2,12],8:[2,12],9:[2,12],10:[2,12],11:[2,12],12:[2,12],13:[2,12],14:[2,12],15:[2,12],16:[2,12],18:[2,12]},{4:30,17:[1,3],19:[1,4],20:[1,5]},{5:[2,2],6:[1,7],7:[2,2],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,2]}], -defaultActions: {6:[2,1]}, -parseError: function parseError(str, hash) { - throw new Error(str); -}, -parse: function parse(input) { - var self = this, - stack = [0], - vstack = [null], // semantic value stack - lstack = [], // location stack - table = this.table, - yytext = '', - yylineno = 0, - yyleng = 0, - recovering = 0, - TERROR = 2, - EOF = 1; - - //this.reductionCount = this.shiftCount = 0; - - this.lexer.setInput(input); - this.lexer.yy = this.yy; - this.yy.lexer = this.lexer; - if (typeof this.lexer.yylloc == 'undefined') - this.lexer.yylloc = {}; - var yyloc = this.lexer.yylloc; - lstack.push(yyloc); - - if (typeof this.yy.parseError === 'function') - this.parseError = this.yy.parseError; - - function popStack (n) { - stack.length = stack.length - 2*n; - vstack.length = vstack.length - n; - lstack.length = lstack.length - n; - } - - function lex() { - var token; - token = self.lexer.lex() || 1; // $end = 1 - // if token isn't its numeric value, convert - if (typeof token !== 'number') { - token = self.symbols_[token] || token; - } - return token; - } - - var symbol, preErrorSymbol, state, action, a, r, yyval={},p,len,newState, expected; - while (true) { - // retreive state number from top of stack - state = stack[stack.length-1]; - - // use default actions if available - if (this.defaultActions[state]) { - action = this.defaultActions[state]; - } else { - if (symbol == null) - symbol = lex(); - // read action for current state and first input - action = table[state] && table[state][symbol]; - } - - // handle parse error - _handle_error: - if (typeof action === 'undefined' || !action.length || !action[0]) { - - if (!recovering) { - // Report error - expected = []; - for (p in table[state]) if (this.terminals_[p] && p > 2) { - expected.push("'"+this.terminals_[p]+"'"); - } - var errStr = ''; - if (this.lexer.showPosition) { - errStr = 'Parse error on line '+(yylineno+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+expected.join(', ') + ", got '" + this.terminals_[symbol]+ "'"; - } else { - errStr = 'Parse error on line '+(yylineno+1)+": Unexpected " + - (symbol == 1 /*EOF*/ ? "end of input" : - ("'"+(this.terminals_[symbol] || symbol)+"'")); - } - this.parseError(errStr, - {text: this.lexer.match, token: this.terminals_[symbol] || symbol, line: this.lexer.yylineno, loc: yyloc, expected: expected}); - } - - // just recovered from another error - if (recovering == 3) { - if (symbol == EOF) { - throw new Error(errStr || 'Parsing halted.'); - } - - // discard current lookahead and grab another - yyleng = this.lexer.yyleng; - yytext = this.lexer.yytext; - yylineno = this.lexer.yylineno; - yyloc = this.lexer.yylloc; - symbol = lex(); - } - - // try to recover from error - while (1) { - // check for error recovery rule in this state - if ((TERROR.toString()) in table[state]) { - break; - } - if (state == 0) { - throw new Error(errStr || 'Parsing halted.'); - } - popStack(1); - state = stack[stack.length-1]; - } - - preErrorSymbol = symbol; // save the lookahead token - symbol = TERROR; // insert generic error symbol as new lookahead - state = stack[stack.length-1]; - action = table[state] && table[state][TERROR]; - recovering = 3; // allow 3 real symbols to be shifted before reporting a new error - } - - // this shouldn't happen, unless resolve defaults are off - if (action[0] instanceof Array && action.length > 1) { - throw new Error('Parse Error: multiple actions possible at state: '+state+', token: '+symbol); - } - - switch (action[0]) { - - case 1: // shift - //this.shiftCount++; - - stack.push(symbol); - vstack.push(this.lexer.yytext); - lstack.push(this.lexer.yylloc); - stack.push(action[1]); // push state - symbol = null; - if (!preErrorSymbol) { // normal execution/no error - yyleng = this.lexer.yyleng; - yytext = this.lexer.yytext; - yylineno = this.lexer.yylineno; - yyloc = this.lexer.yylloc; - if (recovering > 0) - recovering--; - } else { // error just occurred, resume old lookahead f/ before error - symbol = preErrorSymbol; - preErrorSymbol = null; - } - break; - - case 2: // reduce - //this.reductionCount++; - - len = this.productions_[action[1]][1]; - - // perform semantic action - yyval.$ = vstack[vstack.length-len]; // default to $$ = $1 - // default location, uses first token for firsts, last for lasts - yyval._$ = { - first_line: lstack[lstack.length-(len||1)].first_line, - last_line: lstack[lstack.length-1].last_line, - first_column: lstack[lstack.length-(len||1)].first_column, - last_column: lstack[lstack.length-1].last_column - }; - r = this.performAction.call(yyval, yytext, yyleng, yylineno, this.yy, action[1], vstack, lstack); - - if (typeof r !== 'undefined') { - return r; - } - - // pop off stack - if (len) { - stack = stack.slice(0,-1*len*2); - vstack = vstack.slice(0, -1*len); - lstack = lstack.slice(0, -1*len); - } - - stack.push(this.productions_[action[1]][0]); // push nonterminal (reduce) - vstack.push(yyval.$); - lstack.push(yyval._$); - // goto new state = table[STATE][NONTERMINAL] - newState = table[stack[stack.length-2]][stack[stack.length-1]]; - stack.push(newState); - break; - - case 3: // accept - return true; - } - - } - - return true; -}};/* Jison generated lexer */ -var lexer = (function(){ - -var lexer = ({EOF:1, -parseError:function parseError(str, hash) { - if (this.yy.parseError) { - this.yy.parseError(str, hash); - } else { - throw new Error(str); - } - }, -setInput:function (input) { - this._input = input; - this._more = this._less = this.done = false; - this.yylineno = this.yyleng = 0; - this.yytext = this.matched = this.match = ''; - this.conditionStack = ['INITIAL']; - this.yylloc = {first_line:1,first_column:0,last_line:1,last_column:0}; - return this; - }, -input:function () { - var ch = this._input[0]; - this.yytext+=ch; - this.yyleng++; - this.match+=ch; - this.matched+=ch; - var lines = ch.match(/\n/); - if (lines) this.yylineno++; - this._input = this._input.slice(1); - return ch; - }, -unput:function (ch) { - this._input = ch + this._input; - return this; - }, -more:function () { - this._more = true; - return this; - }, -pastInput:function () { - var past = this.matched.substr(0, this.matched.length - this.match.length); - return (past.length > 20 ? '...':'') + past.substr(-20).replace(/\n/g, ""); - }, -upcomingInput:function () { - var next = this.match; - if (next.length < 20) { - next += this._input.substr(0, 20-next.length); - } - return (next.substr(0,20)+(next.length > 20 ? '...':'')).replace(/\n/g, ""); - }, -showPosition:function () { - var pre = this.pastInput(); - var c = new Array(pre.length + 1).join("-"); - return pre + this.upcomingInput() + "\n" + c+"^"; - }, -next:function () { - if (this.done) { - return this.EOF; - } - if (!this._input) this.done = true; - - var token, - match, - col, - lines; - if (!this._more) { - this.yytext = ''; - this.match = ''; - } - var rules = this._currentRules(); - for (var i=0;i < rules.length; i++) { - match = this._input.match(this.rules[rules[i]]); - if (match) { - lines = match[0].match(/\n.*/g); - if (lines) this.yylineno += lines.length; - this.yylloc = {first_line: this.yylloc.last_line, - last_line: this.yylineno+1, - first_column: this.yylloc.last_column, - last_column: lines ? lines[lines.length-1].length-1 : this.yylloc.last_column + match[0].length} - this.yytext += match[0]; - this.match += match[0]; - this.matches = match; - this.yyleng = this.yytext.length; - this._more = false; - this._input = this._input.slice(match[0].length); - this.matched += match[0]; - token = this.performAction.call(this, this.yy, this, rules[i],this.conditionStack[this.conditionStack.length-1]); - if (token) return token; - else return; - } - } - if (this._input === "") { - return this.EOF; - } else { - this.parseError('Lexical error on line '+(this.yylineno+1)+'. Unrecognized text.\n'+this.showPosition(), - {text: "", token: null, line: this.yylineno}); - } - }, -lex:function lex() { - var r = this.next(); - if (typeof r !== 'undefined') { - return r; - } else { - return this.lex(); - } - }, -begin:function begin(condition) { - this.conditionStack.push(condition); - }, -popState:function popState() { - return this.conditionStack.pop(); - }, -_currentRules:function _currentRules() { - return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules; - }, -topState:function () { - return this.conditionStack[this.conditionStack.length-2]; - }, -pushState:function begin(condition) { - this.begin(condition); - }}); -lexer.performAction = function anonymous(yy,yy_,$avoiding_name_collisions,YY_START) { - -var YYSTATE=YY_START; -switch($avoiding_name_collisions) { -case 0:/* skip whitespace */ -break; -case 1:return 20 -break; -case 2:return 19 -break; -case 3:return 8 -break; -case 4:return 9 -break; -case 5:return 6 -break; -case 6:return 7 -break; -case 7:return 11 -break; -case 8:return 13 -break; -case 9:return 10 -break; -case 10:return 12 -break; -case 11:return 14 -break; -case 12:return 15 -break; -case 13:return 16 -break; -case 14:return 17 -break; -case 15:return 18 -break; -case 16:return 5 -break; -case 17:return 'INVALID' -break; -} -}; -lexer.rules = [/^\s+/,/^[0-9]+(\.[0-9]+)?\b/,/^n\b/,/^\|\|/,/^&&/,/^\?/,/^:/,/^<=/,/^>=/,/^/,/^!=/,/^==/,/^%/,/^\(/,/^\)/,/^$/,/^./]; -lexer.conditions = {"INITIAL":{"rules":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],"inclusive":true}};return lexer;})() -parser.lexer = lexer; -return parser; -})(); -// End parser - - // Handle node, amd, and global systems - if (true) { - if (typeof module !== 'undefined' && module.exports) { - exports = module.exports = Jed; - } - exports.Jed = Jed; - } - else {} - -})(this); - - -/***/ }), - -/***/ "./node_modules/memize/index.js": -/*!**************************************!*\ - !*** ./node_modules/memize/index.js ***! - \**************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -module.exports = function memize( fn, options ) { - var size = 0, - maxSize, head, tail; - - if ( options && options.maxSize ) { - maxSize = options.maxSize; - } - - function memoized( /* ...args */ ) { - var node = head, - len = arguments.length, - args, i; - - searchCache: while ( node ) { - // Perform a shallow equality test to confirm that whether the node - // under test is a candidate for the arguments passed. Two arrays - // are shallowly equal if their length matches and each entry is - // strictly equal between the two sets. Avoid abstracting to a - // function which could incur an arguments leaking deoptimization. - - // Check whether node arguments match arguments length - if ( node.args.length !== arguments.length ) { - node = node.next; - continue; - } - - // Check whether node arguments match arguments values - for ( i = 0; i < len; i++ ) { - if ( node.args[ i ] !== arguments[ i ] ) { - node = node.next; - continue searchCache; - } - } - - // At this point we can assume we've found a match - - // Surface matched node to head if not already - if ( node !== head ) { - // As tail, shift to previous. Must only shift if not also - // head, since if both head and tail, there is no previous. - if ( node === tail ) { - tail = node.prev; - } - - // Adjust siblings to point to each other. If node was tail, - // this also handles new tail's empty `next` assignment. - node.prev.next = node.next; - if ( node.next ) { - node.next.prev = node.prev; - } - - node.next = head; - node.prev = null; - head.prev = node; - head = node; - } - - // Return immediately - return node.val; - } - - // No cached value found. Continue to insertion phase: - - // Create a copy of arguments (avoid leaking deoptimization) - args = new Array( len ); - for ( i = 0; i < len; i++ ) { - args[ i ] = arguments[ i ]; - } - - node = { - args: args, - - // Generate the result from original function - val: fn.apply( null, args ) - }; - - // Don't need to check whether node is already head, since it would - // have been returned above already if it was - - // Shift existing head down list - if ( head ) { - head.prev = node; - node.next = head; - } else { - // If no head, follows that there's no tail (at initial or reset) - tail = node; - } - - // Trim tail if we're reached max size and are pending cache insertion - if ( size === maxSize ) { - tail = tail.prev; - tail.next = null; - } else { - size++; - } - - head = node; - - return node.val; - } - - memoized.clear = function() { - head = null; - tail = null; - size = 0; - }; - - if ( false ) {} - - return memoized; -}; - - -/***/ }), - -/***/ 0: -/*!****************************************!*\ - !*** multi ./assets/src/eejs/index.js ***! - \****************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -module.exports = __webpack_require__(/*! ./assets/src/eejs/index.js */"./assets/src/eejs/index.js"); - - -/***/ }) - -/******/ }); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9lZWpzL3dlYnBhY2svYm9vdHN0cmFwIiwid2VicGFjazovL2VlanMvLi9hc3NldHMvc3JjL2VlanMvaW5kZXguanMiLCJ3ZWJwYWNrOi8vZWVqcy8uL25vZGVfbW9kdWxlcy9Ad29yZHByZXNzL2kxOG4vYnVpbGQtbW9kdWxlL2luZGV4LmpzIiwid2VicGFjazovL2VlanMvLi9ub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9jb3JlLWpzL29iamVjdC9hc3NpZ24uanMiLCJ3ZWJwYWNrOi8vZWVqcy8uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2Fzc2lnbi5qcyIsIndlYnBhY2s6Ly9lZWpzLy4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19hLWZ1bmN0aW9uLmpzIiwid2VicGFjazovL2VlanMvLi9ub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2FuLW9iamVjdC5qcyIsIndlYnBhY2s6Ly9lZWpzLy4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19hcnJheS1pbmNsdWRlcy5qcyIsIndlYnBhY2s6Ly9lZWpzLy4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19jb2YuanMiLCJ3ZWJwYWNrOi8vZWVqcy8uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fY29yZS5qcyIsIndlYnBhY2s6Ly9lZWpzLy4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19jdHguanMiLCJ3ZWJwYWNrOi8vZWVqcy8uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fZGVmaW5lZC5qcyIsIndlYnBhY2s6Ly9lZWpzLy4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19kZXNjcmlwdG9ycy5qcyIsIndlYnBhY2s6Ly9lZWpzLy4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19kb20tY3JlYXRlLmpzIiwid2VicGFjazovL2VlanMvLi9ub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2VudW0tYnVnLWtleXMuanMiLCJ3ZWJwYWNrOi8vZWVqcy8uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fZXhwb3J0LmpzIiwid2VicGFjazovL2VlanMvLi9ub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2ZhaWxzLmpzIiwid2VicGFjazovL2VlanMvLi9ub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2dsb2JhbC5qcyIsIndlYnBhY2s6Ly9lZWpzLy4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19oYXMuanMiLCJ3ZWJwYWNrOi8vZWVqcy8uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faGlkZS5qcyIsIndlYnBhY2s6Ly9lZWpzLy4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pZTgtZG9tLWRlZmluZS5qcyIsIndlYnBhY2s6Ly9lZWpzLy4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pb2JqZWN0LmpzIiwid2VicGFjazovL2VlanMvLi9ub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2lzLW9iamVjdC5qcyIsIndlYnBhY2s6Ly9lZWpzLy4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3QtYXNzaWduLmpzIiwid2VicGFjazovL2VlanMvLi9ub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX29iamVjdC1kcC5qcyIsIndlYnBhY2s6Ly9lZWpzLy4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3QtZ29wcy5qcyIsIndlYnBhY2s6Ly9lZWpzLy4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3Qta2V5cy1pbnRlcm5hbC5qcyIsIndlYnBhY2s6Ly9lZWpzLy4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3Qta2V5cy5qcyIsIndlYnBhY2s6Ly9lZWpzLy4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19vYmplY3QtcGllLmpzIiwid2VicGFjazovL2VlanMvLi9ub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3Byb3BlcnR5LWRlc2MuanMiLCJ3ZWJwYWNrOi8vZWVqcy8uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fc2hhcmVkLWtleS5qcyIsIndlYnBhY2s6Ly9lZWpzLy4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19zaGFyZWQuanMiLCJ3ZWJwYWNrOi8vZWVqcy8uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fdG8tYWJzb2x1dGUtaW5kZXguanMiLCJ3ZWJwYWNrOi8vZWVqcy8uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fdG8taW50ZWdlci5qcyIsIndlYnBhY2s6Ly9lZWpzLy4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL190by1pb2JqZWN0LmpzIiwid2VicGFjazovL2VlanMvLi9ub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3RvLWxlbmd0aC5qcyIsIndlYnBhY2s6Ly9lZWpzLy4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL190by1vYmplY3QuanMiLCJ3ZWJwYWNrOi8vZWVqcy8uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fdG8tcHJpbWl0aXZlLmpzIiwid2VicGFjazovL2VlanMvLi9ub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX3VpZC5qcyIsIndlYnBhY2s6Ly9lZWpzLy4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2VzNi5vYmplY3QuYXNzaWduLmpzIiwid2VicGFjazovL2VlanMvLi9ub2RlX21vZHVsZXMvamVkL2plZC5qcyIsIndlYnBhY2s6Ly9lZWpzLy4vbm9kZV9tb2R1bGVzL21lbWl6ZS9pbmRleC5qcyJdLCJuYW1lcyI6WyJkYXRhIiwiZWVqc2RhdGEiLCJpMThuIiwiZXhjZXB0aW9uIiwibXNnIiwibWVzc2FnZSJdLCJtYXBwaW5ncyI6Ijs7QUFBQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBSztBQUNMO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHlEQUFpRCxjQUFjO0FBQy9EOztBQUVBO0FBQ0E7QUFDQTtBQUNBLG1DQUEyQiwwQkFBMEIsRUFBRTtBQUN2RCx5Q0FBaUMsZUFBZTtBQUNoRDtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw4REFBc0QsK0RBQStEOztBQUVySDtBQUNBOzs7QUFHQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7OztBQ25FQTtBQUFBOzs7QUFHQTs7QUFFQTs7OztBQUlBOzs7O0FBSU8sSUFBTUEsT0FBT0MsU0FBU0QsSUFBVCxJQUFpQixFQUE5Qjs7QUFFUDs7OztBQUlPLElBQU1FLE9BQU8sNENBQWI7O0FBRVA7Ozs7O0FBS08sSUFBTUMsWUFBWSxTQUFaQSxTQUFZLENBQVVDLEdBQVYsRUFBZ0I7QUFDeEMsT0FBS0MsT0FBTCxHQUFlRCxHQUFmO0FBQ0EsQ0FGTSxDOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUMxQlA7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0Esb0NBQW9DO0FBQ3BDO0FBQ0E7QUFDQTtBQUNBLFdBQVcsS0FBSztBQUNoQjtBQUNBLGdGQUEwQzs7QUFFMUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxRQUFRO0FBQ25CLFdBQVcsUUFBUTtBQUNuQjtBQUNBO0FBQ0Esd0ZBQXdGLE9BQU87QUFDL0Y7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMOztBQUVBLGtIQUFzRDtBQUN0RDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFlBQVksSUFBSTtBQUNoQjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRO0FBQ25CLFdBQVcsT0FBTztBQUNsQjtBQUNBLFdBQVcsUUFBUTtBQUNuQixXQUFXLFFBQVE7QUFDbkI7QUFDQTtBQUNBLFlBQVksT0FBTztBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxRQUFRO0FBQ25CO0FBQ0EsWUFBWSxPQUFPO0FBQ25CO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsUUFBUTtBQUNuQjtBQUNBLFlBQVksT0FBTztBQUNuQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTztBQUNsQjtBQUNBLFdBQVcsUUFBUTtBQUNuQjtBQUNBLFlBQVksT0FBTztBQUNuQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxPQUFPO0FBQ2xCLFdBQVcsT0FBTztBQUNsQjtBQUNBLFdBQVcsT0FBTztBQUNsQixXQUFXLFFBQVE7QUFDbkI7QUFDQSxZQUFZLE9BQU87QUFDbkI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxXQUFXLE9BQU87QUFDbEIsV0FBVyxTQUFTO0FBQ3BCO0FBQ0E7QUFDQTtBQUNBLFlBQVksT0FBTztBQUNuQjtBQUNBO0FBQ0E7QUFDQSxzRkFBc0YsYUFBYTtBQUNuRztBQUNBOztBQUVBO0FBQ0EsR0FBRztBQUNIOztBQUVBO0FBQ0E7QUFDQSxDOzs7Ozs7Ozs7OztBQ2hMQSxrQkFBa0IsNks7Ozs7Ozs7Ozs7O0FDQWxCO0FBQ0E7Ozs7Ozs7Ozs7OztBQ0RBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUNKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLLFlBQVksZUFBZTtBQUNoQztBQUNBLEtBQUs7QUFDTDtBQUNBOzs7Ozs7Ozs7Ozs7QUN0QkEsaUJBQWlCOztBQUVqQjtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQ0pBLDZCQUE2QjtBQUM3Qix1Q0FBdUM7Ozs7Ozs7Ozs7OztBQ0R2QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUNuQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FDSkE7QUFDQTtBQUNBLGlDQUFpQyxRQUFRLG1CQUFtQixVQUFVLEVBQUUsRUFBRTtBQUMxRSxDQUFDOzs7Ozs7Ozs7Ozs7QUNIRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FDTkE7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQ0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlFQUFpRTtBQUNqRTtBQUNBLGtGQUFrRjtBQUNsRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVztBQUNYLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsK0NBQStDO0FBQy9DO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGNBQWM7QUFDZCxjQUFjO0FBQ2QsY0FBYztBQUNkLGNBQWM7QUFDZCxlQUFlO0FBQ2YsZUFBZTtBQUNmLGVBQWU7QUFDZixnQkFBZ0I7QUFDaEI7Ozs7Ozs7Ozs7OztBQzdEQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUNOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUNBQXlDOzs7Ozs7Ozs7Ozs7QUNMekMsdUJBQXVCO0FBQ3ZCO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FDSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxDQUFDO0FBQ0Q7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUNQQTtBQUNBLDBLQUFzRSxtQkFBbUIsVUFBVSxFQUFFLEVBQUU7QUFDdkcsQ0FBQzs7Ozs7Ozs7Ozs7O0FDRkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUNMQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7QUNGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQ0FBb0MsVUFBVSxFQUFFO0FBQ2hELG1CQUFtQixzQ0FBc0M7QUFDekQsQ0FBQyxxQ0FBcUM7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNILENBQUM7Ozs7Ozs7Ozs7OztBQ2pDRDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHLFlBQVk7QUFDZjtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FDZkE7Ozs7Ozs7Ozs7OztBQ0FBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FDaEJBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQ05BLGNBQWM7Ozs7Ozs7Ozs7OztBQ0FkO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQ0pBO0FBQ0E7QUFDQSxrREFBa0Q7QUFDbEQ7QUFDQSx1Q0FBdUM7QUFDdkM7Ozs7Ozs7Ozs7OztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUNOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyREFBMkQ7QUFDM0Q7Ozs7Ozs7Ozs7OztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQ0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FDWEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FDSkE7QUFDQTs7QUFFQSwwQ0FBMEMsNklBQXNDOzs7Ozs7Ozs7Ozs7QUNIaEY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLG9DQUFvQyxPQUFPO0FBQzNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5Q0FBeUMsaUJBQWlCO0FBQzFEO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsK0JBQStCO0FBQy9COztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDZEQUE2RCxpQkFBaUI7QUFDOUU7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLCtEQUErRCxVQUFVLEVBQUU7QUFDM0U7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQSxLQUFLOztBQUVMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLDhCQUE4QjtBQUM5Qjs7QUFFQSxPQUFPO0FBQ1Asb0NBQW9DOztBQUVwQztBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOzs7QUFHSDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMkJBQTJCLGdCQUFnQixnQ0FBZ0M7QUFDM0U7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLGlCQUFpQixpQkFBaUI7QUFDbEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGdDQUFnQztBQUNoQyx5QkFBeUI7QUFDekI7QUFDQSx1QkFBdUIscUJBQXFCO0FBQzVDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLDhCQUE4QjtBQUM5QjtBQUNBO0FBQ0EsZ0JBQWdCO0FBQ2hCO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSw0Q0FBNEM7QUFDNUMscURBQXFEO0FBQ3JELDhDQUE4QztBQUM5Qyx5RkFBeUY7QUFDekYsMkZBQTJGO0FBQzNGLDRDQUE0QztBQUM1QyxpR0FBaUc7QUFDakcsMENBQTBDO0FBQzFDLDZDQUE2QztBQUM3QywyREFBMkQ7QUFDM0Q7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUNBQWlDLEVBQUU7QUFDbkM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsV0FBVztBQUNYO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsWUFBWTtBQUNaLHFCQUFxQjtBQUNyQjs7QUFFQSx1Q0FBdUM7QUFDdkMsa0NBQWtDO0FBQ2xDO0FBQ0EsZ0JBQWdCO0FBQ2hCOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsY0FBYyx5QkFBeUIsRUFBRTtBQUN6QyxNQUFNO0FBQ04sV0FBVyw2S0FBNks7QUFDeEwsYUFBYSxrSUFBa0k7QUFDL0k7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsZ0JBQWdCO0FBQ2hCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0Esa0JBQWtCO0FBQ2xCO0FBQ0E7QUFDQSxDQUFDO0FBQ0QsU0FBUyxtQ0FBbUMsRUFBRSxNQUFNLEVBQUUsc0dBQXNHLEVBQUUsZ0NBQWdDLEVBQUUsNkhBQTZILEVBQUUsNkhBQTZILEVBQUUsUUFBUSxFQUFFLGdDQUFnQyxFQUFFLGdDQUFnQyxFQUFFLGdDQUFnQyxFQUFFLGdDQUFnQyxFQUFFLGdDQUFnQyxFQUFFLGdDQUFnQyxFQUFFLGdDQUFnQyxFQUFFLGdDQUFnQyxFQUFFLGdDQUFnQyxFQUFFLGdDQUFnQyxFQUFFLHdHQUF3RyxFQUFFLHVHQUF1RyxFQUFFLHVIQUF1SCxFQUFFLHVIQUF1SCxFQUFFLGlIQUFpSCxFQUFFLGlIQUFpSCxFQUFFLGlIQUFpSCxFQUFFLGlIQUFpSCxFQUFFLGlIQUFpSCxFQUFFLDZIQUE2SCxFQUFFLDZIQUE2SCxFQUFFLDZIQUE2SCxFQUFFLGdDQUFnQyxFQUFFLHVIQUF1SDtBQUN0ekUsaUJBQWlCLFFBQVE7QUFDekI7QUFDQTtBQUNBLENBQUM7QUFDRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLDZEQUE2RDtBQUM3RDtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQjtBQUNqQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EscUJBQXFCLDRIQUE0SDtBQUNqSjs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxvQ0FBb0M7QUFDcEMsNEJBQTRCO0FBQzVCO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0I7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxzQ0FBc0M7QUFDdEM7QUFDQSxzQ0FBc0M7QUFDdEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCLE9BQU87QUFDeEI7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLG9EQUFvRDtBQUNwRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsNERBQTREO0FBQzVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7O0FBRUEsY0FBYztBQUNkO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QjtBQUN2QjtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxxQkFBcUIsaUJBQWlCO0FBQ3RDO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsK0JBQStCO0FBQy9CO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQSxxQkFBcUIsMkNBQTJDO0FBQ2hFO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0EsTUFBTTtBQUNOOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0IsV0FBVyx5RUFBeUUsY0FBYztBQUN0SDtBQUNBO0FBQ0EsQ0FBQztBQUNEOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FRQTs7QUFFQSxDQUFDOzs7Ozs7Ozs7Ozs7QUNsZ0NEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxlQUFlLFNBQVM7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLGNBQWMsU0FBUztBQUN2QjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLGdCQU1BOztBQUVBO0FBQ0EiLCJmaWxlIjoiZWUtZWVqcy4wMDI3ZjdkZWVhNzY2MTMwZDk1MC5kaXN0LmpzIiwic291cmNlc0NvbnRlbnQiOlsiIFx0Ly8gVGhlIG1vZHVsZSBjYWNoZVxuIFx0dmFyIGluc3RhbGxlZE1vZHVsZXMgPSB7fTtcblxuIFx0Ly8gVGhlIHJlcXVpcmUgZnVuY3Rpb25cbiBcdGZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcblxuIFx0XHQvLyBDaGVjayBpZiBtb2R1bGUgaXMgaW4gY2FjaGVcbiBcdFx0aWYoaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0pIHtcbiBcdFx0XHRyZXR1cm4gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0uZXhwb3J0cztcbiBcdFx0fVxuIFx0XHQvLyBDcmVhdGUgYSBuZXcgbW9kdWxlIChhbmQgcHV0IGl0IGludG8gdGhlIGNhY2hlKVxuIFx0XHR2YXIgbW9kdWxlID0gaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0gPSB7XG4gXHRcdFx0aTogbW9kdWxlSWQsXG4gXHRcdFx0bDogZmFsc2UsXG4gXHRcdFx0ZXhwb3J0czoge31cbiBcdFx0fTtcblxuIFx0XHQvLyBFeGVjdXRlIHRoZSBtb2R1bGUgZnVuY3Rpb25cbiBcdFx0bW9kdWxlc1ttb2R1bGVJZF0uY2FsbChtb2R1bGUuZXhwb3J0cywgbW9kdWxlLCBtb2R1bGUuZXhwb3J0cywgX193ZWJwYWNrX3JlcXVpcmVfXyk7XG5cbiBcdFx0Ly8gRmxhZyB0aGUgbW9kdWxlIGFzIGxvYWRlZFxuIFx0XHRtb2R1bGUubCA9IHRydWU7XG5cbiBcdFx0Ly8gUmV0dXJuIHRoZSBleHBvcnRzIG9mIHRoZSBtb2R1bGVcbiBcdFx0cmV0dXJuIG1vZHVsZS5leHBvcnRzO1xuIFx0fVxuXG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlcyBvYmplY3QgKF9fd2VicGFja19tb2R1bGVzX18pXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm0gPSBtb2R1bGVzO1xuXG4gXHQvLyBleHBvc2UgdGhlIG1vZHVsZSBjYWNoZVxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5jID0gaW5zdGFsbGVkTW9kdWxlcztcblxuIFx0Ly8gZGVmaW5lIGdldHRlciBmdW5jdGlvbiBmb3IgaGFybW9ueSBleHBvcnRzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSBmdW5jdGlvbihleHBvcnRzLCBuYW1lLCBnZXR0ZXIpIHtcbiBcdFx0aWYoIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBuYW1lKSkge1xuIFx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBuYW1lLCB7XG4gXHRcdFx0XHRjb25maWd1cmFibGU6IGZhbHNlLFxuIFx0XHRcdFx0ZW51bWVyYWJsZTogdHJ1ZSxcbiBcdFx0XHRcdGdldDogZ2V0dGVyXG4gXHRcdFx0fSk7XG4gXHRcdH1cbiBcdH07XG5cbiBcdC8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uciA9IGZ1bmN0aW9uKGV4cG9ydHMpIHtcbiBcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsICdfX2VzTW9kdWxlJywgeyB2YWx1ZTogdHJ1ZSB9KTtcbiBcdH07XG5cbiBcdC8vIGdldERlZmF1bHRFeHBvcnQgZnVuY3Rpb24gZm9yIGNvbXBhdGliaWxpdHkgd2l0aCBub24taGFybW9ueSBtb2R1bGVzXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm4gPSBmdW5jdGlvbihtb2R1bGUpIHtcbiBcdFx0dmFyIGdldHRlciA9IG1vZHVsZSAmJiBtb2R1bGUuX19lc01vZHVsZSA/XG4gXHRcdFx0ZnVuY3Rpb24gZ2V0RGVmYXVsdCgpIHsgcmV0dXJuIG1vZHVsZVsnZGVmYXVsdCddOyB9IDpcbiBcdFx0XHRmdW5jdGlvbiBnZXRNb2R1bGVFeHBvcnRzKCkgeyByZXR1cm4gbW9kdWxlOyB9O1xuIFx0XHRfX3dlYnBhY2tfcmVxdWlyZV9fLmQoZ2V0dGVyLCAnYScsIGdldHRlcik7XG4gXHRcdHJldHVybiBnZXR0ZXI7XG4gXHR9O1xuXG4gXHQvLyBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGxcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubyA9IGZ1bmN0aW9uKG9iamVjdCwgcHJvcGVydHkpIHsgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIHByb3BlcnR5KTsgfTtcblxuIFx0Ly8gX193ZWJwYWNrX3B1YmxpY19wYXRoX19cbiBcdF9fd2VicGFja19yZXF1aXJlX18ucCA9IFwiXCI7XG5cblxuIFx0Ly8gTG9hZCBlbnRyeSBtb2R1bGUgYW5kIHJldHVybiBleHBvcnRzXG4gXHRyZXR1cm4gX193ZWJwYWNrX3JlcXVpcmVfXyhfX3dlYnBhY2tfcmVxdWlyZV9fLnMgPSAwKTtcbiIsIi8qKlxuICogV29yZFByZXNzIGltcG9ydHNcbiAqL1xuaW1wb3J0ICogYXMgd3BJMThuIGZyb20gJ0B3b3JkcHJlc3MvaTE4bic7XG5cbi8qKlxuICogRXhwb3J0ZWQgdG8gdGhlIGBlZWpzYCBnbG9iYWwuXG4gKi9cblxuLyoqXG4gKiBUaGlzIHdpbGwgaG9sZCBhcmJpdHJhcnkgZGF0YSBhc3NpZ25lZCBieSB0aGUgQXNzZXRzIFJlZ2lzdHJ5LlxuICogQHR5cGUge3t9fVxuICovXG5leHBvcnQgY29uc3QgZGF0YSA9IGVlanNkYXRhLmRhdGEgfHwge307XG5cbi8qKlxuICogV3JhcHBlciBhcm91bmQgd3AuaTE4biBmdW5jdGlvbmFsaXR5IHNvIGl0cyBleHBvc2VkIG9uIHRoZSBlZWpzIGdsb2JhbCBhc1xuICogZWVqcy5pMThuO1xuICovXG5leHBvcnQgY29uc3QgaTE4biA9IHdwSTE4bjtcblxuLyoqXG4gKiB1c2UgdGhpcyBmb3IgZWVqcyBleGNlcHRpb25zXG4gKiBVc2FnZTogdGhyb3cgbmV3IGVlanMuZXhjZXB0aW9uKCdzb21lIG1lc3NhZ2UnKVxuICogQHBhcmFtIHtzdHJpbmd9IG1zZ1xuICovXG5leHBvcnQgY29uc3QgZXhjZXB0aW9uID0gZnVuY3Rpb24oIG1zZyApIHtcblx0dGhpcy5tZXNzYWdlID0gbXNnO1xufTtcbiIsImltcG9ydCBfT2JqZWN0JGFzc2lnbiBmcm9tICdiYWJlbC1ydW50aW1lL2NvcmUtanMvb2JqZWN0L2Fzc2lnbic7XG4vKipcbiAqIEV4dGVybmFsIGRlcGVuZGVuY2llc1xuICovXG5pbXBvcnQgSmVkIGZyb20gJ2plZCc7XG5pbXBvcnQgbWVtb2l6ZSBmcm9tICdtZW1pemUnO1xuXG52YXIgaTE4biA9IHZvaWQgMDtcblxuLyoqXG4gKiBMb2cgdG8gY29uc29sZSwgb25jZSBwZXIgbWVzc2FnZTsgb3IgbW9yZSBwcmVjaXNlbHksIHBlciByZWZlcmVudGlhbGx5IGVxdWFsXG4gKiBhcmd1bWVudCBzZXQuIEJlY2F1c2UgSmVkIHRocm93cyBlcnJvcnMsIHdlIGxvZyB0aGVzZSB0byB0aGUgY29uc29sZSBpbnN0ZWFkXG4gKiB0byBhdm9pZCBjcmFzaGluZyB0aGUgYXBwbGljYXRpb24uXG4gKlxuICogQHBhcmFtIHsuLi4qfSBhcmdzIEFyZ3VtZW50cyB0byBwYXNzIHRvIGBjb25zb2xlLmVycm9yYFxuICovXG52YXIgbG9nRXJyb3JPbmNlID0gbWVtb2l6ZShjb25zb2xlLmVycm9yKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1jb25zb2xlXG5cbi8qKlxuICogTWVyZ2VzIGxvY2FsZSBkYXRhIGludG8gdGhlIEplZCBpbnN0YW5jZSBieSBkb21haW4uIENyZWF0ZXMgYSBuZXcgSmVkXG4gKiBpbnN0YW5jZSBpZiBvbmUgaGFzIG5vdCB5ZXQgYmVlbiBhc3NpZ25lZC5cbiAqXG4gKiBAc2VlIGh0dHA6Ly9tZXNzYWdlZm9ybWF0LmdpdGh1Yi5pby9KZWQvXG4gKlxuICogQHBhcmFtIHs/T2JqZWN0fSBsb2NhbGVEYXRhIExvY2FsZSBkYXRhIGNvbmZpZ3VyYXRpb24uXG4gKiBAcGFyYW0gez9zdHJpbmd9IGRvbWFpbiAgICAgRG9tYWluIGZvciB3aGljaCBjb25maWd1cmF0aW9uIGFwcGxpZXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzZXRMb2NhbGVEYXRhKCkge1xuICB2YXIgbG9jYWxlRGF0YSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogeyAnJzoge30gfTtcbiAgdmFyIGRvbWFpbiA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogJ2RlZmF1bHQnO1xuXG4gIGlmICghaTE4bikge1xuICAgIGkxOG4gPSBuZXcgSmVkKHtcbiAgICAgIGRvbWFpbjogJ2RlZmF1bHQnLFxuICAgICAgbG9jYWxlX2RhdGE6IHtcbiAgICAgICAgZGVmYXVsdDoge31cbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIGkxOG4ub3B0aW9ucy5sb2NhbGVfZGF0YVtkb21haW5dID0gX09iamVjdCRhc3NpZ24oe30sIGkxOG4ub3B0aW9ucy5sb2NhbGVfZGF0YVtkb21haW5dLCBsb2NhbGVEYXRhKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBjdXJyZW50IEplZCBpbnN0YW5jZSwgaW5pdGlhbGl6aW5nIHdpdGggYSBkZWZhdWx0IGNvbmZpZ3VyYXRpb25cbiAqIGlmIG5vdCBhbHJlYWR5IGFzc2lnbmVkLlxuICpcbiAqIEByZXR1cm4ge0plZH0gSmVkIGluc3RhbmNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0STE4bigpIHtcbiAgaWYgKCFpMThuKSB7XG4gICAgc2V0TG9jYWxlRGF0YSgpO1xuICB9XG5cbiAgcmV0dXJuIGkxOG47XG59XG5cbi8qKlxuICogV3JhcHBlciBmb3IgSmVkJ3MgYGRjbnBnZXR0ZXh0YCwgaXRzIG1vc3QgcXVhbGlmaWVkIGZ1bmN0aW9uLiBBYnNvcmJzIGVycm9yc1xuICogd2hpY2ggYXJlIHRocm93biBhcyB0aGUgcmVzdWx0IG9mIGludmFsaWQgdHJhbnNsYXRpb24uXG4gKlxuICogQHBhcmFtIHs/c3RyaW5nfSBkb21haW4gIERvbWFpbiB0byByZXRyaWV2ZSB0aGUgdHJhbnNsYXRlZCB0ZXh0LlxuICogQHBhcmFtIHs/c3RyaW5nfSBjb250ZXh0IENvbnRleHQgaW5mb3JtYXRpb24gZm9yIHRoZSB0cmFuc2xhdG9ycy5cbiAqIEBwYXJhbSB7c3RyaW5nfSAgc2luZ2xlICBUZXh0IHRvIHRyYW5zbGF0ZSBpZiBub24tcGx1cmFsLiBVc2VkIGFzIGZhbGxiYWNrXG4gKiAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlIG9uIGEgY2F1Z2h0IGVycm9yLlxuICogQHBhcmFtIHs/c3RyaW5nfSBwbHVyYWwgIFRoZSB0ZXh0IHRvIGJlIHVzZWQgaWYgdGhlIG51bWJlciBpcyBwbHVyYWwuXG4gKiBAcGFyYW0gez9udW1iZXJ9IG51bWJlciAgVGhlIG51bWJlciB0byBjb21wYXJlIGFnYWluc3QgdG8gdXNlIGVpdGhlciB0aGVcbiAqICAgICAgICAgICAgICAgICAgICAgICAgICBzaW5ndWxhciBvciBwbHVyYWwgZm9ybS5cbiAqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSB0cmFuc2xhdGVkIHN0cmluZy5cbiAqL1xuZXhwb3J0IHZhciBkY25wZ2V0dGV4dCA9IG1lbW9pemUoZnVuY3Rpb24gKCkge1xuICB2YXIgZG9tYWluID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiAnZGVmYXVsdCc7XG4gIHZhciBjb250ZXh0ID0gYXJndW1lbnRzWzFdO1xuICB2YXIgc2luZ2xlID0gYXJndW1lbnRzWzJdO1xuICB2YXIgcGx1cmFsID0gYXJndW1lbnRzWzNdO1xuICB2YXIgbnVtYmVyID0gYXJndW1lbnRzWzRdO1xuXG4gIHRyeSB7XG4gICAgcmV0dXJuIGdldEkxOG4oKS5kY25wZ2V0dGV4dChkb21haW4sIGNvbnRleHQsIHNpbmdsZSwgcGx1cmFsLCBudW1iZXIpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGxvZ0Vycm9yT25jZSgnSmVkIGxvY2FsaXphdGlvbiBlcnJvcjogXFxuXFxuJyArIGVycm9yLnRvU3RyaW5nKCkpO1xuXG4gICAgcmV0dXJuIHNpbmdsZTtcbiAgfVxufSk7XG5cbi8qKlxuICogUmV0cmlldmUgdGhlIHRyYW5zbGF0aW9uIG9mIHRleHQuXG4gKlxuICogQHNlZSBodHRwczovL2RldmVsb3Blci53b3JkcHJlc3Mub3JnL3JlZmVyZW5jZS9mdW5jdGlvbnMvX18vXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9ICB0ZXh0ICAgVGV4dCB0byB0cmFuc2xhdGUuXG4gKiBAcGFyYW0gez9zdHJpbmd9IGRvbWFpbiBEb21haW4gdG8gcmV0cmlldmUgdGhlIHRyYW5zbGF0ZWQgdGV4dC5cbiAqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRyYW5zbGF0ZWQgdGV4dC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIF9fKHRleHQsIGRvbWFpbikge1xuICByZXR1cm4gZGNucGdldHRleHQoZG9tYWluLCB1bmRlZmluZWQsIHRleHQpO1xufVxuXG4vKipcbiAqIFJldHJpZXZlIHRyYW5zbGF0ZWQgc3RyaW5nIHdpdGggZ2V0dGV4dCBjb250ZXh0LlxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXIud29yZHByZXNzLm9yZy9yZWZlcmVuY2UvZnVuY3Rpb25zL194L1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSAgdGV4dCAgICBUZXh0IHRvIHRyYW5zbGF0ZS5cbiAqIEBwYXJhbSB7c3RyaW5nfSAgY29udGV4dCBDb250ZXh0IGluZm9ybWF0aW9uIGZvciB0aGUgdHJhbnNsYXRvcnMuXG4gKiBAcGFyYW0gez9zdHJpbmd9IGRvbWFpbiAgRG9tYWluIHRvIHJldHJpZXZlIHRoZSB0cmFuc2xhdGVkIHRleHQuXG4gKlxuICogQHJldHVybiB7c3RyaW5nfSBUcmFuc2xhdGVkIGNvbnRleHQgc3RyaW5nIHdpdGhvdXQgcGlwZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIF94KHRleHQsIGNvbnRleHQsIGRvbWFpbikge1xuICByZXR1cm4gZGNucGdldHRleHQoZG9tYWluLCBjb250ZXh0LCB0ZXh0KTtcbn1cblxuLyoqXG4gKiBUcmFuc2xhdGVzIGFuZCByZXRyaWV2ZXMgdGhlIHNpbmd1bGFyIG9yIHBsdXJhbCBmb3JtIGJhc2VkIG9uIHRoZSBzdXBwbGllZFxuICogbnVtYmVyLlxuICpcbiAqIEBzZWUgaHR0cHM6Ly9kZXZlbG9wZXIud29yZHByZXNzLm9yZy9yZWZlcmVuY2UvZnVuY3Rpb25zL19uL1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSAgc2luZ2xlIFRoZSB0ZXh0IHRvIGJlIHVzZWQgaWYgdGhlIG51bWJlciBpcyBzaW5ndWxhci5cbiAqIEBwYXJhbSB7c3RyaW5nfSAgcGx1cmFsIFRoZSB0ZXh0IHRvIGJlIHVzZWQgaWYgdGhlIG51bWJlciBpcyBwbHVyYWwuXG4gKiBAcGFyYW0ge251bWJlcn0gIG51bWJlciBUaGUgbnVtYmVyIHRvIGNvbXBhcmUgYWdhaW5zdCB0byB1c2UgZWl0aGVyIHRoZVxuICogICAgICAgICAgICAgICAgICAgICAgICAgc2luZ3VsYXIgb3IgcGx1cmFsIGZvcm0uXG4gKiBAcGFyYW0gez9zdHJpbmd9IGRvbWFpbiBEb21haW4gdG8gcmV0cmlldmUgdGhlIHRyYW5zbGF0ZWQgdGV4dC5cbiAqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSB0cmFuc2xhdGVkIHNpbmd1bGFyIG9yIHBsdXJhbCBmb3JtLlxuICovXG5leHBvcnQgZnVuY3Rpb24gX24oc2luZ2xlLCBwbHVyYWwsIG51bWJlciwgZG9tYWluKSB7XG4gIHJldHVybiBkY25wZ2V0dGV4dChkb21haW4sIHVuZGVmaW5lZCwgc2luZ2xlLCBwbHVyYWwsIG51bWJlcik7XG59XG5cbi8qKlxuICogVHJhbnNsYXRlcyBhbmQgcmV0cmlldmVzIHRoZSBzaW5ndWxhciBvciBwbHVyYWwgZm9ybSBiYXNlZCBvbiB0aGUgc3VwcGxpZWRcbiAqIG51bWJlciwgd2l0aCBnZXR0ZXh0IGNvbnRleHQuXG4gKlxuICogQHNlZSBodHRwczovL2RldmVsb3Blci53b3JkcHJlc3Mub3JnL3JlZmVyZW5jZS9mdW5jdGlvbnMvX254L1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSAgc2luZ2xlICBUaGUgdGV4dCB0byBiZSB1c2VkIGlmIHRoZSBudW1iZXIgaXMgc2luZ3VsYXIuXG4gKiBAcGFyYW0ge3N0cmluZ30gIHBsdXJhbCAgVGhlIHRleHQgdG8gYmUgdXNlZCBpZiB0aGUgbnVtYmVyIGlzIHBsdXJhbC5cbiAqIEBwYXJhbSB7bnVtYmVyfSAgbnVtYmVyICBUaGUgbnVtYmVyIHRvIGNvbXBhcmUgYWdhaW5zdCB0byB1c2UgZWl0aGVyIHRoZVxuICogICAgICAgICAgICAgICAgICAgICAgICAgIHNpbmd1bGFyIG9yIHBsdXJhbCBmb3JtLlxuICogQHBhcmFtIHtzdHJpbmd9ICBjb250ZXh0IENvbnRleHQgaW5mb3JtYXRpb24gZm9yIHRoZSB0cmFuc2xhdG9ycy5cbiAqIEBwYXJhbSB7P3N0cmluZ30gZG9tYWluICBEb21haW4gdG8gcmV0cmlldmUgdGhlIHRyYW5zbGF0ZWQgdGV4dC5cbiAqXG4gKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSB0cmFuc2xhdGVkIHNpbmd1bGFyIG9yIHBsdXJhbCBmb3JtLlxuICovXG5leHBvcnQgZnVuY3Rpb24gX254KHNpbmdsZSwgcGx1cmFsLCBudW1iZXIsIGNvbnRleHQsIGRvbWFpbikge1xuICByZXR1cm4gZGNucGdldHRleHQoZG9tYWluLCBjb250ZXh0LCBzaW5nbGUsIHBsdXJhbCwgbnVtYmVyKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgZm9ybWF0dGVkIHN0cmluZy4gSWYgYW4gZXJyb3Igb2NjdXJzIGluIGFwcGx5aW5nIHRoZSBmb3JtYXQsIHRoZVxuICogb3JpZ2luYWwgZm9ybWF0IHN0cmluZyBpcyByZXR1cm5lZC5cbiAqXG4gKiBAcGFyYW0ge3N0cmluZ30gICBmb3JtYXQgIFRoZSBmb3JtYXQgb2YgdGhlIHN0cmluZyB0byBnZW5lcmF0ZS5cbiAqIEBwYXJhbSB7c3RyaW5nW119IC4uLmFyZ3MgQXJndW1lbnRzIHRvIGFwcGx5IHRvIHRoZSBmb3JtYXQuXG4gKlxuICogQHNlZSBodHRwOi8vd3d3LmRpdmVpbnRvamF2YXNjcmlwdC5jb20vcHJvamVjdHMvamF2YXNjcmlwdC1zcHJpbnRmXG4gKlxuICogQHJldHVybiB7c3RyaW5nfSBUaGUgZm9ybWF0dGVkIHN0cmluZy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNwcmludGYoZm9ybWF0KSB7XG4gIHRyeSB7XG4gICAgZm9yICh2YXIgX2xlbiA9IGFyZ3VtZW50cy5sZW5ndGgsIGFyZ3MgPSBBcnJheShfbGVuID4gMSA/IF9sZW4gLSAxIDogMCksIF9rZXkgPSAxOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7XG4gICAgICBhcmdzW19rZXkgLSAxXSA9IGFyZ3VtZW50c1tfa2V5XTtcbiAgICB9XG5cbiAgICByZXR1cm4gSmVkLnNwcmludGYuYXBwbHkoSmVkLCBbZm9ybWF0XS5jb25jYXQoYXJncykpO1xuICB9IGNhdGNoIChlcnJvcikge1xuICAgIGxvZ0Vycm9yT25jZSgnSmVkIHNwcmludGYgZXJyb3I6IFxcblxcbicgKyBlcnJvci50b1N0cmluZygpKTtcblxuICAgIHJldHVybiBmb3JtYXQ7XG4gIH1cbn0iLCJtb2R1bGUuZXhwb3J0cyA9IHsgXCJkZWZhdWx0XCI6IHJlcXVpcmUoXCJjb3JlLWpzL2xpYnJhcnkvZm4vb2JqZWN0L2Fzc2lnblwiKSwgX19lc01vZHVsZTogdHJ1ZSB9OyIsInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2Lm9iamVjdC5hc3NpZ24nKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9fY29yZScpLk9iamVjdC5hc3NpZ247XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICBpZiAodHlwZW9mIGl0ICE9ICdmdW5jdGlvbicpIHRocm93IFR5cGVFcnJvcihpdCArICcgaXMgbm90IGEgZnVuY3Rpb24hJyk7XG4gIHJldHVybiBpdDtcbn07XG4iLCJ2YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuL19pcy1vYmplY3QnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7XG4gIGlmICghaXNPYmplY3QoaXQpKSB0aHJvdyBUeXBlRXJyb3IoaXQgKyAnIGlzIG5vdCBhbiBvYmplY3QhJyk7XG4gIHJldHVybiBpdDtcbn07XG4iLCIvLyBmYWxzZSAtPiBBcnJheSNpbmRleE9mXG4vLyB0cnVlICAtPiBBcnJheSNpbmNsdWRlc1xudmFyIHRvSU9iamVjdCA9IHJlcXVpcmUoJy4vX3RvLWlvYmplY3QnKTtcbnZhciB0b0xlbmd0aCA9IHJlcXVpcmUoJy4vX3RvLWxlbmd0aCcpO1xudmFyIHRvQWJzb2x1dGVJbmRleCA9IHJlcXVpcmUoJy4vX3RvLWFic29sdXRlLWluZGV4Jyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChJU19JTkNMVURFUykge1xuICByZXR1cm4gZnVuY3Rpb24gKCR0aGlzLCBlbCwgZnJvbUluZGV4KSB7XG4gICAgdmFyIE8gPSB0b0lPYmplY3QoJHRoaXMpO1xuICAgIHZhciBsZW5ndGggPSB0b0xlbmd0aChPLmxlbmd0aCk7XG4gICAgdmFyIGluZGV4ID0gdG9BYnNvbHV0ZUluZGV4KGZyb21JbmRleCwgbGVuZ3RoKTtcbiAgICB2YXIgdmFsdWU7XG4gICAgLy8gQXJyYXkjaW5jbHVkZXMgdXNlcyBTYW1lVmFsdWVaZXJvIGVxdWFsaXR5IGFsZ29yaXRobVxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1zZWxmLWNvbXBhcmVcbiAgICBpZiAoSVNfSU5DTFVERVMgJiYgZWwgIT0gZWwpIHdoaWxlIChsZW5ndGggPiBpbmRleCkge1xuICAgICAgdmFsdWUgPSBPW2luZGV4KytdO1xuICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXNlbGYtY29tcGFyZVxuICAgICAgaWYgKHZhbHVlICE9IHZhbHVlKSByZXR1cm4gdHJ1ZTtcbiAgICAvLyBBcnJheSNpbmRleE9mIGlnbm9yZXMgaG9sZXMsIEFycmF5I2luY2x1ZGVzIC0gbm90XG4gICAgfSBlbHNlIGZvciAoO2xlbmd0aCA+IGluZGV4OyBpbmRleCsrKSBpZiAoSVNfSU5DTFVERVMgfHwgaW5kZXggaW4gTykge1xuICAgICAgaWYgKE9baW5kZXhdID09PSBlbCkgcmV0dXJuIElTX0lOQ0xVREVTIHx8IGluZGV4IHx8IDA7XG4gICAgfSByZXR1cm4gIUlTX0lOQ0xVREVTICYmIC0xO1xuICB9O1xufTtcbiIsInZhciB0b1N0cmluZyA9IHt9LnRvU3RyaW5nO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gdG9TdHJpbmcuY2FsbChpdCkuc2xpY2UoOCwgLTEpO1xufTtcbiIsInZhciBjb3JlID0gbW9kdWxlLmV4cG9ydHMgPSB7IHZlcnNpb246ICcyLjUuNScgfTtcbmlmICh0eXBlb2YgX19lID09ICdudW1iZXInKSBfX2UgPSBjb3JlOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG4iLCIvLyBvcHRpb25hbCAvIHNpbXBsZSBjb250ZXh0IGJpbmRpbmdcbnZhciBhRnVuY3Rpb24gPSByZXF1aXJlKCcuL19hLWZ1bmN0aW9uJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChmbiwgdGhhdCwgbGVuZ3RoKSB7XG4gIGFGdW5jdGlvbihmbik7XG4gIGlmICh0aGF0ID09PSB1bmRlZmluZWQpIHJldHVybiBmbjtcbiAgc3dpdGNoIChsZW5ndGgpIHtcbiAgICBjYXNlIDE6IHJldHVybiBmdW5jdGlvbiAoYSkge1xuICAgICAgcmV0dXJuIGZuLmNhbGwodGhhdCwgYSk7XG4gICAgfTtcbiAgICBjYXNlIDI6IHJldHVybiBmdW5jdGlvbiAoYSwgYikge1xuICAgICAgcmV0dXJuIGZuLmNhbGwodGhhdCwgYSwgYik7XG4gICAgfTtcbiAgICBjYXNlIDM6IHJldHVybiBmdW5jdGlvbiAoYSwgYiwgYykge1xuICAgICAgcmV0dXJuIGZuLmNhbGwodGhhdCwgYSwgYiwgYyk7XG4gICAgfTtcbiAgfVxuICByZXR1cm4gZnVuY3Rpb24gKC8qIC4uLmFyZ3MgKi8pIHtcbiAgICByZXR1cm4gZm4uYXBwbHkodGhhdCwgYXJndW1lbnRzKTtcbiAgfTtcbn07XG4iLCIvLyA3LjIuMSBSZXF1aXJlT2JqZWN0Q29lcmNpYmxlKGFyZ3VtZW50KVxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgaWYgKGl0ID09IHVuZGVmaW5lZCkgdGhyb3cgVHlwZUVycm9yKFwiQ2FuJ3QgY2FsbCBtZXRob2Qgb24gIFwiICsgaXQpO1xuICByZXR1cm4gaXQ7XG59O1xuIiwiLy8gVGhhbmsncyBJRTggZm9yIGhpcyBmdW5ueSBkZWZpbmVQcm9wZXJ0eVxubW9kdWxlLmV4cG9ydHMgPSAhcmVxdWlyZSgnLi9fZmFpbHMnKShmdW5jdGlvbiAoKSB7XG4gIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkoe30sICdhJywgeyBnZXQ6IGZ1bmN0aW9uICgpIHsgcmV0dXJuIDc7IH0gfSkuYSAhPSA3O1xufSk7XG4iLCJ2YXIgaXNPYmplY3QgPSByZXF1aXJlKCcuL19pcy1vYmplY3QnKTtcbnZhciBkb2N1bWVudCA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpLmRvY3VtZW50O1xuLy8gdHlwZW9mIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQgaXMgJ29iamVjdCcgaW4gb2xkIElFXG52YXIgaXMgPSBpc09iamVjdChkb2N1bWVudCkgJiYgaXNPYmplY3QoZG9jdW1lbnQuY3JlYXRlRWxlbWVudCk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gaXMgPyBkb2N1bWVudC5jcmVhdGVFbGVtZW50KGl0KSA6IHt9O1xufTtcbiIsIi8vIElFIDgtIGRvbid0IGVudW0gYnVnIGtleXNcbm1vZHVsZS5leHBvcnRzID0gKFxuICAnY29uc3RydWN0b3IsaGFzT3duUHJvcGVydHksaXNQcm90b3R5cGVPZixwcm9wZXJ0eUlzRW51bWVyYWJsZSx0b0xvY2FsZVN0cmluZyx0b1N0cmluZyx2YWx1ZU9mJ1xuKS5zcGxpdCgnLCcpO1xuIiwidmFyIGdsb2JhbCA9IHJlcXVpcmUoJy4vX2dsb2JhbCcpO1xudmFyIGNvcmUgPSByZXF1aXJlKCcuL19jb3JlJyk7XG52YXIgY3R4ID0gcmVxdWlyZSgnLi9fY3R4Jyk7XG52YXIgaGlkZSA9IHJlcXVpcmUoJy4vX2hpZGUnKTtcbnZhciBoYXMgPSByZXF1aXJlKCcuL19oYXMnKTtcbnZhciBQUk9UT1RZUEUgPSAncHJvdG90eXBlJztcblxudmFyICRleHBvcnQgPSBmdW5jdGlvbiAodHlwZSwgbmFtZSwgc291cmNlKSB7XG4gIHZhciBJU19GT1JDRUQgPSB0eXBlICYgJGV4cG9ydC5GO1xuICB2YXIgSVNfR0xPQkFMID0gdHlwZSAmICRleHBvcnQuRztcbiAgdmFyIElTX1NUQVRJQyA9IHR5cGUgJiAkZXhwb3J0LlM7XG4gIHZhciBJU19QUk9UTyA9IHR5cGUgJiAkZXhwb3J0LlA7XG4gIHZhciBJU19CSU5EID0gdHlwZSAmICRleHBvcnQuQjtcbiAgdmFyIElTX1dSQVAgPSB0eXBlICYgJGV4cG9ydC5XO1xuICB2YXIgZXhwb3J0cyA9IElTX0dMT0JBTCA/IGNvcmUgOiBjb3JlW25hbWVdIHx8IChjb3JlW25hbWVdID0ge30pO1xuICB2YXIgZXhwUHJvdG8gPSBleHBvcnRzW1BST1RPVFlQRV07XG4gIHZhciB0YXJnZXQgPSBJU19HTE9CQUwgPyBnbG9iYWwgOiBJU19TVEFUSUMgPyBnbG9iYWxbbmFtZV0gOiAoZ2xvYmFsW25hbWVdIHx8IHt9KVtQUk9UT1RZUEVdO1xuICB2YXIga2V5LCBvd24sIG91dDtcbiAgaWYgKElTX0dMT0JBTCkgc291cmNlID0gbmFtZTtcbiAgZm9yIChrZXkgaW4gc291cmNlKSB7XG4gICAgLy8gY29udGFpbnMgaW4gbmF0aXZlXG4gICAgb3duID0gIUlTX0ZPUkNFRCAmJiB0YXJnZXQgJiYgdGFyZ2V0W2tleV0gIT09IHVuZGVmaW5lZDtcbiAgICBpZiAob3duICYmIGhhcyhleHBvcnRzLCBrZXkpKSBjb250aW51ZTtcbiAgICAvLyBleHBvcnQgbmF0aXZlIG9yIHBhc3NlZFxuICAgIG91dCA9IG93biA/IHRhcmdldFtrZXldIDogc291cmNlW2tleV07XG4gICAgLy8gcHJldmVudCBnbG9iYWwgcG9sbHV0aW9uIGZvciBuYW1lc3BhY2VzXG4gICAgZXhwb3J0c1trZXldID0gSVNfR0xPQkFMICYmIHR5cGVvZiB0YXJnZXRba2V5XSAhPSAnZnVuY3Rpb24nID8gc291cmNlW2tleV1cbiAgICAvLyBiaW5kIHRpbWVycyB0byBnbG9iYWwgZm9yIGNhbGwgZnJvbSBleHBvcnQgY29udGV4dFxuICAgIDogSVNfQklORCAmJiBvd24gPyBjdHgob3V0LCBnbG9iYWwpXG4gICAgLy8gd3JhcCBnbG9iYWwgY29uc3RydWN0b3JzIGZvciBwcmV2ZW50IGNoYW5nZSB0aGVtIGluIGxpYnJhcnlcbiAgICA6IElTX1dSQVAgJiYgdGFyZ2V0W2tleV0gPT0gb3V0ID8gKGZ1bmN0aW9uIChDKSB7XG4gICAgICB2YXIgRiA9IGZ1bmN0aW9uIChhLCBiLCBjKSB7XG4gICAgICAgIGlmICh0aGlzIGluc3RhbmNlb2YgQykge1xuICAgICAgICAgIHN3aXRjaCAoYXJndW1lbnRzLmxlbmd0aCkge1xuICAgICAgICAgICAgY2FzZSAwOiByZXR1cm4gbmV3IEMoKTtcbiAgICAgICAgICAgIGNhc2UgMTogcmV0dXJuIG5ldyBDKGEpO1xuICAgICAgICAgICAgY2FzZSAyOiByZXR1cm4gbmV3IEMoYSwgYik7XG4gICAgICAgICAgfSByZXR1cm4gbmV3IEMoYSwgYiwgYyk7XG4gICAgICAgIH0gcmV0dXJuIEMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICAgIH07XG4gICAgICBGW1BST1RPVFlQRV0gPSBDW1BST1RPVFlQRV07XG4gICAgICByZXR1cm4gRjtcbiAgICAvLyBtYWtlIHN0YXRpYyB2ZXJzaW9ucyBmb3IgcHJvdG90eXBlIG1ldGhvZHNcbiAgICB9KShvdXQpIDogSVNfUFJPVE8gJiYgdHlwZW9mIG91dCA9PSAnZnVuY3Rpb24nID8gY3R4KEZ1bmN0aW9uLmNhbGwsIG91dCkgOiBvdXQ7XG4gICAgLy8gZXhwb3J0IHByb3RvIG1ldGhvZHMgdG8gY29yZS4lQ09OU1RSVUNUT1IlLm1ldGhvZHMuJU5BTUUlXG4gICAgaWYgKElTX1BST1RPKSB7XG4gICAgICAoZXhwb3J0cy52aXJ0dWFsIHx8IChleHBvcnRzLnZpcnR1YWwgPSB7fSkpW2tleV0gPSBvdXQ7XG4gICAgICAvLyBleHBvcnQgcHJvdG8gbWV0aG9kcyB0byBjb3JlLiVDT05TVFJVQ1RPUiUucHJvdG90eXBlLiVOQU1FJVxuICAgICAgaWYgKHR5cGUgJiAkZXhwb3J0LlIgJiYgZXhwUHJvdG8gJiYgIWV4cFByb3RvW2tleV0pIGhpZGUoZXhwUHJvdG8sIGtleSwgb3V0KTtcbiAgICB9XG4gIH1cbn07XG4vLyB0eXBlIGJpdG1hcFxuJGV4cG9ydC5GID0gMTsgICAvLyBmb3JjZWRcbiRleHBvcnQuRyA9IDI7ICAgLy8gZ2xvYmFsXG4kZXhwb3J0LlMgPSA0OyAgIC8vIHN0YXRpY1xuJGV4cG9ydC5QID0gODsgICAvLyBwcm90b1xuJGV4cG9ydC5CID0gMTY7ICAvLyBiaW5kXG4kZXhwb3J0LlcgPSAzMjsgIC8vIHdyYXBcbiRleHBvcnQuVSA9IDY0OyAgLy8gc2FmZVxuJGV4cG9ydC5SID0gMTI4OyAvLyByZWFsIHByb3RvIG1ldGhvZCBmb3IgYGxpYnJhcnlgXG5tb2R1bGUuZXhwb3J0cyA9ICRleHBvcnQ7XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChleGVjKSB7XG4gIHRyeSB7XG4gICAgcmV0dXJuICEhZXhlYygpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbn07XG4iLCIvLyBodHRwczovL2dpdGh1Yi5jb20vemxvaXJvY2svY29yZS1qcy9pc3N1ZXMvODYjaXNzdWVjb21tZW50LTExNTc1OTAyOFxudmFyIGdsb2JhbCA9IG1vZHVsZS5leHBvcnRzID0gdHlwZW9mIHdpbmRvdyAhPSAndW5kZWZpbmVkJyAmJiB3aW5kb3cuTWF0aCA9PSBNYXRoXG4gID8gd2luZG93IDogdHlwZW9mIHNlbGYgIT0gJ3VuZGVmaW5lZCcgJiYgc2VsZi5NYXRoID09IE1hdGggPyBzZWxmXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby1uZXctZnVuY1xuICA6IEZ1bmN0aW9uKCdyZXR1cm4gdGhpcycpKCk7XG5pZiAodHlwZW9mIF9fZyA9PSAnbnVtYmVyJykgX19nID0gZ2xvYmFsOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVuZGVmXG4iLCJ2YXIgaGFzT3duUHJvcGVydHkgPSB7fS5oYXNPd25Qcm9wZXJ0eTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0LCBrZXkpIHtcbiAgcmV0dXJuIGhhc093blByb3BlcnR5LmNhbGwoaXQsIGtleSk7XG59O1xuIiwidmFyIGRQID0gcmVxdWlyZSgnLi9fb2JqZWN0LWRwJyk7XG52YXIgY3JlYXRlRGVzYyA9IHJlcXVpcmUoJy4vX3Byb3BlcnR5LWRlc2MnKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9fZGVzY3JpcHRvcnMnKSA/IGZ1bmN0aW9uIChvYmplY3QsIGtleSwgdmFsdWUpIHtcbiAgcmV0dXJuIGRQLmYob2JqZWN0LCBrZXksIGNyZWF0ZURlc2MoMSwgdmFsdWUpKTtcbn0gOiBmdW5jdGlvbiAob2JqZWN0LCBrZXksIHZhbHVlKSB7XG4gIG9iamVjdFtrZXldID0gdmFsdWU7XG4gIHJldHVybiBvYmplY3Q7XG59O1xuIiwibW9kdWxlLmV4cG9ydHMgPSAhcmVxdWlyZSgnLi9fZGVzY3JpcHRvcnMnKSAmJiAhcmVxdWlyZSgnLi9fZmFpbHMnKShmdW5jdGlvbiAoKSB7XG4gIHJldHVybiBPYmplY3QuZGVmaW5lUHJvcGVydHkocmVxdWlyZSgnLi9fZG9tLWNyZWF0ZScpKCdkaXYnKSwgJ2EnLCB7IGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gNzsgfSB9KS5hICE9IDc7XG59KTtcbiIsIi8vIGZhbGxiYWNrIGZvciBub24tYXJyYXktbGlrZSBFUzMgYW5kIG5vbi1lbnVtZXJhYmxlIG9sZCBWOCBzdHJpbmdzXG52YXIgY29mID0gcmVxdWlyZSgnLi9fY29mJyk7XG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tcHJvdG90eXBlLWJ1aWx0aW5zXG5tb2R1bGUuZXhwb3J0cyA9IE9iamVjdCgneicpLnByb3BlcnR5SXNFbnVtZXJhYmxlKDApID8gT2JqZWN0IDogZnVuY3Rpb24gKGl0KSB7XG4gIHJldHVybiBjb2YoaXQpID09ICdTdHJpbmcnID8gaXQuc3BsaXQoJycpIDogT2JqZWN0KGl0KTtcbn07XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gdHlwZW9mIGl0ID09PSAnb2JqZWN0JyA/IGl0ICE9PSBudWxsIDogdHlwZW9mIGl0ID09PSAnZnVuY3Rpb24nO1xufTtcbiIsIid1c2Ugc3RyaWN0Jztcbi8vIDE5LjEuMi4xIE9iamVjdC5hc3NpZ24odGFyZ2V0LCBzb3VyY2UsIC4uLilcbnZhciBnZXRLZXlzID0gcmVxdWlyZSgnLi9fb2JqZWN0LWtleXMnKTtcbnZhciBnT1BTID0gcmVxdWlyZSgnLi9fb2JqZWN0LWdvcHMnKTtcbnZhciBwSUUgPSByZXF1aXJlKCcuL19vYmplY3QtcGllJyk7XG52YXIgdG9PYmplY3QgPSByZXF1aXJlKCcuL190by1vYmplY3QnKTtcbnZhciBJT2JqZWN0ID0gcmVxdWlyZSgnLi9faW9iamVjdCcpO1xudmFyICRhc3NpZ24gPSBPYmplY3QuYXNzaWduO1xuXG4vLyBzaG91bGQgd29yayB3aXRoIHN5bWJvbHMgYW5kIHNob3VsZCBoYXZlIGRldGVybWluaXN0aWMgcHJvcGVydHkgb3JkZXIgKFY4IGJ1Zylcbm1vZHVsZS5leHBvcnRzID0gISRhc3NpZ24gfHwgcmVxdWlyZSgnLi9fZmFpbHMnKShmdW5jdGlvbiAoKSB7XG4gIHZhciBBID0ge307XG4gIHZhciBCID0ge307XG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby11bmRlZlxuICB2YXIgUyA9IFN5bWJvbCgpO1xuICB2YXIgSyA9ICdhYmNkZWZnaGlqa2xtbm9wcXJzdCc7XG4gIEFbU10gPSA3O1xuICBLLnNwbGl0KCcnKS5mb3JFYWNoKGZ1bmN0aW9uIChrKSB7IEJba10gPSBrOyB9KTtcbiAgcmV0dXJuICRhc3NpZ24oe30sIEEpW1NdICE9IDcgfHwgT2JqZWN0LmtleXMoJGFzc2lnbih7fSwgQikpLmpvaW4oJycpICE9IEs7XG59KSA/IGZ1bmN0aW9uIGFzc2lnbih0YXJnZXQsIHNvdXJjZSkgeyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIG5vLXVudXNlZC12YXJzXG4gIHZhciBUID0gdG9PYmplY3QodGFyZ2V0KTtcbiAgdmFyIGFMZW4gPSBhcmd1bWVudHMubGVuZ3RoO1xuICB2YXIgaW5kZXggPSAxO1xuICB2YXIgZ2V0U3ltYm9scyA9IGdPUFMuZjtcbiAgdmFyIGlzRW51bSA9IHBJRS5mO1xuICB3aGlsZSAoYUxlbiA+IGluZGV4KSB7XG4gICAgdmFyIFMgPSBJT2JqZWN0KGFyZ3VtZW50c1tpbmRleCsrXSk7XG4gICAgdmFyIGtleXMgPSBnZXRTeW1ib2xzID8gZ2V0S2V5cyhTKS5jb25jYXQoZ2V0U3ltYm9scyhTKSkgOiBnZXRLZXlzKFMpO1xuICAgIHZhciBsZW5ndGggPSBrZXlzLmxlbmd0aDtcbiAgICB2YXIgaiA9IDA7XG4gICAgdmFyIGtleTtcbiAgICB3aGlsZSAobGVuZ3RoID4gaikgaWYgKGlzRW51bS5jYWxsKFMsIGtleSA9IGtleXNbaisrXSkpIFRba2V5XSA9IFNba2V5XTtcbiAgfSByZXR1cm4gVDtcbn0gOiAkYXNzaWduO1xuIiwidmFyIGFuT2JqZWN0ID0gcmVxdWlyZSgnLi9fYW4tb2JqZWN0Jyk7XG52YXIgSUU4X0RPTV9ERUZJTkUgPSByZXF1aXJlKCcuL19pZTgtZG9tLWRlZmluZScpO1xudmFyIHRvUHJpbWl0aXZlID0gcmVxdWlyZSgnLi9fdG8tcHJpbWl0aXZlJyk7XG52YXIgZFAgPSBPYmplY3QuZGVmaW5lUHJvcGVydHk7XG5cbmV4cG9ydHMuZiA9IHJlcXVpcmUoJy4vX2Rlc2NyaXB0b3JzJykgPyBPYmplY3QuZGVmaW5lUHJvcGVydHkgOiBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0eShPLCBQLCBBdHRyaWJ1dGVzKSB7XG4gIGFuT2JqZWN0KE8pO1xuICBQID0gdG9QcmltaXRpdmUoUCwgdHJ1ZSk7XG4gIGFuT2JqZWN0KEF0dHJpYnV0ZXMpO1xuICBpZiAoSUU4X0RPTV9ERUZJTkUpIHRyeSB7XG4gICAgcmV0dXJuIGRQKE8sIFAsIEF0dHJpYnV0ZXMpO1xuICB9IGNhdGNoIChlKSB7IC8qIGVtcHR5ICovIH1cbiAgaWYgKCdnZXQnIGluIEF0dHJpYnV0ZXMgfHwgJ3NldCcgaW4gQXR0cmlidXRlcykgdGhyb3cgVHlwZUVycm9yKCdBY2Nlc3NvcnMgbm90IHN1cHBvcnRlZCEnKTtcbiAgaWYgKCd2YWx1ZScgaW4gQXR0cmlidXRlcykgT1tQXSA9IEF0dHJpYnV0ZXMudmFsdWU7XG4gIHJldHVybiBPO1xufTtcbiIsImV4cG9ydHMuZiA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHM7XG4iLCJ2YXIgaGFzID0gcmVxdWlyZSgnLi9faGFzJyk7XG52YXIgdG9JT2JqZWN0ID0gcmVxdWlyZSgnLi9fdG8taW9iamVjdCcpO1xudmFyIGFycmF5SW5kZXhPZiA9IHJlcXVpcmUoJy4vX2FycmF5LWluY2x1ZGVzJykoZmFsc2UpO1xudmFyIElFX1BST1RPID0gcmVxdWlyZSgnLi9fc2hhcmVkLWtleScpKCdJRV9QUk9UTycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvYmplY3QsIG5hbWVzKSB7XG4gIHZhciBPID0gdG9JT2JqZWN0KG9iamVjdCk7XG4gIHZhciBpID0gMDtcbiAgdmFyIHJlc3VsdCA9IFtdO1xuICB2YXIga2V5O1xuICBmb3IgKGtleSBpbiBPKSBpZiAoa2V5ICE9IElFX1BST1RPKSBoYXMoTywga2V5KSAmJiByZXN1bHQucHVzaChrZXkpO1xuICAvLyBEb24ndCBlbnVtIGJ1ZyAmIGhpZGRlbiBrZXlzXG4gIHdoaWxlIChuYW1lcy5sZW5ndGggPiBpKSBpZiAoaGFzKE8sIGtleSA9IG5hbWVzW2krK10pKSB7XG4gICAgfmFycmF5SW5kZXhPZihyZXN1bHQsIGtleSkgfHwgcmVzdWx0LnB1c2goa2V5KTtcbiAgfVxuICByZXR1cm4gcmVzdWx0O1xufTtcbiIsIi8vIDE5LjEuMi4xNCAvIDE1LjIuMy4xNCBPYmplY3Qua2V5cyhPKVxudmFyICRrZXlzID0gcmVxdWlyZSgnLi9fb2JqZWN0LWtleXMtaW50ZXJuYWwnKTtcbnZhciBlbnVtQnVnS2V5cyA9IHJlcXVpcmUoJy4vX2VudW0tYnVnLWtleXMnKTtcblxubW9kdWxlLmV4cG9ydHMgPSBPYmplY3Qua2V5cyB8fCBmdW5jdGlvbiBrZXlzKE8pIHtcbiAgcmV0dXJuICRrZXlzKE8sIGVudW1CdWdLZXlzKTtcbn07XG4iLCJleHBvcnRzLmYgPSB7fS5wcm9wZXJ0eUlzRW51bWVyYWJsZTtcbiIsIm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGJpdG1hcCwgdmFsdWUpIHtcbiAgcmV0dXJuIHtcbiAgICBlbnVtZXJhYmxlOiAhKGJpdG1hcCAmIDEpLFxuICAgIGNvbmZpZ3VyYWJsZTogIShiaXRtYXAgJiAyKSxcbiAgICB3cml0YWJsZTogIShiaXRtYXAgJiA0KSxcbiAgICB2YWx1ZTogdmFsdWVcbiAgfTtcbn07XG4iLCJ2YXIgc2hhcmVkID0gcmVxdWlyZSgnLi9fc2hhcmVkJykoJ2tleXMnKTtcbnZhciB1aWQgPSByZXF1aXJlKCcuL191aWQnKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGtleSkge1xuICByZXR1cm4gc2hhcmVkW2tleV0gfHwgKHNoYXJlZFtrZXldID0gdWlkKGtleSkpO1xufTtcbiIsInZhciBnbG9iYWwgPSByZXF1aXJlKCcuL19nbG9iYWwnKTtcbnZhciBTSEFSRUQgPSAnX19jb3JlLWpzX3NoYXJlZF9fJztcbnZhciBzdG9yZSA9IGdsb2JhbFtTSEFSRURdIHx8IChnbG9iYWxbU0hBUkVEXSA9IHt9KTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGtleSkge1xuICByZXR1cm4gc3RvcmVba2V5XSB8fCAoc3RvcmVba2V5XSA9IHt9KTtcbn07XG4iLCJ2YXIgdG9JbnRlZ2VyID0gcmVxdWlyZSgnLi9fdG8taW50ZWdlcicpO1xudmFyIG1heCA9IE1hdGgubWF4O1xudmFyIG1pbiA9IE1hdGgubWluO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaW5kZXgsIGxlbmd0aCkge1xuICBpbmRleCA9IHRvSW50ZWdlcihpbmRleCk7XG4gIHJldHVybiBpbmRleCA8IDAgPyBtYXgoaW5kZXggKyBsZW5ndGgsIDApIDogbWluKGluZGV4LCBsZW5ndGgpO1xufTtcbiIsIi8vIDcuMS40IFRvSW50ZWdlclxudmFyIGNlaWwgPSBNYXRoLmNlaWw7XG52YXIgZmxvb3IgPSBNYXRoLmZsb29yO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuIGlzTmFOKGl0ID0gK2l0KSA/IDAgOiAoaXQgPiAwID8gZmxvb3IgOiBjZWlsKShpdCk7XG59O1xuIiwiLy8gdG8gaW5kZXhlZCBvYmplY3QsIHRvT2JqZWN0IHdpdGggZmFsbGJhY2sgZm9yIG5vbi1hcnJheS1saWtlIEVTMyBzdHJpbmdzXG52YXIgSU9iamVjdCA9IHJlcXVpcmUoJy4vX2lvYmplY3QnKTtcbnZhciBkZWZpbmVkID0gcmVxdWlyZSgnLi9fZGVmaW5lZCcpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoaXQpIHtcbiAgcmV0dXJuIElPYmplY3QoZGVmaW5lZChpdCkpO1xufTtcbiIsIi8vIDcuMS4xNSBUb0xlbmd0aFxudmFyIHRvSW50ZWdlciA9IHJlcXVpcmUoJy4vX3RvLWludGVnZXInKTtcbnZhciBtaW4gPSBNYXRoLm1pbjtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGl0KSB7XG4gIHJldHVybiBpdCA+IDAgPyBtaW4odG9JbnRlZ2VyKGl0KSwgMHgxZmZmZmZmZmZmZmZmZikgOiAwOyAvLyBwb3coMiwgNTMpIC0gMSA9PSA5MDA3MTk5MjU0NzQwOTkxXG59O1xuIiwiLy8gNy4xLjEzIFRvT2JqZWN0KGFyZ3VtZW50KVxudmFyIGRlZmluZWQgPSByZXF1aXJlKCcuL19kZWZpbmVkJyk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICByZXR1cm4gT2JqZWN0KGRlZmluZWQoaXQpKTtcbn07XG4iLCIvLyA3LjEuMSBUb1ByaW1pdGl2ZShpbnB1dCBbLCBQcmVmZXJyZWRUeXBlXSlcbnZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpO1xuLy8gaW5zdGVhZCBvZiB0aGUgRVM2IHNwZWMgdmVyc2lvbiwgd2UgZGlkbid0IGltcGxlbWVudCBAQHRvUHJpbWl0aXZlIGNhc2Vcbi8vIGFuZCB0aGUgc2Vjb25kIGFyZ3VtZW50IC0gZmxhZyAtIHByZWZlcnJlZCB0eXBlIGlzIGEgc3RyaW5nXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCwgUykge1xuICBpZiAoIWlzT2JqZWN0KGl0KSkgcmV0dXJuIGl0O1xuICB2YXIgZm4sIHZhbDtcbiAgaWYgKFMgJiYgdHlwZW9mIChmbiA9IGl0LnRvU3RyaW5nKSA9PSAnZnVuY3Rpb24nICYmICFpc09iamVjdCh2YWwgPSBmbi5jYWxsKGl0KSkpIHJldHVybiB2YWw7XG4gIGlmICh0eXBlb2YgKGZuID0gaXQudmFsdWVPZikgPT0gJ2Z1bmN0aW9uJyAmJiAhaXNPYmplY3QodmFsID0gZm4uY2FsbChpdCkpKSByZXR1cm4gdmFsO1xuICBpZiAoIVMgJiYgdHlwZW9mIChmbiA9IGl0LnRvU3RyaW5nKSA9PSAnZnVuY3Rpb24nICYmICFpc09iamVjdCh2YWwgPSBmbi5jYWxsKGl0KSkpIHJldHVybiB2YWw7XG4gIHRocm93IFR5cGVFcnJvcihcIkNhbid0IGNvbnZlcnQgb2JqZWN0IHRvIHByaW1pdGl2ZSB2YWx1ZVwiKTtcbn07XG4iLCJ2YXIgaWQgPSAwO1xudmFyIHB4ID0gTWF0aC5yYW5kb20oKTtcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGtleSkge1xuICByZXR1cm4gJ1N5bWJvbCgnLmNvbmNhdChrZXkgPT09IHVuZGVmaW5lZCA/ICcnIDoga2V5LCAnKV8nLCAoKytpZCArIHB4KS50b1N0cmluZygzNikpO1xufTtcbiIsIi8vIDE5LjEuMy4xIE9iamVjdC5hc3NpZ24odGFyZ2V0LCBzb3VyY2UpXG52YXIgJGV4cG9ydCA9IHJlcXVpcmUoJy4vX2V4cG9ydCcpO1xuXG4kZXhwb3J0KCRleHBvcnQuUyArICRleHBvcnQuRiwgJ09iamVjdCcsIHsgYXNzaWduOiByZXF1aXJlKCcuL19vYmplY3QtYXNzaWduJykgfSk7XG4iLCIvKipcbiAqIEBwcmVzZXJ2ZSBqZWQuanMgaHR0cHM6Ly9naXRodWIuY29tL1NsZXhBeHRvbi9KZWRcbiAqL1xuLypcbi0tLS0tLS0tLS0tXG5BIGdldHRleHQgY29tcGF0aWJsZSBpMThuIGxpYnJhcnkgZm9yIG1vZGVybiBKYXZhU2NyaXB0IEFwcGxpY2F0aW9uc1xuXG5ieSBBbGV4IFNleHRvbiAtIEFsZXhTZXh0b24gW2F0XSBnbWFpbCAtIEBTbGV4QXh0b25cblxuTUlUIExpY2Vuc2VcblxuQSBqUXVlcnkgRm91bmRhdGlvbiBwcm9qZWN0IC0gcmVxdWlyZXMgQ0xBIHRvIGNvbnRyaWJ1dGUgLVxuaHR0cHM6Ly9jb250cmlidXRlLmpxdWVyeS5vcmcvQ0xBL1xuXG5cblxuSmVkIG9mZmVycyB0aGUgZW50aXJlIGFwcGxpY2FibGUgR05VIGdldHRleHQgc3BlYydkIHNldCBvZlxuZnVuY3Rpb25zLCBidXQgYWxzbyBvZmZlcnMgc29tZSBuaWNlciB3cmFwcGVycyBhcm91bmQgdGhlbS5cblRoZSBhcGkgZm9yIGdldHRleHQgd2FzIHdyaXR0ZW4gZm9yIGEgbGFuZ3VhZ2Ugd2l0aCBubyBmdW5jdGlvblxub3ZlcmxvYWRpbmcsIHNvIEplZCBhbGxvd3MgYSBsaXR0bGUgbW9yZSBvZiB0aGF0LlxuXG5NYW55IHRoYW5rcyB0byBKb3NodWEgSS4gTWlsbGVyIC0gdW5ydHN0QGNwYW4ub3JnIC0gd2hvIHdyb3RlXG5nZXR0ZXh0LmpzIGJhY2sgaW4gMjAwOC4gSSB3YXMgYWJsZSB0byB2ZXQgYSBsb3Qgb2YgbXkgaWRlYXNcbmFnYWluc3QgaGlzLiBJIGFsc28gbWFkZSBzdXJlIEplZCBwYXNzZWQgYWdhaW5zdCBoaXMgdGVzdHNcbmluIG9yZGVyIHRvIG9mZmVyIGVhc3kgdXBncmFkZXMgLS0ganNnZXR0ZXh0LmJlcmxpb3MuZGVcbiovXG4oZnVuY3Rpb24gKHJvb3QsIHVuZGVmKSB7XG5cbiAgLy8gU2V0IHVwIHNvbWUgdW5kZXJzY29yZS1zdHlsZSBmdW5jdGlvbnMsIGlmIHlvdSBhbHJlYWR5IGhhdmVcbiAgLy8gdW5kZXJzY29yZSwgZmVlbCBmcmVlIHRvIGRlbGV0ZSB0aGlzIHNlY3Rpb24sIGFuZCB1c2UgaXRcbiAgLy8gZGlyZWN0bHksIGhvd2V2ZXIsIHRoZSBhbW91bnQgb2YgZnVuY3Rpb25zIHVzZWQgZG9lc24ndFxuICAvLyB3YXJyYW50IGhhdmluZyB1bmRlcnNjb3JlIGFzIGEgZnVsbCBkZXBlbmRlbmN5LlxuICAvLyBVbmRlcnNjb3JlIDEuMy4wIHdhcyB1c2VkIHRvIHBvcnQgYW5kIGlzIGxpY2Vuc2VkXG4gIC8vIHVuZGVyIHRoZSBNSVQgTGljZW5zZSBieSBKZXJlbXkgQXNoa2VuYXMuXG4gIHZhciBBcnJheVByb3RvICAgID0gQXJyYXkucHJvdG90eXBlLFxuICAgICAgT2JqUHJvdG8gICAgICA9IE9iamVjdC5wcm90b3R5cGUsXG4gICAgICBzbGljZSAgICAgICAgID0gQXJyYXlQcm90by5zbGljZSxcbiAgICAgIGhhc093blByb3AgICAgPSBPYmpQcm90by5oYXNPd25Qcm9wZXJ0eSxcbiAgICAgIG5hdGl2ZUZvckVhY2ggPSBBcnJheVByb3RvLmZvckVhY2gsXG4gICAgICBicmVha2VyICAgICAgID0ge307XG5cbiAgLy8gV2UncmUgbm90IHVzaW5nIHRoZSBPT1Agc3R5bGUgXyBzbyB3ZSBkb24ndCBuZWVkIHRoZVxuICAvLyBleHRyYSBsZXZlbCBvZiBpbmRpcmVjdGlvbi4gVGhpcyBzdGlsbCBtZWFucyB0aGF0IHlvdVxuICAvLyBzdWIgb3V0IGZvciByZWFsIGBfYCB0aG91Z2guXG4gIHZhciBfID0ge1xuICAgIGZvckVhY2ggOiBmdW5jdGlvbiggb2JqLCBpdGVyYXRvciwgY29udGV4dCApIHtcbiAgICAgIHZhciBpLCBsLCBrZXk7XG4gICAgICBpZiAoIG9iaiA9PT0gbnVsbCApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoIG5hdGl2ZUZvckVhY2ggJiYgb2JqLmZvckVhY2ggPT09IG5hdGl2ZUZvckVhY2ggKSB7XG4gICAgICAgIG9iai5mb3JFYWNoKCBpdGVyYXRvciwgY29udGV4dCApO1xuICAgICAgfVxuICAgICAgZWxzZSBpZiAoIG9iai5sZW5ndGggPT09ICtvYmoubGVuZ3RoICkge1xuICAgICAgICBmb3IgKCBpID0gMCwgbCA9IG9iai5sZW5ndGg7IGkgPCBsOyBpKysgKSB7XG4gICAgICAgICAgaWYgKCBpIGluIG9iaiAmJiBpdGVyYXRvci5jYWxsKCBjb250ZXh0LCBvYmpbaV0sIGksIG9iaiApID09PSBicmVha2VyICkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgZWxzZSB7XG4gICAgICAgIGZvciAoIGtleSBpbiBvYmopIHtcbiAgICAgICAgICBpZiAoIGhhc093blByb3AuY2FsbCggb2JqLCBrZXkgKSApIHtcbiAgICAgICAgICAgIGlmICggaXRlcmF0b3IuY2FsbCAoY29udGV4dCwgb2JqW2tleV0sIGtleSwgb2JqICkgPT09IGJyZWFrZXIgKSB7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuICAgIGV4dGVuZCA6IGZ1bmN0aW9uKCBvYmogKSB7XG4gICAgICB0aGlzLmZvckVhY2goIHNsaWNlLmNhbGwoIGFyZ3VtZW50cywgMSApLCBmdW5jdGlvbiAoIHNvdXJjZSApIHtcbiAgICAgICAgZm9yICggdmFyIHByb3AgaW4gc291cmNlICkge1xuICAgICAgICAgIG9ialtwcm9wXSA9IHNvdXJjZVtwcm9wXTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICByZXR1cm4gb2JqO1xuICAgIH1cbiAgfTtcbiAgLy8gRU5EIE1pbmlhdHVyZSB1bmRlcnNjb3JlIGltcGxcblxuICAvLyBKZWQgaXMgYSBjb25zdHJ1Y3RvciBmdW5jdGlvblxuICB2YXIgSmVkID0gZnVuY3Rpb24gKCBvcHRpb25zICkge1xuICAgIC8vIFNvbWUgbWluaW1hbCBkZWZhdWx0c1xuICAgIHRoaXMuZGVmYXVsdHMgPSB7XG4gICAgICBcImxvY2FsZV9kYXRhXCIgOiB7XG4gICAgICAgIFwibWVzc2FnZXNcIiA6IHtcbiAgICAgICAgICBcIlwiIDoge1xuICAgICAgICAgICAgXCJkb21haW5cIiAgICAgICA6IFwibWVzc2FnZXNcIixcbiAgICAgICAgICAgIFwibGFuZ1wiICAgICAgICAgOiBcImVuXCIsXG4gICAgICAgICAgICBcInBsdXJhbF9mb3Jtc1wiIDogXCJucGx1cmFscz0yOyBwbHVyYWw9KG4gIT0gMSk7XCJcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gVGhlcmUgYXJlIG5vIGRlZmF1bHQga2V5cywgdGhvdWdoXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICAvLyBUaGUgZGVmYXVsdCBkb21haW4gaWYgb25lIGlzIG1pc3NpbmdcbiAgICAgIFwiZG9tYWluXCIgOiBcIm1lc3NhZ2VzXCIsXG4gICAgICAvLyBlbmFibGUgZGVidWcgbW9kZSB0byBsb2cgdW50cmFuc2xhdGVkIHN0cmluZ3MgdG8gdGhlIGNvbnNvbGVcbiAgICAgIFwiZGVidWdcIiA6IGZhbHNlXG4gICAgfTtcblxuICAgIC8vIE1peCBpbiB0aGUgc2VudCBvcHRpb25zIHdpdGggdGhlIGRlZmF1bHQgb3B0aW9uc1xuICAgIHRoaXMub3B0aW9ucyA9IF8uZXh0ZW5kKCB7fSwgdGhpcy5kZWZhdWx0cywgb3B0aW9ucyApO1xuICAgIHRoaXMudGV4dGRvbWFpbiggdGhpcy5vcHRpb25zLmRvbWFpbiApO1xuXG4gICAgaWYgKCBvcHRpb25zLmRvbWFpbiAmJiAhIHRoaXMub3B0aW9ucy5sb2NhbGVfZGF0YVsgdGhpcy5vcHRpb25zLmRvbWFpbiBdICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdUZXh0IGRvbWFpbiBzZXQgdG8gbm9uLWV4aXN0ZW50IGRvbWFpbjogYCcgKyBvcHRpb25zLmRvbWFpbiArICdgJyk7XG4gICAgfVxuICB9O1xuXG4gIC8vIFRoZSBnZXR0ZXh0IHNwZWMgc2V0cyB0aGlzIGNoYXJhY3RlciBhcyB0aGUgZGVmYXVsdFxuICAvLyBkZWxpbWl0ZXIgZm9yIGNvbnRleHQgbG9va3Vwcy5cbiAgLy8gZS5nLjogY29udGV4dFxcdTAwMDRrZXlcbiAgLy8gSWYgeW91ciB0cmFuc2xhdGlvbiBjb21wYW55IHVzZXMgc29tZXRoaW5nIGRpZmZlcmVudCxcbiAgLy8ganVzdCBjaGFuZ2UgdGhpcyBhdCBhbnkgdGltZSBhbmQgaXQgd2lsbCB1c2UgdGhhdCBpbnN0ZWFkLlxuICBKZWQuY29udGV4dF9kZWxpbWl0ZXIgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKCA0ICk7XG5cbiAgZnVuY3Rpb24gZ2V0UGx1cmFsRm9ybUZ1bmMgKCBwbHVyYWxfZm9ybV9zdHJpbmcgKSB7XG4gICAgcmV0dXJuIEplZC5QRi5jb21waWxlKCBwbHVyYWxfZm9ybV9zdHJpbmcgfHwgXCJucGx1cmFscz0yOyBwbHVyYWw9KG4gIT0gMSk7XCIpO1xuICB9XG5cbiAgZnVuY3Rpb24gQ2hhaW4oIGtleSwgaTE4biApe1xuICAgIHRoaXMuX2tleSA9IGtleTtcbiAgICB0aGlzLl9pMThuID0gaTE4bjtcbiAgfVxuXG4gIC8vIENyZWF0ZSBhIGNoYWluYWJsZSBhcGkgZm9yIGFkZGluZyBhcmdzIHByZXR0aWx5XG4gIF8uZXh0ZW5kKCBDaGFpbi5wcm90b3R5cGUsIHtcbiAgICBvbkRvbWFpbiA6IGZ1bmN0aW9uICggZG9tYWluICkge1xuICAgICAgdGhpcy5fZG9tYWluID0gZG9tYWluO1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbiAgICB3aXRoQ29udGV4dCA6IGZ1bmN0aW9uICggY29udGV4dCApIHtcbiAgICAgIHRoaXMuX2NvbnRleHQgPSBjb250ZXh0O1xuICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbiAgICBpZlBsdXJhbCA6IGZ1bmN0aW9uICggbnVtLCBwa2V5ICkge1xuICAgICAgdGhpcy5fdmFsID0gbnVtO1xuICAgICAgdGhpcy5fcGtleSA9IHBrZXk7XG4gICAgICByZXR1cm4gdGhpcztcbiAgICB9LFxuICAgIGZldGNoIDogZnVuY3Rpb24gKCBzQXJyICkge1xuICAgICAgaWYgKCB7fS50b1N0cmluZy5jYWxsKCBzQXJyICkgIT0gJ1tvYmplY3QgQXJyYXldJyApIHtcbiAgICAgICAgc0FyciA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLCAwKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiAoIHNBcnIgJiYgc0Fyci5sZW5ndGggPyBKZWQuc3ByaW50ZiA6IGZ1bmN0aW9uKHgpeyByZXR1cm4geDsgfSApKFxuICAgICAgICB0aGlzLl9pMThuLmRjbnBnZXR0ZXh0KHRoaXMuX2RvbWFpbiwgdGhpcy5fY29udGV4dCwgdGhpcy5fa2V5LCB0aGlzLl9wa2V5LCB0aGlzLl92YWwpLFxuICAgICAgICBzQXJyXG4gICAgICApO1xuICAgIH1cbiAgfSk7XG5cbiAgLy8gQWRkIGZ1bmN0aW9ucyB0byB0aGUgSmVkIHByb3RvdHlwZS5cbiAgLy8gVGhlc2Ugd2lsbCBiZSB0aGUgZnVuY3Rpb25zIG9uIHRoZSBvYmplY3QgdGhhdCdzIHJldHVybmVkXG4gIC8vIGZyb20gY3JlYXRpbmcgYSBgbmV3IEplZCgpYFxuICAvLyBUaGVzZSBzZWVtIHJlZHVuZGFudCwgYnV0IHRoZXkgZ3ppcCBwcmV0dHkgd2VsbC5cbiAgXy5leHRlbmQoIEplZC5wcm90b3R5cGUsIHtcbiAgICAvLyBUaGUgc2V4aWVyIGFwaSBzdGFydCBwb2ludFxuICAgIHRyYW5zbGF0ZSA6IGZ1bmN0aW9uICgga2V5ICkge1xuICAgICAgcmV0dXJuIG5ldyBDaGFpbigga2V5LCB0aGlzICk7XG4gICAgfSxcblxuICAgIHRleHRkb21haW4gOiBmdW5jdGlvbiAoIGRvbWFpbiApIHtcbiAgICAgIGlmICggISBkb21haW4gKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl90ZXh0ZG9tYWluO1xuICAgICAgfVxuICAgICAgdGhpcy5fdGV4dGRvbWFpbiA9IGRvbWFpbjtcbiAgICB9LFxuXG4gICAgZ2V0dGV4dCA6IGZ1bmN0aW9uICgga2V5ICkge1xuICAgICAgcmV0dXJuIHRoaXMuZGNucGdldHRleHQuY2FsbCggdGhpcywgdW5kZWYsIHVuZGVmLCBrZXkgKTtcbiAgICB9LFxuXG4gICAgZGdldHRleHQgOiBmdW5jdGlvbiAoIGRvbWFpbiwga2V5ICkge1xuICAgICByZXR1cm4gdGhpcy5kY25wZ2V0dGV4dC5jYWxsKCB0aGlzLCBkb21haW4sIHVuZGVmLCBrZXkgKTtcbiAgICB9LFxuXG4gICAgZGNnZXR0ZXh0IDogZnVuY3Rpb24gKCBkb21haW4gLCBrZXkgLyosIGNhdGVnb3J5ICovICkge1xuICAgICAgLy8gSWdub3JlcyB0aGUgY2F0ZWdvcnkgYW55d2F5c1xuICAgICAgcmV0dXJuIHRoaXMuZGNucGdldHRleHQuY2FsbCggdGhpcywgZG9tYWluLCB1bmRlZiwga2V5ICk7XG4gICAgfSxcblxuICAgIG5nZXR0ZXh0IDogZnVuY3Rpb24gKCBza2V5LCBwa2V5LCB2YWwgKSB7XG4gICAgICByZXR1cm4gdGhpcy5kY25wZ2V0dGV4dC5jYWxsKCB0aGlzLCB1bmRlZiwgdW5kZWYsIHNrZXksIHBrZXksIHZhbCApO1xuICAgIH0sXG5cbiAgICBkbmdldHRleHQgOiBmdW5jdGlvbiAoIGRvbWFpbiwgc2tleSwgcGtleSwgdmFsICkge1xuICAgICAgcmV0dXJuIHRoaXMuZGNucGdldHRleHQuY2FsbCggdGhpcywgZG9tYWluLCB1bmRlZiwgc2tleSwgcGtleSwgdmFsICk7XG4gICAgfSxcblxuICAgIGRjbmdldHRleHQgOiBmdW5jdGlvbiAoIGRvbWFpbiwgc2tleSwgcGtleSwgdmFsLyosIGNhdGVnb3J5ICovKSB7XG4gICAgICByZXR1cm4gdGhpcy5kY25wZ2V0dGV4dC5jYWxsKCB0aGlzLCBkb21haW4sIHVuZGVmLCBza2V5LCBwa2V5LCB2YWwgKTtcbiAgICB9LFxuXG4gICAgcGdldHRleHQgOiBmdW5jdGlvbiAoIGNvbnRleHQsIGtleSApIHtcbiAgICAgIHJldHVybiB0aGlzLmRjbnBnZXR0ZXh0LmNhbGwoIHRoaXMsIHVuZGVmLCBjb250ZXh0LCBrZXkgKTtcbiAgICB9LFxuXG4gICAgZHBnZXR0ZXh0IDogZnVuY3Rpb24gKCBkb21haW4sIGNvbnRleHQsIGtleSApIHtcbiAgICAgIHJldHVybiB0aGlzLmRjbnBnZXR0ZXh0LmNhbGwoIHRoaXMsIGRvbWFpbiwgY29udGV4dCwga2V5ICk7XG4gICAgfSxcblxuICAgIGRjcGdldHRleHQgOiBmdW5jdGlvbiAoIGRvbWFpbiwgY29udGV4dCwga2V5LyosIGNhdGVnb3J5ICovKSB7XG4gICAgICByZXR1cm4gdGhpcy5kY25wZ2V0dGV4dC5jYWxsKCB0aGlzLCBkb21haW4sIGNvbnRleHQsIGtleSApO1xuICAgIH0sXG5cbiAgICBucGdldHRleHQgOiBmdW5jdGlvbiAoIGNvbnRleHQsIHNrZXksIHBrZXksIHZhbCApIHtcbiAgICAgIHJldHVybiB0aGlzLmRjbnBnZXR0ZXh0LmNhbGwoIHRoaXMsIHVuZGVmLCBjb250ZXh0LCBza2V5LCBwa2V5LCB2YWwgKTtcbiAgICB9LFxuXG4gICAgZG5wZ2V0dGV4dCA6IGZ1bmN0aW9uICggZG9tYWluLCBjb250ZXh0LCBza2V5LCBwa2V5LCB2YWwgKSB7XG4gICAgICByZXR1cm4gdGhpcy5kY25wZ2V0dGV4dC5jYWxsKCB0aGlzLCBkb21haW4sIGNvbnRleHQsIHNrZXksIHBrZXksIHZhbCApO1xuICAgIH0sXG5cbiAgICAvLyBUaGUgbW9zdCBmdWxseSBxdWFsaWZpZWQgZ2V0dGV4dCBmdW5jdGlvbi4gSXQgaGFzIGV2ZXJ5IG9wdGlvbi5cbiAgICAvLyBTaW5jZSBpdCBoYXMgZXZlcnkgb3B0aW9uLCB3ZSBjYW4gdXNlIGl0IGZyb20gZXZlcnkgb3RoZXIgbWV0aG9kLlxuICAgIC8vIFRoaXMgaXMgdGhlIGJyZWFkIGFuZCBidXR0ZXIuXG4gICAgLy8gVGVjaG5pY2FsbHkgdGhlcmUgc2hvdWxkIGJlIG9uZSBtb3JlIGFyZ3VtZW50IGluIHRoaXMgZnVuY3Rpb24gZm9yICdDYXRlZ29yeScsXG4gICAgLy8gYnV0IHNpbmNlIHdlIG5ldmVyIHVzZSBpdCwgd2UgbWlnaHQgYXMgd2VsbCBub3Qgd2FzdGUgdGhlIGJ5dGVzIHRvIGRlZmluZSBpdC5cbiAgICBkY25wZ2V0dGV4dCA6IGZ1bmN0aW9uICggZG9tYWluLCBjb250ZXh0LCBzaW5ndWxhcl9rZXksIHBsdXJhbF9rZXksIHZhbCApIHtcbiAgICAgIC8vIFNldCBzb21lIGRlZmF1bHRzXG5cbiAgICAgIHBsdXJhbF9rZXkgPSBwbHVyYWxfa2V5IHx8IHNpbmd1bGFyX2tleTtcblxuICAgICAgLy8gVXNlIHRoZSBnbG9iYWwgZG9tYWluIGRlZmF1bHQgaWYgb25lXG4gICAgICAvLyBpc24ndCBleHBsaWNpdGx5IHBhc3NlZCBpblxuICAgICAgZG9tYWluID0gZG9tYWluIHx8IHRoaXMuX3RleHRkb21haW47XG5cbiAgICAgIHZhciBmYWxsYmFjaztcblxuICAgICAgLy8gSGFuZGxlIHNwZWNpYWwgY2FzZXNcblxuICAgICAgLy8gTm8gb3B0aW9ucyBmb3VuZFxuICAgICAgaWYgKCAhIHRoaXMub3B0aW9ucyApIHtcbiAgICAgICAgLy8gVGhlcmUncyBsaWtlbHkgc29tZXRoaW5nIHdyb25nLCBidXQgd2UnbGwgcmV0dXJuIHRoZSBjb3JyZWN0IGtleSBmb3IgZW5nbGlzaFxuICAgICAgICAvLyBXZSBkbyB0aGlzIGJ5IGluc3RhbnRpYXRpbmcgYSBicmFuZCBuZXcgSmVkIGluc3RhbmNlIHdpdGggdGhlIGRlZmF1bHQgc2V0XG4gICAgICAgIC8vIGZvciBldmVyeXRoaW5nIHRoYXQgY291bGQgYmUgYnJva2VuLlxuICAgICAgICBmYWxsYmFjayA9IG5ldyBKZWQoKTtcbiAgICAgICAgcmV0dXJuIGZhbGxiYWNrLmRjbnBnZXR0ZXh0LmNhbGwoIGZhbGxiYWNrLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgc2luZ3VsYXJfa2V5LCBwbHVyYWxfa2V5LCB2YWwgKTtcbiAgICAgIH1cblxuICAgICAgLy8gTm8gdHJhbnNsYXRpb24gZGF0YSBwcm92aWRlZFxuICAgICAgaWYgKCAhIHRoaXMub3B0aW9ucy5sb2NhbGVfZGF0YSApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBsb2NhbGUgZGF0YSBwcm92aWRlZC4nKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCAhIHRoaXMub3B0aW9ucy5sb2NhbGVfZGF0YVsgZG9tYWluIF0gKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRG9tYWluIGAnICsgZG9tYWluICsgJ2Agd2FzIG5vdCBmb3VuZC4nKTtcbiAgICAgIH1cblxuICAgICAgaWYgKCAhIHRoaXMub3B0aW9ucy5sb2NhbGVfZGF0YVsgZG9tYWluIF1bIFwiXCIgXSApIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBsb2NhbGUgbWV0YSBpbmZvcm1hdGlvbiBwcm92aWRlZC4nKTtcbiAgICAgIH1cblxuICAgICAgLy8gTWFrZSBzdXJlIHdlIGhhdmUgYSB0cnV0aHkga2V5LiBPdGhlcndpc2Ugd2UgbWlnaHQgc3RhcnQgbG9va2luZ1xuICAgICAgLy8gaW50byB0aGUgZW1wdHkgc3RyaW5nIGtleSwgd2hpY2ggaXMgdGhlIG9wdGlvbnMgZm9yIHRoZSBsb2NhbGVcbiAgICAgIC8vIGRhdGEuXG4gICAgICBpZiAoICEgc2luZ3VsYXJfa2V5ICkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIHRyYW5zbGF0aW9uIGtleSBmb3VuZC4nKTtcbiAgICAgIH1cblxuICAgICAgdmFyIGtleSAgPSBjb250ZXh0ID8gY29udGV4dCArIEplZC5jb250ZXh0X2RlbGltaXRlciArIHNpbmd1bGFyX2tleSA6IHNpbmd1bGFyX2tleSxcbiAgICAgICAgICBsb2NhbGVfZGF0YSA9IHRoaXMub3B0aW9ucy5sb2NhbGVfZGF0YSxcbiAgICAgICAgICBkaWN0ID0gbG9jYWxlX2RhdGFbIGRvbWFpbiBdLFxuICAgICAgICAgIGRlZmF1bHRDb25mID0gKGxvY2FsZV9kYXRhLm1lc3NhZ2VzIHx8IHRoaXMuZGVmYXVsdHMubG9jYWxlX2RhdGEubWVzc2FnZXMpW1wiXCJdLFxuICAgICAgICAgIHBsdXJhbEZvcm1zID0gZGljdFtcIlwiXS5wbHVyYWxfZm9ybXMgfHwgZGljdFtcIlwiXVtcIlBsdXJhbC1Gb3Jtc1wiXSB8fCBkaWN0W1wiXCJdW1wicGx1cmFsLWZvcm1zXCJdIHx8IGRlZmF1bHRDb25mLnBsdXJhbF9mb3JtcyB8fCBkZWZhdWx0Q29uZltcIlBsdXJhbC1Gb3Jtc1wiXSB8fCBkZWZhdWx0Q29uZltcInBsdXJhbC1mb3Jtc1wiXSxcbiAgICAgICAgICB2YWxfbGlzdCxcbiAgICAgICAgICByZXM7XG5cbiAgICAgIHZhciB2YWxfaWR4O1xuICAgICAgaWYgKHZhbCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIC8vIE5vIHZhbHVlIHBhc3NlZCBpbjsgYXNzdW1lIHNpbmd1bGFyIGtleSBsb29rdXAuXG4gICAgICAgIHZhbF9pZHggPSAwO1xuXG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBWYWx1ZSBoYXMgYmVlbiBwYXNzZWQgaW47IHVzZSBwbHVyYWwtZm9ybXMgY2FsY3VsYXRpb25zLlxuXG4gICAgICAgIC8vIEhhbmRsZSBpbnZhbGlkIG51bWJlcnMsIGJ1dCB0cnkgY2FzdGluZyBzdHJpbmdzIGZvciBnb29kIG1lYXN1cmVcbiAgICAgICAgaWYgKCB0eXBlb2YgdmFsICE9ICdudW1iZXInICkge1xuICAgICAgICAgIHZhbCA9IHBhcnNlSW50KCB2YWwsIDEwICk7XG5cbiAgICAgICAgICBpZiAoIGlzTmFOKCB2YWwgKSApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIG51bWJlciB0aGF0IHdhcyBwYXNzZWQgaW4gaXMgbm90IGEgbnVtYmVyLicpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhbF9pZHggPSBnZXRQbHVyYWxGb3JtRnVuYyhwbHVyYWxGb3JtcykodmFsKTtcbiAgICAgIH1cblxuICAgICAgLy8gVGhyb3cgYW4gZXJyb3IgaWYgYSBkb21haW4gaXNuJ3QgZm91bmRcbiAgICAgIGlmICggISBkaWN0ICkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGRvbWFpbiBuYW1lZCBgJyArIGRvbWFpbiArICdgIGNvdWxkIGJlIGZvdW5kLicpO1xuICAgICAgfVxuXG4gICAgICB2YWxfbGlzdCA9IGRpY3RbIGtleSBdO1xuXG4gICAgICAvLyBJZiB0aGVyZSBpcyBubyBtYXRjaCwgdGhlbiByZXZlcnQgYmFjayB0b1xuICAgICAgLy8gZW5nbGlzaCBzdHlsZSBzaW5ndWxhci9wbHVyYWwgd2l0aCB0aGUga2V5cyBwYXNzZWQgaW4uXG4gICAgICBpZiAoICEgdmFsX2xpc3QgfHwgdmFsX2lkeCA+IHZhbF9saXN0Lmxlbmd0aCApIHtcbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5taXNzaW5nX2tleV9jYWxsYmFjaykge1xuICAgICAgICAgIHRoaXMub3B0aW9ucy5taXNzaW5nX2tleV9jYWxsYmFjayhrZXksIGRvbWFpbik7XG4gICAgICAgIH1cbiAgICAgICAgcmVzID0gWyBzaW5ndWxhcl9rZXksIHBsdXJhbF9rZXkgXTtcblxuICAgICAgICAvLyBjb2xsZWN0IHVudHJhbnNsYXRlZCBzdHJpbmdzXG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuZGVidWc9PT10cnVlKSB7XG4gICAgICAgICAgY29uc29sZS5sb2cocmVzWyBnZXRQbHVyYWxGb3JtRnVuYyhwbHVyYWxGb3JtcykoIHZhbCApIF0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiByZXNbIGdldFBsdXJhbEZvcm1GdW5jKCkoIHZhbCApIF07XG4gICAgICB9XG5cbiAgICAgIHJlcyA9IHZhbF9saXN0WyB2YWxfaWR4IF07XG5cbiAgICAgIC8vIFRoaXMgaW5jbHVkZXMgZW1wdHkgc3RyaW5ncyBvbiBwdXJwb3NlXG4gICAgICBpZiAoICEgcmVzICApIHtcbiAgICAgICAgcmVzID0gWyBzaW5ndWxhcl9rZXksIHBsdXJhbF9rZXkgXTtcbiAgICAgICAgcmV0dXJuIHJlc1sgZ2V0UGx1cmFsRm9ybUZ1bmMoKSggdmFsICkgXTtcbiAgICAgIH1cbiAgICAgIHJldHVybiByZXM7XG4gICAgfVxuICB9KTtcblxuXG4gIC8vIFdlIGFkZCBpbiBzcHJpbnRmIGNhcGFiaWxpdGllcyBmb3IgcG9zdCB0cmFuc2xhdGlvbiB2YWx1ZSBpbnRlcm9sYXRpb25cbiAgLy8gVGhpcyBpcyBub3QgaW50ZXJuYWxseSB1c2VkLCBzbyB5b3UgY2FuIHJlbW92ZSBpdCBpZiB5b3UgaGF2ZSB0aGlzXG4gIC8vIGF2YWlsYWJsZSBzb21ld2hlcmUgZWxzZSwgb3Igd2FudCB0byB1c2UgYSBkaWZmZXJlbnQgc3lzdGVtLlxuXG4gIC8vIFdlIF9zbGlnaHRseV8gbW9kaWZ5IHRoZSBub3JtYWwgc3ByaW50ZiBiZWhhdmlvciB0byBtb3JlIGdyYWNlZnVsbHkgaGFuZGxlXG4gIC8vIHVuZGVmaW5lZCB2YWx1ZXMuXG5cbiAgLyoqXG4gICBzcHJpbnRmKCkgZm9yIEphdmFTY3JpcHQgMC43LWJldGExXG4gICBodHRwOi8vd3d3LmRpdmVpbnRvamF2YXNjcmlwdC5jb20vcHJvamVjdHMvamF2YXNjcmlwdC1zcHJpbnRmXG5cbiAgIENvcHlyaWdodCAoYykgQWxleGFuZHJ1IE1hcmFzdGVhbnUgPGFsZXhhaG9saWMgW2F0KSBnbWFpbCAoZG90XSBjb20+XG4gICBBbGwgcmlnaHRzIHJlc2VydmVkLlxuXG4gICBSZWRpc3RyaWJ1dGlvbiBhbmQgdXNlIGluIHNvdXJjZSBhbmQgYmluYXJ5IGZvcm1zLCB3aXRoIG9yIHdpdGhvdXRcbiAgIG1vZGlmaWNhdGlvbiwgYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxuICAgICAgICogUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHRcbiAgICAgICAgIG5vdGljZSwgdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lci5cbiAgICAgICAqIFJlZGlzdHJpYnV0aW9ucyBpbiBiaW5hcnkgZm9ybSBtdXN0IHJlcHJvZHVjZSB0aGUgYWJvdmUgY29weXJpZ2h0XG4gICAgICAgICBub3RpY2UsIHRoaXMgbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIgaW4gdGhlXG4gICAgICAgICBkb2N1bWVudGF0aW9uIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuICAgICAgICogTmVpdGhlciB0aGUgbmFtZSBvZiBzcHJpbnRmKCkgZm9yIEphdmFTY3JpcHQgbm9yIHRoZVxuICAgICAgICAgbmFtZXMgb2YgaXRzIGNvbnRyaWJ1dG9ycyBtYXkgYmUgdXNlZCB0byBlbmRvcnNlIG9yIHByb21vdGUgcHJvZHVjdHNcbiAgICAgICAgIGRlcml2ZWQgZnJvbSB0aGlzIHNvZnR3YXJlIHdpdGhvdXQgc3BlY2lmaWMgcHJpb3Igd3JpdHRlbiBwZXJtaXNzaW9uLlxuXG4gICBUSElTIFNPRlRXQVJFIElTIFBST1ZJREVEIEJZIFRIRSBDT1BZUklHSFQgSE9MREVSUyBBTkQgQ09OVFJJQlVUT1JTIFwiQVMgSVNcIiBBTkRcbiAgIEFOWSBFWFBSRVNTIE9SIElNUExJRUQgV0FSUkFOVElFUywgSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFRIRSBJTVBMSUVEXG4gICBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFXG4gICBESVNDTEFJTUVELiBJTiBOTyBFVkVOVCBTSEFMTCBBbGV4YW5kcnUgTWFyYXN0ZWFudSBCRSBMSUFCTEUgRk9SIEFOWVxuICAgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVNcbiAgIChJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgUFJPQ1VSRU1FTlQgT0YgU1VCU1RJVFVURSBHT09EUyBPUiBTRVJWSUNFUztcbiAgIExPU1MgT0YgVVNFLCBEQVRBLCBPUiBQUk9GSVRTOyBPUiBCVVNJTkVTUyBJTlRFUlJVUFRJT04pIEhPV0VWRVIgQ0FVU0VEIEFORFxuICAgT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksIE9SIFRPUlRcbiAgIChJTkNMVURJTkcgTkVHTElHRU5DRSBPUiBPVEhFUldJU0UpIEFSSVNJTkcgSU4gQU5ZIFdBWSBPVVQgT0YgVEhFIFVTRSBPRiBUSElTXG4gICBTT0ZUV0FSRSwgRVZFTiBJRiBBRFZJU0VEIE9GIFRIRSBQT1NTSUJJTElUWSBPRiBTVUNIIERBTUFHRS5cbiAgKi9cbiAgdmFyIHNwcmludGYgPSAoZnVuY3Rpb24oKSB7XG4gICAgZnVuY3Rpb24gZ2V0X3R5cGUodmFyaWFibGUpIHtcbiAgICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFyaWFibGUpLnNsaWNlKDgsIC0xKS50b0xvd2VyQ2FzZSgpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBzdHJfcmVwZWF0KGlucHV0LCBtdWx0aXBsaWVyKSB7XG4gICAgICBmb3IgKHZhciBvdXRwdXQgPSBbXTsgbXVsdGlwbGllciA+IDA7IG91dHB1dFstLW11bHRpcGxpZXJdID0gaW5wdXQpIHsvKiBkbyBub3RoaW5nICovfVxuICAgICAgcmV0dXJuIG91dHB1dC5qb2luKCcnKTtcbiAgICB9XG5cbiAgICB2YXIgc3RyX2Zvcm1hdCA9IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKCFzdHJfZm9ybWF0LmNhY2hlLmhhc093blByb3BlcnR5KGFyZ3VtZW50c1swXSkpIHtcbiAgICAgICAgc3RyX2Zvcm1hdC5jYWNoZVthcmd1bWVudHNbMF1dID0gc3RyX2Zvcm1hdC5wYXJzZShhcmd1bWVudHNbMF0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHN0cl9mb3JtYXQuZm9ybWF0LmNhbGwobnVsbCwgc3RyX2Zvcm1hdC5jYWNoZVthcmd1bWVudHNbMF1dLCBhcmd1bWVudHMpO1xuICAgIH07XG5cbiAgICBzdHJfZm9ybWF0LmZvcm1hdCA9IGZ1bmN0aW9uKHBhcnNlX3RyZWUsIGFyZ3YpIHtcbiAgICAgIHZhciBjdXJzb3IgPSAxLCB0cmVlX2xlbmd0aCA9IHBhcnNlX3RyZWUubGVuZ3RoLCBub2RlX3R5cGUgPSAnJywgYXJnLCBvdXRwdXQgPSBbXSwgaSwgaywgbWF0Y2gsIHBhZCwgcGFkX2NoYXJhY3RlciwgcGFkX2xlbmd0aDtcbiAgICAgIGZvciAoaSA9IDA7IGkgPCB0cmVlX2xlbmd0aDsgaSsrKSB7XG4gICAgICAgIG5vZGVfdHlwZSA9IGdldF90eXBlKHBhcnNlX3RyZWVbaV0pO1xuICAgICAgICBpZiAobm9kZV90eXBlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIG91dHB1dC5wdXNoKHBhcnNlX3RyZWVbaV0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG5vZGVfdHlwZSA9PT0gJ2FycmF5Jykge1xuICAgICAgICAgIG1hdGNoID0gcGFyc2VfdHJlZVtpXTsgLy8gY29udmVuaWVuY2UgcHVycG9zZXMgb25seVxuICAgICAgICAgIGlmIChtYXRjaFsyXSkgeyAvLyBrZXl3b3JkIGFyZ3VtZW50XG4gICAgICAgICAgICBhcmcgPSBhcmd2W2N1cnNvcl07XG4gICAgICAgICAgICBmb3IgKGsgPSAwOyBrIDwgbWF0Y2hbMl0ubGVuZ3RoOyBrKyspIHtcbiAgICAgICAgICAgICAgaWYgKCFhcmcuaGFzT3duUHJvcGVydHkobWF0Y2hbMl1ba10pKSB7XG4gICAgICAgICAgICAgICAgdGhyb3coc3ByaW50ZignW3NwcmludGZdIHByb3BlcnR5IFwiJXNcIiBkb2VzIG5vdCBleGlzdCcsIG1hdGNoWzJdW2tdKSk7XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgYXJnID0gYXJnW21hdGNoWzJdW2tdXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSBpZiAobWF0Y2hbMV0pIHsgLy8gcG9zaXRpb25hbCBhcmd1bWVudCAoZXhwbGljaXQpXG4gICAgICAgICAgICBhcmcgPSBhcmd2W21hdGNoWzFdXTtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSB7IC8vIHBvc2l0aW9uYWwgYXJndW1lbnQgKGltcGxpY2l0KVxuICAgICAgICAgICAgYXJnID0gYXJndltjdXJzb3IrK107XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKC9bXnNdLy50ZXN0KG1hdGNoWzhdKSAmJiAoZ2V0X3R5cGUoYXJnKSAhPSAnbnVtYmVyJykpIHtcbiAgICAgICAgICAgIHRocm93KHNwcmludGYoJ1tzcHJpbnRmXSBleHBlY3RpbmcgbnVtYmVyIGJ1dCBmb3VuZCAlcycsIGdldF90eXBlKGFyZykpKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICAvLyBKZWQgRURJVFxuICAgICAgICAgIGlmICggdHlwZW9mIGFyZyA9PSAndW5kZWZpbmVkJyB8fCBhcmcgPT09IG51bGwgKSB7XG4gICAgICAgICAgICBhcmcgPSAnJztcbiAgICAgICAgICB9XG4gICAgICAgICAgLy8gSmVkIEVESVRcblxuICAgICAgICAgIHN3aXRjaCAobWF0Y2hbOF0pIHtcbiAgICAgICAgICAgIGNhc2UgJ2InOiBhcmcgPSBhcmcudG9TdHJpbmcoMik7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnYyc6IGFyZyA9IFN0cmluZy5mcm9tQ2hhckNvZGUoYXJnKTsgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdkJzogYXJnID0gcGFyc2VJbnQoYXJnLCAxMCk7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnZSc6IGFyZyA9IG1hdGNoWzddID8gYXJnLnRvRXhwb25lbnRpYWwobWF0Y2hbN10pIDogYXJnLnRvRXhwb25lbnRpYWwoKTsgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdmJzogYXJnID0gbWF0Y2hbN10gPyBwYXJzZUZsb2F0KGFyZykudG9GaXhlZChtYXRjaFs3XSkgOiBwYXJzZUZsb2F0KGFyZyk7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnbyc6IGFyZyA9IGFyZy50b1N0cmluZyg4KTsgYnJlYWs7XG4gICAgICAgICAgICBjYXNlICdzJzogYXJnID0gKChhcmcgPSBTdHJpbmcoYXJnKSkgJiYgbWF0Y2hbN10gPyBhcmcuc3Vic3RyaW5nKDAsIG1hdGNoWzddKSA6IGFyZyk7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAndSc6IGFyZyA9IE1hdGguYWJzKGFyZyk7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAneCc6IGFyZyA9IGFyZy50b1N0cmluZygxNik7IGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnWCc6IGFyZyA9IGFyZy50b1N0cmluZygxNikudG9VcHBlckNhc2UoKTsgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGFyZyA9ICgvW2RlZl0vLnRlc3QobWF0Y2hbOF0pICYmIG1hdGNoWzNdICYmIGFyZyA+PSAwID8gJysnKyBhcmcgOiBhcmcpO1xuICAgICAgICAgIHBhZF9jaGFyYWN0ZXIgPSBtYXRjaFs0XSA/IG1hdGNoWzRdID09ICcwJyA/ICcwJyA6IG1hdGNoWzRdLmNoYXJBdCgxKSA6ICcgJztcbiAgICAgICAgICBwYWRfbGVuZ3RoID0gbWF0Y2hbNl0gLSBTdHJpbmcoYXJnKS5sZW5ndGg7XG4gICAgICAgICAgcGFkID0gbWF0Y2hbNl0gPyBzdHJfcmVwZWF0KHBhZF9jaGFyYWN0ZXIsIHBhZF9sZW5ndGgpIDogJyc7XG4gICAgICAgICAgb3V0cHV0LnB1c2gobWF0Y2hbNV0gPyBhcmcgKyBwYWQgOiBwYWQgKyBhcmcpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gb3V0cHV0LmpvaW4oJycpO1xuICAgIH07XG5cbiAgICBzdHJfZm9ybWF0LmNhY2hlID0ge307XG5cbiAgICBzdHJfZm9ybWF0LnBhcnNlID0gZnVuY3Rpb24oZm10KSB7XG4gICAgICB2YXIgX2ZtdCA9IGZtdCwgbWF0Y2ggPSBbXSwgcGFyc2VfdHJlZSA9IFtdLCBhcmdfbmFtZXMgPSAwO1xuICAgICAgd2hpbGUgKF9mbXQpIHtcbiAgICAgICAgaWYgKChtYXRjaCA9IC9eW15cXHgyNV0rLy5leGVjKF9mbXQpKSAhPT0gbnVsbCkge1xuICAgICAgICAgIHBhcnNlX3RyZWUucHVzaChtYXRjaFswXSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoKG1hdGNoID0gL15cXHgyNXsyfS8uZXhlYyhfZm10KSkgIT09IG51bGwpIHtcbiAgICAgICAgICBwYXJzZV90cmVlLnB1c2goJyUnKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICgobWF0Y2ggPSAvXlxceDI1KD86KFsxLTldXFxkKilcXCR8XFwoKFteXFwpXSspXFwpKT8oXFwrKT8oMHwnW14kXSk/KC0pPyhcXGQrKT8oPzpcXC4oXFxkKykpPyhbYi1mb3N1eFhdKS8uZXhlYyhfZm10KSkgIT09IG51bGwpIHtcbiAgICAgICAgICBpZiAobWF0Y2hbMl0pIHtcbiAgICAgICAgICAgIGFyZ19uYW1lcyB8PSAxO1xuICAgICAgICAgICAgdmFyIGZpZWxkX2xpc3QgPSBbXSwgcmVwbGFjZW1lbnRfZmllbGQgPSBtYXRjaFsyXSwgZmllbGRfbWF0Y2ggPSBbXTtcbiAgICAgICAgICAgIGlmICgoZmllbGRfbWF0Y2ggPSAvXihbYS16X11bYS16X1xcZF0qKS9pLmV4ZWMocmVwbGFjZW1lbnRfZmllbGQpKSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICBmaWVsZF9saXN0LnB1c2goZmllbGRfbWF0Y2hbMV0pO1xuICAgICAgICAgICAgICB3aGlsZSAoKHJlcGxhY2VtZW50X2ZpZWxkID0gcmVwbGFjZW1lbnRfZmllbGQuc3Vic3RyaW5nKGZpZWxkX21hdGNoWzBdLmxlbmd0aCkpICE9PSAnJykge1xuICAgICAgICAgICAgICAgIGlmICgoZmllbGRfbWF0Y2ggPSAvXlxcLihbYS16X11bYS16X1xcZF0qKS9pLmV4ZWMocmVwbGFjZW1lbnRfZmllbGQpKSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgZmllbGRfbGlzdC5wdXNoKGZpZWxkX21hdGNoWzFdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoKGZpZWxkX21hdGNoID0gL15cXFsoXFxkKylcXF0vLmV4ZWMocmVwbGFjZW1lbnRfZmllbGQpKSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgZmllbGRfbGlzdC5wdXNoKGZpZWxkX21hdGNoWzFdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICB0aHJvdygnW3NwcmludGZdIGh1aD8nKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICB0aHJvdygnW3NwcmludGZdIGh1aD8nKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG1hdGNoWzJdID0gZmllbGRfbGlzdDtcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBhcmdfbmFtZXMgfD0gMjtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGFyZ19uYW1lcyA9PT0gMykge1xuICAgICAgICAgICAgdGhyb3coJ1tzcHJpbnRmXSBtaXhpbmcgcG9zaXRpb25hbCBhbmQgbmFtZWQgcGxhY2Vob2xkZXJzIGlzIG5vdCAoeWV0KSBzdXBwb3J0ZWQnKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgcGFyc2VfdHJlZS5wdXNoKG1hdGNoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICB0aHJvdygnW3NwcmludGZdIGh1aD8nKTtcbiAgICAgICAgfVxuICAgICAgICBfZm10ID0gX2ZtdC5zdWJzdHJpbmcobWF0Y2hbMF0ubGVuZ3RoKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBwYXJzZV90cmVlO1xuICAgIH07XG5cbiAgICByZXR1cm4gc3RyX2Zvcm1hdDtcbiAgfSkoKTtcblxuICB2YXIgdnNwcmludGYgPSBmdW5jdGlvbihmbXQsIGFyZ3YpIHtcbiAgICBhcmd2LnVuc2hpZnQoZm10KTtcbiAgICByZXR1cm4gc3ByaW50Zi5hcHBseShudWxsLCBhcmd2KTtcbiAgfTtcblxuICBKZWQucGFyc2VfcGx1cmFsID0gZnVuY3Rpb24gKCBwbHVyYWxfZm9ybXMsIG4gKSB7XG4gICAgcGx1cmFsX2Zvcm1zID0gcGx1cmFsX2Zvcm1zLnJlcGxhY2UoL24vZywgbik7XG4gICAgcmV0dXJuIEplZC5wYXJzZV9leHByZXNzaW9uKHBsdXJhbF9mb3Jtcyk7XG4gIH07XG5cbiAgSmVkLnNwcmludGYgPSBmdW5jdGlvbiAoIGZtdCwgYXJncyApIHtcbiAgICBpZiAoIHt9LnRvU3RyaW5nLmNhbGwoIGFyZ3MgKSA9PSAnW29iamVjdCBBcnJheV0nICkge1xuICAgICAgcmV0dXJuIHZzcHJpbnRmKCBmbXQsIFtdLnNsaWNlLmNhbGwoYXJncykgKTtcbiAgICB9XG4gICAgcmV0dXJuIHNwcmludGYuYXBwbHkodGhpcywgW10uc2xpY2UuY2FsbChhcmd1bWVudHMpICk7XG4gIH07XG5cbiAgSmVkLnByb3RvdHlwZS5zcHJpbnRmID0gZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiBKZWQuc3ByaW50Zi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICB9O1xuICAvLyBFTkQgc3ByaW50ZiBJbXBsZW1lbnRhdGlvblxuXG4gIC8vIFN0YXJ0IHRoZSBQbHVyYWwgZm9ybXMgc2VjdGlvblxuICAvLyBUaGlzIGlzIGEgZnVsbCBwbHVyYWwgZm9ybSBleHByZXNzaW9uIHBhcnNlci4gSXQgaXMgdXNlZCB0byBhdm9pZFxuICAvLyBydW5uaW5nICdldmFsJyBvciAnbmV3IEZ1bmN0aW9uJyBkaXJlY3RseSBhZ2FpbnN0IHRoZSBwbHVyYWxcbiAgLy8gZm9ybXMuXG4gIC8vXG4gIC8vIFRoaXMgY2FuIGJlIGltcG9ydGFudCBpZiB5b3UgZ2V0IHRyYW5zbGF0aW9ucyBkb25lIHRocm91Z2ggYSAzcmRcbiAgLy8gcGFydHkgdmVuZG9yLiBJIGVuY291cmFnZSB5b3UgdG8gdXNlIHRoaXMgaW5zdGVhZCwgaG93ZXZlciwgSVxuICAvLyBhbHNvIHdpbGwgcHJvdmlkZSBhICdwcmVjb21waWxlcicgdGhhdCB5b3UgY2FuIHVzZSBhdCBidWlsZCB0aW1lXG4gIC8vIHRvIG91dHB1dCB2YWxpZC9zYWZlIGZ1bmN0aW9uIHJlcHJlc2VudGF0aW9ucyBvZiB0aGUgcGx1cmFsIGZvcm1cbiAgLy8gZXhwcmVzc2lvbnMuIFRoaXMgbWVhbnMgeW91IGNhbiBidWlsZCB0aGlzIGNvZGUgb3V0IGZvciB0aGUgbW9zdFxuICAvLyBwYXJ0LlxuICBKZWQuUEYgPSB7fTtcblxuICBKZWQuUEYucGFyc2UgPSBmdW5jdGlvbiAoIHAgKSB7XG4gICAgdmFyIHBsdXJhbF9zdHIgPSBKZWQuUEYuZXh0cmFjdFBsdXJhbEV4cHIoIHAgKTtcbiAgICByZXR1cm4gSmVkLlBGLnBhcnNlci5wYXJzZS5jYWxsKEplZC5QRi5wYXJzZXIsIHBsdXJhbF9zdHIpO1xuICB9O1xuXG4gIEplZC5QRi5jb21waWxlID0gZnVuY3Rpb24gKCBwICkge1xuICAgIC8vIEhhbmRsZSB0cnVlcyBhbmQgZmFsc2VzIGFzIDAgYW5kIDFcbiAgICBmdW5jdGlvbiBpbXBseSggdmFsICkge1xuICAgICAgcmV0dXJuICh2YWwgPT09IHRydWUgPyAxIDogdmFsID8gdmFsIDogMCk7XG4gICAgfVxuXG4gICAgdmFyIGFzdCA9IEplZC5QRi5wYXJzZSggcCApO1xuICAgIHJldHVybiBmdW5jdGlvbiAoIG4gKSB7XG4gICAgICByZXR1cm4gaW1wbHkoIEplZC5QRi5pbnRlcnByZXRlciggYXN0ICkoIG4gKSApO1xuICAgIH07XG4gIH07XG5cbiAgSmVkLlBGLmludGVycHJldGVyID0gZnVuY3Rpb24gKCBhc3QgKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uICggbiApIHtcbiAgICAgIHZhciByZXM7XG4gICAgICBzd2l0Y2ggKCBhc3QudHlwZSApIHtcbiAgICAgICAgY2FzZSAnR1JPVVAnOlxuICAgICAgICAgIHJldHVybiBKZWQuUEYuaW50ZXJwcmV0ZXIoIGFzdC5leHByICkoIG4gKTtcbiAgICAgICAgY2FzZSAnVEVSTkFSWSc6XG4gICAgICAgICAgaWYgKCBKZWQuUEYuaW50ZXJwcmV0ZXIoIGFzdC5leHByICkoIG4gKSApIHtcbiAgICAgICAgICAgIHJldHVybiBKZWQuUEYuaW50ZXJwcmV0ZXIoIGFzdC50cnV0aHkgKSggbiApO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gSmVkLlBGLmludGVycHJldGVyKCBhc3QuZmFsc2V5ICkoIG4gKTtcbiAgICAgICAgY2FzZSAnT1InOlxuICAgICAgICAgIHJldHVybiBKZWQuUEYuaW50ZXJwcmV0ZXIoIGFzdC5sZWZ0ICkoIG4gKSB8fCBKZWQuUEYuaW50ZXJwcmV0ZXIoIGFzdC5yaWdodCApKCBuICk7XG4gICAgICAgIGNhc2UgJ0FORCc6XG4gICAgICAgICAgcmV0dXJuIEplZC5QRi5pbnRlcnByZXRlciggYXN0LmxlZnQgKSggbiApICYmIEplZC5QRi5pbnRlcnByZXRlciggYXN0LnJpZ2h0ICkoIG4gKTtcbiAgICAgICAgY2FzZSAnTFQnOlxuICAgICAgICAgIHJldHVybiBKZWQuUEYuaW50ZXJwcmV0ZXIoIGFzdC5sZWZ0ICkoIG4gKSA8IEplZC5QRi5pbnRlcnByZXRlciggYXN0LnJpZ2h0ICkoIG4gKTtcbiAgICAgICAgY2FzZSAnR1QnOlxuICAgICAgICAgIHJldHVybiBKZWQuUEYuaW50ZXJwcmV0ZXIoIGFzdC5sZWZ0ICkoIG4gKSA+IEplZC5QRi5pbnRlcnByZXRlciggYXN0LnJpZ2h0ICkoIG4gKTtcbiAgICAgICAgY2FzZSAnTFRFJzpcbiAgICAgICAgICByZXR1cm4gSmVkLlBGLmludGVycHJldGVyKCBhc3QubGVmdCApKCBuICkgPD0gSmVkLlBGLmludGVycHJldGVyKCBhc3QucmlnaHQgKSggbiApO1xuICAgICAgICBjYXNlICdHVEUnOlxuICAgICAgICAgIHJldHVybiBKZWQuUEYuaW50ZXJwcmV0ZXIoIGFzdC5sZWZ0ICkoIG4gKSA+PSBKZWQuUEYuaW50ZXJwcmV0ZXIoIGFzdC5yaWdodCApKCBuICk7XG4gICAgICAgIGNhc2UgJ0VRJzpcbiAgICAgICAgICByZXR1cm4gSmVkLlBGLmludGVycHJldGVyKCBhc3QubGVmdCApKCBuICkgPT0gSmVkLlBGLmludGVycHJldGVyKCBhc3QucmlnaHQgKSggbiApO1xuICAgICAgICBjYXNlICdORVEnOlxuICAgICAgICAgIHJldHVybiBKZWQuUEYuaW50ZXJwcmV0ZXIoIGFzdC5sZWZ0ICkoIG4gKSAhPSBKZWQuUEYuaW50ZXJwcmV0ZXIoIGFzdC5yaWdodCApKCBuICk7XG4gICAgICAgIGNhc2UgJ01PRCc6XG4gICAgICAgICAgcmV0dXJuIEplZC5QRi5pbnRlcnByZXRlciggYXN0LmxlZnQgKSggbiApICUgSmVkLlBGLmludGVycHJldGVyKCBhc3QucmlnaHQgKSggbiApO1xuICAgICAgICBjYXNlICdWQVInOlxuICAgICAgICAgIHJldHVybiBuO1xuICAgICAgICBjYXNlICdOVU0nOlxuICAgICAgICAgIHJldHVybiBhc3QudmFsO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgVG9rZW4gZm91bmQuXCIpO1xuICAgICAgfVxuICAgIH07XG4gIH07XG5cbiAgSmVkLlBGLmV4dHJhY3RQbHVyYWxFeHByID0gZnVuY3Rpb24gKCBwICkge1xuICAgIC8vIHRyaW0gZmlyc3RcbiAgICBwID0gcC5yZXBsYWNlKC9eXFxzXFxzKi8sICcnKS5yZXBsYWNlKC9cXHNcXHMqJC8sICcnKTtcblxuICAgIGlmICghIC87XFxzKiQvLnRlc3QocCkpIHtcbiAgICAgIHAgPSBwLmNvbmNhdCgnOycpO1xuICAgIH1cblxuICAgIHZhciBucGx1cmFsc19yZSA9IC9ucGx1cmFsc1xcPShcXGQrKTsvLFxuICAgICAgICBwbHVyYWxfcmUgPSAvcGx1cmFsXFw9KC4qKTsvLFxuICAgICAgICBucGx1cmFsc19tYXRjaGVzID0gcC5tYXRjaCggbnBsdXJhbHNfcmUgKSxcbiAgICAgICAgcmVzID0ge30sXG4gICAgICAgIHBsdXJhbF9tYXRjaGVzO1xuXG4gICAgLy8gRmluZCB0aGUgbnBsdXJhbHMgbnVtYmVyXG4gICAgaWYgKCBucGx1cmFsc19tYXRjaGVzLmxlbmd0aCA+IDEgKSB7XG4gICAgICByZXMubnBsdXJhbHMgPSBucGx1cmFsc19tYXRjaGVzWzFdO1xuICAgIH1cbiAgICBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignbnBsdXJhbHMgbm90IGZvdW5kIGluIHBsdXJhbF9mb3JtcyBzdHJpbmc6ICcgKyBwICk7XG4gICAgfVxuXG4gICAgLy8gcmVtb3ZlIHRoYXQgZGF0YSB0byBnZXQgdG8gdGhlIGZvcm11bGFcbiAgICBwID0gcC5yZXBsYWNlKCBucGx1cmFsc19yZSwgXCJcIiApO1xuICAgIHBsdXJhbF9tYXRjaGVzID0gcC5tYXRjaCggcGx1cmFsX3JlICk7XG5cbiAgICBpZiAoISggcGx1cmFsX21hdGNoZXMgJiYgcGx1cmFsX21hdGNoZXMubGVuZ3RoID4gMSApICkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdgcGx1cmFsYCBleHByZXNzaW9uIG5vdCBmb3VuZDogJyArIHApO1xuICAgIH1cbiAgICByZXR1cm4gcGx1cmFsX21hdGNoZXNbIDEgXTtcbiAgfTtcblxuICAvKiBKaXNvbiBnZW5lcmF0ZWQgcGFyc2VyICovXG4gIEplZC5QRi5wYXJzZXIgPSAoZnVuY3Rpb24oKXtcblxudmFyIHBhcnNlciA9IHt0cmFjZTogZnVuY3Rpb24gdHJhY2UoKSB7IH0sXG55eToge30sXG5zeW1ib2xzXzoge1wiZXJyb3JcIjoyLFwiZXhwcmVzc2lvbnNcIjozLFwiZVwiOjQsXCJFT0ZcIjo1LFwiP1wiOjYsXCI6XCI6NyxcInx8XCI6OCxcIiYmXCI6OSxcIjxcIjoxMCxcIjw9XCI6MTEsXCI+XCI6MTIsXCI+PVwiOjEzLFwiIT1cIjoxNCxcIj09XCI6MTUsXCIlXCI6MTYsXCIoXCI6MTcsXCIpXCI6MTgsXCJuXCI6MTksXCJOVU1CRVJcIjoyMCxcIiRhY2NlcHRcIjowLFwiJGVuZFwiOjF9LFxudGVybWluYWxzXzogezI6XCJlcnJvclwiLDU6XCJFT0ZcIiw2OlwiP1wiLDc6XCI6XCIsODpcInx8XCIsOTpcIiYmXCIsMTA6XCI8XCIsMTE6XCI8PVwiLDEyOlwiPlwiLDEzOlwiPj1cIiwxNDpcIiE9XCIsMTU6XCI9PVwiLDE2OlwiJVwiLDE3OlwiKFwiLDE4OlwiKVwiLDE5OlwiblwiLDIwOlwiTlVNQkVSXCJ9LFxucHJvZHVjdGlvbnNfOiBbMCxbMywyXSxbNCw1XSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwzXSxbNCwxXSxbNCwxXV0sXG5wZXJmb3JtQWN0aW9uOiBmdW5jdGlvbiBhbm9ueW1vdXMoeXl0ZXh0LHl5bGVuZyx5eWxpbmVubyx5eSx5eXN0YXRlLCQkLF8kKSB7XG5cbnZhciAkMCA9ICQkLmxlbmd0aCAtIDE7XG5zd2l0Y2ggKHl5c3RhdGUpIHtcbmNhc2UgMTogcmV0dXJuIHsgdHlwZSA6ICdHUk9VUCcsIGV4cHI6ICQkWyQwLTFdIH07XG5icmVhaztcbmNhc2UgMjp0aGlzLiQgPSB7IHR5cGU6ICdURVJOQVJZJywgZXhwcjogJCRbJDAtNF0sIHRydXRoeSA6ICQkWyQwLTJdLCBmYWxzZXk6ICQkWyQwXSB9O1xuYnJlYWs7XG5jYXNlIDM6dGhpcy4kID0geyB0eXBlOiBcIk9SXCIsIGxlZnQ6ICQkWyQwLTJdLCByaWdodDogJCRbJDBdIH07XG5icmVhaztcbmNhc2UgNDp0aGlzLiQgPSB7IHR5cGU6IFwiQU5EXCIsIGxlZnQ6ICQkWyQwLTJdLCByaWdodDogJCRbJDBdIH07XG5icmVhaztcbmNhc2UgNTp0aGlzLiQgPSB7IHR5cGU6ICdMVCcsIGxlZnQ6ICQkWyQwLTJdLCByaWdodDogJCRbJDBdIH07XG5icmVhaztcbmNhc2UgNjp0aGlzLiQgPSB7IHR5cGU6ICdMVEUnLCBsZWZ0OiAkJFskMC0yXSwgcmlnaHQ6ICQkWyQwXSB9O1xuYnJlYWs7XG5jYXNlIDc6dGhpcy4kID0geyB0eXBlOiAnR1QnLCBsZWZ0OiAkJFskMC0yXSwgcmlnaHQ6ICQkWyQwXSB9O1xuYnJlYWs7XG5jYXNlIDg6dGhpcy4kID0geyB0eXBlOiAnR1RFJywgbGVmdDogJCRbJDAtMl0sIHJpZ2h0OiAkJFskMF0gfTtcbmJyZWFrO1xuY2FzZSA5OnRoaXMuJCA9IHsgdHlwZTogJ05FUScsIGxlZnQ6ICQkWyQwLTJdLCByaWdodDogJCRbJDBdIH07XG5icmVhaztcbmNhc2UgMTA6dGhpcy4kID0geyB0eXBlOiAnRVEnLCBsZWZ0OiAkJFskMC0yXSwgcmlnaHQ6ICQkWyQwXSB9O1xuYnJlYWs7XG5jYXNlIDExOnRoaXMuJCA9IHsgdHlwZTogJ01PRCcsIGxlZnQ6ICQkWyQwLTJdLCByaWdodDogJCRbJDBdIH07XG5icmVhaztcbmNhc2UgMTI6dGhpcy4kID0geyB0eXBlOiAnR1JPVVAnLCBleHByOiAkJFskMC0xXSB9O1xuYnJlYWs7XG5jYXNlIDEzOnRoaXMuJCA9IHsgdHlwZTogJ1ZBUicgfTtcbmJyZWFrO1xuY2FzZSAxNDp0aGlzLiQgPSB7IHR5cGU6ICdOVU0nLCB2YWw6IE51bWJlcih5eXRleHQpIH07XG5icmVhaztcbn1cbn0sXG50YWJsZTogW3szOjEsNDoyLDE3OlsxLDNdLDE5OlsxLDRdLDIwOlsxLDVdfSx7MTpbM119LHs1OlsxLDZdLDY6WzEsN10sODpbMSw4XSw5OlsxLDldLDEwOlsxLDEwXSwxMTpbMSwxMV0sMTI6WzEsMTJdLDEzOlsxLDEzXSwxNDpbMSwxNF0sMTU6WzEsMTVdLDE2OlsxLDE2XX0sezQ6MTcsMTc6WzEsM10sMTk6WzEsNF0sMjA6WzEsNV19LHs1OlsyLDEzXSw2OlsyLDEzXSw3OlsyLDEzXSw4OlsyLDEzXSw5OlsyLDEzXSwxMDpbMiwxM10sMTE6WzIsMTNdLDEyOlsyLDEzXSwxMzpbMiwxM10sMTQ6WzIsMTNdLDE1OlsyLDEzXSwxNjpbMiwxM10sMTg6WzIsMTNdfSx7NTpbMiwxNF0sNjpbMiwxNF0sNzpbMiwxNF0sODpbMiwxNF0sOTpbMiwxNF0sMTA6WzIsMTRdLDExOlsyLDE0XSwxMjpbMiwxNF0sMTM6WzIsMTRdLDE0OlsyLDE0XSwxNTpbMiwxNF0sMTY6WzIsMTRdLDE4OlsyLDE0XX0sezE6WzIsMV19LHs0OjE4LDE3OlsxLDNdLDE5OlsxLDRdLDIwOlsxLDVdfSx7NDoxOSwxNzpbMSwzXSwxOTpbMSw0XSwyMDpbMSw1XX0sezQ6MjAsMTc6WzEsM10sMTk6WzEsNF0sMjA6WzEsNV19LHs0OjIxLDE3OlsxLDNdLDE5OlsxLDRdLDIwOlsxLDVdfSx7NDoyMiwxNzpbMSwzXSwxOTpbMSw0XSwyMDpbMSw1XX0sezQ6MjMsMTc6WzEsM10sMTk6WzEsNF0sMjA6WzEsNV19LHs0OjI0LDE3OlsxLDNdLDE5OlsxLDRdLDIwOlsxLDVdfSx7NDoyNSwxNzpbMSwzXSwxOTpbMSw0XSwyMDpbMSw1XX0sezQ6MjYsMTc6WzEsM10sMTk6WzEsNF0sMjA6WzEsNV19LHs0OjI3LDE3OlsxLDNdLDE5OlsxLDRdLDIwOlsxLDVdfSx7NjpbMSw3XSw4OlsxLDhdLDk6WzEsOV0sMTA6WzEsMTBdLDExOlsxLDExXSwxMjpbMSwxMl0sMTM6WzEsMTNdLDE0OlsxLDE0XSwxNTpbMSwxNV0sMTY6WzEsMTZdLDE4OlsxLDI4XX0sezY6WzEsN10sNzpbMSwyOV0sODpbMSw4XSw5OlsxLDldLDEwOlsxLDEwXSwxMTpbMSwxMV0sMTI6WzEsMTJdLDEzOlsxLDEzXSwxNDpbMSwxNF0sMTU6WzEsMTVdLDE2OlsxLDE2XX0sezU6WzIsM10sNjpbMiwzXSw3OlsyLDNdLDg6WzIsM10sOTpbMSw5XSwxMDpbMSwxMF0sMTE6WzEsMTFdLDEyOlsxLDEyXSwxMzpbMSwxM10sMTQ6WzEsMTRdLDE1OlsxLDE1XSwxNjpbMSwxNl0sMTg6WzIsM119LHs1OlsyLDRdLDY6WzIsNF0sNzpbMiw0XSw4OlsyLDRdLDk6WzIsNF0sMTA6WzEsMTBdLDExOlsxLDExXSwxMjpbMSwxMl0sMTM6WzEsMTNdLDE0OlsxLDE0XSwxNTpbMSwxNV0sMTY6WzEsMTZdLDE4OlsyLDRdfSx7NTpbMiw1XSw2OlsyLDVdLDc6WzIsNV0sODpbMiw1XSw5OlsyLDVdLDEwOlsyLDVdLDExOlsyLDVdLDEyOlsyLDVdLDEzOlsyLDVdLDE0OlsyLDVdLDE1OlsyLDVdLDE2OlsxLDE2XSwxODpbMiw1XX0sezU6WzIsNl0sNjpbMiw2XSw3OlsyLDZdLDg6WzIsNl0sOTpbMiw2XSwxMDpbMiw2XSwxMTpbMiw2XSwxMjpbMiw2XSwxMzpbMiw2XSwxNDpbMiw2XSwxNTpbMiw2XSwxNjpbMSwxNl0sMTg6WzIsNl19LHs1OlsyLDddLDY6WzIsN10sNzpbMiw3XSw4OlsyLDddLDk6WzIsN10sMTA6WzIsN10sMTE6WzIsN10sMTI6WzIsN10sMTM6WzIsN10sMTQ6WzIsN10sMTU6WzIsN10sMTY6WzEsMTZdLDE4OlsyLDddfSx7NTpbMiw4XSw2OlsyLDhdLDc6WzIsOF0sODpbMiw4XSw5OlsyLDhdLDEwOlsyLDhdLDExOlsyLDhdLDEyOlsyLDhdLDEzOlsyLDhdLDE0OlsyLDhdLDE1OlsyLDhdLDE2OlsxLDE2XSwxODpbMiw4XX0sezU6WzIsOV0sNjpbMiw5XSw3OlsyLDldLDg6WzIsOV0sOTpbMiw5XSwxMDpbMiw5XSwxMTpbMiw5XSwxMjpbMiw5XSwxMzpbMiw5XSwxNDpbMiw5XSwxNTpbMiw5XSwxNjpbMSwxNl0sMTg6WzIsOV19LHs1OlsyLDEwXSw2OlsyLDEwXSw3OlsyLDEwXSw4OlsyLDEwXSw5OlsyLDEwXSwxMDpbMiwxMF0sMTE6WzIsMTBdLDEyOlsyLDEwXSwxMzpbMiwxMF0sMTQ6WzIsMTBdLDE1OlsyLDEwXSwxNjpbMSwxNl0sMTg6WzIsMTBdfSx7NTpbMiwxMV0sNjpbMiwxMV0sNzpbMiwxMV0sODpbMiwxMV0sOTpbMiwxMV0sMTA6WzIsMTFdLDExOlsyLDExXSwxMjpbMiwxMV0sMTM6WzIsMTFdLDE0OlsyLDExXSwxNTpbMiwxMV0sMTY6WzIsMTFdLDE4OlsyLDExXX0sezU6WzIsMTJdLDY6WzIsMTJdLDc6WzIsMTJdLDg6WzIsMTJdLDk6WzIsMTJdLDEwOlsyLDEyXSwxMTpbMiwxMl0sMTI6WzIsMTJdLDEzOlsyLDEyXSwxNDpbMiwxMl0sMTU6WzIsMTJdLDE2OlsyLDEyXSwxODpbMiwxMl19LHs0OjMwLDE3OlsxLDNdLDE5OlsxLDRdLDIwOlsxLDVdfSx7NTpbMiwyXSw2OlsxLDddLDc6WzIsMl0sODpbMSw4XSw5OlsxLDldLDEwOlsxLDEwXSwxMTpbMSwxMV0sMTI6WzEsMTJdLDEzOlsxLDEzXSwxNDpbMSwxNF0sMTU6WzEsMTVdLDE2OlsxLDE2XSwxODpbMiwyXX1dLFxuZGVmYXVsdEFjdGlvbnM6IHs2OlsyLDFdfSxcbnBhcnNlRXJyb3I6IGZ1bmN0aW9uIHBhcnNlRXJyb3Ioc3RyLCBoYXNoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKHN0cik7XG59LFxucGFyc2U6IGZ1bmN0aW9uIHBhcnNlKGlucHV0KSB7XG4gICAgdmFyIHNlbGYgPSB0aGlzLFxuICAgICAgICBzdGFjayA9IFswXSxcbiAgICAgICAgdnN0YWNrID0gW251bGxdLCAvLyBzZW1hbnRpYyB2YWx1ZSBzdGFja1xuICAgICAgICBsc3RhY2sgPSBbXSwgLy8gbG9jYXRpb24gc3RhY2tcbiAgICAgICAgdGFibGUgPSB0aGlzLnRhYmxlLFxuICAgICAgICB5eXRleHQgPSAnJyxcbiAgICAgICAgeXlsaW5lbm8gPSAwLFxuICAgICAgICB5eWxlbmcgPSAwLFxuICAgICAgICByZWNvdmVyaW5nID0gMCxcbiAgICAgICAgVEVSUk9SID0gMixcbiAgICAgICAgRU9GID0gMTtcblxuICAgIC8vdGhpcy5yZWR1Y3Rpb25Db3VudCA9IHRoaXMuc2hpZnRDb3VudCA9IDA7XG5cbiAgICB0aGlzLmxleGVyLnNldElucHV0KGlucHV0KTtcbiAgICB0aGlzLmxleGVyLnl5ID0gdGhpcy55eTtcbiAgICB0aGlzLnl5LmxleGVyID0gdGhpcy5sZXhlcjtcbiAgICBpZiAodHlwZW9mIHRoaXMubGV4ZXIueXlsbG9jID09ICd1bmRlZmluZWQnKVxuICAgICAgICB0aGlzLmxleGVyLnl5bGxvYyA9IHt9O1xuICAgIHZhciB5eWxvYyA9IHRoaXMubGV4ZXIueXlsbG9jO1xuICAgIGxzdGFjay5wdXNoKHl5bG9jKTtcblxuICAgIGlmICh0eXBlb2YgdGhpcy55eS5wYXJzZUVycm9yID09PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aGlzLnBhcnNlRXJyb3IgPSB0aGlzLnl5LnBhcnNlRXJyb3I7XG5cbiAgICBmdW5jdGlvbiBwb3BTdGFjayAobikge1xuICAgICAgICBzdGFjay5sZW5ndGggPSBzdGFjay5sZW5ndGggLSAyKm47XG4gICAgICAgIHZzdGFjay5sZW5ndGggPSB2c3RhY2subGVuZ3RoIC0gbjtcbiAgICAgICAgbHN0YWNrLmxlbmd0aCA9IGxzdGFjay5sZW5ndGggLSBuO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGxleCgpIHtcbiAgICAgICAgdmFyIHRva2VuO1xuICAgICAgICB0b2tlbiA9IHNlbGYubGV4ZXIubGV4KCkgfHwgMTsgLy8gJGVuZCA9IDFcbiAgICAgICAgLy8gaWYgdG9rZW4gaXNuJ3QgaXRzIG51bWVyaWMgdmFsdWUsIGNvbnZlcnRcbiAgICAgICAgaWYgKHR5cGVvZiB0b2tlbiAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgIHRva2VuID0gc2VsZi5zeW1ib2xzX1t0b2tlbl0gfHwgdG9rZW47XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRva2VuO1xuICAgIH1cblxuICAgIHZhciBzeW1ib2wsIHByZUVycm9yU3ltYm9sLCBzdGF0ZSwgYWN0aW9uLCBhLCByLCB5eXZhbD17fSxwLGxlbixuZXdTdGF0ZSwgZXhwZWN0ZWQ7XG4gICAgd2hpbGUgKHRydWUpIHtcbiAgICAgICAgLy8gcmV0cmVpdmUgc3RhdGUgbnVtYmVyIGZyb20gdG9wIG9mIHN0YWNrXG4gICAgICAgIHN0YXRlID0gc3RhY2tbc3RhY2subGVuZ3RoLTFdO1xuXG4gICAgICAgIC8vIHVzZSBkZWZhdWx0IGFjdGlvbnMgaWYgYXZhaWxhYmxlXG4gICAgICAgIGlmICh0aGlzLmRlZmF1bHRBY3Rpb25zW3N0YXRlXSkge1xuICAgICAgICAgICAgYWN0aW9uID0gdGhpcy5kZWZhdWx0QWN0aW9uc1tzdGF0ZV07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoc3ltYm9sID09IG51bGwpXG4gICAgICAgICAgICAgICAgc3ltYm9sID0gbGV4KCk7XG4gICAgICAgICAgICAvLyByZWFkIGFjdGlvbiBmb3IgY3VycmVudCBzdGF0ZSBhbmQgZmlyc3QgaW5wdXRcbiAgICAgICAgICAgIGFjdGlvbiA9IHRhYmxlW3N0YXRlXSAmJiB0YWJsZVtzdGF0ZV1bc3ltYm9sXTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIGhhbmRsZSBwYXJzZSBlcnJvclxuICAgICAgICBfaGFuZGxlX2Vycm9yOlxuICAgICAgICBpZiAodHlwZW9mIGFjdGlvbiA9PT0gJ3VuZGVmaW5lZCcgfHwgIWFjdGlvbi5sZW5ndGggfHwgIWFjdGlvblswXSkge1xuXG4gICAgICAgICAgICBpZiAoIXJlY292ZXJpbmcpIHtcbiAgICAgICAgICAgICAgICAvLyBSZXBvcnQgZXJyb3JcbiAgICAgICAgICAgICAgICBleHBlY3RlZCA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAocCBpbiB0YWJsZVtzdGF0ZV0pIGlmICh0aGlzLnRlcm1pbmFsc19bcF0gJiYgcCA+IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgZXhwZWN0ZWQucHVzaChcIidcIit0aGlzLnRlcm1pbmFsc19bcF0rXCInXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgZXJyU3RyID0gJyc7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMubGV4ZXIuc2hvd1Bvc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIGVyclN0ciA9ICdQYXJzZSBlcnJvciBvbiBsaW5lICcrKHl5bGluZW5vKzEpK1wiOlxcblwiK3RoaXMubGV4ZXIuc2hvd1Bvc2l0aW9uKCkrXCJcXG5FeHBlY3RpbmcgXCIrZXhwZWN0ZWQuam9pbignLCAnKSArIFwiLCBnb3QgJ1wiICsgdGhpcy50ZXJtaW5hbHNfW3N5bWJvbF0rIFwiJ1wiO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGVyclN0ciA9ICdQYXJzZSBlcnJvciBvbiBsaW5lICcrKHl5bGluZW5vKzEpK1wiOiBVbmV4cGVjdGVkIFwiICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoc3ltYm9sID09IDEgLypFT0YqLyA/IFwiZW5kIG9mIGlucHV0XCIgOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChcIidcIisodGhpcy50ZXJtaW5hbHNfW3N5bWJvbF0gfHwgc3ltYm9sKStcIidcIikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB0aGlzLnBhcnNlRXJyb3IoZXJyU3RyLFxuICAgICAgICAgICAgICAgICAgICB7dGV4dDogdGhpcy5sZXhlci5tYXRjaCwgdG9rZW46IHRoaXMudGVybWluYWxzX1tzeW1ib2xdIHx8IHN5bWJvbCwgbGluZTogdGhpcy5sZXhlci55eWxpbmVubywgbG9jOiB5eWxvYywgZXhwZWN0ZWQ6IGV4cGVjdGVkfSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIGp1c3QgcmVjb3ZlcmVkIGZyb20gYW5vdGhlciBlcnJvclxuICAgICAgICAgICAgaWYgKHJlY292ZXJpbmcgPT0gMykge1xuICAgICAgICAgICAgICAgIGlmIChzeW1ib2wgPT0gRU9GKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJTdHIgfHwgJ1BhcnNpbmcgaGFsdGVkLicpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIGRpc2NhcmQgY3VycmVudCBsb29rYWhlYWQgYW5kIGdyYWIgYW5vdGhlclxuICAgICAgICAgICAgICAgIHl5bGVuZyA9IHRoaXMubGV4ZXIueXlsZW5nO1xuICAgICAgICAgICAgICAgIHl5dGV4dCA9IHRoaXMubGV4ZXIueXl0ZXh0O1xuICAgICAgICAgICAgICAgIHl5bGluZW5vID0gdGhpcy5sZXhlci55eWxpbmVubztcbiAgICAgICAgICAgICAgICB5eWxvYyA9IHRoaXMubGV4ZXIueXlsbG9jO1xuICAgICAgICAgICAgICAgIHN5bWJvbCA9IGxleCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyB0cnkgdG8gcmVjb3ZlciBmcm9tIGVycm9yXG4gICAgICAgICAgICB3aGlsZSAoMSkge1xuICAgICAgICAgICAgICAgIC8vIGNoZWNrIGZvciBlcnJvciByZWNvdmVyeSBydWxlIGluIHRoaXMgc3RhdGVcbiAgICAgICAgICAgICAgICBpZiAoKFRFUlJPUi50b1N0cmluZygpKSBpbiB0YWJsZVtzdGF0ZV0pIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChzdGF0ZSA9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJTdHIgfHwgJ1BhcnNpbmcgaGFsdGVkLicpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwb3BTdGFjaygxKTtcbiAgICAgICAgICAgICAgICBzdGF0ZSA9IHN0YWNrW3N0YWNrLmxlbmd0aC0xXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcHJlRXJyb3JTeW1ib2wgPSBzeW1ib2w7IC8vIHNhdmUgdGhlIGxvb2thaGVhZCB0b2tlblxuICAgICAgICAgICAgc3ltYm9sID0gVEVSUk9SOyAgICAgICAgIC8vIGluc2VydCBnZW5lcmljIGVycm9yIHN5bWJvbCBhcyBuZXcgbG9va2FoZWFkXG4gICAgICAgICAgICBzdGF0ZSA9IHN0YWNrW3N0YWNrLmxlbmd0aC0xXTtcbiAgICAgICAgICAgIGFjdGlvbiA9IHRhYmxlW3N0YXRlXSAmJiB0YWJsZVtzdGF0ZV1bVEVSUk9SXTtcbiAgICAgICAgICAgIHJlY292ZXJpbmcgPSAzOyAvLyBhbGxvdyAzIHJlYWwgc3ltYm9scyB0byBiZSBzaGlmdGVkIGJlZm9yZSByZXBvcnRpbmcgYSBuZXcgZXJyb3JcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHRoaXMgc2hvdWxkbid0IGhhcHBlbiwgdW5sZXNzIHJlc29sdmUgZGVmYXVsdHMgYXJlIG9mZlxuICAgICAgICBpZiAoYWN0aW9uWzBdIGluc3RhbmNlb2YgQXJyYXkgJiYgYWN0aW9uLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUGFyc2UgRXJyb3I6IG11bHRpcGxlIGFjdGlvbnMgcG9zc2libGUgYXQgc3RhdGU6ICcrc3RhdGUrJywgdG9rZW46ICcrc3ltYm9sKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHN3aXRjaCAoYWN0aW9uWzBdKSB7XG5cbiAgICAgICAgICAgIGNhc2UgMTogLy8gc2hpZnRcbiAgICAgICAgICAgICAgICAvL3RoaXMuc2hpZnRDb3VudCsrO1xuXG4gICAgICAgICAgICAgICAgc3RhY2sucHVzaChzeW1ib2wpO1xuICAgICAgICAgICAgICAgIHZzdGFjay5wdXNoKHRoaXMubGV4ZXIueXl0ZXh0KTtcbiAgICAgICAgICAgICAgICBsc3RhY2sucHVzaCh0aGlzLmxleGVyLnl5bGxvYyk7XG4gICAgICAgICAgICAgICAgc3RhY2sucHVzaChhY3Rpb25bMV0pOyAvLyBwdXNoIHN0YXRlXG4gICAgICAgICAgICAgICAgc3ltYm9sID0gbnVsbDtcbiAgICAgICAgICAgICAgICBpZiAoIXByZUVycm9yU3ltYm9sKSB7IC8vIG5vcm1hbCBleGVjdXRpb24vbm8gZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgeXlsZW5nID0gdGhpcy5sZXhlci55eWxlbmc7XG4gICAgICAgICAgICAgICAgICAgIHl5dGV4dCA9IHRoaXMubGV4ZXIueXl0ZXh0O1xuICAgICAgICAgICAgICAgICAgICB5eWxpbmVubyA9IHRoaXMubGV4ZXIueXlsaW5lbm87XG4gICAgICAgICAgICAgICAgICAgIHl5bG9jID0gdGhpcy5sZXhlci55eWxsb2M7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZWNvdmVyaW5nID4gMClcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlY292ZXJpbmctLTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgeyAvLyBlcnJvciBqdXN0IG9jY3VycmVkLCByZXN1bWUgb2xkIGxvb2thaGVhZCBmLyBiZWZvcmUgZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgc3ltYm9sID0gcHJlRXJyb3JTeW1ib2w7XG4gICAgICAgICAgICAgICAgICAgIHByZUVycm9yU3ltYm9sID0gbnVsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgIGNhc2UgMjogLy8gcmVkdWNlXG4gICAgICAgICAgICAgICAgLy90aGlzLnJlZHVjdGlvbkNvdW50Kys7XG5cbiAgICAgICAgICAgICAgICBsZW4gPSB0aGlzLnByb2R1Y3Rpb25zX1thY3Rpb25bMV1dWzFdO1xuXG4gICAgICAgICAgICAgICAgLy8gcGVyZm9ybSBzZW1hbnRpYyBhY3Rpb25cbiAgICAgICAgICAgICAgICB5eXZhbC4kID0gdnN0YWNrW3ZzdGFjay5sZW5ndGgtbGVuXTsgLy8gZGVmYXVsdCB0byAkJCA9ICQxXG4gICAgICAgICAgICAgICAgLy8gZGVmYXVsdCBsb2NhdGlvbiwgdXNlcyBmaXJzdCB0b2tlbiBmb3IgZmlyc3RzLCBsYXN0IGZvciBsYXN0c1xuICAgICAgICAgICAgICAgIHl5dmFsLl8kID0ge1xuICAgICAgICAgICAgICAgICAgICBmaXJzdF9saW5lOiBsc3RhY2tbbHN0YWNrLmxlbmd0aC0obGVufHwxKV0uZmlyc3RfbGluZSxcbiAgICAgICAgICAgICAgICAgICAgbGFzdF9saW5lOiBsc3RhY2tbbHN0YWNrLmxlbmd0aC0xXS5sYXN0X2xpbmUsXG4gICAgICAgICAgICAgICAgICAgIGZpcnN0X2NvbHVtbjogbHN0YWNrW2xzdGFjay5sZW5ndGgtKGxlbnx8MSldLmZpcnN0X2NvbHVtbixcbiAgICAgICAgICAgICAgICAgICAgbGFzdF9jb2x1bW46IGxzdGFja1tsc3RhY2subGVuZ3RoLTFdLmxhc3RfY29sdW1uXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICByID0gdGhpcy5wZXJmb3JtQWN0aW9uLmNhbGwoeXl2YWwsIHl5dGV4dCwgeXlsZW5nLCB5eWxpbmVubywgdGhpcy55eSwgYWN0aW9uWzFdLCB2c3RhY2ssIGxzdGFjayk7XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHIgIT09ICd1bmRlZmluZWQnKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIHBvcCBvZmYgc3RhY2tcbiAgICAgICAgICAgICAgICBpZiAobGVuKSB7XG4gICAgICAgICAgICAgICAgICAgIHN0YWNrID0gc3RhY2suc2xpY2UoMCwtMSpsZW4qMik7XG4gICAgICAgICAgICAgICAgICAgIHZzdGFjayA9IHZzdGFjay5zbGljZSgwLCAtMSpsZW4pO1xuICAgICAgICAgICAgICAgICAgICBsc3RhY2sgPSBsc3RhY2suc2xpY2UoMCwgLTEqbGVuKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBzdGFjay5wdXNoKHRoaXMucHJvZHVjdGlvbnNfW2FjdGlvblsxXV1bMF0pOyAgICAvLyBwdXNoIG5vbnRlcm1pbmFsIChyZWR1Y2UpXG4gICAgICAgICAgICAgICAgdnN0YWNrLnB1c2goeXl2YWwuJCk7XG4gICAgICAgICAgICAgICAgbHN0YWNrLnB1c2goeXl2YWwuXyQpO1xuICAgICAgICAgICAgICAgIC8vIGdvdG8gbmV3IHN0YXRlID0gdGFibGVbU1RBVEVdW05PTlRFUk1JTkFMXVxuICAgICAgICAgICAgICAgIG5ld1N0YXRlID0gdGFibGVbc3RhY2tbc3RhY2subGVuZ3RoLTJdXVtzdGFja1tzdGFjay5sZW5ndGgtMV1dO1xuICAgICAgICAgICAgICAgIHN0YWNrLnB1c2gobmV3U3RhdGUpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBjYXNlIDM6IC8vIGFjY2VwdFxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICB9XG5cbiAgICByZXR1cm4gdHJ1ZTtcbn19Oy8qIEppc29uIGdlbmVyYXRlZCBsZXhlciAqL1xudmFyIGxleGVyID0gKGZ1bmN0aW9uKCl7XG5cbnZhciBsZXhlciA9ICh7RU9GOjEsXG5wYXJzZUVycm9yOmZ1bmN0aW9uIHBhcnNlRXJyb3Ioc3RyLCBoYXNoKSB7XG4gICAgICAgIGlmICh0aGlzLnl5LnBhcnNlRXJyb3IpIHtcbiAgICAgICAgICAgIHRoaXMueXkucGFyc2VFcnJvcihzdHIsIGhhc2gpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKHN0cik7XG4gICAgICAgIH1cbiAgICB9LFxuc2V0SW5wdXQ6ZnVuY3Rpb24gKGlucHV0KSB7XG4gICAgICAgIHRoaXMuX2lucHV0ID0gaW5wdXQ7XG4gICAgICAgIHRoaXMuX21vcmUgPSB0aGlzLl9sZXNzID0gdGhpcy5kb25lID0gZmFsc2U7XG4gICAgICAgIHRoaXMueXlsaW5lbm8gPSB0aGlzLnl5bGVuZyA9IDA7XG4gICAgICAgIHRoaXMueXl0ZXh0ID0gdGhpcy5tYXRjaGVkID0gdGhpcy5tYXRjaCA9ICcnO1xuICAgICAgICB0aGlzLmNvbmRpdGlvblN0YWNrID0gWydJTklUSUFMJ107XG4gICAgICAgIHRoaXMueXlsbG9jID0ge2ZpcnN0X2xpbmU6MSxmaXJzdF9jb2x1bW46MCxsYXN0X2xpbmU6MSxsYXN0X2NvbHVtbjowfTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbmlucHV0OmZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGNoID0gdGhpcy5faW5wdXRbMF07XG4gICAgICAgIHRoaXMueXl0ZXh0Kz1jaDtcbiAgICAgICAgdGhpcy55eWxlbmcrKztcbiAgICAgICAgdGhpcy5tYXRjaCs9Y2g7XG4gICAgICAgIHRoaXMubWF0Y2hlZCs9Y2g7XG4gICAgICAgIHZhciBsaW5lcyA9IGNoLm1hdGNoKC9cXG4vKTtcbiAgICAgICAgaWYgKGxpbmVzKSB0aGlzLnl5bGluZW5vKys7XG4gICAgICAgIHRoaXMuX2lucHV0ID0gdGhpcy5faW5wdXQuc2xpY2UoMSk7XG4gICAgICAgIHJldHVybiBjaDtcbiAgICB9LFxudW5wdXQ6ZnVuY3Rpb24gKGNoKSB7XG4gICAgICAgIHRoaXMuX2lucHV0ID0gY2ggKyB0aGlzLl9pbnB1dDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbm1vcmU6ZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLl9tb3JlID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfSxcbnBhc3RJbnB1dDpmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBwYXN0ID0gdGhpcy5tYXRjaGVkLnN1YnN0cigwLCB0aGlzLm1hdGNoZWQubGVuZ3RoIC0gdGhpcy5tYXRjaC5sZW5ndGgpO1xuICAgICAgICByZXR1cm4gKHBhc3QubGVuZ3RoID4gMjAgPyAnLi4uJzonJykgKyBwYXN0LnN1YnN0cigtMjApLnJlcGxhY2UoL1xcbi9nLCBcIlwiKTtcbiAgICB9LFxudXBjb21pbmdJbnB1dDpmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBuZXh0ID0gdGhpcy5tYXRjaDtcbiAgICAgICAgaWYgKG5leHQubGVuZ3RoIDwgMjApIHtcbiAgICAgICAgICAgIG5leHQgKz0gdGhpcy5faW5wdXQuc3Vic3RyKDAsIDIwLW5leHQubGVuZ3RoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gKG5leHQuc3Vic3RyKDAsMjApKyhuZXh0Lmxlbmd0aCA+IDIwID8gJy4uLic6JycpKS5yZXBsYWNlKC9cXG4vZywgXCJcIik7XG4gICAgfSxcbnNob3dQb3NpdGlvbjpmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBwcmUgPSB0aGlzLnBhc3RJbnB1dCgpO1xuICAgICAgICB2YXIgYyA9IG5ldyBBcnJheShwcmUubGVuZ3RoICsgMSkuam9pbihcIi1cIik7XG4gICAgICAgIHJldHVybiBwcmUgKyB0aGlzLnVwY29taW5nSW5wdXQoKSArIFwiXFxuXCIgKyBjK1wiXlwiO1xuICAgIH0sXG5uZXh0OmZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuZG9uZSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuRU9GO1xuICAgICAgICB9XG4gICAgICAgIGlmICghdGhpcy5faW5wdXQpIHRoaXMuZG9uZSA9IHRydWU7XG5cbiAgICAgICAgdmFyIHRva2VuLFxuICAgICAgICAgICAgbWF0Y2gsXG4gICAgICAgICAgICBjb2wsXG4gICAgICAgICAgICBsaW5lcztcbiAgICAgICAgaWYgKCF0aGlzLl9tb3JlKSB7XG4gICAgICAgICAgICB0aGlzLnl5dGV4dCA9ICcnO1xuICAgICAgICAgICAgdGhpcy5tYXRjaCA9ICcnO1xuICAgICAgICB9XG4gICAgICAgIHZhciBydWxlcyA9IHRoaXMuX2N1cnJlbnRSdWxlcygpO1xuICAgICAgICBmb3IgKHZhciBpPTA7aSA8IHJ1bGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBtYXRjaCA9IHRoaXMuX2lucHV0Lm1hdGNoKHRoaXMucnVsZXNbcnVsZXNbaV1dKTtcbiAgICAgICAgICAgIGlmIChtYXRjaCkge1xuICAgICAgICAgICAgICAgIGxpbmVzID0gbWF0Y2hbMF0ubWF0Y2goL1xcbi4qL2cpO1xuICAgICAgICAgICAgICAgIGlmIChsaW5lcykgdGhpcy55eWxpbmVubyArPSBsaW5lcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgdGhpcy55eWxsb2MgPSB7Zmlyc3RfbGluZTogdGhpcy55eWxsb2MubGFzdF9saW5lLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RfbGluZTogdGhpcy55eWxpbmVubysxLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpcnN0X2NvbHVtbjogdGhpcy55eWxsb2MubGFzdF9jb2x1bW4sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGFzdF9jb2x1bW46IGxpbmVzID8gbGluZXNbbGluZXMubGVuZ3RoLTFdLmxlbmd0aC0xIDogdGhpcy55eWxsb2MubGFzdF9jb2x1bW4gKyBtYXRjaFswXS5sZW5ndGh9XG4gICAgICAgICAgICAgICAgdGhpcy55eXRleHQgKz0gbWF0Y2hbMF07XG4gICAgICAgICAgICAgICAgdGhpcy5tYXRjaCArPSBtYXRjaFswXTtcbiAgICAgICAgICAgICAgICB0aGlzLm1hdGNoZXMgPSBtYXRjaDtcbiAgICAgICAgICAgICAgICB0aGlzLnl5bGVuZyA9IHRoaXMueXl0ZXh0Lmxlbmd0aDtcbiAgICAgICAgICAgICAgICB0aGlzLl9tb3JlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgdGhpcy5faW5wdXQgPSB0aGlzLl9pbnB1dC5zbGljZShtYXRjaFswXS5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIHRoaXMubWF0Y2hlZCArPSBtYXRjaFswXTtcbiAgICAgICAgICAgICAgICB0b2tlbiA9IHRoaXMucGVyZm9ybUFjdGlvbi5jYWxsKHRoaXMsIHRoaXMueXksIHRoaXMsIHJ1bGVzW2ldLHRoaXMuY29uZGl0aW9uU3RhY2tbdGhpcy5jb25kaXRpb25TdGFjay5sZW5ndGgtMV0pO1xuICAgICAgICAgICAgICAgIGlmICh0b2tlbikgcmV0dXJuIHRva2VuO1xuICAgICAgICAgICAgICAgIGVsc2UgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmICh0aGlzLl9pbnB1dCA9PT0gXCJcIikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuRU9GO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5wYXJzZUVycm9yKCdMZXhpY2FsIGVycm9yIG9uIGxpbmUgJysodGhpcy55eWxpbmVubysxKSsnLiBVbnJlY29nbml6ZWQgdGV4dC5cXG4nK3RoaXMuc2hvd1Bvc2l0aW9uKCksXG4gICAgICAgICAgICAgICAgICAgIHt0ZXh0OiBcIlwiLCB0b2tlbjogbnVsbCwgbGluZTogdGhpcy55eWxpbmVub30pO1xuICAgICAgICB9XG4gICAgfSxcbmxleDpmdW5jdGlvbiBsZXgoKSB7XG4gICAgICAgIHZhciByID0gdGhpcy5uZXh0KCk7XG4gICAgICAgIGlmICh0eXBlb2YgciAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIHJldHVybiByO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubGV4KCk7XG4gICAgICAgIH1cbiAgICB9LFxuYmVnaW46ZnVuY3Rpb24gYmVnaW4oY29uZGl0aW9uKSB7XG4gICAgICAgIHRoaXMuY29uZGl0aW9uU3RhY2sucHVzaChjb25kaXRpb24pO1xuICAgIH0sXG5wb3BTdGF0ZTpmdW5jdGlvbiBwb3BTdGF0ZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29uZGl0aW9uU3RhY2sucG9wKCk7XG4gICAgfSxcbl9jdXJyZW50UnVsZXM6ZnVuY3Rpb24gX2N1cnJlbnRSdWxlcygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29uZGl0aW9uc1t0aGlzLmNvbmRpdGlvblN0YWNrW3RoaXMuY29uZGl0aW9uU3RhY2subGVuZ3RoLTFdXS5ydWxlcztcbiAgICB9LFxudG9wU3RhdGU6ZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb25kaXRpb25TdGFja1t0aGlzLmNvbmRpdGlvblN0YWNrLmxlbmd0aC0yXTtcbiAgICB9LFxucHVzaFN0YXRlOmZ1bmN0aW9uIGJlZ2luKGNvbmRpdGlvbikge1xuICAgICAgICB0aGlzLmJlZ2luKGNvbmRpdGlvbik7XG4gICAgfX0pO1xubGV4ZXIucGVyZm9ybUFjdGlvbiA9IGZ1bmN0aW9uIGFub255bW91cyh5eSx5eV8sJGF2b2lkaW5nX25hbWVfY29sbGlzaW9ucyxZWV9TVEFSVCkge1xuXG52YXIgWVlTVEFURT1ZWV9TVEFSVDtcbnN3aXRjaCgkYXZvaWRpbmdfbmFtZV9jb2xsaXNpb25zKSB7XG5jYXNlIDA6Lyogc2tpcCB3aGl0ZXNwYWNlICovXG5icmVhaztcbmNhc2UgMTpyZXR1cm4gMjBcbmJyZWFrO1xuY2FzZSAyOnJldHVybiAxOVxuYnJlYWs7XG5jYXNlIDM6cmV0dXJuIDhcbmJyZWFrO1xuY2FzZSA0OnJldHVybiA5XG5icmVhaztcbmNhc2UgNTpyZXR1cm4gNlxuYnJlYWs7XG5jYXNlIDY6cmV0dXJuIDdcbmJyZWFrO1xuY2FzZSA3OnJldHVybiAxMVxuYnJlYWs7XG5jYXNlIDg6cmV0dXJuIDEzXG5icmVhaztcbmNhc2UgOTpyZXR1cm4gMTBcbmJyZWFrO1xuY2FzZSAxMDpyZXR1cm4gMTJcbmJyZWFrO1xuY2FzZSAxMTpyZXR1cm4gMTRcbmJyZWFrO1xuY2FzZSAxMjpyZXR1cm4gMTVcbmJyZWFrO1xuY2FzZSAxMzpyZXR1cm4gMTZcbmJyZWFrO1xuY2FzZSAxNDpyZXR1cm4gMTdcbmJyZWFrO1xuY2FzZSAxNTpyZXR1cm4gMThcbmJyZWFrO1xuY2FzZSAxNjpyZXR1cm4gNVxuYnJlYWs7XG5jYXNlIDE3OnJldHVybiAnSU5WQUxJRCdcbmJyZWFrO1xufVxufTtcbmxleGVyLnJ1bGVzID0gWy9eXFxzKy8sL15bMC05XSsoXFwuWzAtOV0rKT9cXGIvLC9eblxcYi8sL15cXHxcXHwvLC9eJiYvLC9eXFw/LywvXjovLC9ePD0vLC9ePj0vLC9ePC8sL14+LywvXiE9LywvXj09LywvXiUvLC9eXFwoLywvXlxcKS8sL14kLywvXi4vXTtcbmxleGVyLmNvbmRpdGlvbnMgPSB7XCJJTklUSUFMXCI6e1wicnVsZXNcIjpbMCwxLDIsMyw0LDUsNiw3LDgsOSwxMCwxMSwxMiwxMywxNCwxNSwxNiwxN10sXCJpbmNsdXNpdmVcIjp0cnVlfX07cmV0dXJuIGxleGVyO30pKClcbnBhcnNlci5sZXhlciA9IGxleGVyO1xucmV0dXJuIHBhcnNlcjtcbn0pKCk7XG4vLyBFbmQgcGFyc2VyXG5cbiAgLy8gSGFuZGxlIG5vZGUsIGFtZCwgYW5kIGdsb2JhbCBzeXN0ZW1zXG4gIGlmICh0eXBlb2YgZXhwb3J0cyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICBpZiAodHlwZW9mIG1vZHVsZSAhPT0gJ3VuZGVmaW5lZCcgJiYgbW9kdWxlLmV4cG9ydHMpIHtcbiAgICAgIGV4cG9ydHMgPSBtb2R1bGUuZXhwb3J0cyA9IEplZDtcbiAgICB9XG4gICAgZXhwb3J0cy5KZWQgPSBKZWQ7XG4gIH1cbiAgZWxzZSB7XG4gICAgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkge1xuICAgICAgZGVmaW5lKGZ1bmN0aW9uKCkge1xuICAgICAgICByZXR1cm4gSmVkO1xuICAgICAgfSk7XG4gICAgfVxuICAgIC8vIExlYWsgYSBnbG9iYWwgcmVnYXJkbGVzcyBvZiBtb2R1bGUgc3lzdGVtXG4gICAgcm9vdFsnSmVkJ10gPSBKZWQ7XG4gIH1cblxufSkodGhpcyk7XG4iLCJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG1lbWl6ZSggZm4sIG9wdGlvbnMgKSB7XG5cdHZhciBzaXplID0gMCxcblx0XHRtYXhTaXplLCBoZWFkLCB0YWlsO1xuXG5cdGlmICggb3B0aW9ucyAmJiBvcHRpb25zLm1heFNpemUgKSB7XG5cdFx0bWF4U2l6ZSA9IG9wdGlvbnMubWF4U2l6ZTtcblx0fVxuXG5cdGZ1bmN0aW9uIG1lbW9pemVkKCAvKiAuLi5hcmdzICovICkge1xuXHRcdHZhciBub2RlID0gaGVhZCxcblx0XHRcdGxlbiA9IGFyZ3VtZW50cy5sZW5ndGgsXG5cdFx0XHRhcmdzLCBpO1xuXG5cdFx0c2VhcmNoQ2FjaGU6IHdoaWxlICggbm9kZSApIHtcblx0XHRcdC8vIFBlcmZvcm0gYSBzaGFsbG93IGVxdWFsaXR5IHRlc3QgdG8gY29uZmlybSB0aGF0IHdoZXRoZXIgdGhlIG5vZGVcblx0XHRcdC8vIHVuZGVyIHRlc3QgaXMgYSBjYW5kaWRhdGUgZm9yIHRoZSBhcmd1bWVudHMgcGFzc2VkLiBUd28gYXJyYXlzXG5cdFx0XHQvLyBhcmUgc2hhbGxvd2x5IGVxdWFsIGlmIHRoZWlyIGxlbmd0aCBtYXRjaGVzIGFuZCBlYWNoIGVudHJ5IGlzXG5cdFx0XHQvLyBzdHJpY3RseSBlcXVhbCBiZXR3ZWVuIHRoZSB0d28gc2V0cy4gQXZvaWQgYWJzdHJhY3RpbmcgdG8gYVxuXHRcdFx0Ly8gZnVuY3Rpb24gd2hpY2ggY291bGQgaW5jdXIgYW4gYXJndW1lbnRzIGxlYWtpbmcgZGVvcHRpbWl6YXRpb24uXG5cblx0XHRcdC8vIENoZWNrIHdoZXRoZXIgbm9kZSBhcmd1bWVudHMgbWF0Y2ggYXJndW1lbnRzIGxlbmd0aFxuXHRcdFx0aWYgKCBub2RlLmFyZ3MubGVuZ3RoICE9PSBhcmd1bWVudHMubGVuZ3RoICkge1xuXHRcdFx0XHRub2RlID0gbm9kZS5uZXh0O1xuXHRcdFx0XHRjb250aW51ZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gQ2hlY2sgd2hldGhlciBub2RlIGFyZ3VtZW50cyBtYXRjaCBhcmd1bWVudHMgdmFsdWVzXG5cdFx0XHRmb3IgKCBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0XHRpZiAoIG5vZGUuYXJnc1sgaSBdICE9PSBhcmd1bWVudHNbIGkgXSApIHtcblx0XHRcdFx0XHRub2RlID0gbm9kZS5uZXh0O1xuXHRcdFx0XHRcdGNvbnRpbnVlIHNlYXJjaENhY2hlO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cblx0XHRcdC8vIEF0IHRoaXMgcG9pbnQgd2UgY2FuIGFzc3VtZSB3ZSd2ZSBmb3VuZCBhIG1hdGNoXG5cblx0XHRcdC8vIFN1cmZhY2UgbWF0Y2hlZCBub2RlIHRvIGhlYWQgaWYgbm90IGFscmVhZHlcblx0XHRcdGlmICggbm9kZSAhPT0gaGVhZCApIHtcblx0XHRcdFx0Ly8gQXMgdGFpbCwgc2hpZnQgdG8gcHJldmlvdXMuIE11c3Qgb25seSBzaGlmdCBpZiBub3QgYWxzb1xuXHRcdFx0XHQvLyBoZWFkLCBzaW5jZSBpZiBib3RoIGhlYWQgYW5kIHRhaWwsIHRoZXJlIGlzIG5vIHByZXZpb3VzLlxuXHRcdFx0XHRpZiAoIG5vZGUgPT09IHRhaWwgKSB7XG5cdFx0XHRcdFx0dGFpbCA9IG5vZGUucHJldjtcblx0XHRcdFx0fVxuXG5cdFx0XHRcdC8vIEFkanVzdCBzaWJsaW5ncyB0byBwb2ludCB0byBlYWNoIG90aGVyLiBJZiBub2RlIHdhcyB0YWlsLFxuXHRcdFx0XHQvLyB0aGlzIGFsc28gaGFuZGxlcyBuZXcgdGFpbCdzIGVtcHR5IGBuZXh0YCBhc3NpZ25tZW50LlxuXHRcdFx0XHRub2RlLnByZXYubmV4dCA9IG5vZGUubmV4dDtcblx0XHRcdFx0aWYgKCBub2RlLm5leHQgKSB7XG5cdFx0XHRcdFx0bm9kZS5uZXh0LnByZXYgPSBub2RlLnByZXY7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRub2RlLm5leHQgPSBoZWFkO1xuXHRcdFx0XHRub2RlLnByZXYgPSBudWxsO1xuXHRcdFx0XHRoZWFkLnByZXYgPSBub2RlO1xuXHRcdFx0XHRoZWFkID0gbm9kZTtcblx0XHRcdH1cblxuXHRcdFx0Ly8gUmV0dXJuIGltbWVkaWF0ZWx5XG5cdFx0XHRyZXR1cm4gbm9kZS52YWw7XG5cdFx0fVxuXG5cdFx0Ly8gTm8gY2FjaGVkIHZhbHVlIGZvdW5kLiBDb250aW51ZSB0byBpbnNlcnRpb24gcGhhc2U6XG5cblx0XHQvLyBDcmVhdGUgYSBjb3B5IG9mIGFyZ3VtZW50cyAoYXZvaWQgbGVha2luZyBkZW9wdGltaXphdGlvbilcblx0XHRhcmdzID0gbmV3IEFycmF5KCBsZW4gKTtcblx0XHRmb3IgKCBpID0gMDsgaSA8IGxlbjsgaSsrICkge1xuXHRcdFx0YXJnc1sgaSBdID0gYXJndW1lbnRzWyBpIF07XG5cdFx0fVxuXG5cdFx0bm9kZSA9IHtcblx0XHRcdGFyZ3M6IGFyZ3MsXG5cblx0XHRcdC8vIEdlbmVyYXRlIHRoZSByZXN1bHQgZnJvbSBvcmlnaW5hbCBmdW5jdGlvblxuXHRcdFx0dmFsOiBmbi5hcHBseSggbnVsbCwgYXJncyApXG5cdFx0fTtcblxuXHRcdC8vIERvbid0IG5lZWQgdG8gY2hlY2sgd2hldGhlciBub2RlIGlzIGFscmVhZHkgaGVhZCwgc2luY2UgaXQgd291bGRcblx0XHQvLyBoYXZlIGJlZW4gcmV0dXJuZWQgYWJvdmUgYWxyZWFkeSBpZiBpdCB3YXNcblxuXHRcdC8vIFNoaWZ0IGV4aXN0aW5nIGhlYWQgZG93biBsaXN0XG5cdFx0aWYgKCBoZWFkICkge1xuXHRcdFx0aGVhZC5wcmV2ID0gbm9kZTtcblx0XHRcdG5vZGUubmV4dCA9IGhlYWQ7XG5cdFx0fSBlbHNlIHtcblx0XHRcdC8vIElmIG5vIGhlYWQsIGZvbGxvd3MgdGhhdCB0aGVyZSdzIG5vIHRhaWwgKGF0IGluaXRpYWwgb3IgcmVzZXQpXG5cdFx0XHR0YWlsID0gbm9kZTtcblx0XHR9XG5cblx0XHQvLyBUcmltIHRhaWwgaWYgd2UncmUgcmVhY2hlZCBtYXggc2l6ZSBhbmQgYXJlIHBlbmRpbmcgY2FjaGUgaW5zZXJ0aW9uXG5cdFx0aWYgKCBzaXplID09PSBtYXhTaXplICkge1xuXHRcdFx0dGFpbCA9IHRhaWwucHJldjtcblx0XHRcdHRhaWwubmV4dCA9IG51bGw7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHNpemUrKztcblx0XHR9XG5cblx0XHRoZWFkID0gbm9kZTtcblxuXHRcdHJldHVybiBub2RlLnZhbDtcblx0fVxuXG5cdG1lbW9pemVkLmNsZWFyID0gZnVuY3Rpb24oKSB7XG5cdFx0aGVhZCA9IG51bGw7XG5cdFx0dGFpbCA9IG51bGw7XG5cdFx0c2l6ZSA9IDA7XG5cdH07XG5cblx0aWYgKCBwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gJ3Rlc3QnICkge1xuXHRcdC8vIENhY2hlIGlzIG5vdCBleHBvc2VkIGluIHRoZSBwdWJsaWMgQVBJLCBidXQgdXNlZCBpbiB0ZXN0cyB0byBlbnN1cmVcblx0XHQvLyBleHBlY3RlZCBsaXN0IHByb2dyZXNzaW9uXG5cdFx0bWVtb2l6ZWQuZ2V0Q2FjaGUgPSBmdW5jdGlvbigpIHtcblx0XHRcdHJldHVybiBbIGhlYWQsIHRhaWwsIHNpemUgXTtcblx0XHR9O1xuXHR9XG5cblx0cmV0dXJuIG1lbW9pemVkO1xufTtcbiJdLCJzb3VyY2VSb290IjoiIn0= \ No newline at end of file diff --git a/assets/dist/ee-eejs.6fc6d91b0188c3e4ca5a.dist.js b/assets/dist/ee-eejs.6fc6d91b0188c3e4ca5a.dist.js new file mode 100644 index 00000000000..8c3ccdfb138 --- /dev/null +++ b/assets/dist/ee-eejs.6fc6d91b0188c3e4ca5a.dist.js @@ -0,0 +1,5 @@ +this.eejs=function(t){var e={};function n(r){if(e[r])return e[r].exports;var i=e[r]={i:r,l:!1,exports:{}};return t[r].call(i.exports,i,i.exports,n),i.l=!0,i.exports}return n.m=t,n.c=e,n.d=function(t,e,r){n.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:r})},n.r=function(t){Object.defineProperty(t,"__esModule",{value:!0})},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=40)}([function(t,e,n){ +/** + * @preserve jed.js https://github.com/SlexAxton/Jed + */ +!function(n,r){var i=Array.prototype,o=Object.prototype,s=i.slice,a=o.hasOwnProperty,u=i.forEach,c={},l={forEach:function(t,e,n){var r,i,o;if(null!==t)if(u&&t.forEach===u)t.forEach(e,n);else if(t.length===+t.length){for(r=0,i=t.length;rs.length?(this.options.missing_key_callback&&this.options.missing_key_callback(c,t),a=[n,r],!0===this.options.debug&&console.log(a[f(y)(i)]),a[f()(i)]):(a=s[u])||(a=[n,r])[f()(i)]}});var d,y,g=function(){function t(t){return Object.prototype.toString.call(t).slice(8,-1).toLowerCase()}function e(t,e){for(var n=[];e>0;n[--e]=t);return n.join("")}var n=function(){return n.cache.hasOwnProperty(arguments[0])||(n.cache[arguments[0]]=n.parse(arguments[0])),n.format.call(null,n.cache[arguments[0]],arguments)};return n.format=function(n,r){var i,o,s,a,u,c,l,h=1,f=n.length,p="",d=[];for(o=0;o=0?"+"+i:i,c=a[4]?"0"==a[4]?"0":a[4].charAt(1):" ",l=a[6]-String(i).length,u=a[6]?e(c,l):"",d.push(a[5]?i+u:u+i)}return d.join("")},n.cache={},n.parse=function(t){for(var e=t,n=[],r=[],i=0;e;){if(null!==(n=/^[^\x25]+/.exec(e)))r.push(n[0]);else if(null!==(n=/^\x25{2}/.exec(e)))r.push("%");else{if(null===(n=/^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosuxX])/.exec(e)))throw"[sprintf] huh?";if(n[2]){i|=1;var o=[],s=n[2],a=[];if(null===(a=/^([a-z_][a-z_\d]*)/i.exec(s)))throw"[sprintf] huh?";for(o.push(a[1]);""!==(s=s.substring(a[0].length));)if(null!==(a=/^\.([a-z_][a-z_\d]*)/i.exec(s)))o.push(a[1]);else{if(null===(a=/^\[(\d+)\]/.exec(s)))throw"[sprintf] huh?";o.push(a[1])}n[2]=o}else i|=2;if(3===i)throw"[sprintf] mixing positional and named placeholders is not (yet) supported";r.push(n)}e=e.substring(n[0].length)}return r},n}();h.parse_plural=function(t,e){return t=t.replace(/n/g,e),h.parse_expression(t)},h.sprintf=function(t,e){return"[object Array]"=={}.toString.call(e)?function(t,e){return e.unshift(t),g.apply(null,e)}(t,[].slice.call(e)):g.apply(this,[].slice.call(arguments))},h.prototype.sprintf=function(){return h.sprintf.apply(this,arguments)},h.PF={},h.PF.parse=function(t){var e=h.PF.extractPluralExpr(t);return h.PF.parser.parse.call(h.PF.parser,e)},h.PF.compile=function(t){var e=h.PF.parse(t);return function(t){return!0===(n=h.PF.interpreter(e)(t))?1:n||0;var n}},h.PF.interpreter=function(t){return function(e){switch(t.type){case"GROUP":return h.PF.interpreter(t.expr)(e);case"TERNARY":return h.PF.interpreter(t.expr)(e)?h.PF.interpreter(t.truthy)(e):h.PF.interpreter(t.falsey)(e);case"OR":return h.PF.interpreter(t.left)(e)||h.PF.interpreter(t.right)(e);case"AND":return h.PF.interpreter(t.left)(e)&&h.PF.interpreter(t.right)(e);case"LT":return h.PF.interpreter(t.left)(e)h.PF.interpreter(t.right)(e);case"LTE":return h.PF.interpreter(t.left)(e)<=h.PF.interpreter(t.right)(e);case"GTE":return h.PF.interpreter(t.left)(e)>=h.PF.interpreter(t.right)(e);case"EQ":return h.PF.interpreter(t.left)(e)==h.PF.interpreter(t.right)(e);case"NEQ":return h.PF.interpreter(t.left)(e)!=h.PF.interpreter(t.right)(e);case"MOD":return h.PF.interpreter(t.left)(e)%h.PF.interpreter(t.right)(e);case"VAR":return e;case"NUM":return t.val;default:throw new Error("Invalid Token found.")}}},h.PF.extractPluralExpr=function(t){t=t.replace(/^\s\s*/,"").replace(/\s\s*$/,""),/;\s*$/.test(t)||(t=t.concat(";"));var e,n=/nplurals\=(\d+);/,r=t.match(n);if(!(r.length>1))throw new Error("nplurals not found in plural_forms string: "+t);if(r[1],!((e=(t=t.replace(n,"")).match(/plural\=(.*);/))&&e.length>1))throw new Error("`plural` expression not found: "+t);return e[1]},h.PF.parser=(d={trace:function(){},yy:{},symbols_:{error:2,expressions:3,e:4,EOF:5,"?":6,":":7,"||":8,"&&":9,"<":10,"<=":11,">":12,">=":13,"!=":14,"==":15,"%":16,"(":17,")":18,n:19,NUMBER:20,$accept:0,$end:1},terminals_:{2:"error",5:"EOF",6:"?",7:":",8:"||",9:"&&",10:"<",11:"<=",12:">",13:">=",14:"!=",15:"==",16:"%",17:"(",18:")",19:"n",20:"NUMBER"},productions_:[0,[3,2],[4,5],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,3],[4,1],[4,1]],performAction:function(t,e,n,r,i,o,s){var a=o.length-1;switch(i){case 1:return{type:"GROUP",expr:o[a-1]};case 2:this.$={type:"TERNARY",expr:o[a-4],truthy:o[a-2],falsey:o[a]};break;case 3:this.$={type:"OR",left:o[a-2],right:o[a]};break;case 4:this.$={type:"AND",left:o[a-2],right:o[a]};break;case 5:this.$={type:"LT",left:o[a-2],right:o[a]};break;case 6:this.$={type:"LTE",left:o[a-2],right:o[a]};break;case 7:this.$={type:"GT",left:o[a-2],right:o[a]};break;case 8:this.$={type:"GTE",left:o[a-2],right:o[a]};break;case 9:this.$={type:"NEQ",left:o[a-2],right:o[a]};break;case 10:this.$={type:"EQ",left:o[a-2],right:o[a]};break;case 11:this.$={type:"MOD",left:o[a-2],right:o[a]};break;case 12:this.$={type:"GROUP",expr:o[a-1]};break;case 13:this.$={type:"VAR"};break;case 14:this.$={type:"NUM",val:Number(t)}}},table:[{3:1,4:2,17:[1,3],19:[1,4],20:[1,5]},{1:[3]},{5:[1,6],6:[1,7],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16]},{4:17,17:[1,3],19:[1,4],20:[1,5]},{5:[2,13],6:[2,13],7:[2,13],8:[2,13],9:[2,13],10:[2,13],11:[2,13],12:[2,13],13:[2,13],14:[2,13],15:[2,13],16:[2,13],18:[2,13]},{5:[2,14],6:[2,14],7:[2,14],8:[2,14],9:[2,14],10:[2,14],11:[2,14],12:[2,14],13:[2,14],14:[2,14],15:[2,14],16:[2,14],18:[2,14]},{1:[2,1]},{4:18,17:[1,3],19:[1,4],20:[1,5]},{4:19,17:[1,3],19:[1,4],20:[1,5]},{4:20,17:[1,3],19:[1,4],20:[1,5]},{4:21,17:[1,3],19:[1,4],20:[1,5]},{4:22,17:[1,3],19:[1,4],20:[1,5]},{4:23,17:[1,3],19:[1,4],20:[1,5]},{4:24,17:[1,3],19:[1,4],20:[1,5]},{4:25,17:[1,3],19:[1,4],20:[1,5]},{4:26,17:[1,3],19:[1,4],20:[1,5]},{4:27,17:[1,3],19:[1,4],20:[1,5]},{6:[1,7],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[1,28]},{6:[1,7],7:[1,29],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16]},{5:[2,3],6:[2,3],7:[2,3],8:[2,3],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,3]},{5:[2,4],6:[2,4],7:[2,4],8:[2,4],9:[2,4],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,4]},{5:[2,5],6:[2,5],7:[2,5],8:[2,5],9:[2,5],10:[2,5],11:[2,5],12:[2,5],13:[2,5],14:[2,5],15:[2,5],16:[1,16],18:[2,5]},{5:[2,6],6:[2,6],7:[2,6],8:[2,6],9:[2,6],10:[2,6],11:[2,6],12:[2,6],13:[2,6],14:[2,6],15:[2,6],16:[1,16],18:[2,6]},{5:[2,7],6:[2,7],7:[2,7],8:[2,7],9:[2,7],10:[2,7],11:[2,7],12:[2,7],13:[2,7],14:[2,7],15:[2,7],16:[1,16],18:[2,7]},{5:[2,8],6:[2,8],7:[2,8],8:[2,8],9:[2,8],10:[2,8],11:[2,8],12:[2,8],13:[2,8],14:[2,8],15:[2,8],16:[1,16],18:[2,8]},{5:[2,9],6:[2,9],7:[2,9],8:[2,9],9:[2,9],10:[2,9],11:[2,9],12:[2,9],13:[2,9],14:[2,9],15:[2,9],16:[1,16],18:[2,9]},{5:[2,10],6:[2,10],7:[2,10],8:[2,10],9:[2,10],10:[2,10],11:[2,10],12:[2,10],13:[2,10],14:[2,10],15:[2,10],16:[1,16],18:[2,10]},{5:[2,11],6:[2,11],7:[2,11],8:[2,11],9:[2,11],10:[2,11],11:[2,11],12:[2,11],13:[2,11],14:[2,11],15:[2,11],16:[2,11],18:[2,11]},{5:[2,12],6:[2,12],7:[2,12],8:[2,12],9:[2,12],10:[2,12],11:[2,12],12:[2,12],13:[2,12],14:[2,12],15:[2,12],16:[2,12],18:[2,12]},{4:30,17:[1,3],19:[1,4],20:[1,5]},{5:[2,2],6:[1,7],7:[2,2],8:[1,8],9:[1,9],10:[1,10],11:[1,11],12:[1,12],13:[1,13],14:[1,14],15:[1,15],16:[1,16],18:[2,2]}],defaultActions:{6:[2,1]},parseError:function(t,e){throw new Error(t)},parse:function(t){var e=this,n=[0],r=[null],i=[],o=this.table,s="",a=0,u=0,c=0;this.lexer.setInput(t),this.lexer.yy=this.yy,this.yy.lexer=this.lexer,void 0===this.lexer.yylloc&&(this.lexer.yylloc={});var l=this.lexer.yylloc;function h(){var t;return"number"!=typeof(t=e.lexer.lex()||1)&&(t=e.symbols_[t]||t),t}i.push(l),"function"==typeof this.yy.parseError&&(this.parseError=this.yy.parseError);for(var f,p,d,y,g,x,v,m,_,b,w={};;){if(d=n[n.length-1],this.defaultActions[d]?y=this.defaultActions[d]:(null==f&&(f=h()),y=o[d]&&o[d][f]),void 0===y||!y.length||!y[0]){if(!c){for(x in _=[],o[d])this.terminals_[x]&&x>2&&_.push("'"+this.terminals_[x]+"'");var P="";P=this.lexer.showPosition?"Parse error on line "+(a+1)+":\n"+this.lexer.showPosition()+"\nExpecting "+_.join(", ")+", got '"+this.terminals_[f]+"'":"Parse error on line "+(a+1)+": Unexpected "+(1==f?"end of input":"'"+(this.terminals_[f]||f)+"'"),this.parseError(P,{text:this.lexer.match,token:this.terminals_[f]||f,line:this.lexer.yylineno,loc:l,expected:_})}if(3==c){if(1==f)throw new Error(P||"Parsing halted.");u=this.lexer.yyleng,s=this.lexer.yytext,a=this.lexer.yylineno,l=this.lexer.yylloc,f=h()}for(;!(2..toString()in o[d]);){if(0==d)throw new Error(P||"Parsing halted.");b=1,n.length=n.length-2*b,r.length=r.length-b,i.length=i.length-b,d=n[n.length-1]}p=f,f=2,y=o[d=n[n.length-1]]&&o[d][2],c=3}if(y[0]instanceof Array&&y.length>1)throw new Error("Parse Error: multiple actions possible at state: "+d+", token: "+f);switch(y[0]){case 1:n.push(f),r.push(this.lexer.yytext),i.push(this.lexer.yylloc),n.push(y[1]),f=null,p?(f=p,p=null):(u=this.lexer.yyleng,s=this.lexer.yytext,a=this.lexer.yylineno,l=this.lexer.yylloc,c>0&&c--);break;case 2:if(v=this.productions_[y[1]][1],w.$=r[r.length-v],w._$={first_line:i[i.length-(v||1)].first_line,last_line:i[i.length-1].last_line,first_column:i[i.length-(v||1)].first_column,last_column:i[i.length-1].last_column},void 0!==(g=this.performAction.call(w,s,u,a,this.yy,y[1],r,i)))return g;v&&(n=n.slice(0,-1*v*2),r=r.slice(0,-1*v),i=i.slice(0,-1*v)),n.push(this.productions_[y[1]][0]),r.push(w.$),i.push(w._$),m=o[n[n.length-2]][n[n.length-1]],n.push(m);break;case 3:return!0}}return!0}},y=function(){var t={EOF:1,parseError:function(t,e){if(!this.yy.parseError)throw new Error(t);this.yy.parseError(t,e)},setInput:function(t){return this._input=t,this._more=this._less=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this},input:function(){var t=this._input[0];return this.yytext+=t,this.yyleng++,this.match+=t,this.matched+=t,t.match(/\n/)&&this.yylineno++,this._input=this._input.slice(1),t},unput:function(t){return this._input=t+this._input,this},more:function(){return this._more=!0,this},pastInput:function(){var t=this.matched.substr(0,this.matched.length-this.match.length);return(t.length>20?"...":"")+t.substr(-20).replace(/\n/g,"")},upcomingInput:function(){var t=this.match;return t.length<20&&(t+=this._input.substr(0,20-t.length)),(t.substr(0,20)+(t.length>20?"...":"")).replace(/\n/g,"")},showPosition:function(){var t=this.pastInput(),e=new Array(t.length+1).join("-");return t+this.upcomingInput()+"\n"+e+"^"},next:function(){if(this.done)return this.EOF;var t,e;this._input||(this.done=!0),this._more||(this.yytext="",this.match="");for(var n=this._currentRules(),r=0;r=/,/^/,/^!=/,/^==/,/^%/,/^\(/,/^\)/,/^$/,/^./],conditions:{INITIAL:{rules:[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],inclusive:!0}}};return t}(),d.lexer=y,d),void 0!==t&&t.exports&&(e=t.exports=h),e.Jed=h}()},function(t,e){t.exports=function(t){try{return!!t()}catch(t){return!0}}},function(t,e,n){t.exports=!n(1)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},function(t,e){t.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},function(t,e){var n=t.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=n)},function(t,e,n){t.exports=function(t,e){var n,r,i,o=0;function s(){var e,s,a=r,u=arguments.length;t:for(;a;){if(a.args.length===arguments.length){for(s=0;s0?r:n)(t)}},function(t,e){t.exports=function(t){if(void 0==t)throw TypeError("Can't call method on "+t);return t}},function(t,e,n){var r=n(24);t.exports=Object("z").propertyIsEnumerable(0)?Object:function(t){return"String"==r(t)?t.split(""):Object(t)}},function(t,e,n){var r=n(8),i=n(7);t.exports=function(t){return r(i(t))}},function(t,e){var n={}.hasOwnProperty;t.exports=function(t,e){return n.call(t,e)}},function(t,e){var n=t.exports={version:"2.5.5"};"number"==typeof __e&&(__e=n)},function(t,e,n){t.exports={default:n(39),__esModule:!0}},function(t,e,n){"use strict";n.r(e);var r={};n.d(r,"setLocaleData",function(){return f}),n.d(r,"getI18n",function(){return p}),n.d(r,"dcnpgettext",function(){return d}),n.d(r,"__",function(){return y}),n.d(r,"_x",function(){return g}),n.d(r,"_n",function(){return x}),n.d(r,"_nx",function(){return v}),n.d(r,"sprintf",function(){return m});var i=n(12),o=n.n(i),s=n(0),a=n.n(s),u=n(5),c=n.n(u),l=void 0,h=c()(console.error);function f(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{"":{}},e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"default";l||(l=new a.a({domain:"default",locale_data:{default:{}}})),l.options.locale_data[e]=o()({},l.options.locale_data[e],t)}function p(){return l||f(),l}var d=c()(function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"default",e=arguments[1],n=arguments[2],r=arguments[3],i=arguments[4];try{return p().dcnpgettext(t,e,n,r,i)}catch(t){return h("Jed localization error: \n\n"+t.toString()),n}});function y(t,e){return d(e,void 0,t)}function g(t,e,n){return d(n,e,t)}function x(t,e,n,r){return d(r,void 0,t,e,n)}function v(t,e,n,r,i){return d(i,r,t,e,n)}function m(t){try{for(var e=arguments.length,n=Array(e>1?e-1:0),r=1;r0?i(r(t),9007199254740991):0}},function(t,e,n){var r=n(9),i=n(22),o=n(21);t.exports=function(t){return function(e,n,s){var a,u=r(e),c=i(u.length),l=o(s,c);if(t&&n!=n){for(;c>l;)if((a=u[l++])!=a)return!0}else for(;c>l;l++)if((t||l in u)&&u[l]===n)return t||l||0;return!t&&-1}}},function(t,e){var n={}.toString;t.exports=function(t){return n.call(t).slice(8,-1)}},function(t,e,n){var r=n(10),i=n(9),o=n(23)(!1),s=n(20)("IE_PROTO");t.exports=function(t,e){var n,a=i(t),u=0,c=[];for(n in a)n!=s&&r(a,n)&&c.push(n);for(;e.length>u;)r(a,n=e[u++])&&(~o(c,n)||c.push(n));return c}},function(t,e,n){var r=n(25),i=n(17);t.exports=Object.keys||function(t){return r(t,i)}},function(t,e,n){"use strict";var r=n(26),i=n(16),o=n(15),s=n(14),a=n(8),u=Object.assign;t.exports=!u||n(1)(function(){var t={},e={},n=Symbol(),r="abcdefghijklmnopqrst";return t[n]=7,r.split("").forEach(function(t){e[t]=t}),7!=u({},t)[n]||Object.keys(u({},e)).join("")!=r})?function(t,e){for(var n=s(t),u=arguments.length,c=1,l=i.f,h=o.f;u>c;)for(var f,p=a(arguments[c++]),d=l?r(p).concat(l(p)):r(p),y=d.length,g=0;y>g;)h.call(p,f=d[g++])&&(n[f]=p[f]);return n}:u},function(t,e){t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},function(t,e,n){var r=n(3);t.exports=function(t,e){if(!r(t))return t;var n,i;if(e&&"function"==typeof(n=t.toString)&&!r(i=n.call(t)))return i;if("function"==typeof(n=t.valueOf)&&!r(i=n.call(t)))return i;if(!e&&"function"==typeof(n=t.toString)&&!r(i=n.call(t)))return i;throw TypeError("Can't convert object to primitive value")}},function(t,e,n){var r=n(3),i=n(4).document,o=r(i)&&r(i.createElement);t.exports=function(t){return o?i.createElement(t):{}}},function(t,e,n){t.exports=!n(2)&&!n(1)(function(){return 7!=Object.defineProperty(n(30)("div"),"a",{get:function(){return 7}}).a})},function(t,e,n){var r=n(3);t.exports=function(t){if(!r(t))throw TypeError(t+" is not an object!");return t}},function(t,e,n){var r=n(32),i=n(31),o=n(29),s=Object.defineProperty;e.f=n(2)?Object.defineProperty:function(t,e,n){if(r(t),e=o(e,!0),r(n),i)try{return s(t,e,n)}catch(t){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(t[e]=n.value),t}},function(t,e,n){var r=n(33),i=n(28);t.exports=n(2)?function(t,e,n){return r.f(t,e,i(1,n))}:function(t,e,n){return t[e]=n,t}},function(t,e){t.exports=function(t){if("function"!=typeof t)throw TypeError(t+" is not a function!");return t}},function(t,e,n){var r=n(35);t.exports=function(t,e,n){if(r(t),void 0===e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 2:return function(n,r){return t.call(e,n,r)};case 3:return function(n,r,i){return t.call(e,n,r,i)}}return function(){return t.apply(e,arguments)}}},function(t,e,n){var r=n(4),i=n(11),o=n(36),s=n(34),a=n(10),u=function(t,e,n){var c,l,h,f=t&u.F,p=t&u.G,d=t&u.S,y=t&u.P,g=t&u.B,x=t&u.W,v=p?i:i[e]||(i[e]={}),m=v.prototype,_=p?r:d?r[e]:(r[e]||{}).prototype;for(c in p&&(n=e),n)(l=!f&&_&&void 0!==_[c])&&a(v,c)||(h=l?_[c]:n[c],v[c]=p&&"function"!=typeof _[c]?n[c]:g&&l?o(h,r):x&&_[c]==h?function(t){var e=function(e,n,r){if(this instanceof t){switch(arguments.length){case 0:return new t;case 1:return new t(e);case 2:return new t(e,n)}return new t(e,n,r)}return t.apply(this,arguments)};return e.prototype=t.prototype,e}(h):y&&"function"==typeof h?o(Function.call,h):h,y&&((v.virtual||(v.virtual={}))[c]=h,t&u.R&&m&&!m[c]&&s(m,c,h)))};u.F=1,u.G=2,u.S=4,u.P=8,u.B=16,u.W=32,u.U=64,u.R=128,t.exports=u},function(t,e,n){var r=n(37);r(r.S+r.F,"Object",{assign:n(27)})},function(t,e,n){n(38),t.exports=n(11).Object.assign},function(t,e,n){t.exports=n(13)}]); \ No newline at end of file diff --git a/assets/dist/ee-manifest.3b66c2f77d3b01c1b09a.dist.js b/assets/dist/ee-manifest.3b66c2f77d3b01c1b09a.dist.js deleted file mode 100644 index bfde85f1a41..00000000000 --- a/assets/dist/ee-manifest.3b66c2f77d3b01c1b09a.dist.js +++ /dev/null @@ -1,137 +0,0 @@ -/******/ (function(modules) { // webpackBootstrap -/******/ // install a JSONP callback for chunk loading -/******/ function webpackJsonpCallback(data) { -/******/ var chunkIds = data[0]; -/******/ var moreModules = data[1]; -/******/ var executeModules = data[2]; -/******/ // add "moreModules" to the modules object, -/******/ // then flag all "chunkIds" as loaded and fire callback -/******/ var moduleId, chunkId, i = 0, resolves = []; -/******/ for(;i < chunkIds.length; i++) { -/******/ chunkId = chunkIds[i]; -/******/ if(installedChunks[chunkId]) { -/******/ resolves.push(installedChunks[chunkId][0]); -/******/ } -/******/ installedChunks[chunkId] = 0; -/******/ } -/******/ for(moduleId in moreModules) { -/******/ if(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) { -/******/ modules[moduleId] = moreModules[moduleId]; -/******/ } -/******/ } -/******/ if(parentJsonpFunction) parentJsonpFunction(data); -/******/ while(resolves.length) { -/******/ resolves.shift()(); -/******/ } -/******/ -/******/ // add entry modules from loaded chunk to deferred list -/******/ deferredModules.push.apply(deferredModules, executeModules || []); -/******/ -/******/ // run deferred modules when all chunks ready -/******/ return checkDeferredModules(); -/******/ }; -/******/ function checkDeferredModules() { -/******/ var result; -/******/ for(var i = 0; i < deferredModules.length; i++) { -/******/ var deferredModule = deferredModules[i]; -/******/ var fulfilled = true; -/******/ for(var j = 1; j < deferredModule.length; j++) { -/******/ var depId = deferredModule[j]; -/******/ if(installedChunks[depId] !== 0) fulfilled = false; -/******/ } -/******/ if(fulfilled) { -/******/ deferredModules.splice(i--, 1); -/******/ result = __webpack_require__(__webpack_require__.s = deferredModule[0]); -/******/ } -/******/ } -/******/ return result; -/******/ } -/******/ -/******/ // The module cache -/******/ var installedModules = {}; -/******/ -/******/ // object to store loaded and loading chunks -/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched -/******/ // Promise = chunk loading, 0 = chunk loaded -/******/ var installedChunks = { -/******/ "manifest": 0 -/******/ }; -/******/ -/******/ var deferredModules = []; -/******/ -/******/ // The require function -/******/ function __webpack_require__(moduleId) { -/******/ -/******/ // Check if module is in cache -/******/ if(installedModules[moduleId]) { -/******/ return installedModules[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = installedModules[moduleId] = { -/******/ i: moduleId, -/******/ l: false, -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); -/******/ -/******/ // Flag the module as loaded -/******/ module.l = true; -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/******/ -/******/ // expose the modules object (__webpack_modules__) -/******/ __webpack_require__.m = modules; -/******/ -/******/ // expose the module cache -/******/ __webpack_require__.c = installedModules; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { -/******/ configurable: false, -/******/ enumerable: true, -/******/ get: getter -/******/ }); -/******/ } -/******/ }; -/******/ -/******/ // define __esModule on exports -/******/ __webpack_require__.r = function(exports) { -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ -/******/ // getDefaultExport function for compatibility with non-harmony modules -/******/ __webpack_require__.n = function(module) { -/******/ var getter = module && module.__esModule ? -/******/ function getDefault() { return module['default']; } : -/******/ function getModuleExports() { return module; }; -/******/ __webpack_require__.d(getter, 'a', getter); -/******/ return getter; -/******/ }; -/******/ -/******/ // Object.prototype.hasOwnProperty.call -/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; -/******/ -/******/ // __webpack_public_path__ -/******/ __webpack_require__.p = ""; -/******/ -/******/ var jsonpArray = window["webpackJsonp"] = window["webpackJsonp"] || []; -/******/ var oldJsonpFunction = jsonpArray.push.bind(jsonpArray); -/******/ jsonpArray.push = webpackJsonpCallback; -/******/ jsonpArray = jsonpArray.slice(); -/******/ for(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]); -/******/ var parentJsonpFunction = oldJsonpFunction; -/******/ -/******/ -/******/ // run deferred modules from other chunks -/******/ checkDeferredModules(); -/******/ }) -/************************************************************************/ -/******/ ([]); -//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vd2VicGFjay9ib290c3RyYXAiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBUSxvQkFBb0I7QUFDNUI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHlCQUFpQiw0QkFBNEI7QUFDN0M7QUFDQTtBQUNBLDBCQUFrQiwyQkFBMkI7QUFDN0M7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFLO0FBQ0w7QUFDQTs7QUFFQTtBQUNBO0FBQ0EseURBQWlELGNBQWM7QUFDL0Q7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsbUNBQTJCLDBCQUEwQixFQUFFO0FBQ3ZELHlDQUFpQyxlQUFlO0FBQ2hEO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDhEQUFzRCwrREFBK0Q7O0FBRXJIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBZ0IsdUJBQXVCO0FBQ3ZDOzs7QUFHQTtBQUNBIiwiZmlsZSI6ImVlLW1hbmlmZXN0LjNiNjZjMmY3N2QzYjAxYzFiMDlhLmRpc3QuanMiLCJzb3VyY2VzQ29udGVudCI6WyIgXHQvLyBpbnN0YWxsIGEgSlNPTlAgY2FsbGJhY2sgZm9yIGNodW5rIGxvYWRpbmdcbiBcdGZ1bmN0aW9uIHdlYnBhY2tKc29ucENhbGxiYWNrKGRhdGEpIHtcbiBcdFx0dmFyIGNodW5rSWRzID0gZGF0YVswXTtcbiBcdFx0dmFyIG1vcmVNb2R1bGVzID0gZGF0YVsxXTtcbiBcdFx0dmFyIGV4ZWN1dGVNb2R1bGVzID0gZGF0YVsyXTtcbiBcdFx0Ly8gYWRkIFwibW9yZU1vZHVsZXNcIiB0byB0aGUgbW9kdWxlcyBvYmplY3QsXG4gXHRcdC8vIHRoZW4gZmxhZyBhbGwgXCJjaHVua0lkc1wiIGFzIGxvYWRlZCBhbmQgZmlyZSBjYWxsYmFja1xuIFx0XHR2YXIgbW9kdWxlSWQsIGNodW5rSWQsIGkgPSAwLCByZXNvbHZlcyA9IFtdO1xuIFx0XHRmb3IoO2kgPCBjaHVua0lkcy5sZW5ndGg7IGkrKykge1xuIFx0XHRcdGNodW5rSWQgPSBjaHVua0lkc1tpXTtcbiBcdFx0XHRpZihpbnN0YWxsZWRDaHVua3NbY2h1bmtJZF0pIHtcbiBcdFx0XHRcdHJlc29sdmVzLnB1c2goaW5zdGFsbGVkQ2h1bmtzW2NodW5rSWRdWzBdKTtcbiBcdFx0XHR9XG4gXHRcdFx0aW5zdGFsbGVkQ2h1bmtzW2NodW5rSWRdID0gMDtcbiBcdFx0fVxuIFx0XHRmb3IobW9kdWxlSWQgaW4gbW9yZU1vZHVsZXMpIHtcbiBcdFx0XHRpZihPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobW9yZU1vZHVsZXMsIG1vZHVsZUlkKSkge1xuIFx0XHRcdFx0bW9kdWxlc1ttb2R1bGVJZF0gPSBtb3JlTW9kdWxlc1ttb2R1bGVJZF07XG4gXHRcdFx0fVxuIFx0XHR9XG4gXHRcdGlmKHBhcmVudEpzb25wRnVuY3Rpb24pIHBhcmVudEpzb25wRnVuY3Rpb24oZGF0YSk7XG4gXHRcdHdoaWxlKHJlc29sdmVzLmxlbmd0aCkge1xuIFx0XHRcdHJlc29sdmVzLnNoaWZ0KCkoKTtcbiBcdFx0fVxuXG4gXHRcdC8vIGFkZCBlbnRyeSBtb2R1bGVzIGZyb20gbG9hZGVkIGNodW5rIHRvIGRlZmVycmVkIGxpc3RcbiBcdFx0ZGVmZXJyZWRNb2R1bGVzLnB1c2guYXBwbHkoZGVmZXJyZWRNb2R1bGVzLCBleGVjdXRlTW9kdWxlcyB8fCBbXSk7XG5cbiBcdFx0Ly8gcnVuIGRlZmVycmVkIG1vZHVsZXMgd2hlbiBhbGwgY2h1bmtzIHJlYWR5XG4gXHRcdHJldHVybiBjaGVja0RlZmVycmVkTW9kdWxlcygpO1xuIFx0fTtcbiBcdGZ1bmN0aW9uIGNoZWNrRGVmZXJyZWRNb2R1bGVzKCkge1xuIFx0XHR2YXIgcmVzdWx0O1xuIFx0XHRmb3IodmFyIGkgPSAwOyBpIDwgZGVmZXJyZWRNb2R1bGVzLmxlbmd0aDsgaSsrKSB7XG4gXHRcdFx0dmFyIGRlZmVycmVkTW9kdWxlID0gZGVmZXJyZWRNb2R1bGVzW2ldO1xuIFx0XHRcdHZhciBmdWxmaWxsZWQgPSB0cnVlO1xuIFx0XHRcdGZvcih2YXIgaiA9IDE7IGogPCBkZWZlcnJlZE1vZHVsZS5sZW5ndGg7IGorKykge1xuIFx0XHRcdFx0dmFyIGRlcElkID0gZGVmZXJyZWRNb2R1bGVbal07XG4gXHRcdFx0XHRpZihpbnN0YWxsZWRDaHVua3NbZGVwSWRdICE9PSAwKSBmdWxmaWxsZWQgPSBmYWxzZTtcbiBcdFx0XHR9XG4gXHRcdFx0aWYoZnVsZmlsbGVkKSB7XG4gXHRcdFx0XHRkZWZlcnJlZE1vZHVsZXMuc3BsaWNlKGktLSwgMSk7XG4gXHRcdFx0XHRyZXN1bHQgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKF9fd2VicGFja19yZXF1aXJlX18ucyA9IGRlZmVycmVkTW9kdWxlWzBdKTtcbiBcdFx0XHR9XG4gXHRcdH1cbiBcdFx0cmV0dXJuIHJlc3VsdDtcbiBcdH1cblxuIFx0Ly8gVGhlIG1vZHVsZSBjYWNoZVxuIFx0dmFyIGluc3RhbGxlZE1vZHVsZXMgPSB7fTtcblxuIFx0Ly8gb2JqZWN0IHRvIHN0b3JlIGxvYWRlZCBhbmQgbG9hZGluZyBjaHVua3NcbiBcdC8vIHVuZGVmaW5lZCA9IGNodW5rIG5vdCBsb2FkZWQsIG51bGwgPSBjaHVuayBwcmVsb2FkZWQvcHJlZmV0Y2hlZFxuIFx0Ly8gUHJvbWlzZSA9IGNodW5rIGxvYWRpbmcsIDAgPSBjaHVuayBsb2FkZWRcbiBcdHZhciBpbnN0YWxsZWRDaHVua3MgPSB7XG4gXHRcdFwibWFuaWZlc3RcIjogMFxuIFx0fTtcblxuIFx0dmFyIGRlZmVycmVkTW9kdWxlcyA9IFtdO1xuXG4gXHQvLyBUaGUgcmVxdWlyZSBmdW5jdGlvblxuIFx0ZnVuY3Rpb24gX193ZWJwYWNrX3JlcXVpcmVfXyhtb2R1bGVJZCkge1xuXG4gXHRcdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuIFx0XHRpZihpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSkge1xuIFx0XHRcdHJldHVybiBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXS5leHBvcnRzO1xuIFx0XHR9XG4gXHRcdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG4gXHRcdHZhciBtb2R1bGUgPSBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSA9IHtcbiBcdFx0XHRpOiBtb2R1bGVJZCxcbiBcdFx0XHRsOiBmYWxzZSxcbiBcdFx0XHRleHBvcnRzOiB7fVxuIFx0XHR9O1xuXG4gXHRcdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxuIFx0XHRtb2R1bGVzW21vZHVsZUlkXS5jYWxsKG1vZHVsZS5leHBvcnRzLCBtb2R1bGUsIG1vZHVsZS5leHBvcnRzLCBfX3dlYnBhY2tfcmVxdWlyZV9fKTtcblxuIFx0XHQvLyBGbGFnIHRoZSBtb2R1bGUgYXMgbG9hZGVkXG4gXHRcdG1vZHVsZS5sID0gdHJ1ZTtcblxuIFx0XHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxuIFx0XHRyZXR1cm4gbW9kdWxlLmV4cG9ydHM7XG4gXHR9XG5cblxuIFx0Ly8gZXhwb3NlIHRoZSBtb2R1bGVzIG9iamVjdCAoX193ZWJwYWNrX21vZHVsZXNfXylcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubSA9IG1vZHVsZXM7XG5cbiBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlIGNhY2hlXG4gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmMgPSBpbnN0YWxsZWRNb2R1bGVzO1xuXG4gXHQvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9uIGZvciBoYXJtb255IGV4cG9ydHNcbiBcdF9fd2VicGFja19yZXF1aXJlX18uZCA9IGZ1bmN0aW9uKGV4cG9ydHMsIG5hbWUsIGdldHRlcikge1xuIFx0XHRpZighX193ZWJwYWNrX3JlcXVpcmVfXy5vKGV4cG9ydHMsIG5hbWUpKSB7XG4gXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIG5hbWUsIHtcbiBcdFx0XHRcdGNvbmZpZ3VyYWJsZTogZmFsc2UsXG4gXHRcdFx0XHRlbnVtZXJhYmxlOiB0cnVlLFxuIFx0XHRcdFx0Z2V0OiBnZXR0ZXJcbiBcdFx0XHR9KTtcbiBcdFx0fVxuIFx0fTtcblxuIFx0Ly8gZGVmaW5lIF9fZXNNb2R1bGUgb24gZXhwb3J0c1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5yID0gZnVuY3Rpb24oZXhwb3J0cykge1xuIFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xuIFx0fTtcblxuIFx0Ly8gZ2V0RGVmYXVsdEV4cG9ydCBmdW5jdGlvbiBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIG5vbi1oYXJtb255IG1vZHVsZXNcbiBcdF9fd2VicGFja19yZXF1aXJlX18ubiA9IGZ1bmN0aW9uKG1vZHVsZSkge1xuIFx0XHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cbiBcdFx0XHRmdW5jdGlvbiBnZXREZWZhdWx0KCkgeyByZXR1cm4gbW9kdWxlWydkZWZhdWx0J107IH0gOlxuIFx0XHRcdGZ1bmN0aW9uIGdldE1vZHVsZUV4cG9ydHMoKSB7IHJldHVybiBtb2R1bGU7IH07XG4gXHRcdF9fd2VicGFja19yZXF1aXJlX18uZChnZXR0ZXIsICdhJywgZ2V0dGVyKTtcbiBcdFx0cmV0dXJuIGdldHRlcjtcbiBcdH07XG5cbiBcdC8vIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbFxuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5vID0gZnVuY3Rpb24ob2JqZWN0LCBwcm9wZXJ0eSkgeyByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgcHJvcGVydHkpOyB9O1xuXG4gXHQvLyBfX3dlYnBhY2tfcHVibGljX3BhdGhfX1xuIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5wID0gXCJcIjtcblxuIFx0dmFyIGpzb25wQXJyYXkgPSB3aW5kb3dbXCJ3ZWJwYWNrSnNvbnBcIl0gPSB3aW5kb3dbXCJ3ZWJwYWNrSnNvbnBcIl0gfHwgW107XG4gXHR2YXIgb2xkSnNvbnBGdW5jdGlvbiA9IGpzb25wQXJyYXkucHVzaC5iaW5kKGpzb25wQXJyYXkpO1xuIFx0anNvbnBBcnJheS5wdXNoID0gd2VicGFja0pzb25wQ2FsbGJhY2s7XG4gXHRqc29ucEFycmF5ID0ganNvbnBBcnJheS5zbGljZSgpO1xuIFx0Zm9yKHZhciBpID0gMDsgaSA8IGpzb25wQXJyYXkubGVuZ3RoOyBpKyspIHdlYnBhY2tKc29ucENhbGxiYWNrKGpzb25wQXJyYXlbaV0pO1xuIFx0dmFyIHBhcmVudEpzb25wRnVuY3Rpb24gPSBvbGRKc29ucEZ1bmN0aW9uO1xuXG5cbiBcdC8vIHJ1biBkZWZlcnJlZCBtb2R1bGVzIGZyb20gb3RoZXIgY2h1bmtzXG4gXHRjaGVja0RlZmVycmVkTW9kdWxlcygpO1xuIl0sInNvdXJjZVJvb3QiOiIifQ== \ No newline at end of file diff --git a/assets/dist/ee-manifest.943039ef4ea4d65fdbb9.dist.js b/assets/dist/ee-manifest.943039ef4ea4d65fdbb9.dist.js new file mode 100644 index 00000000000..76fcaded5f7 --- /dev/null +++ b/assets/dist/ee-manifest.943039ef4ea4d65fdbb9.dist.js @@ -0,0 +1 @@ +!function(r){function e(e){for(var t,p,a=e[0],c=e[1],f=e[2],l=0,s=[];l camelize('background-color') - * < "backgroundColor" - * - * @param {string} string - * @return {string} - */ -function camelize(string) { - return string.replace(_hyphenPattern, function (_, character) { - return character.toUpperCase(); - }); -} - -module.exports = camelize; - -/***/ }), - -/***/ "./node_modules/fbjs/lib/camelizeStyleName.js": -/*!****************************************************!*\ - !*** ./node_modules/fbjs/lib/camelizeStyleName.js ***! - \****************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/** - * Copyright (c) 2013-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @typechecks - */ - - - -var camelize = __webpack_require__(/*! ./camelize */ "./node_modules/fbjs/lib/camelize.js"); - -var msPattern = /^-ms-/; - -/** - * Camelcases a hyphenated CSS property name, for example: - * - * > camelizeStyleName('background-color') - * < "backgroundColor" - * > camelizeStyleName('-moz-transition') - * < "MozTransition" - * > camelizeStyleName('-ms-transition') - * < "msTransition" - * - * As Andi Smith suggests - * (http://www.andismith.com/blog/2012/02/modernizr-prefixed/), an `-ms` prefix - * is converted to lowercase `ms`. - * - * @param {string} string - * @return {string} - */ -function camelizeStyleName(string) { - return camelize(string.replace(msPattern, 'ms-')); -} - -module.exports = camelizeStyleName; - -/***/ }), - -/***/ "./node_modules/fbjs/lib/containsNode.js": -/*!***********************************************!*\ - !*** ./node_modules/fbjs/lib/containsNode.js ***! - \***********************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/** - * Copyright (c) 2013-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * - */ - -var isTextNode = __webpack_require__(/*! ./isTextNode */ "./node_modules/fbjs/lib/isTextNode.js"); - -/*eslint-disable no-bitwise */ - -/** - * Checks if a given DOM node contains or is another DOM node. - */ -function containsNode(outerNode, innerNode) { - if (!outerNode || !innerNode) { - return false; - } else if (outerNode === innerNode) { - return true; - } else if (isTextNode(outerNode)) { - return false; - } else if (isTextNode(innerNode)) { - return containsNode(outerNode, innerNode.parentNode); - } else if ('contains' in outerNode) { - return outerNode.contains(innerNode); - } else if (outerNode.compareDocumentPosition) { - return !!(outerNode.compareDocumentPosition(innerNode) & 16); - } else { - return false; - } -} - -module.exports = containsNode; - -/***/ }), - -/***/ "./node_modules/fbjs/lib/emptyFunction.js": -/*!************************************************!*\ - !*** ./node_modules/fbjs/lib/emptyFunction.js ***! - \************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/** - * Copyright (c) 2013-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * - */ - -function makeEmptyFunction(arg) { - return function () { - return arg; - }; -} - -/** - * This function accepts and discards inputs; it has no side effects. This is - * primarily useful idiomatically for overridable function endpoints which - * always need to be callable, since JS lacks a null-call idiom ala Cocoa. - */ -var emptyFunction = function emptyFunction() {}; - -emptyFunction.thatReturns = makeEmptyFunction; -emptyFunction.thatReturnsFalse = makeEmptyFunction(false); -emptyFunction.thatReturnsTrue = makeEmptyFunction(true); -emptyFunction.thatReturnsNull = makeEmptyFunction(null); -emptyFunction.thatReturnsThis = function () { - return this; -}; -emptyFunction.thatReturnsArgument = function (arg) { - return arg; -}; - -module.exports = emptyFunction; - -/***/ }), - -/***/ "./node_modules/fbjs/lib/emptyObject.js": -/*!**********************************************!*\ - !*** ./node_modules/fbjs/lib/emptyObject.js ***! - \**********************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/** - * Copyright (c) 2013-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - */ - - - -var emptyObject = {}; - -if (true) { - Object.freeze(emptyObject); -} - -module.exports = emptyObject; - -/***/ }), - -/***/ "./node_modules/fbjs/lib/getActiveElement.js": -/*!***************************************************!*\ - !*** ./node_modules/fbjs/lib/getActiveElement.js ***! - \***************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/** - * Copyright (c) 2013-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @typechecks - */ - -/* eslint-disable fb-www/typeof-undefined */ - -/** - * Same as document.activeElement but wraps in a try-catch block. In IE it is - * not safe to call document.activeElement if there is nothing focused. - * - * The activeElement will be null only if the document or document body is not - * yet defined. - * - * @param {?DOMDocument} doc Defaults to current document. - * @return {?DOMElement} - */ -function getActiveElement(doc) /*?DOMElement*/{ - doc = doc || (typeof document !== 'undefined' ? document : undefined); - if (typeof doc === 'undefined') { - return null; - } - try { - return doc.activeElement || doc.body; - } catch (e) { - return doc.body; - } -} - -module.exports = getActiveElement; - -/***/ }), - -/***/ "./node_modules/fbjs/lib/hyphenate.js": -/*!********************************************!*\ - !*** ./node_modules/fbjs/lib/hyphenate.js ***! - \********************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/** - * Copyright (c) 2013-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @typechecks - */ - -var _uppercasePattern = /([A-Z])/g; - -/** - * Hyphenates a camelcased string, for example: - * - * > hyphenate('backgroundColor') - * < "background-color" - * - * For CSS style names, use `hyphenateStyleName` instead which works properly - * with all vendor prefixes, including `ms`. - * - * @param {string} string - * @return {string} - */ -function hyphenate(string) { - return string.replace(_uppercasePattern, '-$1').toLowerCase(); -} - -module.exports = hyphenate; - -/***/ }), - -/***/ "./node_modules/fbjs/lib/hyphenateStyleName.js": -/*!*****************************************************!*\ - !*** ./node_modules/fbjs/lib/hyphenateStyleName.js ***! - \*****************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/** - * Copyright (c) 2013-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @typechecks - */ - - - -var hyphenate = __webpack_require__(/*! ./hyphenate */ "./node_modules/fbjs/lib/hyphenate.js"); - -var msPattern = /^ms-/; - -/** - * Hyphenates a camelcased CSS property name, for example: - * - * > hyphenateStyleName('backgroundColor') - * < "background-color" - * > hyphenateStyleName('MozTransition') - * < "-moz-transition" - * > hyphenateStyleName('msTransition') - * < "-ms-transition" - * - * As Modernizr suggests (http://modernizr.com/docs/#prefixed), an `ms` prefix - * is converted to `-ms-`. - * - * @param {string} string - * @return {string} - */ -function hyphenateStyleName(string) { - return hyphenate(string).replace(msPattern, '-ms-'); -} - -module.exports = hyphenateStyleName; - -/***/ }), - -/***/ "./node_modules/fbjs/lib/invariant.js": -/*!********************************************!*\ - !*** ./node_modules/fbjs/lib/invariant.js ***! - \********************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/** - * Copyright (c) 2013-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - */ - - - -/** - * Use invariant() to assert state which your program assumes to be true. - * - * Provide sprintf-style format (only %s is supported) and arguments - * to provide information about what broke and what you were - * expecting. - * - * The invariant message will be stripped in production, but the invariant - * will remain to ensure logic does not differ in production. - */ - -var validateFormat = function validateFormat(format) {}; - -if (true) { - validateFormat = function validateFormat(format) { - if (format === undefined) { - throw new Error('invariant requires an error message argument'); - } - }; -} - -function invariant(condition, format, a, b, c, d, e, f) { - validateFormat(format); - - if (!condition) { - var error; - if (format === undefined) { - error = new Error('Minified exception occurred; use the non-minified dev environment ' + 'for the full error message and additional helpful warnings.'); - } else { - var args = [a, b, c, d, e, f]; - var argIndex = 0; - error = new Error(format.replace(/%s/g, function () { - return args[argIndex++]; - })); - error.name = 'Invariant Violation'; - } - - error.framesToPop = 1; // we don't care about invariant's own frame - throw error; - } -} - -module.exports = invariant; - -/***/ }), - -/***/ "./node_modules/fbjs/lib/isNode.js": -/*!*****************************************!*\ - !*** ./node_modules/fbjs/lib/isNode.js ***! - \*****************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/** - * Copyright (c) 2013-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @typechecks - */ - -/** - * @param {*} object The object to check. - * @return {boolean} Whether or not the object is a DOM node. - */ -function isNode(object) { - var doc = object ? object.ownerDocument || object : document; - var defaultView = doc.defaultView || window; - return !!(object && (typeof defaultView.Node === 'function' ? object instanceof defaultView.Node : typeof object === 'object' && typeof object.nodeType === 'number' && typeof object.nodeName === 'string')); -} - -module.exports = isNode; - -/***/ }), - -/***/ "./node_modules/fbjs/lib/isTextNode.js": -/*!*********************************************!*\ - !*** ./node_modules/fbjs/lib/isTextNode.js ***! - \*********************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -/** - * Copyright (c) 2013-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @typechecks - */ - -var isNode = __webpack_require__(/*! ./isNode */ "./node_modules/fbjs/lib/isNode.js"); - -/** - * @param {*} object The object to check. - * @return {boolean} Whether or not the object is a DOM text node. - */ -function isTextNode(object) { - return isNode(object) && object.nodeType == 3; -} - -module.exports = isTextNode; - -/***/ }), - -/***/ "./node_modules/fbjs/lib/shallowEqual.js": -/*!***********************************************!*\ - !*** ./node_modules/fbjs/lib/shallowEqual.js ***! - \***********************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/** - * Copyright (c) 2013-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @typechecks - * - */ - -/*eslint-disable no-self-compare */ - - - -var hasOwnProperty = Object.prototype.hasOwnProperty; - -/** - * inlined Object.is polyfill to avoid requiring consumers ship their own - * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is - */ -function is(x, y) { - // SameValue algorithm - if (x === y) { - // Steps 1-5, 7-10 - // Steps 6.b-6.e: +0 != -0 - // Added the nonzero y check to make Flow happy, but it is redundant - return x !== 0 || y !== 0 || 1 / x === 1 / y; - } else { - // Step 6.a: NaN == NaN - return x !== x && y !== y; - } -} - -/** - * Performs equality by iterating through keys on an object and returning false - * when any key has values which are not strictly equal between the arguments. - * Returns true when the values of all keys are strictly equal. - */ -function shallowEqual(objA, objB) { - if (is(objA, objB)) { - return true; - } - - if (typeof objA !== 'object' || objA === null || typeof objB !== 'object' || objB === null) { - return false; - } - - var keysA = Object.keys(objA); - var keysB = Object.keys(objB); - - if (keysA.length !== keysB.length) { - return false; - } - - // Test for A's keys different from B. - for (var i = 0; i < keysA.length; i++) { - if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) { - return false; - } - } - - return true; -} - -module.exports = shallowEqual; - -/***/ }), - -/***/ "./node_modules/fbjs/lib/warning.js": -/*!******************************************!*\ - !*** ./node_modules/fbjs/lib/warning.js ***! - \******************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/** - * Copyright (c) 2014-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - */ - - - -var emptyFunction = __webpack_require__(/*! ./emptyFunction */ "./node_modules/fbjs/lib/emptyFunction.js"); - -/** - * Similar to invariant but only logs a warning if the condition is not met. - * This can be used to log issues in development environments in critical - * paths. Removing the logging code for production environments will keep the - * same logic and follow the same code paths. - */ - -var warning = emptyFunction; - -if (true) { - var printWarning = function printWarning(format) { - for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { - args[_key - 1] = arguments[_key]; - } - - var argIndex = 0; - var message = 'Warning: ' + format.replace(/%s/g, function () { - return args[argIndex++]; - }); - if (typeof console !== 'undefined') { - console.error(message); - } - try { - // --- Welcome to debugging React --- - // This error was thrown as a convenience so that you can use this stack - // to find the callsite that caused this warning to fire. - throw new Error(message); - } catch (x) {} - }; - - warning = function warning(condition, format) { - if (format === undefined) { - throw new Error('`warning(condition, format, ...args)` requires a warning ' + 'message argument'); - } - - if (format.indexOf('Failed Composite propType: ') === 0) { - return; // Ignore CompositeComponent proptype check. - } - - if (!condition) { - for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { - args[_key2 - 2] = arguments[_key2]; - } - - printWarning.apply(undefined, [format].concat(args)); - } - }; -} - -module.exports = warning; - -/***/ }), - -/***/ "./node_modules/hoist-non-react-statics/index.js": -/*!*******************************************************!*\ - !*** ./node_modules/hoist-non-react-statics/index.js ***! - \*******************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -/** - * Copyright 2015, Yahoo! Inc. - * Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. - */ -(function (global, factory) { - true ? module.exports = factory() : - undefined; -}(this, (function () { - 'use strict'; - - var REACT_STATICS = { - childContextTypes: true, - contextTypes: true, - defaultProps: true, - displayName: true, - getDefaultProps: true, - getDerivedStateFromProps: true, - mixins: true, - propTypes: true, - type: true - }; - - var KNOWN_STATICS = { - name: true, - length: true, - prototype: true, - caller: true, - callee: true, - arguments: true, - arity: true - }; - - var defineProperty = Object.defineProperty; - var getOwnPropertyNames = Object.getOwnPropertyNames; - var getOwnPropertySymbols = Object.getOwnPropertySymbols; - var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; - var getPrototypeOf = Object.getPrototypeOf; - var objectPrototype = getPrototypeOf && getPrototypeOf(Object); - - return function hoistNonReactStatics(targetComponent, sourceComponent, blacklist) { - if (typeof sourceComponent !== 'string') { // don't hoist over string (html) components - - if (objectPrototype) { - var inheritedComponent = getPrototypeOf(sourceComponent); - if (inheritedComponent && inheritedComponent !== objectPrototype) { - hoistNonReactStatics(targetComponent, inheritedComponent, blacklist); - } - } - - var keys = getOwnPropertyNames(sourceComponent); - - if (getOwnPropertySymbols) { - keys = keys.concat(getOwnPropertySymbols(sourceComponent)); - } - - for (var i = 0; i < keys.length; ++i) { - var key = keys[i]; - if (!REACT_STATICS[key] && !KNOWN_STATICS[key] && (!blacklist || !blacklist[key])) { - var descriptor = getOwnPropertyDescriptor(sourceComponent, key); - try { // Avoid failures from read-only properties - defineProperty(targetComponent, key, descriptor); - } catch (e) {} - } - } - - return targetComponent; - } - - return targetComponent; - }; -}))); - - -/***/ }), - -/***/ "./node_modules/invariant/browser.js": -/*!*******************************************!*\ - !*** ./node_modules/invariant/browser.js ***! - \*******************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; -/** - * Copyright (c) 2013-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - - - -/** - * Use invariant() to assert state which your program assumes to be true. - * - * Provide sprintf-style format (only %s is supported) and arguments - * to provide information about what broke and what you were - * expecting. - * - * The invariant message will be stripped in production, but the invariant - * will remain to ensure logic does not differ in production. - */ - -var invariant = function(condition, format, a, b, c, d, e, f) { - if (true) { - if (format === undefined) { - throw new Error('invariant requires an error message argument'); - } - } - - if (!condition) { - var error; - if (format === undefined) { - error = new Error( - 'Minified exception occurred; use the non-minified dev environment ' + - 'for the full error message and additional helpful warnings.' - ); - } else { - var args = [a, b, c, d, e, f]; - var argIndex = 0; - error = new Error( - format.replace(/%s/g, function() { return args[argIndex++]; }) - ); - error.name = 'Invariant Violation'; - } - - error.framesToPop = 1; // we don't care about invariant's own frame - throw error; - } -}; - -module.exports = invariant; - - -/***/ }), - -/***/ "./node_modules/lodash-es/_Symbol.js": -/*!*******************************************!*\ - !*** ./node_modules/lodash-es/_Symbol.js ***! - \*******************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var _root_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./_root.js */ "./node_modules/lodash-es/_root.js"); - - -/** Built-in value references. */ -var Symbol = _root_js__WEBPACK_IMPORTED_MODULE_0__["default"].Symbol; - -/* harmony default export */ __webpack_exports__["default"] = (Symbol); - - -/***/ }), - -/***/ "./node_modules/lodash-es/_baseGetTag.js": -/*!***********************************************!*\ - !*** ./node_modules/lodash-es/_baseGetTag.js ***! - \***********************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var _Symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./_Symbol.js */ "./node_modules/lodash-es/_Symbol.js"); -/* harmony import */ var _getRawTag_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./_getRawTag.js */ "./node_modules/lodash-es/_getRawTag.js"); -/* harmony import */ var _objectToString_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./_objectToString.js */ "./node_modules/lodash-es/_objectToString.js"); - - - - -/** `Object#toString` result references. */ -var nullTag = '[object Null]', - undefinedTag = '[object Undefined]'; - -/** Built-in value references. */ -var symToStringTag = _Symbol_js__WEBPACK_IMPORTED_MODULE_0__["default"] ? _Symbol_js__WEBPACK_IMPORTED_MODULE_0__["default"].toStringTag : undefined; - -/** - * The base implementation of `getTag` without fallbacks for buggy environments. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the `toStringTag`. - */ -function baseGetTag(value) { - if (value == null) { - return value === undefined ? undefinedTag : nullTag; - } - return (symToStringTag && symToStringTag in Object(value)) - ? Object(_getRawTag_js__WEBPACK_IMPORTED_MODULE_1__["default"])(value) - : Object(_objectToString_js__WEBPACK_IMPORTED_MODULE_2__["default"])(value); -} - -/* harmony default export */ __webpack_exports__["default"] = (baseGetTag); - - -/***/ }), - -/***/ "./node_modules/lodash-es/_freeGlobal.js": -/*!***********************************************!*\ - !*** ./node_modules/lodash-es/_freeGlobal.js ***! - \***********************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* WEBPACK VAR INJECTION */(function(global) {/** Detect free variable `global` from Node.js. */ -var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; - -/* harmony default export */ __webpack_exports__["default"] = (freeGlobal); - -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../webpack/buildin/global.js */ "./node_modules/webpack/buildin/global.js"))) - -/***/ }), - -/***/ "./node_modules/lodash-es/_getPrototype.js": -/*!*************************************************!*\ - !*** ./node_modules/lodash-es/_getPrototype.js ***! - \*************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var _overArg_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./_overArg.js */ "./node_modules/lodash-es/_overArg.js"); - - -/** Built-in value references. */ -var getPrototype = Object(_overArg_js__WEBPACK_IMPORTED_MODULE_0__["default"])(Object.getPrototypeOf, Object); - -/* harmony default export */ __webpack_exports__["default"] = (getPrototype); - - -/***/ }), - -/***/ "./node_modules/lodash-es/_getRawTag.js": -/*!**********************************************!*\ - !*** ./node_modules/lodash-es/_getRawTag.js ***! - \**********************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var _Symbol_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./_Symbol.js */ "./node_modules/lodash-es/_Symbol.js"); - - -/** Used for built-in method references. */ -var objectProto = Object.prototype; - -/** Used to check objects for own properties. */ -var hasOwnProperty = objectProto.hasOwnProperty; - -/** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ -var nativeObjectToString = objectProto.toString; - -/** Built-in value references. */ -var symToStringTag = _Symbol_js__WEBPACK_IMPORTED_MODULE_0__["default"] ? _Symbol_js__WEBPACK_IMPORTED_MODULE_0__["default"].toStringTag : undefined; - -/** - * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the raw `toStringTag`. - */ -function getRawTag(value) { - var isOwn = hasOwnProperty.call(value, symToStringTag), - tag = value[symToStringTag]; - - try { - value[symToStringTag] = undefined; - var unmasked = true; - } catch (e) {} - - var result = nativeObjectToString.call(value); - if (unmasked) { - if (isOwn) { - value[symToStringTag] = tag; - } else { - delete value[symToStringTag]; - } - } - return result; -} - -/* harmony default export */ __webpack_exports__["default"] = (getRawTag); - - -/***/ }), - -/***/ "./node_modules/lodash-es/_objectToString.js": -/*!***************************************************!*\ - !*** ./node_modules/lodash-es/_objectToString.js ***! - \***************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/** Used for built-in method references. */ -var objectProto = Object.prototype; - -/** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ -var nativeObjectToString = objectProto.toString; - -/** - * Converts `value` to a string using `Object.prototype.toString`. - * - * @private - * @param {*} value The value to convert. - * @returns {string} Returns the converted string. - */ -function objectToString(value) { - return nativeObjectToString.call(value); -} - -/* harmony default export */ __webpack_exports__["default"] = (objectToString); - - -/***/ }), - -/***/ "./node_modules/lodash-es/_overArg.js": -/*!********************************************!*\ - !*** ./node_modules/lodash-es/_overArg.js ***! - \********************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/** - * Creates a unary function that invokes `func` with its argument transformed. - * - * @private - * @param {Function} func The function to wrap. - * @param {Function} transform The argument transform. - * @returns {Function} Returns the new function. - */ -function overArg(func, transform) { - return function(arg) { - return func(transform(arg)); - }; -} - -/* harmony default export */ __webpack_exports__["default"] = (overArg); - - -/***/ }), - -/***/ "./node_modules/lodash-es/_root.js": -/*!*****************************************!*\ - !*** ./node_modules/lodash-es/_root.js ***! - \*****************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var _freeGlobal_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./_freeGlobal.js */ "./node_modules/lodash-es/_freeGlobal.js"); - - -/** Detect free variable `self`. */ -var freeSelf = typeof self == 'object' && self && self.Object === Object && self; - -/** Used as a reference to the global object. */ -var root = _freeGlobal_js__WEBPACK_IMPORTED_MODULE_0__["default"] || freeSelf || Function('return this')(); - -/* harmony default export */ __webpack_exports__["default"] = (root); - - -/***/ }), - -/***/ "./node_modules/lodash-es/isObjectLike.js": -/*!************************************************!*\ - !*** ./node_modules/lodash-es/isObjectLike.js ***! - \************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/** - * Checks if `value` is object-like. A value is object-like if it's not `null` - * and has a `typeof` result of "object". - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is object-like, else `false`. - * @example - * - * _.isObjectLike({}); - * // => true - * - * _.isObjectLike([1, 2, 3]); - * // => true - * - * _.isObjectLike(_.noop); - * // => false - * - * _.isObjectLike(null); - * // => false - */ -function isObjectLike(value) { - return value != null && typeof value == 'object'; -} - -/* harmony default export */ __webpack_exports__["default"] = (isObjectLike); - - -/***/ }), - -/***/ "./node_modules/lodash-es/isPlainObject.js": -/*!*************************************************!*\ - !*** ./node_modules/lodash-es/isPlainObject.js ***! - \*************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var _baseGetTag_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./_baseGetTag.js */ "./node_modules/lodash-es/_baseGetTag.js"); -/* harmony import */ var _getPrototype_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./_getPrototype.js */ "./node_modules/lodash-es/_getPrototype.js"); -/* harmony import */ var _isObjectLike_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./isObjectLike.js */ "./node_modules/lodash-es/isObjectLike.js"); - - - - -/** `Object#toString` result references. */ -var objectTag = '[object Object]'; - -/** Used for built-in method references. */ -var funcProto = Function.prototype, - objectProto = Object.prototype; - -/** Used to resolve the decompiled source of functions. */ -var funcToString = funcProto.toString; - -/** Used to check objects for own properties. */ -var hasOwnProperty = objectProto.hasOwnProperty; - -/** Used to infer the `Object` constructor. */ -var objectCtorString = funcToString.call(Object); - -/** - * Checks if `value` is a plain object, that is, an object created by the - * `Object` constructor or one with a `[[Prototype]]` of `null`. - * - * @static - * @memberOf _ - * @since 0.8.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. - * @example - * - * function Foo() { - * this.a = 1; - * } - * - * _.isPlainObject(new Foo); - * // => false - * - * _.isPlainObject([1, 2, 3]); - * // => false - * - * _.isPlainObject({ 'x': 0, 'y': 0 }); - * // => true - * - * _.isPlainObject(Object.create(null)); - * // => true - */ -function isPlainObject(value) { - if (!Object(_isObjectLike_js__WEBPACK_IMPORTED_MODULE_2__["default"])(value) || Object(_baseGetTag_js__WEBPACK_IMPORTED_MODULE_0__["default"])(value) != objectTag) { - return false; - } - var proto = Object(_getPrototype_js__WEBPACK_IMPORTED_MODULE_1__["default"])(value); - if (proto === null) { - return true; - } - var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor; - return typeof Ctor == 'function' && Ctor instanceof Ctor && - funcToString.call(Ctor) == objectCtorString; -} - -/* harmony default export */ __webpack_exports__["default"] = (isPlainObject); - - -/***/ }), - -/***/ "./node_modules/lodash/lodash.js": -/*!***************************************!*\ - !*** ./node_modules/lodash/lodash.js ***! - \***************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -/* WEBPACK VAR INJECTION */(function(global, module) {var __WEBPACK_AMD_DEFINE_RESULT__;/** - * @license - * Lodash - * Copyright JS Foundation and other contributors - * Released under MIT license - * Based on Underscore.js 1.8.3 - * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors - */ -;(function() { - - /** Used as a safe reference for `undefined` in pre-ES5 environments. */ - var undefined; - - /** Used as the semantic version number. */ - var VERSION = '4.17.10'; - - /** Used as the size to enable large array optimizations. */ - var LARGE_ARRAY_SIZE = 200; - - /** Error message constants. */ - var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.', - FUNC_ERROR_TEXT = 'Expected a function'; - - /** Used to stand-in for `undefined` hash values. */ - var HASH_UNDEFINED = '__lodash_hash_undefined__'; - - /** Used as the maximum memoize cache size. */ - var MAX_MEMOIZE_SIZE = 500; - - /** Used as the internal argument placeholder. */ - var PLACEHOLDER = '__lodash_placeholder__'; - - /** Used to compose bitmasks for cloning. */ - var CLONE_DEEP_FLAG = 1, - CLONE_FLAT_FLAG = 2, - CLONE_SYMBOLS_FLAG = 4; - - /** Used to compose bitmasks for value comparisons. */ - var COMPARE_PARTIAL_FLAG = 1, - COMPARE_UNORDERED_FLAG = 2; - - /** Used to compose bitmasks for function metadata. */ - var WRAP_BIND_FLAG = 1, - WRAP_BIND_KEY_FLAG = 2, - WRAP_CURRY_BOUND_FLAG = 4, - WRAP_CURRY_FLAG = 8, - WRAP_CURRY_RIGHT_FLAG = 16, - WRAP_PARTIAL_FLAG = 32, - WRAP_PARTIAL_RIGHT_FLAG = 64, - WRAP_ARY_FLAG = 128, - WRAP_REARG_FLAG = 256, - WRAP_FLIP_FLAG = 512; - - /** Used as default options for `_.truncate`. */ - var DEFAULT_TRUNC_LENGTH = 30, - DEFAULT_TRUNC_OMISSION = '...'; - - /** Used to detect hot functions by number of calls within a span of milliseconds. */ - var HOT_COUNT = 800, - HOT_SPAN = 16; - - /** Used to indicate the type of lazy iteratees. */ - var LAZY_FILTER_FLAG = 1, - LAZY_MAP_FLAG = 2, - LAZY_WHILE_FLAG = 3; - - /** Used as references for various `Number` constants. */ - var INFINITY = 1 / 0, - MAX_SAFE_INTEGER = 9007199254740991, - MAX_INTEGER = 1.7976931348623157e+308, - NAN = 0 / 0; - - /** Used as references for the maximum length and index of an array. */ - var MAX_ARRAY_LENGTH = 4294967295, - MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, - HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1; - - /** Used to associate wrap methods with their bit flags. */ - var wrapFlags = [ - ['ary', WRAP_ARY_FLAG], - ['bind', WRAP_BIND_FLAG], - ['bindKey', WRAP_BIND_KEY_FLAG], - ['curry', WRAP_CURRY_FLAG], - ['curryRight', WRAP_CURRY_RIGHT_FLAG], - ['flip', WRAP_FLIP_FLAG], - ['partial', WRAP_PARTIAL_FLAG], - ['partialRight', WRAP_PARTIAL_RIGHT_FLAG], - ['rearg', WRAP_REARG_FLAG] - ]; - - /** `Object#toString` result references. */ - var argsTag = '[object Arguments]', - arrayTag = '[object Array]', - asyncTag = '[object AsyncFunction]', - boolTag = '[object Boolean]', - dateTag = '[object Date]', - domExcTag = '[object DOMException]', - errorTag = '[object Error]', - funcTag = '[object Function]', - genTag = '[object GeneratorFunction]', - mapTag = '[object Map]', - numberTag = '[object Number]', - nullTag = '[object Null]', - objectTag = '[object Object]', - promiseTag = '[object Promise]', - proxyTag = '[object Proxy]', - regexpTag = '[object RegExp]', - setTag = '[object Set]', - stringTag = '[object String]', - symbolTag = '[object Symbol]', - undefinedTag = '[object Undefined]', - weakMapTag = '[object WeakMap]', - weakSetTag = '[object WeakSet]'; - - var arrayBufferTag = '[object ArrayBuffer]', - dataViewTag = '[object DataView]', - float32Tag = '[object Float32Array]', - float64Tag = '[object Float64Array]', - int8Tag = '[object Int8Array]', - int16Tag = '[object Int16Array]', - int32Tag = '[object Int32Array]', - uint8Tag = '[object Uint8Array]', - uint8ClampedTag = '[object Uint8ClampedArray]', - uint16Tag = '[object Uint16Array]', - uint32Tag = '[object Uint32Array]'; - - /** Used to match empty string literals in compiled template source. */ - var reEmptyStringLeading = /\b__p \+= '';/g, - reEmptyStringMiddle = /\b(__p \+=) '' \+/g, - reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g; - - /** Used to match HTML entities and HTML characters. */ - var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, - reUnescapedHtml = /[&<>"']/g, - reHasEscapedHtml = RegExp(reEscapedHtml.source), - reHasUnescapedHtml = RegExp(reUnescapedHtml.source); - - /** Used to match template delimiters. */ - var reEscape = /<%-([\s\S]+?)%>/g, - reEvaluate = /<%([\s\S]+?)%>/g, - reInterpolate = /<%=([\s\S]+?)%>/g; - - /** Used to match property names within property paths. */ - var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, - reIsPlainProp = /^\w*$/, - rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g; - - /** - * Used to match `RegExp` - * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns). - */ - var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, - reHasRegExpChar = RegExp(reRegExpChar.source); - - /** Used to match leading and trailing whitespace. */ - var reTrim = /^\s+|\s+$/g, - reTrimStart = /^\s+/, - reTrimEnd = /\s+$/; - - /** Used to match wrap detail comments. */ - var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, - reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, - reSplitDetails = /,? & /; - - /** Used to match words composed of alphanumeric characters. */ - var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g; - - /** Used to match backslashes in property paths. */ - var reEscapeChar = /\\(\\)?/g; - - /** - * Used to match - * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components). - */ - var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g; - - /** Used to match `RegExp` flags from their coerced string values. */ - var reFlags = /\w*$/; - - /** Used to detect bad signed hexadecimal string values. */ - var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; - - /** Used to detect binary string values. */ - var reIsBinary = /^0b[01]+$/i; - - /** Used to detect host constructors (Safari). */ - var reIsHostCtor = /^\[object .+?Constructor\]$/; - - /** Used to detect octal string values. */ - var reIsOctal = /^0o[0-7]+$/i; - - /** Used to detect unsigned integer values. */ - var reIsUint = /^(?:0|[1-9]\d*)$/; - - /** Used to match Latin Unicode letters (excluding mathematical operators). */ - var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g; - - /** Used to ensure capturing order of template delimiters. */ - var reNoMatch = /($^)/; - - /** Used to match unescaped characters in compiled string literals. */ - var reUnescapedString = /['\n\r\u2028\u2029\\]/g; - - /** Used to compose unicode character classes. */ - var rsAstralRange = '\\ud800-\\udfff', - rsComboMarksRange = '\\u0300-\\u036f', - reComboHalfMarksRange = '\\ufe20-\\ufe2f', - rsComboSymbolsRange = '\\u20d0-\\u20ff', - rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, - rsDingbatRange = '\\u2700-\\u27bf', - rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff', - rsMathOpRange = '\\xac\\xb1\\xd7\\xf7', - rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf', - rsPunctuationRange = '\\u2000-\\u206f', - rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000', - rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde', - rsVarRange = '\\ufe0e\\ufe0f', - rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange; - - /** Used to compose unicode capture groups. */ - var rsApos = "['\u2019]", - rsAstral = '[' + rsAstralRange + ']', - rsBreak = '[' + rsBreakRange + ']', - rsCombo = '[' + rsComboRange + ']', - rsDigits = '\\d+', - rsDingbat = '[' + rsDingbatRange + ']', - rsLower = '[' + rsLowerRange + ']', - rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']', - rsFitz = '\\ud83c[\\udffb-\\udfff]', - rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')', - rsNonAstral = '[^' + rsAstralRange + ']', - rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}', - rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]', - rsUpper = '[' + rsUpperRange + ']', - rsZWJ = '\\u200d'; - - /** Used to compose unicode regexes. */ - var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')', - rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')', - rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?', - rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?', - reOptMod = rsModifier + '?', - rsOptVar = '[' + rsVarRange + ']?', - rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*', - rsOrdLower = '\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])', - rsOrdUpper = '\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])', - rsSeq = rsOptVar + reOptMod + rsOptJoin, - rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq, - rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')'; - - /** Used to match apostrophes. */ - var reApos = RegExp(rsApos, 'g'); - - /** - * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and - * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols). - */ - var reComboMark = RegExp(rsCombo, 'g'); - - /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */ - var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g'); - - /** Used to match complex or compound words. */ - var reUnicodeWord = RegExp([ - rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')', - rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')', - rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower, - rsUpper + '+' + rsOptContrUpper, - rsOrdUpper, - rsOrdLower, - rsDigits, - rsEmoji - ].join('|'), 'g'); - - /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */ - var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + ']'); - - /** Used to detect strings that need a more robust regexp to match words. */ - var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/; - - /** Used to assign default `context` object properties. */ - var contextProps = [ - 'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array', - 'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object', - 'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array', - 'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap', - '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout' - ]; - - /** Used to make template sourceURLs easier to identify. */ - var templateCounter = -1; - - /** Used to identify `toStringTag` values of typed arrays. */ - var typedArrayTags = {}; - typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = - typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = - typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = - typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = - typedArrayTags[uint32Tag] = true; - typedArrayTags[argsTag] = typedArrayTags[arrayTag] = - typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = - typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = - typedArrayTags[errorTag] = typedArrayTags[funcTag] = - typedArrayTags[mapTag] = typedArrayTags[numberTag] = - typedArrayTags[objectTag] = typedArrayTags[regexpTag] = - typedArrayTags[setTag] = typedArrayTags[stringTag] = - typedArrayTags[weakMapTag] = false; - - /** Used to identify `toStringTag` values supported by `_.clone`. */ - var cloneableTags = {}; - cloneableTags[argsTag] = cloneableTags[arrayTag] = - cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = - cloneableTags[boolTag] = cloneableTags[dateTag] = - cloneableTags[float32Tag] = cloneableTags[float64Tag] = - cloneableTags[int8Tag] = cloneableTags[int16Tag] = - cloneableTags[int32Tag] = cloneableTags[mapTag] = - cloneableTags[numberTag] = cloneableTags[objectTag] = - cloneableTags[regexpTag] = cloneableTags[setTag] = - cloneableTags[stringTag] = cloneableTags[symbolTag] = - cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = - cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true; - cloneableTags[errorTag] = cloneableTags[funcTag] = - cloneableTags[weakMapTag] = false; - - /** Used to map Latin Unicode letters to basic Latin letters. */ - var deburredLetters = { - // Latin-1 Supplement block. - '\xc0': 'A', '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A', - '\xe0': 'a', '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a', - '\xc7': 'C', '\xe7': 'c', - '\xd0': 'D', '\xf0': 'd', - '\xc8': 'E', '\xc9': 'E', '\xca': 'E', '\xcb': 'E', - '\xe8': 'e', '\xe9': 'e', '\xea': 'e', '\xeb': 'e', - '\xcc': 'I', '\xcd': 'I', '\xce': 'I', '\xcf': 'I', - '\xec': 'i', '\xed': 'i', '\xee': 'i', '\xef': 'i', - '\xd1': 'N', '\xf1': 'n', - '\xd2': 'O', '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O', - '\xf2': 'o', '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o', - '\xd9': 'U', '\xda': 'U', '\xdb': 'U', '\xdc': 'U', - '\xf9': 'u', '\xfa': 'u', '\xfb': 'u', '\xfc': 'u', - '\xdd': 'Y', '\xfd': 'y', '\xff': 'y', - '\xc6': 'Ae', '\xe6': 'ae', - '\xde': 'Th', '\xfe': 'th', - '\xdf': 'ss', - // Latin Extended-A block. - '\u0100': 'A', '\u0102': 'A', '\u0104': 'A', - '\u0101': 'a', '\u0103': 'a', '\u0105': 'a', - '\u0106': 'C', '\u0108': 'C', '\u010a': 'C', '\u010c': 'C', - '\u0107': 'c', '\u0109': 'c', '\u010b': 'c', '\u010d': 'c', - '\u010e': 'D', '\u0110': 'D', '\u010f': 'd', '\u0111': 'd', - '\u0112': 'E', '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E', - '\u0113': 'e', '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e', - '\u011c': 'G', '\u011e': 'G', '\u0120': 'G', '\u0122': 'G', - '\u011d': 'g', '\u011f': 'g', '\u0121': 'g', '\u0123': 'g', - '\u0124': 'H', '\u0126': 'H', '\u0125': 'h', '\u0127': 'h', - '\u0128': 'I', '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I', - '\u0129': 'i', '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i', - '\u0134': 'J', '\u0135': 'j', - '\u0136': 'K', '\u0137': 'k', '\u0138': 'k', - '\u0139': 'L', '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L', - '\u013a': 'l', '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l', - '\u0143': 'N', '\u0145': 'N', '\u0147': 'N', '\u014a': 'N', - '\u0144': 'n', '\u0146': 'n', '\u0148': 'n', '\u014b': 'n', - '\u014c': 'O', '\u014e': 'O', '\u0150': 'O', - '\u014d': 'o', '\u014f': 'o', '\u0151': 'o', - '\u0154': 'R', '\u0156': 'R', '\u0158': 'R', - '\u0155': 'r', '\u0157': 'r', '\u0159': 'r', - '\u015a': 'S', '\u015c': 'S', '\u015e': 'S', '\u0160': 'S', - '\u015b': 's', '\u015d': 's', '\u015f': 's', '\u0161': 's', - '\u0162': 'T', '\u0164': 'T', '\u0166': 'T', - '\u0163': 't', '\u0165': 't', '\u0167': 't', - '\u0168': 'U', '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U', - '\u0169': 'u', '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u', - '\u0174': 'W', '\u0175': 'w', - '\u0176': 'Y', '\u0177': 'y', '\u0178': 'Y', - '\u0179': 'Z', '\u017b': 'Z', '\u017d': 'Z', - '\u017a': 'z', '\u017c': 'z', '\u017e': 'z', - '\u0132': 'IJ', '\u0133': 'ij', - '\u0152': 'Oe', '\u0153': 'oe', - '\u0149': "'n", '\u017f': 's' - }; - - /** Used to map characters to HTML entities. */ - var htmlEscapes = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - "'": ''' - }; - - /** Used to map HTML entities to characters. */ - var htmlUnescapes = { - '&': '&', - '<': '<', - '>': '>', - '"': '"', - ''': "'" - }; - - /** Used to escape characters for inclusion in compiled string literals. */ - var stringEscapes = { - '\\': '\\', - "'": "'", - '\n': 'n', - '\r': 'r', - '\u2028': 'u2028', - '\u2029': 'u2029' - }; - - /** Built-in method references without a dependency on `root`. */ - var freeParseFloat = parseFloat, - freeParseInt = parseInt; - - /** Detect free variable `global` from Node.js. */ - var freeGlobal = typeof global == 'object' && global && global.Object === Object && global; - - /** Detect free variable `self`. */ - var freeSelf = typeof self == 'object' && self && self.Object === Object && self; - - /** Used as a reference to the global object. */ - var root = freeGlobal || freeSelf || Function('return this')(); - - /** Detect free variable `exports`. */ - var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports; - - /** Detect free variable `module`. */ - var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module; - - /** Detect the popular CommonJS extension `module.exports`. */ - var moduleExports = freeModule && freeModule.exports === freeExports; - - /** Detect free variable `process` from Node.js. */ - var freeProcess = moduleExports && freeGlobal.process; - - /** Used to access faster Node.js helpers. */ - var nodeUtil = (function() { - try { - // Use `util.types` for Node.js 10+. - var types = freeModule && freeModule.require && freeModule.require('util').types; - - if (types) { - return types; - } - - // Legacy `process.binding('util')` for Node.js < 10. - return freeProcess && freeProcess.binding && freeProcess.binding('util'); - } catch (e) {} - }()); - - /* Node.js helper references. */ - var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer, - nodeIsDate = nodeUtil && nodeUtil.isDate, - nodeIsMap = nodeUtil && nodeUtil.isMap, - nodeIsRegExp = nodeUtil && nodeUtil.isRegExp, - nodeIsSet = nodeUtil && nodeUtil.isSet, - nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray; - - /*--------------------------------------------------------------------------*/ - - /** - * A faster alternative to `Function#apply`, this function invokes `func` - * with the `this` binding of `thisArg` and the arguments of `args`. - * - * @private - * @param {Function} func The function to invoke. - * @param {*} thisArg The `this` binding of `func`. - * @param {Array} args The arguments to invoke `func` with. - * @returns {*} Returns the result of `func`. - */ - function apply(func, thisArg, args) { - switch (args.length) { - case 0: return func.call(thisArg); - case 1: return func.call(thisArg, args[0]); - case 2: return func.call(thisArg, args[0], args[1]); - case 3: return func.call(thisArg, args[0], args[1], args[2]); - } - return func.apply(thisArg, args); - } - - /** - * A specialized version of `baseAggregator` for arrays. - * - * @private - * @param {Array} [array] The array to iterate over. - * @param {Function} setter The function to set `accumulator` values. - * @param {Function} iteratee The iteratee to transform keys. - * @param {Object} accumulator The initial aggregated object. - * @returns {Function} Returns `accumulator`. - */ - function arrayAggregator(array, setter, iteratee, accumulator) { - var index = -1, - length = array == null ? 0 : array.length; - - while (++index < length) { - var value = array[index]; - setter(accumulator, value, iteratee(value), array); - } - return accumulator; - } - - /** - * A specialized version of `_.forEach` for arrays without support for - * iteratee shorthands. - * - * @private - * @param {Array} [array] The array to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @returns {Array} Returns `array`. - */ - function arrayEach(array, iteratee) { - var index = -1, - length = array == null ? 0 : array.length; - - while (++index < length) { - if (iteratee(array[index], index, array) === false) { - break; - } - } - return array; - } - - /** - * A specialized version of `_.forEachRight` for arrays without support for - * iteratee shorthands. - * - * @private - * @param {Array} [array] The array to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @returns {Array} Returns `array`. - */ - function arrayEachRight(array, iteratee) { - var length = array == null ? 0 : array.length; - - while (length--) { - if (iteratee(array[length], length, array) === false) { - break; - } - } - return array; - } - - /** - * A specialized version of `_.every` for arrays without support for - * iteratee shorthands. - * - * @private - * @param {Array} [array] The array to iterate over. - * @param {Function} predicate The function invoked per iteration. - * @returns {boolean} Returns `true` if all elements pass the predicate check, - * else `false`. - */ - function arrayEvery(array, predicate) { - var index = -1, - length = array == null ? 0 : array.length; - - while (++index < length) { - if (!predicate(array[index], index, array)) { - return false; - } - } - return true; - } - - /** - * A specialized version of `_.filter` for arrays without support for - * iteratee shorthands. - * - * @private - * @param {Array} [array] The array to iterate over. - * @param {Function} predicate The function invoked per iteration. - * @returns {Array} Returns the new filtered array. - */ - function arrayFilter(array, predicate) { - var index = -1, - length = array == null ? 0 : array.length, - resIndex = 0, - result = []; - - while (++index < length) { - var value = array[index]; - if (predicate(value, index, array)) { - result[resIndex++] = value; - } - } - return result; - } - - /** - * A specialized version of `_.includes` for arrays without support for - * specifying an index to search from. - * - * @private - * @param {Array} [array] The array to inspect. - * @param {*} target The value to search for. - * @returns {boolean} Returns `true` if `target` is found, else `false`. - */ - function arrayIncludes(array, value) { - var length = array == null ? 0 : array.length; - return !!length && baseIndexOf(array, value, 0) > -1; - } - - /** - * This function is like `arrayIncludes` except that it accepts a comparator. - * - * @private - * @param {Array} [array] The array to inspect. - * @param {*} target The value to search for. - * @param {Function} comparator The comparator invoked per element. - * @returns {boolean} Returns `true` if `target` is found, else `false`. - */ - function arrayIncludesWith(array, value, comparator) { - var index = -1, - length = array == null ? 0 : array.length; - - while (++index < length) { - if (comparator(value, array[index])) { - return true; - } - } - return false; - } - - /** - * A specialized version of `_.map` for arrays without support for iteratee - * shorthands. - * - * @private - * @param {Array} [array] The array to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @returns {Array} Returns the new mapped array. - */ - function arrayMap(array, iteratee) { - var index = -1, - length = array == null ? 0 : array.length, - result = Array(length); - - while (++index < length) { - result[index] = iteratee(array[index], index, array); - } - return result; - } - - /** - * Appends the elements of `values` to `array`. - * - * @private - * @param {Array} array The array to modify. - * @param {Array} values The values to append. - * @returns {Array} Returns `array`. - */ - function arrayPush(array, values) { - var index = -1, - length = values.length, - offset = array.length; - - while (++index < length) { - array[offset + index] = values[index]; - } - return array; - } - - /** - * A specialized version of `_.reduce` for arrays without support for - * iteratee shorthands. - * - * @private - * @param {Array} [array] The array to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @param {*} [accumulator] The initial value. - * @param {boolean} [initAccum] Specify using the first element of `array` as - * the initial value. - * @returns {*} Returns the accumulated value. - */ - function arrayReduce(array, iteratee, accumulator, initAccum) { - var index = -1, - length = array == null ? 0 : array.length; - - if (initAccum && length) { - accumulator = array[++index]; - } - while (++index < length) { - accumulator = iteratee(accumulator, array[index], index, array); - } - return accumulator; - } - - /** - * A specialized version of `_.reduceRight` for arrays without support for - * iteratee shorthands. - * - * @private - * @param {Array} [array] The array to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @param {*} [accumulator] The initial value. - * @param {boolean} [initAccum] Specify using the last element of `array` as - * the initial value. - * @returns {*} Returns the accumulated value. - */ - function arrayReduceRight(array, iteratee, accumulator, initAccum) { - var length = array == null ? 0 : array.length; - if (initAccum && length) { - accumulator = array[--length]; - } - while (length--) { - accumulator = iteratee(accumulator, array[length], length, array); - } - return accumulator; - } - - /** - * A specialized version of `_.some` for arrays without support for iteratee - * shorthands. - * - * @private - * @param {Array} [array] The array to iterate over. - * @param {Function} predicate The function invoked per iteration. - * @returns {boolean} Returns `true` if any element passes the predicate check, - * else `false`. - */ - function arraySome(array, predicate) { - var index = -1, - length = array == null ? 0 : array.length; - - while (++index < length) { - if (predicate(array[index], index, array)) { - return true; - } - } - return false; - } - - /** - * Gets the size of an ASCII `string`. - * - * @private - * @param {string} string The string inspect. - * @returns {number} Returns the string size. - */ - var asciiSize = baseProperty('length'); - - /** - * Converts an ASCII `string` to an array. - * - * @private - * @param {string} string The string to convert. - * @returns {Array} Returns the converted array. - */ - function asciiToArray(string) { - return string.split(''); - } - - /** - * Splits an ASCII `string` into an array of its words. - * - * @private - * @param {string} The string to inspect. - * @returns {Array} Returns the words of `string`. - */ - function asciiWords(string) { - return string.match(reAsciiWord) || []; - } - - /** - * The base implementation of methods like `_.findKey` and `_.findLastKey`, - * without support for iteratee shorthands, which iterates over `collection` - * using `eachFunc`. - * - * @private - * @param {Array|Object} collection The collection to inspect. - * @param {Function} predicate The function invoked per iteration. - * @param {Function} eachFunc The function to iterate over `collection`. - * @returns {*} Returns the found element or its key, else `undefined`. - */ - function baseFindKey(collection, predicate, eachFunc) { - var result; - eachFunc(collection, function(value, key, collection) { - if (predicate(value, key, collection)) { - result = key; - return false; - } - }); - return result; - } - - /** - * The base implementation of `_.findIndex` and `_.findLastIndex` without - * support for iteratee shorthands. - * - * @private - * @param {Array} array The array to inspect. - * @param {Function} predicate The function invoked per iteration. - * @param {number} fromIndex The index to search from. - * @param {boolean} [fromRight] Specify iterating from right to left. - * @returns {number} Returns the index of the matched value, else `-1`. - */ - function baseFindIndex(array, predicate, fromIndex, fromRight) { - var length = array.length, - index = fromIndex + (fromRight ? 1 : -1); - - while ((fromRight ? index-- : ++index < length)) { - if (predicate(array[index], index, array)) { - return index; - } - } - return -1; - } - - /** - * The base implementation of `_.indexOf` without `fromIndex` bounds checks. - * - * @private - * @param {Array} array The array to inspect. - * @param {*} value The value to search for. - * @param {number} fromIndex The index to search from. - * @returns {number} Returns the index of the matched value, else `-1`. - */ - function baseIndexOf(array, value, fromIndex) { - return value === value - ? strictIndexOf(array, value, fromIndex) - : baseFindIndex(array, baseIsNaN, fromIndex); - } - - /** - * This function is like `baseIndexOf` except that it accepts a comparator. - * - * @private - * @param {Array} array The array to inspect. - * @param {*} value The value to search for. - * @param {number} fromIndex The index to search from. - * @param {Function} comparator The comparator invoked per element. - * @returns {number} Returns the index of the matched value, else `-1`. - */ - function baseIndexOfWith(array, value, fromIndex, comparator) { - var index = fromIndex - 1, - length = array.length; - - while (++index < length) { - if (comparator(array[index], value)) { - return index; - } - } - return -1; - } - - /** - * The base implementation of `_.isNaN` without support for number objects. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. - */ - function baseIsNaN(value) { - return value !== value; - } - - /** - * The base implementation of `_.mean` and `_.meanBy` without support for - * iteratee shorthands. - * - * @private - * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @returns {number} Returns the mean. - */ - function baseMean(array, iteratee) { - var length = array == null ? 0 : array.length; - return length ? (baseSum(array, iteratee) / length) : NAN; - } - - /** - * The base implementation of `_.property` without support for deep paths. - * - * @private - * @param {string} key The key of the property to get. - * @returns {Function} Returns the new accessor function. - */ - function baseProperty(key) { - return function(object) { - return object == null ? undefined : object[key]; - }; - } - - /** - * The base implementation of `_.propertyOf` without support for deep paths. - * - * @private - * @param {Object} object The object to query. - * @returns {Function} Returns the new accessor function. - */ - function basePropertyOf(object) { - return function(key) { - return object == null ? undefined : object[key]; - }; - } - - /** - * The base implementation of `_.reduce` and `_.reduceRight`, without support - * for iteratee shorthands, which iterates over `collection` using `eachFunc`. - * - * @private - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @param {*} accumulator The initial value. - * @param {boolean} initAccum Specify using the first or last element of - * `collection` as the initial value. - * @param {Function} eachFunc The function to iterate over `collection`. - * @returns {*} Returns the accumulated value. - */ - function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) { - eachFunc(collection, function(value, index, collection) { - accumulator = initAccum - ? (initAccum = false, value) - : iteratee(accumulator, value, index, collection); - }); - return accumulator; - } - - /** - * The base implementation of `_.sortBy` which uses `comparer` to define the - * sort order of `array` and replaces criteria objects with their corresponding - * values. - * - * @private - * @param {Array} array The array to sort. - * @param {Function} comparer The function to define sort order. - * @returns {Array} Returns `array`. - */ - function baseSortBy(array, comparer) { - var length = array.length; - - array.sort(comparer); - while (length--) { - array[length] = array[length].value; - } - return array; - } - - /** - * The base implementation of `_.sum` and `_.sumBy` without support for - * iteratee shorthands. - * - * @private - * @param {Array} array The array to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @returns {number} Returns the sum. - */ - function baseSum(array, iteratee) { - var result, - index = -1, - length = array.length; - - while (++index < length) { - var current = iteratee(array[index]); - if (current !== undefined) { - result = result === undefined ? current : (result + current); - } - } - return result; - } - - /** - * The base implementation of `_.times` without support for iteratee shorthands - * or max array length checks. - * - * @private - * @param {number} n The number of times to invoke `iteratee`. - * @param {Function} iteratee The function invoked per iteration. - * @returns {Array} Returns the array of results. - */ - function baseTimes(n, iteratee) { - var index = -1, - result = Array(n); - - while (++index < n) { - result[index] = iteratee(index); - } - return result; - } - - /** - * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array - * of key-value pairs for `object` corresponding to the property names of `props`. - * - * @private - * @param {Object} object The object to query. - * @param {Array} props The property names to get values for. - * @returns {Object} Returns the key-value pairs. - */ - function baseToPairs(object, props) { - return arrayMap(props, function(key) { - return [key, object[key]]; - }); - } - - /** - * The base implementation of `_.unary` without support for storing metadata. - * - * @private - * @param {Function} func The function to cap arguments for. - * @returns {Function} Returns the new capped function. - */ - function baseUnary(func) { - return function(value) { - return func(value); - }; - } - - /** - * The base implementation of `_.values` and `_.valuesIn` which creates an - * array of `object` property values corresponding to the property names - * of `props`. - * - * @private - * @param {Object} object The object to query. - * @param {Array} props The property names to get values for. - * @returns {Object} Returns the array of property values. - */ - function baseValues(object, props) { - return arrayMap(props, function(key) { - return object[key]; - }); - } - - /** - * Checks if a `cache` value for `key` exists. - * - * @private - * @param {Object} cache The cache to query. - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. - */ - function cacheHas(cache, key) { - return cache.has(key); - } - - /** - * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol - * that is not found in the character symbols. - * - * @private - * @param {Array} strSymbols The string symbols to inspect. - * @param {Array} chrSymbols The character symbols to find. - * @returns {number} Returns the index of the first unmatched string symbol. - */ - function charsStartIndex(strSymbols, chrSymbols) { - var index = -1, - length = strSymbols.length; - - while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} - return index; - } - - /** - * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol - * that is not found in the character symbols. - * - * @private - * @param {Array} strSymbols The string symbols to inspect. - * @param {Array} chrSymbols The character symbols to find. - * @returns {number} Returns the index of the last unmatched string symbol. - */ - function charsEndIndex(strSymbols, chrSymbols) { - var index = strSymbols.length; - - while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {} - return index; - } - - /** - * Gets the number of `placeholder` occurrences in `array`. - * - * @private - * @param {Array} array The array to inspect. - * @param {*} placeholder The placeholder to search for. - * @returns {number} Returns the placeholder count. - */ - function countHolders(array, placeholder) { - var length = array.length, - result = 0; - - while (length--) { - if (array[length] === placeholder) { - ++result; - } - } - return result; - } - - /** - * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A - * letters to basic Latin letters. - * - * @private - * @param {string} letter The matched letter to deburr. - * @returns {string} Returns the deburred letter. - */ - var deburrLetter = basePropertyOf(deburredLetters); - - /** - * Used by `_.escape` to convert characters to HTML entities. - * - * @private - * @param {string} chr The matched character to escape. - * @returns {string} Returns the escaped character. - */ - var escapeHtmlChar = basePropertyOf(htmlEscapes); - - /** - * Used by `_.template` to escape characters for inclusion in compiled string literals. - * - * @private - * @param {string} chr The matched character to escape. - * @returns {string} Returns the escaped character. - */ - function escapeStringChar(chr) { - return '\\' + stringEscapes[chr]; - } - - /** - * Gets the value at `key` of `object`. - * - * @private - * @param {Object} [object] The object to query. - * @param {string} key The key of the property to get. - * @returns {*} Returns the property value. - */ - function getValue(object, key) { - return object == null ? undefined : object[key]; - } - - /** - * Checks if `string` contains Unicode symbols. - * - * @private - * @param {string} string The string to inspect. - * @returns {boolean} Returns `true` if a symbol is found, else `false`. - */ - function hasUnicode(string) { - return reHasUnicode.test(string); - } - - /** - * Checks if `string` contains a word composed of Unicode symbols. - * - * @private - * @param {string} string The string to inspect. - * @returns {boolean} Returns `true` if a word is found, else `false`. - */ - function hasUnicodeWord(string) { - return reHasUnicodeWord.test(string); - } - - /** - * Converts `iterator` to an array. - * - * @private - * @param {Object} iterator The iterator to convert. - * @returns {Array} Returns the converted array. - */ - function iteratorToArray(iterator) { - var data, - result = []; - - while (!(data = iterator.next()).done) { - result.push(data.value); - } - return result; - } - - /** - * Converts `map` to its key-value pairs. - * - * @private - * @param {Object} map The map to convert. - * @returns {Array} Returns the key-value pairs. - */ - function mapToArray(map) { - var index = -1, - result = Array(map.size); - - map.forEach(function(value, key) { - result[++index] = [key, value]; - }); - return result; - } - - /** - * Creates a unary function that invokes `func` with its argument transformed. - * - * @private - * @param {Function} func The function to wrap. - * @param {Function} transform The argument transform. - * @returns {Function} Returns the new function. - */ - function overArg(func, transform) { - return function(arg) { - return func(transform(arg)); - }; - } - - /** - * Replaces all `placeholder` elements in `array` with an internal placeholder - * and returns an array of their indexes. - * - * @private - * @param {Array} array The array to modify. - * @param {*} placeholder The placeholder to replace. - * @returns {Array} Returns the new array of placeholder indexes. - */ - function replaceHolders(array, placeholder) { - var index = -1, - length = array.length, - resIndex = 0, - result = []; - - while (++index < length) { - var value = array[index]; - if (value === placeholder || value === PLACEHOLDER) { - array[index] = PLACEHOLDER; - result[resIndex++] = index; - } - } - return result; - } - - /** - * Gets the value at `key`, unless `key` is "__proto__". - * - * @private - * @param {Object} object The object to query. - * @param {string} key The key of the property to get. - * @returns {*} Returns the property value. - */ - function safeGet(object, key) { - return key == '__proto__' - ? undefined - : object[key]; - } - - /** - * Converts `set` to an array of its values. - * - * @private - * @param {Object} set The set to convert. - * @returns {Array} Returns the values. - */ - function setToArray(set) { - var index = -1, - result = Array(set.size); - - set.forEach(function(value) { - result[++index] = value; - }); - return result; - } - - /** - * Converts `set` to its value-value pairs. - * - * @private - * @param {Object} set The set to convert. - * @returns {Array} Returns the value-value pairs. - */ - function setToPairs(set) { - var index = -1, - result = Array(set.size); - - set.forEach(function(value) { - result[++index] = [value, value]; - }); - return result; - } - - /** - * A specialized version of `_.indexOf` which performs strict equality - * comparisons of values, i.e. `===`. - * - * @private - * @param {Array} array The array to inspect. - * @param {*} value The value to search for. - * @param {number} fromIndex The index to search from. - * @returns {number} Returns the index of the matched value, else `-1`. - */ - function strictIndexOf(array, value, fromIndex) { - var index = fromIndex - 1, - length = array.length; - - while (++index < length) { - if (array[index] === value) { - return index; - } - } - return -1; - } - - /** - * A specialized version of `_.lastIndexOf` which performs strict equality - * comparisons of values, i.e. `===`. - * - * @private - * @param {Array} array The array to inspect. - * @param {*} value The value to search for. - * @param {number} fromIndex The index to search from. - * @returns {number} Returns the index of the matched value, else `-1`. - */ - function strictLastIndexOf(array, value, fromIndex) { - var index = fromIndex + 1; - while (index--) { - if (array[index] === value) { - return index; - } - } - return index; - } - - /** - * Gets the number of symbols in `string`. - * - * @private - * @param {string} string The string to inspect. - * @returns {number} Returns the string size. - */ - function stringSize(string) { - return hasUnicode(string) - ? unicodeSize(string) - : asciiSize(string); - } - - /** - * Converts `string` to an array. - * - * @private - * @param {string} string The string to convert. - * @returns {Array} Returns the converted array. - */ - function stringToArray(string) { - return hasUnicode(string) - ? unicodeToArray(string) - : asciiToArray(string); - } - - /** - * Used by `_.unescape` to convert HTML entities to characters. - * - * @private - * @param {string} chr The matched character to unescape. - * @returns {string} Returns the unescaped character. - */ - var unescapeHtmlChar = basePropertyOf(htmlUnescapes); - - /** - * Gets the size of a Unicode `string`. - * - * @private - * @param {string} string The string inspect. - * @returns {number} Returns the string size. - */ - function unicodeSize(string) { - var result = reUnicode.lastIndex = 0; - while (reUnicode.test(string)) { - ++result; - } - return result; - } - - /** - * Converts a Unicode `string` to an array. - * - * @private - * @param {string} string The string to convert. - * @returns {Array} Returns the converted array. - */ - function unicodeToArray(string) { - return string.match(reUnicode) || []; - } - - /** - * Splits a Unicode `string` into an array of its words. - * - * @private - * @param {string} The string to inspect. - * @returns {Array} Returns the words of `string`. - */ - function unicodeWords(string) { - return string.match(reUnicodeWord) || []; - } - - /*--------------------------------------------------------------------------*/ - - /** - * Create a new pristine `lodash` function using the `context` object. - * - * @static - * @memberOf _ - * @since 1.1.0 - * @category Util - * @param {Object} [context=root] The context object. - * @returns {Function} Returns a new `lodash` function. - * @example - * - * _.mixin({ 'foo': _.constant('foo') }); - * - * var lodash = _.runInContext(); - * lodash.mixin({ 'bar': lodash.constant('bar') }); - * - * _.isFunction(_.foo); - * // => true - * _.isFunction(_.bar); - * // => false - * - * lodash.isFunction(lodash.foo); - * // => false - * lodash.isFunction(lodash.bar); - * // => true - * - * // Create a suped-up `defer` in Node.js. - * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer; - */ - var runInContext = (function runInContext(context) { - context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps)); - - /** Built-in constructor references. */ - var Array = context.Array, - Date = context.Date, - Error = context.Error, - Function = context.Function, - Math = context.Math, - Object = context.Object, - RegExp = context.RegExp, - String = context.String, - TypeError = context.TypeError; - - /** Used for built-in method references. */ - var arrayProto = Array.prototype, - funcProto = Function.prototype, - objectProto = Object.prototype; - - /** Used to detect overreaching core-js shims. */ - var coreJsData = context['__core-js_shared__']; - - /** Used to resolve the decompiled source of functions. */ - var funcToString = funcProto.toString; - - /** Used to check objects for own properties. */ - var hasOwnProperty = objectProto.hasOwnProperty; - - /** Used to generate unique IDs. */ - var idCounter = 0; - - /** Used to detect methods masquerading as native. */ - var maskSrcKey = (function() { - var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || ''); - return uid ? ('Symbol(src)_1.' + uid) : ''; - }()); - - /** - * Used to resolve the - * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) - * of values. - */ - var nativeObjectToString = objectProto.toString; - - /** Used to infer the `Object` constructor. */ - var objectCtorString = funcToString.call(Object); - - /** Used to restore the original `_` reference in `_.noConflict`. */ - var oldDash = root._; - - /** Used to detect if a method is native. */ - var reIsNative = RegExp('^' + - funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&') - .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$' - ); - - /** Built-in value references. */ - var Buffer = moduleExports ? context.Buffer : undefined, - Symbol = context.Symbol, - Uint8Array = context.Uint8Array, - allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined, - getPrototype = overArg(Object.getPrototypeOf, Object), - objectCreate = Object.create, - propertyIsEnumerable = objectProto.propertyIsEnumerable, - splice = arrayProto.splice, - spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined, - symIterator = Symbol ? Symbol.iterator : undefined, - symToStringTag = Symbol ? Symbol.toStringTag : undefined; - - var defineProperty = (function() { - try { - var func = getNative(Object, 'defineProperty'); - func({}, '', {}); - return func; - } catch (e) {} - }()); - - /** Mocked built-ins. */ - var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout, - ctxNow = Date && Date.now !== root.Date.now && Date.now, - ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout; - - /* Built-in method references for those with the same name as other `lodash` methods. */ - var nativeCeil = Math.ceil, - nativeFloor = Math.floor, - nativeGetSymbols = Object.getOwnPropertySymbols, - nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined, - nativeIsFinite = context.isFinite, - nativeJoin = arrayProto.join, - nativeKeys = overArg(Object.keys, Object), - nativeMax = Math.max, - nativeMin = Math.min, - nativeNow = Date.now, - nativeParseInt = context.parseInt, - nativeRandom = Math.random, - nativeReverse = arrayProto.reverse; - - /* Built-in method references that are verified to be native. */ - var DataView = getNative(context, 'DataView'), - Map = getNative(context, 'Map'), - Promise = getNative(context, 'Promise'), - Set = getNative(context, 'Set'), - WeakMap = getNative(context, 'WeakMap'), - nativeCreate = getNative(Object, 'create'); - - /** Used to store function metadata. */ - var metaMap = WeakMap && new WeakMap; - - /** Used to lookup unminified function names. */ - var realNames = {}; - - /** Used to detect maps, sets, and weakmaps. */ - var dataViewCtorString = toSource(DataView), - mapCtorString = toSource(Map), - promiseCtorString = toSource(Promise), - setCtorString = toSource(Set), - weakMapCtorString = toSource(WeakMap); - - /** Used to convert symbols to primitives and strings. */ - var symbolProto = Symbol ? Symbol.prototype : undefined, - symbolValueOf = symbolProto ? symbolProto.valueOf : undefined, - symbolToString = symbolProto ? symbolProto.toString : undefined; - - /*------------------------------------------------------------------------*/ - - /** - * Creates a `lodash` object which wraps `value` to enable implicit method - * chain sequences. Methods that operate on and return arrays, collections, - * and functions can be chained together. Methods that retrieve a single value - * or may return a primitive value will automatically end the chain sequence - * and return the unwrapped value. Otherwise, the value must be unwrapped - * with `_#value`. - * - * Explicit chain sequences, which must be unwrapped with `_#value`, may be - * enabled using `_.chain`. - * - * The execution of chained methods is lazy, that is, it's deferred until - * `_#value` is implicitly or explicitly called. - * - * Lazy evaluation allows several methods to support shortcut fusion. - * Shortcut fusion is an optimization to merge iteratee calls; this avoids - * the creation of intermediate arrays and can greatly reduce the number of - * iteratee executions. Sections of a chain sequence qualify for shortcut - * fusion if the section is applied to an array and iteratees accept only - * one argument. The heuristic for whether a section qualifies for shortcut - * fusion is subject to change. - * - * Chaining is supported in custom builds as long as the `_#value` method is - * directly or indirectly included in the build. - * - * In addition to lodash methods, wrappers have `Array` and `String` methods. - * - * The wrapper `Array` methods are: - * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift` - * - * The wrapper `String` methods are: - * `replace` and `split` - * - * The wrapper methods that support shortcut fusion are: - * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`, - * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`, - * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray` - * - * The chainable wrapper methods are: - * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`, - * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`, - * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`, - * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`, - * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`, - * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`, - * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`, - * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`, - * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`, - * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`, - * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`, - * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`, - * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`, - * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`, - * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`, - * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`, - * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`, - * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`, - * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`, - * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`, - * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`, - * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`, - * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`, - * `zipObject`, `zipObjectDeep`, and `zipWith` - * - * The wrapper methods that are **not** chainable by default are: - * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`, - * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`, - * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`, - * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`, - * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`, - * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`, - * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`, - * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, - * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, - * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, - * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, - * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, - * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`, - * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`, - * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, - * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`, - * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`, - * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`, - * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`, - * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`, - * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`, - * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`, - * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`, - * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`, - * `upperFirst`, `value`, and `words` - * - * @name _ - * @constructor - * @category Seq - * @param {*} value The value to wrap in a `lodash` instance. - * @returns {Object} Returns the new `lodash` wrapper instance. - * @example - * - * function square(n) { - * return n * n; - * } - * - * var wrapped = _([1, 2, 3]); - * - * // Returns an unwrapped value. - * wrapped.reduce(_.add); - * // => 6 - * - * // Returns a wrapped value. - * var squares = wrapped.map(square); - * - * _.isArray(squares); - * // => false - * - * _.isArray(squares.value()); - * // => true - */ - function lodash(value) { - if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) { - if (value instanceof LodashWrapper) { - return value; - } - if (hasOwnProperty.call(value, '__wrapped__')) { - return wrapperClone(value); - } - } - return new LodashWrapper(value); - } - - /** - * The base implementation of `_.create` without support for assigning - * properties to the created object. - * - * @private - * @param {Object} proto The object to inherit from. - * @returns {Object} Returns the new object. - */ - var baseCreate = (function() { - function object() {} - return function(proto) { - if (!isObject(proto)) { - return {}; - } - if (objectCreate) { - return objectCreate(proto); - } - object.prototype = proto; - var result = new object; - object.prototype = undefined; - return result; - }; - }()); - - /** - * The function whose prototype chain sequence wrappers inherit from. - * - * @private - */ - function baseLodash() { - // No operation performed. - } - - /** - * The base constructor for creating `lodash` wrapper objects. - * - * @private - * @param {*} value The value to wrap. - * @param {boolean} [chainAll] Enable explicit method chain sequences. - */ - function LodashWrapper(value, chainAll) { - this.__wrapped__ = value; - this.__actions__ = []; - this.__chain__ = !!chainAll; - this.__index__ = 0; - this.__values__ = undefined; - } - - /** - * By default, the template delimiters used by lodash are like those in - * embedded Ruby (ERB) as well as ES2015 template strings. Change the - * following template settings to use alternative delimiters. - * - * @static - * @memberOf _ - * @type {Object} - */ - lodash.templateSettings = { - - /** - * Used to detect `data` property values to be HTML-escaped. - * - * @memberOf _.templateSettings - * @type {RegExp} - */ - 'escape': reEscape, - - /** - * Used to detect code to be evaluated. - * - * @memberOf _.templateSettings - * @type {RegExp} - */ - 'evaluate': reEvaluate, - - /** - * Used to detect `data` property values to inject. - * - * @memberOf _.templateSettings - * @type {RegExp} - */ - 'interpolate': reInterpolate, - - /** - * Used to reference the data object in the template text. - * - * @memberOf _.templateSettings - * @type {string} - */ - 'variable': '', - - /** - * Used to import variables into the compiled template. - * - * @memberOf _.templateSettings - * @type {Object} - */ - 'imports': { - - /** - * A reference to the `lodash` function. - * - * @memberOf _.templateSettings.imports - * @type {Function} - */ - '_': lodash - } - }; - - // Ensure wrappers are instances of `baseLodash`. - lodash.prototype = baseLodash.prototype; - lodash.prototype.constructor = lodash; - - LodashWrapper.prototype = baseCreate(baseLodash.prototype); - LodashWrapper.prototype.constructor = LodashWrapper; - - /*------------------------------------------------------------------------*/ - - /** - * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation. - * - * @private - * @constructor - * @param {*} value The value to wrap. - */ - function LazyWrapper(value) { - this.__wrapped__ = value; - this.__actions__ = []; - this.__dir__ = 1; - this.__filtered__ = false; - this.__iteratees__ = []; - this.__takeCount__ = MAX_ARRAY_LENGTH; - this.__views__ = []; - } - - /** - * Creates a clone of the lazy wrapper object. - * - * @private - * @name clone - * @memberOf LazyWrapper - * @returns {Object} Returns the cloned `LazyWrapper` object. - */ - function lazyClone() { - var result = new LazyWrapper(this.__wrapped__); - result.__actions__ = copyArray(this.__actions__); - result.__dir__ = this.__dir__; - result.__filtered__ = this.__filtered__; - result.__iteratees__ = copyArray(this.__iteratees__); - result.__takeCount__ = this.__takeCount__; - result.__views__ = copyArray(this.__views__); - return result; - } - - /** - * Reverses the direction of lazy iteration. - * - * @private - * @name reverse - * @memberOf LazyWrapper - * @returns {Object} Returns the new reversed `LazyWrapper` object. - */ - function lazyReverse() { - if (this.__filtered__) { - var result = new LazyWrapper(this); - result.__dir__ = -1; - result.__filtered__ = true; - } else { - result = this.clone(); - result.__dir__ *= -1; - } - return result; - } - - /** - * Extracts the unwrapped value from its lazy wrapper. - * - * @private - * @name value - * @memberOf LazyWrapper - * @returns {*} Returns the unwrapped value. - */ - function lazyValue() { - var array = this.__wrapped__.value(), - dir = this.__dir__, - isArr = isArray(array), - isRight = dir < 0, - arrLength = isArr ? array.length : 0, - view = getView(0, arrLength, this.__views__), - start = view.start, - end = view.end, - length = end - start, - index = isRight ? end : (start - 1), - iteratees = this.__iteratees__, - iterLength = iteratees.length, - resIndex = 0, - takeCount = nativeMin(length, this.__takeCount__); - - if (!isArr || (!isRight && arrLength == length && takeCount == length)) { - return baseWrapperValue(array, this.__actions__); - } - var result = []; - - outer: - while (length-- && resIndex < takeCount) { - index += dir; - - var iterIndex = -1, - value = array[index]; - - while (++iterIndex < iterLength) { - var data = iteratees[iterIndex], - iteratee = data.iteratee, - type = data.type, - computed = iteratee(value); - - if (type == LAZY_MAP_FLAG) { - value = computed; - } else if (!computed) { - if (type == LAZY_FILTER_FLAG) { - continue outer; - } else { - break outer; - } - } - } - result[resIndex++] = value; - } - return result; - } - - // Ensure `LazyWrapper` is an instance of `baseLodash`. - LazyWrapper.prototype = baseCreate(baseLodash.prototype); - LazyWrapper.prototype.constructor = LazyWrapper; - - /*------------------------------------------------------------------------*/ - - /** - * Creates a hash object. - * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. - */ - function Hash(entries) { - var index = -1, - length = entries == null ? 0 : entries.length; - - this.clear(); - while (++index < length) { - var entry = entries[index]; - this.set(entry[0], entry[1]); - } - } - - /** - * Removes all key-value entries from the hash. - * - * @private - * @name clear - * @memberOf Hash - */ - function hashClear() { - this.__data__ = nativeCreate ? nativeCreate(null) : {}; - this.size = 0; - } - - /** - * Removes `key` and its value from the hash. - * - * @private - * @name delete - * @memberOf Hash - * @param {Object} hash The hash to modify. - * @param {string} key The key of the value to remove. - * @returns {boolean} Returns `true` if the entry was removed, else `false`. - */ - function hashDelete(key) { - var result = this.has(key) && delete this.__data__[key]; - this.size -= result ? 1 : 0; - return result; - } - - /** - * Gets the hash value for `key`. - * - * @private - * @name get - * @memberOf Hash - * @param {string} key The key of the value to get. - * @returns {*} Returns the entry value. - */ - function hashGet(key) { - var data = this.__data__; - if (nativeCreate) { - var result = data[key]; - return result === HASH_UNDEFINED ? undefined : result; - } - return hasOwnProperty.call(data, key) ? data[key] : undefined; - } - - /** - * Checks if a hash value for `key` exists. - * - * @private - * @name has - * @memberOf Hash - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. - */ - function hashHas(key) { - var data = this.__data__; - return nativeCreate ? (data[key] !== undefined) : hasOwnProperty.call(data, key); - } - - /** - * Sets the hash `key` to `value`. - * - * @private - * @name set - * @memberOf Hash - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the hash instance. - */ - function hashSet(key, value) { - var data = this.__data__; - this.size += this.has(key) ? 0 : 1; - data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value; - return this; - } - - // Add methods to `Hash`. - Hash.prototype.clear = hashClear; - Hash.prototype['delete'] = hashDelete; - Hash.prototype.get = hashGet; - Hash.prototype.has = hashHas; - Hash.prototype.set = hashSet; - - /*------------------------------------------------------------------------*/ - - /** - * Creates an list cache object. - * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. - */ - function ListCache(entries) { - var index = -1, - length = entries == null ? 0 : entries.length; - - this.clear(); - while (++index < length) { - var entry = entries[index]; - this.set(entry[0], entry[1]); - } - } - - /** - * Removes all key-value entries from the list cache. - * - * @private - * @name clear - * @memberOf ListCache - */ - function listCacheClear() { - this.__data__ = []; - this.size = 0; - } - - /** - * Removes `key` and its value from the list cache. - * - * @private - * @name delete - * @memberOf ListCache - * @param {string} key The key of the value to remove. - * @returns {boolean} Returns `true` if the entry was removed, else `false`. - */ - function listCacheDelete(key) { - var data = this.__data__, - index = assocIndexOf(data, key); - - if (index < 0) { - return false; - } - var lastIndex = data.length - 1; - if (index == lastIndex) { - data.pop(); - } else { - splice.call(data, index, 1); - } - --this.size; - return true; - } - - /** - * Gets the list cache value for `key`. - * - * @private - * @name get - * @memberOf ListCache - * @param {string} key The key of the value to get. - * @returns {*} Returns the entry value. - */ - function listCacheGet(key) { - var data = this.__data__, - index = assocIndexOf(data, key); - - return index < 0 ? undefined : data[index][1]; - } - - /** - * Checks if a list cache value for `key` exists. - * - * @private - * @name has - * @memberOf ListCache - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. - */ - function listCacheHas(key) { - return assocIndexOf(this.__data__, key) > -1; - } - - /** - * Sets the list cache `key` to `value`. - * - * @private - * @name set - * @memberOf ListCache - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the list cache instance. - */ - function listCacheSet(key, value) { - var data = this.__data__, - index = assocIndexOf(data, key); - - if (index < 0) { - ++this.size; - data.push([key, value]); - } else { - data[index][1] = value; - } - return this; - } - - // Add methods to `ListCache`. - ListCache.prototype.clear = listCacheClear; - ListCache.prototype['delete'] = listCacheDelete; - ListCache.prototype.get = listCacheGet; - ListCache.prototype.has = listCacheHas; - ListCache.prototype.set = listCacheSet; - - /*------------------------------------------------------------------------*/ - - /** - * Creates a map cache object to store key-value pairs. - * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. - */ - function MapCache(entries) { - var index = -1, - length = entries == null ? 0 : entries.length; - - this.clear(); - while (++index < length) { - var entry = entries[index]; - this.set(entry[0], entry[1]); - } - } - - /** - * Removes all key-value entries from the map. - * - * @private - * @name clear - * @memberOf MapCache - */ - function mapCacheClear() { - this.size = 0; - this.__data__ = { - 'hash': new Hash, - 'map': new (Map || ListCache), - 'string': new Hash - }; - } - - /** - * Removes `key` and its value from the map. - * - * @private - * @name delete - * @memberOf MapCache - * @param {string} key The key of the value to remove. - * @returns {boolean} Returns `true` if the entry was removed, else `false`. - */ - function mapCacheDelete(key) { - var result = getMapData(this, key)['delete'](key); - this.size -= result ? 1 : 0; - return result; - } - - /** - * Gets the map value for `key`. - * - * @private - * @name get - * @memberOf MapCache - * @param {string} key The key of the value to get. - * @returns {*} Returns the entry value. - */ - function mapCacheGet(key) { - return getMapData(this, key).get(key); - } - - /** - * Checks if a map value for `key` exists. - * - * @private - * @name has - * @memberOf MapCache - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. - */ - function mapCacheHas(key) { - return getMapData(this, key).has(key); - } - - /** - * Sets the map `key` to `value`. - * - * @private - * @name set - * @memberOf MapCache - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the map cache instance. - */ - function mapCacheSet(key, value) { - var data = getMapData(this, key), - size = data.size; - - data.set(key, value); - this.size += data.size == size ? 0 : 1; - return this; - } - - // Add methods to `MapCache`. - MapCache.prototype.clear = mapCacheClear; - MapCache.prototype['delete'] = mapCacheDelete; - MapCache.prototype.get = mapCacheGet; - MapCache.prototype.has = mapCacheHas; - MapCache.prototype.set = mapCacheSet; - - /*------------------------------------------------------------------------*/ - - /** - * - * Creates an array cache object to store unique values. - * - * @private - * @constructor - * @param {Array} [values] The values to cache. - */ - function SetCache(values) { - var index = -1, - length = values == null ? 0 : values.length; - - this.__data__ = new MapCache; - while (++index < length) { - this.add(values[index]); - } - } - - /** - * Adds `value` to the array cache. - * - * @private - * @name add - * @memberOf SetCache - * @alias push - * @param {*} value The value to cache. - * @returns {Object} Returns the cache instance. - */ - function setCacheAdd(value) { - this.__data__.set(value, HASH_UNDEFINED); - return this; - } - - /** - * Checks if `value` is in the array cache. - * - * @private - * @name has - * @memberOf SetCache - * @param {*} value The value to search for. - * @returns {number} Returns `true` if `value` is found, else `false`. - */ - function setCacheHas(value) { - return this.__data__.has(value); - } - - // Add methods to `SetCache`. - SetCache.prototype.add = SetCache.prototype.push = setCacheAdd; - SetCache.prototype.has = setCacheHas; - - /*------------------------------------------------------------------------*/ - - /** - * Creates a stack cache object to store key-value pairs. - * - * @private - * @constructor - * @param {Array} [entries] The key-value pairs to cache. - */ - function Stack(entries) { - var data = this.__data__ = new ListCache(entries); - this.size = data.size; - } - - /** - * Removes all key-value entries from the stack. - * - * @private - * @name clear - * @memberOf Stack - */ - function stackClear() { - this.__data__ = new ListCache; - this.size = 0; - } - - /** - * Removes `key` and its value from the stack. - * - * @private - * @name delete - * @memberOf Stack - * @param {string} key The key of the value to remove. - * @returns {boolean} Returns `true` if the entry was removed, else `false`. - */ - function stackDelete(key) { - var data = this.__data__, - result = data['delete'](key); - - this.size = data.size; - return result; - } - - /** - * Gets the stack value for `key`. - * - * @private - * @name get - * @memberOf Stack - * @param {string} key The key of the value to get. - * @returns {*} Returns the entry value. - */ - function stackGet(key) { - return this.__data__.get(key); - } - - /** - * Checks if a stack value for `key` exists. - * - * @private - * @name has - * @memberOf Stack - * @param {string} key The key of the entry to check. - * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`. - */ - function stackHas(key) { - return this.__data__.has(key); - } - - /** - * Sets the stack `key` to `value`. - * - * @private - * @name set - * @memberOf Stack - * @param {string} key The key of the value to set. - * @param {*} value The value to set. - * @returns {Object} Returns the stack cache instance. - */ - function stackSet(key, value) { - var data = this.__data__; - if (data instanceof ListCache) { - var pairs = data.__data__; - if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) { - pairs.push([key, value]); - this.size = ++data.size; - return this; - } - data = this.__data__ = new MapCache(pairs); - } - data.set(key, value); - this.size = data.size; - return this; - } - - // Add methods to `Stack`. - Stack.prototype.clear = stackClear; - Stack.prototype['delete'] = stackDelete; - Stack.prototype.get = stackGet; - Stack.prototype.has = stackHas; - Stack.prototype.set = stackSet; - - /*------------------------------------------------------------------------*/ - - /** - * Creates an array of the enumerable property names of the array-like `value`. - * - * @private - * @param {*} value The value to query. - * @param {boolean} inherited Specify returning inherited property names. - * @returns {Array} Returns the array of property names. - */ - function arrayLikeKeys(value, inherited) { - var isArr = isArray(value), - isArg = !isArr && isArguments(value), - isBuff = !isArr && !isArg && isBuffer(value), - isType = !isArr && !isArg && !isBuff && isTypedArray(value), - skipIndexes = isArr || isArg || isBuff || isType, - result = skipIndexes ? baseTimes(value.length, String) : [], - length = result.length; - - for (var key in value) { - if ((inherited || hasOwnProperty.call(value, key)) && - !(skipIndexes && ( - // Safari 9 has enumerable `arguments.length` in strict mode. - key == 'length' || - // Node.js 0.10 has enumerable non-index properties on buffers. - (isBuff && (key == 'offset' || key == 'parent')) || - // PhantomJS 2 has enumerable non-index properties on typed arrays. - (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) || - // Skip index properties. - isIndex(key, length) - ))) { - result.push(key); - } - } - return result; - } - - /** - * A specialized version of `_.sample` for arrays. - * - * @private - * @param {Array} array The array to sample. - * @returns {*} Returns the random element. - */ - function arraySample(array) { - var length = array.length; - return length ? array[baseRandom(0, length - 1)] : undefined; - } - - /** - * A specialized version of `_.sampleSize` for arrays. - * - * @private - * @param {Array} array The array to sample. - * @param {number} n The number of elements to sample. - * @returns {Array} Returns the random elements. - */ - function arraySampleSize(array, n) { - return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length)); - } - - /** - * A specialized version of `_.shuffle` for arrays. - * - * @private - * @param {Array} array The array to shuffle. - * @returns {Array} Returns the new shuffled array. - */ - function arrayShuffle(array) { - return shuffleSelf(copyArray(array)); - } - - /** - * This function is like `assignValue` except that it doesn't assign - * `undefined` values. - * - * @private - * @param {Object} object The object to modify. - * @param {string} key The key of the property to assign. - * @param {*} value The value to assign. - */ - function assignMergeValue(object, key, value) { - if ((value !== undefined && !eq(object[key], value)) || - (value === undefined && !(key in object))) { - baseAssignValue(object, key, value); - } - } - - /** - * Assigns `value` to `key` of `object` if the existing value is not equivalent - * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons. - * - * @private - * @param {Object} object The object to modify. - * @param {string} key The key of the property to assign. - * @param {*} value The value to assign. - */ - function assignValue(object, key, value) { - var objValue = object[key]; - if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || - (value === undefined && !(key in object))) { - baseAssignValue(object, key, value); - } - } - - /** - * Gets the index at which the `key` is found in `array` of key-value pairs. - * - * @private - * @param {Array} array The array to inspect. - * @param {*} key The key to search for. - * @returns {number} Returns the index of the matched value, else `-1`. - */ - function assocIndexOf(array, key) { - var length = array.length; - while (length--) { - if (eq(array[length][0], key)) { - return length; - } - } - return -1; - } - - /** - * Aggregates elements of `collection` on `accumulator` with keys transformed - * by `iteratee` and values set by `setter`. - * - * @private - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} setter The function to set `accumulator` values. - * @param {Function} iteratee The iteratee to transform keys. - * @param {Object} accumulator The initial aggregated object. - * @returns {Function} Returns `accumulator`. - */ - function baseAggregator(collection, setter, iteratee, accumulator) { - baseEach(collection, function(value, key, collection) { - setter(accumulator, value, iteratee(value), collection); - }); - return accumulator; - } - - /** - * The base implementation of `_.assign` without support for multiple sources - * or `customizer` functions. - * - * @private - * @param {Object} object The destination object. - * @param {Object} source The source object. - * @returns {Object} Returns `object`. - */ - function baseAssign(object, source) { - return object && copyObject(source, keys(source), object); - } - - /** - * The base implementation of `_.assignIn` without support for multiple sources - * or `customizer` functions. - * - * @private - * @param {Object} object The destination object. - * @param {Object} source The source object. - * @returns {Object} Returns `object`. - */ - function baseAssignIn(object, source) { - return object && copyObject(source, keysIn(source), object); - } - - /** - * The base implementation of `assignValue` and `assignMergeValue` without - * value checks. - * - * @private - * @param {Object} object The object to modify. - * @param {string} key The key of the property to assign. - * @param {*} value The value to assign. - */ - function baseAssignValue(object, key, value) { - if (key == '__proto__' && defineProperty) { - defineProperty(object, key, { - 'configurable': true, - 'enumerable': true, - 'value': value, - 'writable': true - }); - } else { - object[key] = value; - } - } - - /** - * The base implementation of `_.at` without support for individual paths. - * - * @private - * @param {Object} object The object to iterate over. - * @param {string[]} paths The property paths to pick. - * @returns {Array} Returns the picked elements. - */ - function baseAt(object, paths) { - var index = -1, - length = paths.length, - result = Array(length), - skip = object == null; - - while (++index < length) { - result[index] = skip ? undefined : get(object, paths[index]); - } - return result; - } - - /** - * The base implementation of `_.clamp` which doesn't coerce arguments. - * - * @private - * @param {number} number The number to clamp. - * @param {number} [lower] The lower bound. - * @param {number} upper The upper bound. - * @returns {number} Returns the clamped number. - */ - function baseClamp(number, lower, upper) { - if (number === number) { - if (upper !== undefined) { - number = number <= upper ? number : upper; - } - if (lower !== undefined) { - number = number >= lower ? number : lower; - } - } - return number; - } - - /** - * The base implementation of `_.clone` and `_.cloneDeep` which tracks - * traversed objects. - * - * @private - * @param {*} value The value to clone. - * @param {boolean} bitmask The bitmask flags. - * 1 - Deep clone - * 2 - Flatten inherited properties - * 4 - Clone symbols - * @param {Function} [customizer] The function to customize cloning. - * @param {string} [key] The key of `value`. - * @param {Object} [object] The parent object of `value`. - * @param {Object} [stack] Tracks traversed objects and their clone counterparts. - * @returns {*} Returns the cloned value. - */ - function baseClone(value, bitmask, customizer, key, object, stack) { - var result, - isDeep = bitmask & CLONE_DEEP_FLAG, - isFlat = bitmask & CLONE_FLAT_FLAG, - isFull = bitmask & CLONE_SYMBOLS_FLAG; - - if (customizer) { - result = object ? customizer(value, key, object, stack) : customizer(value); - } - if (result !== undefined) { - return result; - } - if (!isObject(value)) { - return value; - } - var isArr = isArray(value); - if (isArr) { - result = initCloneArray(value); - if (!isDeep) { - return copyArray(value, result); - } - } else { - var tag = getTag(value), - isFunc = tag == funcTag || tag == genTag; - - if (isBuffer(value)) { - return cloneBuffer(value, isDeep); - } - if (tag == objectTag || tag == argsTag || (isFunc && !object)) { - result = (isFlat || isFunc) ? {} : initCloneObject(value); - if (!isDeep) { - return isFlat - ? copySymbolsIn(value, baseAssignIn(result, value)) - : copySymbols(value, baseAssign(result, value)); - } - } else { - if (!cloneableTags[tag]) { - return object ? value : {}; - } - result = initCloneByTag(value, tag, isDeep); - } - } - // Check for circular references and return its corresponding clone. - stack || (stack = new Stack); - var stacked = stack.get(value); - if (stacked) { - return stacked; - } - stack.set(value, result); - - if (isSet(value)) { - value.forEach(function(subValue) { - result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack)); - }); - - return result; - } - - if (isMap(value)) { - value.forEach(function(subValue, key) { - result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack)); - }); - - return result; - } - - var keysFunc = isFull - ? (isFlat ? getAllKeysIn : getAllKeys) - : (isFlat ? keysIn : keys); - - var props = isArr ? undefined : keysFunc(value); - arrayEach(props || value, function(subValue, key) { - if (props) { - key = subValue; - subValue = value[key]; - } - // Recursively populate clone (susceptible to call stack limits). - assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack)); - }); - return result; - } - - /** - * The base implementation of `_.conforms` which doesn't clone `source`. - * - * @private - * @param {Object} source The object of property predicates to conform to. - * @returns {Function} Returns the new spec function. - */ - function baseConforms(source) { - var props = keys(source); - return function(object) { - return baseConformsTo(object, source, props); - }; - } - - /** - * The base implementation of `_.conformsTo` which accepts `props` to check. - * - * @private - * @param {Object} object The object to inspect. - * @param {Object} source The object of property predicates to conform to. - * @returns {boolean} Returns `true` if `object` conforms, else `false`. - */ - function baseConformsTo(object, source, props) { - var length = props.length; - if (object == null) { - return !length; - } - object = Object(object); - while (length--) { - var key = props[length], - predicate = source[key], - value = object[key]; - - if ((value === undefined && !(key in object)) || !predicate(value)) { - return false; - } - } - return true; - } - - /** - * The base implementation of `_.delay` and `_.defer` which accepts `args` - * to provide to `func`. - * - * @private - * @param {Function} func The function to delay. - * @param {number} wait The number of milliseconds to delay invocation. - * @param {Array} args The arguments to provide to `func`. - * @returns {number|Object} Returns the timer id or timeout object. - */ - function baseDelay(func, wait, args) { - if (typeof func != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - return setTimeout(function() { func.apply(undefined, args); }, wait); - } - - /** - * The base implementation of methods like `_.difference` without support - * for excluding multiple arrays or iteratee shorthands. - * - * @private - * @param {Array} array The array to inspect. - * @param {Array} values The values to exclude. - * @param {Function} [iteratee] The iteratee invoked per element. - * @param {Function} [comparator] The comparator invoked per element. - * @returns {Array} Returns the new array of filtered values. - */ - function baseDifference(array, values, iteratee, comparator) { - var index = -1, - includes = arrayIncludes, - isCommon = true, - length = array.length, - result = [], - valuesLength = values.length; - - if (!length) { - return result; - } - if (iteratee) { - values = arrayMap(values, baseUnary(iteratee)); - } - if (comparator) { - includes = arrayIncludesWith; - isCommon = false; - } - else if (values.length >= LARGE_ARRAY_SIZE) { - includes = cacheHas; - isCommon = false; - values = new SetCache(values); - } - outer: - while (++index < length) { - var value = array[index], - computed = iteratee == null ? value : iteratee(value); - - value = (comparator || value !== 0) ? value : 0; - if (isCommon && computed === computed) { - var valuesIndex = valuesLength; - while (valuesIndex--) { - if (values[valuesIndex] === computed) { - continue outer; - } - } - result.push(value); - } - else if (!includes(values, computed, comparator)) { - result.push(value); - } - } - return result; - } - - /** - * The base implementation of `_.forEach` without support for iteratee shorthands. - * - * @private - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @returns {Array|Object} Returns `collection`. - */ - var baseEach = createBaseEach(baseForOwn); - - /** - * The base implementation of `_.forEachRight` without support for iteratee shorthands. - * - * @private - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @returns {Array|Object} Returns `collection`. - */ - var baseEachRight = createBaseEach(baseForOwnRight, true); - - /** - * The base implementation of `_.every` without support for iteratee shorthands. - * - * @private - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} predicate The function invoked per iteration. - * @returns {boolean} Returns `true` if all elements pass the predicate check, - * else `false` - */ - function baseEvery(collection, predicate) { - var result = true; - baseEach(collection, function(value, index, collection) { - result = !!predicate(value, index, collection); - return result; - }); - return result; - } - - /** - * The base implementation of methods like `_.max` and `_.min` which accepts a - * `comparator` to determine the extremum value. - * - * @private - * @param {Array} array The array to iterate over. - * @param {Function} iteratee The iteratee invoked per iteration. - * @param {Function} comparator The comparator used to compare values. - * @returns {*} Returns the extremum value. - */ - function baseExtremum(array, iteratee, comparator) { - var index = -1, - length = array.length; - - while (++index < length) { - var value = array[index], - current = iteratee(value); - - if (current != null && (computed === undefined - ? (current === current && !isSymbol(current)) - : comparator(current, computed) - )) { - var computed = current, - result = value; - } - } - return result; - } - - /** - * The base implementation of `_.fill` without an iteratee call guard. - * - * @private - * @param {Array} array The array to fill. - * @param {*} value The value to fill `array` with. - * @param {number} [start=0] The start position. - * @param {number} [end=array.length] The end position. - * @returns {Array} Returns `array`. - */ - function baseFill(array, value, start, end) { - var length = array.length; - - start = toInteger(start); - if (start < 0) { - start = -start > length ? 0 : (length + start); - } - end = (end === undefined || end > length) ? length : toInteger(end); - if (end < 0) { - end += length; - } - end = start > end ? 0 : toLength(end); - while (start < end) { - array[start++] = value; - } - return array; - } - - /** - * The base implementation of `_.filter` without support for iteratee shorthands. - * - * @private - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} predicate The function invoked per iteration. - * @returns {Array} Returns the new filtered array. - */ - function baseFilter(collection, predicate) { - var result = []; - baseEach(collection, function(value, index, collection) { - if (predicate(value, index, collection)) { - result.push(value); - } - }); - return result; - } - - /** - * The base implementation of `_.flatten` with support for restricting flattening. - * - * @private - * @param {Array} array The array to flatten. - * @param {number} depth The maximum recursion depth. - * @param {boolean} [predicate=isFlattenable] The function invoked per iteration. - * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks. - * @param {Array} [result=[]] The initial result value. - * @returns {Array} Returns the new flattened array. - */ - function baseFlatten(array, depth, predicate, isStrict, result) { - var index = -1, - length = array.length; - - predicate || (predicate = isFlattenable); - result || (result = []); - - while (++index < length) { - var value = array[index]; - if (depth > 0 && predicate(value)) { - if (depth > 1) { - // Recursively flatten arrays (susceptible to call stack limits). - baseFlatten(value, depth - 1, predicate, isStrict, result); - } else { - arrayPush(result, value); - } - } else if (!isStrict) { - result[result.length] = value; - } - } - return result; - } - - /** - * The base implementation of `baseForOwn` which iterates over `object` - * properties returned by `keysFunc` and invokes `iteratee` for each property. - * Iteratee functions may exit iteration early by explicitly returning `false`. - * - * @private - * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @param {Function} keysFunc The function to get the keys of `object`. - * @returns {Object} Returns `object`. - */ - var baseFor = createBaseFor(); - - /** - * This function is like `baseFor` except that it iterates over properties - * in the opposite order. - * - * @private - * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @param {Function} keysFunc The function to get the keys of `object`. - * @returns {Object} Returns `object`. - */ - var baseForRight = createBaseFor(true); - - /** - * The base implementation of `_.forOwn` without support for iteratee shorthands. - * - * @private - * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @returns {Object} Returns `object`. - */ - function baseForOwn(object, iteratee) { - return object && baseFor(object, iteratee, keys); - } - - /** - * The base implementation of `_.forOwnRight` without support for iteratee shorthands. - * - * @private - * @param {Object} object The object to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @returns {Object} Returns `object`. - */ - function baseForOwnRight(object, iteratee) { - return object && baseForRight(object, iteratee, keys); - } - - /** - * The base implementation of `_.functions` which creates an array of - * `object` function property names filtered from `props`. - * - * @private - * @param {Object} object The object to inspect. - * @param {Array} props The property names to filter. - * @returns {Array} Returns the function names. - */ - function baseFunctions(object, props) { - return arrayFilter(props, function(key) { - return isFunction(object[key]); - }); - } - - /** - * The base implementation of `_.get` without support for default values. - * - * @private - * @param {Object} object The object to query. - * @param {Array|string} path The path of the property to get. - * @returns {*} Returns the resolved value. - */ - function baseGet(object, path) { - path = castPath(path, object); - - var index = 0, - length = path.length; - - while (object != null && index < length) { - object = object[toKey(path[index++])]; - } - return (index && index == length) ? object : undefined; - } - - /** - * The base implementation of `getAllKeys` and `getAllKeysIn` which uses - * `keysFunc` and `symbolsFunc` to get the enumerable property names and - * symbols of `object`. - * - * @private - * @param {Object} object The object to query. - * @param {Function} keysFunc The function to get the keys of `object`. - * @param {Function} symbolsFunc The function to get the symbols of `object`. - * @returns {Array} Returns the array of property names and symbols. - */ - function baseGetAllKeys(object, keysFunc, symbolsFunc) { - var result = keysFunc(object); - return isArray(object) ? result : arrayPush(result, symbolsFunc(object)); - } - - /** - * The base implementation of `getTag` without fallbacks for buggy environments. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the `toStringTag`. - */ - function baseGetTag(value) { - if (value == null) { - return value === undefined ? undefinedTag : nullTag; - } - return (symToStringTag && symToStringTag in Object(value)) - ? getRawTag(value) - : objectToString(value); - } - - /** - * The base implementation of `_.gt` which doesn't coerce arguments. - * - * @private - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if `value` is greater than `other`, - * else `false`. - */ - function baseGt(value, other) { - return value > other; - } - - /** - * The base implementation of `_.has` without support for deep paths. - * - * @private - * @param {Object} [object] The object to query. - * @param {Array|string} key The key to check. - * @returns {boolean} Returns `true` if `key` exists, else `false`. - */ - function baseHas(object, key) { - return object != null && hasOwnProperty.call(object, key); - } - - /** - * The base implementation of `_.hasIn` without support for deep paths. - * - * @private - * @param {Object} [object] The object to query. - * @param {Array|string} key The key to check. - * @returns {boolean} Returns `true` if `key` exists, else `false`. - */ - function baseHasIn(object, key) { - return object != null && key in Object(object); - } - - /** - * The base implementation of `_.inRange` which doesn't coerce arguments. - * - * @private - * @param {number} number The number to check. - * @param {number} start The start of the range. - * @param {number} end The end of the range. - * @returns {boolean} Returns `true` if `number` is in the range, else `false`. - */ - function baseInRange(number, start, end) { - return number >= nativeMin(start, end) && number < nativeMax(start, end); - } - - /** - * The base implementation of methods like `_.intersection`, without support - * for iteratee shorthands, that accepts an array of arrays to inspect. - * - * @private - * @param {Array} arrays The arrays to inspect. - * @param {Function} [iteratee] The iteratee invoked per element. - * @param {Function} [comparator] The comparator invoked per element. - * @returns {Array} Returns the new array of shared values. - */ - function baseIntersection(arrays, iteratee, comparator) { - var includes = comparator ? arrayIncludesWith : arrayIncludes, - length = arrays[0].length, - othLength = arrays.length, - othIndex = othLength, - caches = Array(othLength), - maxLength = Infinity, - result = []; - - while (othIndex--) { - var array = arrays[othIndex]; - if (othIndex && iteratee) { - array = arrayMap(array, baseUnary(iteratee)); - } - maxLength = nativeMin(array.length, maxLength); - caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120)) - ? new SetCache(othIndex && array) - : undefined; - } - array = arrays[0]; - - var index = -1, - seen = caches[0]; - - outer: - while (++index < length && result.length < maxLength) { - var value = array[index], - computed = iteratee ? iteratee(value) : value; - - value = (comparator || value !== 0) ? value : 0; - if (!(seen - ? cacheHas(seen, computed) - : includes(result, computed, comparator) - )) { - othIndex = othLength; - while (--othIndex) { - var cache = caches[othIndex]; - if (!(cache - ? cacheHas(cache, computed) - : includes(arrays[othIndex], computed, comparator)) - ) { - continue outer; - } - } - if (seen) { - seen.push(computed); - } - result.push(value); - } - } - return result; - } - - /** - * The base implementation of `_.invert` and `_.invertBy` which inverts - * `object` with values transformed by `iteratee` and set by `setter`. - * - * @private - * @param {Object} object The object to iterate over. - * @param {Function} setter The function to set `accumulator` values. - * @param {Function} iteratee The iteratee to transform values. - * @param {Object} accumulator The initial inverted object. - * @returns {Function} Returns `accumulator`. - */ - function baseInverter(object, setter, iteratee, accumulator) { - baseForOwn(object, function(value, key, object) { - setter(accumulator, iteratee(value), key, object); - }); - return accumulator; - } - - /** - * The base implementation of `_.invoke` without support for individual - * method arguments. - * - * @private - * @param {Object} object The object to query. - * @param {Array|string} path The path of the method to invoke. - * @param {Array} args The arguments to invoke the method with. - * @returns {*} Returns the result of the invoked method. - */ - function baseInvoke(object, path, args) { - path = castPath(path, object); - object = parent(object, path); - var func = object == null ? object : object[toKey(last(path))]; - return func == null ? undefined : apply(func, object, args); - } - - /** - * The base implementation of `_.isArguments`. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an `arguments` object, - */ - function baseIsArguments(value) { - return isObjectLike(value) && baseGetTag(value) == argsTag; - } - - /** - * The base implementation of `_.isArrayBuffer` without Node.js optimizations. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. - */ - function baseIsArrayBuffer(value) { - return isObjectLike(value) && baseGetTag(value) == arrayBufferTag; - } - - /** - * The base implementation of `_.isDate` without Node.js optimizations. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a date object, else `false`. - */ - function baseIsDate(value) { - return isObjectLike(value) && baseGetTag(value) == dateTag; - } - - /** - * The base implementation of `_.isEqual` which supports partial comparisons - * and tracks traversed objects. - * - * @private - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @param {boolean} bitmask The bitmask flags. - * 1 - Unordered comparison - * 2 - Partial comparison - * @param {Function} [customizer] The function to customize comparisons. - * @param {Object} [stack] Tracks traversed `value` and `other` objects. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. - */ - function baseIsEqual(value, other, bitmask, customizer, stack) { - if (value === other) { - return true; - } - if (value == null || other == null || (!isObjectLike(value) && !isObjectLike(other))) { - return value !== value && other !== other; - } - return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack); - } - - /** - * A specialized version of `baseIsEqual` for arrays and objects which performs - * deep comparisons and tracks traversed objects enabling objects with circular - * references to be compared. - * - * @private - * @param {Object} object The object to compare. - * @param {Object} other The other object to compare. - * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. - * @param {Function} customizer The function to customize comparisons. - * @param {Function} equalFunc The function to determine equivalents of values. - * @param {Object} [stack] Tracks traversed `object` and `other` objects. - * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. - */ - function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) { - var objIsArr = isArray(object), - othIsArr = isArray(other), - objTag = objIsArr ? arrayTag : getTag(object), - othTag = othIsArr ? arrayTag : getTag(other); - - objTag = objTag == argsTag ? objectTag : objTag; - othTag = othTag == argsTag ? objectTag : othTag; - - var objIsObj = objTag == objectTag, - othIsObj = othTag == objectTag, - isSameTag = objTag == othTag; - - if (isSameTag && isBuffer(object)) { - if (!isBuffer(other)) { - return false; - } - objIsArr = true; - objIsObj = false; - } - if (isSameTag && !objIsObj) { - stack || (stack = new Stack); - return (objIsArr || isTypedArray(object)) - ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) - : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack); - } - if (!(bitmask & COMPARE_PARTIAL_FLAG)) { - var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'), - othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__'); - - if (objIsWrapped || othIsWrapped) { - var objUnwrapped = objIsWrapped ? object.value() : object, - othUnwrapped = othIsWrapped ? other.value() : other; - - stack || (stack = new Stack); - return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack); - } - } - if (!isSameTag) { - return false; - } - stack || (stack = new Stack); - return equalObjects(object, other, bitmask, customizer, equalFunc, stack); - } - - /** - * The base implementation of `_.isMap` without Node.js optimizations. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a map, else `false`. - */ - function baseIsMap(value) { - return isObjectLike(value) && getTag(value) == mapTag; - } - - /** - * The base implementation of `_.isMatch` without support for iteratee shorthands. - * - * @private - * @param {Object} object The object to inspect. - * @param {Object} source The object of property values to match. - * @param {Array} matchData The property names, values, and compare flags to match. - * @param {Function} [customizer] The function to customize comparisons. - * @returns {boolean} Returns `true` if `object` is a match, else `false`. - */ - function baseIsMatch(object, source, matchData, customizer) { - var index = matchData.length, - length = index, - noCustomizer = !customizer; - - if (object == null) { - return !length; - } - object = Object(object); - while (index--) { - var data = matchData[index]; - if ((noCustomizer && data[2]) - ? data[1] !== object[data[0]] - : !(data[0] in object) - ) { - return false; - } - } - while (++index < length) { - data = matchData[index]; - var key = data[0], - objValue = object[key], - srcValue = data[1]; - - if (noCustomizer && data[2]) { - if (objValue === undefined && !(key in object)) { - return false; - } - } else { - var stack = new Stack; - if (customizer) { - var result = customizer(objValue, srcValue, key, object, source, stack); - } - if (!(result === undefined - ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) - : result - )) { - return false; - } - } - } - return true; - } - - /** - * The base implementation of `_.isNative` without bad shim checks. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a native function, - * else `false`. - */ - function baseIsNative(value) { - if (!isObject(value) || isMasked(value)) { - return false; - } - var pattern = isFunction(value) ? reIsNative : reIsHostCtor; - return pattern.test(toSource(value)); - } - - /** - * The base implementation of `_.isRegExp` without Node.js optimizations. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. - */ - function baseIsRegExp(value) { - return isObjectLike(value) && baseGetTag(value) == regexpTag; - } - - /** - * The base implementation of `_.isSet` without Node.js optimizations. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a set, else `false`. - */ - function baseIsSet(value) { - return isObjectLike(value) && getTag(value) == setTag; - } - - /** - * The base implementation of `_.isTypedArray` without Node.js optimizations. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. - */ - function baseIsTypedArray(value) { - return isObjectLike(value) && - isLength(value.length) && !!typedArrayTags[baseGetTag(value)]; - } - - /** - * The base implementation of `_.iteratee`. - * - * @private - * @param {*} [value=_.identity] The value to convert to an iteratee. - * @returns {Function} Returns the iteratee. - */ - function baseIteratee(value) { - // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9. - // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details. - if (typeof value == 'function') { - return value; - } - if (value == null) { - return identity; - } - if (typeof value == 'object') { - return isArray(value) - ? baseMatchesProperty(value[0], value[1]) - : baseMatches(value); - } - return property(value); - } - - /** - * The base implementation of `_.keys` which doesn't treat sparse arrays as dense. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - */ - function baseKeys(object) { - if (!isPrototype(object)) { - return nativeKeys(object); - } - var result = []; - for (var key in Object(object)) { - if (hasOwnProperty.call(object, key) && key != 'constructor') { - result.push(key); - } - } - return result; - } - - /** - * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - */ - function baseKeysIn(object) { - if (!isObject(object)) { - return nativeKeysIn(object); - } - var isProto = isPrototype(object), - result = []; - - for (var key in object) { - if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) { - result.push(key); - } - } - return result; - } - - /** - * The base implementation of `_.lt` which doesn't coerce arguments. - * - * @private - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if `value` is less than `other`, - * else `false`. - */ - function baseLt(value, other) { - return value < other; - } - - /** - * The base implementation of `_.map` without support for iteratee shorthands. - * - * @private - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} iteratee The function invoked per iteration. - * @returns {Array} Returns the new mapped array. - */ - function baseMap(collection, iteratee) { - var index = -1, - result = isArrayLike(collection) ? Array(collection.length) : []; - - baseEach(collection, function(value, key, collection) { - result[++index] = iteratee(value, key, collection); - }); - return result; - } - - /** - * The base implementation of `_.matches` which doesn't clone `source`. - * - * @private - * @param {Object} source The object of property values to match. - * @returns {Function} Returns the new spec function. - */ - function baseMatches(source) { - var matchData = getMatchData(source); - if (matchData.length == 1 && matchData[0][2]) { - return matchesStrictComparable(matchData[0][0], matchData[0][1]); - } - return function(object) { - return object === source || baseIsMatch(object, source, matchData); - }; - } - - /** - * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`. - * - * @private - * @param {string} path The path of the property to get. - * @param {*} srcValue The value to match. - * @returns {Function} Returns the new spec function. - */ - function baseMatchesProperty(path, srcValue) { - if (isKey(path) && isStrictComparable(srcValue)) { - return matchesStrictComparable(toKey(path), srcValue); - } - return function(object) { - var objValue = get(object, path); - return (objValue === undefined && objValue === srcValue) - ? hasIn(object, path) - : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG); - }; - } - - /** - * The base implementation of `_.merge` without support for multiple sources. - * - * @private - * @param {Object} object The destination object. - * @param {Object} source The source object. - * @param {number} srcIndex The index of `source`. - * @param {Function} [customizer] The function to customize merged values. - * @param {Object} [stack] Tracks traversed source values and their merged - * counterparts. - */ - function baseMerge(object, source, srcIndex, customizer, stack) { - if (object === source) { - return; - } - baseFor(source, function(srcValue, key) { - if (isObject(srcValue)) { - stack || (stack = new Stack); - baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack); - } - else { - var newValue = customizer - ? customizer(safeGet(object, key), srcValue, (key + ''), object, source, stack) - : undefined; - - if (newValue === undefined) { - newValue = srcValue; - } - assignMergeValue(object, key, newValue); - } - }, keysIn); - } - - /** - * A specialized version of `baseMerge` for arrays and objects which performs - * deep merges and tracks traversed objects enabling objects with circular - * references to be merged. - * - * @private - * @param {Object} object The destination object. - * @param {Object} source The source object. - * @param {string} key The key of the value to merge. - * @param {number} srcIndex The index of `source`. - * @param {Function} mergeFunc The function to merge values. - * @param {Function} [customizer] The function to customize assigned values. - * @param {Object} [stack] Tracks traversed source values and their merged - * counterparts. - */ - function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) { - var objValue = safeGet(object, key), - srcValue = safeGet(source, key), - stacked = stack.get(srcValue); - - if (stacked) { - assignMergeValue(object, key, stacked); - return; - } - var newValue = customizer - ? customizer(objValue, srcValue, (key + ''), object, source, stack) - : undefined; - - var isCommon = newValue === undefined; - - if (isCommon) { - var isArr = isArray(srcValue), - isBuff = !isArr && isBuffer(srcValue), - isTyped = !isArr && !isBuff && isTypedArray(srcValue); - - newValue = srcValue; - if (isArr || isBuff || isTyped) { - if (isArray(objValue)) { - newValue = objValue; - } - else if (isArrayLikeObject(objValue)) { - newValue = copyArray(objValue); - } - else if (isBuff) { - isCommon = false; - newValue = cloneBuffer(srcValue, true); - } - else if (isTyped) { - isCommon = false; - newValue = cloneTypedArray(srcValue, true); - } - else { - newValue = []; - } - } - else if (isPlainObject(srcValue) || isArguments(srcValue)) { - newValue = objValue; - if (isArguments(objValue)) { - newValue = toPlainObject(objValue); - } - else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) { - newValue = initCloneObject(srcValue); - } - } - else { - isCommon = false; - } - } - if (isCommon) { - // Recursively merge objects and arrays (susceptible to call stack limits). - stack.set(srcValue, newValue); - mergeFunc(newValue, srcValue, srcIndex, customizer, stack); - stack['delete'](srcValue); - } - assignMergeValue(object, key, newValue); - } - - /** - * The base implementation of `_.nth` which doesn't coerce arguments. - * - * @private - * @param {Array} array The array to query. - * @param {number} n The index of the element to return. - * @returns {*} Returns the nth element of `array`. - */ - function baseNth(array, n) { - var length = array.length; - if (!length) { - return; - } - n += n < 0 ? length : 0; - return isIndex(n, length) ? array[n] : undefined; - } - - /** - * The base implementation of `_.orderBy` without param guards. - * - * @private - * @param {Array|Object} collection The collection to iterate over. - * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by. - * @param {string[]} orders The sort orders of `iteratees`. - * @returns {Array} Returns the new sorted array. - */ - function baseOrderBy(collection, iteratees, orders) { - var index = -1; - iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(getIteratee())); - - var result = baseMap(collection, function(value, key, collection) { - var criteria = arrayMap(iteratees, function(iteratee) { - return iteratee(value); - }); - return { 'criteria': criteria, 'index': ++index, 'value': value }; - }); - - return baseSortBy(result, function(object, other) { - return compareMultiple(object, other, orders); - }); - } - - /** - * The base implementation of `_.pick` without support for individual - * property identifiers. - * - * @private - * @param {Object} object The source object. - * @param {string[]} paths The property paths to pick. - * @returns {Object} Returns the new object. - */ - function basePick(object, paths) { - return basePickBy(object, paths, function(value, path) { - return hasIn(object, path); - }); - } - - /** - * The base implementation of `_.pickBy` without support for iteratee shorthands. - * - * @private - * @param {Object} object The source object. - * @param {string[]} paths The property paths to pick. - * @param {Function} predicate The function invoked per property. - * @returns {Object} Returns the new object. - */ - function basePickBy(object, paths, predicate) { - var index = -1, - length = paths.length, - result = {}; - - while (++index < length) { - var path = paths[index], - value = baseGet(object, path); - - if (predicate(value, path)) { - baseSet(result, castPath(path, object), value); - } - } - return result; - } - - /** - * A specialized version of `baseProperty` which supports deep paths. - * - * @private - * @param {Array|string} path The path of the property to get. - * @returns {Function} Returns the new accessor function. - */ - function basePropertyDeep(path) { - return function(object) { - return baseGet(object, path); - }; - } - - /** - * The base implementation of `_.pullAllBy` without support for iteratee - * shorthands. - * - * @private - * @param {Array} array The array to modify. - * @param {Array} values The values to remove. - * @param {Function} [iteratee] The iteratee invoked per element. - * @param {Function} [comparator] The comparator invoked per element. - * @returns {Array} Returns `array`. - */ - function basePullAll(array, values, iteratee, comparator) { - var indexOf = comparator ? baseIndexOfWith : baseIndexOf, - index = -1, - length = values.length, - seen = array; - - if (array === values) { - values = copyArray(values); - } - if (iteratee) { - seen = arrayMap(array, baseUnary(iteratee)); - } - while (++index < length) { - var fromIndex = 0, - value = values[index], - computed = iteratee ? iteratee(value) : value; - - while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) { - if (seen !== array) { - splice.call(seen, fromIndex, 1); - } - splice.call(array, fromIndex, 1); - } - } - return array; - } - - /** - * The base implementation of `_.pullAt` without support for individual - * indexes or capturing the removed elements. - * - * @private - * @param {Array} array The array to modify. - * @param {number[]} indexes The indexes of elements to remove. - * @returns {Array} Returns `array`. - */ - function basePullAt(array, indexes) { - var length = array ? indexes.length : 0, - lastIndex = length - 1; - - while (length--) { - var index = indexes[length]; - if (length == lastIndex || index !== previous) { - var previous = index; - if (isIndex(index)) { - splice.call(array, index, 1); - } else { - baseUnset(array, index); - } - } - } - return array; - } - - /** - * The base implementation of `_.random` without support for returning - * floating-point numbers. - * - * @private - * @param {number} lower The lower bound. - * @param {number} upper The upper bound. - * @returns {number} Returns the random number. - */ - function baseRandom(lower, upper) { - return lower + nativeFloor(nativeRandom() * (upper - lower + 1)); - } - - /** - * The base implementation of `_.range` and `_.rangeRight` which doesn't - * coerce arguments. - * - * @private - * @param {number} start The start of the range. - * @param {number} end The end of the range. - * @param {number} step The value to increment or decrement by. - * @param {boolean} [fromRight] Specify iterating from right to left. - * @returns {Array} Returns the range of numbers. - */ - function baseRange(start, end, step, fromRight) { - var index = -1, - length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), - result = Array(length); - - while (length--) { - result[fromRight ? length : ++index] = start; - start += step; - } - return result; - } - - /** - * The base implementation of `_.repeat` which doesn't coerce arguments. - * - * @private - * @param {string} string The string to repeat. - * @param {number} n The number of times to repeat the string. - * @returns {string} Returns the repeated string. - */ - function baseRepeat(string, n) { - var result = ''; - if (!string || n < 1 || n > MAX_SAFE_INTEGER) { - return result; - } - // Leverage the exponentiation by squaring algorithm for a faster repeat. - // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details. - do { - if (n % 2) { - result += string; - } - n = nativeFloor(n / 2); - if (n) { - string += string; - } - } while (n); - - return result; - } - - /** - * The base implementation of `_.rest` which doesn't validate or coerce arguments. - * - * @private - * @param {Function} func The function to apply a rest parameter to. - * @param {number} [start=func.length-1] The start position of the rest parameter. - * @returns {Function} Returns the new function. - */ - function baseRest(func, start) { - return setToString(overRest(func, start, identity), func + ''); - } - - /** - * The base implementation of `_.sample`. - * - * @private - * @param {Array|Object} collection The collection to sample. - * @returns {*} Returns the random element. - */ - function baseSample(collection) { - return arraySample(values(collection)); - } - - /** - * The base implementation of `_.sampleSize` without param guards. - * - * @private - * @param {Array|Object} collection The collection to sample. - * @param {number} n The number of elements to sample. - * @returns {Array} Returns the random elements. - */ - function baseSampleSize(collection, n) { - var array = values(collection); - return shuffleSelf(array, baseClamp(n, 0, array.length)); - } - - /** - * The base implementation of `_.set`. - * - * @private - * @param {Object} object The object to modify. - * @param {Array|string} path The path of the property to set. - * @param {*} value The value to set. - * @param {Function} [customizer] The function to customize path creation. - * @returns {Object} Returns `object`. - */ - function baseSet(object, path, value, customizer) { - if (!isObject(object)) { - return object; - } - path = castPath(path, object); - - var index = -1, - length = path.length, - lastIndex = length - 1, - nested = object; - - while (nested != null && ++index < length) { - var key = toKey(path[index]), - newValue = value; - - if (index != lastIndex) { - var objValue = nested[key]; - newValue = customizer ? customizer(objValue, key, nested) : undefined; - if (newValue === undefined) { - newValue = isObject(objValue) - ? objValue - : (isIndex(path[index + 1]) ? [] : {}); - } - } - assignValue(nested, key, newValue); - nested = nested[key]; - } - return object; - } - - /** - * The base implementation of `setData` without support for hot loop shorting. - * - * @private - * @param {Function} func The function to associate metadata with. - * @param {*} data The metadata. - * @returns {Function} Returns `func`. - */ - var baseSetData = !metaMap ? identity : function(func, data) { - metaMap.set(func, data); - return func; - }; - - /** - * The base implementation of `setToString` without support for hot loop shorting. - * - * @private - * @param {Function} func The function to modify. - * @param {Function} string The `toString` result. - * @returns {Function} Returns `func`. - */ - var baseSetToString = !defineProperty ? identity : function(func, string) { - return defineProperty(func, 'toString', { - 'configurable': true, - 'enumerable': false, - 'value': constant(string), - 'writable': true - }); - }; - - /** - * The base implementation of `_.shuffle`. - * - * @private - * @param {Array|Object} collection The collection to shuffle. - * @returns {Array} Returns the new shuffled array. - */ - function baseShuffle(collection) { - return shuffleSelf(values(collection)); - } - - /** - * The base implementation of `_.slice` without an iteratee call guard. - * - * @private - * @param {Array} array The array to slice. - * @param {number} [start=0] The start position. - * @param {number} [end=array.length] The end position. - * @returns {Array} Returns the slice of `array`. - */ - function baseSlice(array, start, end) { - var index = -1, - length = array.length; - - if (start < 0) { - start = -start > length ? 0 : (length + start); - } - end = end > length ? length : end; - if (end < 0) { - end += length; - } - length = start > end ? 0 : ((end - start) >>> 0); - start >>>= 0; - - var result = Array(length); - while (++index < length) { - result[index] = array[index + start]; - } - return result; - } - - /** - * The base implementation of `_.some` without support for iteratee shorthands. - * - * @private - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} predicate The function invoked per iteration. - * @returns {boolean} Returns `true` if any element passes the predicate check, - * else `false`. - */ - function baseSome(collection, predicate) { - var result; - - baseEach(collection, function(value, index, collection) { - result = predicate(value, index, collection); - return !result; - }); - return !!result; - } - - /** - * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which - * performs a binary search of `array` to determine the index at which `value` - * should be inserted into `array` in order to maintain its sort order. - * - * @private - * @param {Array} array The sorted array to inspect. - * @param {*} value The value to evaluate. - * @param {boolean} [retHighest] Specify returning the highest qualified index. - * @returns {number} Returns the index at which `value` should be inserted - * into `array`. - */ - function baseSortedIndex(array, value, retHighest) { - var low = 0, - high = array == null ? low : array.length; - - if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) { - while (low < high) { - var mid = (low + high) >>> 1, - computed = array[mid]; - - if (computed !== null && !isSymbol(computed) && - (retHighest ? (computed <= value) : (computed < value))) { - low = mid + 1; - } else { - high = mid; - } - } - return high; - } - return baseSortedIndexBy(array, value, identity, retHighest); - } - - /** - * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy` - * which invokes `iteratee` for `value` and each element of `array` to compute - * their sort ranking. The iteratee is invoked with one argument; (value). - * - * @private - * @param {Array} array The sorted array to inspect. - * @param {*} value The value to evaluate. - * @param {Function} iteratee The iteratee invoked per element. - * @param {boolean} [retHighest] Specify returning the highest qualified index. - * @returns {number} Returns the index at which `value` should be inserted - * into `array`. - */ - function baseSortedIndexBy(array, value, iteratee, retHighest) { - value = iteratee(value); - - var low = 0, - high = array == null ? 0 : array.length, - valIsNaN = value !== value, - valIsNull = value === null, - valIsSymbol = isSymbol(value), - valIsUndefined = value === undefined; - - while (low < high) { - var mid = nativeFloor((low + high) / 2), - computed = iteratee(array[mid]), - othIsDefined = computed !== undefined, - othIsNull = computed === null, - othIsReflexive = computed === computed, - othIsSymbol = isSymbol(computed); - - if (valIsNaN) { - var setLow = retHighest || othIsReflexive; - } else if (valIsUndefined) { - setLow = othIsReflexive && (retHighest || othIsDefined); - } else if (valIsNull) { - setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull); - } else if (valIsSymbol) { - setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol); - } else if (othIsNull || othIsSymbol) { - setLow = false; - } else { - setLow = retHighest ? (computed <= value) : (computed < value); - } - if (setLow) { - low = mid + 1; - } else { - high = mid; - } - } - return nativeMin(high, MAX_ARRAY_INDEX); - } - - /** - * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without - * support for iteratee shorthands. - * - * @private - * @param {Array} array The array to inspect. - * @param {Function} [iteratee] The iteratee invoked per element. - * @returns {Array} Returns the new duplicate free array. - */ - function baseSortedUniq(array, iteratee) { - var index = -1, - length = array.length, - resIndex = 0, - result = []; - - while (++index < length) { - var value = array[index], - computed = iteratee ? iteratee(value) : value; - - if (!index || !eq(computed, seen)) { - var seen = computed; - result[resIndex++] = value === 0 ? 0 : value; - } - } - return result; - } - - /** - * The base implementation of `_.toNumber` which doesn't ensure correct - * conversions of binary, hexadecimal, or octal string values. - * - * @private - * @param {*} value The value to process. - * @returns {number} Returns the number. - */ - function baseToNumber(value) { - if (typeof value == 'number') { - return value; - } - if (isSymbol(value)) { - return NAN; - } - return +value; - } - - /** - * The base implementation of `_.toString` which doesn't convert nullish - * values to empty strings. - * - * @private - * @param {*} value The value to process. - * @returns {string} Returns the string. - */ - function baseToString(value) { - // Exit early for strings to avoid a performance hit in some environments. - if (typeof value == 'string') { - return value; - } - if (isArray(value)) { - // Recursively convert values (susceptible to call stack limits). - return arrayMap(value, baseToString) + ''; - } - if (isSymbol(value)) { - return symbolToString ? symbolToString.call(value) : ''; - } - var result = (value + ''); - return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; - } - - /** - * The base implementation of `_.uniqBy` without support for iteratee shorthands. - * - * @private - * @param {Array} array The array to inspect. - * @param {Function} [iteratee] The iteratee invoked per element. - * @param {Function} [comparator] The comparator invoked per element. - * @returns {Array} Returns the new duplicate free array. - */ - function baseUniq(array, iteratee, comparator) { - var index = -1, - includes = arrayIncludes, - length = array.length, - isCommon = true, - result = [], - seen = result; - - if (comparator) { - isCommon = false; - includes = arrayIncludesWith; - } - else if (length >= LARGE_ARRAY_SIZE) { - var set = iteratee ? null : createSet(array); - if (set) { - return setToArray(set); - } - isCommon = false; - includes = cacheHas; - seen = new SetCache; - } - else { - seen = iteratee ? [] : result; - } - outer: - while (++index < length) { - var value = array[index], - computed = iteratee ? iteratee(value) : value; - - value = (comparator || value !== 0) ? value : 0; - if (isCommon && computed === computed) { - var seenIndex = seen.length; - while (seenIndex--) { - if (seen[seenIndex] === computed) { - continue outer; - } - } - if (iteratee) { - seen.push(computed); - } - result.push(value); - } - else if (!includes(seen, computed, comparator)) { - if (seen !== result) { - seen.push(computed); - } - result.push(value); - } - } - return result; - } - - /** - * The base implementation of `_.unset`. - * - * @private - * @param {Object} object The object to modify. - * @param {Array|string} path The property path to unset. - * @returns {boolean} Returns `true` if the property is deleted, else `false`. - */ - function baseUnset(object, path) { - path = castPath(path, object); - object = parent(object, path); - return object == null || delete object[toKey(last(path))]; - } - - /** - * The base implementation of `_.update`. - * - * @private - * @param {Object} object The object to modify. - * @param {Array|string} path The path of the property to update. - * @param {Function} updater The function to produce the updated value. - * @param {Function} [customizer] The function to customize path creation. - * @returns {Object} Returns `object`. - */ - function baseUpdate(object, path, updater, customizer) { - return baseSet(object, path, updater(baseGet(object, path)), customizer); - } - - /** - * The base implementation of methods like `_.dropWhile` and `_.takeWhile` - * without support for iteratee shorthands. - * - * @private - * @param {Array} array The array to query. - * @param {Function} predicate The function invoked per iteration. - * @param {boolean} [isDrop] Specify dropping elements instead of taking them. - * @param {boolean} [fromRight] Specify iterating from right to left. - * @returns {Array} Returns the slice of `array`. - */ - function baseWhile(array, predicate, isDrop, fromRight) { - var length = array.length, - index = fromRight ? length : -1; - - while ((fromRight ? index-- : ++index < length) && - predicate(array[index], index, array)) {} - - return isDrop - ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length)) - : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index)); - } - - /** - * The base implementation of `wrapperValue` which returns the result of - * performing a sequence of actions on the unwrapped `value`, where each - * successive action is supplied the return value of the previous. - * - * @private - * @param {*} value The unwrapped value. - * @param {Array} actions Actions to perform to resolve the unwrapped value. - * @returns {*} Returns the resolved value. - */ - function baseWrapperValue(value, actions) { - var result = value; - if (result instanceof LazyWrapper) { - result = result.value(); - } - return arrayReduce(actions, function(result, action) { - return action.func.apply(action.thisArg, arrayPush([result], action.args)); - }, result); - } - - /** - * The base implementation of methods like `_.xor`, without support for - * iteratee shorthands, that accepts an array of arrays to inspect. - * - * @private - * @param {Array} arrays The arrays to inspect. - * @param {Function} [iteratee] The iteratee invoked per element. - * @param {Function} [comparator] The comparator invoked per element. - * @returns {Array} Returns the new array of values. - */ - function baseXor(arrays, iteratee, comparator) { - var length = arrays.length; - if (length < 2) { - return length ? baseUniq(arrays[0]) : []; - } - var index = -1, - result = Array(length); - - while (++index < length) { - var array = arrays[index], - othIndex = -1; - - while (++othIndex < length) { - if (othIndex != index) { - result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator); - } - } - } - return baseUniq(baseFlatten(result, 1), iteratee, comparator); - } - - /** - * This base implementation of `_.zipObject` which assigns values using `assignFunc`. - * - * @private - * @param {Array} props The property identifiers. - * @param {Array} values The property values. - * @param {Function} assignFunc The function to assign values. - * @returns {Object} Returns the new object. - */ - function baseZipObject(props, values, assignFunc) { - var index = -1, - length = props.length, - valsLength = values.length, - result = {}; - - while (++index < length) { - var value = index < valsLength ? values[index] : undefined; - assignFunc(result, props[index], value); - } - return result; - } - - /** - * Casts `value` to an empty array if it's not an array like object. - * - * @private - * @param {*} value The value to inspect. - * @returns {Array|Object} Returns the cast array-like object. - */ - function castArrayLikeObject(value) { - return isArrayLikeObject(value) ? value : []; - } - - /** - * Casts `value` to `identity` if it's not a function. - * - * @private - * @param {*} value The value to inspect. - * @returns {Function} Returns cast function. - */ - function castFunction(value) { - return typeof value == 'function' ? value : identity; - } - - /** - * Casts `value` to a path array if it's not one. - * - * @private - * @param {*} value The value to inspect. - * @param {Object} [object] The object to query keys on. - * @returns {Array} Returns the cast property path array. - */ - function castPath(value, object) { - if (isArray(value)) { - return value; - } - return isKey(value, object) ? [value] : stringToPath(toString(value)); - } - - /** - * A `baseRest` alias which can be replaced with `identity` by module - * replacement plugins. - * - * @private - * @type {Function} - * @param {Function} func The function to apply a rest parameter to. - * @returns {Function} Returns the new function. - */ - var castRest = baseRest; - - /** - * Casts `array` to a slice if it's needed. - * - * @private - * @param {Array} array The array to inspect. - * @param {number} start The start position. - * @param {number} [end=array.length] The end position. - * @returns {Array} Returns the cast slice. - */ - function castSlice(array, start, end) { - var length = array.length; - end = end === undefined ? length : end; - return (!start && end >= length) ? array : baseSlice(array, start, end); - } - - /** - * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout). - * - * @private - * @param {number|Object} id The timer id or timeout object of the timer to clear. - */ - var clearTimeout = ctxClearTimeout || function(id) { - return root.clearTimeout(id); - }; - - /** - * Creates a clone of `buffer`. - * - * @private - * @param {Buffer} buffer The buffer to clone. - * @param {boolean} [isDeep] Specify a deep clone. - * @returns {Buffer} Returns the cloned buffer. - */ - function cloneBuffer(buffer, isDeep) { - if (isDeep) { - return buffer.slice(); - } - var length = buffer.length, - result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length); - - buffer.copy(result); - return result; - } - - /** - * Creates a clone of `arrayBuffer`. - * - * @private - * @param {ArrayBuffer} arrayBuffer The array buffer to clone. - * @returns {ArrayBuffer} Returns the cloned array buffer. - */ - function cloneArrayBuffer(arrayBuffer) { - var result = new arrayBuffer.constructor(arrayBuffer.byteLength); - new Uint8Array(result).set(new Uint8Array(arrayBuffer)); - return result; - } - - /** - * Creates a clone of `dataView`. - * - * @private - * @param {Object} dataView The data view to clone. - * @param {boolean} [isDeep] Specify a deep clone. - * @returns {Object} Returns the cloned data view. - */ - function cloneDataView(dataView, isDeep) { - var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer; - return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength); - } - - /** - * Creates a clone of `regexp`. - * - * @private - * @param {Object} regexp The regexp to clone. - * @returns {Object} Returns the cloned regexp. - */ - function cloneRegExp(regexp) { - var result = new regexp.constructor(regexp.source, reFlags.exec(regexp)); - result.lastIndex = regexp.lastIndex; - return result; - } - - /** - * Creates a clone of the `symbol` object. - * - * @private - * @param {Object} symbol The symbol object to clone. - * @returns {Object} Returns the cloned symbol object. - */ - function cloneSymbol(symbol) { - return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {}; - } - - /** - * Creates a clone of `typedArray`. - * - * @private - * @param {Object} typedArray The typed array to clone. - * @param {boolean} [isDeep] Specify a deep clone. - * @returns {Object} Returns the cloned typed array. - */ - function cloneTypedArray(typedArray, isDeep) { - var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer; - return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length); - } - - /** - * Compares values to sort them in ascending order. - * - * @private - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @returns {number} Returns the sort order indicator for `value`. - */ - function compareAscending(value, other) { - if (value !== other) { - var valIsDefined = value !== undefined, - valIsNull = value === null, - valIsReflexive = value === value, - valIsSymbol = isSymbol(value); - - var othIsDefined = other !== undefined, - othIsNull = other === null, - othIsReflexive = other === other, - othIsSymbol = isSymbol(other); - - if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) || - (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) || - (valIsNull && othIsDefined && othIsReflexive) || - (!valIsDefined && othIsReflexive) || - !valIsReflexive) { - return 1; - } - if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) || - (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) || - (othIsNull && valIsDefined && valIsReflexive) || - (!othIsDefined && valIsReflexive) || - !othIsReflexive) { - return -1; - } - } - return 0; - } - - /** - * Used by `_.orderBy` to compare multiple properties of a value to another - * and stable sort them. - * - * If `orders` is unspecified, all values are sorted in ascending order. Otherwise, - * specify an order of "desc" for descending or "asc" for ascending sort order - * of corresponding values. - * - * @private - * @param {Object} object The object to compare. - * @param {Object} other The other object to compare. - * @param {boolean[]|string[]} orders The order to sort by for each property. - * @returns {number} Returns the sort order indicator for `object`. - */ - function compareMultiple(object, other, orders) { - var index = -1, - objCriteria = object.criteria, - othCriteria = other.criteria, - length = objCriteria.length, - ordersLength = orders.length; - - while (++index < length) { - var result = compareAscending(objCriteria[index], othCriteria[index]); - if (result) { - if (index >= ordersLength) { - return result; - } - var order = orders[index]; - return result * (order == 'desc' ? -1 : 1); - } - } - // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications - // that causes it, under certain circumstances, to provide the same value for - // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247 - // for more details. - // - // This also ensures a stable sort in V8 and other engines. - // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details. - return object.index - other.index; - } - - /** - * Creates an array that is the composition of partially applied arguments, - * placeholders, and provided arguments into a single array of arguments. - * - * @private - * @param {Array} args The provided arguments. - * @param {Array} partials The arguments to prepend to those provided. - * @param {Array} holders The `partials` placeholder indexes. - * @params {boolean} [isCurried] Specify composing for a curried function. - * @returns {Array} Returns the new array of composed arguments. - */ - function composeArgs(args, partials, holders, isCurried) { - var argsIndex = -1, - argsLength = args.length, - holdersLength = holders.length, - leftIndex = -1, - leftLength = partials.length, - rangeLength = nativeMax(argsLength - holdersLength, 0), - result = Array(leftLength + rangeLength), - isUncurried = !isCurried; - - while (++leftIndex < leftLength) { - result[leftIndex] = partials[leftIndex]; - } - while (++argsIndex < holdersLength) { - if (isUncurried || argsIndex < argsLength) { - result[holders[argsIndex]] = args[argsIndex]; - } - } - while (rangeLength--) { - result[leftIndex++] = args[argsIndex++]; - } - return result; - } - - /** - * This function is like `composeArgs` except that the arguments composition - * is tailored for `_.partialRight`. - * - * @private - * @param {Array} args The provided arguments. - * @param {Array} partials The arguments to append to those provided. - * @param {Array} holders The `partials` placeholder indexes. - * @params {boolean} [isCurried] Specify composing for a curried function. - * @returns {Array} Returns the new array of composed arguments. - */ - function composeArgsRight(args, partials, holders, isCurried) { - var argsIndex = -1, - argsLength = args.length, - holdersIndex = -1, - holdersLength = holders.length, - rightIndex = -1, - rightLength = partials.length, - rangeLength = nativeMax(argsLength - holdersLength, 0), - result = Array(rangeLength + rightLength), - isUncurried = !isCurried; - - while (++argsIndex < rangeLength) { - result[argsIndex] = args[argsIndex]; - } - var offset = argsIndex; - while (++rightIndex < rightLength) { - result[offset + rightIndex] = partials[rightIndex]; - } - while (++holdersIndex < holdersLength) { - if (isUncurried || argsIndex < argsLength) { - result[offset + holders[holdersIndex]] = args[argsIndex++]; - } - } - return result; - } - - /** - * Copies the values of `source` to `array`. - * - * @private - * @param {Array} source The array to copy values from. - * @param {Array} [array=[]] The array to copy values to. - * @returns {Array} Returns `array`. - */ - function copyArray(source, array) { - var index = -1, - length = source.length; - - array || (array = Array(length)); - while (++index < length) { - array[index] = source[index]; - } - return array; - } - - /** - * Copies properties of `source` to `object`. - * - * @private - * @param {Object} source The object to copy properties from. - * @param {Array} props The property identifiers to copy. - * @param {Object} [object={}] The object to copy properties to. - * @param {Function} [customizer] The function to customize copied values. - * @returns {Object} Returns `object`. - */ - function copyObject(source, props, object, customizer) { - var isNew = !object; - object || (object = {}); - - var index = -1, - length = props.length; - - while (++index < length) { - var key = props[index]; - - var newValue = customizer - ? customizer(object[key], source[key], key, object, source) - : undefined; - - if (newValue === undefined) { - newValue = source[key]; - } - if (isNew) { - baseAssignValue(object, key, newValue); - } else { - assignValue(object, key, newValue); - } - } - return object; - } - - /** - * Copies own symbols of `source` to `object`. - * - * @private - * @param {Object} source The object to copy symbols from. - * @param {Object} [object={}] The object to copy symbols to. - * @returns {Object} Returns `object`. - */ - function copySymbols(source, object) { - return copyObject(source, getSymbols(source), object); - } - - /** - * Copies own and inherited symbols of `source` to `object`. - * - * @private - * @param {Object} source The object to copy symbols from. - * @param {Object} [object={}] The object to copy symbols to. - * @returns {Object} Returns `object`. - */ - function copySymbolsIn(source, object) { - return copyObject(source, getSymbolsIn(source), object); - } - - /** - * Creates a function like `_.groupBy`. - * - * @private - * @param {Function} setter The function to set accumulator values. - * @param {Function} [initializer] The accumulator object initializer. - * @returns {Function} Returns the new aggregator function. - */ - function createAggregator(setter, initializer) { - return function(collection, iteratee) { - var func = isArray(collection) ? arrayAggregator : baseAggregator, - accumulator = initializer ? initializer() : {}; - - return func(collection, setter, getIteratee(iteratee, 2), accumulator); - }; - } - - /** - * Creates a function like `_.assign`. - * - * @private - * @param {Function} assigner The function to assign values. - * @returns {Function} Returns the new assigner function. - */ - function createAssigner(assigner) { - return baseRest(function(object, sources) { - var index = -1, - length = sources.length, - customizer = length > 1 ? sources[length - 1] : undefined, - guard = length > 2 ? sources[2] : undefined; - - customizer = (assigner.length > 3 && typeof customizer == 'function') - ? (length--, customizer) - : undefined; - - if (guard && isIterateeCall(sources[0], sources[1], guard)) { - customizer = length < 3 ? undefined : customizer; - length = 1; - } - object = Object(object); - while (++index < length) { - var source = sources[index]; - if (source) { - assigner(object, source, index, customizer); - } - } - return object; - }); - } - - /** - * Creates a `baseEach` or `baseEachRight` function. - * - * @private - * @param {Function} eachFunc The function to iterate over a collection. - * @param {boolean} [fromRight] Specify iterating from right to left. - * @returns {Function} Returns the new base function. - */ - function createBaseEach(eachFunc, fromRight) { - return function(collection, iteratee) { - if (collection == null) { - return collection; - } - if (!isArrayLike(collection)) { - return eachFunc(collection, iteratee); - } - var length = collection.length, - index = fromRight ? length : -1, - iterable = Object(collection); - - while ((fromRight ? index-- : ++index < length)) { - if (iteratee(iterable[index], index, iterable) === false) { - break; - } - } - return collection; - }; - } - - /** - * Creates a base function for methods like `_.forIn` and `_.forOwn`. - * - * @private - * @param {boolean} [fromRight] Specify iterating from right to left. - * @returns {Function} Returns the new base function. - */ - function createBaseFor(fromRight) { - return function(object, iteratee, keysFunc) { - var index = -1, - iterable = Object(object), - props = keysFunc(object), - length = props.length; - - while (length--) { - var key = props[fromRight ? length : ++index]; - if (iteratee(iterable[key], key, iterable) === false) { - break; - } - } - return object; - }; - } - - /** - * Creates a function that wraps `func` to invoke it with the optional `this` - * binding of `thisArg`. - * - * @private - * @param {Function} func The function to wrap. - * @param {number} bitmask The bitmask flags. See `createWrap` for more details. - * @param {*} [thisArg] The `this` binding of `func`. - * @returns {Function} Returns the new wrapped function. - */ - function createBind(func, bitmask, thisArg) { - var isBind = bitmask & WRAP_BIND_FLAG, - Ctor = createCtor(func); - - function wrapper() { - var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; - return fn.apply(isBind ? thisArg : this, arguments); - } - return wrapper; - } - - /** - * Creates a function like `_.lowerFirst`. - * - * @private - * @param {string} methodName The name of the `String` case method to use. - * @returns {Function} Returns the new case function. - */ - function createCaseFirst(methodName) { - return function(string) { - string = toString(string); - - var strSymbols = hasUnicode(string) - ? stringToArray(string) - : undefined; - - var chr = strSymbols - ? strSymbols[0] - : string.charAt(0); - - var trailing = strSymbols - ? castSlice(strSymbols, 1).join('') - : string.slice(1); - - return chr[methodName]() + trailing; - }; - } - - /** - * Creates a function like `_.camelCase`. - * - * @private - * @param {Function} callback The function to combine each word. - * @returns {Function} Returns the new compounder function. - */ - function createCompounder(callback) { - return function(string) { - return arrayReduce(words(deburr(string).replace(reApos, '')), callback, ''); - }; - } - - /** - * Creates a function that produces an instance of `Ctor` regardless of - * whether it was invoked as part of a `new` expression or by `call` or `apply`. - * - * @private - * @param {Function} Ctor The constructor to wrap. - * @returns {Function} Returns the new wrapped function. - */ - function createCtor(Ctor) { - return function() { - // Use a `switch` statement to work with class constructors. See - // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist - // for more details. - var args = arguments; - switch (args.length) { - case 0: return new Ctor; - case 1: return new Ctor(args[0]); - case 2: return new Ctor(args[0], args[1]); - case 3: return new Ctor(args[0], args[1], args[2]); - case 4: return new Ctor(args[0], args[1], args[2], args[3]); - case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]); - case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]); - case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); - } - var thisBinding = baseCreate(Ctor.prototype), - result = Ctor.apply(thisBinding, args); - - // Mimic the constructor's `return` behavior. - // See https://es5.github.io/#x13.2.2 for more details. - return isObject(result) ? result : thisBinding; - }; - } - - /** - * Creates a function that wraps `func` to enable currying. - * - * @private - * @param {Function} func The function to wrap. - * @param {number} bitmask The bitmask flags. See `createWrap` for more details. - * @param {number} arity The arity of `func`. - * @returns {Function} Returns the new wrapped function. - */ - function createCurry(func, bitmask, arity) { - var Ctor = createCtor(func); - - function wrapper() { - var length = arguments.length, - args = Array(length), - index = length, - placeholder = getHolder(wrapper); - - while (index--) { - args[index] = arguments[index]; - } - var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder) - ? [] - : replaceHolders(args, placeholder); - - length -= holders.length; - if (length < arity) { - return createRecurry( - func, bitmask, createHybrid, wrapper.placeholder, undefined, - args, holders, undefined, undefined, arity - length); - } - var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; - return apply(fn, this, args); - } - return wrapper; - } - - /** - * Creates a `_.find` or `_.findLast` function. - * - * @private - * @param {Function} findIndexFunc The function to find the collection index. - * @returns {Function} Returns the new find function. - */ - function createFind(findIndexFunc) { - return function(collection, predicate, fromIndex) { - var iterable = Object(collection); - if (!isArrayLike(collection)) { - var iteratee = getIteratee(predicate, 3); - collection = keys(collection); - predicate = function(key) { return iteratee(iterable[key], key, iterable); }; - } - var index = findIndexFunc(collection, predicate, fromIndex); - return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined; - }; - } - - /** - * Creates a `_.flow` or `_.flowRight` function. - * - * @private - * @param {boolean} [fromRight] Specify iterating from right to left. - * @returns {Function} Returns the new flow function. - */ - function createFlow(fromRight) { - return flatRest(function(funcs) { - var length = funcs.length, - index = length, - prereq = LodashWrapper.prototype.thru; - - if (fromRight) { - funcs.reverse(); - } - while (index--) { - var func = funcs[index]; - if (typeof func != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - if (prereq && !wrapper && getFuncName(func) == 'wrapper') { - var wrapper = new LodashWrapper([], true); - } - } - index = wrapper ? index : length; - while (++index < length) { - func = funcs[index]; - - var funcName = getFuncName(func), - data = funcName == 'wrapper' ? getData(func) : undefined; - - if (data && isLaziable(data[0]) && - data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) && - !data[4].length && data[9] == 1 - ) { - wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]); - } else { - wrapper = (func.length == 1 && isLaziable(func)) - ? wrapper[funcName]() - : wrapper.thru(func); - } - } - return function() { - var args = arguments, - value = args[0]; - - if (wrapper && args.length == 1 && isArray(value)) { - return wrapper.plant(value).value(); - } - var index = 0, - result = length ? funcs[index].apply(this, args) : value; - - while (++index < length) { - result = funcs[index].call(this, result); - } - return result; - }; - }); - } - - /** - * Creates a function that wraps `func` to invoke it with optional `this` - * binding of `thisArg`, partial application, and currying. - * - * @private - * @param {Function|string} func The function or method name to wrap. - * @param {number} bitmask The bitmask flags. See `createWrap` for more details. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {Array} [partials] The arguments to prepend to those provided to - * the new function. - * @param {Array} [holders] The `partials` placeholder indexes. - * @param {Array} [partialsRight] The arguments to append to those provided - * to the new function. - * @param {Array} [holdersRight] The `partialsRight` placeholder indexes. - * @param {Array} [argPos] The argument positions of the new function. - * @param {number} [ary] The arity cap of `func`. - * @param {number} [arity] The arity of `func`. - * @returns {Function} Returns the new wrapped function. - */ - function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) { - var isAry = bitmask & WRAP_ARY_FLAG, - isBind = bitmask & WRAP_BIND_FLAG, - isBindKey = bitmask & WRAP_BIND_KEY_FLAG, - isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG), - isFlip = bitmask & WRAP_FLIP_FLAG, - Ctor = isBindKey ? undefined : createCtor(func); - - function wrapper() { - var length = arguments.length, - args = Array(length), - index = length; - - while (index--) { - args[index] = arguments[index]; - } - if (isCurried) { - var placeholder = getHolder(wrapper), - holdersCount = countHolders(args, placeholder); - } - if (partials) { - args = composeArgs(args, partials, holders, isCurried); - } - if (partialsRight) { - args = composeArgsRight(args, partialsRight, holdersRight, isCurried); - } - length -= holdersCount; - if (isCurried && length < arity) { - var newHolders = replaceHolders(args, placeholder); - return createRecurry( - func, bitmask, createHybrid, wrapper.placeholder, thisArg, - args, newHolders, argPos, ary, arity - length - ); - } - var thisBinding = isBind ? thisArg : this, - fn = isBindKey ? thisBinding[func] : func; - - length = args.length; - if (argPos) { - args = reorder(args, argPos); - } else if (isFlip && length > 1) { - args.reverse(); - } - if (isAry && ary < length) { - args.length = ary; - } - if (this && this !== root && this instanceof wrapper) { - fn = Ctor || createCtor(fn); - } - return fn.apply(thisBinding, args); - } - return wrapper; - } - - /** - * Creates a function like `_.invertBy`. - * - * @private - * @param {Function} setter The function to set accumulator values. - * @param {Function} toIteratee The function to resolve iteratees. - * @returns {Function} Returns the new inverter function. - */ - function createInverter(setter, toIteratee) { - return function(object, iteratee) { - return baseInverter(object, setter, toIteratee(iteratee), {}); - }; - } - - /** - * Creates a function that performs a mathematical operation on two values. - * - * @private - * @param {Function} operator The function to perform the operation. - * @param {number} [defaultValue] The value used for `undefined` arguments. - * @returns {Function} Returns the new mathematical operation function. - */ - function createMathOperation(operator, defaultValue) { - return function(value, other) { - var result; - if (value === undefined && other === undefined) { - return defaultValue; - } - if (value !== undefined) { - result = value; - } - if (other !== undefined) { - if (result === undefined) { - return other; - } - if (typeof value == 'string' || typeof other == 'string') { - value = baseToString(value); - other = baseToString(other); - } else { - value = baseToNumber(value); - other = baseToNumber(other); - } - result = operator(value, other); - } - return result; - }; - } - - /** - * Creates a function like `_.over`. - * - * @private - * @param {Function} arrayFunc The function to iterate over iteratees. - * @returns {Function} Returns the new over function. - */ - function createOver(arrayFunc) { - return flatRest(function(iteratees) { - iteratees = arrayMap(iteratees, baseUnary(getIteratee())); - return baseRest(function(args) { - var thisArg = this; - return arrayFunc(iteratees, function(iteratee) { - return apply(iteratee, thisArg, args); - }); - }); - }); - } - - /** - * Creates the padding for `string` based on `length`. The `chars` string - * is truncated if the number of characters exceeds `length`. - * - * @private - * @param {number} length The padding length. - * @param {string} [chars=' '] The string used as padding. - * @returns {string} Returns the padding for `string`. - */ - function createPadding(length, chars) { - chars = chars === undefined ? ' ' : baseToString(chars); - - var charsLength = chars.length; - if (charsLength < 2) { - return charsLength ? baseRepeat(chars, length) : chars; - } - var result = baseRepeat(chars, nativeCeil(length / stringSize(chars))); - return hasUnicode(chars) - ? castSlice(stringToArray(result), 0, length).join('') - : result.slice(0, length); - } - - /** - * Creates a function that wraps `func` to invoke it with the `this` binding - * of `thisArg` and `partials` prepended to the arguments it receives. - * - * @private - * @param {Function} func The function to wrap. - * @param {number} bitmask The bitmask flags. See `createWrap` for more details. - * @param {*} thisArg The `this` binding of `func`. - * @param {Array} partials The arguments to prepend to those provided to - * the new function. - * @returns {Function} Returns the new wrapped function. - */ - function createPartial(func, bitmask, thisArg, partials) { - var isBind = bitmask & WRAP_BIND_FLAG, - Ctor = createCtor(func); - - function wrapper() { - var argsIndex = -1, - argsLength = arguments.length, - leftIndex = -1, - leftLength = partials.length, - args = Array(leftLength + argsLength), - fn = (this && this !== root && this instanceof wrapper) ? Ctor : func; - - while (++leftIndex < leftLength) { - args[leftIndex] = partials[leftIndex]; - } - while (argsLength--) { - args[leftIndex++] = arguments[++argsIndex]; - } - return apply(fn, isBind ? thisArg : this, args); - } - return wrapper; - } - - /** - * Creates a `_.range` or `_.rangeRight` function. - * - * @private - * @param {boolean} [fromRight] Specify iterating from right to left. - * @returns {Function} Returns the new range function. - */ - function createRange(fromRight) { - return function(start, end, step) { - if (step && typeof step != 'number' && isIterateeCall(start, end, step)) { - end = step = undefined; - } - // Ensure the sign of `-0` is preserved. - start = toFinite(start); - if (end === undefined) { - end = start; - start = 0; - } else { - end = toFinite(end); - } - step = step === undefined ? (start < end ? 1 : -1) : toFinite(step); - return baseRange(start, end, step, fromRight); - }; - } - - /** - * Creates a function that performs a relational operation on two values. - * - * @private - * @param {Function} operator The function to perform the operation. - * @returns {Function} Returns the new relational operation function. - */ - function createRelationalOperation(operator) { - return function(value, other) { - if (!(typeof value == 'string' && typeof other == 'string')) { - value = toNumber(value); - other = toNumber(other); - } - return operator(value, other); - }; - } - - /** - * Creates a function that wraps `func` to continue currying. - * - * @private - * @param {Function} func The function to wrap. - * @param {number} bitmask The bitmask flags. See `createWrap` for more details. - * @param {Function} wrapFunc The function to create the `func` wrapper. - * @param {*} placeholder The placeholder value. - * @param {*} [thisArg] The `this` binding of `func`. - * @param {Array} [partials] The arguments to prepend to those provided to - * the new function. - * @param {Array} [holders] The `partials` placeholder indexes. - * @param {Array} [argPos] The argument positions of the new function. - * @param {number} [ary] The arity cap of `func`. - * @param {number} [arity] The arity of `func`. - * @returns {Function} Returns the new wrapped function. - */ - function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) { - var isCurry = bitmask & WRAP_CURRY_FLAG, - newHolders = isCurry ? holders : undefined, - newHoldersRight = isCurry ? undefined : holders, - newPartials = isCurry ? partials : undefined, - newPartialsRight = isCurry ? undefined : partials; - - bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG); - bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG); - - if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) { - bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG); - } - var newData = [ - func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, - newHoldersRight, argPos, ary, arity - ]; - - var result = wrapFunc.apply(undefined, newData); - if (isLaziable(func)) { - setData(result, newData); - } - result.placeholder = placeholder; - return setWrapToString(result, func, bitmask); - } - - /** - * Creates a function like `_.round`. - * - * @private - * @param {string} methodName The name of the `Math` method to use when rounding. - * @returns {Function} Returns the new round function. - */ - function createRound(methodName) { - var func = Math[methodName]; - return function(number, precision) { - number = toNumber(number); - precision = precision == null ? 0 : nativeMin(toInteger(precision), 292); - if (precision) { - // Shift with exponential notation to avoid floating-point issues. - // See [MDN](https://mdn.io/round#Examples) for more details. - var pair = (toString(number) + 'e').split('e'), - value = func(pair[0] + 'e' + (+pair[1] + precision)); - - pair = (toString(value) + 'e').split('e'); - return +(pair[0] + 'e' + (+pair[1] - precision)); - } - return func(number); - }; - } - - /** - * Creates a set object of `values`. - * - * @private - * @param {Array} values The values to add to the set. - * @returns {Object} Returns the new set. - */ - var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) { - return new Set(values); - }; - - /** - * Creates a `_.toPairs` or `_.toPairsIn` function. - * - * @private - * @param {Function} keysFunc The function to get the keys of a given object. - * @returns {Function} Returns the new pairs function. - */ - function createToPairs(keysFunc) { - return function(object) { - var tag = getTag(object); - if (tag == mapTag) { - return mapToArray(object); - } - if (tag == setTag) { - return setToPairs(object); - } - return baseToPairs(object, keysFunc(object)); - }; - } - - /** - * Creates a function that either curries or invokes `func` with optional - * `this` binding and partially applied arguments. - * - * @private - * @param {Function|string} func The function or method name to wrap. - * @param {number} bitmask The bitmask flags. - * 1 - `_.bind` - * 2 - `_.bindKey` - * 4 - `_.curry` or `_.curryRight` of a bound function - * 8 - `_.curry` - * 16 - `_.curryRight` - * 32 - `_.partial` - * 64 - `_.partialRight` - * 128 - `_.rearg` - * 256 - `_.ary` - * 512 - `_.flip` - * @param {*} [thisArg] The `this` binding of `func`. - * @param {Array} [partials] The arguments to be partially applied. - * @param {Array} [holders] The `partials` placeholder indexes. - * @param {Array} [argPos] The argument positions of the new function. - * @param {number} [ary] The arity cap of `func`. - * @param {number} [arity] The arity of `func`. - * @returns {Function} Returns the new wrapped function. - */ - function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) { - var isBindKey = bitmask & WRAP_BIND_KEY_FLAG; - if (!isBindKey && typeof func != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - var length = partials ? partials.length : 0; - if (!length) { - bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG); - partials = holders = undefined; - } - ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0); - arity = arity === undefined ? arity : toInteger(arity); - length -= holders ? holders.length : 0; - - if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) { - var partialsRight = partials, - holdersRight = holders; - - partials = holders = undefined; - } - var data = isBindKey ? undefined : getData(func); - - var newData = [ - func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, - argPos, ary, arity - ]; - - if (data) { - mergeData(newData, data); - } - func = newData[0]; - bitmask = newData[1]; - thisArg = newData[2]; - partials = newData[3]; - holders = newData[4]; - arity = newData[9] = newData[9] === undefined - ? (isBindKey ? 0 : func.length) - : nativeMax(newData[9] - length, 0); - - if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) { - bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG); - } - if (!bitmask || bitmask == WRAP_BIND_FLAG) { - var result = createBind(func, bitmask, thisArg); - } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) { - result = createCurry(func, bitmask, arity); - } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) { - result = createPartial(func, bitmask, thisArg, partials); - } else { - result = createHybrid.apply(undefined, newData); - } - var setter = data ? baseSetData : setData; - return setWrapToString(setter(result, newData), func, bitmask); - } - - /** - * Used by `_.defaults` to customize its `_.assignIn` use to assign properties - * of source objects to the destination object for all destination properties - * that resolve to `undefined`. - * - * @private - * @param {*} objValue The destination value. - * @param {*} srcValue The source value. - * @param {string} key The key of the property to assign. - * @param {Object} object The parent object of `objValue`. - * @returns {*} Returns the value to assign. - */ - function customDefaultsAssignIn(objValue, srcValue, key, object) { - if (objValue === undefined || - (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) { - return srcValue; - } - return objValue; - } - - /** - * Used by `_.defaultsDeep` to customize its `_.merge` use to merge source - * objects into destination objects that are passed thru. - * - * @private - * @param {*} objValue The destination value. - * @param {*} srcValue The source value. - * @param {string} key The key of the property to merge. - * @param {Object} object The parent object of `objValue`. - * @param {Object} source The parent object of `srcValue`. - * @param {Object} [stack] Tracks traversed source values and their merged - * counterparts. - * @returns {*} Returns the value to assign. - */ - function customDefaultsMerge(objValue, srcValue, key, object, source, stack) { - if (isObject(objValue) && isObject(srcValue)) { - // Recursively merge objects and arrays (susceptible to call stack limits). - stack.set(srcValue, objValue); - baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack); - stack['delete'](srcValue); - } - return objValue; - } - - /** - * Used by `_.omit` to customize its `_.cloneDeep` use to only clone plain - * objects. - * - * @private - * @param {*} value The value to inspect. - * @param {string} key The key of the property to inspect. - * @returns {*} Returns the uncloned value or `undefined` to defer cloning to `_.cloneDeep`. - */ - function customOmitClone(value) { - return isPlainObject(value) ? undefined : value; - } - - /** - * A specialized version of `baseIsEqualDeep` for arrays with support for - * partial deep comparisons. - * - * @private - * @param {Array} array The array to compare. - * @param {Array} other The other array to compare. - * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. - * @param {Function} customizer The function to customize comparisons. - * @param {Function} equalFunc The function to determine equivalents of values. - * @param {Object} stack Tracks traversed `array` and `other` objects. - * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`. - */ - function equalArrays(array, other, bitmask, customizer, equalFunc, stack) { - var isPartial = bitmask & COMPARE_PARTIAL_FLAG, - arrLength = array.length, - othLength = other.length; - - if (arrLength != othLength && !(isPartial && othLength > arrLength)) { - return false; - } - // Assume cyclic values are equal. - var stacked = stack.get(array); - if (stacked && stack.get(other)) { - return stacked == other; - } - var index = -1, - result = true, - seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined; - - stack.set(array, other); - stack.set(other, array); - - // Ignore non-index properties. - while (++index < arrLength) { - var arrValue = array[index], - othValue = other[index]; - - if (customizer) { - var compared = isPartial - ? customizer(othValue, arrValue, index, other, array, stack) - : customizer(arrValue, othValue, index, array, other, stack); - } - if (compared !== undefined) { - if (compared) { - continue; - } - result = false; - break; - } - // Recursively compare arrays (susceptible to call stack limits). - if (seen) { - if (!arraySome(other, function(othValue, othIndex) { - if (!cacheHas(seen, othIndex) && - (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) { - return seen.push(othIndex); - } - })) { - result = false; - break; - } - } else if (!( - arrValue === othValue || - equalFunc(arrValue, othValue, bitmask, customizer, stack) - )) { - result = false; - break; - } - } - stack['delete'](array); - stack['delete'](other); - return result; - } - - /** - * A specialized version of `baseIsEqualDeep` for comparing objects of - * the same `toStringTag`. - * - * **Note:** This function only supports comparing values with tags of - * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`. - * - * @private - * @param {Object} object The object to compare. - * @param {Object} other The other object to compare. - * @param {string} tag The `toStringTag` of the objects to compare. - * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. - * @param {Function} customizer The function to customize comparisons. - * @param {Function} equalFunc The function to determine equivalents of values. - * @param {Object} stack Tracks traversed `object` and `other` objects. - * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. - */ - function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) { - switch (tag) { - case dataViewTag: - if ((object.byteLength != other.byteLength) || - (object.byteOffset != other.byteOffset)) { - return false; - } - object = object.buffer; - other = other.buffer; - - case arrayBufferTag: - if ((object.byteLength != other.byteLength) || - !equalFunc(new Uint8Array(object), new Uint8Array(other))) { - return false; - } - return true; - - case boolTag: - case dateTag: - case numberTag: - // Coerce booleans to `1` or `0` and dates to milliseconds. - // Invalid dates are coerced to `NaN`. - return eq(+object, +other); - - case errorTag: - return object.name == other.name && object.message == other.message; - - case regexpTag: - case stringTag: - // Coerce regexes to strings and treat strings, primitives and objects, - // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring - // for more details. - return object == (other + ''); - - case mapTag: - var convert = mapToArray; - - case setTag: - var isPartial = bitmask & COMPARE_PARTIAL_FLAG; - convert || (convert = setToArray); - - if (object.size != other.size && !isPartial) { - return false; - } - // Assume cyclic values are equal. - var stacked = stack.get(object); - if (stacked) { - return stacked == other; - } - bitmask |= COMPARE_UNORDERED_FLAG; - - // Recursively compare objects (susceptible to call stack limits). - stack.set(object, other); - var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack); - stack['delete'](object); - return result; - - case symbolTag: - if (symbolValueOf) { - return symbolValueOf.call(object) == symbolValueOf.call(other); - } - } - return false; - } - - /** - * A specialized version of `baseIsEqualDeep` for objects with support for - * partial deep comparisons. - * - * @private - * @param {Object} object The object to compare. - * @param {Object} other The other object to compare. - * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details. - * @param {Function} customizer The function to customize comparisons. - * @param {Function} equalFunc The function to determine equivalents of values. - * @param {Object} stack Tracks traversed `object` and `other` objects. - * @returns {boolean} Returns `true` if the objects are equivalent, else `false`. - */ - function equalObjects(object, other, bitmask, customizer, equalFunc, stack) { - var isPartial = bitmask & COMPARE_PARTIAL_FLAG, - objProps = getAllKeys(object), - objLength = objProps.length, - othProps = getAllKeys(other), - othLength = othProps.length; - - if (objLength != othLength && !isPartial) { - return false; - } - var index = objLength; - while (index--) { - var key = objProps[index]; - if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) { - return false; - } - } - // Assume cyclic values are equal. - var stacked = stack.get(object); - if (stacked && stack.get(other)) { - return stacked == other; - } - var result = true; - stack.set(object, other); - stack.set(other, object); - - var skipCtor = isPartial; - while (++index < objLength) { - key = objProps[index]; - var objValue = object[key], - othValue = other[key]; - - if (customizer) { - var compared = isPartial - ? customizer(othValue, objValue, key, other, object, stack) - : customizer(objValue, othValue, key, object, other, stack); - } - // Recursively compare objects (susceptible to call stack limits). - if (!(compared === undefined - ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack)) - : compared - )) { - result = false; - break; - } - skipCtor || (skipCtor = key == 'constructor'); - } - if (result && !skipCtor) { - var objCtor = object.constructor, - othCtor = other.constructor; - - // Non `Object` object instances with different constructors are not equal. - if (objCtor != othCtor && - ('constructor' in object && 'constructor' in other) && - !(typeof objCtor == 'function' && objCtor instanceof objCtor && - typeof othCtor == 'function' && othCtor instanceof othCtor)) { - result = false; - } - } - stack['delete'](object); - stack['delete'](other); - return result; - } - - /** - * A specialized version of `baseRest` which flattens the rest array. - * - * @private - * @param {Function} func The function to apply a rest parameter to. - * @returns {Function} Returns the new function. - */ - function flatRest(func) { - return setToString(overRest(func, undefined, flatten), func + ''); - } - - /** - * Creates an array of own enumerable property names and symbols of `object`. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names and symbols. - */ - function getAllKeys(object) { - return baseGetAllKeys(object, keys, getSymbols); - } - - /** - * Creates an array of own and inherited enumerable property names and - * symbols of `object`. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names and symbols. - */ - function getAllKeysIn(object) { - return baseGetAllKeys(object, keysIn, getSymbolsIn); - } - - /** - * Gets metadata for `func`. - * - * @private - * @param {Function} func The function to query. - * @returns {*} Returns the metadata for `func`. - */ - var getData = !metaMap ? noop : function(func) { - return metaMap.get(func); - }; - - /** - * Gets the name of `func`. - * - * @private - * @param {Function} func The function to query. - * @returns {string} Returns the function name. - */ - function getFuncName(func) { - var result = (func.name + ''), - array = realNames[result], - length = hasOwnProperty.call(realNames, result) ? array.length : 0; - - while (length--) { - var data = array[length], - otherFunc = data.func; - if (otherFunc == null || otherFunc == func) { - return data.name; - } - } - return result; - } - - /** - * Gets the argument placeholder value for `func`. - * - * @private - * @param {Function} func The function to inspect. - * @returns {*} Returns the placeholder value. - */ - function getHolder(func) { - var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func; - return object.placeholder; - } - - /** - * Gets the appropriate "iteratee" function. If `_.iteratee` is customized, - * this function returns the custom method, otherwise it returns `baseIteratee`. - * If arguments are provided, the chosen function is invoked with them and - * its result is returned. - * - * @private - * @param {*} [value] The value to convert to an iteratee. - * @param {number} [arity] The arity of the created iteratee. - * @returns {Function} Returns the chosen function or its result. - */ - function getIteratee() { - var result = lodash.iteratee || iteratee; - result = result === iteratee ? baseIteratee : result; - return arguments.length ? result(arguments[0], arguments[1]) : result; - } - - /** - * Gets the data for `map`. - * - * @private - * @param {Object} map The map to query. - * @param {string} key The reference key. - * @returns {*} Returns the map data. - */ - function getMapData(map, key) { - var data = map.__data__; - return isKeyable(key) - ? data[typeof key == 'string' ? 'string' : 'hash'] - : data.map; - } - - /** - * Gets the property names, values, and compare flags of `object`. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the match data of `object`. - */ - function getMatchData(object) { - var result = keys(object), - length = result.length; - - while (length--) { - var key = result[length], - value = object[key]; - - result[length] = [key, value, isStrictComparable(value)]; - } - return result; - } - - /** - * Gets the native function at `key` of `object`. - * - * @private - * @param {Object} object The object to query. - * @param {string} key The key of the method to get. - * @returns {*} Returns the function if it's native, else `undefined`. - */ - function getNative(object, key) { - var value = getValue(object, key); - return baseIsNative(value) ? value : undefined; - } - - /** - * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the raw `toStringTag`. - */ - function getRawTag(value) { - var isOwn = hasOwnProperty.call(value, symToStringTag), - tag = value[symToStringTag]; - - try { - value[symToStringTag] = undefined; - var unmasked = true; - } catch (e) {} - - var result = nativeObjectToString.call(value); - if (unmasked) { - if (isOwn) { - value[symToStringTag] = tag; - } else { - delete value[symToStringTag]; - } - } - return result; - } - - /** - * Creates an array of the own enumerable symbols of `object`. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of symbols. - */ - var getSymbols = !nativeGetSymbols ? stubArray : function(object) { - if (object == null) { - return []; - } - object = Object(object); - return arrayFilter(nativeGetSymbols(object), function(symbol) { - return propertyIsEnumerable.call(object, symbol); - }); - }; - - /** - * Creates an array of the own and inherited enumerable symbols of `object`. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of symbols. - */ - var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) { - var result = []; - while (object) { - arrayPush(result, getSymbols(object)); - object = getPrototype(object); - } - return result; - }; - - /** - * Gets the `toStringTag` of `value`. - * - * @private - * @param {*} value The value to query. - * @returns {string} Returns the `toStringTag`. - */ - var getTag = baseGetTag; - - // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6. - if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) || - (Map && getTag(new Map) != mapTag) || - (Promise && getTag(Promise.resolve()) != promiseTag) || - (Set && getTag(new Set) != setTag) || - (WeakMap && getTag(new WeakMap) != weakMapTag)) { - getTag = function(value) { - var result = baseGetTag(value), - Ctor = result == objectTag ? value.constructor : undefined, - ctorString = Ctor ? toSource(Ctor) : ''; - - if (ctorString) { - switch (ctorString) { - case dataViewCtorString: return dataViewTag; - case mapCtorString: return mapTag; - case promiseCtorString: return promiseTag; - case setCtorString: return setTag; - case weakMapCtorString: return weakMapTag; - } - } - return result; - }; - } - - /** - * Gets the view, applying any `transforms` to the `start` and `end` positions. - * - * @private - * @param {number} start The start of the view. - * @param {number} end The end of the view. - * @param {Array} transforms The transformations to apply to the view. - * @returns {Object} Returns an object containing the `start` and `end` - * positions of the view. - */ - function getView(start, end, transforms) { - var index = -1, - length = transforms.length; - - while (++index < length) { - var data = transforms[index], - size = data.size; - - switch (data.type) { - case 'drop': start += size; break; - case 'dropRight': end -= size; break; - case 'take': end = nativeMin(end, start + size); break; - case 'takeRight': start = nativeMax(start, end - size); break; - } - } - return { 'start': start, 'end': end }; - } - - /** - * Extracts wrapper details from the `source` body comment. - * - * @private - * @param {string} source The source to inspect. - * @returns {Array} Returns the wrapper details. - */ - function getWrapDetails(source) { - var match = source.match(reWrapDetails); - return match ? match[1].split(reSplitDetails) : []; - } - - /** - * Checks if `path` exists on `object`. - * - * @private - * @param {Object} object The object to query. - * @param {Array|string} path The path to check. - * @param {Function} hasFunc The function to check properties. - * @returns {boolean} Returns `true` if `path` exists, else `false`. - */ - function hasPath(object, path, hasFunc) { - path = castPath(path, object); - - var index = -1, - length = path.length, - result = false; - - while (++index < length) { - var key = toKey(path[index]); - if (!(result = object != null && hasFunc(object, key))) { - break; - } - object = object[key]; - } - if (result || ++index != length) { - return result; - } - length = object == null ? 0 : object.length; - return !!length && isLength(length) && isIndex(key, length) && - (isArray(object) || isArguments(object)); - } - - /** - * Initializes an array clone. - * - * @private - * @param {Array} array The array to clone. - * @returns {Array} Returns the initialized clone. - */ - function initCloneArray(array) { - var length = array.length, - result = new array.constructor(length); - - // Add properties assigned by `RegExp#exec`. - if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) { - result.index = array.index; - result.input = array.input; - } - return result; - } - - /** - * Initializes an object clone. - * - * @private - * @param {Object} object The object to clone. - * @returns {Object} Returns the initialized clone. - */ - function initCloneObject(object) { - return (typeof object.constructor == 'function' && !isPrototype(object)) - ? baseCreate(getPrototype(object)) - : {}; - } - - /** - * Initializes an object clone based on its `toStringTag`. - * - * **Note:** This function only supports cloning values with tags of - * `Boolean`, `Date`, `Error`, `Map`, `Number`, `RegExp`, `Set`, or `String`. - * - * @private - * @param {Object} object The object to clone. - * @param {string} tag The `toStringTag` of the object to clone. - * @param {boolean} [isDeep] Specify a deep clone. - * @returns {Object} Returns the initialized clone. - */ - function initCloneByTag(object, tag, isDeep) { - var Ctor = object.constructor; - switch (tag) { - case arrayBufferTag: - return cloneArrayBuffer(object); - - case boolTag: - case dateTag: - return new Ctor(+object); - - case dataViewTag: - return cloneDataView(object, isDeep); - - case float32Tag: case float64Tag: - case int8Tag: case int16Tag: case int32Tag: - case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag: - return cloneTypedArray(object, isDeep); - - case mapTag: - return new Ctor; - - case numberTag: - case stringTag: - return new Ctor(object); - - case regexpTag: - return cloneRegExp(object); - - case setTag: - return new Ctor; - - case symbolTag: - return cloneSymbol(object); - } - } - - /** - * Inserts wrapper `details` in a comment at the top of the `source` body. - * - * @private - * @param {string} source The source to modify. - * @returns {Array} details The details to insert. - * @returns {string} Returns the modified source. - */ - function insertWrapDetails(source, details) { - var length = details.length; - if (!length) { - return source; - } - var lastIndex = length - 1; - details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex]; - details = details.join(length > 2 ? ', ' : ' '); - return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n'); - } - - /** - * Checks if `value` is a flattenable `arguments` object or array. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is flattenable, else `false`. - */ - function isFlattenable(value) { - return isArray(value) || isArguments(value) || - !!(spreadableSymbol && value && value[spreadableSymbol]); - } - - /** - * Checks if `value` is a valid array-like index. - * - * @private - * @param {*} value The value to check. - * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index. - * @returns {boolean} Returns `true` if `value` is a valid index, else `false`. - */ - function isIndex(value, length) { - var type = typeof value; - length = length == null ? MAX_SAFE_INTEGER : length; - - return !!length && - (type == 'number' || - (type != 'symbol' && reIsUint.test(value))) && - (value > -1 && value % 1 == 0 && value < length); - } - - /** - * Checks if the given arguments are from an iteratee call. - * - * @private - * @param {*} value The potential iteratee value argument. - * @param {*} index The potential iteratee index or key argument. - * @param {*} object The potential iteratee object argument. - * @returns {boolean} Returns `true` if the arguments are from an iteratee call, - * else `false`. - */ - function isIterateeCall(value, index, object) { - if (!isObject(object)) { - return false; - } - var type = typeof index; - if (type == 'number' - ? (isArrayLike(object) && isIndex(index, object.length)) - : (type == 'string' && index in object) - ) { - return eq(object[index], value); - } - return false; - } - - /** - * Checks if `value` is a property name and not a property path. - * - * @private - * @param {*} value The value to check. - * @param {Object} [object] The object to query keys on. - * @returns {boolean} Returns `true` if `value` is a property name, else `false`. - */ - function isKey(value, object) { - if (isArray(value)) { - return false; - } - var type = typeof value; - if (type == 'number' || type == 'symbol' || type == 'boolean' || - value == null || isSymbol(value)) { - return true; - } - return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || - (object != null && value in Object(object)); - } - - /** - * Checks if `value` is suitable for use as unique object key. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is suitable, else `false`. - */ - function isKeyable(value) { - var type = typeof value; - return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean') - ? (value !== '__proto__') - : (value === null); - } - - /** - * Checks if `func` has a lazy counterpart. - * - * @private - * @param {Function} func The function to check. - * @returns {boolean} Returns `true` if `func` has a lazy counterpart, - * else `false`. - */ - function isLaziable(func) { - var funcName = getFuncName(func), - other = lodash[funcName]; - - if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) { - return false; - } - if (func === other) { - return true; - } - var data = getData(other); - return !!data && func === data[0]; - } - - /** - * Checks if `func` has its source masked. - * - * @private - * @param {Function} func The function to check. - * @returns {boolean} Returns `true` if `func` is masked, else `false`. - */ - function isMasked(func) { - return !!maskSrcKey && (maskSrcKey in func); - } - - /** - * Checks if `func` is capable of being masked. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `func` is maskable, else `false`. - */ - var isMaskable = coreJsData ? isFunction : stubFalse; - - /** - * Checks if `value` is likely a prototype object. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a prototype, else `false`. - */ - function isPrototype(value) { - var Ctor = value && value.constructor, - proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto; - - return value === proto; - } - - /** - * Checks if `value` is suitable for strict equality comparisons, i.e. `===`. - * - * @private - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` if suitable for strict - * equality comparisons, else `false`. - */ - function isStrictComparable(value) { - return value === value && !isObject(value); - } - - /** - * A specialized version of `matchesProperty` for source values suitable - * for strict equality comparisons, i.e. `===`. - * - * @private - * @param {string} key The key of the property to get. - * @param {*} srcValue The value to match. - * @returns {Function} Returns the new spec function. - */ - function matchesStrictComparable(key, srcValue) { - return function(object) { - if (object == null) { - return false; - } - return object[key] === srcValue && - (srcValue !== undefined || (key in Object(object))); - }; - } - - /** - * A specialized version of `_.memoize` which clears the memoized function's - * cache when it exceeds `MAX_MEMOIZE_SIZE`. - * - * @private - * @param {Function} func The function to have its output memoized. - * @returns {Function} Returns the new memoized function. - */ - function memoizeCapped(func) { - var result = memoize(func, function(key) { - if (cache.size === MAX_MEMOIZE_SIZE) { - cache.clear(); - } - return key; - }); - - var cache = result.cache; - return result; - } - - /** - * Merges the function metadata of `source` into `data`. - * - * Merging metadata reduces the number of wrappers used to invoke a function. - * This is possible because methods like `_.bind`, `_.curry`, and `_.partial` - * may be applied regardless of execution order. Methods like `_.ary` and - * `_.rearg` modify function arguments, making the order in which they are - * executed important, preventing the merging of metadata. However, we make - * an exception for a safe combined case where curried functions have `_.ary` - * and or `_.rearg` applied. - * - * @private - * @param {Array} data The destination metadata. - * @param {Array} source The source metadata. - * @returns {Array} Returns `data`. - */ - function mergeData(data, source) { - var bitmask = data[1], - srcBitmask = source[1], - newBitmask = bitmask | srcBitmask, - isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG); - - var isCombo = - ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) || - ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) || - ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG)); - - // Exit early if metadata can't be merged. - if (!(isCommon || isCombo)) { - return data; - } - // Use source `thisArg` if available. - if (srcBitmask & WRAP_BIND_FLAG) { - data[2] = source[2]; - // Set when currying a bound function. - newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG; - } - // Compose partial arguments. - var value = source[3]; - if (value) { - var partials = data[3]; - data[3] = partials ? composeArgs(partials, value, source[4]) : value; - data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4]; - } - // Compose partial right arguments. - value = source[5]; - if (value) { - partials = data[5]; - data[5] = partials ? composeArgsRight(partials, value, source[6]) : value; - data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6]; - } - // Use source `argPos` if available. - value = source[7]; - if (value) { - data[7] = value; - } - // Use source `ary` if it's smaller. - if (srcBitmask & WRAP_ARY_FLAG) { - data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]); - } - // Use source `arity` if one is not provided. - if (data[9] == null) { - data[9] = source[9]; - } - // Use source `func` and merge bitmasks. - data[0] = source[0]; - data[1] = newBitmask; - - return data; - } - - /** - * This function is like - * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) - * except that it includes inherited enumerable properties. - * - * @private - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - */ - function nativeKeysIn(object) { - var result = []; - if (object != null) { - for (var key in Object(object)) { - result.push(key); - } - } - return result; - } - - /** - * Converts `value` to a string using `Object.prototype.toString`. - * - * @private - * @param {*} value The value to convert. - * @returns {string} Returns the converted string. - */ - function objectToString(value) { - return nativeObjectToString.call(value); - } - - /** - * A specialized version of `baseRest` which transforms the rest array. - * - * @private - * @param {Function} func The function to apply a rest parameter to. - * @param {number} [start=func.length-1] The start position of the rest parameter. - * @param {Function} transform The rest array transform. - * @returns {Function} Returns the new function. - */ - function overRest(func, start, transform) { - start = nativeMax(start === undefined ? (func.length - 1) : start, 0); - return function() { - var args = arguments, - index = -1, - length = nativeMax(args.length - start, 0), - array = Array(length); - - while (++index < length) { - array[index] = args[start + index]; - } - index = -1; - var otherArgs = Array(start + 1); - while (++index < start) { - otherArgs[index] = args[index]; - } - otherArgs[start] = transform(array); - return apply(func, this, otherArgs); - }; - } - - /** - * Gets the parent value at `path` of `object`. - * - * @private - * @param {Object} object The object to query. - * @param {Array} path The path to get the parent value of. - * @returns {*} Returns the parent value. - */ - function parent(object, path) { - return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1)); - } - - /** - * Reorder `array` according to the specified indexes where the element at - * the first index is assigned as the first element, the element at - * the second index is assigned as the second element, and so on. - * - * @private - * @param {Array} array The array to reorder. - * @param {Array} indexes The arranged array indexes. - * @returns {Array} Returns `array`. - */ - function reorder(array, indexes) { - var arrLength = array.length, - length = nativeMin(indexes.length, arrLength), - oldArray = copyArray(array); - - while (length--) { - var index = indexes[length]; - array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined; - } - return array; - } - - /** - * Sets metadata for `func`. - * - * **Note:** If this function becomes hot, i.e. is invoked a lot in a short - * period of time, it will trip its breaker and transition to an identity - * function to avoid garbage collection pauses in V8. See - * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070) - * for more details. - * - * @private - * @param {Function} func The function to associate metadata with. - * @param {*} data The metadata. - * @returns {Function} Returns `func`. - */ - var setData = shortOut(baseSetData); - - /** - * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout). - * - * @private - * @param {Function} func The function to delay. - * @param {number} wait The number of milliseconds to delay invocation. - * @returns {number|Object} Returns the timer id or timeout object. - */ - var setTimeout = ctxSetTimeout || function(func, wait) { - return root.setTimeout(func, wait); - }; - - /** - * Sets the `toString` method of `func` to return `string`. - * - * @private - * @param {Function} func The function to modify. - * @param {Function} string The `toString` result. - * @returns {Function} Returns `func`. - */ - var setToString = shortOut(baseSetToString); - - /** - * Sets the `toString` method of `wrapper` to mimic the source of `reference` - * with wrapper details in a comment at the top of the source body. - * - * @private - * @param {Function} wrapper The function to modify. - * @param {Function} reference The reference function. - * @param {number} bitmask The bitmask flags. See `createWrap` for more details. - * @returns {Function} Returns `wrapper`. - */ - function setWrapToString(wrapper, reference, bitmask) { - var source = (reference + ''); - return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask))); - } - - /** - * Creates a function that'll short out and invoke `identity` instead - * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN` - * milliseconds. - * - * @private - * @param {Function} func The function to restrict. - * @returns {Function} Returns the new shortable function. - */ - function shortOut(func) { - var count = 0, - lastCalled = 0; - - return function() { - var stamp = nativeNow(), - remaining = HOT_SPAN - (stamp - lastCalled); - - lastCalled = stamp; - if (remaining > 0) { - if (++count >= HOT_COUNT) { - return arguments[0]; - } - } else { - count = 0; - } - return func.apply(undefined, arguments); - }; - } - - /** - * A specialized version of `_.shuffle` which mutates and sets the size of `array`. - * - * @private - * @param {Array} array The array to shuffle. - * @param {number} [size=array.length] The size of `array`. - * @returns {Array} Returns `array`. - */ - function shuffleSelf(array, size) { - var index = -1, - length = array.length, - lastIndex = length - 1; - - size = size === undefined ? length : size; - while (++index < size) { - var rand = baseRandom(index, lastIndex), - value = array[rand]; - - array[rand] = array[index]; - array[index] = value; - } - array.length = size; - return array; - } - - /** - * Converts `string` to a property path array. - * - * @private - * @param {string} string The string to convert. - * @returns {Array} Returns the property path array. - */ - var stringToPath = memoizeCapped(function(string) { - var result = []; - if (string.charCodeAt(0) === 46 /* . */) { - result.push(''); - } - string.replace(rePropName, function(match, number, quote, subString) { - result.push(quote ? subString.replace(reEscapeChar, '$1') : (number || match)); - }); - return result; - }); - - /** - * Converts `value` to a string key if it's not a string or symbol. - * - * @private - * @param {*} value The value to inspect. - * @returns {string|symbol} Returns the key. - */ - function toKey(value) { - if (typeof value == 'string' || isSymbol(value)) { - return value; - } - var result = (value + ''); - return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result; - } - - /** - * Converts `func` to its source code. - * - * @private - * @param {Function} func The function to convert. - * @returns {string} Returns the source code. - */ - function toSource(func) { - if (func != null) { - try { - return funcToString.call(func); - } catch (e) {} - try { - return (func + ''); - } catch (e) {} - } - return ''; - } - - /** - * Updates wrapper `details` based on `bitmask` flags. - * - * @private - * @returns {Array} details The details to modify. - * @param {number} bitmask The bitmask flags. See `createWrap` for more details. - * @returns {Array} Returns `details`. - */ - function updateWrapDetails(details, bitmask) { - arrayEach(wrapFlags, function(pair) { - var value = '_.' + pair[0]; - if ((bitmask & pair[1]) && !arrayIncludes(details, value)) { - details.push(value); - } - }); - return details.sort(); - } - - /** - * Creates a clone of `wrapper`. - * - * @private - * @param {Object} wrapper The wrapper to clone. - * @returns {Object} Returns the cloned wrapper. - */ - function wrapperClone(wrapper) { - if (wrapper instanceof LazyWrapper) { - return wrapper.clone(); - } - var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__); - result.__actions__ = copyArray(wrapper.__actions__); - result.__index__ = wrapper.__index__; - result.__values__ = wrapper.__values__; - return result; - } - - /*------------------------------------------------------------------------*/ - - /** - * Creates an array of elements split into groups the length of `size`. - * If `array` can't be split evenly, the final chunk will be the remaining - * elements. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Array - * @param {Array} array The array to process. - * @param {number} [size=1] The length of each chunk - * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. - * @returns {Array} Returns the new array of chunks. - * @example - * - * _.chunk(['a', 'b', 'c', 'd'], 2); - * // => [['a', 'b'], ['c', 'd']] - * - * _.chunk(['a', 'b', 'c', 'd'], 3); - * // => [['a', 'b', 'c'], ['d']] - */ - function chunk(array, size, guard) { - if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) { - size = 1; - } else { - size = nativeMax(toInteger(size), 0); - } - var length = array == null ? 0 : array.length; - if (!length || size < 1) { - return []; - } - var index = 0, - resIndex = 0, - result = Array(nativeCeil(length / size)); - - while (index < length) { - result[resIndex++] = baseSlice(array, index, (index += size)); - } - return result; - } - - /** - * Creates an array with all falsey values removed. The values `false`, `null`, - * `0`, `""`, `undefined`, and `NaN` are falsey. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Array - * @param {Array} array The array to compact. - * @returns {Array} Returns the new array of filtered values. - * @example - * - * _.compact([0, 1, false, 2, '', 3]); - * // => [1, 2, 3] - */ - function compact(array) { - var index = -1, - length = array == null ? 0 : array.length, - resIndex = 0, - result = []; - - while (++index < length) { - var value = array[index]; - if (value) { - result[resIndex++] = value; - } - } - return result; - } - - /** - * Creates a new array concatenating `array` with any additional arrays - * and/or values. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {Array} array The array to concatenate. - * @param {...*} [values] The values to concatenate. - * @returns {Array} Returns the new concatenated array. - * @example - * - * var array = [1]; - * var other = _.concat(array, 2, [3], [[4]]); - * - * console.log(other); - * // => [1, 2, 3, [4]] - * - * console.log(array); - * // => [1] - */ - function concat() { - var length = arguments.length; - if (!length) { - return []; - } - var args = Array(length - 1), - array = arguments[0], - index = length; - - while (index--) { - args[index - 1] = arguments[index]; - } - return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1)); - } - - /** - * Creates an array of `array` values not included in the other given arrays - * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons. The order and references of result values are - * determined by the first array. - * - * **Note:** Unlike `_.pullAll`, this method returns a new array. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Array - * @param {Array} array The array to inspect. - * @param {...Array} [values] The values to exclude. - * @returns {Array} Returns the new array of filtered values. - * @see _.without, _.xor - * @example - * - * _.difference([2, 1], [2, 3]); - * // => [1] - */ - var difference = baseRest(function(array, values) { - return isArrayLikeObject(array) - ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) - : []; - }); - - /** - * This method is like `_.difference` except that it accepts `iteratee` which - * is invoked for each element of `array` and `values` to generate the criterion - * by which they're compared. The order and references of result values are - * determined by the first array. The iteratee is invoked with one argument: - * (value). - * - * **Note:** Unlike `_.pullAllBy`, this method returns a new array. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {Array} array The array to inspect. - * @param {...Array} [values] The values to exclude. - * @param {Function} [iteratee=_.identity] The iteratee invoked per element. - * @returns {Array} Returns the new array of filtered values. - * @example - * - * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor); - * // => [1.2] - * - * // The `_.property` iteratee shorthand. - * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x'); - * // => [{ 'x': 2 }] - */ - var differenceBy = baseRest(function(array, values) { - var iteratee = last(values); - if (isArrayLikeObject(iteratee)) { - iteratee = undefined; - } - return isArrayLikeObject(array) - ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)) - : []; - }); - - /** - * This method is like `_.difference` except that it accepts `comparator` - * which is invoked to compare elements of `array` to `values`. The order and - * references of result values are determined by the first array. The comparator - * is invoked with two arguments: (arrVal, othVal). - * - * **Note:** Unlike `_.pullAllWith`, this method returns a new array. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {Array} array The array to inspect. - * @param {...Array} [values] The values to exclude. - * @param {Function} [comparator] The comparator invoked per element. - * @returns {Array} Returns the new array of filtered values. - * @example - * - * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; - * - * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual); - * // => [{ 'x': 2, 'y': 1 }] - */ - var differenceWith = baseRest(function(array, values) { - var comparator = last(values); - if (isArrayLikeObject(comparator)) { - comparator = undefined; - } - return isArrayLikeObject(array) - ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator) - : []; - }); - - /** - * Creates a slice of `array` with `n` elements dropped from the beginning. - * - * @static - * @memberOf _ - * @since 0.5.0 - * @category Array - * @param {Array} array The array to query. - * @param {number} [n=1] The number of elements to drop. - * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. - * @returns {Array} Returns the slice of `array`. - * @example - * - * _.drop([1, 2, 3]); - * // => [2, 3] - * - * _.drop([1, 2, 3], 2); - * // => [3] - * - * _.drop([1, 2, 3], 5); - * // => [] - * - * _.drop([1, 2, 3], 0); - * // => [1, 2, 3] - */ - function drop(array, n, guard) { - var length = array == null ? 0 : array.length; - if (!length) { - return []; - } - n = (guard || n === undefined) ? 1 : toInteger(n); - return baseSlice(array, n < 0 ? 0 : n, length); - } - - /** - * Creates a slice of `array` with `n` elements dropped from the end. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Array - * @param {Array} array The array to query. - * @param {number} [n=1] The number of elements to drop. - * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. - * @returns {Array} Returns the slice of `array`. - * @example - * - * _.dropRight([1, 2, 3]); - * // => [1, 2] - * - * _.dropRight([1, 2, 3], 2); - * // => [1] - * - * _.dropRight([1, 2, 3], 5); - * // => [] - * - * _.dropRight([1, 2, 3], 0); - * // => [1, 2, 3] - */ - function dropRight(array, n, guard) { - var length = array == null ? 0 : array.length; - if (!length) { - return []; - } - n = (guard || n === undefined) ? 1 : toInteger(n); - n = length - n; - return baseSlice(array, 0, n < 0 ? 0 : n); - } - - /** - * Creates a slice of `array` excluding elements dropped from the end. - * Elements are dropped until `predicate` returns falsey. The predicate is - * invoked with three arguments: (value, index, array). - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Array - * @param {Array} array The array to query. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @returns {Array} Returns the slice of `array`. - * @example - * - * var users = [ - * { 'user': 'barney', 'active': true }, - * { 'user': 'fred', 'active': false }, - * { 'user': 'pebbles', 'active': false } - * ]; - * - * _.dropRightWhile(users, function(o) { return !o.active; }); - * // => objects for ['barney'] - * - * // The `_.matches` iteratee shorthand. - * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false }); - * // => objects for ['barney', 'fred'] - * - * // The `_.matchesProperty` iteratee shorthand. - * _.dropRightWhile(users, ['active', false]); - * // => objects for ['barney'] - * - * // The `_.property` iteratee shorthand. - * _.dropRightWhile(users, 'active'); - * // => objects for ['barney', 'fred', 'pebbles'] - */ - function dropRightWhile(array, predicate) { - return (array && array.length) - ? baseWhile(array, getIteratee(predicate, 3), true, true) - : []; - } - - /** - * Creates a slice of `array` excluding elements dropped from the beginning. - * Elements are dropped until `predicate` returns falsey. The predicate is - * invoked with three arguments: (value, index, array). - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Array - * @param {Array} array The array to query. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @returns {Array} Returns the slice of `array`. - * @example - * - * var users = [ - * { 'user': 'barney', 'active': false }, - * { 'user': 'fred', 'active': false }, - * { 'user': 'pebbles', 'active': true } - * ]; - * - * _.dropWhile(users, function(o) { return !o.active; }); - * // => objects for ['pebbles'] - * - * // The `_.matches` iteratee shorthand. - * _.dropWhile(users, { 'user': 'barney', 'active': false }); - * // => objects for ['fred', 'pebbles'] - * - * // The `_.matchesProperty` iteratee shorthand. - * _.dropWhile(users, ['active', false]); - * // => objects for ['pebbles'] - * - * // The `_.property` iteratee shorthand. - * _.dropWhile(users, 'active'); - * // => objects for ['barney', 'fred', 'pebbles'] - */ - function dropWhile(array, predicate) { - return (array && array.length) - ? baseWhile(array, getIteratee(predicate, 3), true) - : []; - } - - /** - * Fills elements of `array` with `value` from `start` up to, but not - * including, `end`. - * - * **Note:** This method mutates `array`. - * - * @static - * @memberOf _ - * @since 3.2.0 - * @category Array - * @param {Array} array The array to fill. - * @param {*} value The value to fill `array` with. - * @param {number} [start=0] The start position. - * @param {number} [end=array.length] The end position. - * @returns {Array} Returns `array`. - * @example - * - * var array = [1, 2, 3]; - * - * _.fill(array, 'a'); - * console.log(array); - * // => ['a', 'a', 'a'] - * - * _.fill(Array(3), 2); - * // => [2, 2, 2] - * - * _.fill([4, 6, 8, 10], '*', 1, 3); - * // => [4, '*', '*', 10] - */ - function fill(array, value, start, end) { - var length = array == null ? 0 : array.length; - if (!length) { - return []; - } - if (start && typeof start != 'number' && isIterateeCall(array, value, start)) { - start = 0; - end = length; - } - return baseFill(array, value, start, end); - } - - /** - * This method is like `_.find` except that it returns the index of the first - * element `predicate` returns truthy for instead of the element itself. - * - * @static - * @memberOf _ - * @since 1.1.0 - * @category Array - * @param {Array} array The array to inspect. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @param {number} [fromIndex=0] The index to search from. - * @returns {number} Returns the index of the found element, else `-1`. - * @example - * - * var users = [ - * { 'user': 'barney', 'active': false }, - * { 'user': 'fred', 'active': false }, - * { 'user': 'pebbles', 'active': true } - * ]; - * - * _.findIndex(users, function(o) { return o.user == 'barney'; }); - * // => 0 - * - * // The `_.matches` iteratee shorthand. - * _.findIndex(users, { 'user': 'fred', 'active': false }); - * // => 1 - * - * // The `_.matchesProperty` iteratee shorthand. - * _.findIndex(users, ['active', false]); - * // => 0 - * - * // The `_.property` iteratee shorthand. - * _.findIndex(users, 'active'); - * // => 2 - */ - function findIndex(array, predicate, fromIndex) { - var length = array == null ? 0 : array.length; - if (!length) { - return -1; - } - var index = fromIndex == null ? 0 : toInteger(fromIndex); - if (index < 0) { - index = nativeMax(length + index, 0); - } - return baseFindIndex(array, getIteratee(predicate, 3), index); - } - - /** - * This method is like `_.findIndex` except that it iterates over elements - * of `collection` from right to left. - * - * @static - * @memberOf _ - * @since 2.0.0 - * @category Array - * @param {Array} array The array to inspect. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @param {number} [fromIndex=array.length-1] The index to search from. - * @returns {number} Returns the index of the found element, else `-1`. - * @example - * - * var users = [ - * { 'user': 'barney', 'active': true }, - * { 'user': 'fred', 'active': false }, - * { 'user': 'pebbles', 'active': false } - * ]; - * - * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; }); - * // => 2 - * - * // The `_.matches` iteratee shorthand. - * _.findLastIndex(users, { 'user': 'barney', 'active': true }); - * // => 0 - * - * // The `_.matchesProperty` iteratee shorthand. - * _.findLastIndex(users, ['active', false]); - * // => 2 - * - * // The `_.property` iteratee shorthand. - * _.findLastIndex(users, 'active'); - * // => 0 - */ - function findLastIndex(array, predicate, fromIndex) { - var length = array == null ? 0 : array.length; - if (!length) { - return -1; - } - var index = length - 1; - if (fromIndex !== undefined) { - index = toInteger(fromIndex); - index = fromIndex < 0 - ? nativeMax(length + index, 0) - : nativeMin(index, length - 1); - } - return baseFindIndex(array, getIteratee(predicate, 3), index, true); - } - - /** - * Flattens `array` a single level deep. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Array - * @param {Array} array The array to flatten. - * @returns {Array} Returns the new flattened array. - * @example - * - * _.flatten([1, [2, [3, [4]], 5]]); - * // => [1, 2, [3, [4]], 5] - */ - function flatten(array) { - var length = array == null ? 0 : array.length; - return length ? baseFlatten(array, 1) : []; - } - - /** - * Recursively flattens `array`. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Array - * @param {Array} array The array to flatten. - * @returns {Array} Returns the new flattened array. - * @example - * - * _.flattenDeep([1, [2, [3, [4]], 5]]); - * // => [1, 2, 3, 4, 5] - */ - function flattenDeep(array) { - var length = array == null ? 0 : array.length; - return length ? baseFlatten(array, INFINITY) : []; - } - - /** - * Recursively flatten `array` up to `depth` times. - * - * @static - * @memberOf _ - * @since 4.4.0 - * @category Array - * @param {Array} array The array to flatten. - * @param {number} [depth=1] The maximum recursion depth. - * @returns {Array} Returns the new flattened array. - * @example - * - * var array = [1, [2, [3, [4]], 5]]; - * - * _.flattenDepth(array, 1); - * // => [1, 2, [3, [4]], 5] - * - * _.flattenDepth(array, 2); - * // => [1, 2, 3, [4], 5] - */ - function flattenDepth(array, depth) { - var length = array == null ? 0 : array.length; - if (!length) { - return []; - } - depth = depth === undefined ? 1 : toInteger(depth); - return baseFlatten(array, depth); - } - - /** - * The inverse of `_.toPairs`; this method returns an object composed - * from key-value `pairs`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {Array} pairs The key-value pairs. - * @returns {Object} Returns the new object. - * @example - * - * _.fromPairs([['a', 1], ['b', 2]]); - * // => { 'a': 1, 'b': 2 } - */ - function fromPairs(pairs) { - var index = -1, - length = pairs == null ? 0 : pairs.length, - result = {}; - - while (++index < length) { - var pair = pairs[index]; - result[pair[0]] = pair[1]; - } - return result; - } - - /** - * Gets the first element of `array`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @alias first - * @category Array - * @param {Array} array The array to query. - * @returns {*} Returns the first element of `array`. - * @example - * - * _.head([1, 2, 3]); - * // => 1 - * - * _.head([]); - * // => undefined - */ - function head(array) { - return (array && array.length) ? array[0] : undefined; - } - - /** - * Gets the index at which the first occurrence of `value` is found in `array` - * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons. If `fromIndex` is negative, it's used as the - * offset from the end of `array`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Array - * @param {Array} array The array to inspect. - * @param {*} value The value to search for. - * @param {number} [fromIndex=0] The index to search from. - * @returns {number} Returns the index of the matched value, else `-1`. - * @example - * - * _.indexOf([1, 2, 1, 2], 2); - * // => 1 - * - * // Search from the `fromIndex`. - * _.indexOf([1, 2, 1, 2], 2, 2); - * // => 3 - */ - function indexOf(array, value, fromIndex) { - var length = array == null ? 0 : array.length; - if (!length) { - return -1; - } - var index = fromIndex == null ? 0 : toInteger(fromIndex); - if (index < 0) { - index = nativeMax(length + index, 0); - } - return baseIndexOf(array, value, index); - } - - /** - * Gets all but the last element of `array`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Array - * @param {Array} array The array to query. - * @returns {Array} Returns the slice of `array`. - * @example - * - * _.initial([1, 2, 3]); - * // => [1, 2] - */ - function initial(array) { - var length = array == null ? 0 : array.length; - return length ? baseSlice(array, 0, -1) : []; - } - - /** - * Creates an array of unique values that are included in all given arrays - * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons. The order and references of result values are - * determined by the first array. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Array - * @param {...Array} [arrays] The arrays to inspect. - * @returns {Array} Returns the new array of intersecting values. - * @example - * - * _.intersection([2, 1], [2, 3]); - * // => [2] - */ - var intersection = baseRest(function(arrays) { - var mapped = arrayMap(arrays, castArrayLikeObject); - return (mapped.length && mapped[0] === arrays[0]) - ? baseIntersection(mapped) - : []; - }); - - /** - * This method is like `_.intersection` except that it accepts `iteratee` - * which is invoked for each element of each `arrays` to generate the criterion - * by which they're compared. The order and references of result values are - * determined by the first array. The iteratee is invoked with one argument: - * (value). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {...Array} [arrays] The arrays to inspect. - * @param {Function} [iteratee=_.identity] The iteratee invoked per element. - * @returns {Array} Returns the new array of intersecting values. - * @example - * - * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor); - * // => [2.1] - * - * // The `_.property` iteratee shorthand. - * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); - * // => [{ 'x': 1 }] - */ - var intersectionBy = baseRest(function(arrays) { - var iteratee = last(arrays), - mapped = arrayMap(arrays, castArrayLikeObject); - - if (iteratee === last(mapped)) { - iteratee = undefined; - } else { - mapped.pop(); - } - return (mapped.length && mapped[0] === arrays[0]) - ? baseIntersection(mapped, getIteratee(iteratee, 2)) - : []; - }); - - /** - * This method is like `_.intersection` except that it accepts `comparator` - * which is invoked to compare elements of `arrays`. The order and references - * of result values are determined by the first array. The comparator is - * invoked with two arguments: (arrVal, othVal). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {...Array} [arrays] The arrays to inspect. - * @param {Function} [comparator] The comparator invoked per element. - * @returns {Array} Returns the new array of intersecting values. - * @example - * - * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; - * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; - * - * _.intersectionWith(objects, others, _.isEqual); - * // => [{ 'x': 1, 'y': 2 }] - */ - var intersectionWith = baseRest(function(arrays) { - var comparator = last(arrays), - mapped = arrayMap(arrays, castArrayLikeObject); - - comparator = typeof comparator == 'function' ? comparator : undefined; - if (comparator) { - mapped.pop(); - } - return (mapped.length && mapped[0] === arrays[0]) - ? baseIntersection(mapped, undefined, comparator) - : []; - }); - - /** - * Converts all elements in `array` into a string separated by `separator`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {Array} array The array to convert. - * @param {string} [separator=','] The element separator. - * @returns {string} Returns the joined string. - * @example - * - * _.join(['a', 'b', 'c'], '~'); - * // => 'a~b~c' - */ - function join(array, separator) { - return array == null ? '' : nativeJoin.call(array, separator); - } - - /** - * Gets the last element of `array`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Array - * @param {Array} array The array to query. - * @returns {*} Returns the last element of `array`. - * @example - * - * _.last([1, 2, 3]); - * // => 3 - */ - function last(array) { - var length = array == null ? 0 : array.length; - return length ? array[length - 1] : undefined; - } - - /** - * This method is like `_.indexOf` except that it iterates over elements of - * `array` from right to left. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Array - * @param {Array} array The array to inspect. - * @param {*} value The value to search for. - * @param {number} [fromIndex=array.length-1] The index to search from. - * @returns {number} Returns the index of the matched value, else `-1`. - * @example - * - * _.lastIndexOf([1, 2, 1, 2], 2); - * // => 3 - * - * // Search from the `fromIndex`. - * _.lastIndexOf([1, 2, 1, 2], 2, 2); - * // => 1 - */ - function lastIndexOf(array, value, fromIndex) { - var length = array == null ? 0 : array.length; - if (!length) { - return -1; - } - var index = length; - if (fromIndex !== undefined) { - index = toInteger(fromIndex); - index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1); - } - return value === value - ? strictLastIndexOf(array, value, index) - : baseFindIndex(array, baseIsNaN, index, true); - } - - /** - * Gets the element at index `n` of `array`. If `n` is negative, the nth - * element from the end is returned. - * - * @static - * @memberOf _ - * @since 4.11.0 - * @category Array - * @param {Array} array The array to query. - * @param {number} [n=0] The index of the element to return. - * @returns {*} Returns the nth element of `array`. - * @example - * - * var array = ['a', 'b', 'c', 'd']; - * - * _.nth(array, 1); - * // => 'b' - * - * _.nth(array, -2); - * // => 'c'; - */ - function nth(array, n) { - return (array && array.length) ? baseNth(array, toInteger(n)) : undefined; - } - - /** - * Removes all given values from `array` using - * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons. - * - * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove` - * to remove elements from an array by predicate. - * - * @static - * @memberOf _ - * @since 2.0.0 - * @category Array - * @param {Array} array The array to modify. - * @param {...*} [values] The values to remove. - * @returns {Array} Returns `array`. - * @example - * - * var array = ['a', 'b', 'c', 'a', 'b', 'c']; - * - * _.pull(array, 'a', 'c'); - * console.log(array); - * // => ['b', 'b'] - */ - var pull = baseRest(pullAll); - - /** - * This method is like `_.pull` except that it accepts an array of values to remove. - * - * **Note:** Unlike `_.difference`, this method mutates `array`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {Array} array The array to modify. - * @param {Array} values The values to remove. - * @returns {Array} Returns `array`. - * @example - * - * var array = ['a', 'b', 'c', 'a', 'b', 'c']; - * - * _.pullAll(array, ['a', 'c']); - * console.log(array); - * // => ['b', 'b'] - */ - function pullAll(array, values) { - return (array && array.length && values && values.length) - ? basePullAll(array, values) - : array; - } - - /** - * This method is like `_.pullAll` except that it accepts `iteratee` which is - * invoked for each element of `array` and `values` to generate the criterion - * by which they're compared. The iteratee is invoked with one argument: (value). - * - * **Note:** Unlike `_.differenceBy`, this method mutates `array`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {Array} array The array to modify. - * @param {Array} values The values to remove. - * @param {Function} [iteratee=_.identity] The iteratee invoked per element. - * @returns {Array} Returns `array`. - * @example - * - * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }]; - * - * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x'); - * console.log(array); - * // => [{ 'x': 2 }] - */ - function pullAllBy(array, values, iteratee) { - return (array && array.length && values && values.length) - ? basePullAll(array, values, getIteratee(iteratee, 2)) - : array; - } - - /** - * This method is like `_.pullAll` except that it accepts `comparator` which - * is invoked to compare elements of `array` to `values`. The comparator is - * invoked with two arguments: (arrVal, othVal). - * - * **Note:** Unlike `_.differenceWith`, this method mutates `array`. - * - * @static - * @memberOf _ - * @since 4.6.0 - * @category Array - * @param {Array} array The array to modify. - * @param {Array} values The values to remove. - * @param {Function} [comparator] The comparator invoked per element. - * @returns {Array} Returns `array`. - * @example - * - * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }]; - * - * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual); - * console.log(array); - * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }] - */ - function pullAllWith(array, values, comparator) { - return (array && array.length && values && values.length) - ? basePullAll(array, values, undefined, comparator) - : array; - } - - /** - * Removes elements from `array` corresponding to `indexes` and returns an - * array of removed elements. - * - * **Note:** Unlike `_.at`, this method mutates `array`. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Array - * @param {Array} array The array to modify. - * @param {...(number|number[])} [indexes] The indexes of elements to remove. - * @returns {Array} Returns the new array of removed elements. - * @example - * - * var array = ['a', 'b', 'c', 'd']; - * var pulled = _.pullAt(array, [1, 3]); - * - * console.log(array); - * // => ['a', 'c'] - * - * console.log(pulled); - * // => ['b', 'd'] - */ - var pullAt = flatRest(function(array, indexes) { - var length = array == null ? 0 : array.length, - result = baseAt(array, indexes); - - basePullAt(array, arrayMap(indexes, function(index) { - return isIndex(index, length) ? +index : index; - }).sort(compareAscending)); - - return result; - }); - - /** - * Removes all elements from `array` that `predicate` returns truthy for - * and returns an array of the removed elements. The predicate is invoked - * with three arguments: (value, index, array). - * - * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull` - * to pull elements from an array by value. - * - * @static - * @memberOf _ - * @since 2.0.0 - * @category Array - * @param {Array} array The array to modify. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @returns {Array} Returns the new array of removed elements. - * @example - * - * var array = [1, 2, 3, 4]; - * var evens = _.remove(array, function(n) { - * return n % 2 == 0; - * }); - * - * console.log(array); - * // => [1, 3] - * - * console.log(evens); - * // => [2, 4] - */ - function remove(array, predicate) { - var result = []; - if (!(array && array.length)) { - return result; - } - var index = -1, - indexes = [], - length = array.length; - - predicate = getIteratee(predicate, 3); - while (++index < length) { - var value = array[index]; - if (predicate(value, index, array)) { - result.push(value); - indexes.push(index); - } - } - basePullAt(array, indexes); - return result; - } - - /** - * Reverses `array` so that the first element becomes the last, the second - * element becomes the second to last, and so on. - * - * **Note:** This method mutates `array` and is based on - * [`Array#reverse`](https://mdn.io/Array/reverse). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {Array} array The array to modify. - * @returns {Array} Returns `array`. - * @example - * - * var array = [1, 2, 3]; - * - * _.reverse(array); - * // => [3, 2, 1] - * - * console.log(array); - * // => [3, 2, 1] - */ - function reverse(array) { - return array == null ? array : nativeReverse.call(array); - } - - /** - * Creates a slice of `array` from `start` up to, but not including, `end`. - * - * **Note:** This method is used instead of - * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are - * returned. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Array - * @param {Array} array The array to slice. - * @param {number} [start=0] The start position. - * @param {number} [end=array.length] The end position. - * @returns {Array} Returns the slice of `array`. - */ - function slice(array, start, end) { - var length = array == null ? 0 : array.length; - if (!length) { - return []; - } - if (end && typeof end != 'number' && isIterateeCall(array, start, end)) { - start = 0; - end = length; - } - else { - start = start == null ? 0 : toInteger(start); - end = end === undefined ? length : toInteger(end); - } - return baseSlice(array, start, end); - } - - /** - * Uses a binary search to determine the lowest index at which `value` - * should be inserted into `array` in order to maintain its sort order. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Array - * @param {Array} array The sorted array to inspect. - * @param {*} value The value to evaluate. - * @returns {number} Returns the index at which `value` should be inserted - * into `array`. - * @example - * - * _.sortedIndex([30, 50], 40); - * // => 1 - */ - function sortedIndex(array, value) { - return baseSortedIndex(array, value); - } - - /** - * This method is like `_.sortedIndex` except that it accepts `iteratee` - * which is invoked for `value` and each element of `array` to compute their - * sort ranking. The iteratee is invoked with one argument: (value). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {Array} array The sorted array to inspect. - * @param {*} value The value to evaluate. - * @param {Function} [iteratee=_.identity] The iteratee invoked per element. - * @returns {number} Returns the index at which `value` should be inserted - * into `array`. - * @example - * - * var objects = [{ 'x': 4 }, { 'x': 5 }]; - * - * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); - * // => 0 - * - * // The `_.property` iteratee shorthand. - * _.sortedIndexBy(objects, { 'x': 4 }, 'x'); - * // => 0 - */ - function sortedIndexBy(array, value, iteratee) { - return baseSortedIndexBy(array, value, getIteratee(iteratee, 2)); - } - - /** - * This method is like `_.indexOf` except that it performs a binary - * search on a sorted `array`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {Array} array The array to inspect. - * @param {*} value The value to search for. - * @returns {number} Returns the index of the matched value, else `-1`. - * @example - * - * _.sortedIndexOf([4, 5, 5, 5, 6], 5); - * // => 1 - */ - function sortedIndexOf(array, value) { - var length = array == null ? 0 : array.length; - if (length) { - var index = baseSortedIndex(array, value); - if (index < length && eq(array[index], value)) { - return index; - } - } - return -1; - } - - /** - * This method is like `_.sortedIndex` except that it returns the highest - * index at which `value` should be inserted into `array` in order to - * maintain its sort order. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Array - * @param {Array} array The sorted array to inspect. - * @param {*} value The value to evaluate. - * @returns {number} Returns the index at which `value` should be inserted - * into `array`. - * @example - * - * _.sortedLastIndex([4, 5, 5, 5, 6], 5); - * // => 4 - */ - function sortedLastIndex(array, value) { - return baseSortedIndex(array, value, true); - } - - /** - * This method is like `_.sortedLastIndex` except that it accepts `iteratee` - * which is invoked for `value` and each element of `array` to compute their - * sort ranking. The iteratee is invoked with one argument: (value). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {Array} array The sorted array to inspect. - * @param {*} value The value to evaluate. - * @param {Function} [iteratee=_.identity] The iteratee invoked per element. - * @returns {number} Returns the index at which `value` should be inserted - * into `array`. - * @example - * - * var objects = [{ 'x': 4 }, { 'x': 5 }]; - * - * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; }); - * // => 1 - * - * // The `_.property` iteratee shorthand. - * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x'); - * // => 1 - */ - function sortedLastIndexBy(array, value, iteratee) { - return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true); - } - - /** - * This method is like `_.lastIndexOf` except that it performs a binary - * search on a sorted `array`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {Array} array The array to inspect. - * @param {*} value The value to search for. - * @returns {number} Returns the index of the matched value, else `-1`. - * @example - * - * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5); - * // => 3 - */ - function sortedLastIndexOf(array, value) { - var length = array == null ? 0 : array.length; - if (length) { - var index = baseSortedIndex(array, value, true) - 1; - if (eq(array[index], value)) { - return index; - } - } - return -1; - } - - /** - * This method is like `_.uniq` except that it's designed and optimized - * for sorted arrays. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {Array} array The array to inspect. - * @returns {Array} Returns the new duplicate free array. - * @example - * - * _.sortedUniq([1, 1, 2]); - * // => [1, 2] - */ - function sortedUniq(array) { - return (array && array.length) - ? baseSortedUniq(array) - : []; - } - - /** - * This method is like `_.uniqBy` except that it's designed and optimized - * for sorted arrays. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {Array} array The array to inspect. - * @param {Function} [iteratee] The iteratee invoked per element. - * @returns {Array} Returns the new duplicate free array. - * @example - * - * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor); - * // => [1.1, 2.3] - */ - function sortedUniqBy(array, iteratee) { - return (array && array.length) - ? baseSortedUniq(array, getIteratee(iteratee, 2)) - : []; - } - - /** - * Gets all but the first element of `array`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {Array} array The array to query. - * @returns {Array} Returns the slice of `array`. - * @example - * - * _.tail([1, 2, 3]); - * // => [2, 3] - */ - function tail(array) { - var length = array == null ? 0 : array.length; - return length ? baseSlice(array, 1, length) : []; - } - - /** - * Creates a slice of `array` with `n` elements taken from the beginning. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Array - * @param {Array} array The array to query. - * @param {number} [n=1] The number of elements to take. - * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. - * @returns {Array} Returns the slice of `array`. - * @example - * - * _.take([1, 2, 3]); - * // => [1] - * - * _.take([1, 2, 3], 2); - * // => [1, 2] - * - * _.take([1, 2, 3], 5); - * // => [1, 2, 3] - * - * _.take([1, 2, 3], 0); - * // => [] - */ - function take(array, n, guard) { - if (!(array && array.length)) { - return []; - } - n = (guard || n === undefined) ? 1 : toInteger(n); - return baseSlice(array, 0, n < 0 ? 0 : n); - } - - /** - * Creates a slice of `array` with `n` elements taken from the end. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Array - * @param {Array} array The array to query. - * @param {number} [n=1] The number of elements to take. - * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. - * @returns {Array} Returns the slice of `array`. - * @example - * - * _.takeRight([1, 2, 3]); - * // => [3] - * - * _.takeRight([1, 2, 3], 2); - * // => [2, 3] - * - * _.takeRight([1, 2, 3], 5); - * // => [1, 2, 3] - * - * _.takeRight([1, 2, 3], 0); - * // => [] - */ - function takeRight(array, n, guard) { - var length = array == null ? 0 : array.length; - if (!length) { - return []; - } - n = (guard || n === undefined) ? 1 : toInteger(n); - n = length - n; - return baseSlice(array, n < 0 ? 0 : n, length); - } - - /** - * Creates a slice of `array` with elements taken from the end. Elements are - * taken until `predicate` returns falsey. The predicate is invoked with - * three arguments: (value, index, array). - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Array - * @param {Array} array The array to query. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @returns {Array} Returns the slice of `array`. - * @example - * - * var users = [ - * { 'user': 'barney', 'active': true }, - * { 'user': 'fred', 'active': false }, - * { 'user': 'pebbles', 'active': false } - * ]; - * - * _.takeRightWhile(users, function(o) { return !o.active; }); - * // => objects for ['fred', 'pebbles'] - * - * // The `_.matches` iteratee shorthand. - * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false }); - * // => objects for ['pebbles'] - * - * // The `_.matchesProperty` iteratee shorthand. - * _.takeRightWhile(users, ['active', false]); - * // => objects for ['fred', 'pebbles'] - * - * // The `_.property` iteratee shorthand. - * _.takeRightWhile(users, 'active'); - * // => [] - */ - function takeRightWhile(array, predicate) { - return (array && array.length) - ? baseWhile(array, getIteratee(predicate, 3), false, true) - : []; - } - - /** - * Creates a slice of `array` with elements taken from the beginning. Elements - * are taken until `predicate` returns falsey. The predicate is invoked with - * three arguments: (value, index, array). - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Array - * @param {Array} array The array to query. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @returns {Array} Returns the slice of `array`. - * @example - * - * var users = [ - * { 'user': 'barney', 'active': false }, - * { 'user': 'fred', 'active': false }, - * { 'user': 'pebbles', 'active': true } - * ]; - * - * _.takeWhile(users, function(o) { return !o.active; }); - * // => objects for ['barney', 'fred'] - * - * // The `_.matches` iteratee shorthand. - * _.takeWhile(users, { 'user': 'barney', 'active': false }); - * // => objects for ['barney'] - * - * // The `_.matchesProperty` iteratee shorthand. - * _.takeWhile(users, ['active', false]); - * // => objects for ['barney', 'fred'] - * - * // The `_.property` iteratee shorthand. - * _.takeWhile(users, 'active'); - * // => [] - */ - function takeWhile(array, predicate) { - return (array && array.length) - ? baseWhile(array, getIteratee(predicate, 3)) - : []; - } - - /** - * Creates an array of unique values, in order, from all given arrays using - * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Array - * @param {...Array} [arrays] The arrays to inspect. - * @returns {Array} Returns the new array of combined values. - * @example - * - * _.union([2], [1, 2]); - * // => [2, 1] - */ - var union = baseRest(function(arrays) { - return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true)); - }); - - /** - * This method is like `_.union` except that it accepts `iteratee` which is - * invoked for each element of each `arrays` to generate the criterion by - * which uniqueness is computed. Result values are chosen from the first - * array in which the value occurs. The iteratee is invoked with one argument: - * (value). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {...Array} [arrays] The arrays to inspect. - * @param {Function} [iteratee=_.identity] The iteratee invoked per element. - * @returns {Array} Returns the new array of combined values. - * @example - * - * _.unionBy([2.1], [1.2, 2.3], Math.floor); - * // => [2.1, 1.2] - * - * // The `_.property` iteratee shorthand. - * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); - * // => [{ 'x': 1 }, { 'x': 2 }] - */ - var unionBy = baseRest(function(arrays) { - var iteratee = last(arrays); - if (isArrayLikeObject(iteratee)) { - iteratee = undefined; - } - return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)); - }); - - /** - * This method is like `_.union` except that it accepts `comparator` which - * is invoked to compare elements of `arrays`. Result values are chosen from - * the first array in which the value occurs. The comparator is invoked - * with two arguments: (arrVal, othVal). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {...Array} [arrays] The arrays to inspect. - * @param {Function} [comparator] The comparator invoked per element. - * @returns {Array} Returns the new array of combined values. - * @example - * - * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; - * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; - * - * _.unionWith(objects, others, _.isEqual); - * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] - */ - var unionWith = baseRest(function(arrays) { - var comparator = last(arrays); - comparator = typeof comparator == 'function' ? comparator : undefined; - return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator); - }); - - /** - * Creates a duplicate-free version of an array, using - * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons, in which only the first occurrence of each element - * is kept. The order of result values is determined by the order they occur - * in the array. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Array - * @param {Array} array The array to inspect. - * @returns {Array} Returns the new duplicate free array. - * @example - * - * _.uniq([2, 1, 2]); - * // => [2, 1] - */ - function uniq(array) { - return (array && array.length) ? baseUniq(array) : []; - } - - /** - * This method is like `_.uniq` except that it accepts `iteratee` which is - * invoked for each element in `array` to generate the criterion by which - * uniqueness is computed. The order of result values is determined by the - * order they occur in the array. The iteratee is invoked with one argument: - * (value). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {Array} array The array to inspect. - * @param {Function} [iteratee=_.identity] The iteratee invoked per element. - * @returns {Array} Returns the new duplicate free array. - * @example - * - * _.uniqBy([2.1, 1.2, 2.3], Math.floor); - * // => [2.1, 1.2] - * - * // The `_.property` iteratee shorthand. - * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x'); - * // => [{ 'x': 1 }, { 'x': 2 }] - */ - function uniqBy(array, iteratee) { - return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : []; - } - - /** - * This method is like `_.uniq` except that it accepts `comparator` which - * is invoked to compare elements of `array`. The order of result values is - * determined by the order they occur in the array.The comparator is invoked - * with two arguments: (arrVal, othVal). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {Array} array The array to inspect. - * @param {Function} [comparator] The comparator invoked per element. - * @returns {Array} Returns the new duplicate free array. - * @example - * - * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }]; - * - * _.uniqWith(objects, _.isEqual); - * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }] - */ - function uniqWith(array, comparator) { - comparator = typeof comparator == 'function' ? comparator : undefined; - return (array && array.length) ? baseUniq(array, undefined, comparator) : []; - } - - /** - * This method is like `_.zip` except that it accepts an array of grouped - * elements and creates an array regrouping the elements to their pre-zip - * configuration. - * - * @static - * @memberOf _ - * @since 1.2.0 - * @category Array - * @param {Array} array The array of grouped elements to process. - * @returns {Array} Returns the new array of regrouped elements. - * @example - * - * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]); - * // => [['a', 1, true], ['b', 2, false]] - * - * _.unzip(zipped); - * // => [['a', 'b'], [1, 2], [true, false]] - */ - function unzip(array) { - if (!(array && array.length)) { - return []; - } - var length = 0; - array = arrayFilter(array, function(group) { - if (isArrayLikeObject(group)) { - length = nativeMax(group.length, length); - return true; - } - }); - return baseTimes(length, function(index) { - return arrayMap(array, baseProperty(index)); - }); - } - - /** - * This method is like `_.unzip` except that it accepts `iteratee` to specify - * how regrouped values should be combined. The iteratee is invoked with the - * elements of each group: (...group). - * - * @static - * @memberOf _ - * @since 3.8.0 - * @category Array - * @param {Array} array The array of grouped elements to process. - * @param {Function} [iteratee=_.identity] The function to combine - * regrouped values. - * @returns {Array} Returns the new array of regrouped elements. - * @example - * - * var zipped = _.zip([1, 2], [10, 20], [100, 200]); - * // => [[1, 10, 100], [2, 20, 200]] - * - * _.unzipWith(zipped, _.add); - * // => [3, 30, 300] - */ - function unzipWith(array, iteratee) { - if (!(array && array.length)) { - return []; - } - var result = unzip(array); - if (iteratee == null) { - return result; - } - return arrayMap(result, function(group) { - return apply(iteratee, undefined, group); - }); - } - - /** - * Creates an array excluding all given values using - * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * for equality comparisons. - * - * **Note:** Unlike `_.pull`, this method returns a new array. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Array - * @param {Array} array The array to inspect. - * @param {...*} [values] The values to exclude. - * @returns {Array} Returns the new array of filtered values. - * @see _.difference, _.xor - * @example - * - * _.without([2, 1, 2, 3], 1, 2); - * // => [3] - */ - var without = baseRest(function(array, values) { - return isArrayLikeObject(array) - ? baseDifference(array, values) - : []; - }); - - /** - * Creates an array of unique values that is the - * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference) - * of the given arrays. The order of result values is determined by the order - * they occur in the arrays. - * - * @static - * @memberOf _ - * @since 2.4.0 - * @category Array - * @param {...Array} [arrays] The arrays to inspect. - * @returns {Array} Returns the new array of filtered values. - * @see _.difference, _.without - * @example - * - * _.xor([2, 1], [2, 3]); - * // => [1, 3] - */ - var xor = baseRest(function(arrays) { - return baseXor(arrayFilter(arrays, isArrayLikeObject)); - }); - - /** - * This method is like `_.xor` except that it accepts `iteratee` which is - * invoked for each element of each `arrays` to generate the criterion by - * which by which they're compared. The order of result values is determined - * by the order they occur in the arrays. The iteratee is invoked with one - * argument: (value). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {...Array} [arrays] The arrays to inspect. - * @param {Function} [iteratee=_.identity] The iteratee invoked per element. - * @returns {Array} Returns the new array of filtered values. - * @example - * - * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor); - * // => [1.2, 3.4] - * - * // The `_.property` iteratee shorthand. - * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x'); - * // => [{ 'x': 2 }] - */ - var xorBy = baseRest(function(arrays) { - var iteratee = last(arrays); - if (isArrayLikeObject(iteratee)) { - iteratee = undefined; - } - return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2)); - }); - - /** - * This method is like `_.xor` except that it accepts `comparator` which is - * invoked to compare elements of `arrays`. The order of result values is - * determined by the order they occur in the arrays. The comparator is invoked - * with two arguments: (arrVal, othVal). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Array - * @param {...Array} [arrays] The arrays to inspect. - * @param {Function} [comparator] The comparator invoked per element. - * @returns {Array} Returns the new array of filtered values. - * @example - * - * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]; - * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }]; - * - * _.xorWith(objects, others, _.isEqual); - * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }] - */ - var xorWith = baseRest(function(arrays) { - var comparator = last(arrays); - comparator = typeof comparator == 'function' ? comparator : undefined; - return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator); - }); - - /** - * Creates an array of grouped elements, the first of which contains the - * first elements of the given arrays, the second of which contains the - * second elements of the given arrays, and so on. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Array - * @param {...Array} [arrays] The arrays to process. - * @returns {Array} Returns the new array of grouped elements. - * @example - * - * _.zip(['a', 'b'], [1, 2], [true, false]); - * // => [['a', 1, true], ['b', 2, false]] - */ - var zip = baseRest(unzip); - - /** - * This method is like `_.fromPairs` except that it accepts two arrays, - * one of property identifiers and one of corresponding values. - * - * @static - * @memberOf _ - * @since 0.4.0 - * @category Array - * @param {Array} [props=[]] The property identifiers. - * @param {Array} [values=[]] The property values. - * @returns {Object} Returns the new object. - * @example - * - * _.zipObject(['a', 'b'], [1, 2]); - * // => { 'a': 1, 'b': 2 } - */ - function zipObject(props, values) { - return baseZipObject(props || [], values || [], assignValue); - } - - /** - * This method is like `_.zipObject` except that it supports property paths. - * - * @static - * @memberOf _ - * @since 4.1.0 - * @category Array - * @param {Array} [props=[]] The property identifiers. - * @param {Array} [values=[]] The property values. - * @returns {Object} Returns the new object. - * @example - * - * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]); - * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } } - */ - function zipObjectDeep(props, values) { - return baseZipObject(props || [], values || [], baseSet); - } - - /** - * This method is like `_.zip` except that it accepts `iteratee` to specify - * how grouped values should be combined. The iteratee is invoked with the - * elements of each group: (...group). - * - * @static - * @memberOf _ - * @since 3.8.0 - * @category Array - * @param {...Array} [arrays] The arrays to process. - * @param {Function} [iteratee=_.identity] The function to combine - * grouped values. - * @returns {Array} Returns the new array of grouped elements. - * @example - * - * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) { - * return a + b + c; - * }); - * // => [111, 222] - */ - var zipWith = baseRest(function(arrays) { - var length = arrays.length, - iteratee = length > 1 ? arrays[length - 1] : undefined; - - iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined; - return unzipWith(arrays, iteratee); - }); - - /*------------------------------------------------------------------------*/ - - /** - * Creates a `lodash` wrapper instance that wraps `value` with explicit method - * chain sequences enabled. The result of such sequences must be unwrapped - * with `_#value`. - * - * @static - * @memberOf _ - * @since 1.3.0 - * @category Seq - * @param {*} value The value to wrap. - * @returns {Object} Returns the new `lodash` wrapper instance. - * @example - * - * var users = [ - * { 'user': 'barney', 'age': 36 }, - * { 'user': 'fred', 'age': 40 }, - * { 'user': 'pebbles', 'age': 1 } - * ]; - * - * var youngest = _ - * .chain(users) - * .sortBy('age') - * .map(function(o) { - * return o.user + ' is ' + o.age; - * }) - * .head() - * .value(); - * // => 'pebbles is 1' - */ - function chain(value) { - var result = lodash(value); - result.__chain__ = true; - return result; - } - - /** - * This method invokes `interceptor` and returns `value`. The interceptor - * is invoked with one argument; (value). The purpose of this method is to - * "tap into" a method chain sequence in order to modify intermediate results. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Seq - * @param {*} value The value to provide to `interceptor`. - * @param {Function} interceptor The function to invoke. - * @returns {*} Returns `value`. - * @example - * - * _([1, 2, 3]) - * .tap(function(array) { - * // Mutate input array. - * array.pop(); - * }) - * .reverse() - * .value(); - * // => [2, 1] - */ - function tap(value, interceptor) { - interceptor(value); - return value; - } - - /** - * This method is like `_.tap` except that it returns the result of `interceptor`. - * The purpose of this method is to "pass thru" values replacing intermediate - * results in a method chain sequence. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Seq - * @param {*} value The value to provide to `interceptor`. - * @param {Function} interceptor The function to invoke. - * @returns {*} Returns the result of `interceptor`. - * @example - * - * _(' abc ') - * .chain() - * .trim() - * .thru(function(value) { - * return [value]; - * }) - * .value(); - * // => ['abc'] - */ - function thru(value, interceptor) { - return interceptor(value); - } - - /** - * This method is the wrapper version of `_.at`. - * - * @name at - * @memberOf _ - * @since 1.0.0 - * @category Seq - * @param {...(string|string[])} [paths] The property paths to pick. - * @returns {Object} Returns the new `lodash` wrapper instance. - * @example - * - * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; - * - * _(object).at(['a[0].b.c', 'a[1]']).value(); - * // => [3, 4] - */ - var wrapperAt = flatRest(function(paths) { - var length = paths.length, - start = length ? paths[0] : 0, - value = this.__wrapped__, - interceptor = function(object) { return baseAt(object, paths); }; - - if (length > 1 || this.__actions__.length || - !(value instanceof LazyWrapper) || !isIndex(start)) { - return this.thru(interceptor); - } - value = value.slice(start, +start + (length ? 1 : 0)); - value.__actions__.push({ - 'func': thru, - 'args': [interceptor], - 'thisArg': undefined - }); - return new LodashWrapper(value, this.__chain__).thru(function(array) { - if (length && !array.length) { - array.push(undefined); - } - return array; - }); - }); - - /** - * Creates a `lodash` wrapper instance with explicit method chain sequences enabled. - * - * @name chain - * @memberOf _ - * @since 0.1.0 - * @category Seq - * @returns {Object} Returns the new `lodash` wrapper instance. - * @example - * - * var users = [ - * { 'user': 'barney', 'age': 36 }, - * { 'user': 'fred', 'age': 40 } - * ]; - * - * // A sequence without explicit chaining. - * _(users).head(); - * // => { 'user': 'barney', 'age': 36 } - * - * // A sequence with explicit chaining. - * _(users) - * .chain() - * .head() - * .pick('user') - * .value(); - * // => { 'user': 'barney' } - */ - function wrapperChain() { - return chain(this); - } - - /** - * Executes the chain sequence and returns the wrapped result. - * - * @name commit - * @memberOf _ - * @since 3.2.0 - * @category Seq - * @returns {Object} Returns the new `lodash` wrapper instance. - * @example - * - * var array = [1, 2]; - * var wrapped = _(array).push(3); - * - * console.log(array); - * // => [1, 2] - * - * wrapped = wrapped.commit(); - * console.log(array); - * // => [1, 2, 3] - * - * wrapped.last(); - * // => 3 - * - * console.log(array); - * // => [1, 2, 3] - */ - function wrapperCommit() { - return new LodashWrapper(this.value(), this.__chain__); - } - - /** - * Gets the next value on a wrapped object following the - * [iterator protocol](https://mdn.io/iteration_protocols#iterator). - * - * @name next - * @memberOf _ - * @since 4.0.0 - * @category Seq - * @returns {Object} Returns the next iterator value. - * @example - * - * var wrapped = _([1, 2]); - * - * wrapped.next(); - * // => { 'done': false, 'value': 1 } - * - * wrapped.next(); - * // => { 'done': false, 'value': 2 } - * - * wrapped.next(); - * // => { 'done': true, 'value': undefined } - */ - function wrapperNext() { - if (this.__values__ === undefined) { - this.__values__ = toArray(this.value()); - } - var done = this.__index__ >= this.__values__.length, - value = done ? undefined : this.__values__[this.__index__++]; - - return { 'done': done, 'value': value }; - } - - /** - * Enables the wrapper to be iterable. - * - * @name Symbol.iterator - * @memberOf _ - * @since 4.0.0 - * @category Seq - * @returns {Object} Returns the wrapper object. - * @example - * - * var wrapped = _([1, 2]); - * - * wrapped[Symbol.iterator]() === wrapped; - * // => true - * - * Array.from(wrapped); - * // => [1, 2] - */ - function wrapperToIterator() { - return this; - } - - /** - * Creates a clone of the chain sequence planting `value` as the wrapped value. - * - * @name plant - * @memberOf _ - * @since 3.2.0 - * @category Seq - * @param {*} value The value to plant. - * @returns {Object} Returns the new `lodash` wrapper instance. - * @example - * - * function square(n) { - * return n * n; - * } - * - * var wrapped = _([1, 2]).map(square); - * var other = wrapped.plant([3, 4]); - * - * other.value(); - * // => [9, 16] - * - * wrapped.value(); - * // => [1, 4] - */ - function wrapperPlant(value) { - var result, - parent = this; - - while (parent instanceof baseLodash) { - var clone = wrapperClone(parent); - clone.__index__ = 0; - clone.__values__ = undefined; - if (result) { - previous.__wrapped__ = clone; - } else { - result = clone; - } - var previous = clone; - parent = parent.__wrapped__; - } - previous.__wrapped__ = value; - return result; - } - - /** - * This method is the wrapper version of `_.reverse`. - * - * **Note:** This method mutates the wrapped array. - * - * @name reverse - * @memberOf _ - * @since 0.1.0 - * @category Seq - * @returns {Object} Returns the new `lodash` wrapper instance. - * @example - * - * var array = [1, 2, 3]; - * - * _(array).reverse().value() - * // => [3, 2, 1] - * - * console.log(array); - * // => [3, 2, 1] - */ - function wrapperReverse() { - var value = this.__wrapped__; - if (value instanceof LazyWrapper) { - var wrapped = value; - if (this.__actions__.length) { - wrapped = new LazyWrapper(this); - } - wrapped = wrapped.reverse(); - wrapped.__actions__.push({ - 'func': thru, - 'args': [reverse], - 'thisArg': undefined - }); - return new LodashWrapper(wrapped, this.__chain__); - } - return this.thru(reverse); - } - - /** - * Executes the chain sequence to resolve the unwrapped value. - * - * @name value - * @memberOf _ - * @since 0.1.0 - * @alias toJSON, valueOf - * @category Seq - * @returns {*} Returns the resolved unwrapped value. - * @example - * - * _([1, 2, 3]).value(); - * // => [1, 2, 3] - */ - function wrapperValue() { - return baseWrapperValue(this.__wrapped__, this.__actions__); - } - - /*------------------------------------------------------------------------*/ - - /** - * Creates an object composed of keys generated from the results of running - * each element of `collection` thru `iteratee`. The corresponding value of - * each key is the number of times the key was returned by `iteratee`. The - * iteratee is invoked with one argument: (value). - * - * @static - * @memberOf _ - * @since 0.5.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [iteratee=_.identity] The iteratee to transform keys. - * @returns {Object} Returns the composed aggregate object. - * @example - * - * _.countBy([6.1, 4.2, 6.3], Math.floor); - * // => { '4': 1, '6': 2 } - * - * // The `_.property` iteratee shorthand. - * _.countBy(['one', 'two', 'three'], 'length'); - * // => { '3': 2, '5': 1 } - */ - var countBy = createAggregator(function(result, value, key) { - if (hasOwnProperty.call(result, key)) { - ++result[key]; - } else { - baseAssignValue(result, key, 1); - } - }); - - /** - * Checks if `predicate` returns truthy for **all** elements of `collection`. - * Iteration is stopped once `predicate` returns falsey. The predicate is - * invoked with three arguments: (value, index|key, collection). - * - * **Note:** This method returns `true` for - * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because - * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of - * elements of empty collections. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. - * @returns {boolean} Returns `true` if all elements pass the predicate check, - * else `false`. - * @example - * - * _.every([true, 1, null, 'yes'], Boolean); - * // => false - * - * var users = [ - * { 'user': 'barney', 'age': 36, 'active': false }, - * { 'user': 'fred', 'age': 40, 'active': false } - * ]; - * - * // The `_.matches` iteratee shorthand. - * _.every(users, { 'user': 'barney', 'active': false }); - * // => false - * - * // The `_.matchesProperty` iteratee shorthand. - * _.every(users, ['active', false]); - * // => true - * - * // The `_.property` iteratee shorthand. - * _.every(users, 'active'); - * // => false - */ - function every(collection, predicate, guard) { - var func = isArray(collection) ? arrayEvery : baseEvery; - if (guard && isIterateeCall(collection, predicate, guard)) { - predicate = undefined; - } - return func(collection, getIteratee(predicate, 3)); - } - - /** - * Iterates over elements of `collection`, returning an array of all elements - * `predicate` returns truthy for. The predicate is invoked with three - * arguments: (value, index|key, collection). - * - * **Note:** Unlike `_.remove`, this method returns a new array. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @returns {Array} Returns the new filtered array. - * @see _.reject - * @example - * - * var users = [ - * { 'user': 'barney', 'age': 36, 'active': true }, - * { 'user': 'fred', 'age': 40, 'active': false } - * ]; - * - * _.filter(users, function(o) { return !o.active; }); - * // => objects for ['fred'] - * - * // The `_.matches` iteratee shorthand. - * _.filter(users, { 'age': 36, 'active': true }); - * // => objects for ['barney'] - * - * // The `_.matchesProperty` iteratee shorthand. - * _.filter(users, ['active', false]); - * // => objects for ['fred'] - * - * // The `_.property` iteratee shorthand. - * _.filter(users, 'active'); - * // => objects for ['barney'] - */ - function filter(collection, predicate) { - var func = isArray(collection) ? arrayFilter : baseFilter; - return func(collection, getIteratee(predicate, 3)); - } - - /** - * Iterates over elements of `collection`, returning the first element - * `predicate` returns truthy for. The predicate is invoked with three - * arguments: (value, index|key, collection). - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Collection - * @param {Array|Object} collection The collection to inspect. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @param {number} [fromIndex=0] The index to search from. - * @returns {*} Returns the matched element, else `undefined`. - * @example - * - * var users = [ - * { 'user': 'barney', 'age': 36, 'active': true }, - * { 'user': 'fred', 'age': 40, 'active': false }, - * { 'user': 'pebbles', 'age': 1, 'active': true } - * ]; - * - * _.find(users, function(o) { return o.age < 40; }); - * // => object for 'barney' - * - * // The `_.matches` iteratee shorthand. - * _.find(users, { 'age': 1, 'active': true }); - * // => object for 'pebbles' - * - * // The `_.matchesProperty` iteratee shorthand. - * _.find(users, ['active', false]); - * // => object for 'fred' - * - * // The `_.property` iteratee shorthand. - * _.find(users, 'active'); - * // => object for 'barney' - */ - var find = createFind(findIndex); - - /** - * This method is like `_.find` except that it iterates over elements of - * `collection` from right to left. - * - * @static - * @memberOf _ - * @since 2.0.0 - * @category Collection - * @param {Array|Object} collection The collection to inspect. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @param {number} [fromIndex=collection.length-1] The index to search from. - * @returns {*} Returns the matched element, else `undefined`. - * @example - * - * _.findLast([1, 2, 3, 4], function(n) { - * return n % 2 == 1; - * }); - * // => 3 - */ - var findLast = createFind(findLastIndex); - - /** - * Creates a flattened array of values by running each element in `collection` - * thru `iteratee` and flattening the mapped results. The iteratee is invoked - * with three arguments: (value, index|key, collection). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @returns {Array} Returns the new flattened array. - * @example - * - * function duplicate(n) { - * return [n, n]; - * } - * - * _.flatMap([1, 2], duplicate); - * // => [1, 1, 2, 2] - */ - function flatMap(collection, iteratee) { - return baseFlatten(map(collection, iteratee), 1); - } - - /** - * This method is like `_.flatMap` except that it recursively flattens the - * mapped results. - * - * @static - * @memberOf _ - * @since 4.7.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @returns {Array} Returns the new flattened array. - * @example - * - * function duplicate(n) { - * return [[[n, n]]]; - * } - * - * _.flatMapDeep([1, 2], duplicate); - * // => [1, 1, 2, 2] - */ - function flatMapDeep(collection, iteratee) { - return baseFlatten(map(collection, iteratee), INFINITY); - } - - /** - * This method is like `_.flatMap` except that it recursively flattens the - * mapped results up to `depth` times. - * - * @static - * @memberOf _ - * @since 4.7.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @param {number} [depth=1] The maximum recursion depth. - * @returns {Array} Returns the new flattened array. - * @example - * - * function duplicate(n) { - * return [[[n, n]]]; - * } - * - * _.flatMapDepth([1, 2], duplicate, 2); - * // => [[1, 1], [2, 2]] - */ - function flatMapDepth(collection, iteratee, depth) { - depth = depth === undefined ? 1 : toInteger(depth); - return baseFlatten(map(collection, iteratee), depth); - } - - /** - * Iterates over elements of `collection` and invokes `iteratee` for each element. - * The iteratee is invoked with three arguments: (value, index|key, collection). - * Iteratee functions may exit iteration early by explicitly returning `false`. - * - * **Note:** As with other "Collections" methods, objects with a "length" - * property are iterated like arrays. To avoid this behavior use `_.forIn` - * or `_.forOwn` for object iteration. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @alias each - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @returns {Array|Object} Returns `collection`. - * @see _.forEachRight - * @example - * - * _.forEach([1, 2], function(value) { - * console.log(value); - * }); - * // => Logs `1` then `2`. - * - * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) { - * console.log(key); - * }); - * // => Logs 'a' then 'b' (iteration order is not guaranteed). - */ - function forEach(collection, iteratee) { - var func = isArray(collection) ? arrayEach : baseEach; - return func(collection, getIteratee(iteratee, 3)); - } - - /** - * This method is like `_.forEach` except that it iterates over elements of - * `collection` from right to left. - * - * @static - * @memberOf _ - * @since 2.0.0 - * @alias eachRight - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @returns {Array|Object} Returns `collection`. - * @see _.forEach - * @example - * - * _.forEachRight([1, 2], function(value) { - * console.log(value); - * }); - * // => Logs `2` then `1`. - */ - function forEachRight(collection, iteratee) { - var func = isArray(collection) ? arrayEachRight : baseEachRight; - return func(collection, getIteratee(iteratee, 3)); - } - - /** - * Creates an object composed of keys generated from the results of running - * each element of `collection` thru `iteratee`. The order of grouped values - * is determined by the order they occur in `collection`. The corresponding - * value of each key is an array of elements responsible for generating the - * key. The iteratee is invoked with one argument: (value). - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [iteratee=_.identity] The iteratee to transform keys. - * @returns {Object} Returns the composed aggregate object. - * @example - * - * _.groupBy([6.1, 4.2, 6.3], Math.floor); - * // => { '4': [4.2], '6': [6.1, 6.3] } - * - * // The `_.property` iteratee shorthand. - * _.groupBy(['one', 'two', 'three'], 'length'); - * // => { '3': ['one', 'two'], '5': ['three'] } - */ - var groupBy = createAggregator(function(result, value, key) { - if (hasOwnProperty.call(result, key)) { - result[key].push(value); - } else { - baseAssignValue(result, key, [value]); - } - }); - - /** - * Checks if `value` is in `collection`. If `collection` is a string, it's - * checked for a substring of `value`, otherwise - * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * is used for equality comparisons. If `fromIndex` is negative, it's used as - * the offset from the end of `collection`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Collection - * @param {Array|Object|string} collection The collection to inspect. - * @param {*} value The value to search for. - * @param {number} [fromIndex=0] The index to search from. - * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. - * @returns {boolean} Returns `true` if `value` is found, else `false`. - * @example - * - * _.includes([1, 2, 3], 1); - * // => true - * - * _.includes([1, 2, 3], 1, 2); - * // => false - * - * _.includes({ 'a': 1, 'b': 2 }, 1); - * // => true - * - * _.includes('abcd', 'bc'); - * // => true - */ - function includes(collection, value, fromIndex, guard) { - collection = isArrayLike(collection) ? collection : values(collection); - fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0; - - var length = collection.length; - if (fromIndex < 0) { - fromIndex = nativeMax(length + fromIndex, 0); - } - return isString(collection) - ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1) - : (!!length && baseIndexOf(collection, value, fromIndex) > -1); - } - - /** - * Invokes the method at `path` of each element in `collection`, returning - * an array of the results of each invoked method. Any additional arguments - * are provided to each invoked method. If `path` is a function, it's invoked - * for, and `this` bound to, each element in `collection`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Array|Function|string} path The path of the method to invoke or - * the function invoked per iteration. - * @param {...*} [args] The arguments to invoke each method with. - * @returns {Array} Returns the array of results. - * @example - * - * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort'); - * // => [[1, 5, 7], [1, 2, 3]] - * - * _.invokeMap([123, 456], String.prototype.split, ''); - * // => [['1', '2', '3'], ['4', '5', '6']] - */ - var invokeMap = baseRest(function(collection, path, args) { - var index = -1, - isFunc = typeof path == 'function', - result = isArrayLike(collection) ? Array(collection.length) : []; - - baseEach(collection, function(value) { - result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args); - }); - return result; - }); - - /** - * Creates an object composed of keys generated from the results of running - * each element of `collection` thru `iteratee`. The corresponding value of - * each key is the last element responsible for generating the key. The - * iteratee is invoked with one argument: (value). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [iteratee=_.identity] The iteratee to transform keys. - * @returns {Object} Returns the composed aggregate object. - * @example - * - * var array = [ - * { 'dir': 'left', 'code': 97 }, - * { 'dir': 'right', 'code': 100 } - * ]; - * - * _.keyBy(array, function(o) { - * return String.fromCharCode(o.code); - * }); - * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } } - * - * _.keyBy(array, 'dir'); - * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } } - */ - var keyBy = createAggregator(function(result, value, key) { - baseAssignValue(result, key, value); - }); - - /** - * Creates an array of values by running each element in `collection` thru - * `iteratee`. The iteratee is invoked with three arguments: - * (value, index|key, collection). - * - * Many lodash methods are guarded to work as iteratees for methods like - * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`. - * - * The guarded methods are: - * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`, - * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`, - * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`, - * `template`, `trim`, `trimEnd`, `trimStart`, and `words` - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @returns {Array} Returns the new mapped array. - * @example - * - * function square(n) { - * return n * n; - * } - * - * _.map([4, 8], square); - * // => [16, 64] - * - * _.map({ 'a': 4, 'b': 8 }, square); - * // => [16, 64] (iteration order is not guaranteed) - * - * var users = [ - * { 'user': 'barney' }, - * { 'user': 'fred' } - * ]; - * - * // The `_.property` iteratee shorthand. - * _.map(users, 'user'); - * // => ['barney', 'fred'] - */ - function map(collection, iteratee) { - var func = isArray(collection) ? arrayMap : baseMap; - return func(collection, getIteratee(iteratee, 3)); - } - - /** - * This method is like `_.sortBy` except that it allows specifying the sort - * orders of the iteratees to sort by. If `orders` is unspecified, all values - * are sorted in ascending order. Otherwise, specify an order of "desc" for - * descending or "asc" for ascending sort order of corresponding values. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]] - * The iteratees to sort by. - * @param {string[]} [orders] The sort orders of `iteratees`. - * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`. - * @returns {Array} Returns the new sorted array. - * @example - * - * var users = [ - * { 'user': 'fred', 'age': 48 }, - * { 'user': 'barney', 'age': 34 }, - * { 'user': 'fred', 'age': 40 }, - * { 'user': 'barney', 'age': 36 } - * ]; - * - * // Sort by `user` in ascending order and by `age` in descending order. - * _.orderBy(users, ['user', 'age'], ['asc', 'desc']); - * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] - */ - function orderBy(collection, iteratees, orders, guard) { - if (collection == null) { - return []; - } - if (!isArray(iteratees)) { - iteratees = iteratees == null ? [] : [iteratees]; - } - orders = guard ? undefined : orders; - if (!isArray(orders)) { - orders = orders == null ? [] : [orders]; - } - return baseOrderBy(collection, iteratees, orders); - } - - /** - * Creates an array of elements split into two groups, the first of which - * contains elements `predicate` returns truthy for, the second of which - * contains elements `predicate` returns falsey for. The predicate is - * invoked with one argument: (value). - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @returns {Array} Returns the array of grouped elements. - * @example - * - * var users = [ - * { 'user': 'barney', 'age': 36, 'active': false }, - * { 'user': 'fred', 'age': 40, 'active': true }, - * { 'user': 'pebbles', 'age': 1, 'active': false } - * ]; - * - * _.partition(users, function(o) { return o.active; }); - * // => objects for [['fred'], ['barney', 'pebbles']] - * - * // The `_.matches` iteratee shorthand. - * _.partition(users, { 'age': 1, 'active': false }); - * // => objects for [['pebbles'], ['barney', 'fred']] - * - * // The `_.matchesProperty` iteratee shorthand. - * _.partition(users, ['active', false]); - * // => objects for [['barney', 'pebbles'], ['fred']] - * - * // The `_.property` iteratee shorthand. - * _.partition(users, 'active'); - * // => objects for [['fred'], ['barney', 'pebbles']] - */ - var partition = createAggregator(function(result, value, key) { - result[key ? 0 : 1].push(value); - }, function() { return [[], []]; }); - - /** - * Reduces `collection` to a value which is the accumulated result of running - * each element in `collection` thru `iteratee`, where each successive - * invocation is supplied the return value of the previous. If `accumulator` - * is not given, the first element of `collection` is used as the initial - * value. The iteratee is invoked with four arguments: - * (accumulator, value, index|key, collection). - * - * Many lodash methods are guarded to work as iteratees for methods like - * `_.reduce`, `_.reduceRight`, and `_.transform`. - * - * The guarded methods are: - * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`, - * and `sortBy` - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @param {*} [accumulator] The initial value. - * @returns {*} Returns the accumulated value. - * @see _.reduceRight - * @example - * - * _.reduce([1, 2], function(sum, n) { - * return sum + n; - * }, 0); - * // => 3 - * - * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { - * (result[value] || (result[value] = [])).push(key); - * return result; - * }, {}); - * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed) - */ - function reduce(collection, iteratee, accumulator) { - var func = isArray(collection) ? arrayReduce : baseReduce, - initAccum = arguments.length < 3; - - return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach); - } - - /** - * This method is like `_.reduce` except that it iterates over elements of - * `collection` from right to left. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @param {*} [accumulator] The initial value. - * @returns {*} Returns the accumulated value. - * @see _.reduce - * @example - * - * var array = [[0, 1], [2, 3], [4, 5]]; - * - * _.reduceRight(array, function(flattened, other) { - * return flattened.concat(other); - * }, []); - * // => [4, 5, 2, 3, 0, 1] - */ - function reduceRight(collection, iteratee, accumulator) { - var func = isArray(collection) ? arrayReduceRight : baseReduce, - initAccum = arguments.length < 3; - - return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight); - } - - /** - * The opposite of `_.filter`; this method returns the elements of `collection` - * that `predicate` does **not** return truthy for. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @returns {Array} Returns the new filtered array. - * @see _.filter - * @example - * - * var users = [ - * { 'user': 'barney', 'age': 36, 'active': false }, - * { 'user': 'fred', 'age': 40, 'active': true } - * ]; - * - * _.reject(users, function(o) { return !o.active; }); - * // => objects for ['fred'] - * - * // The `_.matches` iteratee shorthand. - * _.reject(users, { 'age': 40, 'active': true }); - * // => objects for ['barney'] - * - * // The `_.matchesProperty` iteratee shorthand. - * _.reject(users, ['active', false]); - * // => objects for ['fred'] - * - * // The `_.property` iteratee shorthand. - * _.reject(users, 'active'); - * // => objects for ['barney'] - */ - function reject(collection, predicate) { - var func = isArray(collection) ? arrayFilter : baseFilter; - return func(collection, negate(getIteratee(predicate, 3))); - } - - /** - * Gets a random element from `collection`. - * - * @static - * @memberOf _ - * @since 2.0.0 - * @category Collection - * @param {Array|Object} collection The collection to sample. - * @returns {*} Returns the random element. - * @example - * - * _.sample([1, 2, 3, 4]); - * // => 2 - */ - function sample(collection) { - var func = isArray(collection) ? arraySample : baseSample; - return func(collection); - } - - /** - * Gets `n` random elements at unique keys from `collection` up to the - * size of `collection`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Collection - * @param {Array|Object} collection The collection to sample. - * @param {number} [n=1] The number of elements to sample. - * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. - * @returns {Array} Returns the random elements. - * @example - * - * _.sampleSize([1, 2, 3], 2); - * // => [3, 1] - * - * _.sampleSize([1, 2, 3], 4); - * // => [2, 3, 1] - */ - function sampleSize(collection, n, guard) { - if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) { - n = 1; - } else { - n = toInteger(n); - } - var func = isArray(collection) ? arraySampleSize : baseSampleSize; - return func(collection, n); - } - - /** - * Creates an array of shuffled values, using a version of the - * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle). - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Collection - * @param {Array|Object} collection The collection to shuffle. - * @returns {Array} Returns the new shuffled array. - * @example - * - * _.shuffle([1, 2, 3, 4]); - * // => [4, 1, 3, 2] - */ - function shuffle(collection) { - var func = isArray(collection) ? arrayShuffle : baseShuffle; - return func(collection); - } - - /** - * Gets the size of `collection` by returning its length for array-like - * values or the number of own enumerable string keyed properties for objects. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Collection - * @param {Array|Object|string} collection The collection to inspect. - * @returns {number} Returns the collection size. - * @example - * - * _.size([1, 2, 3]); - * // => 3 - * - * _.size({ 'a': 1, 'b': 2 }); - * // => 2 - * - * _.size('pebbles'); - * // => 7 - */ - function size(collection) { - if (collection == null) { - return 0; - } - if (isArrayLike(collection)) { - return isString(collection) ? stringSize(collection) : collection.length; - } - var tag = getTag(collection); - if (tag == mapTag || tag == setTag) { - return collection.size; - } - return baseKeys(collection).length; - } - - /** - * Checks if `predicate` returns truthy for **any** element of `collection`. - * Iteration is stopped once `predicate` returns truthy. The predicate is - * invoked with three arguments: (value, index|key, collection). - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. - * @returns {boolean} Returns `true` if any element passes the predicate check, - * else `false`. - * @example - * - * _.some([null, 0, 'yes', false], Boolean); - * // => true - * - * var users = [ - * { 'user': 'barney', 'active': true }, - * { 'user': 'fred', 'active': false } - * ]; - * - * // The `_.matches` iteratee shorthand. - * _.some(users, { 'user': 'barney', 'active': false }); - * // => false - * - * // The `_.matchesProperty` iteratee shorthand. - * _.some(users, ['active', false]); - * // => true - * - * // The `_.property` iteratee shorthand. - * _.some(users, 'active'); - * // => true - */ - function some(collection, predicate, guard) { - var func = isArray(collection) ? arraySome : baseSome; - if (guard && isIterateeCall(collection, predicate, guard)) { - predicate = undefined; - } - return func(collection, getIteratee(predicate, 3)); - } - - /** - * Creates an array of elements, sorted in ascending order by the results of - * running each element in a collection thru each iteratee. This method - * performs a stable sort, that is, it preserves the original sort order of - * equal elements. The iteratees are invoked with one argument: (value). - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Collection - * @param {Array|Object} collection The collection to iterate over. - * @param {...(Function|Function[])} [iteratees=[_.identity]] - * The iteratees to sort by. - * @returns {Array} Returns the new sorted array. - * @example - * - * var users = [ - * { 'user': 'fred', 'age': 48 }, - * { 'user': 'barney', 'age': 36 }, - * { 'user': 'fred', 'age': 40 }, - * { 'user': 'barney', 'age': 34 } - * ]; - * - * _.sortBy(users, [function(o) { return o.user; }]); - * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]] - * - * _.sortBy(users, ['user', 'age']); - * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]] - */ - var sortBy = baseRest(function(collection, iteratees) { - if (collection == null) { - return []; - } - var length = iteratees.length; - if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) { - iteratees = []; - } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) { - iteratees = [iteratees[0]]; - } - return baseOrderBy(collection, baseFlatten(iteratees, 1), []); - }); - - /*------------------------------------------------------------------------*/ - - /** - * Gets the timestamp of the number of milliseconds that have elapsed since - * the Unix epoch (1 January 1970 00:00:00 UTC). - * - * @static - * @memberOf _ - * @since 2.4.0 - * @category Date - * @returns {number} Returns the timestamp. - * @example - * - * _.defer(function(stamp) { - * console.log(_.now() - stamp); - * }, _.now()); - * // => Logs the number of milliseconds it took for the deferred invocation. - */ - var now = ctxNow || function() { - return root.Date.now(); - }; - - /*------------------------------------------------------------------------*/ - - /** - * The opposite of `_.before`; this method creates a function that invokes - * `func` once it's called `n` or more times. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Function - * @param {number} n The number of calls before `func` is invoked. - * @param {Function} func The function to restrict. - * @returns {Function} Returns the new restricted function. - * @example - * - * var saves = ['profile', 'settings']; - * - * var done = _.after(saves.length, function() { - * console.log('done saving!'); - * }); - * - * _.forEach(saves, function(type) { - * asyncSave({ 'type': type, 'complete': done }); - * }); - * // => Logs 'done saving!' after the two async saves have completed. - */ - function after(n, func) { - if (typeof func != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - n = toInteger(n); - return function() { - if (--n < 1) { - return func.apply(this, arguments); - } - }; - } - - /** - * Creates a function that invokes `func`, with up to `n` arguments, - * ignoring any additional arguments. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Function - * @param {Function} func The function to cap arguments for. - * @param {number} [n=func.length] The arity cap. - * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. - * @returns {Function} Returns the new capped function. - * @example - * - * _.map(['6', '8', '10'], _.ary(parseInt, 1)); - * // => [6, 8, 10] - */ - function ary(func, n, guard) { - n = guard ? undefined : n; - n = (func && n == null) ? func.length : n; - return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n); - } - - /** - * Creates a function that invokes `func`, with the `this` binding and arguments - * of the created function, while it's called less than `n` times. Subsequent - * calls to the created function return the result of the last `func` invocation. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Function - * @param {number} n The number of calls at which `func` is no longer invoked. - * @param {Function} func The function to restrict. - * @returns {Function} Returns the new restricted function. - * @example - * - * jQuery(element).on('click', _.before(5, addContactToList)); - * // => Allows adding up to 4 contacts to the list. - */ - function before(n, func) { - var result; - if (typeof func != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - n = toInteger(n); - return function() { - if (--n > 0) { - result = func.apply(this, arguments); - } - if (n <= 1) { - func = undefined; - } - return result; - }; - } - - /** - * Creates a function that invokes `func` with the `this` binding of `thisArg` - * and `partials` prepended to the arguments it receives. - * - * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds, - * may be used as a placeholder for partially applied arguments. - * - * **Note:** Unlike native `Function#bind`, this method doesn't set the "length" - * property of bound functions. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Function - * @param {Function} func The function to bind. - * @param {*} thisArg The `this` binding of `func`. - * @param {...*} [partials] The arguments to be partially applied. - * @returns {Function} Returns the new bound function. - * @example - * - * function greet(greeting, punctuation) { - * return greeting + ' ' + this.user + punctuation; - * } - * - * var object = { 'user': 'fred' }; - * - * var bound = _.bind(greet, object, 'hi'); - * bound('!'); - * // => 'hi fred!' - * - * // Bound with placeholders. - * var bound = _.bind(greet, object, _, '!'); - * bound('hi'); - * // => 'hi fred!' - */ - var bind = baseRest(function(func, thisArg, partials) { - var bitmask = WRAP_BIND_FLAG; - if (partials.length) { - var holders = replaceHolders(partials, getHolder(bind)); - bitmask |= WRAP_PARTIAL_FLAG; - } - return createWrap(func, bitmask, thisArg, partials, holders); - }); - - /** - * Creates a function that invokes the method at `object[key]` with `partials` - * prepended to the arguments it receives. - * - * This method differs from `_.bind` by allowing bound functions to reference - * methods that may be redefined or don't yet exist. See - * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern) - * for more details. - * - * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic - * builds, may be used as a placeholder for partially applied arguments. - * - * @static - * @memberOf _ - * @since 0.10.0 - * @category Function - * @param {Object} object The object to invoke the method on. - * @param {string} key The key of the method. - * @param {...*} [partials] The arguments to be partially applied. - * @returns {Function} Returns the new bound function. - * @example - * - * var object = { - * 'user': 'fred', - * 'greet': function(greeting, punctuation) { - * return greeting + ' ' + this.user + punctuation; - * } - * }; - * - * var bound = _.bindKey(object, 'greet', 'hi'); - * bound('!'); - * // => 'hi fred!' - * - * object.greet = function(greeting, punctuation) { - * return greeting + 'ya ' + this.user + punctuation; - * }; - * - * bound('!'); - * // => 'hiya fred!' - * - * // Bound with placeholders. - * var bound = _.bindKey(object, 'greet', _, '!'); - * bound('hi'); - * // => 'hiya fred!' - */ - var bindKey = baseRest(function(object, key, partials) { - var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG; - if (partials.length) { - var holders = replaceHolders(partials, getHolder(bindKey)); - bitmask |= WRAP_PARTIAL_FLAG; - } - return createWrap(key, bitmask, object, partials, holders); - }); - - /** - * Creates a function that accepts arguments of `func` and either invokes - * `func` returning its result, if at least `arity` number of arguments have - * been provided, or returns a function that accepts the remaining `func` - * arguments, and so on. The arity of `func` may be specified if `func.length` - * is not sufficient. - * - * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds, - * may be used as a placeholder for provided arguments. - * - * **Note:** This method doesn't set the "length" property of curried functions. - * - * @static - * @memberOf _ - * @since 2.0.0 - * @category Function - * @param {Function} func The function to curry. - * @param {number} [arity=func.length] The arity of `func`. - * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. - * @returns {Function} Returns the new curried function. - * @example - * - * var abc = function(a, b, c) { - * return [a, b, c]; - * }; - * - * var curried = _.curry(abc); - * - * curried(1)(2)(3); - * // => [1, 2, 3] - * - * curried(1, 2)(3); - * // => [1, 2, 3] - * - * curried(1, 2, 3); - * // => [1, 2, 3] - * - * // Curried with placeholders. - * curried(1)(_, 3)(2); - * // => [1, 2, 3] - */ - function curry(func, arity, guard) { - arity = guard ? undefined : arity; - var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity); - result.placeholder = curry.placeholder; - return result; - } - - /** - * This method is like `_.curry` except that arguments are applied to `func` - * in the manner of `_.partialRight` instead of `_.partial`. - * - * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic - * builds, may be used as a placeholder for provided arguments. - * - * **Note:** This method doesn't set the "length" property of curried functions. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Function - * @param {Function} func The function to curry. - * @param {number} [arity=func.length] The arity of `func`. - * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. - * @returns {Function} Returns the new curried function. - * @example - * - * var abc = function(a, b, c) { - * return [a, b, c]; - * }; - * - * var curried = _.curryRight(abc); - * - * curried(3)(2)(1); - * // => [1, 2, 3] - * - * curried(2, 3)(1); - * // => [1, 2, 3] - * - * curried(1, 2, 3); - * // => [1, 2, 3] - * - * // Curried with placeholders. - * curried(3)(1, _)(2); - * // => [1, 2, 3] - */ - function curryRight(func, arity, guard) { - arity = guard ? undefined : arity; - var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity); - result.placeholder = curryRight.placeholder; - return result; - } - - /** - * Creates a debounced function that delays invoking `func` until after `wait` - * milliseconds have elapsed since the last time the debounced function was - * invoked. The debounced function comes with a `cancel` method to cancel - * delayed `func` invocations and a `flush` method to immediately invoke them. - * Provide `options` to indicate whether `func` should be invoked on the - * leading and/or trailing edge of the `wait` timeout. The `func` is invoked - * with the last arguments provided to the debounced function. Subsequent - * calls to the debounced function return the result of the last `func` - * invocation. - * - * **Note:** If `leading` and `trailing` options are `true`, `func` is - * invoked on the trailing edge of the timeout only if the debounced function - * is invoked more than once during the `wait` timeout. - * - * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred - * until to the next tick, similar to `setTimeout` with a timeout of `0`. - * - * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) - * for details over the differences between `_.debounce` and `_.throttle`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Function - * @param {Function} func The function to debounce. - * @param {number} [wait=0] The number of milliseconds to delay. - * @param {Object} [options={}] The options object. - * @param {boolean} [options.leading=false] - * Specify invoking on the leading edge of the timeout. - * @param {number} [options.maxWait] - * The maximum time `func` is allowed to be delayed before it's invoked. - * @param {boolean} [options.trailing=true] - * Specify invoking on the trailing edge of the timeout. - * @returns {Function} Returns the new debounced function. - * @example - * - * // Avoid costly calculations while the window size is in flux. - * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); - * - * // Invoke `sendMail` when clicked, debouncing subsequent calls. - * jQuery(element).on('click', _.debounce(sendMail, 300, { - * 'leading': true, - * 'trailing': false - * })); - * - * // Ensure `batchLog` is invoked once after 1 second of debounced calls. - * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); - * var source = new EventSource('/stream'); - * jQuery(source).on('message', debounced); - * - * // Cancel the trailing debounced invocation. - * jQuery(window).on('popstate', debounced.cancel); - */ - function debounce(func, wait, options) { - var lastArgs, - lastThis, - maxWait, - result, - timerId, - lastCallTime, - lastInvokeTime = 0, - leading = false, - maxing = false, - trailing = true; - - if (typeof func != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - wait = toNumber(wait) || 0; - if (isObject(options)) { - leading = !!options.leading; - maxing = 'maxWait' in options; - maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; - trailing = 'trailing' in options ? !!options.trailing : trailing; - } - - function invokeFunc(time) { - var args = lastArgs, - thisArg = lastThis; - - lastArgs = lastThis = undefined; - lastInvokeTime = time; - result = func.apply(thisArg, args); - return result; - } - - function leadingEdge(time) { - // Reset any `maxWait` timer. - lastInvokeTime = time; - // Start the timer for the trailing edge. - timerId = setTimeout(timerExpired, wait); - // Invoke the leading edge. - return leading ? invokeFunc(time) : result; - } - - function remainingWait(time) { - var timeSinceLastCall = time - lastCallTime, - timeSinceLastInvoke = time - lastInvokeTime, - timeWaiting = wait - timeSinceLastCall; - - return maxing - ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) - : timeWaiting; - } - - function shouldInvoke(time) { - var timeSinceLastCall = time - lastCallTime, - timeSinceLastInvoke = time - lastInvokeTime; - - // Either this is the first call, activity has stopped and we're at the - // trailing edge, the system time has gone backwards and we're treating - // it as the trailing edge, or we've hit the `maxWait` limit. - return (lastCallTime === undefined || (timeSinceLastCall >= wait) || - (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); - } - - function timerExpired() { - var time = now(); - if (shouldInvoke(time)) { - return trailingEdge(time); - } - // Restart the timer. - timerId = setTimeout(timerExpired, remainingWait(time)); - } - - function trailingEdge(time) { - timerId = undefined; - - // Only invoke if we have `lastArgs` which means `func` has been - // debounced at least once. - if (trailing && lastArgs) { - return invokeFunc(time); - } - lastArgs = lastThis = undefined; - return result; - } - - function cancel() { - if (timerId !== undefined) { - clearTimeout(timerId); - } - lastInvokeTime = 0; - lastArgs = lastCallTime = lastThis = timerId = undefined; - } - - function flush() { - return timerId === undefined ? result : trailingEdge(now()); - } - - function debounced() { - var time = now(), - isInvoking = shouldInvoke(time); - - lastArgs = arguments; - lastThis = this; - lastCallTime = time; - - if (isInvoking) { - if (timerId === undefined) { - return leadingEdge(lastCallTime); - } - if (maxing) { - // Handle invocations in a tight loop. - timerId = setTimeout(timerExpired, wait); - return invokeFunc(lastCallTime); - } - } - if (timerId === undefined) { - timerId = setTimeout(timerExpired, wait); - } - return result; - } - debounced.cancel = cancel; - debounced.flush = flush; - return debounced; - } - - /** - * Defers invoking the `func` until the current call stack has cleared. Any - * additional arguments are provided to `func` when it's invoked. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Function - * @param {Function} func The function to defer. - * @param {...*} [args] The arguments to invoke `func` with. - * @returns {number} Returns the timer id. - * @example - * - * _.defer(function(text) { - * console.log(text); - * }, 'deferred'); - * // => Logs 'deferred' after one millisecond. - */ - var defer = baseRest(function(func, args) { - return baseDelay(func, 1, args); - }); - - /** - * Invokes `func` after `wait` milliseconds. Any additional arguments are - * provided to `func` when it's invoked. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Function - * @param {Function} func The function to delay. - * @param {number} wait The number of milliseconds to delay invocation. - * @param {...*} [args] The arguments to invoke `func` with. - * @returns {number} Returns the timer id. - * @example - * - * _.delay(function(text) { - * console.log(text); - * }, 1000, 'later'); - * // => Logs 'later' after one second. - */ - var delay = baseRest(function(func, wait, args) { - return baseDelay(func, toNumber(wait) || 0, args); - }); - - /** - * Creates a function that invokes `func` with arguments reversed. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Function - * @param {Function} func The function to flip arguments for. - * @returns {Function} Returns the new flipped function. - * @example - * - * var flipped = _.flip(function() { - * return _.toArray(arguments); - * }); - * - * flipped('a', 'b', 'c', 'd'); - * // => ['d', 'c', 'b', 'a'] - */ - function flip(func) { - return createWrap(func, WRAP_FLIP_FLAG); - } - - /** - * Creates a function that memoizes the result of `func`. If `resolver` is - * provided, it determines the cache key for storing the result based on the - * arguments provided to the memoized function. By default, the first argument - * provided to the memoized function is used as the map cache key. The `func` - * is invoked with the `this` binding of the memoized function. - * - * **Note:** The cache is exposed as the `cache` property on the memoized - * function. Its creation may be customized by replacing the `_.memoize.Cache` - * constructor with one whose instances implement the - * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object) - * method interface of `clear`, `delete`, `get`, `has`, and `set`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Function - * @param {Function} func The function to have its output memoized. - * @param {Function} [resolver] The function to resolve the cache key. - * @returns {Function} Returns the new memoized function. - * @example - * - * var object = { 'a': 1, 'b': 2 }; - * var other = { 'c': 3, 'd': 4 }; - * - * var values = _.memoize(_.values); - * values(object); - * // => [1, 2] - * - * values(other); - * // => [3, 4] - * - * object.a = 2; - * values(object); - * // => [1, 2] - * - * // Modify the result cache. - * values.cache.set(object, ['a', 'b']); - * values(object); - * // => ['a', 'b'] - * - * // Replace `_.memoize.Cache`. - * _.memoize.Cache = WeakMap; - */ - function memoize(func, resolver) { - if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) { - throw new TypeError(FUNC_ERROR_TEXT); - } - var memoized = function() { - var args = arguments, - key = resolver ? resolver.apply(this, args) : args[0], - cache = memoized.cache; - - if (cache.has(key)) { - return cache.get(key); - } - var result = func.apply(this, args); - memoized.cache = cache.set(key, result) || cache; - return result; - }; - memoized.cache = new (memoize.Cache || MapCache); - return memoized; - } - - // Expose `MapCache`. - memoize.Cache = MapCache; - - /** - * Creates a function that negates the result of the predicate `func`. The - * `func` predicate is invoked with the `this` binding and arguments of the - * created function. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Function - * @param {Function} predicate The predicate to negate. - * @returns {Function} Returns the new negated function. - * @example - * - * function isEven(n) { - * return n % 2 == 0; - * } - * - * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven)); - * // => [1, 3, 5] - */ - function negate(predicate) { - if (typeof predicate != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - return function() { - var args = arguments; - switch (args.length) { - case 0: return !predicate.call(this); - case 1: return !predicate.call(this, args[0]); - case 2: return !predicate.call(this, args[0], args[1]); - case 3: return !predicate.call(this, args[0], args[1], args[2]); - } - return !predicate.apply(this, args); - }; - } - - /** - * Creates a function that is restricted to invoking `func` once. Repeat calls - * to the function return the value of the first invocation. The `func` is - * invoked with the `this` binding and arguments of the created function. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Function - * @param {Function} func The function to restrict. - * @returns {Function} Returns the new restricted function. - * @example - * - * var initialize = _.once(createApplication); - * initialize(); - * initialize(); - * // => `createApplication` is invoked once - */ - function once(func) { - return before(2, func); - } - - /** - * Creates a function that invokes `func` with its arguments transformed. - * - * @static - * @since 4.0.0 - * @memberOf _ - * @category Function - * @param {Function} func The function to wrap. - * @param {...(Function|Function[])} [transforms=[_.identity]] - * The argument transforms. - * @returns {Function} Returns the new function. - * @example - * - * function doubled(n) { - * return n * 2; - * } - * - * function square(n) { - * return n * n; - * } - * - * var func = _.overArgs(function(x, y) { - * return [x, y]; - * }, [square, doubled]); - * - * func(9, 3); - * // => [81, 6] - * - * func(10, 5); - * // => [100, 10] - */ - var overArgs = castRest(function(func, transforms) { - transforms = (transforms.length == 1 && isArray(transforms[0])) - ? arrayMap(transforms[0], baseUnary(getIteratee())) - : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee())); - - var funcsLength = transforms.length; - return baseRest(function(args) { - var index = -1, - length = nativeMin(args.length, funcsLength); - - while (++index < length) { - args[index] = transforms[index].call(this, args[index]); - } - return apply(func, this, args); - }); - }); - - /** - * Creates a function that invokes `func` with `partials` prepended to the - * arguments it receives. This method is like `_.bind` except it does **not** - * alter the `this` binding. - * - * The `_.partial.placeholder` value, which defaults to `_` in monolithic - * builds, may be used as a placeholder for partially applied arguments. - * - * **Note:** This method doesn't set the "length" property of partially - * applied functions. - * - * @static - * @memberOf _ - * @since 0.2.0 - * @category Function - * @param {Function} func The function to partially apply arguments to. - * @param {...*} [partials] The arguments to be partially applied. - * @returns {Function} Returns the new partially applied function. - * @example - * - * function greet(greeting, name) { - * return greeting + ' ' + name; - * } - * - * var sayHelloTo = _.partial(greet, 'hello'); - * sayHelloTo('fred'); - * // => 'hello fred' - * - * // Partially applied with placeholders. - * var greetFred = _.partial(greet, _, 'fred'); - * greetFred('hi'); - * // => 'hi fred' - */ - var partial = baseRest(function(func, partials) { - var holders = replaceHolders(partials, getHolder(partial)); - return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders); - }); - - /** - * This method is like `_.partial` except that partially applied arguments - * are appended to the arguments it receives. - * - * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic - * builds, may be used as a placeholder for partially applied arguments. - * - * **Note:** This method doesn't set the "length" property of partially - * applied functions. - * - * @static - * @memberOf _ - * @since 1.0.0 - * @category Function - * @param {Function} func The function to partially apply arguments to. - * @param {...*} [partials] The arguments to be partially applied. - * @returns {Function} Returns the new partially applied function. - * @example - * - * function greet(greeting, name) { - * return greeting + ' ' + name; - * } - * - * var greetFred = _.partialRight(greet, 'fred'); - * greetFred('hi'); - * // => 'hi fred' - * - * // Partially applied with placeholders. - * var sayHelloTo = _.partialRight(greet, 'hello', _); - * sayHelloTo('fred'); - * // => 'hello fred' - */ - var partialRight = baseRest(function(func, partials) { - var holders = replaceHolders(partials, getHolder(partialRight)); - return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders); - }); - - /** - * Creates a function that invokes `func` with arguments arranged according - * to the specified `indexes` where the argument value at the first index is - * provided as the first argument, the argument value at the second index is - * provided as the second argument, and so on. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Function - * @param {Function} func The function to rearrange arguments for. - * @param {...(number|number[])} indexes The arranged argument indexes. - * @returns {Function} Returns the new function. - * @example - * - * var rearged = _.rearg(function(a, b, c) { - * return [a, b, c]; - * }, [2, 0, 1]); - * - * rearged('b', 'c', 'a') - * // => ['a', 'b', 'c'] - */ - var rearg = flatRest(function(func, indexes) { - return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes); - }); - - /** - * Creates a function that invokes `func` with the `this` binding of the - * created function and arguments from `start` and beyond provided as - * an array. - * - * **Note:** This method is based on the - * [rest parameter](https://mdn.io/rest_parameters). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Function - * @param {Function} func The function to apply a rest parameter to. - * @param {number} [start=func.length-1] The start position of the rest parameter. - * @returns {Function} Returns the new function. - * @example - * - * var say = _.rest(function(what, names) { - * return what + ' ' + _.initial(names).join(', ') + - * (_.size(names) > 1 ? ', & ' : '') + _.last(names); - * }); - * - * say('hello', 'fred', 'barney', 'pebbles'); - * // => 'hello fred, barney, & pebbles' - */ - function rest(func, start) { - if (typeof func != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - start = start === undefined ? start : toInteger(start); - return baseRest(func, start); - } - - /** - * Creates a function that invokes `func` with the `this` binding of the - * create function and an array of arguments much like - * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply). - * - * **Note:** This method is based on the - * [spread operator](https://mdn.io/spread_operator). - * - * @static - * @memberOf _ - * @since 3.2.0 - * @category Function - * @param {Function} func The function to spread arguments over. - * @param {number} [start=0] The start position of the spread. - * @returns {Function} Returns the new function. - * @example - * - * var say = _.spread(function(who, what) { - * return who + ' says ' + what; - * }); - * - * say(['fred', 'hello']); - * // => 'fred says hello' - * - * var numbers = Promise.all([ - * Promise.resolve(40), - * Promise.resolve(36) - * ]); - * - * numbers.then(_.spread(function(x, y) { - * return x + y; - * })); - * // => a Promise of 76 - */ - function spread(func, start) { - if (typeof func != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - start = start == null ? 0 : nativeMax(toInteger(start), 0); - return baseRest(function(args) { - var array = args[start], - otherArgs = castSlice(args, 0, start); - - if (array) { - arrayPush(otherArgs, array); - } - return apply(func, this, otherArgs); - }); - } - - /** - * Creates a throttled function that only invokes `func` at most once per - * every `wait` milliseconds. The throttled function comes with a `cancel` - * method to cancel delayed `func` invocations and a `flush` method to - * immediately invoke them. Provide `options` to indicate whether `func` - * should be invoked on the leading and/or trailing edge of the `wait` - * timeout. The `func` is invoked with the last arguments provided to the - * throttled function. Subsequent calls to the throttled function return the - * result of the last `func` invocation. - * - * **Note:** If `leading` and `trailing` options are `true`, `func` is - * invoked on the trailing edge of the timeout only if the throttled function - * is invoked more than once during the `wait` timeout. - * - * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred - * until to the next tick, similar to `setTimeout` with a timeout of `0`. - * - * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) - * for details over the differences between `_.throttle` and `_.debounce`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Function - * @param {Function} func The function to throttle. - * @param {number} [wait=0] The number of milliseconds to throttle invocations to. - * @param {Object} [options={}] The options object. - * @param {boolean} [options.leading=true] - * Specify invoking on the leading edge of the timeout. - * @param {boolean} [options.trailing=true] - * Specify invoking on the trailing edge of the timeout. - * @returns {Function} Returns the new throttled function. - * @example - * - * // Avoid excessively updating the position while scrolling. - * jQuery(window).on('scroll', _.throttle(updatePosition, 100)); - * - * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes. - * var throttled = _.throttle(renewToken, 300000, { 'trailing': false }); - * jQuery(element).on('click', throttled); - * - * // Cancel the trailing throttled invocation. - * jQuery(window).on('popstate', throttled.cancel); - */ - function throttle(func, wait, options) { - var leading = true, - trailing = true; - - if (typeof func != 'function') { - throw new TypeError(FUNC_ERROR_TEXT); - } - if (isObject(options)) { - leading = 'leading' in options ? !!options.leading : leading; - trailing = 'trailing' in options ? !!options.trailing : trailing; - } - return debounce(func, wait, { - 'leading': leading, - 'maxWait': wait, - 'trailing': trailing - }); - } - - /** - * Creates a function that accepts up to one argument, ignoring any - * additional arguments. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Function - * @param {Function} func The function to cap arguments for. - * @returns {Function} Returns the new capped function. - * @example - * - * _.map(['6', '8', '10'], _.unary(parseInt)); - * // => [6, 8, 10] - */ - function unary(func) { - return ary(func, 1); - } - - /** - * Creates a function that provides `value` to `wrapper` as its first - * argument. Any additional arguments provided to the function are appended - * to those provided to the `wrapper`. The wrapper is invoked with the `this` - * binding of the created function. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Function - * @param {*} value The value to wrap. - * @param {Function} [wrapper=identity] The wrapper function. - * @returns {Function} Returns the new function. - * @example - * - * var p = _.wrap(_.escape, function(func, text) { - * return '

' + func(text) + '

'; - * }); - * - * p('fred, barney, & pebbles'); - * // => '

fred, barney, & pebbles

' - */ - function wrap(value, wrapper) { - return partial(castFunction(wrapper), value); - } - - /*------------------------------------------------------------------------*/ - - /** - * Casts `value` as an array if it's not one. - * - * @static - * @memberOf _ - * @since 4.4.0 - * @category Lang - * @param {*} value The value to inspect. - * @returns {Array} Returns the cast array. - * @example - * - * _.castArray(1); - * // => [1] - * - * _.castArray({ 'a': 1 }); - * // => [{ 'a': 1 }] - * - * _.castArray('abc'); - * // => ['abc'] - * - * _.castArray(null); - * // => [null] - * - * _.castArray(undefined); - * // => [undefined] - * - * _.castArray(); - * // => [] - * - * var array = [1, 2, 3]; - * console.log(_.castArray(array) === array); - * // => true - */ - function castArray() { - if (!arguments.length) { - return []; - } - var value = arguments[0]; - return isArray(value) ? value : [value]; - } - - /** - * Creates a shallow clone of `value`. - * - * **Note:** This method is loosely based on the - * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm) - * and supports cloning arrays, array buffers, booleans, date objects, maps, - * numbers, `Object` objects, regexes, sets, strings, symbols, and typed - * arrays. The own enumerable properties of `arguments` objects are cloned - * as plain objects. An empty object is returned for uncloneable values such - * as error objects, functions, DOM nodes, and WeakMaps. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to clone. - * @returns {*} Returns the cloned value. - * @see _.cloneDeep - * @example - * - * var objects = [{ 'a': 1 }, { 'b': 2 }]; - * - * var shallow = _.clone(objects); - * console.log(shallow[0] === objects[0]); - * // => true - */ - function clone(value) { - return baseClone(value, CLONE_SYMBOLS_FLAG); - } - - /** - * This method is like `_.clone` except that it accepts `customizer` which - * is invoked to produce the cloned value. If `customizer` returns `undefined`, - * cloning is handled by the method instead. The `customizer` is invoked with - * up to four arguments; (value [, index|key, object, stack]). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to clone. - * @param {Function} [customizer] The function to customize cloning. - * @returns {*} Returns the cloned value. - * @see _.cloneDeepWith - * @example - * - * function customizer(value) { - * if (_.isElement(value)) { - * return value.cloneNode(false); - * } - * } - * - * var el = _.cloneWith(document.body, customizer); - * - * console.log(el === document.body); - * // => false - * console.log(el.nodeName); - * // => 'BODY' - * console.log(el.childNodes.length); - * // => 0 - */ - function cloneWith(value, customizer) { - customizer = typeof customizer == 'function' ? customizer : undefined; - return baseClone(value, CLONE_SYMBOLS_FLAG, customizer); - } - - /** - * This method is like `_.clone` except that it recursively clones `value`. - * - * @static - * @memberOf _ - * @since 1.0.0 - * @category Lang - * @param {*} value The value to recursively clone. - * @returns {*} Returns the deep cloned value. - * @see _.clone - * @example - * - * var objects = [{ 'a': 1 }, { 'b': 2 }]; - * - * var deep = _.cloneDeep(objects); - * console.log(deep[0] === objects[0]); - * // => false - */ - function cloneDeep(value) { - return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG); - } - - /** - * This method is like `_.cloneWith` except that it recursively clones `value`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to recursively clone. - * @param {Function} [customizer] The function to customize cloning. - * @returns {*} Returns the deep cloned value. - * @see _.cloneWith - * @example - * - * function customizer(value) { - * if (_.isElement(value)) { - * return value.cloneNode(true); - * } - * } - * - * var el = _.cloneDeepWith(document.body, customizer); - * - * console.log(el === document.body); - * // => false - * console.log(el.nodeName); - * // => 'BODY' - * console.log(el.childNodes.length); - * // => 20 - */ - function cloneDeepWith(value, customizer) { - customizer = typeof customizer == 'function' ? customizer : undefined; - return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer); - } - - /** - * Checks if `object` conforms to `source` by invoking the predicate - * properties of `source` with the corresponding property values of `object`. - * - * **Note:** This method is equivalent to `_.conforms` when `source` is - * partially applied. - * - * @static - * @memberOf _ - * @since 4.14.0 - * @category Lang - * @param {Object} object The object to inspect. - * @param {Object} source The object of property predicates to conform to. - * @returns {boolean} Returns `true` if `object` conforms, else `false`. - * @example - * - * var object = { 'a': 1, 'b': 2 }; - * - * _.conformsTo(object, { 'b': function(n) { return n > 1; } }); - * // => true - * - * _.conformsTo(object, { 'b': function(n) { return n > 2; } }); - * // => false - */ - function conformsTo(object, source) { - return source == null || baseConformsTo(object, source, keys(source)); - } - - /** - * Performs a - * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero) - * comparison between two values to determine if they are equivalent. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. - * @example - * - * var object = { 'a': 1 }; - * var other = { 'a': 1 }; - * - * _.eq(object, object); - * // => true - * - * _.eq(object, other); - * // => false - * - * _.eq('a', 'a'); - * // => true - * - * _.eq('a', Object('a')); - * // => false - * - * _.eq(NaN, NaN); - * // => true - */ - function eq(value, other) { - return value === other || (value !== value && other !== other); - } - - /** - * Checks if `value` is greater than `other`. - * - * @static - * @memberOf _ - * @since 3.9.0 - * @category Lang - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if `value` is greater than `other`, - * else `false`. - * @see _.lt - * @example - * - * _.gt(3, 1); - * // => true - * - * _.gt(3, 3); - * // => false - * - * _.gt(1, 3); - * // => false - */ - var gt = createRelationalOperation(baseGt); - - /** - * Checks if `value` is greater than or equal to `other`. - * - * @static - * @memberOf _ - * @since 3.9.0 - * @category Lang - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if `value` is greater than or equal to - * `other`, else `false`. - * @see _.lte - * @example - * - * _.gte(3, 1); - * // => true - * - * _.gte(3, 3); - * // => true - * - * _.gte(1, 3); - * // => false - */ - var gte = createRelationalOperation(function(value, other) { - return value >= other; - }); - - /** - * Checks if `value` is likely an `arguments` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an `arguments` object, - * else `false`. - * @example - * - * _.isArguments(function() { return arguments; }()); - * // => true - * - * _.isArguments([1, 2, 3]); - * // => false - */ - var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) { - return isObjectLike(value) && hasOwnProperty.call(value, 'callee') && - !propertyIsEnumerable.call(value, 'callee'); - }; - - /** - * Checks if `value` is classified as an `Array` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an array, else `false`. - * @example - * - * _.isArray([1, 2, 3]); - * // => true - * - * _.isArray(document.body.children); - * // => false - * - * _.isArray('abc'); - * // => false - * - * _.isArray(_.noop); - * // => false - */ - var isArray = Array.isArray; - - /** - * Checks if `value` is classified as an `ArrayBuffer` object. - * - * @static - * @memberOf _ - * @since 4.3.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`. - * @example - * - * _.isArrayBuffer(new ArrayBuffer(2)); - * // => true - * - * _.isArrayBuffer(new Array(2)); - * // => false - */ - var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer; - - /** - * Checks if `value` is array-like. A value is considered array-like if it's - * not a function and has a `value.length` that's an integer greater than or - * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is array-like, else `false`. - * @example - * - * _.isArrayLike([1, 2, 3]); - * // => true - * - * _.isArrayLike(document.body.children); - * // => true - * - * _.isArrayLike('abc'); - * // => true - * - * _.isArrayLike(_.noop); - * // => false - */ - function isArrayLike(value) { - return value != null && isLength(value.length) && !isFunction(value); - } - - /** - * This method is like `_.isArrayLike` except that it also checks if `value` - * is an object. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an array-like object, - * else `false`. - * @example - * - * _.isArrayLikeObject([1, 2, 3]); - * // => true - * - * _.isArrayLikeObject(document.body.children); - * // => true - * - * _.isArrayLikeObject('abc'); - * // => false - * - * _.isArrayLikeObject(_.noop); - * // => false - */ - function isArrayLikeObject(value) { - return isObjectLike(value) && isArrayLike(value); - } - - /** - * Checks if `value` is classified as a boolean primitive or object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a boolean, else `false`. - * @example - * - * _.isBoolean(false); - * // => true - * - * _.isBoolean(null); - * // => false - */ - function isBoolean(value) { - return value === true || value === false || - (isObjectLike(value) && baseGetTag(value) == boolTag); - } - - /** - * Checks if `value` is a buffer. - * - * @static - * @memberOf _ - * @since 4.3.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a buffer, else `false`. - * @example - * - * _.isBuffer(new Buffer(2)); - * // => true - * - * _.isBuffer(new Uint8Array(2)); - * // => false - */ - var isBuffer = nativeIsBuffer || stubFalse; - - /** - * Checks if `value` is classified as a `Date` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a date object, else `false`. - * @example - * - * _.isDate(new Date); - * // => true - * - * _.isDate('Mon April 23 2012'); - * // => false - */ - var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate; - - /** - * Checks if `value` is likely a DOM element. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`. - * @example - * - * _.isElement(document.body); - * // => true - * - * _.isElement(''); - * // => false - */ - function isElement(value) { - return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value); - } - - /** - * Checks if `value` is an empty object, collection, map, or set. - * - * Objects are considered empty if they have no own enumerable string keyed - * properties. - * - * Array-like values such as `arguments` objects, arrays, buffers, strings, or - * jQuery-like collections are considered empty if they have a `length` of `0`. - * Similarly, maps and sets are considered empty if they have a `size` of `0`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is empty, else `false`. - * @example - * - * _.isEmpty(null); - * // => true - * - * _.isEmpty(true); - * // => true - * - * _.isEmpty(1); - * // => true - * - * _.isEmpty([1, 2, 3]); - * // => false - * - * _.isEmpty({ 'a': 1 }); - * // => false - */ - function isEmpty(value) { - if (value == null) { - return true; - } - if (isArrayLike(value) && - (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' || - isBuffer(value) || isTypedArray(value) || isArguments(value))) { - return !value.length; - } - var tag = getTag(value); - if (tag == mapTag || tag == setTag) { - return !value.size; - } - if (isPrototype(value)) { - return !baseKeys(value).length; - } - for (var key in value) { - if (hasOwnProperty.call(value, key)) { - return false; - } - } - return true; - } - - /** - * Performs a deep comparison between two values to determine if they are - * equivalent. - * - * **Note:** This method supports comparing arrays, array buffers, booleans, - * date objects, error objects, maps, numbers, `Object` objects, regexes, - * sets, strings, symbols, and typed arrays. `Object` objects are compared - * by their own, not inherited, enumerable properties. Functions and DOM - * nodes are compared by strict equality, i.e. `===`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. - * @example - * - * var object = { 'a': 1 }; - * var other = { 'a': 1 }; - * - * _.isEqual(object, other); - * // => true - * - * object === other; - * // => false - */ - function isEqual(value, other) { - return baseIsEqual(value, other); - } - - /** - * This method is like `_.isEqual` except that it accepts `customizer` which - * is invoked to compare values. If `customizer` returns `undefined`, comparisons - * are handled by the method instead. The `customizer` is invoked with up to - * six arguments: (objValue, othValue [, index|key, object, other, stack]). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @param {Function} [customizer] The function to customize comparisons. - * @returns {boolean} Returns `true` if the values are equivalent, else `false`. - * @example - * - * function isGreeting(value) { - * return /^h(?:i|ello)$/.test(value); - * } - * - * function customizer(objValue, othValue) { - * if (isGreeting(objValue) && isGreeting(othValue)) { - * return true; - * } - * } - * - * var array = ['hello', 'goodbye']; - * var other = ['hi', 'goodbye']; - * - * _.isEqualWith(array, other, customizer); - * // => true - */ - function isEqualWith(value, other, customizer) { - customizer = typeof customizer == 'function' ? customizer : undefined; - var result = customizer ? customizer(value, other) : undefined; - return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result; - } - - /** - * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`, - * `SyntaxError`, `TypeError`, or `URIError` object. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an error object, else `false`. - * @example - * - * _.isError(new Error); - * // => true - * - * _.isError(Error); - * // => false - */ - function isError(value) { - if (!isObjectLike(value)) { - return false; - } - var tag = baseGetTag(value); - return tag == errorTag || tag == domExcTag || - (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value)); - } - - /** - * Checks if `value` is a finite primitive number. - * - * **Note:** This method is based on - * [`Number.isFinite`](https://mdn.io/Number/isFinite). - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a finite number, else `false`. - * @example - * - * _.isFinite(3); - * // => true - * - * _.isFinite(Number.MIN_VALUE); - * // => true - * - * _.isFinite(Infinity); - * // => false - * - * _.isFinite('3'); - * // => false - */ - function isFinite(value) { - return typeof value == 'number' && nativeIsFinite(value); - } - - /** - * Checks if `value` is classified as a `Function` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a function, else `false`. - * @example - * - * _.isFunction(_); - * // => true - * - * _.isFunction(/abc/); - * // => false - */ - function isFunction(value) { - if (!isObject(value)) { - return false; - } - // The use of `Object#toString` avoids issues with the `typeof` operator - // in Safari 9 which returns 'object' for typed arrays and other constructors. - var tag = baseGetTag(value); - return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag; - } - - /** - * Checks if `value` is an integer. - * - * **Note:** This method is based on - * [`Number.isInteger`](https://mdn.io/Number/isInteger). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an integer, else `false`. - * @example - * - * _.isInteger(3); - * // => true - * - * _.isInteger(Number.MIN_VALUE); - * // => false - * - * _.isInteger(Infinity); - * // => false - * - * _.isInteger('3'); - * // => false - */ - function isInteger(value) { - return typeof value == 'number' && value == toInteger(value); - } - - /** - * Checks if `value` is a valid array-like length. - * - * **Note:** This method is loosely based on - * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a valid length, else `false`. - * @example - * - * _.isLength(3); - * // => true - * - * _.isLength(Number.MIN_VALUE); - * // => false - * - * _.isLength(Infinity); - * // => false - * - * _.isLength('3'); - * // => false - */ - function isLength(value) { - return typeof value == 'number' && - value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER; - } - - /** - * Checks if `value` is the - * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) - * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is an object, else `false`. - * @example - * - * _.isObject({}); - * // => true - * - * _.isObject([1, 2, 3]); - * // => true - * - * _.isObject(_.noop); - * // => true - * - * _.isObject(null); - * // => false - */ - function isObject(value) { - var type = typeof value; - return value != null && (type == 'object' || type == 'function'); - } - - /** - * Checks if `value` is object-like. A value is object-like if it's not `null` - * and has a `typeof` result of "object". - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is object-like, else `false`. - * @example - * - * _.isObjectLike({}); - * // => true - * - * _.isObjectLike([1, 2, 3]); - * // => true - * - * _.isObjectLike(_.noop); - * // => false - * - * _.isObjectLike(null); - * // => false - */ - function isObjectLike(value) { - return value != null && typeof value == 'object'; - } - - /** - * Checks if `value` is classified as a `Map` object. - * - * @static - * @memberOf _ - * @since 4.3.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a map, else `false`. - * @example - * - * _.isMap(new Map); - * // => true - * - * _.isMap(new WeakMap); - * // => false - */ - var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap; - - /** - * Performs a partial deep comparison between `object` and `source` to - * determine if `object` contains equivalent property values. - * - * **Note:** This method is equivalent to `_.matches` when `source` is - * partially applied. - * - * Partial comparisons will match empty array and empty object `source` - * values against any array or object value, respectively. See `_.isEqual` - * for a list of supported value comparisons. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Lang - * @param {Object} object The object to inspect. - * @param {Object} source The object of property values to match. - * @returns {boolean} Returns `true` if `object` is a match, else `false`. - * @example - * - * var object = { 'a': 1, 'b': 2 }; - * - * _.isMatch(object, { 'b': 2 }); - * // => true - * - * _.isMatch(object, { 'b': 1 }); - * // => false - */ - function isMatch(object, source) { - return object === source || baseIsMatch(object, source, getMatchData(source)); - } - - /** - * This method is like `_.isMatch` except that it accepts `customizer` which - * is invoked to compare values. If `customizer` returns `undefined`, comparisons - * are handled by the method instead. The `customizer` is invoked with five - * arguments: (objValue, srcValue, index|key, object, source). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {Object} object The object to inspect. - * @param {Object} source The object of property values to match. - * @param {Function} [customizer] The function to customize comparisons. - * @returns {boolean} Returns `true` if `object` is a match, else `false`. - * @example - * - * function isGreeting(value) { - * return /^h(?:i|ello)$/.test(value); - * } - * - * function customizer(objValue, srcValue) { - * if (isGreeting(objValue) && isGreeting(srcValue)) { - * return true; - * } - * } - * - * var object = { 'greeting': 'hello' }; - * var source = { 'greeting': 'hi' }; - * - * _.isMatchWith(object, source, customizer); - * // => true - */ - function isMatchWith(object, source, customizer) { - customizer = typeof customizer == 'function' ? customizer : undefined; - return baseIsMatch(object, source, getMatchData(source), customizer); - } - - /** - * Checks if `value` is `NaN`. - * - * **Note:** This method is based on - * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as - * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for - * `undefined` and other non-number values. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`. - * @example - * - * _.isNaN(NaN); - * // => true - * - * _.isNaN(new Number(NaN)); - * // => true - * - * isNaN(undefined); - * // => true - * - * _.isNaN(undefined); - * // => false - */ - function isNaN(value) { - // An `NaN` primitive is the only value that is not equal to itself. - // Perform the `toStringTag` check first to avoid errors with some - // ActiveX objects in IE. - return isNumber(value) && value != +value; - } - - /** - * Checks if `value` is a pristine native function. - * - * **Note:** This method can't reliably detect native functions in the presence - * of the core-js package because core-js circumvents this kind of detection. - * Despite multiple requests, the core-js maintainer has made it clear: any - * attempt to fix the detection will be obstructed. As a result, we're left - * with little choice but to throw an error. Unfortunately, this also affects - * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill), - * which rely on core-js. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a native function, - * else `false`. - * @example - * - * _.isNative(Array.prototype.push); - * // => true - * - * _.isNative(_); - * // => false - */ - function isNative(value) { - if (isMaskable(value)) { - throw new Error(CORE_ERROR_TEXT); - } - return baseIsNative(value); - } - - /** - * Checks if `value` is `null`. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is `null`, else `false`. - * @example - * - * _.isNull(null); - * // => true - * - * _.isNull(void 0); - * // => false - */ - function isNull(value) { - return value === null; - } - - /** - * Checks if `value` is `null` or `undefined`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is nullish, else `false`. - * @example - * - * _.isNil(null); - * // => true - * - * _.isNil(void 0); - * // => true - * - * _.isNil(NaN); - * // => false - */ - function isNil(value) { - return value == null; - } - - /** - * Checks if `value` is classified as a `Number` primitive or object. - * - * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are - * classified as numbers, use the `_.isFinite` method. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a number, else `false`. - * @example - * - * _.isNumber(3); - * // => true - * - * _.isNumber(Number.MIN_VALUE); - * // => true - * - * _.isNumber(Infinity); - * // => true - * - * _.isNumber('3'); - * // => false - */ - function isNumber(value) { - return typeof value == 'number' || - (isObjectLike(value) && baseGetTag(value) == numberTag); - } - - /** - * Checks if `value` is a plain object, that is, an object created by the - * `Object` constructor or one with a `[[Prototype]]` of `null`. - * - * @static - * @memberOf _ - * @since 0.8.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a plain object, else `false`. - * @example - * - * function Foo() { - * this.a = 1; - * } - * - * _.isPlainObject(new Foo); - * // => false - * - * _.isPlainObject([1, 2, 3]); - * // => false - * - * _.isPlainObject({ 'x': 0, 'y': 0 }); - * // => true - * - * _.isPlainObject(Object.create(null)); - * // => true - */ - function isPlainObject(value) { - if (!isObjectLike(value) || baseGetTag(value) != objectTag) { - return false; - } - var proto = getPrototype(value); - if (proto === null) { - return true; - } - var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor; - return typeof Ctor == 'function' && Ctor instanceof Ctor && - funcToString.call(Ctor) == objectCtorString; - } - - /** - * Checks if `value` is classified as a `RegExp` object. - * - * @static - * @memberOf _ - * @since 0.1.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a regexp, else `false`. - * @example - * - * _.isRegExp(/abc/); - * // => true - * - * _.isRegExp('/abc/'); - * // => false - */ - var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp; - - /** - * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754 - * double precision number which isn't the result of a rounded unsafe integer. - * - * **Note:** This method is based on - * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`. - * @example - * - * _.isSafeInteger(3); - * // => true - * - * _.isSafeInteger(Number.MIN_VALUE); - * // => false - * - * _.isSafeInteger(Infinity); - * // => false - * - * _.isSafeInteger('3'); - * // => false - */ - function isSafeInteger(value) { - return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER; - } - - /** - * Checks if `value` is classified as a `Set` object. - * - * @static - * @memberOf _ - * @since 4.3.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a set, else `false`. - * @example - * - * _.isSet(new Set); - * // => true - * - * _.isSet(new WeakSet); - * // => false - */ - var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet; - - /** - * Checks if `value` is classified as a `String` primitive or object. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a string, else `false`. - * @example - * - * _.isString('abc'); - * // => true - * - * _.isString(1); - * // => false - */ - function isString(value) { - return typeof value == 'string' || - (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag); - } - - /** - * Checks if `value` is classified as a `Symbol` primitive or object. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. - * @example - * - * _.isSymbol(Symbol.iterator); - * // => true - * - * _.isSymbol('abc'); - * // => false - */ - function isSymbol(value) { - return typeof value == 'symbol' || - (isObjectLike(value) && baseGetTag(value) == symbolTag); - } - - /** - * Checks if `value` is classified as a typed array. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a typed array, else `false`. - * @example - * - * _.isTypedArray(new Uint8Array); - * // => true - * - * _.isTypedArray([]); - * // => false - */ - var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray; - - /** - * Checks if `value` is `undefined`. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`. - * @example - * - * _.isUndefined(void 0); - * // => true - * - * _.isUndefined(null); - * // => false - */ - function isUndefined(value) { - return value === undefined; - } - - /** - * Checks if `value` is classified as a `WeakMap` object. - * - * @static - * @memberOf _ - * @since 4.3.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a weak map, else `false`. - * @example - * - * _.isWeakMap(new WeakMap); - * // => true - * - * _.isWeakMap(new Map); - * // => false - */ - function isWeakMap(value) { - return isObjectLike(value) && getTag(value) == weakMapTag; - } - - /** - * Checks if `value` is classified as a `WeakSet` object. - * - * @static - * @memberOf _ - * @since 4.3.0 - * @category Lang - * @param {*} value The value to check. - * @returns {boolean} Returns `true` if `value` is a weak set, else `false`. - * @example - * - * _.isWeakSet(new WeakSet); - * // => true - * - * _.isWeakSet(new Set); - * // => false - */ - function isWeakSet(value) { - return isObjectLike(value) && baseGetTag(value) == weakSetTag; - } - - /** - * Checks if `value` is less than `other`. - * - * @static - * @memberOf _ - * @since 3.9.0 - * @category Lang - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if `value` is less than `other`, - * else `false`. - * @see _.gt - * @example - * - * _.lt(1, 3); - * // => true - * - * _.lt(3, 3); - * // => false - * - * _.lt(3, 1); - * // => false - */ - var lt = createRelationalOperation(baseLt); - - /** - * Checks if `value` is less than or equal to `other`. - * - * @static - * @memberOf _ - * @since 3.9.0 - * @category Lang - * @param {*} value The value to compare. - * @param {*} other The other value to compare. - * @returns {boolean} Returns `true` if `value` is less than or equal to - * `other`, else `false`. - * @see _.gte - * @example - * - * _.lte(1, 3); - * // => true - * - * _.lte(3, 3); - * // => true - * - * _.lte(3, 1); - * // => false - */ - var lte = createRelationalOperation(function(value, other) { - return value <= other; - }); - - /** - * Converts `value` to an array. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Lang - * @param {*} value The value to convert. - * @returns {Array} Returns the converted array. - * @example - * - * _.toArray({ 'a': 1, 'b': 2 }); - * // => [1, 2] - * - * _.toArray('abc'); - * // => ['a', 'b', 'c'] - * - * _.toArray(1); - * // => [] - * - * _.toArray(null); - * // => [] - */ - function toArray(value) { - if (!value) { - return []; - } - if (isArrayLike(value)) { - return isString(value) ? stringToArray(value) : copyArray(value); - } - if (symIterator && value[symIterator]) { - return iteratorToArray(value[symIterator]()); - } - var tag = getTag(value), - func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values); - - return func(value); - } - - /** - * Converts `value` to a finite number. - * - * @static - * @memberOf _ - * @since 4.12.0 - * @category Lang - * @param {*} value The value to convert. - * @returns {number} Returns the converted number. - * @example - * - * _.toFinite(3.2); - * // => 3.2 - * - * _.toFinite(Number.MIN_VALUE); - * // => 5e-324 - * - * _.toFinite(Infinity); - * // => 1.7976931348623157e+308 - * - * _.toFinite('3.2'); - * // => 3.2 - */ - function toFinite(value) { - if (!value) { - return value === 0 ? value : 0; - } - value = toNumber(value); - if (value === INFINITY || value === -INFINITY) { - var sign = (value < 0 ? -1 : 1); - return sign * MAX_INTEGER; - } - return value === value ? value : 0; - } - - /** - * Converts `value` to an integer. - * - * **Note:** This method is loosely based on - * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to convert. - * @returns {number} Returns the converted integer. - * @example - * - * _.toInteger(3.2); - * // => 3 - * - * _.toInteger(Number.MIN_VALUE); - * // => 0 - * - * _.toInteger(Infinity); - * // => 1.7976931348623157e+308 - * - * _.toInteger('3.2'); - * // => 3 - */ - function toInteger(value) { - var result = toFinite(value), - remainder = result % 1; - - return result === result ? (remainder ? result - remainder : result) : 0; - } - - /** - * Converts `value` to an integer suitable for use as the length of an - * array-like object. - * - * **Note:** This method is based on - * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to convert. - * @returns {number} Returns the converted integer. - * @example - * - * _.toLength(3.2); - * // => 3 - * - * _.toLength(Number.MIN_VALUE); - * // => 0 - * - * _.toLength(Infinity); - * // => 4294967295 - * - * _.toLength('3.2'); - * // => 3 - */ - function toLength(value) { - return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0; - } - - /** - * Converts `value` to a number. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to process. - * @returns {number} Returns the number. - * @example - * - * _.toNumber(3.2); - * // => 3.2 - * - * _.toNumber(Number.MIN_VALUE); - * // => 5e-324 - * - * _.toNumber(Infinity); - * // => Infinity - * - * _.toNumber('3.2'); - * // => 3.2 - */ - function toNumber(value) { - if (typeof value == 'number') { - return value; - } - if (isSymbol(value)) { - return NAN; - } - if (isObject(value)) { - var other = typeof value.valueOf == 'function' ? value.valueOf() : value; - value = isObject(other) ? (other + '') : other; - } - if (typeof value != 'string') { - return value === 0 ? value : +value; - } - value = value.replace(reTrim, ''); - var isBinary = reIsBinary.test(value); - return (isBinary || reIsOctal.test(value)) - ? freeParseInt(value.slice(2), isBinary ? 2 : 8) - : (reIsBadHex.test(value) ? NAN : +value); - } - - /** - * Converts `value` to a plain object flattening inherited enumerable string - * keyed properties of `value` to own properties of the plain object. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Lang - * @param {*} value The value to convert. - * @returns {Object} Returns the converted plain object. - * @example - * - * function Foo() { - * this.b = 2; - * } - * - * Foo.prototype.c = 3; - * - * _.assign({ 'a': 1 }, new Foo); - * // => { 'a': 1, 'b': 2 } - * - * _.assign({ 'a': 1 }, _.toPlainObject(new Foo)); - * // => { 'a': 1, 'b': 2, 'c': 3 } - */ - function toPlainObject(value) { - return copyObject(value, keysIn(value)); - } - - /** - * Converts `value` to a safe integer. A safe integer can be compared and - * represented correctly. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to convert. - * @returns {number} Returns the converted integer. - * @example - * - * _.toSafeInteger(3.2); - * // => 3 - * - * _.toSafeInteger(Number.MIN_VALUE); - * // => 0 - * - * _.toSafeInteger(Infinity); - * // => 9007199254740991 - * - * _.toSafeInteger('3.2'); - * // => 3 - */ - function toSafeInteger(value) { - return value - ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER) - : (value === 0 ? value : 0); - } - - /** - * Converts `value` to a string. An empty string is returned for `null` - * and `undefined` values. The sign of `-0` is preserved. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Lang - * @param {*} value The value to convert. - * @returns {string} Returns the converted string. - * @example - * - * _.toString(null); - * // => '' - * - * _.toString(-0); - * // => '-0' - * - * _.toString([1, 2, 3]); - * // => '1,2,3' - */ - function toString(value) { - return value == null ? '' : baseToString(value); - } - - /*------------------------------------------------------------------------*/ - - /** - * Assigns own enumerable string keyed properties of source objects to the - * destination object. Source objects are applied from left to right. - * Subsequent sources overwrite property assignments of previous sources. - * - * **Note:** This method mutates `object` and is loosely based on - * [`Object.assign`](https://mdn.io/Object/assign). - * - * @static - * @memberOf _ - * @since 0.10.0 - * @category Object - * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. - * @returns {Object} Returns `object`. - * @see _.assignIn - * @example - * - * function Foo() { - * this.a = 1; - * } - * - * function Bar() { - * this.c = 3; - * } - * - * Foo.prototype.b = 2; - * Bar.prototype.d = 4; - * - * _.assign({ 'a': 0 }, new Foo, new Bar); - * // => { 'a': 1, 'c': 3 } - */ - var assign = createAssigner(function(object, source) { - if (isPrototype(source) || isArrayLike(source)) { - copyObject(source, keys(source), object); - return; - } - for (var key in source) { - if (hasOwnProperty.call(source, key)) { - assignValue(object, key, source[key]); - } - } - }); - - /** - * This method is like `_.assign` except that it iterates over own and - * inherited source properties. - * - * **Note:** This method mutates `object`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @alias extend - * @category Object - * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. - * @returns {Object} Returns `object`. - * @see _.assign - * @example - * - * function Foo() { - * this.a = 1; - * } - * - * function Bar() { - * this.c = 3; - * } - * - * Foo.prototype.b = 2; - * Bar.prototype.d = 4; - * - * _.assignIn({ 'a': 0 }, new Foo, new Bar); - * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 } - */ - var assignIn = createAssigner(function(object, source) { - copyObject(source, keysIn(source), object); - }); - - /** - * This method is like `_.assignIn` except that it accepts `customizer` - * which is invoked to produce the assigned values. If `customizer` returns - * `undefined`, assignment is handled by the method instead. The `customizer` - * is invoked with five arguments: (objValue, srcValue, key, object, source). - * - * **Note:** This method mutates `object`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @alias extendWith - * @category Object - * @param {Object} object The destination object. - * @param {...Object} sources The source objects. - * @param {Function} [customizer] The function to customize assigned values. - * @returns {Object} Returns `object`. - * @see _.assignWith - * @example - * - * function customizer(objValue, srcValue) { - * return _.isUndefined(objValue) ? srcValue : objValue; - * } - * - * var defaults = _.partialRight(_.assignInWith, customizer); - * - * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); - * // => { 'a': 1, 'b': 2 } - */ - var assignInWith = createAssigner(function(object, source, srcIndex, customizer) { - copyObject(source, keysIn(source), object, customizer); - }); - - /** - * This method is like `_.assign` except that it accepts `customizer` - * which is invoked to produce the assigned values. If `customizer` returns - * `undefined`, assignment is handled by the method instead. The `customizer` - * is invoked with five arguments: (objValue, srcValue, key, object, source). - * - * **Note:** This method mutates `object`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Object - * @param {Object} object The destination object. - * @param {...Object} sources The source objects. - * @param {Function} [customizer] The function to customize assigned values. - * @returns {Object} Returns `object`. - * @see _.assignInWith - * @example - * - * function customizer(objValue, srcValue) { - * return _.isUndefined(objValue) ? srcValue : objValue; - * } - * - * var defaults = _.partialRight(_.assignWith, customizer); - * - * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); - * // => { 'a': 1, 'b': 2 } - */ - var assignWith = createAssigner(function(object, source, srcIndex, customizer) { - copyObject(source, keys(source), object, customizer); - }); - - /** - * Creates an array of values corresponding to `paths` of `object`. - * - * @static - * @memberOf _ - * @since 1.0.0 - * @category Object - * @param {Object} object The object to iterate over. - * @param {...(string|string[])} [paths] The property paths to pick. - * @returns {Array} Returns the picked values. - * @example - * - * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] }; - * - * _.at(object, ['a[0].b.c', 'a[1]']); - * // => [3, 4] - */ - var at = flatRest(baseAt); - - /** - * Creates an object that inherits from the `prototype` object. If a - * `properties` object is given, its own enumerable string keyed properties - * are assigned to the created object. - * - * @static - * @memberOf _ - * @since 2.3.0 - * @category Object - * @param {Object} prototype The object to inherit from. - * @param {Object} [properties] The properties to assign to the object. - * @returns {Object} Returns the new object. - * @example - * - * function Shape() { - * this.x = 0; - * this.y = 0; - * } - * - * function Circle() { - * Shape.call(this); - * } - * - * Circle.prototype = _.create(Shape.prototype, { - * 'constructor': Circle - * }); - * - * var circle = new Circle; - * circle instanceof Circle; - * // => true - * - * circle instanceof Shape; - * // => true - */ - function create(prototype, properties) { - var result = baseCreate(prototype); - return properties == null ? result : baseAssign(result, properties); - } - - /** - * Assigns own and inherited enumerable string keyed properties of source - * objects to the destination object for all destination properties that - * resolve to `undefined`. Source objects are applied from left to right. - * Once a property is set, additional values of the same property are ignored. - * - * **Note:** This method mutates `object`. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Object - * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. - * @returns {Object} Returns `object`. - * @see _.defaultsDeep - * @example - * - * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 }); - * // => { 'a': 1, 'b': 2 } - */ - var defaults = baseRest(function(object, sources) { - object = Object(object); - - var index = -1; - var length = sources.length; - var guard = length > 2 ? sources[2] : undefined; - - if (guard && isIterateeCall(sources[0], sources[1], guard)) { - length = 1; - } - - while (++index < length) { - var source = sources[index]; - var props = keysIn(source); - var propsIndex = -1; - var propsLength = props.length; - - while (++propsIndex < propsLength) { - var key = props[propsIndex]; - var value = object[key]; - - if (value === undefined || - (eq(value, objectProto[key]) && !hasOwnProperty.call(object, key))) { - object[key] = source[key]; - } - } - } - - return object; - }); - - /** - * This method is like `_.defaults` except that it recursively assigns - * default properties. - * - * **Note:** This method mutates `object`. - * - * @static - * @memberOf _ - * @since 3.10.0 - * @category Object - * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. - * @returns {Object} Returns `object`. - * @see _.defaults - * @example - * - * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } }); - * // => { 'a': { 'b': 2, 'c': 3 } } - */ - var defaultsDeep = baseRest(function(args) { - args.push(undefined, customDefaultsMerge); - return apply(mergeWith, undefined, args); - }); - - /** - * This method is like `_.find` except that it returns the key of the first - * element `predicate` returns truthy for instead of the element itself. - * - * @static - * @memberOf _ - * @since 1.1.0 - * @category Object - * @param {Object} object The object to inspect. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @returns {string|undefined} Returns the key of the matched element, - * else `undefined`. - * @example - * - * var users = { - * 'barney': { 'age': 36, 'active': true }, - * 'fred': { 'age': 40, 'active': false }, - * 'pebbles': { 'age': 1, 'active': true } - * }; - * - * _.findKey(users, function(o) { return o.age < 40; }); - * // => 'barney' (iteration order is not guaranteed) - * - * // The `_.matches` iteratee shorthand. - * _.findKey(users, { 'age': 1, 'active': true }); - * // => 'pebbles' - * - * // The `_.matchesProperty` iteratee shorthand. - * _.findKey(users, ['active', false]); - * // => 'fred' - * - * // The `_.property` iteratee shorthand. - * _.findKey(users, 'active'); - * // => 'barney' - */ - function findKey(object, predicate) { - return baseFindKey(object, getIteratee(predicate, 3), baseForOwn); - } - - /** - * This method is like `_.findKey` except that it iterates over elements of - * a collection in the opposite order. - * - * @static - * @memberOf _ - * @since 2.0.0 - * @category Object - * @param {Object} object The object to inspect. - * @param {Function} [predicate=_.identity] The function invoked per iteration. - * @returns {string|undefined} Returns the key of the matched element, - * else `undefined`. - * @example - * - * var users = { - * 'barney': { 'age': 36, 'active': true }, - * 'fred': { 'age': 40, 'active': false }, - * 'pebbles': { 'age': 1, 'active': true } - * }; - * - * _.findLastKey(users, function(o) { return o.age < 40; }); - * // => returns 'pebbles' assuming `_.findKey` returns 'barney' - * - * // The `_.matches` iteratee shorthand. - * _.findLastKey(users, { 'age': 36, 'active': true }); - * // => 'barney' - * - * // The `_.matchesProperty` iteratee shorthand. - * _.findLastKey(users, ['active', false]); - * // => 'fred' - * - * // The `_.property` iteratee shorthand. - * _.findLastKey(users, 'active'); - * // => 'pebbles' - */ - function findLastKey(object, predicate) { - return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight); - } - - /** - * Iterates over own and inherited enumerable string keyed properties of an - * object and invokes `iteratee` for each property. The iteratee is invoked - * with three arguments: (value, key, object). Iteratee functions may exit - * iteration early by explicitly returning `false`. - * - * @static - * @memberOf _ - * @since 0.3.0 - * @category Object - * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @returns {Object} Returns `object`. - * @see _.forInRight - * @example - * - * function Foo() { - * this.a = 1; - * this.b = 2; - * } - * - * Foo.prototype.c = 3; - * - * _.forIn(new Foo, function(value, key) { - * console.log(key); - * }); - * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed). - */ - function forIn(object, iteratee) { - return object == null - ? object - : baseFor(object, getIteratee(iteratee, 3), keysIn); - } - - /** - * This method is like `_.forIn` except that it iterates over properties of - * `object` in the opposite order. - * - * @static - * @memberOf _ - * @since 2.0.0 - * @category Object - * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @returns {Object} Returns `object`. - * @see _.forIn - * @example - * - * function Foo() { - * this.a = 1; - * this.b = 2; - * } - * - * Foo.prototype.c = 3; - * - * _.forInRight(new Foo, function(value, key) { - * console.log(key); - * }); - * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'. - */ - function forInRight(object, iteratee) { - return object == null - ? object - : baseForRight(object, getIteratee(iteratee, 3), keysIn); - } - - /** - * Iterates over own enumerable string keyed properties of an object and - * invokes `iteratee` for each property. The iteratee is invoked with three - * arguments: (value, key, object). Iteratee functions may exit iteration - * early by explicitly returning `false`. - * - * @static - * @memberOf _ - * @since 0.3.0 - * @category Object - * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @returns {Object} Returns `object`. - * @see _.forOwnRight - * @example - * - * function Foo() { - * this.a = 1; - * this.b = 2; - * } - * - * Foo.prototype.c = 3; - * - * _.forOwn(new Foo, function(value, key) { - * console.log(key); - * }); - * // => Logs 'a' then 'b' (iteration order is not guaranteed). - */ - function forOwn(object, iteratee) { - return object && baseForOwn(object, getIteratee(iteratee, 3)); - } - - /** - * This method is like `_.forOwn` except that it iterates over properties of - * `object` in the opposite order. - * - * @static - * @memberOf _ - * @since 2.0.0 - * @category Object - * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @returns {Object} Returns `object`. - * @see _.forOwn - * @example - * - * function Foo() { - * this.a = 1; - * this.b = 2; - * } - * - * Foo.prototype.c = 3; - * - * _.forOwnRight(new Foo, function(value, key) { - * console.log(key); - * }); - * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'. - */ - function forOwnRight(object, iteratee) { - return object && baseForOwnRight(object, getIteratee(iteratee, 3)); - } - - /** - * Creates an array of function property names from own enumerable properties - * of `object`. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Object - * @param {Object} object The object to inspect. - * @returns {Array} Returns the function names. - * @see _.functionsIn - * @example - * - * function Foo() { - * this.a = _.constant('a'); - * this.b = _.constant('b'); - * } - * - * Foo.prototype.c = _.constant('c'); - * - * _.functions(new Foo); - * // => ['a', 'b'] - */ - function functions(object) { - return object == null ? [] : baseFunctions(object, keys(object)); - } - - /** - * Creates an array of function property names from own and inherited - * enumerable properties of `object`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Object - * @param {Object} object The object to inspect. - * @returns {Array} Returns the function names. - * @see _.functions - * @example - * - * function Foo() { - * this.a = _.constant('a'); - * this.b = _.constant('b'); - * } - * - * Foo.prototype.c = _.constant('c'); - * - * _.functionsIn(new Foo); - * // => ['a', 'b', 'c'] - */ - function functionsIn(object) { - return object == null ? [] : baseFunctions(object, keysIn(object)); - } - - /** - * Gets the value at `path` of `object`. If the resolved value is - * `undefined`, the `defaultValue` is returned in its place. - * - * @static - * @memberOf _ - * @since 3.7.0 - * @category Object - * @param {Object} object The object to query. - * @param {Array|string} path The path of the property to get. - * @param {*} [defaultValue] The value returned for `undefined` resolved values. - * @returns {*} Returns the resolved value. - * @example - * - * var object = { 'a': [{ 'b': { 'c': 3 } }] }; - * - * _.get(object, 'a[0].b.c'); - * // => 3 - * - * _.get(object, ['a', '0', 'b', 'c']); - * // => 3 - * - * _.get(object, 'a.b.c', 'default'); - * // => 'default' - */ - function get(object, path, defaultValue) { - var result = object == null ? undefined : baseGet(object, path); - return result === undefined ? defaultValue : result; - } - - /** - * Checks if `path` is a direct property of `object`. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Object - * @param {Object} object The object to query. - * @param {Array|string} path The path to check. - * @returns {boolean} Returns `true` if `path` exists, else `false`. - * @example - * - * var object = { 'a': { 'b': 2 } }; - * var other = _.create({ 'a': _.create({ 'b': 2 }) }); - * - * _.has(object, 'a'); - * // => true - * - * _.has(object, 'a.b'); - * // => true - * - * _.has(object, ['a', 'b']); - * // => true - * - * _.has(other, 'a'); - * // => false - */ - function has(object, path) { - return object != null && hasPath(object, path, baseHas); - } - - /** - * Checks if `path` is a direct or inherited property of `object`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Object - * @param {Object} object The object to query. - * @param {Array|string} path The path to check. - * @returns {boolean} Returns `true` if `path` exists, else `false`. - * @example - * - * var object = _.create({ 'a': _.create({ 'b': 2 }) }); - * - * _.hasIn(object, 'a'); - * // => true - * - * _.hasIn(object, 'a.b'); - * // => true - * - * _.hasIn(object, ['a', 'b']); - * // => true - * - * _.hasIn(object, 'b'); - * // => false - */ - function hasIn(object, path) { - return object != null && hasPath(object, path, baseHasIn); - } - - /** - * Creates an object composed of the inverted keys and values of `object`. - * If `object` contains duplicate values, subsequent values overwrite - * property assignments of previous values. - * - * @static - * @memberOf _ - * @since 0.7.0 - * @category Object - * @param {Object} object The object to invert. - * @returns {Object} Returns the new inverted object. - * @example - * - * var object = { 'a': 1, 'b': 2, 'c': 1 }; - * - * _.invert(object); - * // => { '1': 'c', '2': 'b' } - */ - var invert = createInverter(function(result, value, key) { - if (value != null && - typeof value.toString != 'function') { - value = nativeObjectToString.call(value); - } - - result[value] = key; - }, constant(identity)); - - /** - * This method is like `_.invert` except that the inverted object is generated - * from the results of running each element of `object` thru `iteratee`. The - * corresponding inverted value of each inverted key is an array of keys - * responsible for generating the inverted value. The iteratee is invoked - * with one argument: (value). - * - * @static - * @memberOf _ - * @since 4.1.0 - * @category Object - * @param {Object} object The object to invert. - * @param {Function} [iteratee=_.identity] The iteratee invoked per element. - * @returns {Object} Returns the new inverted object. - * @example - * - * var object = { 'a': 1, 'b': 2, 'c': 1 }; - * - * _.invertBy(object); - * // => { '1': ['a', 'c'], '2': ['b'] } - * - * _.invertBy(object, function(value) { - * return 'group' + value; - * }); - * // => { 'group1': ['a', 'c'], 'group2': ['b'] } - */ - var invertBy = createInverter(function(result, value, key) { - if (value != null && - typeof value.toString != 'function') { - value = nativeObjectToString.call(value); - } - - if (hasOwnProperty.call(result, value)) { - result[value].push(key); - } else { - result[value] = [key]; - } - }, getIteratee); - - /** - * Invokes the method at `path` of `object`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Object - * @param {Object} object The object to query. - * @param {Array|string} path The path of the method to invoke. - * @param {...*} [args] The arguments to invoke the method with. - * @returns {*} Returns the result of the invoked method. - * @example - * - * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] }; - * - * _.invoke(object, 'a[0].b.c.slice', 1, 3); - * // => [2, 3] - */ - var invoke = baseRest(baseInvoke); - - /** - * Creates an array of the own enumerable property names of `object`. - * - * **Note:** Non-object values are coerced to objects. See the - * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys) - * for more details. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Object - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - * @example - * - * function Foo() { - * this.a = 1; - * this.b = 2; - * } - * - * Foo.prototype.c = 3; - * - * _.keys(new Foo); - * // => ['a', 'b'] (iteration order is not guaranteed) - * - * _.keys('hi'); - * // => ['0', '1'] - */ - function keys(object) { - return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object); - } - - /** - * Creates an array of the own and inherited enumerable property names of `object`. - * - * **Note:** Non-object values are coerced to objects. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Object - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property names. - * @example - * - * function Foo() { - * this.a = 1; - * this.b = 2; - * } - * - * Foo.prototype.c = 3; - * - * _.keysIn(new Foo); - * // => ['a', 'b', 'c'] (iteration order is not guaranteed) - */ - function keysIn(object) { - return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object); - } - - /** - * The opposite of `_.mapValues`; this method creates an object with the - * same values as `object` and keys generated by running each own enumerable - * string keyed property of `object` thru `iteratee`. The iteratee is invoked - * with three arguments: (value, key, object). - * - * @static - * @memberOf _ - * @since 3.8.0 - * @category Object - * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @returns {Object} Returns the new mapped object. - * @see _.mapValues - * @example - * - * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) { - * return key + value; - * }); - * // => { 'a1': 1, 'b2': 2 } - */ - function mapKeys(object, iteratee) { - var result = {}; - iteratee = getIteratee(iteratee, 3); - - baseForOwn(object, function(value, key, object) { - baseAssignValue(result, iteratee(value, key, object), value); - }); - return result; - } - - /** - * Creates an object with the same keys as `object` and values generated - * by running each own enumerable string keyed property of `object` thru - * `iteratee`. The iteratee is invoked with three arguments: - * (value, key, object). - * - * @static - * @memberOf _ - * @since 2.4.0 - * @category Object - * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @returns {Object} Returns the new mapped object. - * @see _.mapKeys - * @example - * - * var users = { - * 'fred': { 'user': 'fred', 'age': 40 }, - * 'pebbles': { 'user': 'pebbles', 'age': 1 } - * }; - * - * _.mapValues(users, function(o) { return o.age; }); - * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) - * - * // The `_.property` iteratee shorthand. - * _.mapValues(users, 'age'); - * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed) - */ - function mapValues(object, iteratee) { - var result = {}; - iteratee = getIteratee(iteratee, 3); - - baseForOwn(object, function(value, key, object) { - baseAssignValue(result, key, iteratee(value, key, object)); - }); - return result; - } - - /** - * This method is like `_.assign` except that it recursively merges own and - * inherited enumerable string keyed properties of source objects into the - * destination object. Source properties that resolve to `undefined` are - * skipped if a destination value exists. Array and plain object properties - * are merged recursively. Other objects and value types are overridden by - * assignment. Source objects are applied from left to right. Subsequent - * sources overwrite property assignments of previous sources. - * - * **Note:** This method mutates `object`. - * - * @static - * @memberOf _ - * @since 0.5.0 - * @category Object - * @param {Object} object The destination object. - * @param {...Object} [sources] The source objects. - * @returns {Object} Returns `object`. - * @example - * - * var object = { - * 'a': [{ 'b': 2 }, { 'd': 4 }] - * }; - * - * var other = { - * 'a': [{ 'c': 3 }, { 'e': 5 }] - * }; - * - * _.merge(object, other); - * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] } - */ - var merge = createAssigner(function(object, source, srcIndex) { - baseMerge(object, source, srcIndex); - }); - - /** - * This method is like `_.merge` except that it accepts `customizer` which - * is invoked to produce the merged values of the destination and source - * properties. If `customizer` returns `undefined`, merging is handled by the - * method instead. The `customizer` is invoked with six arguments: - * (objValue, srcValue, key, object, source, stack). - * - * **Note:** This method mutates `object`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Object - * @param {Object} object The destination object. - * @param {...Object} sources The source objects. - * @param {Function} customizer The function to customize assigned values. - * @returns {Object} Returns `object`. - * @example - * - * function customizer(objValue, srcValue) { - * if (_.isArray(objValue)) { - * return objValue.concat(srcValue); - * } - * } - * - * var object = { 'a': [1], 'b': [2] }; - * var other = { 'a': [3], 'b': [4] }; - * - * _.mergeWith(object, other, customizer); - * // => { 'a': [1, 3], 'b': [2, 4] } - */ - var mergeWith = createAssigner(function(object, source, srcIndex, customizer) { - baseMerge(object, source, srcIndex, customizer); - }); - - /** - * The opposite of `_.pick`; this method creates an object composed of the - * own and inherited enumerable property paths of `object` that are not omitted. - * - * **Note:** This method is considerably slower than `_.pick`. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Object - * @param {Object} object The source object. - * @param {...(string|string[])} [paths] The property paths to omit. - * @returns {Object} Returns the new object. - * @example - * - * var object = { 'a': 1, 'b': '2', 'c': 3 }; - * - * _.omit(object, ['a', 'c']); - * // => { 'b': '2' } - */ - var omit = flatRest(function(object, paths) { - var result = {}; - if (object == null) { - return result; - } - var isDeep = false; - paths = arrayMap(paths, function(path) { - path = castPath(path, object); - isDeep || (isDeep = path.length > 1); - return path; - }); - copyObject(object, getAllKeysIn(object), result); - if (isDeep) { - result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone); - } - var length = paths.length; - while (length--) { - baseUnset(result, paths[length]); - } - return result; - }); - - /** - * The opposite of `_.pickBy`; this method creates an object composed of - * the own and inherited enumerable string keyed properties of `object` that - * `predicate` doesn't return truthy for. The predicate is invoked with two - * arguments: (value, key). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Object - * @param {Object} object The source object. - * @param {Function} [predicate=_.identity] The function invoked per property. - * @returns {Object} Returns the new object. - * @example - * - * var object = { 'a': 1, 'b': '2', 'c': 3 }; - * - * _.omitBy(object, _.isNumber); - * // => { 'b': '2' } - */ - function omitBy(object, predicate) { - return pickBy(object, negate(getIteratee(predicate))); - } - - /** - * Creates an object composed of the picked `object` properties. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Object - * @param {Object} object The source object. - * @param {...(string|string[])} [paths] The property paths to pick. - * @returns {Object} Returns the new object. - * @example - * - * var object = { 'a': 1, 'b': '2', 'c': 3 }; - * - * _.pick(object, ['a', 'c']); - * // => { 'a': 1, 'c': 3 } - */ - var pick = flatRest(function(object, paths) { - return object == null ? {} : basePick(object, paths); - }); - - /** - * Creates an object composed of the `object` properties `predicate` returns - * truthy for. The predicate is invoked with two arguments: (value, key). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Object - * @param {Object} object The source object. - * @param {Function} [predicate=_.identity] The function invoked per property. - * @returns {Object} Returns the new object. - * @example - * - * var object = { 'a': 1, 'b': '2', 'c': 3 }; - * - * _.pickBy(object, _.isNumber); - * // => { 'a': 1, 'c': 3 } - */ - function pickBy(object, predicate) { - if (object == null) { - return {}; - } - var props = arrayMap(getAllKeysIn(object), function(prop) { - return [prop]; - }); - predicate = getIteratee(predicate); - return basePickBy(object, props, function(value, path) { - return predicate(value, path[0]); - }); - } - - /** - * This method is like `_.get` except that if the resolved value is a - * function it's invoked with the `this` binding of its parent object and - * its result is returned. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Object - * @param {Object} object The object to query. - * @param {Array|string} path The path of the property to resolve. - * @param {*} [defaultValue] The value returned for `undefined` resolved values. - * @returns {*} Returns the resolved value. - * @example - * - * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] }; - * - * _.result(object, 'a[0].b.c1'); - * // => 3 - * - * _.result(object, 'a[0].b.c2'); - * // => 4 - * - * _.result(object, 'a[0].b.c3', 'default'); - * // => 'default' - * - * _.result(object, 'a[0].b.c3', _.constant('default')); - * // => 'default' - */ - function result(object, path, defaultValue) { - path = castPath(path, object); - - var index = -1, - length = path.length; - - // Ensure the loop is entered when path is empty. - if (!length) { - length = 1; - object = undefined; - } - while (++index < length) { - var value = object == null ? undefined : object[toKey(path[index])]; - if (value === undefined) { - index = length; - value = defaultValue; - } - object = isFunction(value) ? value.call(object) : value; - } - return object; - } - - /** - * Sets the value at `path` of `object`. If a portion of `path` doesn't exist, - * it's created. Arrays are created for missing index properties while objects - * are created for all other missing properties. Use `_.setWith` to customize - * `path` creation. - * - * **Note:** This method mutates `object`. - * - * @static - * @memberOf _ - * @since 3.7.0 - * @category Object - * @param {Object} object The object to modify. - * @param {Array|string} path The path of the property to set. - * @param {*} value The value to set. - * @returns {Object} Returns `object`. - * @example - * - * var object = { 'a': [{ 'b': { 'c': 3 } }] }; - * - * _.set(object, 'a[0].b.c', 4); - * console.log(object.a[0].b.c); - * // => 4 - * - * _.set(object, ['x', '0', 'y', 'z'], 5); - * console.log(object.x[0].y.z); - * // => 5 - */ - function set(object, path, value) { - return object == null ? object : baseSet(object, path, value); - } - - /** - * This method is like `_.set` except that it accepts `customizer` which is - * invoked to produce the objects of `path`. If `customizer` returns `undefined` - * path creation is handled by the method instead. The `customizer` is invoked - * with three arguments: (nsValue, key, nsObject). - * - * **Note:** This method mutates `object`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Object - * @param {Object} object The object to modify. - * @param {Array|string} path The path of the property to set. - * @param {*} value The value to set. - * @param {Function} [customizer] The function to customize assigned values. - * @returns {Object} Returns `object`. - * @example - * - * var object = {}; - * - * _.setWith(object, '[0][1]', 'a', Object); - * // => { '0': { '1': 'a' } } - */ - function setWith(object, path, value, customizer) { - customizer = typeof customizer == 'function' ? customizer : undefined; - return object == null ? object : baseSet(object, path, value, customizer); - } - - /** - * Creates an array of own enumerable string keyed-value pairs for `object` - * which can be consumed by `_.fromPairs`. If `object` is a map or set, its - * entries are returned. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @alias entries - * @category Object - * @param {Object} object The object to query. - * @returns {Array} Returns the key-value pairs. - * @example - * - * function Foo() { - * this.a = 1; - * this.b = 2; - * } - * - * Foo.prototype.c = 3; - * - * _.toPairs(new Foo); - * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed) - */ - var toPairs = createToPairs(keys); - - /** - * Creates an array of own and inherited enumerable string keyed-value pairs - * for `object` which can be consumed by `_.fromPairs`. If `object` is a map - * or set, its entries are returned. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @alias entriesIn - * @category Object - * @param {Object} object The object to query. - * @returns {Array} Returns the key-value pairs. - * @example - * - * function Foo() { - * this.a = 1; - * this.b = 2; - * } - * - * Foo.prototype.c = 3; - * - * _.toPairsIn(new Foo); - * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed) - */ - var toPairsIn = createToPairs(keysIn); - - /** - * An alternative to `_.reduce`; this method transforms `object` to a new - * `accumulator` object which is the result of running each of its own - * enumerable string keyed properties thru `iteratee`, with each invocation - * potentially mutating the `accumulator` object. If `accumulator` is not - * provided, a new object with the same `[[Prototype]]` will be used. The - * iteratee is invoked with four arguments: (accumulator, value, key, object). - * Iteratee functions may exit iteration early by explicitly returning `false`. - * - * @static - * @memberOf _ - * @since 1.3.0 - * @category Object - * @param {Object} object The object to iterate over. - * @param {Function} [iteratee=_.identity] The function invoked per iteration. - * @param {*} [accumulator] The custom accumulator value. - * @returns {*} Returns the accumulated value. - * @example - * - * _.transform([2, 3, 4], function(result, n) { - * result.push(n *= n); - * return n % 2 == 0; - * }, []); - * // => [4, 9] - * - * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) { - * (result[value] || (result[value] = [])).push(key); - * }, {}); - * // => { '1': ['a', 'c'], '2': ['b'] } - */ - function transform(object, iteratee, accumulator) { - var isArr = isArray(object), - isArrLike = isArr || isBuffer(object) || isTypedArray(object); - - iteratee = getIteratee(iteratee, 4); - if (accumulator == null) { - var Ctor = object && object.constructor; - if (isArrLike) { - accumulator = isArr ? new Ctor : []; - } - else if (isObject(object)) { - accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {}; - } - else { - accumulator = {}; - } - } - (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) { - return iteratee(accumulator, value, index, object); - }); - return accumulator; - } - - /** - * Removes the property at `path` of `object`. - * - * **Note:** This method mutates `object`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Object - * @param {Object} object The object to modify. - * @param {Array|string} path The path of the property to unset. - * @returns {boolean} Returns `true` if the property is deleted, else `false`. - * @example - * - * var object = { 'a': [{ 'b': { 'c': 7 } }] }; - * _.unset(object, 'a[0].b.c'); - * // => true - * - * console.log(object); - * // => { 'a': [{ 'b': {} }] }; - * - * _.unset(object, ['a', '0', 'b', 'c']); - * // => true - * - * console.log(object); - * // => { 'a': [{ 'b': {} }] }; - */ - function unset(object, path) { - return object == null ? true : baseUnset(object, path); - } - - /** - * This method is like `_.set` except that accepts `updater` to produce the - * value to set. Use `_.updateWith` to customize `path` creation. The `updater` - * is invoked with one argument: (value). - * - * **Note:** This method mutates `object`. - * - * @static - * @memberOf _ - * @since 4.6.0 - * @category Object - * @param {Object} object The object to modify. - * @param {Array|string} path The path of the property to set. - * @param {Function} updater The function to produce the updated value. - * @returns {Object} Returns `object`. - * @example - * - * var object = { 'a': [{ 'b': { 'c': 3 } }] }; - * - * _.update(object, 'a[0].b.c', function(n) { return n * n; }); - * console.log(object.a[0].b.c); - * // => 9 - * - * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; }); - * console.log(object.x[0].y.z); - * // => 0 - */ - function update(object, path, updater) { - return object == null ? object : baseUpdate(object, path, castFunction(updater)); - } - - /** - * This method is like `_.update` except that it accepts `customizer` which is - * invoked to produce the objects of `path`. If `customizer` returns `undefined` - * path creation is handled by the method instead. The `customizer` is invoked - * with three arguments: (nsValue, key, nsObject). - * - * **Note:** This method mutates `object`. - * - * @static - * @memberOf _ - * @since 4.6.0 - * @category Object - * @param {Object} object The object to modify. - * @param {Array|string} path The path of the property to set. - * @param {Function} updater The function to produce the updated value. - * @param {Function} [customizer] The function to customize assigned values. - * @returns {Object} Returns `object`. - * @example - * - * var object = {}; - * - * _.updateWith(object, '[0][1]', _.constant('a'), Object); - * // => { '0': { '1': 'a' } } - */ - function updateWith(object, path, updater, customizer) { - customizer = typeof customizer == 'function' ? customizer : undefined; - return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer); - } - - /** - * Creates an array of the own enumerable string keyed property values of `object`. - * - * **Note:** Non-object values are coerced to objects. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category Object - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property values. - * @example - * - * function Foo() { - * this.a = 1; - * this.b = 2; - * } - * - * Foo.prototype.c = 3; - * - * _.values(new Foo); - * // => [1, 2] (iteration order is not guaranteed) - * - * _.values('hi'); - * // => ['h', 'i'] - */ - function values(object) { - return object == null ? [] : baseValues(object, keys(object)); - } - - /** - * Creates an array of the own and inherited enumerable string keyed property - * values of `object`. - * - * **Note:** Non-object values are coerced to objects. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category Object - * @param {Object} object The object to query. - * @returns {Array} Returns the array of property values. - * @example - * - * function Foo() { - * this.a = 1; - * this.b = 2; - * } - * - * Foo.prototype.c = 3; - * - * _.valuesIn(new Foo); - * // => [1, 2, 3] (iteration order is not guaranteed) - */ - function valuesIn(object) { - return object == null ? [] : baseValues(object, keysIn(object)); - } - - /*------------------------------------------------------------------------*/ - - /** - * Clamps `number` within the inclusive `lower` and `upper` bounds. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category Number - * @param {number} number The number to clamp. - * @param {number} [lower] The lower bound. - * @param {number} upper The upper bound. - * @returns {number} Returns the clamped number. - * @example - * - * _.clamp(-10, -5, 5); - * // => -5 - * - * _.clamp(10, -5, 5); - * // => 5 - */ - function clamp(number, lower, upper) { - if (upper === undefined) { - upper = lower; - lower = undefined; - } - if (upper !== undefined) { - upper = toNumber(upper); - upper = upper === upper ? upper : 0; - } - if (lower !== undefined) { - lower = toNumber(lower); - lower = lower === lower ? lower : 0; - } - return baseClamp(toNumber(number), lower, upper); - } - - /** - * Checks if `n` is between `start` and up to, but not including, `end`. If - * `end` is not specified, it's set to `start` with `start` then set to `0`. - * If `start` is greater than `end` the params are swapped to support - * negative ranges. - * - * @static - * @memberOf _ - * @since 3.3.0 - * @category Number - * @param {number} number The number to check. - * @param {number} [start=0] The start of the range. - * @param {number} end The end of the range. - * @returns {boolean} Returns `true` if `number` is in the range, else `false`. - * @see _.range, _.rangeRight - * @example - * - * _.inRange(3, 2, 4); - * // => true - * - * _.inRange(4, 8); - * // => true - * - * _.inRange(4, 2); - * // => false - * - * _.inRange(2, 2); - * // => false - * - * _.inRange(1.2, 2); - * // => true - * - * _.inRange(5.2, 4); - * // => false - * - * _.inRange(-3, -2, -6); - * // => true - */ - function inRange(number, start, end) { - start = toFinite(start); - if (end === undefined) { - end = start; - start = 0; - } else { - end = toFinite(end); - } - number = toNumber(number); - return baseInRange(number, start, end); - } - - /** - * Produces a random number between the inclusive `lower` and `upper` bounds. - * If only one argument is provided a number between `0` and the given number - * is returned. If `floating` is `true`, or either `lower` or `upper` are - * floats, a floating-point number is returned instead of an integer. - * - * **Note:** JavaScript follows the IEEE-754 standard for resolving - * floating-point values which can produce unexpected results. - * - * @static - * @memberOf _ - * @since 0.7.0 - * @category Number - * @param {number} [lower=0] The lower bound. - * @param {number} [upper=1] The upper bound. - * @param {boolean} [floating] Specify returning a floating-point number. - * @returns {number} Returns the random number. - * @example - * - * _.random(0, 5); - * // => an integer between 0 and 5 - * - * _.random(5); - * // => also an integer between 0 and 5 - * - * _.random(5, true); - * // => a floating-point number between 0 and 5 - * - * _.random(1.2, 5.2); - * // => a floating-point number between 1.2 and 5.2 - */ - function random(lower, upper, floating) { - if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) { - upper = floating = undefined; - } - if (floating === undefined) { - if (typeof upper == 'boolean') { - floating = upper; - upper = undefined; - } - else if (typeof lower == 'boolean') { - floating = lower; - lower = undefined; - } - } - if (lower === undefined && upper === undefined) { - lower = 0; - upper = 1; - } - else { - lower = toFinite(lower); - if (upper === undefined) { - upper = lower; - lower = 0; - } else { - upper = toFinite(upper); - } - } - if (lower > upper) { - var temp = lower; - lower = upper; - upper = temp; - } - if (floating || lower % 1 || upper % 1) { - var rand = nativeRandom(); - return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper); - } - return baseRandom(lower, upper); - } - - /*------------------------------------------------------------------------*/ - - /** - * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase). - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category String - * @param {string} [string=''] The string to convert. - * @returns {string} Returns the camel cased string. - * @example - * - * _.camelCase('Foo Bar'); - * // => 'fooBar' - * - * _.camelCase('--foo-bar--'); - * // => 'fooBar' - * - * _.camelCase('__FOO_BAR__'); - * // => 'fooBar' - */ - var camelCase = createCompounder(function(result, word, index) { - word = word.toLowerCase(); - return result + (index ? capitalize(word) : word); - }); - - /** - * Converts the first character of `string` to upper case and the remaining - * to lower case. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category String - * @param {string} [string=''] The string to capitalize. - * @returns {string} Returns the capitalized string. - * @example - * - * _.capitalize('FRED'); - * // => 'Fred' - */ - function capitalize(string) { - return upperFirst(toString(string).toLowerCase()); - } - - /** - * Deburrs `string` by converting - * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table) - * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A) - * letters to basic Latin letters and removing - * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks). - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category String - * @param {string} [string=''] The string to deburr. - * @returns {string} Returns the deburred string. - * @example - * - * _.deburr('déjà vu'); - * // => 'deja vu' - */ - function deburr(string) { - string = toString(string); - return string && string.replace(reLatin, deburrLetter).replace(reComboMark, ''); - } - - /** - * Checks if `string` ends with the given target string. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category String - * @param {string} [string=''] The string to inspect. - * @param {string} [target] The string to search for. - * @param {number} [position=string.length] The position to search up to. - * @returns {boolean} Returns `true` if `string` ends with `target`, - * else `false`. - * @example - * - * _.endsWith('abc', 'c'); - * // => true - * - * _.endsWith('abc', 'b'); - * // => false - * - * _.endsWith('abc', 'b', 2); - * // => true - */ - function endsWith(string, target, position) { - string = toString(string); - target = baseToString(target); - - var length = string.length; - position = position === undefined - ? length - : baseClamp(toInteger(position), 0, length); - - var end = position; - position -= target.length; - return position >= 0 && string.slice(position, end) == target; - } - - /** - * Converts the characters "&", "<", ">", '"', and "'" in `string` to their - * corresponding HTML entities. - * - * **Note:** No other characters are escaped. To escape additional - * characters use a third-party library like [_he_](https://mths.be/he). - * - * Though the ">" character is escaped for symmetry, characters like - * ">" and "/" don't need escaping in HTML and have no special meaning - * unless they're part of a tag or unquoted attribute value. See - * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands) - * (under "semi-related fun fact") for more details. - * - * When working with HTML you should always - * [quote attribute values](http://wonko.com/post/html-escaping) to reduce - * XSS vectors. - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category String - * @param {string} [string=''] The string to escape. - * @returns {string} Returns the escaped string. - * @example - * - * _.escape('fred, barney, & pebbles'); - * // => 'fred, barney, & pebbles' - */ - function escape(string) { - string = toString(string); - return (string && reHasUnescapedHtml.test(string)) - ? string.replace(reUnescapedHtml, escapeHtmlChar) - : string; - } - - /** - * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+", - * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category String - * @param {string} [string=''] The string to escape. - * @returns {string} Returns the escaped string. - * @example - * - * _.escapeRegExp('[lodash](https://lodash.com/)'); - * // => '\[lodash\]\(https://lodash\.com/\)' - */ - function escapeRegExp(string) { - string = toString(string); - return (string && reHasRegExpChar.test(string)) - ? string.replace(reRegExpChar, '\\$&') - : string; - } - - /** - * Converts `string` to - * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles). - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category String - * @param {string} [string=''] The string to convert. - * @returns {string} Returns the kebab cased string. - * @example - * - * _.kebabCase('Foo Bar'); - * // => 'foo-bar' - * - * _.kebabCase('fooBar'); - * // => 'foo-bar' - * - * _.kebabCase('__FOO_BAR__'); - * // => 'foo-bar' - */ - var kebabCase = createCompounder(function(result, word, index) { - return result + (index ? '-' : '') + word.toLowerCase(); - }); - - /** - * Converts `string`, as space separated words, to lower case. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category String - * @param {string} [string=''] The string to convert. - * @returns {string} Returns the lower cased string. - * @example - * - * _.lowerCase('--Foo-Bar--'); - * // => 'foo bar' - * - * _.lowerCase('fooBar'); - * // => 'foo bar' - * - * _.lowerCase('__FOO_BAR__'); - * // => 'foo bar' - */ - var lowerCase = createCompounder(function(result, word, index) { - return result + (index ? ' ' : '') + word.toLowerCase(); - }); - - /** - * Converts the first character of `string` to lower case. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category String - * @param {string} [string=''] The string to convert. - * @returns {string} Returns the converted string. - * @example - * - * _.lowerFirst('Fred'); - * // => 'fred' - * - * _.lowerFirst('FRED'); - * // => 'fRED' - */ - var lowerFirst = createCaseFirst('toLowerCase'); - - /** - * Pads `string` on the left and right sides if it's shorter than `length`. - * Padding characters are truncated if they can't be evenly divided by `length`. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category String - * @param {string} [string=''] The string to pad. - * @param {number} [length=0] The padding length. - * @param {string} [chars=' '] The string used as padding. - * @returns {string} Returns the padded string. - * @example - * - * _.pad('abc', 8); - * // => ' abc ' - * - * _.pad('abc', 8, '_-'); - * // => '_-abc_-_' - * - * _.pad('abc', 3); - * // => 'abc' - */ - function pad(string, length, chars) { - string = toString(string); - length = toInteger(length); - - var strLength = length ? stringSize(string) : 0; - if (!length || strLength >= length) { - return string; - } - var mid = (length - strLength) / 2; - return ( - createPadding(nativeFloor(mid), chars) + - string + - createPadding(nativeCeil(mid), chars) - ); - } - - /** - * Pads `string` on the right side if it's shorter than `length`. Padding - * characters are truncated if they exceed `length`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category String - * @param {string} [string=''] The string to pad. - * @param {number} [length=0] The padding length. - * @param {string} [chars=' '] The string used as padding. - * @returns {string} Returns the padded string. - * @example - * - * _.padEnd('abc', 6); - * // => 'abc ' - * - * _.padEnd('abc', 6, '_-'); - * // => 'abc_-_' - * - * _.padEnd('abc', 3); - * // => 'abc' - */ - function padEnd(string, length, chars) { - string = toString(string); - length = toInteger(length); - - var strLength = length ? stringSize(string) : 0; - return (length && strLength < length) - ? (string + createPadding(length - strLength, chars)) - : string; - } - - /** - * Pads `string` on the left side if it's shorter than `length`. Padding - * characters are truncated if they exceed `length`. - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category String - * @param {string} [string=''] The string to pad. - * @param {number} [length=0] The padding length. - * @param {string} [chars=' '] The string used as padding. - * @returns {string} Returns the padded string. - * @example - * - * _.padStart('abc', 6); - * // => ' abc' - * - * _.padStart('abc', 6, '_-'); - * // => '_-_abc' - * - * _.padStart('abc', 3); - * // => 'abc' - */ - function padStart(string, length, chars) { - string = toString(string); - length = toInteger(length); - - var strLength = length ? stringSize(string) : 0; - return (length && strLength < length) - ? (createPadding(length - strLength, chars) + string) - : string; - } - - /** - * Converts `string` to an integer of the specified radix. If `radix` is - * `undefined` or `0`, a `radix` of `10` is used unless `value` is a - * hexadecimal, in which case a `radix` of `16` is used. - * - * **Note:** This method aligns with the - * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`. - * - * @static - * @memberOf _ - * @since 1.1.0 - * @category String - * @param {string} string The string to convert. - * @param {number} [radix=10] The radix to interpret `value` by. - * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. - * @returns {number} Returns the converted integer. - * @example - * - * _.parseInt('08'); - * // => 8 - * - * _.map(['6', '08', '10'], _.parseInt); - * // => [6, 8, 10] - */ - function parseInt(string, radix, guard) { - if (guard || radix == null) { - radix = 0; - } else if (radix) { - radix = +radix; - } - return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0); - } - - /** - * Repeats the given string `n` times. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category String - * @param {string} [string=''] The string to repeat. - * @param {number} [n=1] The number of times to repeat the string. - * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. - * @returns {string} Returns the repeated string. - * @example - * - * _.repeat('*', 3); - * // => '***' - * - * _.repeat('abc', 2); - * // => 'abcabc' - * - * _.repeat('abc', 0); - * // => '' - */ - function repeat(string, n, guard) { - if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) { - n = 1; - } else { - n = toInteger(n); - } - return baseRepeat(toString(string), n); - } - - /** - * Replaces matches for `pattern` in `string` with `replacement`. - * - * **Note:** This method is based on - * [`String#replace`](https://mdn.io/String/replace). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category String - * @param {string} [string=''] The string to modify. - * @param {RegExp|string} pattern The pattern to replace. - * @param {Function|string} replacement The match replacement. - * @returns {string} Returns the modified string. - * @example - * - * _.replace('Hi Fred', 'Fred', 'Barney'); - * // => 'Hi Barney' - */ - function replace() { - var args = arguments, - string = toString(args[0]); - - return args.length < 3 ? string : string.replace(args[1], args[2]); - } - - /** - * Converts `string` to - * [snake case](https://en.wikipedia.org/wiki/Snake_case). - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category String - * @param {string} [string=''] The string to convert. - * @returns {string} Returns the snake cased string. - * @example - * - * _.snakeCase('Foo Bar'); - * // => 'foo_bar' - * - * _.snakeCase('fooBar'); - * // => 'foo_bar' - * - * _.snakeCase('--FOO-BAR--'); - * // => 'foo_bar' - */ - var snakeCase = createCompounder(function(result, word, index) { - return result + (index ? '_' : '') + word.toLowerCase(); - }); - - /** - * Splits `string` by `separator`. - * - * **Note:** This method is based on - * [`String#split`](https://mdn.io/String/split). - * - * @static - * @memberOf _ - * @since 4.0.0 - * @category String - * @param {string} [string=''] The string to split. - * @param {RegExp|string} separator The separator pattern to split by. - * @param {number} [limit] The length to truncate results to. - * @returns {Array} Returns the string segments. - * @example - * - * _.split('a-b-c', '-', 2); - * // => ['a', 'b'] - */ - function split(string, separator, limit) { - if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) { - separator = limit = undefined; - } - limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0; - if (!limit) { - return []; - } - string = toString(string); - if (string && ( - typeof separator == 'string' || - (separator != null && !isRegExp(separator)) - )) { - separator = baseToString(separator); - if (!separator && hasUnicode(string)) { - return castSlice(stringToArray(string), 0, limit); - } - } - return string.split(separator, limit); - } - - /** - * Converts `string` to - * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage). - * - * @static - * @memberOf _ - * @since 3.1.0 - * @category String - * @param {string} [string=''] The string to convert. - * @returns {string} Returns the start cased string. - * @example - * - * _.startCase('--foo-bar--'); - * // => 'Foo Bar' - * - * _.startCase('fooBar'); - * // => 'Foo Bar' - * - * _.startCase('__FOO_BAR__'); - * // => 'FOO BAR' - */ - var startCase = createCompounder(function(result, word, index) { - return result + (index ? ' ' : '') + upperFirst(word); - }); - - /** - * Checks if `string` starts with the given target string. - * - * @static - * @memberOf _ - * @since 3.0.0 - * @category String - * @param {string} [string=''] The string to inspect. - * @param {string} [target] The string to search for. - * @param {number} [position=0] The position to search from. - * @returns {boolean} Returns `true` if `string` starts with `target`, - * else `false`. - * @example - * - * _.startsWith('abc', 'a'); - * // => true - * - * _.startsWith('abc', 'b'); - * // => false - * - * _.startsWith('abc', 'b', 1); - * // => true - */ - function startsWith(string, target, position) { - string = toString(string); - position = position == null - ? 0 - : baseClamp(toInteger(position), 0, string.length); - - target = baseToString(target); - return string.slice(position, position + target.length) == target; - } - - /** - * Creates a compiled template function that can interpolate data properties - * in "interpolate" delimiters, HTML-escape interpolated data properties in - * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data - * properties may be accessed as free variables in the template. If a setting - * object is given, it takes precedence over `_.templateSettings` values. - * - * **Note:** In the development build `_.template` utilizes - * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) - * for easier debugging. - * - * For more information on precompiling templates see - * [lodash's custom builds documentation](https://lodash.com/custom-builds). - * - * For more information on Chrome extension sandboxes see - * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval). - * - * @static - * @since 0.1.0 - * @memberOf _ - * @category String - * @param {string} [string=''] The template string. - * @param {Object} [options={}] The options object. - * @param {RegExp} [options.escape=_.templateSettings.escape] - * The HTML "escape" delimiter. - * @param {RegExp} [options.evaluate=_.templateSettings.evaluate] - * The "evaluate" delimiter. - * @param {Object} [options.imports=_.templateSettings.imports] - * An object to import into the template as free variables. - * @param {RegExp} [options.interpolate=_.templateSettings.interpolate] - * The "interpolate" delimiter. - * @param {string} [options.sourceURL='lodash.templateSources[n]'] - * The sourceURL of the compiled template. - * @param {string} [options.variable='obj'] - * The data object variable name. - * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`. - * @returns {Function} Returns the compiled template function. - * @example - * - * // Use the "interpolate" delimiter to create a compiled template. - * var compiled = _.template('hello <%= user %>!'); - * compiled({ 'user': 'fred' }); - * // => 'hello fred!' - * - * // Use the HTML "escape" delimiter to escape data property values. - * var compiled = _.template('<%- value %>'); - * compiled({ 'value': ' - - - - - - - -
-

This page is using the Event Espresso API

- -

If you are making a request from a different domain, you will probably need to install and activate the WP API CORS addon, which is however currently in BETA.

- - -``` - -To see this plugin in action, [click here](http://dev2.eventespresso.com/wp-content/plugins/eea-rest-api-client/standalone-scripts/ee-events-calendar.php). - -As you can see, this example using the [FullCalendar library](http://fullcalendar.io/) for displaying the calendar, which itself requires [jQuery](https://jquery.com/) and [moment.js](http://momentjs.com/). It simply initializes the calendar, and fetches event data from the EE4 JSON REST API in order to populate the calendar. Note this is just a sample usage of the EE4 JSON REST API, it is by no means a replacement for the [EE4 Calendar Addon](https://eventespresso.com/product/ee4-events-calendar/). - -However, the server that is running the EE4 JSON REST API will probably also need to be using the [WP API CORS addon](https://github.com/thenbrent/WP-API-CORS), which isn't currently ready for use on live sites. - -## Conclusion - -You may also be interested in the tutorial on how to create an addon that uses [Angular.js to fetch data from the EE4 JSON REST API](building-an-ee4-addon-that-uses-angular-js-and-the-ee4-json-rest-api.md). - -Hopefully these two simple examples give you an idea of how to use the EE4 JSON REST API. If you'd like to submit another example, please open a [pull request on the EE4 JSON REST API Client repository](https://github.com/eventespresso/eea-rest-api-client). - -For more detailed information, please refer to our [EE4 REST API documentation](../C--REST-API). \ No newline at end of file diff --git a/docs/T--Tutorials/modifying-defaults-for-events.md b/docs/T--Tutorials/modifying-defaults-for-events.md deleted file mode 100644 index 19b139ec275..00000000000 --- a/docs/T--Tutorials/modifying-defaults-for-events.md +++ /dev/null @@ -1,87 +0,0 @@ -# Modifying the Defaults on Creating a New Event - -With filter hooks provided in Event Espresso core, it is possible to modify the defaults used when creating a new event. Below is the content of a sample plugin that demonstrates how this is possible: - -```php - Applications, then "Add new". -4. Use any "Consumer Name" and "Description" you want. -5. For "Callback", use `{yoursite}/{path-to-wp-api-oauth-client}/www?step=authorize`. - So if your site lives at `http://src.wordpress-develop.dev` and you placed the client application in the folder - `wp-content/plugins/wp-api-oauth-client`, the url should be `http://src.wordpress-develop.dev/wp-content/plugins/wp-api-oauth-client/www/?step=authorize`. See [this screenshot](https://drive.google.com/file/d/0B2KCao4zFjaxQU5aaTFjWUZ1bTg/view?usp=drivesdk) -6. Now direct your browser to `http://src.wordpress-develop.dev/wp-content/plugins/wp-api-oauth-client/www`. -7. Enter `http://src.wordpress-develop.dev` in the "Address to start discovery", [like this](https://drive.google.com/file/d/0B2KCao4zFjaxMHFfTkNicFdLOXc/view?usp=drivesdk). -8. [Enter the "Client Key" and "Client Secret"](https://drive.google.com/file/d/0B2KCao4zFjaxQXpSbWRydmJqRm8/view?usp=drivesdk) you noted earlier and submit the form. (This step won't work if you have Basic Auth or the current version of Event Espresso 4 active) -9. [Authorize!](https://drive.google.com/file/d/0B2KCao4zFjaxRVh3VjZ5UWV2aE0/view?usp=drivesdk). -10.[Bask in how it's working](https://drive.google.com/file/d/0B2KCao4zFjaxWDloV2MyaWRtUEU/view?usp=drivesdk). - - - diff --git a/docs/Z--General/README.md b/docs/Z--General/README.md deleted file mode 100644 index 6c6f3b839a5..00000000000 --- a/docs/Z--General/README.md +++ /dev/null @@ -1,5 +0,0 @@ -This folder is for general documentation that is applies generally to all of EE as opposed to specific subsystems. - -## Table of Contents: - -- [Third Party Libraries in Use](third-party-libraries-in-use.md) \ No newline at end of file diff --git a/docs/Z--General/third-party-libraries-in-use.md b/docs/Z--General/third-party-libraries-in-use.md deleted file mode 100644 index 8d0ab89553d..00000000000 --- a/docs/Z--General/third-party-libraries-in-use.md +++ /dev/null @@ -1,65 +0,0 @@ -# Third Party Libraries in Use - -This is just to document the third party libraries in use for EE4 and where to find them. (`last updated` is used to indicate what version of EE the library was last updated). - -### accounting.js - -* link: https://github.com/josscrowcroft/accounting.js -* version in use: 0.3.2 -* last updated: EE4.1 - -### dompdf - -* link: https://github.com/dompdf/dompdf -* version in use: ? -* last updated: EE4.1 - -### Zurb Joyride - -* link: https://github.com/zurb/joyride -* version in use: 2.1 -* last updated: EE4.1 - -### moment.js - -* link: https://github.com/moment/moment -* version in use: 2.29 -* last updated: EE4.9.59 - -### qtip2 - -* link: http://github.com/Craga89/qTip2 -* version in use: 3.0.3 -* last updated: EE4.9.59 - - -### jQuery UI Timepicker - -* link: https://github.com/trentrichardson/jQuery-Timepicker-Addon -* version in use: 1.0.1 -* last updated: EE4.1 - - -### jQuery serializeFullArray - -* link: http://github.com/jhogendorn/jQuery-serializeFullArray/ -* version in use: 0.1 -* last updated: EE4.1 - -### jQuery validate - -* link: https://github.com/jzaefferer/jquery-validation -* version in use: 1.17.0 -* last updated: EE4.9.59 - -### parseuri - -* link: http://blog.stevenlevithan.com/archives/parseuri -* version in use: 1.2.2 -* last updated: EE4.1 - -## jQuery countdown timer - -* link: https://github.com/harshen/jQuery-countdownTimer -* version in use: 2.1.0 -* last updated: EE4.9.59 \ No newline at end of file diff --git a/docs/images/REAME.md b/docs/images/REAME.md deleted file mode 100644 index c44fa1223f1..00000000000 --- a/docs/images/REAME.md +++ /dev/null @@ -1 +0,0 @@ -This folder is where all images referenced in the documentation are found. \ No newline at end of file diff --git a/docs/images/checkin-admin-screen.png b/docs/images/checkin-admin-screen.png deleted file mode 100644 index c908a6b9364..00000000000 Binary files a/docs/images/checkin-admin-screen.png and /dev/null differ diff --git a/docs/images/database-migration-manager.png b/docs/images/database-migration-manager.png deleted file mode 100644 index dd7fa6fdb76..00000000000 Binary files a/docs/images/database-migration-manager.png and /dev/null differ diff --git a/docs/images/date-time-contexts.jpg b/docs/images/date-time-contexts.jpg deleted file mode 100644 index 087824f1f00..00000000000 Binary files a/docs/images/date-time-contexts.jpg and /dev/null differ diff --git a/docs/images/maintenance-mode-page.png b/docs/images/maintenance-mode-page.png deleted file mode 100644 index 368a9cd0c0c..00000000000 Binary files a/docs/images/maintenance-mode-page.png and /dev/null differ diff --git a/docs/images/maintenance-mode.png b/docs/images/maintenance-mode.png deleted file mode 100644 index a490f371e0c..00000000000 Binary files a/docs/images/maintenance-mode.png and /dev/null differ diff --git a/docs/images/message-templates-heirarchy.png b/docs/images/message-templates-heirarchy.png deleted file mode 100644 index 69c10b075ce..00000000000 Binary files a/docs/images/message-templates-heirarchy.png and /dev/null differ diff --git a/docs/images/messages-admin-metabox.png b/docs/images/messages-admin-metabox.png deleted file mode 100644 index 602f8a48ea3..00000000000 Binary files a/docs/images/messages-admin-metabox.png and /dev/null differ diff --git a/docs/images/messages-system-flow-new.jpeg b/docs/images/messages-system-flow-new.jpeg deleted file mode 100644 index 9c797c17dba..00000000000 Binary files a/docs/images/messages-system-flow-new.jpeg and /dev/null differ diff --git a/docs/images/models-venn-diagram.png b/docs/images/models-venn-diagram.png deleted file mode 100644 index 92deb915b2f..00000000000 Binary files a/docs/images/models-venn-diagram.png and /dev/null differ diff --git a/docs/images/payment-form-example-frontend.png b/docs/images/payment-form-example-frontend.png deleted file mode 100644 index 9a07cba211e..00000000000 Binary files a/docs/images/payment-form-example-frontend.png and /dev/null differ diff --git a/docs/images/payment-method-admin-interface.png b/docs/images/payment-method-admin-interface.png deleted file mode 100644 index 9ba784069c2..00000000000 Binary files a/docs/images/payment-method-admin-interface.png and /dev/null differ diff --git a/docs/images/postman-delete-force.JPG b/docs/images/postman-delete-force.JPG deleted file mode 100644 index dfb5df81353..00000000000 Binary files a/docs/images/postman-delete-force.JPG and /dev/null differ diff --git a/docs/images/postman-delete.JPG b/docs/images/postman-delete.JPG deleted file mode 100644 index e04e6922afd..00000000000 Binary files a/docs/images/postman-delete.JPG and /dev/null differ diff --git a/docs/images/postman-post-multiple-values.JPG b/docs/images/postman-post-multiple-values.JPG deleted file mode 100644 index e1a50179eee..00000000000 Binary files a/docs/images/postman-post-multiple-values.JPG and /dev/null differ diff --git a/docs/images/postman-post-single-value.JPG b/docs/images/postman-post-single-value.JPG deleted file mode 100644 index 6d0dc3294d5..00000000000 Binary files a/docs/images/postman-post-single-value.JPG and /dev/null differ diff --git a/docs/images/postman-put.JPG b/docs/images/postman-put.JPG deleted file mode 100644 index 9100c7ff10b..00000000000 Binary files a/docs/images/postman-put.JPG and /dev/null differ diff --git a/eslint/config.js b/eslint/config.js deleted file mode 100644 index 8b99bc73697..00000000000 --- a/eslint/config.js +++ /dev/null @@ -1,171 +0,0 @@ -module.exports = { - parser: 'babel-eslint', - extends: [ - 'wordpress', - 'plugin:wordpress/esnext', - 'plugin:react/recommended', - 'plugin:jsx-a11y/recommended', - ], - env: { - browser: false, - es6: true, - node: true, - }, - parserOptions: { - sourceType: 'module', - ecmaFeatures: { - jsx: true, - }, - }, - globals: { - wp: true, - window: true, - document: true, - }, - plugins: [ - 'wordpress', - 'react', - 'jsx-a11y', - ], - settings: { - react: { - pragma: 'wp', - }, - }, - rules: { - 'array-bracket-spacing': [ 'error', 'always' ], - 'brace-style': [ 'error', '1tbs' ], - camelcase: [ 'error', { properties: 'never' } ], - 'comma-dangle': [ 'error', 'always-multiline' ], - 'comma-spacing': 'error', - 'comma-style': 'error', - 'computed-property-spacing': [ 'error', 'always' ], - 'dot-notation': 'error', - 'eol-last': 'error', - eqeqeq: 'error', - 'func-call-spacing': 'error', - indent: [ 'error', 'tab', { SwitchCase: 1 } ], - 'jsx-a11y/label-has-for': [ - 'error', { - required: 'id', - }, - ], - 'jsx-a11y/media-has-caption': 'off', - 'jsx-a11y/no-noninteractive-tabindex': 'off', - 'jsx-a11y/role-has-required-aria-props': 'off', - 'jsx-quotes': 'error', - 'key-spacing': 'error', - 'keyword-spacing': 'error', - 'lines-around-comment': 'off', - 'no-alert': 'error', - 'no-bitwise': 'error', - 'no-caller': 'error', - 'no-console': 'error', - 'no-debugger': 'error', - 'no-dupe-args': 'error', - 'no-dupe-keys': 'error', - 'no-duplicate-case': 'error', - 'no-else-return': 'error', - 'no-eval': 'error', - 'no-extra-semi': 'error', - 'no-fallthrough': 'error', - 'no-lonely-if': 'error', - 'no-mixed-operators': 'error', - 'no-mixed-spaces-and-tabs': 'error', - 'no-multiple-empty-lines': [ 'error', { max: 1 } ], - 'no-multi-spaces': 'error', - 'no-multi-str': 'off', - 'no-negated-in-lhs': 'error', - 'no-nested-ternary': 'error', - 'no-redeclare': 'error', - 'no-restricted-syntax': [ - 'error', - { - selector: 'CallExpression[callee.name=/^__|_n|_x$/]:not([arguments.0.type=/^Literal|BinaryExpression$/])', - message: 'Translate function arguments must be string literals.', - }, - { - selector: 'CallExpression[callee.name=/^_n|_x$/]:not([arguments.1.type=/^Literal|BinaryExpression$/])', - message: 'Translate function arguments must be string literals.', - }, - { - selector: 'CallExpression[callee.name=_nx]:not([arguments.2.type=/^Literal|BinaryExpression$/])', - message: 'Translate function arguments must be string literals.', - }, - ], - 'no-shadow': 'error', - 'no-undef': 'error', - 'no-undef-init': 'error', - 'no-unreachable': 'error', - 'no-unsafe-negation': 'error', - 'no-unused-expressions': 'error', - 'no-unused-vars': 'error', - 'no-useless-return': 'error', - 'no-whitespace-before-property': 'error', - 'object-curly-spacing': [ 'error', 'always' ], - 'padded-blocks': [ 'error', 'never' ], - 'quote-props': [ 'error', 'as-needed' ], - 'react/display-name': 'off', - 'react/jsx-curly-spacing': [ - 'error', { - when: 'always', - children: true, - }, - ], - 'react/jsx-equals-spacing': 'error', - 'react/jsx-indent': [ 'error', 'tab' ], - 'react/jsx-indent-props': [ 'error', 'tab' ], - 'react/jsx-key': 'error', - 'react/jsx-tag-spacing': 'error', - 'react/no-children-prop': 'off', - 'react/prop-types': 'off', - semi: 'error', - 'semi-spacing': 'error', - 'space-before-blocks': [ 'error', 'always' ], - 'space-before-function-paren': [ - 'error', { - anonymous: 'never', - named: 'never', - asyncArrow: 'always', - }, - ], - 'space-in-parens': [ 'error', 'always' ], - 'space-infix-ops': [ 'error', { int32Hint: false } ], - 'space-unary-ops': [ - 'error', { - overrides: { - '!': true, - yield: true, - }, - }, - ], - 'valid-jsdoc': [ - 'error', { - prefer: { - arg: 'param', - argument: 'param', - extends: 'augments', - returns: 'return', - }, - preferType: { - array: 'Array', - bool: 'boolean', - Boolean: 'boolean', - float: 'number', - Float: 'number', - int: 'number', - integer: 'number', - Integer: 'number', - Number: 'number', - object: 'Object', - String: 'string', - Void: 'void', - }, - requireParamDescription: false, - requireReturn: false, - }, - ], - 'valid-typeof': 'error', - yoda: 'off', - }, -}; diff --git a/info.json b/info.json deleted file mode 100644 index ee33f256aa9..00000000000 --- a/info.json +++ /dev/null @@ -1 +0,0 @@ -{"versionFile":"espresso.php","slug":"event-espresso-core-reg","textDomain":"event_espresso","wpOrgSlug":"event-espresso-decaf","wpOrgMainFileSlug":"espresso","wpOrgUser":"eventespresso","wpOrgRelease":"4.9.62.p","wpOrgPluginName":"Event Espresso 4 Decaf","wpOrgPluginUrl":"https:\/\/eventespresso.com\/pricing\/?ee_ver=ee4&utm_source=ee4_decaf_plugin_admin&utm_medium=link&utm_campaign=wordpress_plugins_page&utm_content=support_link","name":"Event Espresso Core","jsBuildDirectory":".\/","wpi18nJsPotFilePath":".\/languages\/ee-js.pot","srcBuildFolderName":"event-espresso-core","releaseFilesRemove":["src\/tests\/**","src\/acceptance_tests\/**","src\/bin\/**","src\/docs\/**","src\/info.json","src\/circle.yml","src\/readme.txt","src\/wp-assets\/**","src\/.travis.yml","src\/.github\/**","src\/assets\/src\/**","src\/eslint\/**","src\/.babelrc","src\/.editorconfig","src\/.eslintignore","src\/.eslintrc.js","src\/.nvmrc","src\/.postcss.config.js"],"decafFilesRemove":["src\/tests\/**","src\/acceptance_tests\/**","src\/bin\/**","src\/docs\/**","src\/info.json","src\/circle.yml","src\/.travis.yml","src\/caffeinated","src\/wp-assets\/**","src\/.github\/**","src\/assets\/src\/**","src\/eslint\/**","src\/.babelrc","src\/.editorconfig","src\/.eslintignore","src\/.eslintrc.js","src\/.nvmrc","src\/.postcss.config.js"],"awsbucket":"","awsregion":"","remoteNamesToPushTo":["demoee","devboxsitehub"]} \ No newline at end of file diff --git a/languages/ee-js.pot.php b/languages/ee-js.pot.php new file mode 100644 index 00000000000..8a7094f582b --- /dev/null +++ b/languages/ee-js.pot.php @@ -0,0 +1,13 @@ +=0.0.4" + "amdefine": "1.0.1" } } } @@ -5923,8 +5922,8 @@ "integrity": "sha1-ukAsJmGU8VlW7xXg/PJCmT9qff0=", "dev": true, "requires": { - "ajv": "^5.1.0", - "har-schema": "^2.0.0" + "ajv": "5.5.2", + "har-schema": "2.0.0" } }, "has": { @@ -5932,7 +5931,7 @@ "resolved": "https://registry.npmjs.org/has/-/has-1.0.1.tgz", "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", "requires": { - "function-bind": "^1.0.2" + "function-bind": "1.1.1" } }, "has-ansi": { @@ -5940,7 +5939,7 @@ "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" }, "dependencies": { "ansi-regex": { @@ -5978,7 +5977,7 @@ "integrity": "sha512-vdbKfmw+3LoOYVr+mtxHaX5a96+0f3DljYd8JOqvOLsf5mw2Otda2qCDT9qRqLAhrjyQ0h7ual5nOiASpsGNFw==", "dev": true, "requires": { - "has-symbol-support-x": "^1.4.1" + "has-symbol-support-x": "1.4.2" } }, "has-value": { @@ -5986,9 +5985,9 @@ "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" } }, "has-values": { @@ -5996,8 +5995,8 @@ "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" + "is-number": "3.0.0", + "kind-of": "4.0.0" }, "dependencies": { "kind-of": { @@ -6005,7 +6004,7 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -6016,8 +6015,8 @@ "integrity": "sha1-X8hoaEfs1zSZQDMZprCj8/auSRg=", "dev": true, "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "2.0.3", + "safe-buffer": "5.1.2" } }, "hash.js": { @@ -6026,8 +6025,8 @@ "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", "dev": true, "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" + "inherits": "2.0.3", + "minimalistic-assert": "1.0.1" } }, "hawk": { @@ -6036,10 +6035,10 @@ "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", "dev": true, "requires": { - "boom": "4.x.x", - "cryptiles": "3.x.x", - "hoek": "4.x.x", - "sntp": "2.x.x" + "boom": "4.3.1", + "cryptiles": "3.1.2", + "hoek": "4.2.1", + "sntp": "2.1.0" } }, "hmac-drbg": { @@ -6048,9 +6047,9 @@ "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", "dev": true, "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" + "hash.js": "1.1.3", + "minimalistic-assert": "1.0.1", + "minimalistic-crypto-utils": "1.0.1" } }, "hoek": { @@ -6070,8 +6069,8 @@ "integrity": "sha1-42w/LSyufXRqhX440Y1fMqeILbg=", "dev": true, "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.1" + "os-homedir": "1.0.2", + "os-tmpdir": "1.0.2" } }, "homedir-polyfill": { @@ -6080,7 +6079,7 @@ "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", "dev": true, "requires": { - "parse-passwd": "^1.0.0" + "parse-passwd": "1.0.0" } }, "hosted-git-info": { @@ -6100,7 +6099,7 @@ "integrity": "sha512-71lZziiDnsuabfdYiUeWdCVyKuqwWi23L8YeIgV9jSSZHCtb6wB1BKWooH7L3tn4/FuZJMVWyNaIDr4RGmaSYw==", "dev": true, "requires": { - "whatwg-encoding": "^1.0.1" + "whatwg-encoding": "1.0.3" } }, "htmlparser2": { @@ -6108,12 +6107,12 @@ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", "requires": { - "domelementtype": "^1.3.0", - "domhandler": "^2.3.0", - "domutils": "^1.5.1", - "entities": "^1.1.1", - "inherits": "^2.0.1", - "readable-stream": "^2.0.2" + "domelementtype": "1.3.0", + "domhandler": "2.4.1", + "domutils": "1.5.1", + "entities": "1.1.1", + "inherits": "2.0.3", + "readable-stream": "2.3.6" } }, "http-cache-semantics": { @@ -6128,9 +6127,9 @@ "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", "dev": true, "requires": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "assert-plus": "1.0.0", + "jsprim": "1.4.1", + "sshpk": "1.14.1" } }, "https-browserify": { @@ -6144,7 +6143,7 @@ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.21.tgz", "integrity": "sha512-En5V9za5mBt2oUA03WGD3TwDv0MKAruqsuxstbMUZaj9W9k/m1CV/9py3l0L5kw9Bln8fdHQmzHSYtvpvTLpKw==", "requires": { - "safer-buffer": "^2.1.0" + "safer-buffer": "2.1.2" } }, "icss-replace-symbols": { @@ -6159,7 +6158,7 @@ "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", "dev": true, "requires": { - "postcss": "^6.0.1" + "postcss": "6.0.21" } }, "ieee754": { @@ -6185,7 +6184,7 @@ "resolved": "https://registry.npmjs.org/immutability-helper/-/immutability-helper-2.6.6.tgz", "integrity": "sha512-CdLyZ9QuiWGk884SKhRvi8xjtB2PYMCBwa6fc8wZ5QltrdFEhwGz0upikzvjxjrDbsGs7qhgIUIMvI2YFywihA==", "requires": { - "invariant": "^2.2.0" + "invariant": "2.2.4" } }, "import-local": { @@ -6194,8 +6193,8 @@ "integrity": "sha512-vAaZHieK9qjGo58agRBg+bhHX3hoTZU/Oa3GESWLz7t1U62fk63aHuDJJEteXoDeTCcPmUT+z38gkHPZkkmpmQ==", "dev": true, "requires": { - "pkg-dir": "^2.0.0", - "resolve-cwd": "^2.0.0" + "pkg-dir": "2.0.0", + "resolve-cwd": "2.0.0" } }, "imurmurhash": { @@ -6210,7 +6209,7 @@ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "dev": true, "requires": { - "repeating": "^2.0.0" + "repeating": "2.0.1" } }, "indexes-of": { @@ -6231,8 +6230,8 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "once": "1.4.0", + "wrappy": "1.0.2" } }, "inherits": { @@ -6252,20 +6251,20 @@ "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^2.0.4", - "figures": "^2.0.0", - "lodash": "^4.3.0", + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.10", "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rx-lite": "^4.0.8", - "rx-lite-aggregates": "^4.0.8", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" }, "dependencies": { "strip-ansi": { @@ -6274,7 +6273,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } } } @@ -6291,8 +6290,8 @@ "integrity": "sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY=", "dev": true, "requires": { - "from2": "^2.1.1", - "p-is-promise": "^1.1.0" + "from2": "2.3.0", + "p-is-promise": "1.1.0" } }, "invariant": { @@ -6300,7 +6299,7 @@ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "requires": { - "loose-envify": "^1.0.0" + "loose-envify": "1.3.1" } }, "invert-kv": { @@ -6320,7 +6319,7 @@ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -6328,7 +6327,7 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -6344,7 +6343,7 @@ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, "requires": { - "binary-extensions": "^1.0.0" + "binary-extensions": "1.11.0" } }, "is-boolean-object": { @@ -6362,7 +6361,7 @@ "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "requires": { - "builtin-modules": "^1.0.0" + "builtin-modules": "1.1.1" } }, "is-callable": { @@ -6376,7 +6375,7 @@ "integrity": "sha512-c7TnwxLePuqIlxHgr7xtxzycJPegNHFuIrBkwbf8hc58//+Op1CqFkyS+xnIMkwn9UsJIwc174BIjkyBmSpjKg==", "dev": true, "requires": { - "ci-info": "^1.0.0" + "ci-info": "1.1.3" } }, "is-data-descriptor": { @@ -6384,7 +6383,7 @@ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -6392,7 +6391,7 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -6407,9 +6406,9 @@ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" }, "dependencies": { "kind-of": { @@ -6437,7 +6436,7 @@ "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", "dev": true, "requires": { - "is-primitive": "^2.0.0" + "is-primitive": "2.0.0" } }, "is-extendable": { @@ -6456,7 +6455,7 @@ "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "requires": { - "number-is-nan": "^1.0.0" + "number-is-nan": "1.0.1" } }, "is-fullwidth-code-point": { @@ -6477,7 +6476,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } }, "is-number": { @@ -6485,7 +6484,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -6493,7 +6492,7 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -6515,7 +6514,7 @@ "integrity": "sha1-s2ExHYPG5dcmyr9eJQsCNxBvWuI=", "dev": true, "requires": { - "symbol-observable": "^0.2.2" + "symbol-observable": "0.2.4" }, "dependencies": { "symbol-observable": { @@ -6531,7 +6530,7 @@ "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", "requires": { - "is-number": "^4.0.0" + "is-number": "4.0.0" }, "dependencies": { "is-number": { @@ -6553,7 +6552,7 @@ "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", "dev": true, "requires": { - "is-path-inside": "^1.0.0" + "is-path-inside": "1.0.1" } }, "is-path-inside": { @@ -6562,7 +6561,7 @@ "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "requires": { - "path-is-inside": "^1.0.1" + "path-is-inside": "1.0.2" } }, "is-plain-obj": { @@ -6576,7 +6575,7 @@ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "requires": { - "isobject": "^3.0.1" + "isobject": "3.0.1" } }, "is-posix-bracket": { @@ -6602,7 +6601,7 @@ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", "requires": { - "has": "^1.0.1" + "has": "1.0.1" } }, "is-resolvable": { @@ -6623,7 +6622,7 @@ "integrity": "sha1-RJypgpnnEwOCViieyytUDcQ3yzA=", "dev": true, "requires": { - "scoped-regex": "^1.0.0" + "scoped-regex": "1.0.0" } }, "is-stream": { @@ -6647,7 +6646,7 @@ "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", "dev": true, "requires": { - "html-comment-regex": "^1.1.0" + "html-comment-regex": "1.1.1" } }, "is-symbol": { @@ -6703,8 +6702,8 @@ "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", "requires": { - "node-fetch": "^1.0.1", - "whatwg-fetch": ">=0.10.0" + "node-fetch": "1.7.3", + "whatwg-fetch": "2.0.4" } }, "isstream": { @@ -6719,18 +6718,18 @@ "integrity": "sha512-duj6AlLcsWNwUpfyfHt0nWIeRiZpuShnP40YTxOGQgtaN8fd6JYSxsvxUphTDy8V5MfDXo4s/xVCIIvVCO808g==", "dev": true, "requires": { - "async": "^2.1.4", - "compare-versions": "^3.1.0", - "fileset": "^2.0.2", - "istanbul-lib-coverage": "^1.2.0", - "istanbul-lib-hook": "^1.2.0", - "istanbul-lib-instrument": "^1.10.1", - "istanbul-lib-report": "^1.1.4", - "istanbul-lib-source-maps": "^1.2.4", - "istanbul-reports": "^1.3.0", - "js-yaml": "^3.7.0", - "mkdirp": "^0.5.1", - "once": "^1.4.0" + "async": "2.6.0", + "compare-versions": "3.1.0", + "fileset": "2.0.3", + "istanbul-lib-coverage": "1.2.0", + "istanbul-lib-hook": "1.2.0", + "istanbul-lib-instrument": "1.10.1", + "istanbul-lib-report": "1.1.4", + "istanbul-lib-source-maps": "1.2.4", + "istanbul-reports": "1.3.0", + "js-yaml": "3.11.0", + "mkdirp": "0.5.1", + "once": "1.4.0" }, "dependencies": { "debug": { @@ -6748,11 +6747,11 @@ "integrity": "sha512-UzuK0g1wyQijiaYQxj/CdNycFhAd2TLtO2obKQMTZrZ1jzEMRY3rvpASEKkaxbRR6brvdovfA03znPa/pXcejg==", "dev": true, "requires": { - "debug": "^3.1.0", - "istanbul-lib-coverage": "^1.2.0", - "mkdirp": "^0.5.1", - "rimraf": "^2.6.1", - "source-map": "^0.5.3" + "debug": "3.1.0", + "istanbul-lib-coverage": "1.2.0", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "source-map": "0.5.7" } } } @@ -6768,7 +6767,7 @@ "integrity": "sha512-p3En6/oGkFQV55Up8ZPC2oLxvgSxD8CzA0yBrhRZSh3pfv3OFj9aSGVC0yoerAi/O4u7jUVnOGVX1eVFM+0tmQ==", "dev": true, "requires": { - "append-transform": "^0.4.0" + "append-transform": "0.4.0" } }, "istanbul-lib-instrument": { @@ -6776,13 +6775,13 @@ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.1.tgz", "integrity": "sha512-1dYuzkOCbuR5GRJqySuZdsmsNKPL3PTuyPevQfoCXJePT9C8y1ga75neU+Tuy9+yS3G/dgx8wgOmp2KLpgdoeQ==", "requires": { - "babel-generator": "^6.18.0", - "babel-template": "^6.16.0", - "babel-traverse": "^6.18.0", - "babel-types": "^6.18.0", - "babylon": "^6.18.0", - "istanbul-lib-coverage": "^1.2.0", - "semver": "^5.3.0" + "babel-generator": "6.26.1", + "babel-template": "6.26.0", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "istanbul-lib-coverage": "1.2.0", + "semver": "5.5.0" } }, "istanbul-lib-report": { @@ -6791,10 +6790,10 @@ "integrity": "sha512-Azqvq5tT0U09nrncK3q82e/Zjkxa4tkFZv7E6VcqP0QCPn6oNljDPfrZEC/umNXds2t7b8sRJfs6Kmpzt8m2kA==", "dev": true, "requires": { - "istanbul-lib-coverage": "^1.2.0", - "mkdirp": "^0.5.1", - "path-parse": "^1.0.5", - "supports-color": "^3.1.2" + "istanbul-lib-coverage": "1.2.0", + "mkdirp": "0.5.1", + "path-parse": "1.0.5", + "supports-color": "3.2.3" }, "dependencies": { "has-flag": { @@ -6809,7 +6808,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -6820,11 +6819,11 @@ "integrity": "sha512-fDa0hwU/5sDXwAklXgAoCJCOsFsBplVQ6WBldz5UwaqOzmDhUK4nfuR7/G//G2lERlblUNJB8P6e8cXq3a7MlA==", "dev": true, "requires": { - "debug": "^3.1.0", - "istanbul-lib-coverage": "^1.1.2", - "mkdirp": "^0.5.1", - "rimraf": "^2.6.1", - "source-map": "^0.5.3" + "debug": "3.1.0", + "istanbul-lib-coverage": "1.2.0", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "source-map": "0.5.7" }, "dependencies": { "debug": { @@ -6844,7 +6843,7 @@ "integrity": "sha512-y2Z2IMqE1gefWUaVjrBm0mSKvUkaBy9Vqz8iwr/r40Y9hBbIteH5wqHG/9DLTfJ9xUnUT2j7A3+VVJ6EaYBllA==", "dev": true, "requires": { - "handlebars": "^4.0.3" + "handlebars": "4.0.11" } }, "istextorbinary": { @@ -6853,9 +6852,9 @@ "integrity": "sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw==", "dev": true, "requires": { - "binaryextensions": "2", - "editions": "^1.3.3", - "textextensions": "2" + "binaryextensions": "2.1.1", + "editions": "1.3.4", + "textextensions": "2.2.0" } }, "isurl": { @@ -6864,8 +6863,8 @@ "integrity": "sha512-1P/yWsxPlDtn7QeRD+ULKQPaIaN6yF368GZ2vDfv0AL0NwpStafjWCDDdn0k8wgFMWpVAqG7oJhxHnlud42i9w==", "dev": true, "requires": { - "has-to-string-tag-x": "^1.2.0", - "is-object": "^1.0.1" + "has-to-string-tag-x": "1.4.1", + "is-object": "1.0.1" } }, "jed": { @@ -6879,8 +6878,8 @@ "integrity": "sha512-FFCdU/pXOEASfHxFDOWUysI/+FFoqiXJADEIXgDKuZyqSmBD3tZ4BEGH7+M79v7czj7bbkhwtd2LaEDcJiM/GQ==", "dev": true, "requires": { - "import-local": "^1.0.0", - "jest-cli": "^22.4.3" + "import-local": "1.0.0", + "jest-cli": "22.4.3" }, "dependencies": { "arr-diff": { @@ -6889,7 +6888,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "^1.0.1" + "arr-flatten": "1.1.0" } }, "array-unique": { @@ -6904,9 +6903,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" } }, "expand-brackets": { @@ -6915,7 +6914,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "^0.1.0" + "is-posix-bracket": "0.1.1" } }, "extglob": { @@ -6924,7 +6923,7 @@ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } }, "jest-cli": { @@ -6933,40 +6932,40 @@ "integrity": "sha512-IiHybF0DJNqZPsbjn4Cy4vcqcmImpoFwNFnkehzVw8lTUSl4axZh5DHewu5bdpZF2Y5gUqFKYzH0FH4Qx2k+UA==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.1", - "exit": "^0.1.2", - "glob": "^7.1.2", - "graceful-fs": "^4.1.11", - "import-local": "^1.0.0", - "is-ci": "^1.0.10", - "istanbul-api": "^1.1.14", - "istanbul-lib-coverage": "^1.1.1", - "istanbul-lib-instrument": "^1.8.0", - "istanbul-lib-source-maps": "^1.2.1", - "jest-changed-files": "^22.4.3", - "jest-config": "^22.4.3", - "jest-environment-jsdom": "^22.4.3", - "jest-get-type": "^22.4.3", - "jest-haste-map": "^22.4.3", - "jest-message-util": "^22.4.3", - "jest-regex-util": "^22.4.3", - "jest-resolve-dependencies": "^22.4.3", - "jest-runner": "^22.4.3", - "jest-runtime": "^22.4.3", - "jest-snapshot": "^22.4.3", - "jest-util": "^22.4.3", - "jest-validate": "^22.4.3", - "jest-worker": "^22.4.3", - "micromatch": "^2.3.11", - "node-notifier": "^5.2.1", - "realpath-native": "^1.0.0", - "rimraf": "^2.5.4", - "slash": "^1.0.0", - "string-length": "^2.0.0", - "strip-ansi": "^4.0.0", - "which": "^1.2.12", - "yargs": "^10.0.3" + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "exit": "0.1.2", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "import-local": "1.0.0", + "is-ci": "1.1.0", + "istanbul-api": "1.3.1", + "istanbul-lib-coverage": "1.2.0", + "istanbul-lib-instrument": "1.10.1", + "istanbul-lib-source-maps": "1.2.3", + "jest-changed-files": "22.4.3", + "jest-config": "22.4.3", + "jest-environment-jsdom": "22.4.3", + "jest-get-type": "22.4.3", + "jest-haste-map": "22.4.3", + "jest-message-util": "22.4.3", + "jest-regex-util": "22.4.3", + "jest-resolve-dependencies": "22.4.3", + "jest-runner": "22.4.3", + "jest-runtime": "22.4.3", + "jest-snapshot": "22.4.3", + "jest-util": "22.4.3", + "jest-validate": "22.4.3", + "jest-worker": "22.4.3", + "micromatch": "2.3.11", + "node-notifier": "5.2.1", + "realpath-native": "1.0.0", + "rimraf": "2.6.2", + "slash": "1.0.0", + "string-length": "2.0.0", + "strip-ansi": "4.0.0", + "which": "1.3.0", + "yargs": "10.1.2" } }, "kind-of": { @@ -6975,7 +6974,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } }, "micromatch": { @@ -6984,19 +6983,19 @@ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" } }, "strip-ansi": { @@ -7005,7 +7004,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } } } @@ -7016,7 +7015,7 @@ "integrity": "sha512-83Dh0w1aSkUNFhy5d2dvqWxi/y6weDwVVLU6vmK0cV9VpRxPzhTeGimbsbRDSnEoszhF937M4sDLLeS7Cu/Tmw==", "dev": true, "requires": { - "throat": "^4.0.0" + "throat": "4.1.0" } }, "jest-config": { @@ -7025,17 +7024,17 @@ "integrity": "sha512-KSg3EOToCgkX+lIvenKY7J8s426h6ahXxaUFJxvGoEk0562Z6inWj1TnKoGycTASwiLD+6kSYFALcjdosq9KIQ==", "dev": true, "requires": { - "chalk": "^2.0.1", - "glob": "^7.1.1", - "jest-environment-jsdom": "^22.4.3", - "jest-environment-node": "^22.4.3", - "jest-get-type": "^22.4.3", - "jest-jasmine2": "^22.4.3", - "jest-regex-util": "^22.4.3", - "jest-resolve": "^22.4.3", - "jest-util": "^22.4.3", - "jest-validate": "^22.4.3", - "pretty-format": "^22.4.3" + "chalk": "2.4.1", + "glob": "7.1.2", + "jest-environment-jsdom": "22.4.3", + "jest-environment-node": "22.4.3", + "jest-get-type": "22.4.3", + "jest-jasmine2": "22.4.3", + "jest-regex-util": "22.4.3", + "jest-resolve": "22.4.3", + "jest-util": "22.4.3", + "jest-validate": "22.4.3", + "pretty-format": "22.4.3" }, "dependencies": { "pretty-format": { @@ -7044,8 +7043,8 @@ "integrity": "sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ==", "dev": true, "requires": { - "ansi-regex": "^3.0.0", - "ansi-styles": "^3.2.0" + "ansi-regex": "3.0.0", + "ansi-styles": "3.2.1" } } } @@ -7056,10 +7055,10 @@ "integrity": "sha512-/QqGvCDP5oZOF6PebDuLwrB2BMD8ffJv6TAGAdEVuDx1+uEgrHpSFrfrOiMRx2eJ1hgNjlQrOQEHetVwij90KA==", "dev": true, "requires": { - "chalk": "^2.0.1", - "diff": "^3.2.0", - "jest-get-type": "^22.4.3", - "pretty-format": "^22.4.3" + "chalk": "2.4.1", + "diff": "3.5.0", + "jest-get-type": "22.4.3", + "pretty-format": "22.4.3" }, "dependencies": { "pretty-format": { @@ -7068,8 +7067,8 @@ "integrity": "sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ==", "dev": true, "requires": { - "ansi-regex": "^3.0.0", - "ansi-styles": "^3.2.0" + "ansi-regex": "3.0.0", + "ansi-styles": "3.2.1" } } } @@ -7080,7 +7079,7 @@ "integrity": "sha512-uPKBEAw7YrEMcXueMKZXn/rbMxBiSv48fSqy3uEnmgOlQhSX+lthBqHb1fKWNVmFqAp9E/RsSdBfiV31LbzaOg==", "dev": true, "requires": { - "detect-newline": "^2.1.0" + "detect-newline": "2.1.0" } }, "jest-environment-jsdom": { @@ -7089,9 +7088,9 @@ "integrity": "sha512-FviwfR+VyT3Datf13+ULjIMO5CSeajlayhhYQwpzgunswoaLIPutdbrnfUHEMyJCwvqQFaVtTmn9+Y8WCt6n1w==", "dev": true, "requires": { - "jest-mock": "^22.4.3", - "jest-util": "^22.4.3", - "jsdom": "^11.5.1" + "jest-mock": "22.4.3", + "jest-util": "22.4.3", + "jsdom": "11.9.0" } }, "jest-environment-node": { @@ -7100,8 +7099,8 @@ "integrity": "sha512-reZl8XF6t/lMEuPWwo9OLfttyC26A5AMgDyEQ6DBgZuyfyeNUzYT8BFo6uxCCP/Av/b7eb9fTi3sIHFPBzmlRA==", "dev": true, "requires": { - "jest-mock": "^22.4.3", - "jest-util": "^22.4.3" + "jest-mock": "22.4.3", + "jest-util": "22.4.3" } }, "jest-enzyme": { @@ -7109,8 +7108,8 @@ "resolved": "https://registry.npmjs.org/jest-enzyme/-/jest-enzyme-4.2.0.tgz", "integrity": "sha512-nna99NnU6sDbWqVX0153c81RUuxI/spTgw4Xobh049NcKihu0OAtAawbuSzZUnlCqdZOoXlKMudfjUPm0sCTsg==", "requires": { - "enzyme-matchers": "^4.2.0", - "enzyme-to-json": "^3.3.0" + "enzyme-matchers": "4.2.0", + "enzyme-to-json": "3.3.3" } }, "jest-get-type": { @@ -7124,13 +7123,13 @@ "integrity": "sha512-4Q9fjzuPVwnaqGKDpIsCSoTSnG3cteyk2oNVjBX12HHOaF1oxql+uUiqZb5Ndu7g/vTZfdNwwy4WwYogLh29DQ==", "dev": true, "requires": { - "fb-watchman": "^2.0.0", - "graceful-fs": "^4.1.11", - "jest-docblock": "^22.4.3", - "jest-serializer": "^22.4.3", - "jest-worker": "^22.4.3", - "micromatch": "^2.3.11", - "sane": "^2.0.0" + "fb-watchman": "2.0.0", + "graceful-fs": "4.1.11", + "jest-docblock": "22.4.3", + "jest-serializer": "22.4.3", + "jest-worker": "22.4.3", + "micromatch": "2.3.11", + "sane": "2.5.0" }, "dependencies": { "arr-diff": { @@ -7139,7 +7138,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "^1.0.1" + "arr-flatten": "1.1.0" } }, "array-unique": { @@ -7154,9 +7153,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" } }, "expand-brackets": { @@ -7165,7 +7164,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "^0.1.0" + "is-posix-bracket": "0.1.1" } }, "extglob": { @@ -7174,7 +7173,7 @@ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } }, "kind-of": { @@ -7183,7 +7182,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } }, "micromatch": { @@ -7192,19 +7191,19 @@ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" } } } @@ -7215,17 +7214,17 @@ "integrity": "sha512-yZCPCJUcEY6R5KJB/VReo1AYI2b+5Ky+C+JA1v34jndJsRcLpU4IZX4rFJn7yDTtdNbO/nNqg+3SDIPNH2ecnw==", "dev": true, "requires": { - "chalk": "^2.0.1", - "co": "^4.6.0", - "expect": "^22.4.3", - "graceful-fs": "^4.1.11", - "is-generator-fn": "^1.0.0", - "jest-diff": "^22.4.3", - "jest-matcher-utils": "^22.4.3", - "jest-message-util": "^22.4.3", - "jest-snapshot": "^22.4.3", - "jest-util": "^22.4.3", - "source-map-support": "^0.5.0" + "chalk": "2.4.1", + "co": "4.6.0", + "expect": "22.4.3", + "graceful-fs": "4.1.11", + "is-generator-fn": "1.0.0", + "jest-diff": "22.4.3", + "jest-matcher-utils": "22.4.3", + "jest-message-util": "22.4.3", + "jest-snapshot": "22.4.3", + "jest-util": "22.4.3", + "source-map-support": "0.5.5" } }, "jest-leak-detector": { @@ -7234,7 +7233,7 @@ "integrity": "sha512-NZpR/Ls7+ndO57LuXROdgCGz2RmUdC541tTImL9bdUtU3WadgFGm0yV+Ok4Fuia/1rLAn5KaJ+i76L6e3zGJYQ==", "dev": true, "requires": { - "pretty-format": "^22.4.3" + "pretty-format": "22.4.3" }, "dependencies": { "pretty-format": { @@ -7243,8 +7242,8 @@ "integrity": "sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ==", "dev": true, "requires": { - "ansi-regex": "^3.0.0", - "ansi-styles": "^3.2.0" + "ansi-regex": "3.0.0", + "ansi-styles": "3.2.1" } } } @@ -7254,9 +7253,9 @@ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-22.4.3.tgz", "integrity": "sha512-lsEHVaTnKzdAPR5t4B6OcxXo9Vy4K+kRRbG5gtddY8lBEC+Mlpvm1CJcsMESRjzUhzkz568exMV1hTB76nAKbA==", "requires": { - "chalk": "^2.0.1", - "jest-get-type": "^22.4.3", - "pretty-format": "^22.4.3" + "chalk": "2.4.1", + "jest-get-type": "22.4.3", + "pretty-format": "22.4.3" }, "dependencies": { "pretty-format": { @@ -7264,8 +7263,8 @@ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-22.4.3.tgz", "integrity": "sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ==", "requires": { - "ansi-regex": "^3.0.0", - "ansi-styles": "^3.2.0" + "ansi-regex": "3.0.0", + "ansi-styles": "3.2.1" } } } @@ -7276,11 +7275,11 @@ "integrity": "sha512-iAMeKxhB3Se5xkSjU0NndLLCHtP4n+GtCqV0bISKA5dmOXQfEbdEmYiu2qpnWBDCQdEafNDDU6Q+l6oBMd/+BA==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0-beta.35", - "chalk": "^2.0.1", - "micromatch": "^2.3.11", - "slash": "^1.0.0", - "stack-utils": "^1.0.1" + "@babel/code-frame": "7.0.0-beta.46", + "chalk": "2.4.1", + "micromatch": "2.3.11", + "slash": "1.0.0", + "stack-utils": "1.0.1" }, "dependencies": { "arr-diff": { @@ -7289,7 +7288,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "^1.0.1" + "arr-flatten": "1.1.0" } }, "array-unique": { @@ -7304,9 +7303,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" } }, "expand-brackets": { @@ -7315,7 +7314,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "^0.1.0" + "is-posix-bracket": "0.1.1" } }, "extglob": { @@ -7324,7 +7323,7 @@ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } }, "kind-of": { @@ -7333,7 +7332,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } }, "micromatch": { @@ -7342,19 +7341,19 @@ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" } } } @@ -7377,8 +7376,8 @@ "integrity": "sha512-u3BkD/MQBmwrOJDzDIaxpyqTxYH+XqAXzVJP51gt29H8jpj3QgKof5GGO2uPGKGeA1yTMlpbMs1gIQ6U4vcRhw==", "dev": true, "requires": { - "browser-resolve": "^1.11.2", - "chalk": "^2.0.1" + "browser-resolve": "1.11.2", + "chalk": "2.4.1" } }, "jest-resolve-dependencies": { @@ -7387,7 +7386,7 @@ "integrity": "sha512-06czCMVToSN8F2U4EvgSB1Bv/56gc7MpCftZ9z9fBgUQM7dzHGCMBsyfVA6dZTx8v0FDcnALf7hupeQxaBCvpA==", "dev": true, "requires": { - "jest-regex-util": "^22.4.3" + "jest-regex-util": "22.4.3" } }, "jest-runner": { @@ -7396,17 +7395,17 @@ "integrity": "sha512-U7PLlQPRlWNbvOHWOrrVay9sqhBJmiKeAdKIkvX4n1G2tsvzLlf77nBD28GL1N6tGv4RmuTfI8R8JrkvCa+IBg==", "dev": true, "requires": { - "exit": "^0.1.2", - "jest-config": "^22.4.3", - "jest-docblock": "^22.4.3", - "jest-haste-map": "^22.4.3", - "jest-jasmine2": "^22.4.3", - "jest-leak-detector": "^22.4.3", - "jest-message-util": "^22.4.3", - "jest-runtime": "^22.4.3", - "jest-util": "^22.4.3", - "jest-worker": "^22.4.3", - "throat": "^4.0.0" + "exit": "0.1.2", + "jest-config": "22.4.3", + "jest-docblock": "22.4.3", + "jest-haste-map": "22.4.3", + "jest-jasmine2": "22.4.3", + "jest-leak-detector": "22.4.3", + "jest-message-util": "22.4.3", + "jest-runtime": "22.4.3", + "jest-util": "22.4.3", + "jest-worker": "22.4.3", + "throat": "4.1.0" } }, "jest-runtime": { @@ -7415,26 +7414,26 @@ "integrity": "sha512-Eat/esQjevhx9BgJEC8udye+FfoJ2qvxAZfOAWshYGS22HydHn5BgsvPdTtt9cp0fSl5LxYOFA1Pja9Iz2Zt8g==", "dev": true, "requires": { - "babel-core": "^6.0.0", - "babel-jest": "^22.4.3", - "babel-plugin-istanbul": "^4.1.5", - "chalk": "^2.0.1", - "convert-source-map": "^1.4.0", - "exit": "^0.1.2", - "graceful-fs": "^4.1.11", - "jest-config": "^22.4.3", - "jest-haste-map": "^22.4.3", - "jest-regex-util": "^22.4.3", - "jest-resolve": "^22.4.3", - "jest-util": "^22.4.3", - "jest-validate": "^22.4.3", - "json-stable-stringify": "^1.0.1", - "micromatch": "^2.3.11", - "realpath-native": "^1.0.0", - "slash": "^1.0.0", + "babel-core": "6.26.3", + "babel-jest": "22.4.3", + "babel-plugin-istanbul": "4.1.6", + "chalk": "2.4.1", + "convert-source-map": "1.5.1", + "exit": "0.1.2", + "graceful-fs": "4.1.11", + "jest-config": "22.4.3", + "jest-haste-map": "22.4.3", + "jest-regex-util": "22.4.3", + "jest-resolve": "22.4.3", + "jest-util": "22.4.3", + "jest-validate": "22.4.3", + "json-stable-stringify": "1.0.1", + "micromatch": "2.3.11", + "realpath-native": "1.0.0", + "slash": "1.0.0", "strip-bom": "3.0.0", - "write-file-atomic": "^2.1.0", - "yargs": "^10.0.3" + "write-file-atomic": "2.3.0", + "yargs": "10.1.2" }, "dependencies": { "arr-diff": { @@ -7443,7 +7442,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "^1.0.1" + "arr-flatten": "1.1.0" } }, "array-unique": { @@ -7458,9 +7457,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" } }, "expand-brackets": { @@ -7469,7 +7468,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "^0.1.0" + "is-posix-bracket": "0.1.1" } }, "extglob": { @@ -7478,7 +7477,7 @@ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } }, "kind-of": { @@ -7487,7 +7486,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } }, "micromatch": { @@ -7496,19 +7495,19 @@ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" } }, "strip-bom": { @@ -7531,12 +7530,12 @@ "integrity": "sha512-JXA0gVs5YL0HtLDCGa9YxcmmV2LZbwJ+0MfyXBBc5qpgkEYITQFJP7XNhcHFbUvRiniRpRbGVfJrOoYhhGE0RQ==", "dev": true, "requires": { - "chalk": "^2.0.1", - "jest-diff": "^22.4.3", - "jest-matcher-utils": "^22.4.3", - "mkdirp": "^0.5.1", - "natural-compare": "^1.4.0", - "pretty-format": "^22.4.3" + "chalk": "2.4.1", + "jest-diff": "22.4.3", + "jest-matcher-utils": "22.4.3", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "pretty-format": "22.4.3" }, "dependencies": { "pretty-format": { @@ -7545,8 +7544,8 @@ "integrity": "sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ==", "dev": true, "requires": { - "ansi-regex": "^3.0.0", - "ansi-styles": "^3.2.0" + "ansi-regex": "3.0.0", + "ansi-styles": "3.2.1" } } } @@ -7557,13 +7556,13 @@ "integrity": "sha512-rfDfG8wyC5pDPNdcnAlZgwKnzHvZDu8Td2NJI/jAGKEGxJPYiE4F0ss/gSAkG4778Y23Hvbz+0GMrDJTeo7RjQ==", "dev": true, "requires": { - "callsites": "^2.0.0", - "chalk": "^2.0.1", - "graceful-fs": "^4.1.11", - "is-ci": "^1.0.10", - "jest-message-util": "^22.4.3", - "mkdirp": "^0.5.1", - "source-map": "^0.6.0" + "callsites": "2.0.0", + "chalk": "2.4.1", + "graceful-fs": "4.1.11", + "is-ci": "1.1.0", + "jest-message-util": "22.4.3", + "mkdirp": "0.5.1", + "source-map": "0.6.1" }, "dependencies": { "source-map": { @@ -7580,11 +7579,11 @@ "integrity": "sha512-CfFM18W3GSP/xgmA4UouIx0ljdtfD2mjeBC6c89Gg17E44D4tQhAcTrZmf9djvipwU30kSTnk6CzcxdCCeSXfA==", "dev": true, "requires": { - "chalk": "^2.0.1", - "jest-config": "^22.4.3", - "jest-get-type": "^22.4.3", - "leven": "^2.1.0", - "pretty-format": "^22.4.3" + "chalk": "2.4.1", + "jest-config": "22.4.3", + "jest-get-type": "22.4.3", + "leven": "2.1.0", + "pretty-format": "22.4.3" }, "dependencies": { "pretty-format": { @@ -7593,8 +7592,8 @@ "integrity": "sha512-S4oT9/sT6MN7/3COoOy+ZJeA92VmOnveLHgrwBE3Z1W5N9S2A1QGNYiE1z75DAENbJrXXUb+OWXhpJcg05QKQQ==", "dev": true, "requires": { - "ansi-regex": "^3.0.0", - "ansi-styles": "^3.2.0" + "ansi-regex": "3.0.0", + "ansi-styles": "3.2.1" } } } @@ -7605,7 +7604,7 @@ "integrity": "sha512-B1ucW4fI8qVAuZmicFxI1R3kr2fNeYJyvIQ1rKcuLYnenFV5K5aMbxFj6J0i00Ju83S8jP2d7Dz14+AvbIHRYQ==", "dev": true, "requires": { - "merge-stream": "^1.0.1" + "merge-stream": "1.0.1" } }, "js-base64": { @@ -7625,8 +7624,8 @@ "integrity": "sha512-saJstZWv7oNeOyBh3+Dx1qWzhW0+e6/8eDzo7p5rDFqxntSztloLtuKu+Ejhtq82jsilwOIZYsCz+lIjthg1Hw==", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" + "argparse": "1.0.10", + "esprima": "4.0.0" } }, "jsbn": { @@ -7642,21 +7641,21 @@ "integrity": "sha512-JAcQINNMFpdzzpKJN8k5xXjF3XDuckB1/48uScSzcnNyK199iWEc9AxKL9OoX5144M2w5zEx9Qs4/E/eBZZUlw==", "dev": true, "requires": { - "babel-plugin-transform-flow-strip-types": "^6.8.0", - "babel-preset-es2015": "^6.9.0", - "babel-preset-stage-1": "^6.5.0", - "babel-register": "^6.9.0", - "babylon": "^7.0.0-beta.30", - "colors": "^1.1.2", - "flow-parser": "^0.*", - "lodash": "^4.13.1", - "micromatch": "^2.3.7", - "neo-async": "^2.5.0", + "babel-plugin-transform-flow-strip-types": "6.22.0", + "babel-preset-es2015": "6.24.1", + "babel-preset-stage-1": "6.24.1", + "babel-register": "6.26.0", + "babylon": "7.0.0-beta.47", + "colors": "1.2.5", + "flow-parser": "0.72.0", + "lodash": "4.17.10", + "micromatch": "2.3.11", + "neo-async": "2.5.1", "node-dir": "0.1.8", - "nomnom": "^1.8.1", - "recast": "^0.14.1", - "temp": "^0.8.1", - "write-file-atomic": "^1.2.0" + "nomnom": "1.8.1", + "recast": "0.14.7", + "temp": "0.8.3", + "write-file-atomic": "1.3.4" }, "dependencies": { "ansi-styles": { @@ -7671,7 +7670,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "^1.0.1" + "arr-flatten": "1.1.0" } }, "array-unique": { @@ -7692,9 +7691,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" } }, "chalk": { @@ -7703,9 +7702,9 @@ "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", "dev": true, "requires": { - "ansi-styles": "~1.0.0", - "has-color": "~0.1.0", - "strip-ansi": "~0.1.0" + "ansi-styles": "1.0.0", + "has-color": "0.1.7", + "strip-ansi": "0.1.1" } }, "colors": { @@ -7720,7 +7719,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "^0.1.0" + "is-posix-bracket": "0.1.1" } }, "extglob": { @@ -7729,7 +7728,7 @@ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } }, "kind-of": { @@ -7738,7 +7737,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } }, "micromatch": { @@ -7747,19 +7746,19 @@ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" } }, "nomnom": { @@ -7768,8 +7767,8 @@ "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", "dev": true, "requires": { - "chalk": "~0.4.0", - "underscore": "~1.6.0" + "chalk": "0.4.0", + "underscore": "1.6.0" } }, "strip-ansi": { @@ -7790,9 +7789,9 @@ "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", "dev": true, "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "slide": "^1.1.5" + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "slide": "1.1.6" } } } @@ -7803,32 +7802,32 @@ "integrity": "sha512-sb3omwJTJ+HwAltLZevM/KQBusY+l2Ar5UfnTCWk9oUVBiDnQPBNiG1BaTAKttCnneonYbNo7vi4EFDY2lBfNA==", "dev": true, "requires": { - "abab": "^1.0.4", - "acorn": "^5.3.0", - "acorn-globals": "^4.1.0", - "array-equal": "^1.0.0", - "cssom": ">= 0.3.2 < 0.4.0", - "cssstyle": ">= 0.2.37 < 0.3.0", - "data-urls": "^1.0.0", - "domexception": "^1.0.0", - "escodegen": "^1.9.0", - "html-encoding-sniffer": "^1.0.2", - "left-pad": "^1.2.0", - "nwmatcher": "^1.4.3", + "abab": "1.0.4", + "acorn": "5.5.3", + "acorn-globals": "4.1.0", + "array-equal": "1.0.0", + "cssom": "0.3.2", + "cssstyle": "0.2.37", + "data-urls": "1.0.0", + "domexception": "1.0.1", + "escodegen": "1.9.1", + "html-encoding-sniffer": "1.0.2", + "left-pad": "1.3.0", + "nwmatcher": "1.4.4", "parse5": "4.0.0", - "pn": "^1.1.0", - "request": "^2.83.0", - "request-promise-native": "^1.0.5", - "sax": "^1.2.4", - "symbol-tree": "^3.2.2", - "tough-cookie": "^2.3.3", - "w3c-hr-time": "^1.0.1", - "webidl-conversions": "^4.0.2", - "whatwg-encoding": "^1.0.3", - "whatwg-mimetype": "^2.1.0", - "whatwg-url": "^6.4.0", - "ws": "^4.0.0", - "xml-name-validator": "^3.0.0" + "pn": "1.1.0", + "request": "2.85.0", + "request-promise-native": "1.0.5", + "sax": "1.2.4", + "symbol-tree": "3.2.2", + "tough-cookie": "2.3.4", + "w3c-hr-time": "1.0.1", + "webidl-conversions": "4.0.2", + "whatwg-encoding": "1.0.3", + "whatwg-mimetype": "2.1.0", + "whatwg-url": "6.4.1", + "ws": "4.1.0", + "xml-name-validator": "3.0.0" }, "dependencies": { "parse5": { @@ -7874,7 +7873,7 @@ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", "dev": true, "requires": { - "jsonify": "~0.0.0" + "jsonify": "0.0.0" } }, "json-stable-stringify-without-jsonify": { @@ -7919,7 +7918,7 @@ "integrity": "sha1-6AGxs5mF4g//yHtA43SAgOLcrH8=", "dev": true, "requires": { - "array-includes": "^3.0.3" + "array-includes": "3.0.3" } }, "keyv": { @@ -7949,7 +7948,7 @@ "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", "dev": true, "requires": { - "invert-kv": "^1.0.0" + "invert-kv": "1.0.0" } }, "leb": { @@ -7976,8 +7975,8 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "prelude-ls": "1.1.2", + "type-check": "0.3.2" } }, "listr": { @@ -7986,23 +7985,23 @@ "integrity": "sha1-ILsLowuuZg7oTMBQPfS+PVYjiH0=", "dev": true, "requires": { - "chalk": "^1.1.3", - "cli-truncate": "^0.2.1", - "figures": "^1.7.0", - "indent-string": "^2.1.0", - "is-observable": "^0.2.0", - "is-promise": "^2.1.0", - "is-stream": "^1.1.0", - "listr-silent-renderer": "^1.1.1", - "listr-update-renderer": "^0.4.0", - "listr-verbose-renderer": "^0.4.0", - "log-symbols": "^1.0.2", - "log-update": "^1.0.2", - "ora": "^0.2.3", - "p-map": "^1.1.1", - "rxjs": "^5.4.2", - "stream-to-observable": "^0.2.0", - "strip-ansi": "^3.0.1" + "chalk": "1.1.3", + "cli-truncate": "0.2.1", + "figures": "1.7.0", + "indent-string": "2.1.0", + "is-observable": "0.2.0", + "is-promise": "2.1.0", + "is-stream": "1.1.0", + "listr-silent-renderer": "1.1.1", + "listr-update-renderer": "0.4.0", + "listr-verbose-renderer": "0.4.1", + "log-symbols": "1.0.2", + "log-update": "1.0.2", + "ora": "0.2.3", + "p-map": "1.2.0", + "rxjs": "5.5.10", + "stream-to-observable": "0.2.0", + "strip-ansi": "3.0.1" }, "dependencies": { "ansi-styles": { @@ -8017,11 +8016,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" } }, "figures": { @@ -8030,8 +8029,8 @@ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" } }, "log-symbols": { @@ -8040,7 +8039,7 @@ "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", "dev": true, "requires": { - "chalk": "^1.0.0" + "chalk": "1.1.3" } }, "supports-color": { @@ -8063,14 +8062,14 @@ "integrity": "sha1-NE2YDaLKLosUW6MFkI8yrj9MyKc=", "dev": true, "requires": { - "chalk": "^1.1.3", - "cli-truncate": "^0.2.1", - "elegant-spinner": "^1.0.1", - "figures": "^1.7.0", - "indent-string": "^3.0.0", - "log-symbols": "^1.0.2", - "log-update": "^1.0.2", - "strip-ansi": "^3.0.1" + "chalk": "1.1.3", + "cli-truncate": "0.2.1", + "elegant-spinner": "1.0.1", + "figures": "1.7.0", + "indent-string": "3.2.0", + "log-symbols": "1.0.2", + "log-update": "1.0.2", + "strip-ansi": "3.0.1" }, "dependencies": { "ansi-styles": { @@ -8085,11 +8084,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" } }, "figures": { @@ -8098,8 +8097,8 @@ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" } }, "indent-string": { @@ -8114,7 +8113,7 @@ "integrity": "sha1-N2/3tY6jCGoPCfrMdGF+ylAeGhg=", "dev": true, "requires": { - "chalk": "^1.0.0" + "chalk": "1.1.3" } }, "supports-color": { @@ -8131,10 +8130,10 @@ "integrity": "sha1-ggb0z21S3cWCfl/RSYng6WWTOjU=", "dev": true, "requires": { - "chalk": "^1.1.3", - "cli-cursor": "^1.0.2", - "date-fns": "^1.27.2", - "figures": "^1.7.0" + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "date-fns": "1.29.0", + "figures": "1.7.0" }, "dependencies": { "ansi-styles": { @@ -8149,11 +8148,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" } }, "cli-cursor": { @@ -8162,7 +8161,7 @@ "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", "dev": true, "requires": { - "restore-cursor": "^1.0.1" + "restore-cursor": "1.0.1" } }, "figures": { @@ -8171,8 +8170,8 @@ "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", "dev": true, "requires": { - "escape-string-regexp": "^1.0.5", - "object-assign": "^4.1.0" + "escape-string-regexp": "1.0.5", + "object-assign": "4.1.1" } }, "onetime": { @@ -8187,8 +8186,8 @@ "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", "dev": true, "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" + "exit-hook": "1.1.1", + "onetime": "1.1.0" } }, "supports-color": { @@ -8204,11 +8203,11 @@ "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" } }, "loader-runner": { @@ -8223,9 +8222,9 @@ "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", "dev": true, "requires": { - "big.js": "^3.1.3", - "emojis-list": "^2.0.0", - "json5": "^0.5.0" + "big.js": "3.2.0", + "emojis-list": "2.1.0", + "json5": "0.5.1" } }, "locate-path": { @@ -8233,8 +8232,8 @@ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "p-locate": "2.0.0", + "path-exists": "3.0.0" } }, "lodash": { @@ -8252,9 +8251,9 @@ "resolved": "https://registry.npmjs.org/lodash._baseisequal/-/lodash._baseisequal-3.0.7.tgz", "integrity": "sha1-2AJfdjOdKTQnZ9zIh85cuVpbUfE=", "requires": { - "lodash.isarray": "^3.0.0", - "lodash.istypedarray": "^3.0.0", - "lodash.keys": "^3.0.0" + "lodash.isarray": "3.0.4", + "lodash.istypedarray": "3.0.6", + "lodash.keys": "3.1.2" } }, "lodash._bindcallback": { @@ -8305,8 +8304,8 @@ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-3.0.4.tgz", "integrity": "sha1-HDXrO27wzR/1F0Pj6jz3/f/ay2Q=", "requires": { - "lodash._baseisequal": "^3.0.0", - "lodash._bindcallback": "^3.0.0" + "lodash._baseisequal": "3.0.7", + "lodash._bindcallback": "3.0.1" } }, "lodash.istypedarray": { @@ -8319,9 +8318,9 @@ "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" } }, "lodash.memoize": { @@ -8348,7 +8347,7 @@ "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", "dev": true, "requires": { - "chalk": "^2.0.1" + "chalk": "2.4.1" } }, "log-update": { @@ -8357,8 +8356,8 @@ "integrity": "sha1-GZKfZMQJPS0ucHWh2tivWcKWuNE=", "dev": true, "requires": { - "ansi-escapes": "^1.0.0", - "cli-cursor": "^1.0.2" + "ansi-escapes": "1.4.0", + "cli-cursor": "1.0.2" }, "dependencies": { "ansi-escapes": { @@ -8373,7 +8372,7 @@ "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", "dev": true, "requires": { - "restore-cursor": "^1.0.1" + "restore-cursor": "1.0.1" } }, "onetime": { @@ -8388,8 +8387,8 @@ "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", "dev": true, "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" + "exit-hook": "1.1.1", + "onetime": "1.1.0" } } } @@ -8411,7 +8410,7 @@ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", "requires": { - "js-tokens": "^3.0.0" + "js-tokens": "3.0.2" } }, "lowercase-keys": { @@ -8426,8 +8425,8 @@ "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", "dev": true, "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "pseudomap": "1.0.2", + "yallist": "2.1.2" } }, "macaddress": { @@ -8442,7 +8441,7 @@ "integrity": "sha512-aNUAa4UMg/UougV25bbrU4ZaaKNjJ/3/xnvg/twpmKROPdKZPZ9wGgI0opdZzO8q/zUFawoUuixuOv33eZ61Iw==", "dev": true, "requires": { - "pify": "^3.0.0" + "pify": "3.0.0" }, "dependencies": { "pify": { @@ -8459,7 +8458,7 @@ "integrity": "sha1-4BpckQnyr3lmDk6LlYd5AYT1qWw=", "dev": true, "requires": { - "tmpl": "1.0.x" + "tmpl": "1.0.4" } }, "map-cache": { @@ -8472,7 +8471,7 @@ "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "requires": { - "object-visit": "^1.0.0" + "object-visit": "1.0.1" } }, "math-expression-evaluator": { @@ -8487,8 +8486,8 @@ "integrity": "sha1-6b296UogpawYsENA/Fdk1bCdkB0=", "dev": true, "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "hash-base": "3.0.4", + "inherits": "2.0.3" } }, "mem": { @@ -8497,7 +8496,7 @@ "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "mimic-fn": "1.2.0" } }, "mem-fs": { @@ -8506,9 +8505,9 @@ "integrity": "sha1-uK6NLj/Lb10/kWXBLUVRoGXZicw=", "dev": true, "requires": { - "through2": "^2.0.0", - "vinyl": "^1.1.0", - "vinyl-file": "^2.0.0" + "through2": "2.0.3", + "vinyl": "1.2.0", + "vinyl-file": "2.0.0" } }, "mem-fs-editor": { @@ -8517,17 +8516,17 @@ "integrity": "sha512-QHvdXLLNmwJXxKdf7x27aNUren6IoPxwcM8Sfd+S6/ddQQMcYdEtVKsh6ilpqMrU18VQuKZEaH0aCGt3JDbA0g==", "dev": true, "requires": { - "commondir": "^1.0.1", - "deep-extend": "^0.5.1", - "ejs": "^2.5.9", - "glob": "^7.0.3", - "globby": "^8.0.0", - "isbinaryfile": "^3.0.2", - "mkdirp": "^0.5.0", - "multimatch": "^2.0.0", - "rimraf": "^2.2.8", - "through2": "^2.0.0", - "vinyl": "^2.0.1" + "commondir": "1.0.1", + "deep-extend": "0.5.1", + "ejs": "2.6.1", + "glob": "7.1.2", + "globby": "8.0.1", + "isbinaryfile": "3.0.2", + "mkdirp": "0.5.1", + "multimatch": "2.1.0", + "rimraf": "2.6.2", + "through2": "2.0.3", + "vinyl": "2.1.0" }, "dependencies": { "clone": { @@ -8548,13 +8547,13 @@ "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", "dev": true, "requires": { - "array-union": "^1.0.1", - "dir-glob": "^2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" + "array-union": "1.0.2", + "dir-glob": "2.0.0", + "fast-glob": "2.2.2", + "glob": "7.1.2", + "ignore": "3.3.8", + "pify": "3.0.0", + "slash": "1.0.0" } }, "pify": { @@ -8575,12 +8574,12 @@ "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", "dev": true, "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" + "clone": "2.1.1", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.1.2", + "remove-trailing-separator": "1.1.0", + "replace-ext": "1.0.0" } } } @@ -8596,8 +8595,8 @@ "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", "dev": true, "requires": { - "errno": "^0.1.3", - "readable-stream": "^2.0.1" + "errno": "0.1.7", + "readable-stream": "2.3.6" } }, "merge": { @@ -8612,7 +8611,7 @@ "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", "dev": true, "requires": { - "readable-stream": "^2.0.1" + "readable-stream": "2.3.6" } }, "merge2": { @@ -8626,19 +8625,19 @@ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" } }, "miller-rabin": { @@ -8647,8 +8646,8 @@ "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", "dev": true, "requires": { - "bn.js": "^4.0.0", - "brorand": "^1.0.1" + "bn.js": "4.11.8", + "brorand": "1.1.0" } }, "mime-db": { @@ -8663,7 +8662,7 @@ "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", "dev": true, "requires": { - "mime-db": "~1.33.0" + "mime-db": "1.33.0" } }, "mimic-fn": { @@ -8684,8 +8683,8 @@ "integrity": "sha512-2Zik6PhUZ/MbiboG6SDS9UTPL4XXy4qnyGjSdCIWRrr8xb6PwLtHE+AYOjkXJWdF0OG8vo/yrJ8CgS5WbMpzIg==", "dev": true, "requires": { - "loader-utils": "^1.1.0", - "webpack-sources": "^1.1.0" + "loader-utils": "1.1.0", + "webpack-sources": "1.1.0" } }, "minimalistic-assert": { @@ -8706,7 +8705,7 @@ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "1.1.11" } }, "minimist": { @@ -8721,16 +8720,16 @@ "integrity": "sha512-zHo8v+otD1J10j/tC+VNoGK9keCuByhKovAvdn74dmxJl9+mWHnx6EMsDN4lgRoMI/eYo2nchAxniIbUPb5onw==", "dev": true, "requires": { - "concat-stream": "^1.5.0", - "duplexify": "^3.4.2", - "end-of-stream": "^1.1.0", - "flush-write-stream": "^1.0.0", - "from2": "^2.1.0", - "parallel-transform": "^1.1.0", - "pump": "^2.0.1", - "pumpify": "^1.3.3", - "stream-each": "^1.1.0", - "through2": "^2.0.0" + "concat-stream": "1.6.2", + "duplexify": "3.5.4", + "end-of-stream": "1.4.1", + "flush-write-stream": "1.0.3", + "from2": "2.3.0", + "parallel-transform": "1.1.0", + "pump": "2.0.1", + "pumpify": "1.4.0", + "stream-each": "1.2.2", + "through2": "2.0.3" } }, "mixin-deep": { @@ -8738,8 +8737,8 @@ "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" + "for-in": "1.0.2", + "is-extendable": "1.0.1" }, "dependencies": { "is-extendable": { @@ -8747,7 +8746,7 @@ "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "requires": { - "is-plain-object": "^2.0.4" + "is-plain-object": "2.0.4" } } } @@ -8767,12 +8766,12 @@ "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", "dev": true, "requires": { - "aproba": "^1.1.1", - "copy-concurrently": "^1.0.0", - "fs-write-stream-atomic": "^1.0.8", - "mkdirp": "^0.5.1", - "rimraf": "^2.5.4", - "run-queue": "^1.0.3" + "aproba": "1.2.0", + "copy-concurrently": "1.0.5", + "fs-write-stream-atomic": "1.0.10", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "run-queue": "1.0.3" } }, "ms": { @@ -8786,10 +8785,10 @@ "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", "dev": true, "requires": { - "array-differ": "^1.0.0", - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "minimatch": "^3.0.0" + "array-differ": "1.0.0", + "array-union": "1.0.2", + "arrify": "1.0.1", + "minimatch": "3.0.4" } }, "mute-stream": { @@ -8810,18 +8809,18 @@ "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-odd": "^2.0.0", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-odd": "2.0.0", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" } }, "natural-compare": { @@ -8835,10 +8834,10 @@ "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.13.0.tgz", "integrity": "sha512-ioYYogSaZhFlCpRizQgY3UT3G1qFXmHGY/5ozoFE3dMfiCRAeJfh+IPE3/eh9gCZvqLhPCWb4bLt7Bqzo+1mLQ==", "requires": { - "nomnom": "~1.6.2", - "railroad-diagrams": "^1.0.0", + "nomnom": "1.6.2", + "railroad-diagrams": "1.0.0", "randexp": "0.4.6", - "semver": "^5.4.1" + "semver": "5.5.0" } }, "neo-async": { @@ -8864,8 +8863,8 @@ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz", "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==", "requires": { - "encoding": "^0.1.11", - "is-stream": "^1.0.1" + "encoding": "0.1.12", + "is-stream": "1.1.0" } }, "node-int64": { @@ -8880,28 +8879,28 @@ "integrity": "sha512-5AzFzdoIMb89hBGMZglEegffzgRg+ZFoUmisQ8HI4j1KDdpx13J0taNp2y9xPbur6W61gepGDDotGBVQ7mfUCg==", "dev": true, "requires": { - "assert": "^1.1.1", - "browserify-zlib": "^0.2.0", - "buffer": "^4.3.0", - "console-browserify": "^1.1.0", - "constants-browserify": "^1.0.0", - "crypto-browserify": "^3.11.0", - "domain-browser": "^1.1.1", - "events": "^1.0.0", - "https-browserify": "^1.0.0", - "os-browserify": "^0.3.0", + "assert": "1.4.1", + "browserify-zlib": "0.2.0", + "buffer": "4.9.1", + "console-browserify": "1.1.0", + "constants-browserify": "1.0.0", + "crypto-browserify": "3.12.0", + "domain-browser": "1.2.0", + "events": "1.1.1", + "https-browserify": "1.0.0", + "os-browserify": "0.3.0", "path-browserify": "0.0.0", - "process": "^0.11.10", - "punycode": "^1.2.4", - "querystring-es3": "^0.2.0", - "readable-stream": "^2.3.3", - "stream-browserify": "^2.0.1", - "stream-http": "^2.7.2", - "string_decoder": "^1.0.0", - "timers-browserify": "^2.0.4", + "process": "0.11.10", + "punycode": "1.4.1", + "querystring-es3": "0.2.1", + "readable-stream": "2.3.6", + "stream-browserify": "2.0.1", + "stream-http": "2.8.2", + "string_decoder": "1.1.1", + "timers-browserify": "2.0.10", "tty-browserify": "0.0.0", - "url": "^0.11.0", - "util": "^0.10.3", + "url": "0.11.0", + "util": "0.10.3", "vm-browserify": "0.0.4" }, "dependencies": { @@ -8919,10 +8918,10 @@ "integrity": "sha512-MIBs+AAd6dJ2SklbbE8RUDRlIVhU8MaNLh1A9SUZDUHPiZkWLFde6UNwG41yQHZEToHgJMXqyVZ9UcS/ReOVTg==", "dev": true, "requires": { - "growly": "^1.3.0", - "semver": "^5.4.1", - "shellwords": "^0.1.1", - "which": "^1.3.0" + "growly": "1.3.0", + "semver": "5.5.0", + "shellwords": "0.1.1", + "which": "1.3.0" } }, "nomnom": { @@ -8930,8 +8929,8 @@ "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.6.2.tgz", "integrity": "sha1-hKZqJgF0QI/Ft3oY+IjszET7aXE=", "requires": { - "colors": "0.5.x", - "underscore": "~1.4.4" + "colors": "0.5.1", + "underscore": "1.4.4" } }, "normalize-package-data": { @@ -8939,10 +8938,10 @@ "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "hosted-git-info": "2.6.0", + "is-builtin-module": "1.0.0", + "semver": "5.5.0", + "validate-npm-package-license": "3.0.3" } }, "normalize-path": { @@ -8951,7 +8950,7 @@ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "^1.0.1" + "remove-trailing-separator": "1.1.0" } }, "normalize-range": { @@ -8966,10 +8965,10 @@ "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", "dev": true, "requires": { - "object-assign": "^4.0.1", - "prepend-http": "^1.0.0", - "query-string": "^4.1.0", - "sort-keys": "^1.0.0" + "object-assign": "4.1.1", + "prepend-http": "1.0.4", + "query-string": "4.3.4", + "sort-keys": "1.1.2" } }, "npm-run-path": { @@ -8978,7 +8977,7 @@ "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", "dev": true, "requires": { - "path-key": "^2.0.0" + "path-key": "2.0.1" } }, "nth-check": { @@ -8986,7 +8985,7 @@ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", "requires": { - "boolbase": "~1.0.0" + "boolbase": "1.0.0" } }, "num2fraction": { @@ -9022,9 +9021,9 @@ "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" }, "dependencies": { "define-property": { @@ -9032,7 +9031,7 @@ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "kind-of": { @@ -9040,7 +9039,7 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -9065,7 +9064,7 @@ "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "requires": { - "isobject": "^3.0.0" + "isobject": "3.0.1" } }, "object.assign": { @@ -9073,10 +9072,10 @@ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "define-properties": "1.1.2", + "function-bind": "1.1.1", + "has-symbols": "1.0.0", + "object-keys": "1.0.11" } }, "object.entries": { @@ -9084,10 +9083,10 @@ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.0.4.tgz", "integrity": "sha1-G/mk3SKI9bM/Opk9JXZh8F0WGl8=", "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.6.1", - "function-bind": "^1.1.0", - "has": "^1.0.1" + "define-properties": "1.1.2", + "es-abstract": "1.11.0", + "function-bind": "1.1.1", + "has": "1.0.1" } }, "object.getownpropertydescriptors": { @@ -9096,8 +9095,8 @@ "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", "dev": true, "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.5.1" + "define-properties": "1.1.2", + "es-abstract": "1.11.0" } }, "object.omit": { @@ -9106,8 +9105,8 @@ "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", "dev": true, "requires": { - "for-own": "^0.1.4", - "is-extendable": "^0.1.1" + "for-own": "0.1.5", + "is-extendable": "0.1.1" } }, "object.pick": { @@ -9115,7 +9114,7 @@ "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "requires": { - "isobject": "^3.0.1" + "isobject": "3.0.1" } }, "object.values": { @@ -9123,10 +9122,10 @@ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz", "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=", "requires": { - "define-properties": "^1.1.2", - "es-abstract": "^1.6.1", - "function-bind": "^1.1.0", - "has": "^1.0.1" + "define-properties": "1.1.2", + "es-abstract": "1.11.0", + "function-bind": "1.1.1", + "has": "1.0.1" } }, "once": { @@ -9135,7 +9134,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1" + "wrappy": "1.0.2" } }, "onetime": { @@ -9144,7 +9143,7 @@ "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", "dev": true, "requires": { - "mimic-fn": "^1.0.0" + "mimic-fn": "1.2.0" } }, "optimist": { @@ -9153,8 +9152,8 @@ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" + "minimist": "0.0.8", + "wordwrap": "0.0.3" } }, "optionator": { @@ -9163,12 +9162,12 @@ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" }, "dependencies": { "wordwrap": { @@ -9185,10 +9184,10 @@ "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", "dev": true, "requires": { - "chalk": "^1.1.1", - "cli-cursor": "^1.0.2", - "cli-spinners": "^0.1.2", - "object-assign": "^4.0.1" + "chalk": "1.1.3", + "cli-cursor": "1.0.2", + "cli-spinners": "0.1.2", + "object-assign": "4.1.1" }, "dependencies": { "ansi-styles": { @@ -9203,11 +9202,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" } }, "cli-cursor": { @@ -9216,7 +9215,7 @@ "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", "dev": true, "requires": { - "restore-cursor": "^1.0.1" + "restore-cursor": "1.0.1" } }, "onetime": { @@ -9231,8 +9230,8 @@ "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", "dev": true, "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" + "exit-hook": "1.1.1", + "onetime": "1.1.0" } }, "supports-color": { @@ -9261,9 +9260,9 @@ "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", "dev": true, "requires": { - "execa": "^0.7.0", - "lcid": "^1.0.0", - "mem": "^1.1.0" + "execa": "0.7.0", + "lcid": "1.0.0", + "mem": "1.1.0" } }, "os-tmpdir": { @@ -9284,7 +9283,7 @@ "integrity": "sha1-kw89Et0fUOdDRFeiLNbwSsatf3E=", "dev": true, "requires": { - "p-reduce": "^1.0.0" + "p-reduce": "1.0.0" } }, "p-finally": { @@ -9310,7 +9309,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", "requires": { - "p-try": "^1.0.0" + "p-try": "1.0.0" } }, "p-locate": { @@ -9318,7 +9317,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", "requires": { - "p-limit": "^1.1.0" + "p-limit": "1.2.0" } }, "p-map": { @@ -9339,7 +9338,7 @@ "integrity": "sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA==", "dev": true, "requires": { - "p-finally": "^1.0.0" + "p-finally": "1.0.0" } }, "p-try": { @@ -9359,9 +9358,9 @@ "integrity": "sha1-1BDwZbBdojCB/NEPKIVMKb2jOwY=", "dev": true, "requires": { - "cyclist": "~0.2.2", - "inherits": "^2.0.3", - "readable-stream": "^2.1.5" + "cyclist": "0.2.2", + "inherits": "2.0.3", + "readable-stream": "2.3.6" } }, "parse-asn1": { @@ -9370,11 +9369,11 @@ "integrity": "sha512-KPx7flKXg775zZpnp9SxJlz00gTd4BmJ2yJufSc44gMCRrRQ7NSzAcSJQfifuOLgW6bEi+ftrALtsgALeB2Adw==", "dev": true, "requires": { - "asn1.js": "^4.0.0", - "browserify-aes": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3" + "asn1.js": "4.10.1", + "browserify-aes": "1.2.0", + "create-hash": "1.2.0", + "evp_bytestokey": "1.0.3", + "pbkdf2": "3.0.16" } }, "parse-glob": { @@ -9383,10 +9382,10 @@ "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", "dev": true, "requires": { - "glob-base": "^0.3.0", - "is-dotfile": "^1.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" } }, "parse-json": { @@ -9394,7 +9393,7 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "requires": { - "error-ex": "^1.2.0" + "error-ex": "1.3.1" } }, "parse-passwd": { @@ -9408,7 +9407,7 @@ "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", "requires": { - "@types/node": "*" + "@types/node": "10.0.0" } }, "pascalcase": { @@ -9462,9 +9461,9 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" } }, "pbkdf2": { @@ -9473,11 +9472,11 @@ "integrity": "sha512-y4CXP3thSxqf7c0qmOF+9UeOTrifiVTIM+u7NWlq+PRsHbr7r7dpCmvzrZxa96JJUNi0Y5w9VqG5ZNeCVMoDcA==", "dev": true, "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" + "create-hash": "1.2.0", + "create-hmac": "1.1.7", + "ripemd160": "2.0.2", + "safe-buffer": "5.1.2", + "sha.js": "2.4.11" } }, "pegjs": { @@ -9505,7 +9504,7 @@ "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "requires": { - "pinkie": "^2.0.0" + "pinkie": "2.0.4" } }, "pkg-dir": { @@ -9514,7 +9513,7 @@ "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", "dev": true, "requires": { - "find-up": "^2.1.0" + "find-up": "2.1.0" } }, "pluralize": { @@ -9540,9 +9539,9 @@ "integrity": "sha512-y/bKfbQz2Nn/QBC08bwvYUxEFOVGfPIUOTsJ2CK5inzlXW9SdYR1x4pEsG9blRAF/PX+wRNdOah+gx/hv4q7dw==", "dev": true, "requires": { - "chalk": "^2.3.2", - "source-map": "^0.6.1", - "supports-color": "^5.3.0" + "chalk": "2.4.1", + "source-map": "0.6.1", + "supports-color": "5.4.0" }, "dependencies": { "source-map": { @@ -9559,9 +9558,9 @@ "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", "dev": true, "requires": { - "postcss": "^5.0.2", - "postcss-message-helpers": "^2.0.0", - "reduce-css-calc": "^1.2.6" + "postcss": "5.2.18", + "postcss-message-helpers": "2.0.0", + "reduce-css-calc": "1.3.0" }, "dependencies": { "ansi-styles": { @@ -9576,11 +9575,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -9603,10 +9602,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -9615,7 +9614,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -9626,9 +9625,9 @@ "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", "dev": true, "requires": { - "colormin": "^1.0.5", - "postcss": "^5.0.13", - "postcss-value-parser": "^3.2.3" + "colormin": "1.1.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" }, "dependencies": { "ansi-styles": { @@ -9643,11 +9642,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -9670,10 +9669,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -9682,7 +9681,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -9693,8 +9692,8 @@ "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", "dev": true, "requires": { - "postcss": "^5.0.11", - "postcss-value-parser": "^3.1.2" + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" }, "dependencies": { "ansi-styles": { @@ -9709,11 +9708,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -9736,10 +9735,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -9748,7 +9747,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -9759,7 +9758,7 @@ "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", "dev": true, "requires": { - "postcss": "^5.0.14" + "postcss": "5.2.18" }, "dependencies": { "ansi-styles": { @@ -9774,11 +9773,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -9801,10 +9800,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -9813,7 +9812,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -9824,7 +9823,7 @@ "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", "dev": true, "requires": { - "postcss": "^5.0.4" + "postcss": "5.2.18" }, "dependencies": { "ansi-styles": { @@ -9839,11 +9838,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -9866,10 +9865,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -9878,7 +9877,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -9889,7 +9888,7 @@ "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", "dev": true, "requires": { - "postcss": "^5.0.14" + "postcss": "5.2.18" }, "dependencies": { "ansi-styles": { @@ -9904,11 +9903,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -9931,10 +9930,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -9943,7 +9942,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -9954,7 +9953,7 @@ "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", "dev": true, "requires": { - "postcss": "^5.0.16" + "postcss": "5.2.18" }, "dependencies": { "ansi-styles": { @@ -9969,11 +9968,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -9996,10 +9995,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -10008,7 +10007,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -10019,8 +10018,8 @@ "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", "dev": true, "requires": { - "postcss": "^5.0.14", - "uniqs": "^2.0.0" + "postcss": "5.2.18", + "uniqs": "2.0.0" }, "dependencies": { "ansi-styles": { @@ -10035,11 +10034,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -10062,10 +10061,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -10074,7 +10073,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -10085,8 +10084,8 @@ "integrity": "sha1-bYWGJTTXNaxCDkqFgG4fXUKG2Ew=", "dev": true, "requires": { - "postcss": "^5.0.4", - "uniqid": "^4.0.0" + "postcss": "5.2.18", + "uniqid": "4.1.1" }, "dependencies": { "ansi-styles": { @@ -10101,11 +10100,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -10128,10 +10127,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -10140,7 +10139,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -10151,10 +10150,10 @@ "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=", "dev": true, "requires": { - "cosmiconfig": "^2.1.0", - "object-assign": "^4.1.0", - "postcss-load-options": "^1.2.0", - "postcss-load-plugins": "^2.3.0" + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1", + "postcss-load-options": "1.2.0", + "postcss-load-plugins": "2.3.0" } }, "postcss-load-options": { @@ -10163,8 +10162,8 @@ "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=", "dev": true, "requires": { - "cosmiconfig": "^2.1.0", - "object-assign": "^4.1.0" + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1" } }, "postcss-load-plugins": { @@ -10173,8 +10172,8 @@ "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=", "dev": true, "requires": { - "cosmiconfig": "^2.1.1", - "object-assign": "^4.1.0" + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1" } }, "postcss-loader": { @@ -10183,10 +10182,10 @@ "integrity": "sha512-pV7kB5neJ0/1tZ8L1uGOBNTVBCSCXQoIsZMsrwvO8V2rKGa2tBl/f80GGVxow2jJnRJ2w1ocx693EKhZAb9Isg==", "dev": true, "requires": { - "loader-utils": "^1.1.0", - "postcss": "^6.0.0", - "postcss-load-config": "^1.2.0", - "schema-utils": "^0.4.0" + "loader-utils": "1.1.0", + "postcss": "6.0.21", + "postcss-load-config": "1.2.0", + "schema-utils": "0.4.5" }, "dependencies": { "ajv": { @@ -10195,10 +10194,10 @@ "integrity": "sha512-VDUX1oSajablmiyFyED9L1DFndg0P9h7p1F+NO8FkIzei6EPrR6Zu1n18rd5P8PqaSRd/FrWv3G1TVBqpM83gA==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0", - "uri-js": "^4.2.1" + "fast-deep-equal": "2.0.1", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1", + "uri-js": "4.2.1" } }, "ajv-keywords": { @@ -10219,8 +10218,8 @@ "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", "dev": true, "requires": { - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0" + "ajv": "6.5.0", + "ajv-keywords": "3.2.0" } }, "uri-js": { @@ -10229,7 +10228,7 @@ "integrity": "sha512-jpKCA3HjsBfSDOEgxRDAxQCNyHfCPSbq57PqCkd3gAyBuPb3IWxw54EHncqESznIdqSetHfw3D7ylThu2Kcc9A==", "dev": true, "requires": { - "punycode": "^2.1.0" + "punycode": "2.1.0" } } } @@ -10240,9 +10239,9 @@ "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", "dev": true, "requires": { - "has": "^1.0.1", - "postcss": "^5.0.10", - "postcss-value-parser": "^3.1.1" + "has": "1.0.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" }, "dependencies": { "ansi-styles": { @@ -10257,11 +10256,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -10284,10 +10283,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -10296,7 +10295,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -10307,7 +10306,7 @@ "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", "dev": true, "requires": { - "postcss": "^5.0.4" + "postcss": "5.2.18" }, "dependencies": { "ansi-styles": { @@ -10322,11 +10321,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -10349,10 +10348,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -10361,7 +10360,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -10372,11 +10371,11 @@ "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", "dev": true, "requires": { - "browserslist": "^1.5.2", - "caniuse-api": "^1.5.2", - "postcss": "^5.0.4", - "postcss-selector-parser": "^2.2.2", - "vendors": "^1.0.0" + "browserslist": "1.7.7", + "caniuse-api": "1.6.1", + "postcss": "5.2.18", + "postcss-selector-parser": "2.2.3", + "vendors": "1.0.2" }, "dependencies": { "ansi-styles": { @@ -10391,8 +10390,8 @@ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "dev": true, "requires": { - "caniuse-db": "^1.0.30000639", - "electron-to-chromium": "^1.2.7" + "caniuse-db": "1.0.30000830", + "electron-to-chromium": "1.3.44" } }, "chalk": { @@ -10401,11 +10400,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -10428,10 +10427,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -10440,7 +10439,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -10457,9 +10456,9 @@ "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", "dev": true, "requires": { - "object-assign": "^4.0.1", - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.2" + "object-assign": "4.1.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" }, "dependencies": { "ansi-styles": { @@ -10474,11 +10473,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -10501,10 +10500,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -10513,7 +10512,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -10524,8 +10523,8 @@ "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", "dev": true, "requires": { - "postcss": "^5.0.12", - "postcss-value-parser": "^3.3.0" + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" }, "dependencies": { "ansi-styles": { @@ -10540,11 +10539,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -10567,10 +10566,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -10579,7 +10578,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -10590,10 +10589,10 @@ "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", "dev": true, "requires": { - "alphanum-sort": "^1.0.1", - "postcss": "^5.0.2", - "postcss-value-parser": "^3.0.2", - "uniqs": "^2.0.0" + "alphanum-sort": "1.0.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0", + "uniqs": "2.0.0" }, "dependencies": { "ansi-styles": { @@ -10608,11 +10607,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -10635,10 +10634,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -10647,7 +10646,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -10658,10 +10657,10 @@ "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", "dev": true, "requires": { - "alphanum-sort": "^1.0.2", - "has": "^1.0.1", - "postcss": "^5.0.14", - "postcss-selector-parser": "^2.0.0" + "alphanum-sort": "1.0.2", + "has": "1.0.1", + "postcss": "5.2.18", + "postcss-selector-parser": "2.2.3" }, "dependencies": { "ansi-styles": { @@ -10676,11 +10675,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -10703,10 +10702,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -10715,7 +10714,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -10726,7 +10725,7 @@ "integrity": "sha1-ZhQOzs447wa/DT41XWm/WdFB6oU=", "dev": true, "requires": { - "postcss": "^6.0.1" + "postcss": "6.0.21" } }, "postcss-modules-local-by-default": { @@ -10735,8 +10734,8 @@ "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", "dev": true, "requires": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" + "css-selector-tokenizer": "0.7.0", + "postcss": "6.0.21" } }, "postcss-modules-scope": { @@ -10745,8 +10744,8 @@ "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", "dev": true, "requires": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" + "css-selector-tokenizer": "0.7.0", + "postcss": "6.0.21" } }, "postcss-modules-values": { @@ -10755,8 +10754,8 @@ "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", "dev": true, "requires": { - "icss-replace-symbols": "^1.1.0", - "postcss": "^6.0.1" + "icss-replace-symbols": "1.1.0", + "postcss": "6.0.21" } }, "postcss-normalize-charset": { @@ -10765,7 +10764,7 @@ "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", "dev": true, "requires": { - "postcss": "^5.0.5" + "postcss": "5.2.18" }, "dependencies": { "ansi-styles": { @@ -10780,11 +10779,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -10807,10 +10806,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -10819,7 +10818,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -10830,10 +10829,10 @@ "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", "dev": true, "requires": { - "is-absolute-url": "^2.0.0", - "normalize-url": "^1.4.0", - "postcss": "^5.0.14", - "postcss-value-parser": "^3.2.3" + "is-absolute-url": "2.1.0", + "normalize-url": "1.9.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" }, "dependencies": { "ansi-styles": { @@ -10848,11 +10847,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -10875,10 +10874,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -10887,7 +10886,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -10898,8 +10897,8 @@ "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", "dev": true, "requires": { - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.1" + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" }, "dependencies": { "ansi-styles": { @@ -10914,11 +10913,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -10941,10 +10940,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -10953,7 +10952,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -10964,8 +10963,8 @@ "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", "dev": true, "requires": { - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.2" + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" }, "dependencies": { "ansi-styles": { @@ -10980,11 +10979,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -11007,10 +11006,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -11019,7 +11018,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -11030,7 +11029,7 @@ "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", "dev": true, "requires": { - "postcss": "^5.0.4" + "postcss": "5.2.18" }, "dependencies": { "ansi-styles": { @@ -11045,11 +11044,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -11072,10 +11071,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -11084,7 +11083,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -11095,9 +11094,9 @@ "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", "dev": true, "requires": { - "has": "^1.0.1", - "postcss": "^5.0.8", - "postcss-value-parser": "^3.0.1" + "has": "1.0.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" }, "dependencies": { "ansi-styles": { @@ -11112,11 +11111,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -11139,10 +11138,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -11151,7 +11150,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -11162,9 +11161,9 @@ "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", "dev": true, "requires": { - "flatten": "^1.0.2", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" + "flatten": "1.0.2", + "indexes-of": "1.0.1", + "uniq": "1.0.1" } }, "postcss-svgo": { @@ -11173,10 +11172,10 @@ "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", "dev": true, "requires": { - "is-svg": "^2.0.0", - "postcss": "^5.0.14", - "postcss-value-parser": "^3.2.3", - "svgo": "^0.7.0" + "is-svg": "2.1.0", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0", + "svgo": "0.7.2" }, "dependencies": { "ansi-styles": { @@ -11191,11 +11190,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -11218,10 +11217,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -11230,7 +11229,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -11241,9 +11240,9 @@ "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", "dev": true, "requires": { - "alphanum-sort": "^1.0.1", - "postcss": "^5.0.4", - "uniqs": "^2.0.0" + "alphanum-sort": "1.0.2", + "postcss": "5.2.18", + "uniqs": "2.0.0" }, "dependencies": { "ansi-styles": { @@ -11258,11 +11257,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -11285,10 +11284,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -11297,7 +11296,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -11314,9 +11313,9 @@ "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", "dev": true, "requires": { - "has": "^1.0.1", - "postcss": "^5.0.4", - "uniqs": "^2.0.0" + "has": "1.0.1", + "postcss": "5.2.18", + "uniqs": "2.0.0" }, "dependencies": { "ansi-styles": { @@ -11331,11 +11330,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -11358,10 +11357,10 @@ "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "supports-color": { @@ -11370,7 +11369,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } } } @@ -11385,11 +11384,11 @@ "resolved": "https://registry.npmjs.org/preact-compat/-/preact-compat-3.18.0.tgz", "integrity": "sha512-4ygl49bkMyPEx2ZwkNDh2AhUa62g2lwJYIsQU4IR5zW4d4QIyucmZFr/hu2+aeFP4YVR8nVZg1KWMETpP32UkA==", "requires": { - "immutability-helper": "^2.1.2", - "preact-render-to-string": "^3.6.0", - "preact-transition-group": "^1.1.0", - "prop-types": "^15.5.8", - "standalone-react-addons-pure-render-mixin": "^0.1.1" + "immutability-helper": "2.6.6", + "preact-render-to-string": "3.7.0", + "preact-transition-group": "1.1.1", + "prop-types": "15.6.1", + "standalone-react-addons-pure-render-mixin": "0.1.1" } }, "preact-render-to-string": { @@ -11397,7 +11396,7 @@ "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-3.7.0.tgz", "integrity": "sha1-fbQXdFS8ATleDQHWrAe8XoOOMe4=", "requires": { - "pretty-format": "^3.5.1" + "pretty-format": "3.8.0" } }, "preact-transition-group": { @@ -11468,7 +11467,7 @@ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", "requires": { - "asap": "~2.0.3" + "asap": "2.0.6" } }, "promise-inflight": { @@ -11482,9 +11481,9 @@ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.1.tgz", "integrity": "sha512-4ec7bY1Y66LymSUOH/zARVYObB23AT2h8cf6e/O6ZALB/N0sqZFEx7rq6EYPX2MkOdKORuooI/H5k9TlR4q7kQ==", "requires": { - "fbjs": "^0.8.16", - "loose-envify": "^1.3.1", - "object-assign": "^4.1.1" + "fbjs": "0.8.16", + "loose-envify": "1.3.1", + "object-assign": "4.1.1" } }, "prr": { @@ -11505,11 +11504,11 @@ "integrity": "sha512-4kJ5Esocg8X3h8YgJsKAuoesBgB7mqH3eowiDzMUPKiRDDE7E/BqqZD1hnTByIaAFiwAw246YEltSq7tdrOH0Q==", "dev": true, "requires": { - "bn.js": "^4.1.0", - "browserify-rsa": "^4.0.0", - "create-hash": "^1.1.0", - "parse-asn1": "^5.0.0", - "randombytes": "^2.0.1" + "bn.js": "4.11.8", + "browserify-rsa": "4.0.1", + "create-hash": "1.2.0", + "parse-asn1": "5.1.1", + "randombytes": "2.0.6" } }, "pump": { @@ -11518,8 +11517,8 @@ "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", "dev": true, "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" + "end-of-stream": "1.4.1", + "once": "1.4.0" } }, "pumpify": { @@ -11528,9 +11527,9 @@ "integrity": "sha512-2kmNR9ry+Pf45opRVirpNuIFotsxUGLaYqxIwuR77AYrYRMuFCz9eryHBS52L360O+NcR383CL4QYlMKPq4zYA==", "dev": true, "requires": { - "duplexify": "^3.5.3", - "inherits": "^2.0.3", - "pump": "^2.0.0" + "duplexify": "3.5.4", + "inherits": "2.0.3", + "pump": "2.0.1" } }, "punycode": { @@ -11557,8 +11556,8 @@ "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", "dev": true, "requires": { - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" + "object-assign": "4.1.1", + "strict-uri-encode": "1.1.0" } }, "querystring": { @@ -11583,7 +11582,7 @@ "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.0.tgz", "integrity": "sha512-pDP/NMRAXoTfrhCfyfSEwJAKLaxBU9eApMeBPB1TkDouZmvPerIClV8lTAd+uF8ZiTaVl69e1FCxQrAd/VTjGw==", "requires": { - "performance-now": "^2.1.0" + "performance-now": "2.1.0" } }, "railroad-diagrams": { @@ -11597,7 +11596,7 @@ "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", "requires": { "discontinuous-range": "1.0.0", - "ret": "~0.1.10" + "ret": "0.1.15" } }, "randomatic": { @@ -11606,8 +11605,8 @@ "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", "dev": true, "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" + "is-number": "3.0.0", + "kind-of": "4.0.0" }, "dependencies": { "kind-of": { @@ -11616,7 +11615,7 @@ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -11627,7 +11626,7 @@ "integrity": "sha512-CIQ5OFxf4Jou6uOKe9t1AOgqpeU5fd70A8NPdHSGeYXqXsPe6peOwI0cUl88RWZ6sP1vPMV3avd/R6cZ5/sP1A==", "dev": true, "requires": { - "safe-buffer": "^5.1.0" + "safe-buffer": "5.1.2" } }, "randomfill": { @@ -11636,8 +11635,8 @@ "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", "dev": true, "requires": { - "randombytes": "^2.0.5", - "safe-buffer": "^5.1.0" + "randombytes": "2.0.6", + "safe-buffer": "5.1.2" } }, "react": { @@ -11645,10 +11644,10 @@ "resolved": "https://registry.npmjs.org/react/-/react-16.3.2.tgz", "integrity": "sha512-o5GPdkhciQ3cEph6qgvYB7LTOHw/GB0qRI6ZFNugj49qJCFfgHwVNjZ5u+b7nif4vOeMIOuYj3CeYe2IBD74lg==", "requires": { - "fbjs": "^0.8.16", - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.0" + "fbjs": "0.8.16", + "loose-envify": "1.3.1", + "object-assign": "4.1.1", + "prop-types": "15.6.1" } }, "react-dom": { @@ -11656,10 +11655,10 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.3.2.tgz", "integrity": "sha512-MMPko3zYncNrz/7gG17wJWUREZDvskZHXOwbttzl0F0L3wDmToyuETuo/r8Y5yvDejwYcRyWI1lvVBjLJWFwKA==", "requires": { - "fbjs": "^0.8.16", - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.0" + "fbjs": "0.8.16", + "loose-envify": "1.3.1", + "object-assign": "4.1.1", + "prop-types": "15.6.1" } }, "react-is": { @@ -11677,10 +11676,10 @@ "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.4.4.tgz", "integrity": "sha512-5VYNvy301Z0xxGBQhPmDdzOcyEkUG8sU7bpRsAPI4OHgEUkbBFrpjzs/ocNI0m824/lOqTxddXzwgmDJXx3s3Q==", "requires": { - "exenv": "^1.2.0", - "prop-types": "^15.5.10", - "react-lifecycles-compat": "^3.0.0", - "warning": "^3.0.0" + "exenv": "1.2.2", + "prop-types": "15.6.1", + "react-lifecycles-compat": "3.0.2", + "warning": "3.0.0" } }, "react-reconciler": { @@ -11688,10 +11687,10 @@ "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.7.0.tgz", "integrity": "sha512-50JwZ3yNyMS8fchN+jjWEJOH3Oze7UmhxeoJLn2j6f3NjpfCRbcmih83XTWmzqtar/ivd5f7tvQhvvhism2fgg==", "requires": { - "fbjs": "^0.8.16", - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.0" + "fbjs": "0.8.16", + "loose-envify": "1.3.1", + "object-assign": "4.1.1", + "prop-types": "15.6.1" } }, "react-redux": { @@ -11699,12 +11698,12 @@ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-5.0.7.tgz", "integrity": "sha512-5VI8EV5hdgNgyjfmWzBbdrqUkrVRKlyTKk1sGH3jzM2M2Mhj/seQgPXaz6gVAj2lz/nz688AdTqMO18Lr24Zhg==", "requires": { - "hoist-non-react-statics": "^2.5.0", - "invariant": "^2.0.0", - "lodash": "^4.17.5", - "lodash-es": "^4.17.5", - "loose-envify": "^1.1.0", - "prop-types": "^15.6.0" + "hoist-non-react-statics": "2.5.0", + "invariant": "2.2.4", + "lodash": "4.17.10", + "lodash-es": "4.17.10", + "loose-envify": "1.3.1", + "prop-types": "15.6.1" }, "dependencies": { "lodash": { @@ -11719,10 +11718,10 @@ "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-16.3.2.tgz", "integrity": "sha512-lL8WHIpCTMdSe+CRkt0rfMxBkJFyhVrpdQ54BaJRIrXf9aVmbeHbRA8GFRpTvohPN5tPzMabmrzW2PUfWCfWwQ==", "requires": { - "fbjs": "^0.8.16", - "object-assign": "^4.1.1", - "prop-types": "^15.6.0", - "react-is": "^16.3.2" + "fbjs": "0.8.16", + "object-assign": "4.1.1", + "prop-types": "15.6.1", + "react-is": "16.3.2" } }, "read-chunk": { @@ -11731,8 +11730,8 @@ "integrity": "sha1-agTAkoAF7Z1C4aasVgDhnLx/9lU=", "dev": true, "requires": { - "pify": "^3.0.0", - "safe-buffer": "^5.1.1" + "pify": "3.0.0", + "safe-buffer": "5.1.2" }, "dependencies": { "pify": { @@ -11748,9 +11747,9 @@ "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" } }, "read-pkg-up": { @@ -11758,8 +11757,8 @@ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" + "find-up": "1.1.2", + "read-pkg": "1.1.0" }, "dependencies": { "find-up": { @@ -11767,8 +11766,8 @@ "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" } }, "path-exists": { @@ -11776,7 +11775,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "requires": { - "pinkie-promise": "^2.0.0" + "pinkie-promise": "2.0.1" } } } @@ -11786,13 +11785,13 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.2", + "string_decoder": "1.1.1", + "util-deprecate": "1.0.2" } }, "readdirp": { @@ -11801,10 +11800,10 @@ "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "minimatch": "^3.0.2", - "readable-stream": "^2.0.2", - "set-immediate-shim": "^1.0.1" + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.6", + "set-immediate-shim": "1.0.1" } }, "realpath-native": { @@ -11813,7 +11812,7 @@ "integrity": "sha512-XJtlRJ9jf0E1H1SLeJyQ9PGzQD7S65h1pRXEcAeK48doKOnKxcgPeNohJvD5u/2sI9J1oke6E8bZHS/fmW1UiQ==", "dev": true, "requires": { - "util.promisify": "^1.0.0" + "util.promisify": "1.0.0" } }, "recast": { @@ -11823,9 +11822,9 @@ "dev": true, "requires": { "ast-types": "0.11.3", - "esprima": "~4.0.0", - "private": "~0.1.5", - "source-map": "~0.6.1" + "esprima": "4.0.0", + "private": "0.1.8", + "source-map": "0.6.1" }, "dependencies": { "source-map": { @@ -11842,7 +11841,7 @@ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "dev": true, "requires": { - "resolve": "^1.1.6" + "resolve": "1.1.7" } }, "reduce-css-calc": { @@ -11851,9 +11850,9 @@ "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", "dev": true, "requires": { - "balanced-match": "^0.4.2", - "math-expression-evaluator": "^1.2.14", - "reduce-function-call": "^1.0.1" + "balanced-match": "0.4.2", + "math-expression-evaluator": "1.2.17", + "reduce-function-call": "1.0.2" }, "dependencies": { "balanced-match": { @@ -11870,7 +11869,7 @@ "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", "dev": true, "requires": { - "balanced-match": "^0.4.2" + "balanced-match": "0.4.2" }, "dependencies": { "balanced-match": { @@ -11886,10 +11885,10 @@ "resolved": "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz", "integrity": "sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A==", "requires": { - "lodash": "^4.2.1", - "lodash-es": "^4.2.1", - "loose-envify": "^1.1.0", - "symbol-observable": "^1.0.3" + "lodash": "4.17.10", + "lodash-es": "4.17.10", + "loose-envify": "1.3.1", + "symbol-observable": "1.2.0" } }, "regenerate": { @@ -11909,9 +11908,9 @@ "integrity": "sha512-PJepbvDbuK1xgIgnau7Y90cwaAmO/LCLMI2mPvaXq2heGMR3aWW5/BQvYrhJ8jgmQjXewXvBjzfqKcVOmhjZ6Q==", "dev": true, "requires": { - "babel-runtime": "^6.18.0", - "babel-types": "^6.19.0", - "private": "^0.1.6" + "babel-runtime": "6.26.0", + "babel-types": "6.26.0", + "private": "0.1.8" } }, "regex-cache": { @@ -11920,7 +11919,7 @@ "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", "dev": true, "requires": { - "is-equal-shallow": "^0.1.3" + "is-equal-shallow": "0.1.3" } }, "regex-not": { @@ -11928,8 +11927,8 @@ "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" } }, "regexpp": { @@ -11944,9 +11943,9 @@ "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", "dev": true, "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" + "regenerate": "1.3.3", + "regjsgen": "0.2.0", + "regjsparser": "0.1.5" } }, "regjsgen": { @@ -11961,7 +11960,7 @@ "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", "dev": true, "requires": { - "jsesc": "~0.5.0" + "jsesc": "0.5.0" }, "dependencies": { "jsesc": { @@ -11993,7 +11992,7 @@ "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "requires": { - "is-finite": "^1.0.0" + "is-finite": "1.0.2" } }, "replace-ext": { @@ -12008,28 +12007,28 @@ "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", "dev": true, "requires": { - "aws-sign2": "~0.7.0", - "aws4": "^1.6.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.1", - "forever-agent": "~0.6.1", - "form-data": "~2.3.1", - "har-validator": "~5.0.3", - "hawk": "~6.0.2", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.17", - "oauth-sign": "~0.8.2", - "performance-now": "^2.1.0", - "qs": "~6.5.1", - "safe-buffer": "^5.1.1", - "stringstream": "~0.0.5", - "tough-cookie": "~2.3.3", - "tunnel-agent": "^0.6.0", - "uuid": "^3.1.0" + "aws-sign2": "0.7.0", + "aws4": "1.7.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.3.2", + "har-validator": "5.0.3", + "hawk": "6.0.2", + "http-signature": "1.2.0", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "2.1.0", + "qs": "6.5.1", + "safe-buffer": "5.1.2", + "stringstream": "0.0.5", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" } }, "request-promise-core": { @@ -12038,7 +12037,7 @@ "integrity": "sha1-Pu4AssWqgyOc+wTFcA2jb4HNCLY=", "dev": true, "requires": { - "lodash": "^4.13.1" + "lodash": "4.17.10" } }, "request-promise-native": { @@ -12048,8 +12047,8 @@ "dev": true, "requires": { "request-promise-core": "1.1.1", - "stealthy-require": "^1.1.0", - "tough-cookie": ">=2.3.3" + "stealthy-require": "1.1.1", + "tough-cookie": "2.3.4" } }, "require-directory": { @@ -12075,8 +12074,8 @@ "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", "dev": true, "requires": { - "caller-path": "^0.1.0", - "resolve-from": "^1.0.0" + "caller-path": "0.1.0", + "resolve-from": "1.0.1" }, "dependencies": { "resolve-from": { @@ -12110,7 +12109,7 @@ "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", "dev": true, "requires": { - "resolve-from": "^3.0.0" + "resolve-from": "3.0.0" } }, "resolve-dir": { @@ -12119,8 +12118,8 @@ "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", "dev": true, "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" + "expand-tilde": "2.0.2", + "global-modules": "1.0.0" } }, "resolve-from": { @@ -12140,7 +12139,7 @@ "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", "dev": true, "requires": { - "lowercase-keys": "^1.0.0" + "lowercase-keys": "1.0.1" } }, "restore-cursor": { @@ -12149,8 +12148,8 @@ "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", "dev": true, "requires": { - "onetime": "^2.0.0", - "signal-exit": "^3.0.2" + "onetime": "2.0.1", + "signal-exit": "3.0.2" } }, "ret": { @@ -12165,7 +12164,7 @@ "dev": true, "optional": true, "requires": { - "align-text": "^0.1.1" + "align-text": "0.1.4" } }, "rimraf": { @@ -12174,7 +12173,7 @@ "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { - "glob": "^7.0.5" + "glob": "7.1.2" } }, "ripemd160": { @@ -12183,8 +12182,8 @@ "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", "dev": true, "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" + "hash-base": "3.0.4", + "inherits": "2.0.3" } }, "rst-selector-parser": { @@ -12192,8 +12191,8 @@ "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz", "integrity": "sha1-gbIw6i/MYGbInjRy3nlChdmwPZE=", "requires": { - "lodash.flattendeep": "^4.4.0", - "nearley": "^2.7.10" + "lodash.flattendeep": "4.4.0", + "nearley": "2.13.0" } }, "run-async": { @@ -12202,7 +12201,7 @@ "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", "dev": true, "requires": { - "is-promise": "^2.1.0" + "is-promise": "2.1.0" } }, "run-queue": { @@ -12211,7 +12210,7 @@ "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", "dev": true, "requires": { - "aproba": "^1.1.1" + "aproba": "1.2.0" } }, "rx": { @@ -12232,7 +12231,7 @@ "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", "dev": true, "requires": { - "rx-lite": "*" + "rx-lite": "4.0.8" } }, "rxjs": { @@ -12262,7 +12261,7 @@ "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "requires": { - "ret": "~0.1.10" + "ret": "0.1.15" } }, "safer-buffer": { @@ -12276,14 +12275,14 @@ "integrity": "sha512-glfKd7YH4UCrh/7dD+UESsr8ylKWRE7UQPoXuz28FgmcF0ViJQhCTCCZHICRKxf8G8O1KdLEn20dcICK54c7ew==", "dev": true, "requires": { - "anymatch": "^2.0.0", - "exec-sh": "^0.2.0", - "fb-watchman": "^2.0.0", - "fsevents": "^1.1.1", - "micromatch": "^3.1.4", - "minimist": "^1.1.1", - "walker": "~1.0.5", - "watch": "~0.18.0" + "anymatch": "2.0.0", + "exec-sh": "0.2.1", + "fb-watchman": "2.0.0", + "fsevents": "1.2.2", + "micromatch": "3.1.10", + "minimist": "1.2.0", + "walker": "1.0.7", + "watch": "0.18.0" }, "dependencies": { "minimist": { @@ -12339,10 +12338,10 @@ "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" }, "dependencies": { "extend-shallow": { @@ -12350,7 +12349,7 @@ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -12366,8 +12365,8 @@ "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "dev": true, "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "2.0.3", + "safe-buffer": "5.1.2" } }, "shebang-command": { @@ -12376,7 +12375,7 @@ "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", "dev": true, "requires": { - "shebang-regex": "^1.0.0" + "shebang-regex": "1.0.0" } }, "shebang-regex": { @@ -12391,9 +12390,9 @@ "integrity": "sha512-pRXeNrCA2Wd9itwhvLp5LZQvPJ0wU6bcjaTMywHHGX5XWhVN2nzSu7WV0q+oUY7mGK3mgSkDDzP3MgjqdyIgbQ==", "dev": true, "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" + "glob": "7.1.2", + "interpret": "1.1.0", + "rechoir": "0.6.2" } }, "shellwords": { @@ -12420,7 +12419,7 @@ "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0" + "is-fullwidth-code-point": "2.0.0" } }, "slide": { @@ -12434,14 +12433,14 @@ "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.1", + "use": "3.1.0" }, "dependencies": { "define-property": { @@ -12449,7 +12448,7 @@ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "extend-shallow": { @@ -12457,7 +12456,7 @@ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -12467,9 +12466,9 @@ "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" }, "dependencies": { "define-property": { @@ -12477,7 +12476,7 @@ "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "1.0.2" } }, "is-accessor-descriptor": { @@ -12485,7 +12484,7 @@ "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-data-descriptor": { @@ -12493,7 +12492,7 @@ "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-descriptor": { @@ -12501,9 +12500,9 @@ "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } } } @@ -12513,7 +12512,7 @@ "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "requires": { - "kind-of": "^3.2.0" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -12521,7 +12520,7 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -12532,7 +12531,7 @@ "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", "dev": true, "requires": { - "hoek": "4.x.x" + "hoek": "4.2.1" } }, "sort-keys": { @@ -12541,7 +12540,7 @@ "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", "dev": true, "requires": { - "is-plain-obj": "^1.0.0" + "is-plain-obj": "1.1.0" } }, "source-list-map": { @@ -12560,11 +12559,11 @@ "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.1.tgz", "integrity": "sha512-0KW2wvzfxm8NCTb30z0LMNyPqWCdDGE2viwzUaucqJdkTRXtZiSY3I+2A6nVAjmdOy0I4gU8DwnVVGsk9jvP2A==", "requires": { - "atob": "^2.0.0", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" + "atob": "2.1.0", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" } }, "source-map-support": { @@ -12573,8 +12572,8 @@ "integrity": "sha512-mR7/Nd5l1z6g99010shcXJiNEaf3fEtmLhRB/sBcQVJGodcHCULPp2y4Sfa43Kv2zq7T+Izmfp/WHCR6dYkQCA==", "dev": true, "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "buffer-from": "1.0.0", + "source-map": "0.6.1" }, "dependencies": { "source-map": { @@ -12601,8 +12600,8 @@ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", "integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" } }, "spdx-exceptions": { @@ -12615,8 +12614,8 @@ "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" } }, "spdx-license-ids": { @@ -12634,7 +12633,7 @@ "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "requires": { - "extend-shallow": "^3.0.0" + "extend-shallow": "3.0.2" } }, "sprintf-js": { @@ -12649,14 +12648,14 @@ "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", "dev": true, "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "tweetnacl": "~0.14.0" + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" } }, "ssri": { @@ -12665,7 +12664,7 @@ "integrity": "sha512-XRSIPqLij52MtgoQavH/x/dU1qVKtWUAAZeOHsR9c2Ddi4XerFy3mc1alf+dLJKl9EUIm/Ht+EowFkTUOA6GAQ==", "dev": true, "requires": { - "safe-buffer": "^5.1.1" + "safe-buffer": "5.1.2" } }, "stack-utils": { @@ -12684,8 +12683,8 @@ "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "define-property": "0.2.5", + "object-copy": "0.1.0" }, "dependencies": { "define-property": { @@ -12693,7 +12692,7 @@ "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } } } @@ -12710,8 +12709,8 @@ "integrity": "sha1-ZiZu5fm9uZQKTkUUyvtDu3Hlyds=", "dev": true, "requires": { - "inherits": "~2.0.1", - "readable-stream": "^2.0.2" + "inherits": "2.0.3", + "readable-stream": "2.3.6" } }, "stream-each": { @@ -12720,8 +12719,8 @@ "integrity": "sha512-mc1dbFhGBxvTM3bIWmAAINbqiuAk9TATcfIQC8P+/+HJefgaiTlMn2dHvkX8qlI12KeYKSQ1Ua9RrIqrn1VPoA==", "dev": true, "requires": { - "end-of-stream": "^1.1.0", - "stream-shift": "^1.0.0" + "end-of-stream": "1.4.1", + "stream-shift": "1.0.0" } }, "stream-http": { @@ -12730,11 +12729,11 @@ "integrity": "sha512-QllfrBhqF1DPcz46WxKTs6Mz1Bpc+8Qm6vbqOpVav5odAXwbyzwnEczoWqtxrsmlO+cJqtPrp/8gWKWjaKLLlA==", "dev": true, "requires": { - "builtin-status-codes": "^3.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.3.6", - "to-arraybuffer": "^1.0.0", - "xtend": "^4.0.0" + "builtin-status-codes": "3.0.0", + "inherits": "2.0.3", + "readable-stream": "2.3.6", + "to-arraybuffer": "1.0.1", + "xtend": "4.0.1" } }, "stream-shift": { @@ -12749,7 +12748,7 @@ "integrity": "sha1-WdbqOT2HwsDdrBCqDVYbxrpvDhA=", "dev": true, "requires": { - "any-observable": "^0.2.0" + "any-observable": "0.2.0" } }, "strict-uri-encode": { @@ -12764,8 +12763,8 @@ "integrity": "sha1-1A27aGo6zpYMHP/KVivyxF+DY+0=", "dev": true, "requires": { - "astral-regex": "^1.0.0", - "strip-ansi": "^4.0.0" + "astral-regex": "1.0.0", + "strip-ansi": "4.0.0" }, "dependencies": { "strip-ansi": { @@ -12774,7 +12773,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } } } @@ -12791,8 +12790,8 @@ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" }, "dependencies": { "strip-ansi": { @@ -12801,7 +12800,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } } } @@ -12811,7 +12810,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.2" } }, "stringstream": { @@ -12825,7 +12824,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" }, "dependencies": { "ansi-regex": { @@ -12840,7 +12839,7 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "requires": { - "is-utf8": "^0.2.0" + "is-utf8": "0.2.1" } }, "strip-bom-stream": { @@ -12849,8 +12848,8 @@ "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", "dev": true, "requires": { - "first-chunk-stream": "^2.0.0", - "strip-bom": "^2.0.0" + "first-chunk-stream": "2.0.0", + "strip-bom": "2.0.0" } }, "strip-eof": { @@ -12880,7 +12879,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", "requires": { - "has-flag": "^3.0.0" + "has-flag": "3.0.0" } }, "svgo": { @@ -12889,13 +12888,13 @@ "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", "dev": true, "requires": { - "coa": "~1.0.1", - "colors": "~1.1.2", - "csso": "~2.3.1", - "js-yaml": "~3.7.0", - "mkdirp": "~0.5.1", - "sax": "~1.2.1", - "whet.extend": "~0.9.9" + "coa": "1.0.4", + "colors": "1.1.2", + "csso": "2.3.2", + "js-yaml": "3.7.0", + "mkdirp": "0.5.1", + "sax": "1.2.4", + "whet.extend": "0.9.9" }, "dependencies": { "colors": { @@ -12916,8 +12915,8 @@ "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^2.6.0" + "argparse": "1.0.10", + "esprima": "2.7.3" } } } @@ -12939,12 +12938,12 @@ "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", "dev": true, "requires": { - "ajv": "^5.2.3", - "ajv-keywords": "^2.1.0", - "chalk": "^2.1.0", - "lodash": "^4.17.4", + "ajv": "5.5.2", + "ajv-keywords": "2.1.1", + "chalk": "2.4.1", + "lodash": "4.17.10", "slice-ansi": "1.0.0", - "string-width": "^2.1.1" + "string-width": "2.1.1" } }, "tapable": { @@ -12959,8 +12958,8 @@ "integrity": "sha1-4Ma8TSa5AxJEEOT+2BEDAU38H1k=", "dev": true, "requires": { - "os-tmpdir": "^1.0.0", - "rimraf": "~2.2.6" + "os-tmpdir": "1.0.2", + "rimraf": "2.2.8" }, "dependencies": { "rimraf": { @@ -12976,11 +12975,11 @@ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-4.2.1.tgz", "integrity": "sha512-qpqlP/8Zl+sosLxBcVKl9vYy26T9NPalxSzzCP/OY6K7j938ui2oKgo+kRZYfxAeIpLqpbVnsHq1tyV70E4lWQ==", "requires": { - "arrify": "^1.0.1", - "micromatch": "^3.1.8", - "object-assign": "^4.1.0", - "read-pkg-up": "^1.0.1", - "require-main-filename": "^1.0.1" + "arrify": "1.0.1", + "micromatch": "3.1.10", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "require-main-filename": "1.0.1" } }, "text-table": { @@ -13013,8 +13012,8 @@ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" + "readable-stream": "2.3.6", + "xtend": "4.0.1" } }, "timed-out": { @@ -13029,7 +13028,7 @@ "integrity": "sha512-YvC1SV1XdOUaL6gx5CoGroT3Gu49pK9+TZ38ErPldOWW4j49GI1HKs9DV+KGq/w6y+LZ72W1c8cKz2vzY+qpzg==", "dev": true, "requires": { - "setimmediate": "^1.0.4" + "setimmediate": "1.0.5" } }, "tinycolor2": { @@ -13043,7 +13042,7 @@ "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { - "os-tmpdir": "~1.0.2" + "os-tmpdir": "1.0.2" } }, "tmpl": { @@ -13068,7 +13067,7 @@ "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -13076,7 +13075,7 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -13086,10 +13085,10 @@ "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" } }, "to-regex-range": { @@ -13097,8 +13096,8 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "is-number": "3.0.0", + "repeat-string": "1.6.1" } }, "tough-cookie": { @@ -13107,7 +13106,7 @@ "integrity": "sha512-TZ6TTfI5NtZnuyy/Kecv+CnoROnyXn2DN97LontgQpCwsX2XyLYCC0ENhYkehSOwAp8rTQKc/NUIF7BkQ5rKLA==", "dev": true, "requires": { - "punycode": "^1.4.1" + "punycode": "1.4.1" }, "dependencies": { "punycode": { @@ -13124,7 +13123,7 @@ "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", "dev": true, "requires": { - "punycode": "^2.1.0" + "punycode": "2.1.0" } }, "tree-kill": { @@ -13150,7 +13149,7 @@ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "requires": { - "safe-buffer": "^5.0.1" + "safe-buffer": "5.1.2" } }, "tweetnacl": { @@ -13166,7 +13165,7 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "~1.1.2" + "prelude-ls": "1.1.2" } }, "typedarray": { @@ -13187,9 +13186,9 @@ "dev": true, "optional": true, "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" }, "dependencies": { "yargs": { @@ -13199,9 +13198,9 @@ "dev": true, "optional": true, "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", "window-size": "0.1.0" } } @@ -13220,14 +13219,14 @@ "integrity": "sha512-hIQJ1yxAPhEA2yW/i7Fr+SXZVMp+VEI3d42RTHBgQd2yhp/1UdBcR3QEWPV5ahBxlqQDMEMTuTEvDHSFINfwSw==", "dev": true, "requires": { - "cacache": "^10.0.4", - "find-cache-dir": "^1.0.0", - "schema-utils": "^0.4.5", - "serialize-javascript": "^1.4.0", - "source-map": "^0.6.1", - "uglify-es": "^3.3.4", - "webpack-sources": "^1.1.0", - "worker-farm": "^1.5.2" + "cacache": "10.0.4", + "find-cache-dir": "1.0.0", + "schema-utils": "0.4.5", + "serialize-javascript": "1.5.0", + "source-map": "0.6.1", + "uglify-es": "3.3.9", + "webpack-sources": "1.1.0", + "worker-farm": "1.6.0" }, "dependencies": { "ajv": { @@ -13236,10 +13235,10 @@ "integrity": "sha1-06/3jpJ3VJdx2vAWTP9ISCt1T8Y=", "dev": true, "requires": { - "fast-deep-equal": "^1.0.0", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0", - "uri-js": "^3.0.2" + "fast-deep-equal": "1.1.0", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1", + "uri-js": "3.0.2" } }, "ajv-keywords": { @@ -13260,8 +13259,8 @@ "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", "dev": true, "requires": { - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0" + "ajv": "6.4.0", + "ajv-keywords": "3.1.0" } }, "source-map": { @@ -13276,8 +13275,8 @@ "integrity": "sha512-r+MU0rfv4L/0eeW3xZrd16t4NZfK8Ld4SWVglYBb7ez5uXFWHuVRs6xCTrf1yirs9a4j4Y27nn7SRfO6v67XsQ==", "dev": true, "requires": { - "commander": "~2.13.0", - "source-map": "~0.6.1" + "commander": "2.13.0", + "source-map": "0.6.1" } } } @@ -13292,10 +13291,10 @@ "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^0.4.3" + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" }, "dependencies": { "extend-shallow": { @@ -13303,7 +13302,7 @@ "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } }, "set-value": { @@ -13311,10 +13310,10 @@ "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" } } } @@ -13331,7 +13330,7 @@ "integrity": "sha1-iSIN32t1GuUrX3JISGNShZa7hME=", "dev": true, "requires": { - "macaddress": "^0.2.8" + "macaddress": "0.2.8" } }, "uniqs": { @@ -13346,7 +13345,7 @@ "integrity": "sha1-0F8v5AMlYIcfMOk8vnNe6iAVFPM=", "dev": true, "requires": { - "unique-slug": "^2.0.0" + "unique-slug": "2.0.0" } }, "unique-slug": { @@ -13355,7 +13354,7 @@ "integrity": "sha1-22Z258fMBimHj/GWCXx4hVrp9Ks=", "dev": true, "requires": { - "imurmurhash": "^0.1.4" + "imurmurhash": "0.1.4" } }, "unset-value": { @@ -13363,8 +13362,8 @@ "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" + "has-value": "0.3.1", + "isobject": "3.0.1" }, "dependencies": { "has-value": { @@ -13372,9 +13371,9 @@ "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" }, "dependencies": { "isobject": { @@ -13412,7 +13411,7 @@ "integrity": "sha1-+QuFhQf4HepNz7s8TD2/orVX+qo=", "dev": true, "requires": { - "punycode": "^2.1.0" + "punycode": "2.1.0" } }, "urix": { @@ -13443,8 +13442,8 @@ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.0.tgz", "integrity": "sha512-ERuGxDiQ6Xw/agN4tuoCRbmwRuZP0cJ1lJxJubXr5Q/5cDa78+Dc4wfvtxzhzhkm5VvmW6Mf8EVj9SPGN4l8Lg==", "requires": { - "querystringify": "^2.0.0", - "requires-port": "^1.0.0" + "querystringify": "2.0.0", + "requires-port": "1.0.0" }, "dependencies": { "querystringify": { @@ -13460,7 +13459,7 @@ "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", "dev": true, "requires": { - "prepend-http": "^2.0.0" + "prepend-http": "2.0.0" }, "dependencies": { "prepend-http": { @@ -13488,7 +13487,7 @@ "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", "integrity": "sha512-6UJEQM/L+mzC3ZJNM56Q4DFGLX/evKGRg15UJHGB9X5j5Z3AFbgZvjUh2yq/UJUY4U5dh7Fal++XbNg1uzpRAw==", "requires": { - "kind-of": "^6.0.2" + "kind-of": "6.0.2" } }, "util": { @@ -13519,8 +13518,8 @@ "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "object.getownpropertydescriptors": "^2.0.3" + "define-properties": "1.1.2", + "object.getownpropertydescriptors": "2.0.3" } }, "uuid": { @@ -13540,8 +13539,8 @@ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", "integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" } }, "vendors": { @@ -13556,9 +13555,9 @@ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, "requires": { - "assert-plus": "^1.0.0", + "assert-plus": "1.0.0", "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "extsprintf": "1.3.0" } }, "vinyl": { @@ -13567,8 +13566,8 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", + "clone": "1.0.4", + "clone-stats": "0.0.1", "replace-ext": "0.0.1" } }, @@ -13578,12 +13577,12 @@ "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.3.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0", - "strip-bom-stream": "^2.0.0", - "vinyl": "^1.1.0" + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0", + "strip-bom-stream": "2.0.0", + "vinyl": "1.2.0" } }, "vm-browserify": { @@ -13601,7 +13600,7 @@ "integrity": "sha1-gqwr/2PZUOqeMYmlimViX+3xkEU=", "dev": true, "requires": { - "browser-process-hrtime": "^0.1.2" + "browser-process-hrtime": "0.1.2" } }, "walker": { @@ -13610,7 +13609,7 @@ "integrity": "sha1-L3+bj9ENZ3JisYqITijRlhjgKPs=", "dev": true, "requires": { - "makeerror": "1.0.x" + "makeerror": "1.0.11" } }, "warning": { @@ -13618,7 +13617,7 @@ "resolved": "https://registry.npmjs.org/warning/-/warning-3.0.0.tgz", "integrity": "sha1-MuU3fLVy3kqwR1O9+IIcAe1gW3w=", "requires": { - "loose-envify": "^1.0.0" + "loose-envify": "1.3.1" } }, "watch": { @@ -13627,8 +13626,8 @@ "integrity": "sha1-KAlUdsbffJDJYxOJkMClQj60uYY=", "dev": true, "requires": { - "exec-sh": "^0.2.0", - "minimist": "^1.2.0" + "exec-sh": "0.2.1", + "minimist": "1.2.0" }, "dependencies": { "minimist": { @@ -13645,9 +13644,9 @@ "integrity": "sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA==", "dev": true, "requires": { - "chokidar": "^2.0.2", - "graceful-fs": "^4.1.2", - "neo-async": "^2.5.0" + "chokidar": "2.0.3", + "graceful-fs": "4.1.11", + "neo-async": "2.5.1" } }, "webassemblyjs": { @@ -13660,7 +13659,7 @@ "@webassemblyjs/validation": "1.4.3", "@webassemblyjs/wasm-parser": "1.4.3", "@webassemblyjs/wast-parser": "1.4.3", - "long": "^3.2.0" + "long": "3.2.0" } }, "webfontloader": { @@ -13683,25 +13682,25 @@ "@webassemblyjs/ast": "1.4.3", "@webassemblyjs/wasm-edit": "1.4.3", "@webassemblyjs/wasm-parser": "1.4.3", - "acorn": "^5.0.0", - "acorn-dynamic-import": "^3.0.0", - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0", - "chrome-trace-event": "^0.1.1", - "enhanced-resolve": "^4.0.0", - "eslint-scope": "^3.7.1", - "loader-runner": "^2.3.0", - "loader-utils": "^1.1.0", - "memory-fs": "~0.4.1", - "micromatch": "^3.1.8", - "mkdirp": "~0.5.0", - "neo-async": "^2.5.0", - "node-libs-browser": "^2.0.0", - "schema-utils": "^0.4.4", - "tapable": "^1.0.0", - "uglifyjs-webpack-plugin": "^1.2.4", - "watchpack": "^1.5.0", - "webpack-sources": "^1.0.1" + "acorn": "5.5.3", + "acorn-dynamic-import": "3.0.0", + "ajv": "6.5.0", + "ajv-keywords": "3.2.0", + "chrome-trace-event": "0.1.3", + "enhanced-resolve": "4.0.0", + "eslint-scope": "3.7.1", + "loader-runner": "2.3.0", + "loader-utils": "1.1.0", + "memory-fs": "0.4.1", + "micromatch": "3.1.10", + "mkdirp": "0.5.1", + "neo-async": "2.5.1", + "node-libs-browser": "2.1.0", + "schema-utils": "0.4.5", + "tapable": "1.0.0", + "uglifyjs-webpack-plugin": "1.2.5", + "watchpack": "1.6.0", + "webpack-sources": "1.1.0" }, "dependencies": { "ajv": { @@ -13710,10 +13709,10 @@ "integrity": "sha512-VDUX1oSajablmiyFyED9L1DFndg0P9h7p1F+NO8FkIzei6EPrR6Zu1n18rd5P8PqaSRd/FrWv3G1TVBqpM83gA==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0", - "uri-js": "^4.2.1" + "fast-deep-equal": "2.0.1", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1", + "uri-js": "4.2.1" } }, "ajv-keywords": { @@ -13734,8 +13733,8 @@ "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", "dev": true, "requires": { - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0" + "ajv": "6.5.0", + "ajv-keywords": "3.2.0" } }, "uri-js": { @@ -13744,7 +13743,7 @@ "integrity": "sha512-jpKCA3HjsBfSDOEgxRDAxQCNyHfCPSbq57PqCkd3gAyBuPb3IWxw54EHncqESznIdqSetHfw3D7ylThu2Kcc9A==", "dev": true, "requires": { - "punycode": "^2.1.0" + "punycode": "2.1.0" } } } @@ -13755,7 +13754,7 @@ "integrity": "sha512-MGO0nVniCLFAQz1qv22zM02QPjcpAoJdy7ED0i3Zy7SY1IecgXCm460ib7H/Wq7e9oL5VL6S2BxaObxwIcag0g==", "dev": true, "requires": { - "jscodeshift": "^0.4.0" + "jscodeshift": "0.4.1" }, "dependencies": { "ansi-styles": { @@ -13770,7 +13769,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "^1.0.1" + "arr-flatten": "1.1.0" } }, "array-unique": { @@ -13797,9 +13796,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" } }, "chalk": { @@ -13808,9 +13807,9 @@ "integrity": "sha1-UZmj3c0MHv4jvAjBsCewYXbgxk8=", "dev": true, "requires": { - "ansi-styles": "~1.0.0", - "has-color": "~0.1.0", - "strip-ansi": "~0.1.0" + "ansi-styles": "1.0.0", + "has-color": "0.1.7", + "strip-ansi": "0.1.1" } }, "colors": { @@ -13825,7 +13824,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "^0.1.0" + "is-posix-bracket": "0.1.1" } }, "extglob": { @@ -13834,7 +13833,7 @@ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } }, "jscodeshift": { @@ -13843,21 +13842,21 @@ "integrity": "sha512-iOX6If+hsw0q99V3n31t4f5VlD1TQZddH08xbT65ZqA7T4Vkx68emrDZMUOLVvCEAJ6NpAk7DECe3fjC/t52AQ==", "dev": true, "requires": { - "async": "^1.5.0", - "babel-plugin-transform-flow-strip-types": "^6.8.0", - "babel-preset-es2015": "^6.9.0", - "babel-preset-stage-1": "^6.5.0", - "babel-register": "^6.9.0", - "babylon": "^6.17.3", - "colors": "^1.1.2", - "flow-parser": "^0.*", - "lodash": "^4.13.1", - "micromatch": "^2.3.7", + "async": "1.5.2", + "babel-plugin-transform-flow-strip-types": "6.22.0", + "babel-preset-es2015": "6.24.1", + "babel-preset-stage-1": "6.24.1", + "babel-register": "6.26.0", + "babylon": "6.18.0", + "colors": "1.2.5", + "flow-parser": "0.72.0", + "lodash": "4.17.10", + "micromatch": "2.3.11", "node-dir": "0.1.8", - "nomnom": "^1.8.1", - "recast": "^0.12.5", - "temp": "^0.8.1", - "write-file-atomic": "^1.2.0" + "nomnom": "1.8.1", + "recast": "0.12.9", + "temp": "0.8.3", + "write-file-atomic": "1.3.4" } }, "kind-of": { @@ -13866,7 +13865,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } }, "micromatch": { @@ -13875,19 +13874,19 @@ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" } }, "nomnom": { @@ -13896,8 +13895,8 @@ "integrity": "sha1-IVH3Ikcrp55Qp2/BJbuMjy5Nwqc=", "dev": true, "requires": { - "chalk": "~0.4.0", - "underscore": "~1.6.0" + "chalk": "0.4.0", + "underscore": "1.6.0" } }, "recast": { @@ -13907,10 +13906,10 @@ "dev": true, "requires": { "ast-types": "0.10.1", - "core-js": "^2.4.1", - "esprima": "~4.0.0", - "private": "~0.1.5", - "source-map": "~0.6.1" + "core-js": "2.5.6", + "esprima": "4.0.0", + "private": "0.1.8", + "source-map": "0.6.1" } }, "source-map": { @@ -13937,9 +13936,9 @@ "integrity": "sha1-+Aek8LHZ6ROuekgRLmzDrxmRtF8=", "dev": true, "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "slide": "^1.1.5" + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "slide": "1.1.6" } } } @@ -13950,12 +13949,12 @@ "integrity": "sha512-YE6F3XDX8yOwT0SJWRivbQy3UG/iq+9n3ia9ruV2v3Uzw5q1D8PD4zL49x96YrCG1EWec+SenZbeifPDnxGfeQ==", "dev": true, "requires": { - "chalk": "^2.0", - "lodash.get": "^4.0", - "lodash.has": "^4.0", - "mkdirp": "^0.5", - "schema-utils": "^0.4.5", - "tapable": "^1.0.0" + "chalk": "2.4.1", + "lodash.get": "4.4.2", + "lodash.has": "4.5.2", + "mkdirp": "0.5.1", + "schema-utils": "0.4.5", + "tapable": "1.0.0" }, "dependencies": { "ajv": { @@ -13964,10 +13963,10 @@ "integrity": "sha512-VDUX1oSajablmiyFyED9L1DFndg0P9h7p1F+NO8FkIzei6EPrR6Zu1n18rd5P8PqaSRd/FrWv3G1TVBqpM83gA==", "dev": true, "requires": { - "fast-deep-equal": "^2.0.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0", - "uri-js": "^4.2.1" + "fast-deep-equal": "2.0.1", + "fast-json-stable-stringify": "2.0.0", + "json-schema-traverse": "0.3.1", + "uri-js": "4.2.1" } }, "ajv-keywords": { @@ -13988,8 +13987,8 @@ "integrity": "sha512-yYrjb9TX2k/J1Y5UNy3KYdZq10xhYcF8nMpAW6o3hy6Q8WSIEf9lJHG/ePnOBfziPM3fvQwfOwa13U/Fh8qTfA==", "dev": true, "requires": { - "ajv": "^6.1.0", - "ajv-keywords": "^3.1.0" + "ajv": "6.5.0", + "ajv-keywords": "3.2.0" } }, "uri-js": { @@ -13998,7 +13997,7 @@ "integrity": "sha512-jpKCA3HjsBfSDOEgxRDAxQCNyHfCPSbq57PqCkd3gAyBuPb3IWxw54EHncqESznIdqSetHfw3D7ylThu2Kcc9A==", "dev": true, "requires": { - "punycode": "^2.1.0" + "punycode": "2.1.0" } } } @@ -14009,32 +14008,32 @@ "integrity": "sha512-5AsKoL/Ccn8iTrwk3uErdyhetGH+c7VRQ7Itim2GL0IhBRq5rtojVDk00buMRmFmBpw1RvHXq97Gup965LbozA==", "dev": true, "requires": { - "chalk": "^2.3.2", - "cross-spawn": "^6.0.5", - "diff": "^3.5.0", - "enhanced-resolve": "^4.0.0", - "envinfo": "^4.4.2", - "glob-all": "^3.1.0", - "global-modules": "^1.0.0", - "got": "^8.2.0", - "import-local": "^1.0.0", - "inquirer": "^5.1.0", - "interpret": "^1.0.4", - "jscodeshift": "^0.5.0", - "listr": "^0.13.0", - "loader-utils": "^1.1.0", - "lodash": "^4.17.5", - "log-symbols": "^2.2.0", - "mkdirp": "^0.5.1", - "p-each-series": "^1.0.0", - "p-lazy": "^1.0.0", - "prettier": "^1.5.3", - "supports-color": "^5.3.0", - "v8-compile-cache": "^1.1.2", - "webpack-addons": "^1.1.5", - "yargs": "^11.1.0", - "yeoman-environment": "^2.0.0", - "yeoman-generator": "^2.0.4" + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "diff": "3.5.0", + "enhanced-resolve": "4.0.0", + "envinfo": "4.4.2", + "glob-all": "3.1.0", + "global-modules": "1.0.0", + "got": "8.3.1", + "import-local": "1.0.0", + "inquirer": "5.2.0", + "interpret": "1.1.0", + "jscodeshift": "0.5.0", + "listr": "0.13.0", + "loader-utils": "1.1.0", + "lodash": "4.17.10", + "log-symbols": "2.2.0", + "mkdirp": "0.5.1", + "p-each-series": "1.0.0", + "p-lazy": "1.0.0", + "prettier": "1.12.1", + "supports-color": "5.4.0", + "v8-compile-cache": "1.1.2", + "webpack-addons": "1.1.5", + "yargs": "11.1.0", + "yeoman-environment": "2.1.1", + "yeoman-generator": "2.0.5" }, "dependencies": { "camelcase": { @@ -14049,9 +14048,9 @@ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" } }, "cross-spawn": { @@ -14060,11 +14059,11 @@ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.0" } }, "inquirer": { @@ -14073,19 +14072,19 @@ "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^2.1.0", - "figures": "^2.0.0", - "lodash": "^4.3.0", + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.10", "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^5.5.2", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" + "run-async": "2.3.0", + "rxjs": "5.5.10", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" } }, "lodash": { @@ -14100,7 +14099,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } }, "yargs": { @@ -14109,18 +14108,18 @@ "integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==", "dev": true, "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^9.0.2" + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "9.0.2" } }, "yargs-parser": { @@ -14129,7 +14128,7 @@ "integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=", "dev": true, "requires": { - "camelcase": "^4.1.0" + "camelcase": "4.1.0" } } } @@ -14140,7 +14139,7 @@ "integrity": "sha512-/0QYwW/H1N/CdXYA2PNPVbsxO3u2Fpz34vs72xm03SRfg6bMNGfMJIQEpQjKRvkG2JvT6oRJFpDtSrwbX8Jzvw==", "dev": true, "requires": { - "lodash": "^4.17.5" + "lodash": "4.17.10" }, "dependencies": { "lodash": { @@ -14157,8 +14156,8 @@ "integrity": "sha512-aqYp18kPphgoO5c/+NaUvEeACtZjMESmDChuD3NBciVpah3XpMEU9VAAtIaB1BsfJWWTSdv8Vv1m3T0aRk2dUw==", "dev": true, "requires": { - "source-list-map": "^2.0.0", - "source-map": "~0.6.1" + "source-list-map": "2.0.0", + "source-map": "0.6.1" }, "dependencies": { "source-map": { @@ -14203,9 +14202,9 @@ "integrity": "sha512-FwygsxsXx27x6XXuExA/ox3Ktwcbf+OAvrKmLulotDAiO1Q6ixchPFaHYsis2zZBZSJTR0+dR+JVtf7MlbqZjw==", "dev": true, "requires": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" + "lodash.sortby": "4.7.0", + "tr46": "1.0.1", + "webidl-conversions": "4.0.2" } }, "whet.extend": { @@ -14220,7 +14219,7 @@ "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", "dev": true, "requires": { - "isexe": "^2.0.0" + "isexe": "2.0.0" } }, "which-module": { @@ -14248,7 +14247,7 @@ "integrity": "sha512-6w+3tHbM87WnSWnENBUvA2pxJPLhQUg5LKwUQHq3r+XPhIM+Gh2R5ycbwPCyuGbNg+lPgdcnQUhuC02kJCvffQ==", "dev": true, "requires": { - "errno": "~0.1.7" + "errno": "0.1.7" } }, "wrap-ansi": { @@ -14257,8 +14256,8 @@ "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", "dev": true, "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" + "string-width": "1.0.2", + "strip-ansi": "3.0.1" }, "dependencies": { "is-fullwidth-code-point": { @@ -14267,7 +14266,7 @@ "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "number-is-nan": "1.0.1" } }, "string-width": { @@ -14276,9 +14275,9 @@ "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", "dev": true, "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" } } } @@ -14295,7 +14294,7 @@ "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", "dev": true, "requires": { - "mkdirp": "^0.5.1" + "mkdirp": "0.5.1" } }, "write-file-atomic": { @@ -14304,9 +14303,9 @@ "integrity": "sha512-xuPeK4OdjWqtfi59ylvVL0Yn35SF3zgcAcv7rBPFHVaEapaDr4GdGgm3j7ckTwH9wHL7fGmgfAnb0+THrHb8tA==", "dev": true, "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "graceful-fs": "4.1.11", + "imurmurhash": "0.1.4", + "signal-exit": "3.0.2" } }, "ws": { @@ -14315,8 +14314,8 @@ "integrity": "sha512-ZGh/8kF9rrRNffkLFV4AzhvooEclrOH0xaugmqGsIfFgOE/pIz4fMc4Ef+5HSQqTEug2S9JZIWDR47duDSLfaA==", "dev": true, "requires": { - "async-limiter": "~1.0.0", - "safe-buffer": "~5.1.0" + "async-limiter": "1.0.0", + "safe-buffer": "5.1.2" } }, "xml-name-validator": { @@ -14349,18 +14348,18 @@ "integrity": "sha512-ivSoxqBGYOqQVruxD35+EyCFDYNEFL/Uo6FcOnz+9xZdZzK0Zzw4r4KhbrME1Oo2gOggwJod2MnsdamSG7H9ig==", "dev": true, "requires": { - "cliui": "^4.0.0", - "decamelize": "^1.1.1", - "find-up": "^2.1.0", - "get-caller-file": "^1.0.1", - "os-locale": "^2.0.0", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^2.0.0", - "which-module": "^2.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^8.1.0" + "cliui": "4.1.0", + "decamelize": "1.2.0", + "find-up": "2.1.0", + "get-caller-file": "1.0.2", + "os-locale": "2.1.0", + "require-directory": "2.1.1", + "require-main-filename": "1.0.1", + "set-blocking": "2.0.0", + "string-width": "2.1.1", + "which-module": "2.0.0", + "y18n": "3.2.1", + "yargs-parser": "8.1.0" }, "dependencies": { "cliui": { @@ -14369,9 +14368,9 @@ "integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==", "dev": true, "requires": { - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0", - "wrap-ansi": "^2.0.0" + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "wrap-ansi": "2.1.0" } }, "strip-ansi": { @@ -14380,7 +14379,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } } } @@ -14391,7 +14390,7 @@ "integrity": "sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ==", "dev": true, "requires": { - "camelcase": "^4.1.0" + "camelcase": "4.1.0" }, "dependencies": { "camelcase": { @@ -14408,21 +14407,21 @@ "integrity": "sha512-IBLwCUrJrDxBYuwdYm1wuF3O/CR2LpXR0rFS684QOrU6x69DPPrsdd20dZOFaedZ/M9sON7po73WhO3I1CbgNQ==", "dev": true, "requires": { - "chalk": "^2.1.0", - "cross-spawn": "^6.0.5", - "debug": "^3.1.0", - "diff": "^3.3.1", - "escape-string-regexp": "^1.0.2", - "globby": "^8.0.1", - "grouped-queue": "^0.3.3", - "inquirer": "^5.2.0", - "is-scoped": "^1.0.0", - "lodash": "^4.17.10", - "log-symbols": "^2.1.0", - "mem-fs": "^1.1.0", - "strip-ansi": "^4.0.0", - "text-table": "^0.2.0", - "untildify": "^3.0.2" + "chalk": "2.4.1", + "cross-spawn": "6.0.5", + "debug": "3.1.0", + "diff": "3.5.0", + "escape-string-regexp": "1.0.5", + "globby": "8.0.1", + "grouped-queue": "0.3.3", + "inquirer": "5.2.0", + "is-scoped": "1.0.0", + "lodash": "4.17.10", + "log-symbols": "2.2.0", + "mem-fs": "1.1.3", + "strip-ansi": "4.0.0", + "text-table": "0.2.0", + "untildify": "3.0.2" }, "dependencies": { "cross-spawn": { @@ -14431,11 +14430,11 @@ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.0" } }, "debug": { @@ -14453,13 +14452,13 @@ "integrity": "sha512-oMrYrJERnKBLXNLVTqhm3vPEdJ/b2ZE28xN4YARiix1NOIOBPEpOUnm844K1iu/BkphCaf2WNFwMszv8Soi1pw==", "dev": true, "requires": { - "array-union": "^1.0.1", - "dir-glob": "^2.0.0", - "fast-glob": "^2.0.2", - "glob": "^7.1.2", - "ignore": "^3.3.5", - "pify": "^3.0.0", - "slash": "^1.0.0" + "array-union": "1.0.2", + "dir-glob": "2.0.0", + "fast-glob": "2.2.2", + "glob": "7.1.2", + "ignore": "3.3.8", + "pify": "3.0.0", + "slash": "1.0.0" } }, "inquirer": { @@ -14468,19 +14467,19 @@ "integrity": "sha512-E9BmnJbAKLPGonz0HeWHtbKf+EeSP93paWO3ZYoUpq/aowXvYGjjCSuashhXPpzbArIjBbji39THkxTz9ZeEUQ==", "dev": true, "requires": { - "ansi-escapes": "^3.0.0", - "chalk": "^2.0.0", - "cli-cursor": "^2.1.0", - "cli-width": "^2.0.0", - "external-editor": "^2.1.0", - "figures": "^2.0.0", - "lodash": "^4.3.0", + "ansi-escapes": "3.1.0", + "chalk": "2.4.1", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.2.0", + "figures": "2.0.0", + "lodash": "4.17.10", "mute-stream": "0.0.7", - "run-async": "^2.2.0", - "rxjs": "^5.5.2", - "string-width": "^2.1.0", - "strip-ansi": "^4.0.0", - "through": "^2.3.6" + "run-async": "2.3.0", + "rxjs": "5.5.10", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" } }, "lodash": { @@ -14501,7 +14500,7 @@ "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "3.0.0" } } } @@ -14512,31 +14511,31 @@ "integrity": "sha512-rV6tJ8oYzm4mmdF2T3wjY+Q42jKF2YiiD0VKfJ8/0ZYwmhCKC9Xs2346HVLPj/xE13i68psnFJv7iS6gWRkeAg==", "dev": true, "requires": { - "async": "^2.6.0", - "chalk": "^2.3.0", - "cli-table": "^0.3.1", - "cross-spawn": "^6.0.5", - "dargs": "^5.1.0", - "dateformat": "^3.0.3", - "debug": "^3.1.0", - "detect-conflict": "^1.0.0", - "error": "^7.0.2", - "find-up": "^2.1.0", - "github-username": "^4.0.0", - "istextorbinary": "^2.2.1", - "lodash": "^4.17.10", - "make-dir": "^1.1.0", - "mem-fs-editor": "^4.0.0", - "minimist": "^1.2.0", - "pretty-bytes": "^4.0.2", - "read-chunk": "^2.1.0", - "read-pkg-up": "^3.0.0", - "rimraf": "^2.6.2", - "run-async": "^2.0.0", - "shelljs": "^0.8.0", - "text-table": "^0.2.0", - "through2": "^2.0.0", - "yeoman-environment": "^2.0.5" + "async": "2.6.0", + "chalk": "2.4.1", + "cli-table": "0.3.1", + "cross-spawn": "6.0.5", + "dargs": "5.1.0", + "dateformat": "3.0.3", + "debug": "3.1.0", + "detect-conflict": "1.0.1", + "error": "7.0.2", + "find-up": "2.1.0", + "github-username": "4.1.0", + "istextorbinary": "2.2.1", + "lodash": "4.17.10", + "make-dir": "1.2.0", + "mem-fs-editor": "4.0.2", + "minimist": "1.2.0", + "pretty-bytes": "4.0.2", + "read-chunk": "2.1.0", + "read-pkg-up": "3.0.0", + "rimraf": "2.6.2", + "run-async": "2.3.0", + "shelljs": "0.8.2", + "text-table": "0.2.0", + "through2": "2.0.3", + "yeoman-environment": "2.1.1" }, "dependencies": { "cross-spawn": { @@ -14545,11 +14544,11 @@ "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", "dev": true, "requires": { - "nice-try": "^1.0.4", - "path-key": "^2.0.1", - "semver": "^5.5.0", - "shebang-command": "^1.2.0", - "which": "^1.2.9" + "nice-try": "1.0.4", + "path-key": "2.0.1", + "semver": "5.5.0", + "shebang-command": "1.2.0", + "which": "1.3.0" } }, "debug": { @@ -14567,10 +14566,10 @@ "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^4.0.0", - "pify": "^3.0.0", - "strip-bom": "^3.0.0" + "graceful-fs": "4.1.11", + "parse-json": "4.0.0", + "pify": "3.0.0", + "strip-bom": "3.0.0" } }, "lodash": { @@ -14591,8 +14590,8 @@ "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", "dev": true, "requires": { - "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1" + "error-ex": "1.3.1", + "json-parse-better-errors": "1.0.2" } }, "path-type": { @@ -14601,7 +14600,7 @@ "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", "dev": true, "requires": { - "pify": "^3.0.0" + "pify": "3.0.0" } }, "pify": { @@ -14616,9 +14615,9 @@ "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", "dev": true, "requires": { - "load-json-file": "^4.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^3.0.0" + "load-json-file": "4.0.0", + "normalize-package-data": "2.4.0", + "path-type": "3.0.0" } }, "read-pkg-up": { @@ -14627,8 +14626,8 @@ "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", "dev": true, "requires": { - "find-up": "^2.0.0", - "read-pkg": "^3.0.0" + "find-up": "2.1.0", + "read-pkg": "3.0.0" } }, "strip-bom": { diff --git a/readme.txt b/readme.txt deleted file mode 100644 index 1e15337c2bc..00000000000 --- a/readme.txt +++ /dev/null @@ -1,384 +0,0 @@ -=== Event Espresso 4 Decaf - Event Registration Event Ticketing === -Contributors: eventespresso, sethshoultes, garthkoyle, pebblo, nerrad, mnelson4, lorenzocaum, charliespider, builtbynorthby -Donate link: https://eventespresso.com/pricing/?ee_ver=ee4&utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_donate_link&utm_content=Donate+link -Tags: events, tickets, registration, event management, event manager, event booking, class booking, booking, class registration, conference registration, events calendar, events planner, event ticketing, online registration, registration, sports, training, wordpress events, online event registration -Requires at least: 4.1 -Requires PHP Version: 5.4 -Tested up to: 4.9 -Stable tag: 4.9.51.decaf -License: GPL2 - -Manage online event registration and ticketing. Create event registration forms, sell tickets, collect money, send email, and SEO for events. - -== Description == - -Manage your events from your WordPress dashboard. Reduce your admin, [reduce your costs](https://eventespresso.com/2010/08/friends-dont-let-friends-host-events-eventbrite/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_description_tab&utm_content=reduce+your+costs+link), make your life easier! - -Event Espresso is a [WordPress event manager](https://eventespresso.com/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_description_tab&utm_content=WordPress+event+manager) which makes it easy for you to sell tickets for events, workshops, events, training, conferences or concerts, register attendees for classes, all from your WordPress website. Quickly create events from within the WordPress admin area using the Event Espresso engine. You can create signup forms to collect information about your attendees, accept payments, and create reports. The decaf version of the plugin provides everything that you need to sell tickets, collect payments, and manage events all from within your WordPress dashboard. - -[youtube http://www.youtube.com/watch?v=K_yVwWnTjL8] -(Some features not available in all versions) - - -= Why Online Event Management? = -You shouldn't need to be convinced about how awesome online event management is, but in case you do: - -* Save yourself countless hours of tedious admin processes -* Create green, paperless [event registration](https://eventespresso.com/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_description_tab&utm_content=event+registration) -* Reduce costs -* Process sign-ups 24/7 - -= What's Included? = -**Everything you need** to sell tickets and manage event registrations from your website. Here's what you get: - -* Out-of-the-box event ticketing and registration from your WordPress website -* Process payments using PayPal Express Checkout, or [buy a support license](https://eventespresso.com/pricing/?ee_ver=ee4&utm_source=wordpress_org&utm_medium=link&utm_content=buy+a+support+license&utm_campaign=ee4_decaf_whats_included) for more [payment options](https://eventespresso.com/features/payment-options/?ee_ver=ee4&utm_source=wordpress_org&utm_medium=link&utm_content=more+payment+options&utm_campaign=ee4_decaf_whats_included). -* Automated confirmation emails -* Manage registrants (attendees) and export registrant (attendee) data -* Easily manage registrants' (attendees) profiles -* [Android & Apple event apps](https://eventespresso.com/features/mobile-ticketing-apps/?ee_ver=ee4&utm_source=wordpress_org&utm_medium=link&utm_content=mobile+event+apps&utm_campaign=ee4_decaf_whats_included) for ticket scanning and attendance tracking - - -[View Features & Sample Screenshots Here](https://eventespresso.com/features/?ee_ver=ee4&utm_source=wordpress_org&utm_medium=link&utm_content=View+Sample+Screens+Here&utm_campaign=ee4_decaf_plugin_screenshots_tab) OR [Compare Features](https://eventespresso.com/differences-ee4-ee3/?utm_source=wordpress_org&utm_medium=link&utm_content=Compare+Features&utm_campaign=ee4_decaf_plugin_screenshots_tab) - - -= Support License = -Just in case you want some advanced features, you can purchase a **[Premium Support License](https://eventespresso.com/pricing/?ee_ver=ee4&utm_source=wordpress_org&utm_medium=link&utm_content=Buy+a+Premium+Support+License&utm_campaign=ee4_decaf_plugin_dscreenshots_tab)** to get access to additional features and payment options for your events. - -**Premium Features** -* [Event Calendar](https://eventespresso.com/product/ee4-events-calendar/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_description_tab&utm_content=Event+Calendar) -* [Additional Payment Gateways](https://eventespresso.com/features/payment-options/?ee_ver=ee4&utm_source=wordpress_org&utm_campaign=ee4_decaf_plugin_description_tab&utm_content=Additional+Payment+Gateways) (including Authorize.net and PayPal Pro) -* [Multiple Pricing and Ticket Options](https://eventespresso.com/features/multiple-ticket-pricing-options/?ee_ver=ee4&utm_source=wordpress_org&utm_campaign=ee4_decaf_plugin_description_tab&utm_content=Multiple+Pricing+Options) -* [Manual Registration](https://eventespresso.com/features/manual-registration/?ee_ver=ee4&utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_description_tab&utm_content=Manual+Registration) -* [Reusable, Customizable Email Templates](https://eventespresso.com/features/confirmation-emails/?ee_ver=ee4&utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_description_tab&utm_content=Reusable+Email+Templates) -* [Transaction Reporting](https://eventespresso.com/features/transaction-reporting/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_description_tab&utm_content=Transaction+Reporting) -* [Event Check-in](https://eventespresso.com/features/event-check-list/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_description_tab&utm_content=Event+Check-in) -* [Contact Profiles & Contact List](https://eventespresso.com/features/contacts/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_description_tab&utm_content=Contact+Profiles+Contact+List) -* [Tax Administration](https://eventespresso.com/features/tax-administration/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_description_tab&utm_content=Tax+Administration) - -= Newsletter = -Be the first to know when we ship new features, [signup here](https://eventespresso.com/newsletter/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_plugin_description_tab&utm_content=newsletter+signup). - -= Community Chat = -Join a real-time community chat group for professionals that are leading the way in events from event management, event technology and event marketing to work-life balance. - -[Join the Discussion →](https://eventsmart.com/contact/community-chat/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_plugin_description_tab&utm_content=community+chat) - -= Testimonials & Reviews = -> Your plugin saved our client nearly $9000 in development costs because it handled the majority of the functionality we were looking for at a much lower cost. Event Espresso's staff have been very responsive to our needs when we have them (which has been rare, because the plugin is so well coded). Great job on a great plugin! - -Brandon P. - [Experience Farm](http://www.experiencefarm.com/) - -> At first we looked at CVENT for one of our clients and they wanted $16,000 per year for 3000 event attendees + fees totaling $22k. That is before Staff and Webinar fees. Worst of all we had to prepay the $16k amount even if we never used all 3000 attendees. That was when we looked at Event Espresso and we realized we could build our own event system for less than 16K. For the most part we have been very satisfied with our decision. The real ROI will come next year when they don't have to pay another 16k-22K! Over the next 5-6 years we should be able to claim that we saved the company over $100,000 - Thanks Event Espresso! - -David Waterman - [KT Benefits & InkItDigital.com](http://ktbenefits.info/) - -> I can't really estimate how much time or money I've saved by using EE because I've always used it! I would have to guess that without it, I would need someone full time to keep my events organized, so that's at least $10K. In 3 years I went from running up to 7 parties per weekend (Fri. night - Sun. night) to running up to 33 parties per weekend. My sales for 2014 were $540,000+. It boggles my mind sometimes. I don't know how I would possibly keep this all straight without my Event Espresso registration system which allows my guests to register and pay online, and keeps track of everything for me. - -Tara Smith - [The Uncorked Artist](http://www.theuncorkedartist.com/) - -> Thank you, we just did 2 sell out seminars of 50 attendees in 48 hours using Event Espresso and it was awesome. My wife was able to pick up on the processing backend with ease. You have done a great job on getting this system together - very simple, clear and well laid out With powerful functionality. I am so glad I dumped the old booking application we had and gave Event Espresso a go. Just wanted to say thanks, and thanks for the very patient, friendly and speedy assistance in helping me to get it all set up at the start. Many thanks to you and your team. A grateful customer. - -Nicholas de Castella - [Emotional Intelligence Trainings](http://www.eq.net.au/) -> It is a very, very slick plugin. It's one of those plugins where you install it, change a couple of settings, and boom you're selling tickets. - -Brad Williams - [WebDevStudios](http://webdevstudios.com/) - -> Thanks to you and the rest of the team for Event Espresso -- Every time I get a signup for an event, I think about how much time EE saves me -- and signups happen while I'm out on the water teaching kayaking, not answering the phone. - -Tue Brems Olesen [OnAdventure](http://onadventure.dk/) - -> [Tri-South, Inc](http://tri-southinc.com/) is using Event Espresso to manage the course catalog, event ticketing, and class registration. [As their developer] I have customized a few items to make the site and plugin a seamless integration. The client is very pleased! - -Jenifer - [Jenifer Design](http://jeniferdesign.com/) - -> Event Espresso saves us money, saves our secretary 16-24 hours and looks so professionally done that people ask us how we do it; which we happily tell them, "Event Espresso, and be sure to get the ticketing add-on." - -David - [House of Prayer](http://hop.org/) - -> I have been using Event Espresso to run my festival and have been very happy with how it has worked out. They have provided tremendous support and their iPhone app is amazing and easy to use. I suggest using it for your event. - -Alex Grant - [Byron Spirit Festival](http://www.spiritfestival.com.au/) - -> Love the plugin, we only use it once a year for a race we have in February. This saved us tons of time in data entry. In addition, we had more runners register than any other year. We attribute that to the ease of registering online. Thanks for your work. - -Ed - [Friends of Oscar Scherer Park](http://www.friendsofoscarscherer.com/) - -> My hope with this whole integration is to be able to show other school districts an affordable and easy solution to these registrations. I cannot believe how much money they are charged for less by other companies. This has the potential to save schools tens of thousands, which is huge right now. - -Kelly - [College Station Independent School District](http://csisd.org/) - - -> I chose EE because, a few years ago, I was using it on a personal website and loved it. So, when I discovered that our current event management system that is deployed in other areas of campus was completely deficient for this initiative's needs, I didn't even hesitate to use EE. - -Rob Domaschuk - - -= Support = -This version is self-supported only. We DO NOT regularly monitor the WordPress.org support forums. For faster support you can purchase a [support license](https://eventespresso.com/pricing/?ee_ver=ee4&utm_source=wordpress_org&utm_medium=link&utm_content=Buy+a+Premium+Support+License&utm_campaign=ee4_decaf_plugin_support_tab) and ask questions in our [support forum](https://eventespresso.com/support/forums/?utm_source=wordpress_org&utm_medium=link&utm_content=forum&utm_campaign=ee4_decaf_plugin_description_tab). You can also visit the Help/Support menu from the Event Espresso admin. - -If your support issue is urgent, we also offer [priority event management support](https://eventespresso.com/product/premium-support-token/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_description_tab&utm_content=priority+event+management+support) (support tokens). - -Check out the advanced [installation](https://eventespresso.com/wiki/installing-event-espresso/?utm_source=wordpress_org&utm_medium=link&utm_content=installation&utm_campaign=ee4_decaf_plugin_description_tab) and [setup instructions](https://eventespresso.com/wiki/how-to-setup-event-espresso-and-publish-your-first-event/?utm_source=wordpress_org&utm_medium=link&utm_content=setup+instructions&utm_campaign=ee4_decaf_plugin_description_tab) on our website. - -= Developer Resources = -* [Event Espresso 4 on Github](http://evts.io/EE4_WP_Readme) -* [Developer Targeted Documentation](http://evts.io/EE4_Dev_Docs) -* [Code structure and PHPDOC parsed documentation](http://code.eventespresso.com) - -== Screenshots == - -1. Multiple Ticket and Pricing Options -2. Customized Confirmation Emails -3. Customizable Event Designs -4. Smart Single Page Checkout -5. Contact Profiles -6. Contact List -7. In-app Documentation -8. Customizable Country Settings - -== Installation == - -= Quick Install = -1. Event Espresso can be installed and activated by searching for the plugin through WordPress admin → Plugins → Add New. - -= Installing via FTP = -Alternatively, you can download Event Espresso to your computer from the WordPress Plugin Directory. - -1. Then locate the `event-espresso-core-decaf` folder on your computer and unzip it. -2. Login to your WordPress root with an SFTP or FTP client and browse to the WordPress plugins directory: `wp-content/plugins`. -3. Now upload the `event-espresso` folder to the WordPress plugins directory. -4. Return to the WordPress admin and go to Plugins. Then activate Event Espresso. - -Check out the advanced [installation](https://eventespresso.com/wiki/installing-event-espresso/?utm_source=wordpress_org&utm_medium=link&utm_content=installation&utm_campaign=ee4_decaf_plugin_installation_tab) and [setup instructions](https://eventespresso.com/wiki/the-basic-settings/?utm_source=wordpress_org&utm_medium=link&utm_content=setup+instructions&utm_campaign=ee4_decaf_plugin_installation_tab) on our website. - -= Documentation = -Find resources on Event Espresso 4 for a beginner to advanced users. - -[View Event Espresso 4 Documentation →](https://eventespresso.com/support/documentation/versioned-docs?doc_ver=ee4&utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_plugin_description_tab&utm_content=view+ee4+documentation) - -= Mobile Event Apps = -The Event Espresso 4 check-in & ticket scanning event app is available for [Android](http://evts.io/EE4_Android_App?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_plugin_description_tab&utm_content=mobile+event+apps+android) and [Apple](http://evts.io/EE4_Apple_App?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_plugin_description_tab) - -= Developers = -**The full version can be [found on Github](http://evts.io/EE4_WP_Readme)** and provides everything that you need to [sell tickets](https://eventespresso.com/features/multiple-ticket-pricing-options/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_plugin_description_tab&utm_content=sell+tickets), [collect payments](https://eventespresso.com/features/payment-options/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_plugin_description_tab&utm_content=collect+payments), and [manage events](https://eventespresso.com/features/event-management/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_plugin_description_tab&utm_content=manage+events) all from within your WordPress dashboard. - - -Buy a **[Premium Support License](https://eventespresso.com/pricing/?ee_ver=ee4&utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_plugin_description_tab&utm_content=premium+support+license)** to get access to more features (including [one-click upgrades](https://eventespresso.com/features/one-click-upgrades/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_plugin_description_tab&utm_content=one+click+upgrades), [growing list of add-ons](https://eventespresso.com/add-ons/?ee_ver=ee4&utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_plugin_description_tab&utm_content=growing+list+of+addons)). - -== Frequently Asked Questions == - -= What is Event Espresso? = - -Event Espresso is ticket and event management software for the modern world. Do you need to convince someone about Event Espresso? Share our [new video](https://eventespresso.com/2012/11/what-is-event-espresso-video/) or [print a brochure](http://ee-screenshots.s3.amazonaws.com/2012/02/EE_brochure_small.pdf). - -= Can I fully manage my events with Event Espresso Decaf? = - -You will be able to manage basic events with Event Espresso Decaf entirely, which is sufficient for many WordPress users. If you need advanced features, you can check out our Premium [Event Management plugin](https://eventespresso.com/pricing/?ee_ver=ee4&utm_source=wordpress_org&utm_medium=link&utm_content=Event+Management+plugin&utm_campaign=ee4_decaf_plugin_faq_tab) - -= Can I use the Android & Apple event apps with Event Espresso Decaf? = - -Yes, the [event apps](https://eventespresso.com/features/mobile-ticketing-apps/?ee_ver=ee4&utm_source=wordpress_org&utm_medium=link&utm_content=event+apps&utm_campaign=ee4_decaf_plugin_faq_tab) work great with Event Espresso Decaf! - -= Will Event Espresso work on my server? = - -We have a plugin available that will check your server for the [minimum requirements](https://eventespresso.com/requirements/). - -= Do you support WordPress multisite? = - -WordPress multisite brings some complexity that can lead to some challenges. As such we cannot support multisite, but we'll offer recommendations wherever we can. Multisite compatibility is much better with EE4 than EE3. If you're unsure about using multisite, then please read [this article](http://halfelf.org/2011/dont-use-wordpress-multisite/). - -= Which web browsers work with Event Espresso? = - -Event Espresso has been tested with the most current versions Internet Explorer (Windows only), Firefox, Safari, Chrome on the Windows PC and Mac OSX platforms. Event Espresso may function just as well in older or other, less modern browsers, but we only support those listed previously. For more information, please see our [supported web browsers](https://eventespresso.com/faqs/supported-web-browsers/) page. - -= Do you monitor the WordPress.org support forums? = - -We DO NOT regularly monitor the support forums on WordPress.org. You'll find a faster response time at the [support forums on our website](https://eventespresso.com/support/forums/?utm_source=wordpress_org&utm_medium=link&utm_content=support+forums+on+our+website&utm_campaign=ee4_decaf_plugin_faq_tab). - -= What if I don't have (or don't want) a WordPress website? = - -If you want to organize your event fast without the hassle of managing a server, plugins, and security, then build your event website on our event cloud [Event Smart - free online event registration and ticketing management](https://eventsmart.com/?utm_source=wordpress_org&utm_medium=EE4_faq&utm_campaign=EE4&utm_content=link). - -= Is Event Espresso 4 available on Github? = - -Yes, you can get access to the core files via the [Event Espresso 4 Github page](http://evts.io/EE4_WP_Readme). - -== Changelog == - -= Important Note = - -Backup your WordPress before installing any updates. Please see our article on [Backing Up your WordPress Site](https://eventespresso.com/wiki/how-to-back-up-your-site/?utm_source=wordpress_org&utm_medium=link&utm_content=changelog&utm_campaign=ee4_decaf_plugin_changelog_tab). - -**Please Note:** Due to the fact that the Event Espresso 4 Decaf and Caffeinated (paid) versions share the same codebase, the changelog presented here is based on the Caffeinated (paid) version of Event Espresso 4. Up to date changelog for the current premium version [can be found here](https://eventespresso.com/wiki/ee4-changelog/?utm_source=wordpress_org&utm_medium=link&utm_content=changelog&utm_campaign=ee4_decaf_plugin_changelog_tab). - -**Developers, [find us on Github](http://evts.io/EE4_WP_Readme)** - -== Upgrade Notice == - -Backup your WordPress website before installing any updates. - -== Other Notes == - -**Developers, [find us on Github](http://evts.io/EE4_WP_Readme)** - -**Use Cases** - -[Event Espresso](http:eventespresso.com/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) is a very flexible, and robust event ticketing plugin for WordPress. Many [optional features](https://eventespresso.com/features/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) include an [integrated calendar](https://eventespresso.com/product/ee4-events-calendar/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases), [ticket scanning](https://eventespresso.com/product/eea-barcode-scanner/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) & check-in/out capabilities, [single page checkout](https://eventespresso.com/features/intelligent-single-page-checkout/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases), [multiple event registration](https://eventespresso.com/product/eea-multi-event-registration/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases), and after event [marketing tools](https://eventespresso.com/product/eea-mailchimp/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_case). - -= Arts & Culture = - -* City Tours -* Club Performances -* Concerts -* [Film Festivals](https://eventespresso.com/use-cases/film-festival-ticketing-software/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) -* Museum Tickets -* Music Festivals -* Movie Theater Ticket Sales -* [Paint & Wine](https://eventespresso.com/use-cases/paint-wine-party-ticketing-software/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) -* Plays and Theatrical Performances -* [Sewing & Quilting Retreats](https://eventespresso.com/use-cases/quilt-retreat-booking/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) -* Social Events - -= Business = - -* Asset/Resource Booking/Scheduling -* Car Wash Sales & Reservations -* [Conference Registration](https://eventespresso.com/use-cases/conference-registration/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) -* [Haunted House Ticket Sales](https://eventespresso.com/2012/09/haunted-house-ticketing-system/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) -* House Cleaning Services -* [Model Agency Booking/Scheduling](https://eventespresso.com/use-cases/modeling-talent-agency-scheduling/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) -* Room Booking/Scheduling -* Workshop Registrations - -= Classes = - -* [Art Classes](https://eventespresso.com/use-cases/paint-wine-party-ticketing-software/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) -* Cooking Classes -* Dance Classes -* Continuing Education Classes -* Fitness Club Classes -* Martial Arts Classes -* Firearms and Concealed Weapons Training -* Music Classes -* Scrapbooking Classes -* [Skydiving Classes](https://eventespresso.com/use-cases/skydiving-jumping-class-reservations/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) -* Training Classes -* Yoga Classes -* Drivers Education -* Technical/IT Training - -= Community Events Conferences = - -* [Backyard Barbecues](https://eventespresso.com/use-cases/backyard-bbq-ticketing/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) -* [BBQ Festivals](https://eventespresso.com/use-cases/bbq-festival-ticketing/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) -* [Car Shows](https://eventespresso.com/use-cases/car-show-registration-ticket-sales/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) -* Geek/IT Conferences/Camps -* Group Meetings -* Political Conferences -* Social Media Conferences -* Tradeshow Booth Reservations/Sales -* WordCamps -* Youth Conferences/Camps - -= Conferences = - -* [Conference Registration](https://eventespresso.com/use-cases/conference-registration/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) -* Geek/IT Conferences/Camps -* Political Conferences -* Social Media Conferences -* Tradeshow Booth Reservations/Sales -* Tradeshow Vendor Registration -* WordCamps - - -= Education = - -* Concealed Weapons Courses -* Course Registrations -* School Lunch Reservations -* Parent Teacher Conferences -* Parent Teacher Association Conferences and Meetings -* Wildlife Education and Tours - -= Fundraisers & Non-Profit Organizations = - -* Boy Scout Troop Events -* [Car Show Registration](https://eventespresso.com/use-cases/car-show-registration-ticket-sales/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) -* Donation Drives -* Indusry Association Events -* Religous Events -* Volunteer Management - -= Government = - -* Chamber of Commerce -* Community Recreation Centers -* Department of Justice - -= Parties = - -* Birthday Parties -* Christmas Parties -* Class Reunions -* New-Year's Eve Parties -* [Paint & Wine Parties](https://eventespresso.com/use-cases/paint-wine-party-ticketing-software/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) -* Weddings - -= Recreation = - -* [Skydiving Bookings](https://eventespresso.com/use-cases/skydiving-jumping-class-reservations/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) -* Adventure Tours - -= Socials = - -* Dancing -* [Painting & Vino](https://eventespresso.com/use-cases/paint-wine-party-ticketing-software/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) -* [Sewing & Quilting Retreats](https://eventespresso.com/use-cases/quilt-retreat-booking/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) -* Speed Dating - -= Sports = - -* Races -* Sports Arena Tickets and Season Passes -* Tournament Registration -* Football and Soccer Training -* Tennis Classes - -= Training = - -* ACLS & CPR Training -* Firearms and Concealed Weapons Training -* Medical & First Aid Training -* Scrum Master Training -* Technical/IT Training - -= Workshops = - -* Carpentry & Wood Working -* Furniture Restoration -* Marketing -* Public Speaking -* Real Estate Workshops -* Visualization Workshops - -If you aren't quite sure if Event Espresso will work for you and it's not listed above, then [contact us](https://eventespresso.com/contact/?utm_source=wordpress_org&utm_medium=link&utm_campaign=ee4_decaf_plugin_more_info_use_cases_tab&utm_content=WordPress+event+manager+use_cases) and we'll do our best to evaluate your needs. - - -= License = - - Copyright 2016 Event Espresso (email : info@eventespresso.com) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License, version 2, as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - diff --git a/tests/bin/install-wp-tests.sh b/tests/bin/install-wp-tests.sh deleted file mode 100755 index 0aaf09f3cc5..00000000000 --- a/tests/bin/install-wp-tests.sh +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env bash - -if [ $# -lt 3 ]; then - echo "usage: $0 [db-host] [wp-version]" - exit 1 -fi - -DB_NAME=$1 -DB_USER=$2 -DB_PASS=$3 -DB_HOST=${4-localhost} -WP_VERSION=${5-latest} - -WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib} -WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/} - -download() { - if [ `which curl` ]; then - curl -s "$1" > "$2"; - elif [ `which wget` ]; then - wget -nv -O "$2" "$1" - fi -} - -if [[ $WP_VERSION =~ [0-9]+\.[0-9]+(\.[0-9]+)? ]]; then - WP_TESTS_TAG="tags/$WP_VERSION" -else - # http serves a single offer, whereas https serves multiple. we only want one - download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json - grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json - LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//') - if [[ -z "$LATEST_VERSION" ]]; then - echo "Latest WordPress version could not be found" - exit 1 - fi - WP_TESTS_TAG="tags/$LATEST_VERSION" -fi - -set -ex - -install_wp() { - - if [ -d $WP_CORE_DIR ]; then - return; - fi - - mkdir -p $WP_CORE_DIR - - if [ $WP_VERSION == 'latest' ]; then - local ARCHIVE_NAME='latest' - else - local ARCHIVE_NAME="wordpress-$WP_VERSION" - fi - - download https://wordpress.org/${ARCHIVE_NAME}.tar.gz /tmp/wordpress.tar.gz - tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR - - download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php -} - -install_test_suite() { - # portable in-place argument for both GNU sed and Mac OSX sed - if [[ $(uname -s) == 'Darwin' ]]; then - local ioption='-i .bak' - else - local ioption='-i' - fi - - # set up testing suite if it doesn't yet exist - if [ ! -d $WP_TESTS_DIR ]; then - # set up testing suite - mkdir -p $WP_TESTS_DIR - svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes - fi - - cd $WP_TESTS_DIR - - if [ ! -f wp-tests-config.php ]; then - download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php - sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR':" "$WP_TESTS_DIR"/wp-tests-config.php - sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php - sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php - sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php - sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php - fi - -} - -install_db() { - # parse DB_HOST for port or socket references - local PARTS=(${DB_HOST//\:/ }) - local DB_HOSTNAME=${PARTS[0]}; - local DB_SOCK_OR_PORT=${PARTS[1]}; - local EXTRA="" - - if ! [ -z $DB_HOSTNAME ] ; then - if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then - EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp" - elif ! [ -z $DB_SOCK_OR_PORT ] ; then - EXTRA=" --socket=$DB_SOCK_OR_PORT" - elif ! [ -z $DB_HOSTNAME ] ; then - EXTRA=" --host=$DB_HOSTNAME --protocol=tcp" - fi - fi - - # create database - mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA -} - -install_wp -install_test_suite -install_db diff --git a/tests/bootstrap.php b/tests/bootstrap.php deleted file mode 100644 index 5eb21767282..00000000000 --- a/tests/bootstrap.php +++ /dev/null @@ -1,19 +0,0 @@ -init(); - - -/** - * Redefining wp_mail function here as a mock for our tests. Has to be done early - * to override the existing wp_mail. Tests can use the given filter to adjust the responses as necessary. - */ -function wp_mail($to, $subject, $message, $headers = '', $attachments = array()) -{ - return apply_filters('FHEE__wp_mail', true, $to, $subject, $message, $headers, $attachments); -} diff --git a/tests/checklists/README.md b/tests/checklists/README.md deleted file mode 100644 index bd389a855ab..00000000000 --- a/tests/checklists/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Table of Contents - -| Checklists | Has Acceptance Test| -| ---------------------------------------------------|-------------------| -| [Registration Summary Message Type](registration-summary-message-type.md)| ✅ | -| [Custom Templates for Multiple Events in Message](custom-templates-multiple-events.md)| ✅ | -| [Verify calculations done by js for totals in ticket editor are correct](test-ticket-editor-subtotal-calcs.md) | ✅ | -| [Capabilities](capabilities.md) | | -| [Verifying CC field for Email messages work](verifying-cc-in-email-messages.md) | | -| [Verifying Disabling Message Context works](verifying-disabling-message-context-works.md) | | -| [Datepicker related tests](datepicker.md) | | \ No newline at end of file diff --git a/tests/checklists/capabilities.md b/tests/checklists/capabilities.md deleted file mode 100644 index 6ce12645e46..00000000000 --- a/tests/checklists/capabilities.md +++ /dev/null @@ -1,120 +0,0 @@ -This is for testing the capability system within EE. - -## Stage One of testing: Ensure existing routes/actions work with administrator role. - -* [ ] Test Event Admin Pages and routes -* [ ] Test Registrations Pages and routes -* [ ] Test Transactions Pages and routes -* [ ] Test Messages Pages and routes -* [ ] Test Pricing Pages and routes -* [ ] Test Registration Form Pages and routes. -* [ ] Test Venues pages and routes -* [ ] Test General Settings pages and routes -* [ ] Test Payment Methods pages and routes -* [ ] Test Help & Support pages and routes. -* [ ] Test Maintenance pages and routes (and test reset capabilities button). -* [ ] Test about pages and routes. - -## Stage Two of testing: Ensure existing routes/actions work with Event Administrator role. - -The expectation is that the Event Administrator role has all ee_capabilities *except* those related to payment methods. The role also has the following wp core capabilities: - * 'read', - * 'read_private_pages', - * 'read_private_posts', - * 'edit_users', - * 'edit_posts', - * 'edit_pages', - * 'edit_published_posts', - * 'edit_published_pages', - * 'edit_private_pages', - * 'edit_private_posts', - * 'edit_others_posts', - * 'edit_others_pages', - * 'publish_posts', - * 'publish_pages', - * 'delete_posts', - * 'delete_pages', - * 'delete_private_pages', - * 'delete_private_posts', - * 'delete_published_pages', - * 'delete_published_posts', - * 'delete_others_posts', - * 'delete_others_pages', - * 'manage_categories', - * 'manage_links', - * 'moderate_comments', - * 'unfiltered_html', - * 'upload_files', - * 'export', - * 'import', - * 'list_users', - * 'level_1' - -So when testing with the above role that's why you should expect. - -* [ ] Verify that Event Administrator role has expected capabilities. - -## Stage Three of Testing - -In this stage, verify that the following add-ons when activated successfully add their capabilities to the Administrator and Event Administrator roles: - -* [ ] People Add-on adds its cap. -* [ ] Barcode Scanner add-on adds its caps. -* [ ] Promotions add-on adds its caps. - -Also test that when adding a custom payment method add-on, its capability gets added. For this test just testing one payment add-on such as Stripe should be sufficient. Remember that only the Administrator role gets the payment method caps. - -* [ ] Verify payment method add-on capability gets added when it is installed for the first time. - -## Stage Four of Testing - -### Testing Prep: - -- [The EE Capability spreadsheet][1] - This describes all the capabilities and the behaviour you can expect. Each sheet in the file is for a major capability subset. Use this when testing specific systems. -- Remember that not only are "routes" protected by capabilities, but also the associated buttons/actions for those routes. So for instance, the create_new route for events is protected by the "edit_events" capability. That means that not only should a user without that capability not be able to access the create new event editor but any buttons/links to that should not be visible either. - -**Third Party Roles and Capabilities Plugin(s) to test with:** - -- http://wordpress.org/plugins/capability-manager-enhanced/ for a quick start guide see: http://www.wpbeginner.com/plugins/how-to-add-or-remove-capabilities-to-user-roles-in-wordpress/ - -- https://wordpress.org/plugins/members/ Quick overview: http://justintadlock.com/archives/2009/09/17/members-wordpress-plugin - -- also recommended to help quickly switch between accounts: http://wordpress.org/plugins/user-switching/ - -### To Test: -(using your choice of roles and capabilities plugin) - -**Testing all capabilities with custom role** - -* [ ] Create a Custom role and add ONLY the EE capabilities to it. -* [ ] Create a user and assign that role to them. Then log in as that user. -* [ ] Test every aspect of the EE_Admin with that user and verify things work as expected. - -**Testing some capabilities with custom role** - -* [ ] Create another custom role and pick single subsystem of EE to add capabilities to that role for (i.e. events). -* [ ] Assign that role to a user, and login as that user. -* [ ] Verify that the user is ONLY able to do the things they have capabilities for. - -**Testing the "meta" capabilities** - -* [ ] Repeat a custom role setup for a capability subset that includes meta capabilities. For instance include `ee_read_others_events` but not `ee_read_private_events`, or add all the *read capabilities but none of the *edit meta capabilities. -* [ ] Assign that role to a user, and login as that user. -* [ ] Test that the capabilities work for that user as expected considering they don't have the required filtered capabilities for certain actions. - - [1]: https://docs.google.com/a/eventespresso.com/spreadsheet/ccc?key=0Al0RhqTD8pDfdEhtcFhLdW9rTFdPOWtrODh3d1QyN1E&usp=drive_web#gid=4 - -## Stage Five of testing - - This test is to verify that once the user edits capabilities on a role (i.e. removing capabilities that get added by default), on a version update, those capabilities do NOT get re-added. - - * On the Event Administrator Role, remove a couple ee core capabilities and remove the people add-on capabilities. - * Manually bump the version of EE core higher and do the same for the people add-on. - * [ ] After reloading the admin, verify that there were no changes to the capabilities from before the version change for the Event Administrator role. - * [ ] Do the same for a payment method add-on (such as stripe) (but this would have to be done on the Administrator role) - -## Stage Six of testing - - This is to test the reset capabilities tool. After Stage Five testing, the Event Administrator role and the Administrator role (payment method cap) should have caps missing. We want to test restoring the missing caps using the reset capabilities tool. This tool is found in the Maintenance Admin Reset/Delete Data tab. - - * [ ] Verify that after clicking the reset capabilities button, the capabilities manually removed in Stage 5 are restored. \ No newline at end of file diff --git a/tests/checklists/custom-templates-multiple-events.md b/tests/checklists/custom-templates-multiple-events.md deleted file mode 100644 index 9fe2235e0ec..00000000000 --- a/tests/checklists/custom-templates-multiple-events.md +++ /dev/null @@ -1,15 +0,0 @@ -This checklist verifies that when there are more than one event registered for, and there all the events in the registration have the same custom template, then a custom template will get used. Thus, the only time a global template will be used is when there are more than one event in the outgoing message and each event is assigned to a different message template group. For reference see [https://events.codebasehq.com/projects/event-espresso/tickets/10201](https://events.codebasehq.com/projects/event-espresso/tickets/10201). - -> Note: you can test this with any message template group but the below steps are a basic validation of expected behaviour. The below steps are also covered by `c-TestCustomMessageTemplateCept.php`. - -> You will need the MER add-on active for this. - -* [ ] Create two custom message template groups for the Registration Approved Message Type. Name one "Custom Template A" and the other "Custom Template B". -* [ ] In each of the custom message template groups you created. Edit them so that you have a way later for verifying which template was used in generating a message. -* [ ] Create three events. For two of the events, assign them to Custom Template A message template group, for the third, assign it to the Custom Template B message template group. -* [ ] Do one registration process via SPCO where you select tickets from both Events that have Custom Message Template A assigned to them. -* [ ] Do another registration process via SPCO where you select one (or more) tickets from an event assigned to Custom Message Template A and one (or more) tickets from an event assigned to Custom Message Template B. -* [ ] Go to the message activity list table. Verify that the messages associated with the first transaction are all using Custom Message Template A for the generated message. -* [ ] Verify that the messages associated with the second transaction are using the global registration approved message template group for the generated message. - - diff --git a/tests/checklists/datepicker.md b/tests/checklists/datepicker.md deleted file mode 100644 index d4b6d723757..00000000000 --- a/tests/checklists/datepicker.md +++ /dev/null @@ -1,14 +0,0 @@ -The following are tests for datepickers in EE. - -Where there are start dates and end dates: - -* [ ] Verify that when you click a start date, an acceptable default is setup. -* [ ] Verify that when you click out of a start date field, an acceptable default for the end date is set. -* [ ] Verify that if you manually empty either start date or end date field that no errors occur and that there will be a replacement date added based on the related field. In other words, if you blank the start date field, when you change focus it should automatically be filled with a date based off of the end date field. - - -For all date fields - -* [ ] Verify selecting the field triggers the datepicker to display. -* [ ] Verify that what is selected in the datepicker ends up being the value for the input. -* [ ] Verify that modifying the value in the input adjusts what is available in the datepicker. \ No newline at end of file diff --git a/tests/checklists/registration-summary-message-type.md b/tests/checklists/registration-summary-message-type.md deleted file mode 100644 index fbd8d368dff..00000000000 --- a/tests/checklists/registration-summary-message-type.md +++ /dev/null @@ -1,13 +0,0 @@ -This checklist verifies that the registration summary message type works as expected. - - * [ ] Make sure MER is active - * [ ] Make sure the Registration Summary message type is active (its not by default on a fresh install) - * [ ] Setup one event that has the DRS set to RPP - * [ ] Setup another event that has the DRS set to Not Approved - * [ ] Setup another event that has the DRS set to RPP - * [ ] Go to the frontend and add tickets for both Event 1 and Event 2 to the cart. - * [ ] Complete the registration for the tickets in the cart. - * [ ] Verify that the registration summary sends as expected. - * [ ] Go to the frontend and add tickets for both Event 1 and Event 3 to the cart. - * [ ] Complete the registration for the tickets in the cart. - * [ ] Verify that the registration summary does NOT get sent (it shouldn't because the registrations in the cart are the same status) \ No newline at end of file diff --git a/tests/checklists/test-ticket-editor-subtotal-calcs.md b/tests/checklists/test-ticket-editor-subtotal-calcs.md deleted file mode 100644 index 28572d6ec6c..00000000000 --- a/tests/checklists/test-ticket-editor-subtotal-calcs.md +++ /dev/null @@ -1,8 +0,0 @@ -This checklist is for verifying that the subtotal/total section in the advanced details pane for the ticket editor is calculating correctly. - -* [ ] Create a new event. -* [ ] Add a value for one of the tickets that has a cents amount. -* [ ] Verify the final total for the amount displayed is correct. -* [ ] Click the taxable ticket checkbox -* [ ] Verify the subtotal, taxable amount, and total is correct. -* [ ] Do the same tests as above but for different currency settings. \ No newline at end of file diff --git a/tests/checklists/verifying-cc-in-email-messages.md b/tests/checklists/verifying-cc-in-email-messages.md deleted file mode 100644 index 4aaad58e5b4..00000000000 --- a/tests/checklists/verifying-cc-in-email-messages.md +++ /dev/null @@ -1,25 +0,0 @@ -### Expectations - -- On existing installs, there is not a `cc` field for the message templates created in the db until the initial time someone adds a value in this field. This means for someone used to the structure of the `esp_message_template` table, they might wonder _where_ the cc field is. Also of note is that the cc field row when created will not be grouped with the other rows for the same template because its inserted after they were created. It's not a big deal from a technical standpoint, but just something to note. -- Fresh installs or resetting message templates for the email messenger will have the cc field created in the db right away. -- The cc field allows the same valid shortcodes as what is available for the to field. -- When a message is generated and sent, the cc field is saved with the extra meta for the message. On future resends of that _identical_ message (from the context of the list table) any attached cc's will be used again. If you're watching the database you'll see this extra meta entry show up as `MSG_cc` -- The message activity list table does not show any cc information and the cc email addresses are not included in any search queries. - -### Initial install - -* [ ] Verify on fresh install that in the db there is a row for the cc field in the `esp_message_template` table for each message template attached to the email messenger. -* [ ] Verify on existing/fresh installs that the cc field shows up in the message template editor for email message templates but does NOT show up for non email message templates. - * [ ] Verify on existing installs that when you save a template for the email messenger with content in the cc field, that the content sticks. In the db there should be a new row for cc field for that message type and messsenger in the `esp_message_template` table. - * [ ] When you send a test message from a message template with something in the cc field, the test message should go to the cc email address (if its a valid address). - - ### Shortcode Parsing/Sending - -* [ ] Verify that when you have something in the cc field on initial message creation/sending, that something (if its a shortcode is parsed correctly), if its a valid email, receives the email. -* [ ] Verify that when you regenerate a message from the context of list tables and that message has a cc field with content, the cc field value (assuming a valid email) receives the message. -* [ ] Verify when resending from the context of the message activity list table, for any messages that had an attached cc value, the cc email address (assuming its valid) receives the emails. -* [ ] Verify for all email sends, that if there is nothing in the cc field, that the message is still sent to/received by the main recipient just fine. - -### Other - -* [ ] Ensure activating any add-ons that add new templates (ticketing for example, or the new Automated Upcoming Event Notifications add-on) still add their custom templates without issues and their messages work as expected. \ No newline at end of file diff --git a/tests/checklists/verifying-disabling-message-context-works.md b/tests/checklists/verifying-disabling-message-context-works.md deleted file mode 100644 index b3e55f572e1..00000000000 --- a/tests/checklists/verifying-disabling-message-context-works.md +++ /dev/null @@ -1,10 +0,0 @@ -Tests whether disabling a message context works as expected for generating and sending messages. - -* [ ] Pick a message template to edit (doesn't matter which - but pick one that has all contexts with "To" field content) -* [ ] In the editor for the message template, verify the UI for enabling/disabling context appears. -* [ ] Verify the action of enabling/disabling the context works as expected and ONLY disables/enables for that message template. -* [ ] Verify that the context disabled reflects that state for the context label in the Message Template List Table. -* [ ] Leave the context disabled. -* [ ] Trigger a message to send for that message template (doesn't matter how you trigger) and verify that no messages for the disabled context are sent. -* [ ] Verify that even if a context is enabled and there is no "To" field content that the context will still not be generated/sent. - \ No newline at end of file diff --git a/tests/includes/AddonLoader.php b/tests/includes/AddonLoader.php deleted file mode 100644 index d3aafc301eb..00000000000 --- a/tests/includes/AddonLoader.php +++ /dev/null @@ -1,24 +0,0 @@ -addon_tests_path = $addon_tests_path; - $this->addon_main_path = $addon_main_path; - $this->addon_main_file = $addon_main_file; - } - - - public function setupAndLoadEE() - { - parent::setupAndloadEE(); - //bootstrap addon - require $this->addon_main_path . $this->addon_main_file; - } -} \ No newline at end of file diff --git a/tests/includes/CoreLoader.php b/tests/includes/CoreLoader.php deleted file mode 100644 index 239e1867f7f..00000000000 --- a/tests/includes/CoreLoader.php +++ /dev/null @@ -1,227 +0,0 @@ -setConstants(); - $this->preLoadWPandEE(); - $this->loadWP(); - $this->postLoadWPandEE(); - $this->requireTestCaseParents(); - $this->bootstrapMockAddon(); - $this->onShutdown(); - \EventEspresso\core\services\Benchmark::writeResultsAtShutdown( - EVENT_ESPRESSO_UPLOAD_DIR . 'logs/benchmarking-master.html', false - ); - } - - protected function setConstants() - { - if (! defined('EE_TESTS_DIR')) { - if (getenv('EE_TESTS_DIR')) { - define('EE_TESTS_DIR', getenv('EE_TESTS_DIR')); - define('EE_PLUGIN_DIR', dirname(dirname(EE_TESTS_DIR)) . '/'); - } else { - define('EE_PLUGIN_DIR', dirname(dirname(dirname(__FILE__))) . '/'); - define('EE_TESTS_DIR', EE_PLUGIN_DIR . 'tests/'); - } - - define('EE_MOCKS_DIR', EE_TESTS_DIR . 'mocks/'); - $_tests_dir = getenv('WP_TESTS_DIR'); - if (! $_tests_dir) { - $_tests_dir = '/tmp/wordpress-tests-lib'; - } - if (file_exists($_tests_dir . '/includes/functions.php')) { - define('WP_TESTS_DIR', $_tests_dir); - } else { - define( - 'WP_TESTS_DIR', - dirname( - dirname( - dirname( - dirname( - dirname( - dirname( - __DIR__ - ) - ) - ) - ) - ) - ) . '/tests/phpunit' - ); - } - // define('EE_REST_API_DEBUG_MODE', true); - } - } - - - protected function preLoadWPandEE() - { - //if WordPress test suite isn't found then we can't do anything. - if (! is_readable(WP_TESTS_DIR . '/includes/functions.php')) { - die("The WordPress PHPUnit test suite could not be found.\n"); - } - require_once WP_TESTS_DIR . '/includes/functions.php'; - require_once EE_PLUGIN_DIR . 'core/Psr4Autoloader.php'; - //set filter for bootstrapping EE which needs to happen BEFORE loading WP. - tests_add_filter('muplugins_loaded', array($this, 'setupAndLoadEE')); - } - - - protected function loadWP() - { - require WP_TESTS_DIR . '/includes/bootstrap.php'; - } - - - public function setupAndLoadEE() - { - tests_add_filter('FHEE__EE_System__detect_if_activation_or_upgrade__testsbypass', '__return_true'); - //make sure EE_session does not load - tests_add_filter('FHEE_load_EE_Session', '__return_false'); - // and don't set cookies - tests_add_filter('FHEE__EE_Error__get_error__show_normal_exceptions', '__return_true'); - // we need to add these filters BEFORE the Registry is instantiated - tests_add_filter( - 'FHEE__EE_Registry____construct___class_abbreviations', - function ($class_abbreviations = array()) { - $class_abbreviations['EE_Session_Mock'] = 'SSN'; - return $class_abbreviations; - } - ); - tests_add_filter( - 'FHEE__EE_Registry__load_core__core_paths', - function ($core_paths = array()) { - $core_paths[] = EE_TESTS_DIR . 'mocks' . DS . 'core' . DS; - return $core_paths; - } - ); - // and this stuff needs to happen just AFTER the Registry initializes - tests_add_filter( - 'EE_Load_Espresso_Core__handle_request__initialize_core_loading', - array($this, 'setupDependencyMap'), - 15 - ); - // Bootstrap EE - require EE_PLUGIN_DIR . 'espresso.php'; - //save wpdb queries in case we want to know what queries ran during a test - if (! defined('SAVEQUERIES')) { - define('SAVEQUERIES', true); - } - add_action( - 'AHEE__EE_System__core_loaded_and_ready', - function () - { - LoaderFactory::getLoader()->getShared( - 'EventEspresso\core\services\notifications\PersistentAdminNoticeManager' - ); - } - ); - } - - - /** - * @throws \DomainException - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException - * @throws \InvalidArgumentException - */ - public function setupDependencyMap() - { - EE_Dependency_Map::register_class_loader('EE_Session_Mock'); - EE_Dependency_Map::register_dependencies( - 'EE_Session_Mock', - array( - 'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache, - 'EventEspresso\core\domain\values\session\SessionLifespan' => EE_Dependency_Map::load_from_cache, - 'EventEspresso\core\services\request\Request' => EE_Dependency_Map::load_from_cache, - 'EE_Encryption' => EE_Dependency_Map::load_from_cache, - ) - ); - EE_Dependency_Map::register_dependencies( - 'EventEspresso\core\services\cache\BasicCacheManager', - array( - 'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache, - 'EE_Session_Mock' => EE_Dependency_Map::load_from_cache - ), - true - ); - EE_Dependency_Map::register_dependencies( - 'EventEspresso\core\services\cache\PostRelatedCacheManager', - array( - 'EventEspresso\core\services\cache\TransientCacheStorage' => EE_Dependency_Map::load_from_cache, - 'EE_Session_Mock' => EE_Dependency_Map::load_from_cache - ), - true - ); - EE_Dependency_Map::instance()->add_alias( - 'EE_Session_Mock', - 'EventEspresso\core\domain\services\session\SessionIdentifierInterface' - ); - } - - - public function postLoadWPandEE() - { - // ensure date and time formats are set - if (! get_option('date_format')) { - update_option('date_format', 'F j, Y'); - } - if (! get_option('time_format')) { - update_option('time_format', 'g:i a'); - } - EE_Registry::instance()->SSN = EE_Registry::instance()->load_core('EE_Session_Mock'); - } - - - - protected function requireTestCaseParents() - { - //Load the EE_specific testing tools - require EE_TESTS_DIR . 'includes/EE_UnitTestCase.class.php'; - require EE_TESTS_DIR . 'includes/EE_REST_TestCase.php'; - } - - - protected function bootstrapMockAddon() - { - require_once EE_TESTS_DIR . 'mocks/addons/eea-new-addon/eea-new-addon.php'; - remove_action('AHEE__EE_System__load_espresso_addons', 'load_espresso_new_addon'); - } - - - - protected function onShutdown() - { - //nuke all EE4 data once the tests are done, so that it doesn't carry over to the next time we run tests - register_shutdown_function( - function () { - EEH_Activation::delete_all_espresso_tables_and_data(); - } - ); - } - - - /** - * @param array $maps - */ - public function registerPsr4Path(array $maps) - { - foreach ($maps as $prefix => $base_dir) { - EE_Psr4AutoloaderInit::psr4_loader()->addNamespace( - $prefix, - $base_dir - ); - } - } -} diff --git a/tests/includes/EE_REST_TestCase.php b/tests/includes/EE_REST_TestCase.php deleted file mode 100644 index 8b35ae904ce..00000000000 --- a/tests/includes/EE_REST_TestCase.php +++ /dev/null @@ -1,75 +0,0 @@ -markTestSkipped( - 'Test being run on a version of WP that does not have the REST framework installed' - ); - } - - if (! function_exists('rest_validate_value_from_schema')) { - $this->markTestSkipped( - 'Test being run on a version of WP that does not have the `rest_validate_value_from_schema` function available.' - ); - } - - add_filter('rest_url', array($this, 'filter_rest_url_for_leading_slash'), 10, 2); - /** @var WP_REST_Server $wp_rest_server */ - global $wp_rest_server; - $this->server = $wp_rest_server = new \Spy_REST_Server; - do_action('rest_api_init'); - } - - public function tearDown() - { - parent::tearDown(); - remove_filter('rest_url', array($this, 'test_rest_url_for_leading_slash'), 10, 2); - /** @var WP_REST_Server $wp_rest_server */ - global $wp_rest_server; - $this->server = $wp_rest_server = null; - } - - public function filter_rest_url_for_leading_slash($url, $path) - { - if (is_multisite()) { - return $url; - } - - // Make sure path for rest_url has a leading slash for proper resolution. - $this->assertTrue(0 === strpos($path, '/'), 'REST API URL should have a leading slash.'); - - return $url; - } - - /** - * Creates a new wp admin user and sets them to the new current user - * - * @global \WP_User $current_user - * @return \WP_User - */ - public function authenticate_as_admin() - { - global $current_user; - $current_user = $this->wp_admin_with_ee_caps(); - return $current_user; - } -} \ No newline at end of file diff --git a/tests/includes/EE_UnitTestCase.class.php b/tests/includes/EE_UnitTestCase.class.php deleted file mode 100644 index 81bd9fea361..00000000000 --- a/tests/includes/EE_UnitTestCase.class.php +++ /dev/null @@ -1,1395 +0,0 @@ -getName()) . '()'; - //save the hooks state before WP_UnitTestCase actually gets its hands on it... - //as it immediately adds a few hooks we might not want to backup - global $auto_made_thing_seed, $wp_filter, $wp_actions, $merged_filters, $wp_current_filter, $wpdb, $current_user; - $this->wp_filters_saved = array( - 'wp_filter' => $wp_filter, - 'wp_actions' => $wp_actions, - 'merged_filters' => $merged_filters, - 'wp_current_filter' => $wp_current_filter - ); - $this->_orig_current_user = $current_user instanceof WP_User ? clone $current_user : new WP_User(1); - parent::setUp(); - $auto_made_thing_seed = 1; - //reset wpdb's list of queries executed so it only stores those from the current test - $wpdb->queries = array(); - //the accidental txn commit indicator option shouldn't be set from the previous test - update_option('accidental_txn_commit_indicator', TRUE); - - // Fake WP mail globals, to avoid errors - add_filter('wp_mail', array($this, 'setUp_wp_mail')); - add_filter('wp_mail_from', array($this, 'tearDown_wp_mail')); - add_filter('FHEE__EEH_Activation__create_table__short_circuit', '__return_true'); - add_filter('FHEE__EEH_Activation__add_column_if_it_doesnt_exist__short_circuit', '__return_true'); - add_filter('FHEE__EEH_Activation__drop_index__short_circuit', '__return_true'); - - // load factories - EEH_Autoloader::register_autoloaders_for_each_file_in_folder(EE_TESTS_DIR . 'includes' . DS . 'factories'); - $this->factory = new EE_UnitTest_Factory(); - - //IF we detect we're running tests on WP4.1, then we need to make sure current_user_can tests pass by implementing - //updating all_caps when `WP_User::add_cap` is run (which is fixed in later wp versions). So we hook into the - // 'user_has_cap' filter to do this - $_wp_test_version = getenv('WP_VERSION'); - if ($_wp_test_version && $_wp_test_version === '4.1') { - add_filter('user_has_cap', function ($all_caps, $caps, $args, WP_User $WP_User) { - $WP_User->get_role_caps(); - - return $WP_User->allcaps; - }, 10, 4); - } - //tell EE_Registry to do a hard reset - add_filter( 'FHEE__EE_Registry__reset__hard', '__return_true'); - do_action('AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache'); - // turn off caching for any loaders in use during tests - add_filter('FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache', '__return_true'); - } - - - /** - * @param bool $short_circuit - * @param string $table_name - * @param string $sql - * @return bool - */ - public function _short_circuit_db_implicit_commits($short_circuit = FALSE, $table_name, $sql) - { - $whitelisted_tables = apply_filters('FHEE__EE_UnitTestCase__short_circuit_db_implicit_commits__whitelisted_tables', array()); - if (in_array($table_name, $whitelisted_tables, true)) { - //it's not altering. it's ok - return FALSE; - } else { - return TRUE; - } - } - - public function tearDown() - { - parent::tearDown(); - global $wp_filter, $wp_actions, $merged_filters, $wp_current_filter, $current_user; - $wp_filter = $this->wp_filters_saved['wp_filter']; - $wp_actions = $this->wp_filters_saved['wp_actions']; - $merged_filters = $this->wp_filters_saved['merged_filters']; - $wp_current_filter = $this->wp_filters_saved['wp_current_filter']; - $current_user = $this->_orig_current_user; - $this->_detect_accidental_txn_commit(); - $notices = EE_Error::get_notices(false, false, true); - EE_Error::reset_notices(); - if (!empty($notices['errors'])) { - $error_message = sprintf( - 'The following error(s) occurred during test "%1$s" : %2$s', - get_called_class() . '::' . $this->getName() . '()', - "\n" . $notices['errors'] - ); - $this->fail($error_message); - // if you need a stack trace for the above, then uncomment the following - // it won't be entirely accurate, but might help - // throw new Exception( $error_message ); - } - // turn caching back on for any loaders in use - remove_all_filters('FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache'); - } - - protected function loadTestScenarios() - { - // load scenarios - require_once EE_TESTS_DIR . 'includes/scenarios/EE_Test_Scenario_Classes.php'; - $this->scenarios = new EE_Test_Scenario_Factory($this); - } - - /** - * Detects whether or not a MYSQL query was issued which caused an implicit commit - * (or an explicit one). Basically, we can't do a commit mid-test because it messes - * up the test's state (which means the database state at the time of the commit will - * become the new starting state for all future tests, which will likely cause hard-to-find - * bugs, and makes test results dependent on order of execution) - * @global WPDB $wpdb - * @throws EE_Error - */ - protected function _detect_accidental_txn_commit() - { - //for some reason WP waits until the start of the next test to do this. but - //we prefer to do it now so that we can check for implicit commits - $this->clean_up_global_scope(); - //now we can check if there was an accidental implicit commit - if (!self::$accidental_txn_commit_noted && get_option('accidental_txn_commit_indicator', FALSE)) { - global $wpdb; - self::$accidental_txn_commit_noted = TRUE; - throw new EE_Error(sprintf(__("Accidental MySQL Commit was issued sometime during the previous test. This means we couldn't properly restore database to its pre-test state. If this doesnt create problems now it probably will later! Read up on MySQL commits, especially Implicit Commits. Queries executed were: \r\n%s. \r\nThis accidental commit happened during %s", 'event_espresso'), print_r($wpdb->queries, TRUE), $this->getName())); - } - } - - - /** - * Use this to clean up any global scope singletons etc that we may have being used by EE so - * that they are fresh between tests. - * - * @todo this of course means we need an easy way to reset our singletons... - * @see parent::cleanup_global_scope(); - */ - public function clean_up_global_scope() - { - parent::clean_up_global_scope(); - } - - - /** - * Set up globals necessary to avoid errors when using wp_mail() - */ - public function setUp_wp_mail($args) - { - if (isset($_SERVER['SERVER_NAME'])) { - $this->_cached_SERVER_NAME = $_SERVER['SERVER_NAME']; - } - - $_SERVER['SERVER_NAME'] = 'example.com'; - - // passthrough - return $args; - } - - - /** - * Tear down globals set up in setUp_wp_mail() - */ - public function tearDown_wp_mail($args) - { - if (!empty($this->_cached_SERVER_NAME)) { - $_SERVER['SERVER_NAME'] = $this->_cached_SERVER_NAME; - unset($this->_cached_SERVER_NAME); - } else { - unset($_SERVER['SERVER_NAME']); - } - - // passthrough - return $args; - } - - - /** - * Helper method for setting the maintenance mode of EE to given maintenance mode - * - * @param int $level use to indicate which maintenance mode to set. - * @since 4.3.0 - */ - public function setMaintenanceMode($level = 0) - { - EE_Registry::instance()->load_core('Maintenance_Mode'); - switch ($level) { - case EE_Maintenance_Mode::level_0_not_in_maintenance : - $level = EE_Maintenance_Mode::level_0_not_in_maintenance; - break; - case EE_Maintenance_Mode::level_1_frontend_only_maintenance : - $level = EE_Maintenance_Mode::level_1_frontend_only_maintenance; - break; - case EE_Maintenance_Mode::level_2_complete_maintenance : - $level = EE_Maintenance_Mode::level_2_complete_maintenance; - break; - default : - $level = EE_Maintenance_Mode::level_0_not_in_maintenance; - break; - } - update_option(EE_Maintenance_Mode::option_name_maintenance_mode, $level); - } - - - /** - * Helper method for just setting the core config and net config on EE_Registry, so - * configuration tests can be run. - * - * @since 4.3.0 - */ - public function setCoreConfig() - { - EE_Registry::instance()->load_core('Config'); - EE_Registry::instance()->load_core('Network_Config'); - } - - - /** - * Helper method for resetting EE_Registry->CFG and EE_Registry->NET_CFG - * - * @since 4.3.0 - */ - public function resetCoreConfig() - { - EE_Registry::instance()->CFG = NULL; - EE_Registry::instance()->NET_CFG = NULL; - } - - - /** - * Method that accepts an array of filter refs to clear all filters from. - * - * @since 4.3.0 - * @param array $filters array of filter refs to clear. (be careful about core wp filters). - */ - public function clearAllFilters($filters = array()) - { - foreach ($filters as $filter) { - remove_all_filters($filter); - } - } - - - /** - * Method that accepts an array of action refs to clear all actions from. - * - * @since 4.3.0 - * @param array $actions array of action refs to clear. (be careful about core wp actions). - */ - public function clearAllActions($actions = array()) - { - foreach ($actions as $action) { - remove_all_actions($action); - } - } - - - /** - * This defines EE_Admin_Constants to point to the admin mocks * folder instead of the default admin folder. Note, you will need - * to be careful of using this. - * - * @since 4.3.0 - */ - public function defineAdminConstants() - { - if (!defined('EE_ADMIN_PAGES')){ - define('EE_ADMIN_PAGES', EE_TESTS_DIR . 'mocks/admin'); - } - } - - - /** - * This loads the various admin mock files required for tests. - * - * @since 4.3.0 - */ - public function loadAdminMocks() - { - require_once EE_TESTS_DIR . 'mocks/admin/EE_Admin_Mocks.php'; - require_once EE_TESTS_DIR . 'mocks/admin/admin_mock_valid/Admin_Mock_Valid_Admin_Page.core.php'; - require_once EE_TESTS_DIR . 'mocks/admin/pricing/espresso_events_Pricing_Hooks_Mock.php'; - require_once EE_TESTS_DIR . 'mocks/admin/registrations/EE_Registrations_List_Table_Mock.php'; - } - - - /** - * This loads the various admin page mock files required for tests. - * Note these pages should be loaded on demand, because constants will be defined that will interfere with other Admin Page loading tests. - * @since 4.6.0 - * @param string $page - */ - public function delayedAdminPageMocks($page = '') - { - - switch ($page) { - case 'decaf_events' : - case 'events' : - require_once EE_TESTS_DIR . 'mocks/admin/events/Events_Admin_Page_Mock.php'; - break; - case 'registrations' : - require_once EE_TESTS_DIR . 'mocks/admin/registrations/Registrations_Admin_Page_Mock.php'; - break; - case 'transactions' : - require_once EE_TESTS_DIR . 'mocks/admin/transactions/Transactions_Admin_Page_Mock.php'; - break; - case 'messages' : - require_once EE_TESTS_DIR . 'mocks/admin/messages/Messages_Admin_Page_Mock.php'; - break; - - } - } - - - public function loadMessagesMocks() - { - require_once EE_TESTS_DIR . 'mocks/core/libraries/messages/validators/EE_Messages_Validator_Mock.php'; - } - - - /** - * @param array $ModelsMocks array of Model class names like "EEM_Event" - */ - public function loadModelsMocks($ModelsMocks = array()) - { - foreach ($ModelsMocks as $ModelsMock) { - require_once EE_TESTS_DIR . 'mocks/core/db_models/' . $ModelsMock . '_Mock.php'; - } - } - - - /** - * @param array $ModelFieldMocks array of Model Field class names like "EE_Datetime_Field" - */ - public function loadModelFieldMocks($ModelFieldMocks = array()) - { - foreach ($ModelFieldMocks as $ModelFieldMock) { - require_once EE_TESTS_DIR . 'mocks/core/db_models/fields/' . $ModelFieldMock . '_Mock.php'; - } - } - - - /** - * @param array $ModuleMocks array of Module class names like "EED_Single_Page_Checkout" - */ - public function loadModuleMocks($ModuleMocks = array()) - { - foreach ($ModuleMocks as $ModuleMock) { - require_once EE_TESTS_DIR . 'mocks/modules/' . $ModuleMock . '_Mock.php'; - } - } - - - /** - * This returns an array of date and time formats that are commonly used in testing. - * - * @return array - */ - public function date_formats_to_test() - { - return array( - 'date' => array( - 'F j, Y', - 'Y-m-d', - 'm/d/Y', - 'd/m/Y', - 'j F, Y', - 'd-m-Y', - 'm-d-Y', - 'd-m Y', - '\D\a\t\e\: Y-m-d' - ), - 'time' => array( - 'g:i a', - 'g:i A', - 'H: i', - 'h:i:s a', - '\T\i\m\e\: g:i a' - ) - ); - } - - - /** - * This sets a bunch of default dates for common data properties using dates for testing. - * - * @param string $timezone Timezone string to initialize the times in. - */ - protected function _set_default_dates($timezone = 'America/Vancouver') - { - $tz = new DateTimeZone($timezone); - $this->_default_dates = array( - 'DTT_start' => new DateTime('2015-02-20 11:30 am', $tz), - 'DTT_end' => new DateTime('2015-02-20 2:00 pm', $tz), - 'TKT_start' => new DateTime('2015-01-30 8:00 am', $tz), - 'TKT_end' => new DateTime('2015-02-20 8:00 am', $tz) - ); - } - - - /** - * _get_one_month_period_offset_in_days - * - * returns a period offset of one month - * for example : P31D, P30D, etc - * this can be used to calculate a date that is guaranteed to occur LAST month - * - * Note, the reason for using this instead of P1M is because - * the PHP Interval for a month is calculated based on either - * the previous or next month depending on if you are - * subtracting or adding a date interval. - * So subtracting a month, would subtract the number of days for the previous month, - * and adding a month will add the number of days for the next month. - * Example: - * if today's date is March 31st, and you want to subtract P1M, - * PHP would subtract the number of days in February (the previous month), - * so 31 - 28 = 3, leaving you with a date of March 03. - * - * Similarly, if you were to add P1M to Feb 1st, - * PHP would add 31 days, because the next month, March, has 31 days - * so, Feb 1 + 31 days = March 4th or 5th depending on the leap year - * - * There is a weird PHP behaviour where subtracting one month - * will result in a date remaining in March. - * see http://php.net/manual/en/datetime.sub.php#example-2469 - * - * @param \DateTime $now - * @param bool $adding_interval - * @return string - */ - protected function _get_one_month_period_offset_in_days(DateTime $now, $adding_interval = true) - { - $year = (int)$now->format('Y'); - $month = (int)$now->format('n'); - $day = (int)$now->format('j'); - // determine how to increment or decrement the year and month - if ($adding_interval && $month === 12) { - // adding a month to december? - $year++; - $month = 1; - } else if ($adding_interval) { - $month++; - } else if ($month === 1) { - $year--; - $month = 12; - } else { - $month--; - } - // create a date for the first day in the offset month (actual day doesn't really matter) - $offset_month = new DateTime("{$year}-{$month}-01"); - // get the number of days in the offset month - $days_in_offset_month = (int)$offset_month->format('t'); - // get the number of days in the original passed month - $days_in_month = (int)$now->format('t'); - // now figure out what period to actually return - // by looking at whether we are adding or subtract a time period - // and also comparing the days in each month, - // as well as the day of the month we are currently on - if ($adding_interval && $day > $days_in_offset_month) { - // add 1 month to Jan 31, but wait.... - // adding 31 days would take us into March !!! - // so just add the number of days in February - //echo "\n add days_in_offset_month : " . $days_in_offset_month; - return "P{$days_in_offset_month}D"; - } else if ($adding_interval) { - // all other additions can safely just use the number of days in the current month - // ie: Jan 27 can add 31 days - //echo "\n add days_in_month : " . $days_in_month; - return "P{$days_in_month}D"; - } else if ($day > $days_in_offset_month) { - // subtract 1 month from March 28, but wait... - // subtracting 31 days could take us to Feb 25 !!! - // so just subtract the day of the month we are on - // Mar 31 - 31 = Mar 30 - 30 = Mar 29 - 29 = Feb 28 (or 29th if a leap year) - //echo "\n subtract day : " . $day; - return "P{$day}D"; - } else { - // all other subtractions can safely just use the number of days in the current month - //echo "\n subtract days_in_month : " . $days_in_month; - return "P{$days_in_offset_month}D"; - } - } - - - /** - * _get_date_one_month_ago - * - * correctly calculates a date that is slightly more than one month in the past from passed date - * - * @param \DateTime $now - * @return \DateTime - */ - protected function _get_date_one_month_ago(DateTime $now) - { - // clone passed date so as not to modify it - $last_month = clone $now; - // one month period in days - $one_month_period = $this->_get_one_month_period_offset_in_days($last_month, false); - // now set $last_month back by our one month period - return $last_month->sub(new DateInterval($one_month_period)); - } - - - /** - * _get_date_one_month_from_now - * - * correctly calculates a date that is slightly more than one month in the future from passed date - * - * @param \DateTime $now - * @return \DateTime - */ - protected function _get_date_one_month_from_now(DateTime $now) - { - // clone passed date so as not to modify it - $next_month = clone $now; - // one month period in days - $one_month_period = $this->_get_one_month_period_offset_in_days($next_month); - // set $next_month ahead by our one month period - return $next_month->add(new DateInterval($one_month_period)); - } - - - /** - * @param string $expected_date The expected date string in the given full_format date string format. - * @param string $actual_date The actual date string in the given full_format date string format. - * @param $full_format - * @param string $custom_error_message - * @throws \EE_Error - */ - public function assertDateWithinOneMinute($expected_date, $actual_date, $full_format, $custom_error_message = '') - { - //take the incoming date strings convert to datetime objects and verify they are within one minute of each other - $expected_date_obj = date_create_from_format($full_format, $expected_date); - $actual_date_obj = date_create_from_format($full_format, $actual_date); - $date_parsing_error = ''; - if (!$expected_date_obj instanceof DateTime) { - $date_parsing_error = sprintf( - __('Expected date %1$s could not be parsed into format %2$s', 'event_espresso'), - print_r($expected_date, true), - $full_format - ); - } - if (!$actual_date_obj instanceof DateTime) { - $date_parsing_error = sprintf( - __('Actual date %1$s could not be parsed into format %2$s', 'event_espresso'), - print_r($actual_date, true), - $full_format - ); - } - if ($date_parsing_error) { - throw new EE_Error($date_parsing_error); - } - $difference = $actual_date_obj->format('U') - $expected_date_obj->format('U'); - $custom_error_message = !empty($custom_error_message) - ? $custom_error_message - : sprintf( - __( - 'The expected date "%1$s" differs from the actual date "%2$s" by more than one minute', - 'event_espresso' - ), - print_r($expected_date, true), - print_r($actual_date, true) - ); - $this->assertTrue($difference < 60, $custom_error_message); - } - - - /** - * This sets up some save data for use in testing updates and saves via the event editor. - * - * @todo Add extra event data for testing event creation/save. - * @param string $format The format used for incoming date strings. - * @param string $prefix A string to prefix the fields being assembled. Used as a way of - * differentiating between multiple calls. - * @param string $row Equals the value we want to give for row. - * @param string $timezone Timezone string to add to the timezone data point. Remember that - * $this->_default_date() datetime objects are used for the default dates, so if - * you include a string here make sure it matches what you set used for setting - * _default_dates unless you are intentionally testing timezone mismatches. - * - * @return array of data in post format from the save action. - */ - protected function _get_save_data($format = 'Y-m-d h:i a', $prefix = '', $row = '1', $timezone = 'America/Vancouver') - { - $data = array( - 'starting_ticket_datetime_rows' => array( - $row => '' - ), - 'ticket_datetime_rows' => array( - $row => '1' - ), - 'datetime_IDs' => '', - 'edit_event_datetimes' => array( - $row => array( - 'DTT_EVT_end' => $this->_default_dates['DTT_end']->format($format), - 'DTT_EVT_start' => $this->_default_dates['DTT_start']->format($format), - 'DTT_ID' => '0', - 'DTT_name' => $prefix . ' Datetime A', - 'DTT_description' => $prefix . ' Lorem Ipsum Emitetad', - 'DTT_reg_limit' => '', - 'DTT_order' => $row - ) - ), - 'edit_tickets' => array( - $row => array( - 'TKT_ID' => '0', - 'TKT_base_price' => '0', - 'TKT_base_price_ID' => '1', - 'TTM_ID' => '0', - 'TKT_name' => $prefix . ' Ticket A', - 'TKT_description' => $prefix . ' Lorem Ipsum Tekcit', - 'TKT_start_date' => $this->_default_dates['TKT_start']->format($format), - 'TKT_end_date' => $this->_default_dates['TKT_end']->format($format), - 'TKT_qty' => '', - 'TKT_uses' => '', - 'TKT_min' => '', - 'TKT_max' => '', - 'TKT_row' => '', - 'TKT_order' => $row, - 'TKT_taxable' => '0', - 'TKT_required' => '0', - 'TKT_price' => '0', - 'TKT_is_default' => '0' - ) - ), - 'edit_prices' => array( - $row => array( - 'PRT_ID' => '1', - 'PRC_ID' => '0', - 'PRC_amount' => '0', - 'PRC_name' => $prefix . ' Price A', - 'PRC_desc' => $prefix . ' Lorem Ipsum Ecirp', - 'PRC_is_default' => '1', - 'PRC_order' => $row - ) - ), - 'timezone_string' => $timezone - ); - return $data; - } - - - /** - * IT would be better to add a constraint and do this properly at some point - * @param mixed $item - * @param $haystack - */ - public function assertArrayContains($item, $haystack) - { - $in_there = in_array($item, $haystack, true); - if ($in_there) { - $this->assertTrue(true); - } else { - $this->assertTrue($in_there, sprintf(__('Array %1$s does not contain %2$s', 'event_espresso'), print_r($haystack, true), print_r($item, true))); - } - } - - - /** - * @param $item - * @param $haystack - */ - public function assertArrayDoesNotContain($item, $haystack) - { - $not_in_there = !in_array($item, $haystack, true); - if ($not_in_there) { - $this->assertTrue($not_in_there); - } else { - $this->assertTrue($not_in_there, sprintf(__('Array %1$s DOES contain %2$s when it shouldn\'t', 'event_espresso'), print_r($haystack, true), print_r($item, true))); - } - } - - /** - * - * @param string $option_name - */ - public function assertWPOptionExists($option_name) - { - $option = get_option($option_name, NULL); - if ($option) { - $this->assertTrue(true); - } else { - $this->assertNotNull($option, sprintf(__('The WP Option "%s" does not exist but should', 'event_espresso'), $option_name)); - } - } - - - /** - * @param $option_name - */ - public function assertWPOptionDoesNotExist($option_name) - { - $option = get_option($option_name, NULL); - if ($option) { - $this->assertNull($option, sprintf(__('The WP Option "%s" exists but shouldn\'t', 'event_espresso'), $option_name)); - } else { - $this->assertTrue(true); - } - } - - - - /** - * Compares two EE model objects by just looking at their field's values. If you want strict comparison just use ordinary '==='. - * If you pass it two arrays of EE objects, that works too - * - * @param EE_Base_Class|EE_Base_Class[] $expected_object - * @param EE_Base_Class|EE_Base_Class[] $actual_object - * @throws \EE_Error - */ - public function assertEEModelObjectsEquals($expected_object, $actual_object) - { - if (is_array($expected_object)) { - $this->assertTrue(is_array($actual_object)); - foreach ($expected_object as $single_expected_object) { - $this->assertEEModelObjectsEquals($single_expected_object, array_shift($actual_object)); - } - } else { - $this->assertInstanceOf('EE_Base_Class', $expected_object); - $this->assertInstanceOf('EE_Base_Class', $actual_object); - $this->assertEquals(get_class($expected_object), get_class($actual_object)); - foreach ($expected_object->model_field_array() as $field_name => $expected_value) { - $actual_value = $actual_object->get($field_name); - if ($expected_value !== $actual_value) { - $this->fail( - sprintf( - __('EE objects for the field %4$s of class "%1$s" did not match. They were: %2$s and %3$s. The values for the field were %5$s and %6$s', 'event_espresso'), - get_class($expected_object), - print_r($expected_object->model_field_array(), true), - print_r($actual_object->model_field_array(), true), - $field_name, - print_r($expected_value, true), - print_r($actual_value, true) - ) - ); - } - } - } - } - - /** - * Compares HTML, ignoring whitespace differences; also tries to make differences - * more obvious for comparison in PHPUnit results. - * Ideally this would actually parse the HTML, and just verify its functionality equivalent. - * Eg, ignore case differences,unnecessary whitespace differences (eg '< br >' vs '
'), - * attribute order differences, so this would only fail when there would be a noticeable - * difference. The true ideal would be system testing using something codeception or something - * @param string $expected - * @param string $actual - * @param string $error_message - * @return void - */ - public function assertHTMLEquals($expected, $actual, $error_message = null) - { - $expected_standardized_whitespace = preg_replace('~(\\s)+~', PHP_EOL, $expected); - $actual_standardized_whitespace = preg_replace('~(\\s)+~', PHP_EOL, $actual); - $this->assertEquals($expected_standardized_whitespace, $actual_standardized_whitespace, $error_message); - } - - - /** - *Creates a model object and its required dependencies - * @param string $model_name - * @param array $args array of arguments to supply when constructing the model object - * @param boolean $save - * @throws EE_Error - * @global int $auto_made_thing_seed - * @return EE_Base_Class - */ - public function new_model_obj_with_dependencies($model_name, $args = array(), $save = true) - { - global $auto_made_thing_seed; - if ($auto_made_thing_seed === NULL) { - $auto_made_thing_seed = 1; - } - $model = EE_Registry::instance()->load_model($model_name); - - //set the related model foreign keys - foreach ($model->relation_settings() as $related_model_name => $relation) { - if ($relation instanceof EE_Belongs_To_Any_Relation) { - continue; - } elseif ($related_model_name === 'WP_User' && get_current_user_id()) { - $fk = $model->get_foreign_key_to($related_model_name); - if (! isset($args[$fk->get_name()])) { - $obj = \EEM_WP_User::instance()->get_one_by_ID(get_current_user_id()); - $args[$fk->get_name()] = $obj->ID(); - } - } elseif ($related_model_name === 'Country' && ! isset($args['CNT_ISO'])) { - //we already have lots of countries. lets not make any more - //what's more making them is tricky: the primary key needs to be a unique - //2-character string but not an integer (else it confuses the country - //form input validation) - $args['CNT_ISO'] = 'US'; - } elseif ($related_model_name === 'Status') { - $fk = $model->get_foreign_key_to($related_model_name); - if (!isset($args[$fk->get_name()])) { - //only set the default if they haven't specified anything - $args[$fk->get_name()] = $fk->get_default_value(); - } - } elseif ($relation instanceof EE_Belongs_To_Relation) { - $obj = $this->new_model_obj_with_dependencies($related_model_name); - $fk = $model->get_foreign_key_to($related_model_name); - if (!isset($args[$fk->get_name()])) { - $args[$fk->get_name()] = $obj->ID(); - } - } - } - //set any other fields which haven't yet been set - foreach ($model->field_settings() as $field_name => $field) { - $value = NULL; - if ( - in_array( - $field_name, - array( - 'EVT_timezone_string', - 'PAY_redirect_url', - 'PAY_redirect_args', - 'TKT_reserved', - 'DTT_reserved', - 'parent', - //don't make system questions etc - 'QST_system', - 'QSG_system', - 'QSO_system' - ), - true - ) - ) { - $value = NULL; - } elseif ( - $field_name === 'TKT_start_date' || - $field_name === 'DTT_EVT_start' - ) { - $value = time() + MONTH_IN_SECONDS; - } elseif ( - $field_name === 'TKT_end_date' || - $field_name === 'DTT_EVT_end' - ) { - $value = time() + MONTH_IN_SECONDS + DAY_IN_SECONDS; - } elseif ( - $field instanceof EE_Enum_Integer_Field || - $field instanceof EE_Enum_Text_Field || - $field instanceof EE_Boolean_Field || - $field_name === 'PMD_type' || - $field_name === 'CNT_cur_dec_mrk' || - $field_name === 'CNT_cur_thsnds' || - $field_name === 'CNT_tel_code' - ) { - $value = $field->get_default_value(); - } elseif ( - $field instanceof EE_Integer_Field || - $field instanceof EE_Float_Field || - $field instanceof EE_Foreign_Key_Field_Base || - $field_name === 'STA_abbrev' || - $field_name === 'CNT_ISO3' || - $field_name === 'CNT_cur_code' - ) { - $value = $auto_made_thing_seed; - } elseif ($field instanceof EE_Primary_Key_String_Field) { - $value = "$auto_made_thing_seed"; - } elseif ($field instanceof EE_Email_Field) { - $value = $auto_made_thing_seed . 'ee@ee' . $auto_made_thing_seed . '.dev'; - } elseif ($field instanceof EE_Text_Field_Base) { - $value = $auto_made_thing_seed . "_" . $field_name; - } - if (!array_key_exists($field_name, $args) && $value !== NULL) { - $args[$field_name] = $value; - } - } - //and finally make the model obj - $classname = 'EE_' . $model_name; - $model_obj = $classname::new_instance($args); - if ($save) { - $success = $model_obj->save(); - if (!$success) { - global $wpdb; - throw new EE_Error( - sprintf( - __('Could not save %1$s using %2$s. Error was %3$s', 'event_espresso'), - $model_name, - wp_json_encode($args), - $wpdb->last_error - ) - ); - } - } - $auto_made_thing_seed++; - return $model_obj; - - } - - - /** - * asserts that a table (even temporary one) exists - * We really should implement this function in the proper PHPunit style - * @see http://php-and-symfony.matthiasnoback.nl/2012/02/phpunit-writing-a-custom-assertion/ - * @global WPDB $wpdb - * @param string $table_name with or without $wpdb->prefix - * @param string $model_name the model's name (only used for error reporting) - */ - public function assertTableExists($table_name, $model_name = 'Unknown') - { - $table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true); - if (!$table_analysis->tableExists($table_name)) { - global $wpdb; - $this->fail($wpdb->last_error); - } - } - - /** - * Asserts the table (even temporary one) does not exist - * We really should implement this function in the proper PHPunit style - * @see http://php-and-symfony.matthiasnoback.nl/2012/02/phpunit-writing-a-custom-assertion/ - * @global WPDB $wpdb - * @param string $table_name with or without $wpdb->prefix - * @param string $model_name the model's name (only used for error reporting) - */ - public function assertTableDoesNotExist($table_name, $model_name = 'Unknown') - { - $table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true); - if ($table_analysis->tableExists($table_name)) { - $this->fail( - sprintf( - __('Table like %1$s SHOULD NOT exist. It was apparently defined on the model "%2$s"', 'event_espresso'), - $table_name, - $model_name - ) - ); - } - } - - /** - * Modifies the $wp_actions global to make it look like certain actions were and weren't - * performed, so that EE_Register_Addon is deceived into thinking it's the right - * time to register an addon etc - * @global array $wp_actions - */ - protected function _pretend_addon_hook_time() - { - global $wp_actions; - unset( - $wp_actions['AHEE__EE_System___detect_if_activation_or_upgrade__begin'], - $wp_actions['FHEE__EE_System__parse_model_names'], - $wp_actions['FHEE__EE_System__parse_implemented_model_names'], - $wp_actions['AHEE__EE_System__register_shortcodes_modules_and_widgets'] - ); - $wp_actions['AHEE__EE_System__load_espresso_addons'] = 1; - } - - /** - * Restores the $wp_actions global to how ti should have been before we - * started pretending we hooked in at the right time etc - * @global array $wp_actions - */ - protected function _stop_pretending_addon_hook_time() - { - global $wp_actions; - $wp_actions['AHEE__EE_System___detect_if_activation_or_upgrade__begin'] = 1; - $wp_actions['FHEE__EE_System__parse_model_names'] = 1; - $wp_actions['FHEE__EE_System__parse_implemented_model_names'] = 1; - unset($wp_actions['AHEE__EE_System__load_espresso_addons']); - } - - - - /** - * Makes a complete transaction record with all associated data (ie, its line items, - * registrations, tickets, datetimes, events, attendees, questions, answers, etc). - * - * @param array $options { - * @type int $ticket_types the number of different ticket types in this transaction. Default 1 - * @type int $taxable_tickets how many of those ticket types should be taxable. Default EE_INF - * } - * @return EE_Transaction - * @throws \EE_Error - */ - protected function new_typical_transaction($options = array()) - { - /** @var EE_Transaction $txn */ - $txn = $this->new_model_obj_with_dependencies('Transaction', array('TXN_paid' => 0)); - $total_line_item = EEH_Line_Item::create_total_line_item($txn->ID()); - $total_line_item->save_this_and_descendants_to_txn($txn->ID()); - $ticket_types = isset($options['ticket_types']) - ? $options['ticket_types'] - : $ticket_types = 1; - $taxable_tickets = isset($options['taxable_tickets']) - ? $options['taxable_tickets'] - : $taxable_tickets = EE_INF; - $fixed_ticket_price_modifiers = isset($options['fixed_ticket_price_modifiers']) - ? $options['fixed_ticket_price_modifiers'] - : $fixed_ticket_price_modifiers = 1; - $reg_status = isset($options['reg_status']) - ? $options['reg_status'] - : EEM_Registration::status_id_approved; - $setup_reg = isset($options['setup_reg']) - ? $options['setup_reg'] - : true; - $tkt_qty = isset($options['tkt_qty']) - ? $options['tkt_qty'] - : 1; - $ticket_types = isset($options['tickets']) - ? count($options['tickets']) - : $ticket_types; - $taxes = EEM_Price::instance()->get_all_prices_that_are_taxes(); - for ($i = 1; $i <= $ticket_types; $i++) { - /** @var EE_Ticket $ticket */ - if(isset($options['tickets'], $options['tickets'][$i])){ - $ticket = $options['tickets'][$i]; - $reg_final_price = $ticket->price(); - $datetime = $ticket->first_datetime(); - } else { - $ticket = $this->new_model_obj_with_dependencies( - 'Ticket', - array('TKT_price' => $i * 10, 'TKT_taxable' => $taxable_tickets-- > 0 ? true : false) - ); - $sum_of_sub_prices = 0; - for ($j = 1; $j <= $fixed_ticket_price_modifiers; $j++) { - if ($j === $fixed_ticket_price_modifiers) { - $price_amount = $ticket->price() - $sum_of_sub_prices; - } else { - $price_amount = $i * 10 / $fixed_ticket_price_modifiers; - } - /** @var EE_Price $price */ - $price = $this->new_model_obj_with_dependencies( - 'Price', - array('PRC_amount' => $price_amount, 'PRC_order' => $j) - ); - $sum_of_sub_prices += $price->amount(); - $ticket->_add_relation_to($price, 'Price'); - } - /** @var EE_Datetime $datetime */ - $datetime = $this->new_model_obj_with_dependencies('Datetime'); - $ticket->_add_relation_to($datetime, 'Datetime'); - $reg_final_price = $ticket->price(); - foreach ($taxes as $taxes_at_priority) { - foreach ($taxes_at_priority as $tax) { - /** @var EE_Price $tax */ - $reg_final_price += $reg_final_price * $tax->amount() / 100; - } - } - } - $line_item = EEH_Line_Item::add_ticket_purchase($total_line_item, $ticket, $tkt_qty); - $this->assertInstanceOf( - 'EE_Line_Item', - $line_item - ); - if ($setup_reg) { - $this->new_model_obj_with_dependencies( - 'Registration', - array( - 'TXN_ID' => $txn->ID(), - 'TKT_ID' => $ticket->ID(), - 'STS_ID' => $reg_status, - 'EVT_ID' => $datetime->get('EVT_ID'), - 'REG_count' => 1, - 'REG_group_size' => 1, - 'REG_final_price' => $reg_final_price - ) - ); - } - } - $txn->set_total($total_line_item->total()); - $txn->save(); - - return $txn; - } - - - - /** - * Creates an interesting ticket, with a base price, dollar surcharge, and a percent surcharge, - * which is for 2 different datetimes. - * - * @param array $options { - * @type int $dollar_surcharge the dollar surcharge to add to this ticket - * @type int $percent_surcharge teh percent surcharge to add to this ticket (value in percent, not in decimal. Eg if it's a 10% surcharge, enter 10.00, not 0.10 - * @type int $datetimes the number of datetimes for this ticket, - * @type int $TKT_price set the TKT_price to this value. - * @type int $TKT_taxable set the TKT_taxable to this value. - * } - * @return EE_Ticket - * @throws \EE_Error - */ - public function new_ticket($options = array()) - { - // copy incoming options to use for ticket args - $ticket_args = $options; - // make sure ticket price is set or use default of 16.50 - $ticket_args['TKT_price'] = isset($options['TKT_price']) && is_numeric($options['TKT_price']) - ? $options['TKT_price'] - : 16.5; - // apply taxes? default = true - $ticket_args['TKT_taxable'] = isset($options['TKT_taxable']) - ? filter_var($options['TKT_taxable'], FILTER_VALIDATE_BOOLEAN) - : true; - // make sure ticket start and end dates are set else they will default to NOW !!! - $ticket_args['TKT_start_date'] = isset($options['TKT_start_date']) - ? $options['TKT_start_date'] - : time() + MONTH_IN_SECONDS; - $ticket_args['TKT_end_date'] = isset($options['TKT_end_date']) - ? $options['TKT_end_date'] - : time() + MONTH_IN_SECONDS + DAY_IN_SECONDS; - // now dump any other elements that came from the incoming options that are not ticket properties - $ticket_args = array_intersect_key( - $ticket_args, - array( - 'TTM_ID' => 1, - 'TKT_name' => 1, - 'TKT_description' => 1, - 'TKT_start_date' => 1, - 'TKT_end_date' => 1, - 'TKT_min' => 1, - 'TKT_max' => 1, - 'TKT_price' => 1, - 'TKT_sold' => 1, - 'TKT_qty' => 1, - 'TKT_reserved' => 1, - 'TKT_uses' => 1, - 'TKT_required' => 1, - 'TKT_taxable' => 1, - 'TKT_is_default' => 1, - 'TKT_order' => 1, - 'TKT_row' => 1, - 'TKT_deleted' => 1, - 'TKT_wp_user' => 1, - 'TKT_parent' => 1, - ) - ); - /** @type EE_Ticket $ticket */ - $ticket = $this->new_model_obj_with_dependencies('Ticket',$ticket_args); - $base_price_type = EEM_Price_Type::instance()->get_one(array(array('PRT_name' => 'Base Price'))); - $this->assertInstanceOf('EE_Price_Type', $base_price_type); - - //only associate on the tickets if TKT_price is not included - if (!isset($options['TKT_price'])) { - $base_price = $this->new_model_obj_with_dependencies('Price', array('PRC_amount' => 10, 'PRT_ID' => $base_price_type->ID())); - $ticket->_add_relation_to($base_price, 'Price'); - $this->assertArrayContains($base_price, $ticket->prices()); - if (isset($options['dollar_surcharge'])) { - $dollar_surcharge_price_type = EEM_Price_Type::instance()->get_one(array(array('PRT_name' => 'Dollar Surcharge'))); - $this->assertInstanceOf('EE_Price_Type', $dollar_surcharge_price_type); - $dollar_surcharge = $this->new_model_obj_with_dependencies('Price', array('PRC_amount' => $options['dollar_surcharge'], 'PRT_ID' => $dollar_surcharge_price_type->ID())); - $ticket->_add_relation_to($dollar_surcharge, 'Price'); - $this->assertArrayContains($dollar_surcharge, $ticket->prices()); - } - if (isset($options['percent_surcharge'])) { - $percent_surcharge_price_type = EEM_Price_Type::instance()->get_one(array(array('PRT_name' => 'Percent Surcharge'))); - $this->assertInstanceOf('EE_Price_Type', $percent_surcharge_price_type); - $percent_surcharge = $this->new_model_obj_with_dependencies('Price', array('PRC_amount' => $options['percent_surcharge'], 'PRT_ID' => $percent_surcharge_price_type->ID())); - $ticket->_add_relation_to($percent_surcharge, 'Price'); - $this->assertArrayContains($percent_surcharge, $ticket->prices()); - } - } else { - $ticket->set('TKT_price', $options['TKT_price']); - //set the base price - $base_price = $this->new_model_obj_with_dependencies('Price', array('PRC_amount' => $options['TKT_price'], 'PRT_ID' => $base_price_type->ID())); - $ticket->_add_relation_to($base_price, 'Price'); - $this->assertArrayContains($base_price, $ticket->prices()); - } - - if (isset($options['TKT_taxable'])) { - $ticket->set('TKT_taxable', $options['TKT_taxable']); - } - - // were datetimes (and their related events) already setup? - if(!empty($options['datetime_objects']) && is_array($options['datetime_objects'])) { - foreach ($options['datetime_objects'] as $datetime_object) { - $ticket->_add_relation_to($datetime_object, 'Datetime'); - } - } else { - /** - * Set the author to the current user. This is done in case a running test switched the current user global - * after models were instantiated. - */ - global $current_user; - // create new datetimes, default = 1 - $datetimes = isset($options['datetimes']) ? $options['datetimes'] : 1; - $event = $this->new_model_obj_with_dependencies('Event', array('EVT_wp_user' => $current_user->ID)); - for ($i = 0; $i <= $datetimes; $i++) { - $ddt = $this->new_model_obj_with_dependencies( - 'Datetime', - array( - 'EVT_ID' => $event->ID(), - 'DTT_EVT_start' => time() + MONTH_IN_SECONDS, - 'DTT_EVT_end' => time() + MONTH_IN_SECONDS + DAY_IN_SECONDS, - ) - ); - $ticket->_add_relation_to($ddt, 'Datetime'); - $this->assertArrayContains($ddt, $ticket->datetimes()); - } - } - - //resave ticket to account for possible field value changes - $ticket->save(); - return $ticket; - } - - - /** - * Creates a WP user with standard admin caps PLUS all EE CAPS (default) - * - * @param array $ee_capabilities array of EE CAPS if you don't want the user to have ALL EE CAPS - * @return WP_User - * @throws EE_Error - */ - public function wp_admin_with_ee_caps($ee_capabilities = array()) - { - //if caps were provided then just add the caps to a default user role (non admin user). - if ($ee_capabilities) { - /** @type WP_User $user */ - $user = $this->factory->user->create_and_get(); - foreach ($ee_capabilities as $cap) { - $user->add_cap($cap); - } - return $user; - } - /** @type WP_User $user */ - $user = $this->factory->user->create_and_get(array('role' => 'administrator')); - return $user; - } - - - /** - * increments the ticket and datetime sold values - * @param \EE_ticket $ticket - * @param int $qty - * @throws \EE_Error - */ - public function simulate_x_number_ticket_sales(EE_ticket $ticket, $qty = 1) - { - $ticket->increase_sold($qty); - $ticket->save(); - $datetimes = $ticket->datetimes(); - if (is_array($datetimes)) { - foreach ($datetimes as $datetime) { - if ($datetime instanceof EE_Datetime) { - $datetime->increase_sold($qty); - $datetime->save(); - } - } - } - } - - - /** - * decrements the ticket and datetime sold values - * @param \EE_ticket $ticket - * @param int $qty - * @throws \EE_Error - */ - public function reverse_x_number_ticket_sales(EE_ticket $ticket, $qty = 1) - { - $ticket->decrease_sold($qty); - $ticket->save(); - $datetimes = $ticket->datetimes(); - if (is_array($datetimes)) { - foreach ($datetimes as $datetime) { - if ($datetime instanceof EE_Datetime) { - $datetime->decrease_sold($qty); - $datetime->save(); - } - } - } - } - - - - /** - * Calls the WordPress version specific method for refreshing user roles during tests - * @param WP_User $user - */ - protected function refreshRolesForUser(WP_User $user) - { - if (method_exists($user, 'for_site')) { - $user->for_site(); - } else { - $user->_init_caps(); - } - } - - - /** - * \PHPUnit\Framework\TestCase::expectException() only exists in PHPUnit version 5.7+ - * but on Travis-CI we test using PHPUnit 4.8 because it supports PHP versions < 5.6 - * This should call the appropriate method regardless of version - * - * @param string $exception - * @throws \PHPUnit\Framework\Exception - */ - public function setExceptionExpected($exception) - { - if (method_exists($this, 'expectException')) { - parent::expectException($exception); - } elseif (method_exists($this, 'setExpectedException')) { - $this->setExpectedException($exception); - } - } - - - protected function loadShortcodesManagerAndShortcodes() - { - // load, register, and add shortcodes the new way - LoaderFactory::getLoader()->getShared( - 'EventEspresso\core\services\shortcodes\ShortcodesManager', - array( - // and the old way, but we'll put it under control of the new system - EE_Config::getLegacyShortcodesManager() - ) - ); - do_action('AHEE__EE_System__register_shortcodes_modules_and_widgets'); - do_action('AHEE__EE_System__core_loaded_and_ready'); - global $wp_query; - do_action('parse_query', $wp_query); - require_once EE_PUBLIC . 'template_tags.php'; - } - -} diff --git a/tests/includes/EeAddonTestCase.php b/tests/includes/EeAddonTestCase.php deleted file mode 100644 index 9670ab2e413..00000000000 --- a/tests/includes/EeAddonTestCase.php +++ /dev/null @@ -1,145 +0,0 @@ -pretendAddonHookTime(); - $this->registerAddon(); - $this->current_db_state = get_option(EE_Data_Migration_Manager::current_database_state); - delete_option(EE_Data_Migration_Manager::current_database_state); - update_option(EE_Data_Migration_Manager::current_database_state, array('Core' => espresso_version())); - } - - - - public function tearDown() - { - //only need to reset if $this->_addon isn't set - if ($this->addon instanceof EE_Addon) { - update_option($this->addon->get_activation_history_option_name(), $this->addon_activation_history); - update_option(EE_Data_Migration_Manager::current_database_state, $this->current_db_state); - EE_Register_Addon::deregister(EE_NewAddonMock::getCurrentName()); - try { - EE_Registry::instance()->addons->{EE_NewAddonMock::getCurrentName()}; - $this->fail('The addon is still registered. Deregistering the addon failed.'); - } catch (Exception $e) { - $this->assertInstanceOf('OutOfBoundsException', $e); - } - $this->stopPretendingAddonHookTime(); - } - parent::tearDown(); - } - - - protected function registerAddon($addon_name = 'EE_NewAddonMock', $options = array()) - { - //register addon with default options. - EE_NewAddonMock::registerWithGivenOptions($addon_name, $options); - //ensure the addon has been registered - $this->assertArrayHasKey($addon_name, EE_Registry::instance()->addons); - $this->assertInstanceOf($addon_name, EE_Registry::instance()->addons->{$addon_name}); - //assert is the only addon setup - $this->assertCount(1, EE_Registry::instance()->addons); - $this->addon = EE_Registry::instance()->addons->{$addon_name}; - $this->addon_activation_history = $this->addon->get_activation_history(); - } - - - protected function deRegisterAddon($addon_name = 'EE_NewAddonMock') - { - EE_Register_Addon::deregister($addon_name); - } - - - - protected function pretendAddonHookTime() - { - /** @todo move logic from this method into here from EE_UnitTestCase */ - $this->_pretend_addon_hook_time(); - } - - - protected function stopPretendingAddonHookTime() - { - /** @todo move logic from this method into here from EE_UnitTestCase */ - $this->_stop_pretending_addon_hook_time(); - } - - - protected function pretendReactivation() - { - $this->assertEquals(EE_Maintenance_Mode::level_0_not_in_maintenance, EE_Maintenance_Mode::instance()->level()); - //it should have an entry in its activation history and db state - $activation_history_option_name = $this->addon->get_activation_history_option_name(); - update_option($activation_history_option_name, array($this->addon->version() => array(current_time('mysql')))); - $db_state = get_option(EE_Data_Migration_Manager::current_database_state); - $db_state['New_Addon'] = $this->addon->version(); - update_option(EE_Data_Migration_Manager::current_database_state, $db_state); - $this->deRegisterAddon(); - //trigger activate_plugin hook - do_action('activate_plugin'); - $this->registerAddon(); - } -} diff --git a/tests/includes/factories/EE_UnitTest_Factory.class.php b/tests/includes/factories/EE_UnitTest_Factory.class.php deleted file mode 100644 index ab808f2916c..00000000000 --- a/tests/includes/factories/EE_UnitTest_Factory.class.php +++ /dev/null @@ -1,145 +0,0 @@ -event = new EE_UnitTest_Factory_For_Event( $this ); - $this->venue = new EE_UnitTest_Factory_For_Venue( $this ); - $this->datetime = new EE_UnitTest_Factory_For_Datetime( $this ); - $this->datetime_chained = new EE_UnitTest_Factory_For_Datetime( $this, true ); - $this->ticket = new EE_UnitTest_Factory_For_Ticket( $this ); - $this->ticket_chained = new EE_UnitTest_Factory_For_Ticket( $this, true ); - $this->price = new EE_UnitTest_Factory_For_Price( $this ); - $this->price_chained = new EE_UnitTest_Factory_For_Price( $this, true ); - $this->price_type = new EE_UnitTest_Factory_For_Price_Type( $this ); - $this->price_type_chained = new EE_UnitTest_Factory_For_Price_Type( $this, true ); - $this->registration = new EE_UnitTest_Factory_For_Registration( $this ); - $this->registration_chained = new EE_UnitTest_Factory_For_Registration( $this, true ); - $this->transaction = new EE_UnitTest_Factory_For_Transaction( $this ); - $this->transaction_chained = new EE_UnitTest_Factory_For_Transaction( $this, true ); - $this->attendee = new EE_UnitTest_Factory_For_Attendee( $this ); - $this->attendee_chained = new EE_UnitTest_Factory_For_Attendee( $this, true ); - $this->status = new EE_UnitTest_Factory_For_Status( $this ); - $this->payment = new EE_UnitTest_Factory_For_Payment( $this ); - $this->message = new EE_UnitTest_Factory_For_Message( $this ); - - //complex relationship factory - //This is a unique factory (not extending WP_UnitTest_Factory_for_Thing) that builds EE objects from a given special formatted - //setup array outlining object instantiation and relationships. - $this->complex_factory = new EE_UnitTest_Factory_for_Specific_Builds( $this ); - - } -} - - diff --git a/tests/includes/factories/EE_UnitTest_Factory_For_Attendee.class.php b/tests/includes/factories/EE_UnitTest_Factory_For_Attendee.class.php deleted file mode 100644 index 2f27b3cf8d5..00000000000 --- a/tests/includes/factories/EE_UnitTest_Factory_For_Attendee.class.php +++ /dev/null @@ -1,167 +0,0 @@ -_chained = $chained; - //default args for creating attendees - $this->default_generation_definitions = array( - 'ATT_fname' => 'Anonymous', - 'ATT_lname' => new WP_UnitTest_Generator_Sequence( 'Llama %s' ), - 'ATT_address' => new WP_UnitTest_Generator_Sequence( '%s Farm Lane' ), - 'ATT_city' => 'Some Town', - 'ATT_zip' => new WP_UnitTest_Generator_Sequence( '00000%s' ), - 'ATT_email' => new WP_UnitTest_Generator_Sequence( 'llamasrule%s@llama.lm' ), - 'ATT_phone' => '123-123-1234' - ); - } - - - - /** - * This generates the dummy relation objects for use in a new attendee if the $_chained flag is set. Note this is called on EVERY new attendee created when create_many() is called. - * - * @since 4.3.0 - * - * @param array $args arguments that are sent to the factory that *may contain registration id. - * @param int $ATT_ID required to make sure that when registration_chained is called, it does not create a new attendee object but uses THIS attendee and sets the relation. - */ - private function _set_new_relations( $args, $ATT_ID ) { - //registration - $this->_registration = empty( $args[ 'REG_ID' ] ) ? $this->factory->registration_chained->create( array( 'ATT_ID' => $ATT_ID ) ) : EEM_Registration::instance()->get_one_by_ID( $args[ 'REG_ID' ] ); - $this->_registration = empty( $this->_registration ) ? $this->factory->registration_chained->create( array( 'ATT_ID' => $ATT_ID ) ) : $this->_registration; - } - - - - /** - * This handles connecting a attendee to related items when the chained flag is true. - * - * @since 4.3.0 - * - * @param EE_Attendee $attendee - * @param array $args incoming arguments from caller for specifying overrides. - * - * @return EE_Attendee - */ - private function _maybe_chained( EE_Attendee $attendee, $args ) { - if ( $this->_chained ) { - if ( empty( $this->_status ) ) { - $this->_set_repeated_relation( $args, $attendee->ID() ); - } - //YES we DO want to set brand new relation objects because multiple attendees do not share the same related objects (for the purpose of tests at least) - $this->_set_new_relations( $args, $attendee->ID() ); - //note relation to registration should already be set via the factory->registration_chained->create() method. - //add relation to status - $attendee->_add_relation_to( $this->_status, 'Status' ); - $attendee->save(); - return $attendee; - } - return $attendee; - } - - - - /** - * used by factory to create attendee object. - * - * @since 4.3.0 - * - * @param array $args Incoming field values to set on the new object - * - * @return EE_Attendee|false - */ - public function create_object( $args ) { - $attendee = EE_Attendee::new_instance( $args ); - $attendeeID = $attendee->save(); - $attendee = $this->_maybe_chained( $attendee, $args ); - $attendee->save(); - return $attendeeID ? $attendee : false; - } - - - - /** - * Update attendee object for given attendee. - * - * @since 4.3.0 - * - * @param int $ATT_ID Attendee ID for the attendee to update - * @param array $cols_n_data columns and values to change/update - * - * @return EE_Attendee|false. - */ - public function update_object( $ATT_ID, $cols_n_data ) { - //all the stuff for updating an attendee. - $attendee = EEM_Attendee::instance()->get_one_by_ID( $ATT_ID ); - if ( ! $attendee instanceof EE_Attendee ) { - return null; - } - foreach ( $cols_n_data as $key => $val ) { - $attendee->set( $key, $val ); - } - $success = $attendee->save(); - return $success ? $attendee : false; - } - - - - /** - * return the attendee object for a given attendee ID. - * - * @since 4.3.0 - * - * @param int $ATT_ID the attendee id for the attendee to attempt to retrieve - * - * @return mixed null|EE_Attendee - */ - public function get_object_by_id( $ATT_ID ) { - return EEM_Attendee::instance()->get_one_by_ID( $ATT_ID ); - } - - - -} -// End of file EE_UnitTest_Factory_For_Attendee.class.php -// Location: /EE_UnitTest_Factory_For_Attendee.class.php \ No newline at end of file diff --git a/tests/includes/factories/EE_UnitTest_Factory_For_Datetime.class.php b/tests/includes/factories/EE_UnitTest_Factory_For_Datetime.class.php deleted file mode 100644 index eb93f3be573..00000000000 --- a/tests/includes/factories/EE_UnitTest_Factory_For_Datetime.class.php +++ /dev/null @@ -1,178 +0,0 @@ -_chained = $chained; - //default args for creating datetimes - $this->default_generation_definitions = array( - 'DTT_name' => new WP_UnitTest_Generator_Sequence( 'Datetime %s' ), - 'DTT_description' => new WP_UnitTest_Generator_Sequence( 'Datetime Description %s' ), - 'DTT_EVT_start' => strtotime( '+1 month' ), - 'DTT_EVT_end' => strtotime( '+2 months' ) - ); - } - - - - /** - * This allows setting the $_event property to a new event object if the incoming args for the - * new dtt have an event id (or set to default if no evt_id) - * - * @since 4.3.0 - * @param int $EVT_ID EE_Event ID - */ - private function _set_new_event( $EVT_ID = 0 ) { - $this->_event = empty( $EVT_ID ) ? EEM_Event::instance()->get_one_by_ID( $EVT_ID ) : $this->factory->event->create(); - //fail safe just in case (so we can be sure to have an event). - if ( empty( $this->_event ) ) { - $this->_event = $this->factory->event->create(); - } - } - - - - /** - * This handles connecting a datetime to the event object that's been generated. - * - * @since 4.3.0 - * - * @param EE_Datetime $dtt - * @param array $args incoming arguments from caller for specifying overrides. - * - * @return EE_Datetime - */ - private function _maybe_chained( EE_Datetime $dtt, $args ) { - if ( $this->_chained ) { - if ( empty( $this->_event ) ) { - $EVT_ID = isset( $this->_special_args[ 'EVT_ID' ] ) ? $this->_special_args[ 'EVT_ID' ] : 0; - $this->_set_new_event( $EVT_ID ); - } - //add relation to event - $dtt->_add_relation_to( $this->_event, 'Event' ); - $dtt->save(); - return $dtt; - } - return $dtt; - } - - - - /** - * used by factory to create datetime object - * - * @since 4.3.0 - * - * @param array $args Incoming field values to set on the new object - * - * @return EE_Datetime|false - */ - public function create_object( $args ) { - $this->_special_args[ 'EVT_ID' ] = isset( $args[ 'EVT_ID' ] ) ? $args[ 'EVT_ID' ] : 0; - if ( isset( $args[ 'EVT_ID' ] ) ) { - unset( $args[ 'EVT_ID' ] ); - } - //timezone? - if ( isset( $args[ 'timezone' ] ) ) { - $timezone = $args[ 'timezone' ]; - unset( $args[ 'timezone' ] ); - } else { - $timezone = null; - } - //date formats? - if ( isset( $args[ 'formats' ] ) && is_array( $args[ 'formats' ] ) ) { - $formats = $args[ 'formats' ]; - unset( $args[ 'formats' ] ); - } else { - $formats = array(); - } - $dtt = EE_Datetime::new_instance( $args, $timezone, $formats ); - $dttID = $dtt->save(); - $dtt = $this->_maybe_chained( $dtt, $args ); - return $dttID ? $dtt : false; - } - - - - /** - * Update datetime object for given datetime - * - * @since 4.3.0 - * - * @param int $DTT_ID Datetime ID for the datetime to update - * @param array $cols_n_data columns and values to change/update - * - * @return EE_Datetime|false. - */ - public function update_object( $DTT_ID, $cols_n_data ) { - //all the stuff for updating an datetime. - $dtt = EEM_Datetime::instance()->get_one_by_ID( $DTT_ID ); - if ( ! $dtt instanceof EE_Datetime ) { - return null; - } - foreach ( $cols_n_data as $key => $val ) { - $dtt->set( $key, $val ); - } - $success = $dtt->save(); - return $success ? $dtt : false; - } - - - - /** - * return the datetime object for a given datetime ID - * - * @since 4.3.0 - * - * @param int $DTT_ID the datetime id for the datetime to attempt to retrieve - * - * @return mixed null|EE_Datetime - */ - public function get_object_by_id( $DTT_ID ) { - return EEM_Datetime::instance()->get_one_by_ID( $DTT_ID ); - } - - - -} -// End of file EE_UnitTest_Factory_For_Datetime.class.php -// Location: /EE_UnitTest_Factory_For_Datetime.class.php \ No newline at end of file diff --git a/tests/includes/factories/EE_UnitTest_Factory_For_Event.class.php b/tests/includes/factories/EE_UnitTest_Factory_For_Event.class.php deleted file mode 100644 index 128d6cf02d2..00000000000 --- a/tests/includes/factories/EE_UnitTest_Factory_For_Event.class.php +++ /dev/null @@ -1,84 +0,0 @@ -default_generation_definitions = array( - 'EVT_name' => new WP_UnitTest_Generator_Sequence( 'Event %s' ), - 'EVT_desc' => new WP_UnitTest_Generator_Sequence( 'Event content %s' ), - 'EVT_short_desc' => new WP_UnitTest_Generator_Sequence( 'Event excerpt %s' ), - 'EVT_wp_user' => 1 - ); - } - - - - /** - * used by factory to create event object - * - * @since 4.3.0 - * - * @param array $args Incoming field values to set on the new object - * - * @return EE_Event|false - */ - public function create_object( $args ) { - $event = EE_Event::new_instance( $args ); - $evtID = $event->save(); - return $evtID ? $event : false; - } - - - - /** - * Update event object for given event - * - * @since 4.3.0 - * - * @param int $EVT_ID Event ID for the event to update - * @param array $cols_n_data columns and values to change/update - * - * @return EE_Event|false - */ - public function update_object( $EVT_ID, $cols_n_data ) { - //all the stuff for updating an event. - $event = EEM_Event::instance()->get_one_by_ID( $EVT_ID ); - if ( ! $event instanceof EE_Event ) { - return null; - } - foreach ( $cols_n_data as $key => $val ) { - $event->set( $key, $val ); - } - $success = $event->save(); - return $success ? $event : false; - } - - - - /** - * return the event object for a given event ID - * - * @since 4.3.0 - * - * @param int $EVT_ID the event id for the event to attempt to retrieve - * - * @return null|EE_Event - */ - public function get_object_by_id( $EVT_ID ) { - return EEM_Event::instance()->get_one_by_ID( $EVT_ID ); - } - - - -} -// End of file EE_UnitTest_Factory_For_Event.class.php -// Location: tests/includes/factories/EE_UnitTest_Factory_For_Event.class.php \ No newline at end of file diff --git a/tests/includes/factories/EE_UnitTest_Factory_For_Message.class.php b/tests/includes/factories/EE_UnitTest_Factory_For_Message.class.php deleted file mode 100644 index b5be4f802e5..00000000000 --- a/tests/includes/factories/EE_UnitTest_Factory_For_Message.class.php +++ /dev/null @@ -1,106 +0,0 @@ -get_one( array( array( 'MTP_messenger' => 'email', 'MTP_message_type' => 'registration', 'MTP_is_global' => true ) ) ); - //default args for creating messages. - $this->default_generation_definitions = array( - 'GRP_ID' => $grp instanceof EE_Message_Template_Group ? $grp->ID() : 0, - 'MSG_messenger' => 'email', - 'MSG_message_type' => 'registration', - 'MSG_context' => 'admin', - 'MSG_to' => 'dude@example.com', - 'MSG_from' => 'admin@example.com', - 'MSG_subject' => new WP_UnitTest_Generator_Sequence( 'Message subject %s' ), - 'MSG_content' => new WP_UnitTest_Generator_Sequence( 'Message content excerpt %s' ), - 'STS_ID' => EEM_Message::status_incomplete - ); - } - - - - /** - * used by factory to create message object - * - * @since 4.9.0 - * - * @param array $args Incoming field values to set on the new object - * - * @return EE_Message|false - */ - public function create_object( $args ) { - //allow callers to override the default persistence of the object to the db. - if ( isset( $args['nosave'] ) ) { - $save = false; - unset( $args['nosave'] ); - } else { - $save = true; - } - $message = EE_Message_Factory::create( $args ); - - $msgID = $save ? $message->save() : 1; - - //if $save then let's attach the preview message handler so it can actually be generated - if ( $save && $msgID ) { - $message->set_field_or_extra_meta( 'data_handler_class_name', 'EE_Messages_Preview_incoming_data' ); - } - - return $msgID ? $message : false; - } - - - - /** - * Update message object for given message - * - * @since 4.9.0 - * - * @param int $MSG_ID Message ID for the message to update - * @param array $cols_n_data columns and values to change/update - * - * @return EE_Message|false - */ - public function update_object( $MSG_ID, $cols_n_data ) { - //all the stuff for updating an message. - $message = EEM_Message::instance()->get_one_by_ID( $MSG_ID ); - if ( ! $message instanceof EE_Message ) { - return null; - } - foreach ( $cols_n_data as $key => $val ) { - $message->set( $key, $val ); - } - $success = $message->save(); - return $success ? $message : false; - } - - - - /** - * return the message object for a given message ID - * - * @since 4.9.0 - * - * @param int $MSG_ID the message id for the message to attempt to retrieve - * - * @return null|EE_Message - */ - public function get_object_by_id( $MSG_ID ) { - return EEM_Message::instance()->get_one_by_ID( $MSG_ID ); - } - - - -} -// End of file EE_UnitTest_Factory_For_Message.class.php -// Location: /EE_UnitTest_Factory_For_Message.class.php \ No newline at end of file diff --git a/tests/includes/factories/EE_UnitTest_Factory_For_Payment.class.php b/tests/includes/factories/EE_UnitTest_Factory_For_Payment.class.php deleted file mode 100644 index f9ec091e146..00000000000 --- a/tests/includes/factories/EE_UnitTest_Factory_For_Payment.class.php +++ /dev/null @@ -1,96 +0,0 @@ -default_generation_definitions = array(); - } - - - - /** - * used by factory to create payment object - * - * @since 4.3.0 - * - * @param array $args Incoming field values to set on the new object - * - * @return EE_Payment|false - */ - public function create_object( $args ) { - //timezone? - if ( isset( $args[ 'timezone' ] ) ) { - $timezone = $args[ 'timezone' ]; - unset( $args[ 'timezone' ] ); - } else { - $timezone = null; - } - //date_formats? - if ( isset( $args[ 'formats' ] ) && is_array( $args[ 'formats' ] ) ) { - $formats = $args[ 'formats' ]; - unset( $args[ 'formats' ] ); - } else { - $formats = array(); - } - $payment = EE_Payment::new_instance( $args, $timezone, $formats ); - $paymentID = $payment->save(); - return $paymentID ? $payment : false; - } - - - - /** - * Update payment object for given payment - * - * @since 4.3.0 - * - * @param int $PMT_ID Payment ID for the payment to update - * @param array $cols_n_data columns and values to change/update - * - * @return EE_Payment|false - */ - public function update_object( $PMT_ID, $cols_n_data ) { - //all the stuff for updating an payment. - $payment = EEM_Payment::instance()->get_one_by_ID( $PMT_ID ); - if ( ! $payment instanceof EE_Payment ) { - return null; - } - foreach ( $cols_n_data as $key => $val ) { - $payment->set( $key, $val ); - } - $success = $payment->save(); - return $success ? $payment : false; - } - - - - /** - * return the payment object for a given payment ID - * - * @since 4.3.0 - * - * @param int $PMT_ID the payment id for the payment to attempt to retrieve - * - * @return mixed null|EE_Payment - */ - public function get_object_by_id( $PMT_ID ) { - return EEM_Payment::instance()->get_one_by_ID( $PMT_ID ); - } - - - -} -// End of file EE_UnitTest_Factory_For_Payment.class.php -// Location: /EE_UnitTest_Factory_For_Payment.class.php \ No newline at end of file diff --git a/tests/includes/factories/EE_UnitTest_Factory_For_Price.class.php b/tests/includes/factories/EE_UnitTest_Factory_For_Price.class.php deleted file mode 100644 index e5f20eb8a9d..00000000000 --- a/tests/includes/factories/EE_UnitTest_Factory_For_Price.class.php +++ /dev/null @@ -1,231 +0,0 @@ -_chained = $chained; - //default args for creating prices - $this->default_generation_definitions = array( - 'PRC_name' => new WP_UnitTest_Generator_Sequence( 'Price %s' ), - 'PRC_desc' => new WP_UnitTest_Generator_Sequence( 'Price Description %s' ), - 'PRC_amount' => 0, - /** - * Options for price type are: - * 'base': This will result in a base price type created for EEM_Price_type::base_type_base_price - * 'discount': This will result in a discount price type created for EEM_Price_type::base_type_discount - * 'surcharge': This will result in a surcharge price type created for EEM_Price_Type::base_type_surcharge - * 'tax': This will result in a tax price type created for EEM_Price_Type::base_type_tax - */ - 'PRT_name' => 'Base Price Type', - 'PRC_type' => 'base', - 'PRC_type_is_percent' => false, //true if percent for price type, false if dollar - 'TKT_end_date' => strtotime( '+2 months' ) - ); - } - - - - /** - * This allows setting the $_price_type property to a new price_type object if the incoming args for the - * new price have a prt_id (or set to default if no prt_id). This optionally will use any args for price type that is included in the incoming arguments. - * - * @since 4.3.0 - * @param int $PRT_ID EE_Price_Type ID - */ - private function _set_new_price_type( $PRT_ID = 0, $args ) { - $this->_price_type = empty( $PRT_ID ) ? EEM_Price_Type::instance()->get_one_by_ID( $PRT_ID ) : $this->_create_price_type( $args ); - //fail safe just in case (so we can be sure to have an price_type). - if ( empty( $this->_price_type ) ) { - $this->_price_type = $this->_create_price_type( $args ); - } - } - - - - /** - * Create a EE_Price_Type (optionally using provided args ) - * - * @since 4.3.0 - * - * @param array $args incoming arguments - * - * @return EE_Price_Type - */ - private function _create_price_type( $args ) { - //BASE PRICE TYPE - $base_price_type = ! empty( $args[ 'PRC_type' ] ) ? $args[ 'PRC_type' ] : $this->default_generation_definitions[ 'PRC_type' ]; - switch ( $base_price_type ) { - case 'base' : - $base_type = EEM_Price_Type::base_type_base_price; - break; - case 'discount' : - $base_type = EEM_Price_Type::base_type_discount; - break; - case 'surcharge' : - $base_type = EEM_Price_Type::base_type_surcharge; - break; - default : - $base_type = EEM_Price_Type::base_type_tax; - break; - } - //set the properties for the price type depending on the args - $prt_args = array( - 'PRT_name' => ! empty( $args[ 'PRT_name' ] ) ? $args[ 'PRT_name' ] : $this->default_generation_definitions[ 'PRT_name' ], - 'PBT_ID' => $base_type, - 'PRT_is_percent' => ! empty( $args[ 'PRC_type_is_percent' ] ) ? $args[ 'PRC_type_is_percent' ] : $this->default_generation_definitions[ 'PRC_type_is_percent' ] - ); - return $this->factory->price_type->create( $prt_args ); - } - - - - /** - * This handles connecting a ticket to the price type object that's been generated. - * - * @since 4.3.0 - * - * @param EE_Price $price - * @param array $args incoming args to override defaults. - * - * @return EE_Price - */ - private function _maybe_chained( EE_Price $price, $args ) { - if ( $this->_chained ) { - if ( empty( $this->_price_type ) ) { - $PRT_ID = isset( $this->_special_args[ 'PRT_ID' ] ) ? $this->_special_args[ 'PRT_ID' ] : 0; - $this->_set_new_price_type( $PRT_ID, $args ); - } - //add relation to datetime - $price->_add_relation_to( $this->_price_type, 'Price_Type' ); - $price->save(); - return $price; - } - return $price; - } - - - - /** - * used by factory to create price object. - * - * @since 4.3.0 - * - * @param array $args Incoming field values to set on the new object - * - * @return EE_Price|false - */ - public function create_object( $args ) { - if ( isset( $args['TKT_end_date'] ) ) { - $this->_special_args['TKT_end_date'] = $args['TKT_end_date']; - unset( $args['TKT_end_date'] ); - } - if ( isset( $args['PRT_ID'] ) ) { - $this->_special_args['PRT_ID'] = $args['PRT_id']; - unset( $args['PRT_ID'] ); - } - if ( isset( $args['PRC_type'] ) ) { - $this->_special_args['PRC_type'] = $args['PRC_type']; - unset( $args['PRC_type'] ); - } - if ( isset( $args['PRT_name'] ) ) { - $this->_special_args['PRT_name'] = $args['PRT_name']; - unset( $args['PRT_name'] ); - } - if ( isset( $args['PRC_type_is_percent'] ) ) { - $this->_special_args['PRC_type_is_percent'] = $args['PRC_type_is_percent']; - unset( $args['PRC_type_is_percent'] ); - } - $price = EE_Price::new_instance( $args ); - $priceID = $price->save(); - $price = $this->_maybe_chained( $price, $args ); - return $priceID ? $price : false; - } - - - - /** - * Update price object for given price. - * - * @since 4.3.0 - * - * @param int $PRC_ID Price ID for the price to update - * @param array $cols_n_data columns and values to change/update - * - * @return EE_Price|false. - */ - public function update_object( $PRC_ID, $cols_n_data ) { - //all the stuff for updating an price. - $price = EEM_Price::instance()->get_one_by_ID( $PRC_ID ); - if ( ! $price instanceof EE_Price ) { - return null; - } - foreach ( $cols_n_data as $key => $val ) { - $price->set( $key, $val ); - } - $success = $price->save(); - return $success ? $price : false; - } - - - - /** - * return the price object for a given price ID. - * - * @since 4.3.0 - * - * @param int $PRC_ID the price id for the price to attempt to retrieve - * - * @return mixed null|EE_Price - */ - public function get_object_by_id( $PRC_ID ) { - return EEM_Price::instance()->get_one_by_ID( $PRC_ID ); - } - - - -} -// End of file EE_UnitTest_Factory_For_Price.class.php -// Location: /EE_UnitTest_Factory_For_Price.class.php \ No newline at end of file diff --git a/tests/includes/factories/EE_UnitTest_Factory_For_Price_Type.class.php b/tests/includes/factories/EE_UnitTest_Factory_For_Price_Type.class.php deleted file mode 100644 index e4184f17a82..00000000000 --- a/tests/includes/factories/EE_UnitTest_Factory_For_Price_Type.class.php +++ /dev/null @@ -1,165 +0,0 @@ -_chained = $chained; - //default args for creating prices - $this->default_generation_definitions = array( - 'PRT_name' => new WP_UnitTest_Generator_Sequence( '%s Price Type' ) - ); - } - - - - /** - * This allows setting the $_price property to a new price object if the incoming args for the - * new price have a prc_id (or set to default if no prc_id). This optionally will use any args for price type that is included in the incoming arguments. - * - * @since 4.3.0 - * @param int $PRC_ID EE_Price ID - */ - private function _set_new_price( $PRC_ID = 0 ) { - $this->_price = empty( $PRC_ID ) ? EEM_Price::instance()->get_one_by_ID( $PRC_ID ) : $this->factory->price->create(); - //fail safe just in case (so we can be sure to have an price). - if ( empty( $this->_price ) ) { - $this->_price = $this->factory->price->create(); - } - } - - - - /** - * This handles connecting a ticket to the price object that's been generated. - * - * @since 4.3.0 - * - * @param EE_Price_Type $price_type - * @param array $args incoming arguments from caller for specifying overrides. - * - * @return EE_Price_Type - */ - private function _maybe_chained( EE_Price_Type $price_type, $args ) { - if ( $this->_chained ) { - if ( empty( $this->_price ) ) { - $PRC_ID = isset( $args[ 'PRC_ID' ] ) ? $args[ 'PRC_ID' ] : 0; - $this->_set_new_price( $PRC_ID ); - } - //add relation to datetime - $price_type->_add_relation_to( $this->_price, 'Price' ); - $price_type->save(); - return $price_type; - } - return $price_type; - } - - - - /** - * used by factory to create price type object. - * - * @since 4.3.0 - * - * @param array $args Incoming field values to set on the new object - * - * @return EE_Price_Type|false - */ - public function create_object( $args ) { - $this->_special_args[ 'PRC_ID' ] = isset( $args[ 'PRC_ID' ] ) ? $args[ 'PRC_ID' ] : 0; - if ( isset( $args[ 'PRC_ID' ] ) ) { - unset( $args[ 'PRC_ID' ] ); - } - $price_type = EE_Price_Type::new_instance( $args ); - $price_typeID = $price_type->save(); - $price_type = $this->_maybe_chained( $price_type, $args ); - return $price_typeID ? $price_type : false; - } - - - - /** - * Update price_type object for given price_type. - * - * @since 4.3.0 - * - * @param int $PRT_ID Price_Type ID for the price_type to update - * @param array $cols_n_data columns and values to change/update - * - * @return EE_Price_Type|false. - */ - public function update_object( $PRT_ID, $cols_n_data ) { - //all the stuff for updating an price_type. - $price_type = EEM_Price_Type::instance()->get_one_by_ID( $PRT_ID ); - if ( ! $price_type instanceof EE_Price_Type ) { - return null; - } - foreach ( $cols_n_data as $key => $val ) { - $price_type->set( $key, $val ); - } - $success = $price_type->save(); - return $success ? $price_type : false; - } - - - - /** - * return the price type object for a given price type ID. - * - * @since 4.3.0 - * - * @param int $PRT_ID the price type id for the price type to attempt to retrieve - * - * @return mixed null|EE_Price_Type - */ - public function get_object_by_id( $PRT_ID ) { - return EEM_Price_Type::instance()->get_one_by_ID( $PRT_ID ); - } - - - -} -// End of file EE_UnitTest_Factory_For_Price_Type.class.php -// Location: /EE_UnitTest_Factory_For_Price_Type.class.php \ No newline at end of file diff --git a/tests/includes/factories/EE_UnitTest_Factory_For_Registration.class.php b/tests/includes/factories/EE_UnitTest_Factory_For_Registration.class.php deleted file mode 100644 index 22d65bf6c4e..00000000000 --- a/tests/includes/factories/EE_UnitTest_Factory_For_Registration.class.php +++ /dev/null @@ -1,249 +0,0 @@ -Tickets - * (which also means the EVT_ID is set), Registrations->transaction, Registrations->attendee, - * Registrations->status. Registrations to custom questions and answers are NOT set. Also the transaction is just - * a base transaction, there are NO relations via transaction to line items. - * - * @var bool - */ - protected $_chained; - - - /** - * constructor - * - * @param EE_UnitTest_Factory $factory - * @param bool $chained This indicates that we are chaining this registrations to related objects. - */ - public function __construct($factory = null, $chained = false) - { - parent::__construct($factory); - $this->_chained = $chained; - //default args for creating registrations - $this->default_generation_definitions = array( - 'REG_url_link' => new WP_UnitTest_Generator_Sequence('%s-' . md5(uniqid())), - ); - } - - - /** - * This generates the dummy relation objects for use in a new registration. - * - * @since 4.3.0 - * @param array $args - * @throws EE_Error - */ - private function _set_new_relations($args) - { - //transaction - $this->_transaction = empty($args['TXN_ID']) - ? $this->factory->transaction->create() - : EEM_Transaction::instance()->get_one_by_ID($args['TXN_ID']); - $this->_transaction = empty($this->_transaction) ? $this->factory->transaction->create() : $this->_transaction; - //set line item - $total_line_item = EEH_Line_Item::create_total_line_item($this->_transaction->ID()); - $total_line_item->save_this_and_descendants_to_txn($this->_transaction->ID()); - //ticket - $this->_ticket = empty($args['TKT_ID']) - ? $this->factory->ticket_chained->create() - : EEM_Ticket::instance()->get_one_by_ID($args['TKT_ID']); - $this->_ticket = empty($this->_ticket) ? $this->factory->ticket_chained->create() : $this->_ticket; - - //set price on ticket - $this->_ticket->set_price(10); - /** @var EE_Price $price */ - $price = $this->factory->price_chained->create(); - $price->set_amount(10); - $this->_ticket->_add_relation_to($price, 'Price'); - $this->_ticket->save(); - EEH_Line_Item::add_ticket_purchase($total_line_item, $this->_ticket); - $this->_transaction->set_total($total_line_item->total()); - $this->_transaction->save(); - - //attendee - $this->_attendee = empty($args['ATT_ID']) - ? $this->factory->attendee->create() - : EEM_Attendee::instance()->get_one_by_ID($args['ATT_ID']); - $this->_attendee = empty($this->_attendee) ? $this->factory->attendee->create() : $this->_attendee; - //status - $this->_status = empty($args['STS_ID']) - ? EEM_Registration::status_id_pending_payment - : $args['STS_ID']; - } - - - /** - * This handles connecting a registration to related items when the chained flag is true. - * - * @since 4.3.0 - * @param EE_Registration $registration - * @param array $args incoming arguments from caller for specifying overrides. - * @return EE_Registration - * @throws EE_Error - * @throws RuntimeException - */ - private function _maybe_chained(EE_Registration $registration, $args) - { - if ($this->_chained) { - if (empty($this->_transaction) - || empty($this->_ticket) - || empty($this->_attendee) - || empty($this->_status) - ) { - $this->_set_new_relations($args); - } - //add relation to transaction - $registration->_add_relation_to($this->_transaction, 'Transaction'); - //add relation to ticket - $registration->_add_relation_to($this->_ticket, 'Ticket'); - //add relation to event - $event = $this->_ticket->get_first_related('Datetime')->get_first_related('Event'); - $registration->_add_relation_to($event, 'Event'); - //add relation to attendee - $registration->_add_relation_to($this->_attendee, 'Attendee'); - //add relation to status (just set the registration object to have the STS_ID) - $registration->set_status($this->_status); - $registration->save(); - return $registration; - } - return $registration; - } - - - /** - * used by factory to create registration object. - * - * @since 4.3.0 - * @param array $args Incoming field values to set on the new object - * @return EE_Registration|false - * @throws EE_Error - * @throws InvalidArgumentException - * @throws RuntimeException - * @throws \EventEspresso\core\exceptions\EntityNotFoundException - */ - public function create_object($args) - { - static $att_nmbr = 0; - //timezone? - if (isset($args['timezone'])) { - $timezone = $args['timezone']; - unset($args['timezone']); - } else { - $timezone = null; - } - //date_formats? - if (isset($args['formats']) && is_array($args['formats'])) { - $formats = $args['formats']; - unset($args['formats']); - } else { - $formats = array(); - } - $registration = EE_Registration::new_instance($args, $timezone, $formats); - //some things have to be set after the registration has been instantiated. - $registration->set('REG_session', uniqid()); - $registrationID = $registration->save(); - $registration = $this->_maybe_chained($registration, $args); - //only run finalize if $chained because it requires EE_Transaction - if ($this->_chained) { - $att_nmbr++; - $registration->set_reg_url_link(new RegUrlLink($att_nmbr, md5('ticket' . $registrationID . time()))); - $registration->set_reg_code( - new RegCode( - RegUrlLink::fromRegistration($registration), - $registration->transaction(), - $registration->ticket() - ) - ); - $registration->save(); - } - return $registrationID ? $registration : false; - } - - - /** - * Update registration object for given registration. - * - * @since 4.3.0 - * @param int $REG_ID Registration ID for the registration to update - * @param array $cols_n_data columns and values to change/update - * @return EE_Registration|false . - * @throws EE_Error - */ - public function update_object($REG_ID, $cols_n_data) - { - //all the stuff for updating an registration. - $registration = EEM_Registration::instance()->get_one_by_ID($REG_ID); - if (! $registration instanceof EE_Registration) { - return null; - } - foreach ($cols_n_data as $key => $val) { - $registration->set($key, $val); - } - $success = $registration->save(); - return $success ? $registration : false; - } - - - /** - * return the registration object for a given registration ID. - * - * @since 4.3.0 - * @param int $REG_ID the registration id for the registration to attempt to retrieve - * @return mixed null|EE_Registration - */ - public function get_object_by_id($REG_ID) - { - return EEM_Registration::instance()->get_one_by_ID($REG_ID); - } -} diff --git a/tests/includes/factories/EE_UnitTest_Factory_For_Status.class.php b/tests/includes/factories/EE_UnitTest_Factory_For_Status.class.php deleted file mode 100644 index c44900e1e72..00000000000 --- a/tests/includes/factories/EE_UnitTest_Factory_For_Status.class.php +++ /dev/null @@ -1,81 +0,0 @@ -default_generation_definitions = array(); - } - - - /** - * used by factory to create status object - * - * @since 4.3.0 - * @param array $args Incoming field values to set on the new object - * @return EE_Status|false - * @throws EE_Error - */ - public function create_object($args) - { - //first see if we have an existing status (because EE creates a bunch on initial install) - $status = EEM_Status::instance()->get_one(array($args)); - if (! $status instanceof EE_Status) { - $status = EE_Status::new_instance($args); - $statusID = $status->save(); - } else { - $statusID = $status->ID(); - } - return $statusID ? $status : false; - } - - - /** - * Update status object for given status - * - * @since 4.3.0 - * @param int $STS_ID Status ID for the status to update - * @param array $cols_n_data columns and values to change/update - * @return EE_Status|false - * @throws EE_Error - */ - public function update_object($STS_ID, $cols_n_data) - { - //all the stuff for updating an status. - $status = EEM_Status::instance()->get_one_by_ID($STS_ID); - if (! $status instanceof EE_Status) { - return null; - } - foreach ($cols_n_data as $key => $val) { - $status->set($key, $val); - } - $success = $status->save(); - return $success ? $status : false; - } - - - /** - * return the status object for a given status ID - * - * @since 4.3.0 - * @param int $STS_ID the status id for the status to attempt to retrieve - * @return mixed null|EE_Status - */ - public function get_object_by_id($STS_ID) - { - return EEM_Status::instance()->get_one_by_ID($STS_ID); - } -} diff --git a/tests/includes/factories/EE_UnitTest_Factory_For_Ticket.class.php b/tests/includes/factories/EE_UnitTest_Factory_For_Ticket.class.php deleted file mode 100644 index 3a2fa9d6415..00000000000 --- a/tests/includes/factories/EE_UnitTest_Factory_For_Ticket.class.php +++ /dev/null @@ -1,220 +0,0 @@ -_chained = $chained; - //default args for creating tickets - $this->default_generation_definitions = array( - 'TKT_name' => new WP_UnitTest_Generator_Sequence( 'Ticket %s' ), - 'TKT_description' => new WP_UnitTest_Generator_Sequence( 'Ticket Description %s' ), - 'TKT_start_date' => strtotime( '+1 month' ), - 'TKT_end_date' => strtotime( '+2 months' ) - ); - } - - - - /** - * This allows setting the $_datetime property to a new ticket object if the incoming args for the - * new ticket have a dtt_id (or set to default if no dtt_id) - * - * @since 4.3.0 - * @param int $DTT_ID EE_Datetime ID - */ - private function _set_new_datetime( $DTT_ID = 0 ) { - $this->_datetime = empty( $DTT_ID ) ? EEM_Datetime::instance()->get_one_by_ID( $DTT_ID ) : $this->factory->datetime_chained->create(); - //fail safe just in case (so we can be sure to have an datetime). - if ( empty( $this->_datetime ) ) { - $this->_datetime = $this->factory->datetime_chained->create(); - } - } - - - - /** - * This allows setting the $_price property to a new ticket object if the incoming args for the new ticket have a PRC_ID (or set to default if no PRIC_ID) provided. - * Note that we are using the price_chained method to ensure that the price has a corresponding price type object applied. - * - * @since 4.3.0 - * @param int $PRC_ID - * @return void - */ - private function _set_new_price( $PRC_ID = 0 ) { - $this->_price = ! empty( $PRC_ID ) ? EEM_Price::instance()->get_one_by_ID( $PRC_ID ) : $this->factory->price_chained->create(); - //fail safe just in case (so we can be sure to have an price). - if ( empty( $this->_price ) ) { - $this->_price = $this->factory->price_chained->create(); - } - - } - - - - /** - * This handles connecting a ticket to the datetime and price object that's been generated. - * - * @since 4.3.0 - * - * @param EE_Ticket $tkt - * @param array $args incoming arguments from caller for specifying overrides. - * - * @return EE_Ticket - */ - private function _maybe_chained( EE_Ticket $tkt, $args ) { - if ( $this->_chained ) { - if ( empty( $this->_datetime ) ) { - $DTT_ID = isset( $this->_special_args[ 'DTT_ID' ] ) ? $this->_special_args[ 'DTT_ID' ] : 0; - $this->_set_new_datetime( $DTT_ID ); - } - if ( empty( $this->_price ) ) { - $PRC_ID = isset( $this->_special_args[ 'PRC_ID' ] ) ? $this->_special_args[ 'PRC_ID' ] : 0; - $this->_set_new_price( $PRC_ID ); - } - //add relation to datetime - $tkt->_add_relation_to( $this->_datetime, 'Datetime' ); - //add relation to price - $tkt->_add_relation_to( $this->_price, 'Price' ); - $tkt->save(); - return $tkt; - } - return $tkt; - } - - - - /** - * used by factory to create ticket object - * - * @since 4.3.0 - * - * @param array $args Incoming field values to set on the new object - * - * @return EE_Ticket|false - */ - public function create_object( $args ) { - $this->_special_args[ 'PRC_ID' ] = isset( $args[ 'PRC_ID' ] ) ? $args[ 'PRC_ID' ] : 0; - $this->_special_args[ 'DTT_ID' ] = isset( $args[ 'DTT_ID' ] ) ? $args[ 'DTT_ID' ] : 0; - //maybe unset PRC_ID - if ( isset( $args[ 'PRC_ID' ] ) ) { - unset( $args[ 'PRC_ID' ] ); - } - //maybe unset DTT_ID - if ( isset( $args[ 'DTT_ID' ] ) ) { - unset( $args[ 'DTT_ID' ] ); - } - //timezone? - if ( isset( $args[ 'timezone' ] ) ) { - $timezone = $args[ 'timezone' ]; - unset( $args[ 'timezone' ] ); - } else { - $timezone = null; - } - //date_formats? - if ( isset( $args[ 'formats' ] ) && is_array( $args[ 'formats' ] ) ) { - $formats = $args[ 'formats' ]; - unset( $args[ 'formats' ] ); - } else { - $formats = array(); - } - $tkt = EE_Ticket::new_instance( $args, $timezone, $formats ); - $tktID = $tkt->save(); - $tkt = $this->_maybe_chained( $tkt, $args ); - return $tktID ? $tkt : false; - } - - - - /** - * Update ticket object for given ticket - * - * @since 4.3.0 - * - * @param int $TKT_ID Ticket ID for the ticket to update - * @param array $cols_n_data columns and values to change/update - * - * @return EE_Ticket|false. - */ - public function update_object( $TKT_ID, $cols_n_data ) { - //all the stuff for updating an ticket. - $tkt = EEM_Ticket::instance()->get_one_by_ID( $TKT_ID ); - if ( ! $tkt instanceof EE_Ticket ) { - return null; - } - foreach ( $cols_n_data as $key => $val ) { - $tkt->set( $key, $val ); - } - $success = $tkt->save(); - return $success ? $tkt : false; - } - - - - /** - * return the ticket object for a given ticket ID - * - * @since 4.3.0 - * - * @param int $TKT_ID the ticket id for the ticket to attempt to retrieve - * - * @return mixed null|EE_Ticket - */ - public function get_object_by_id( $TKT_ID ) { - return EEM_Ticket::instance()->get_one_by_ID( $TKT_ID ); - } - - - -} -// End of file EE_UnitTest_Factory_For_Ticket.class.php -// Location: /EE_UnitTest_Factory_For_Ticket.class.php \ No newline at end of file diff --git a/tests/includes/factories/EE_UnitTest_Factory_For_Transaction.class.php b/tests/includes/factories/EE_UnitTest_Factory_For_Transaction.class.php deleted file mode 100644 index 57c757a6b99..00000000000 --- a/tests/includes/factories/EE_UnitTest_Factory_For_Transaction.class.php +++ /dev/null @@ -1,208 +0,0 @@ -_chained = $chained; - //default args for creating transactions - $this->default_generation_definitions = array(); - } - - - - /** - * This generates the dummy relation objects for use in a new transaction if the $_chained flag is set. Note this is called on EVERY new transaction created when create_many() is called. - * - * @since 4.3.0 - * - * @param array $args arguments that are sent to the factory that *may contain registration id. - * @param int $TXN_ID required to make sure that when registration_chained is called, it does not create a new transaction object but uses THIS transaction and sets the relation. - */ - private function _set_new_relations( $args, $TXN_ID ) { - //registration - $this->_registration = empty( $args[ 'REG_ID' ] ) ? $this->factory->registration_chained->create( array( 'TXN_ID' => $TXN_ID ) ) : EEM_Registration::instance()->get_one_by_ID( $args[ 'REG_ID' ] ); - $this->_registration = empty( $this->_registration ) ? $this->factory->registration_chained->create( array( 'TXN_ID' => $TXN_ID ) ) : $this->_registration; - } - - - - /** - * This generates the dummy relation objects for use in a new transaction if the $_chained flag is true. Note this is called just once when create_many() method is used. - * - * @since 4.3.0 - * - * @param array $args arguments that are sent to the factory that *may contain registration id. - * @param int $TXN_ID required to make sure that when registration_chained is called, it does not create a new transaction object but uses THIS transaction and sets the relation. - */ - private function _set_repeated_relation( $args, $TXN_ID ) { - //status - $this->_status = empty( $args[ 'STS_ID' ] ) ? $this->factory->status->create( array( 'STS_ID' => EEM_Transaction::incomplete_status_code, - 'STS_type' => 'transaction', - 'STS_code' => 'INCOMPLETE' - ) ) : EEM_Status::instance()->get_one_by_ID( $args[ 'STS_ID' ] ); - $this->_status = empty( $this->_status ) ? $this->factory->status->create( array( 'STS_ID' => EEM_Transaction::incomplete_status_code, - 'STS_type' => 'transaction', - 'STS_code' => 'INCOMPLETE' - ) ) : $this->_status; - } - - - - /** - * This handles connecting a transaction to related items when the chained flag is true. - * - * @since 4.3.0 - * - * @param EE_Transaction $transaction - * @param array $args incoming arguments from caller for specifying overrides. - * - * @return EE_Transaction - */ - private function _maybe_chained( EE_Transaction $transaction, $args ) { - if ( $this->_chained ) { - if ( empty( $this->_status ) ) { - $this->_set_repeated_relation( $args, $transaction->ID() ); - } - //YES we DO want to set brand new relation objects because multiple transactions do not share the same related objects (for the purpose of tests at least) - $this->_set_new_relations( $args, $transaction->ID() ); - //note relation to registration should already be set via the factory->registration_chained->create() method. - //add relation to status - $transaction->_add_relation_to( $this->_status, 'Status' ); - $transaction->save(); - return $transaction; - } - return $transaction; - } - - - - /** - * used by factory to create transaction object. - * - * @since 4.3.0 - * - * @param array $args Incoming field values to set on the new object - * - * @return EE_Transaction|false - */ - public function create_object( $args ) { - //timezone? - if ( isset( $args[ 'timezone' ] ) ) { - $timezone = $args[ 'timezone' ]; - unset( $args[ 'timezone' ] ); - } else { - $timezone = null; - } - //date_formats? - if ( isset( $args[ 'formats' ] ) && is_array( $args[ 'formats' ] ) ) { - $formats = $args[ 'formats' ]; - unset( $args[ 'formats' ] ); - } else { - $formats = array(); - } - $transaction = EE_Transaction::new_instance( $args, $timezone, $formats ); - $transactionID = $transaction->save(); - $transaction = $this->_maybe_chained( $transaction, $args ); - $transaction->save(); - return $transactionID ? $transaction : false; - } - - - - /** - * Update transaction object for given transaction. - * - * @since 4.3.0 - * - * @param int $TXN_ID Transaction ID for the transaction to update - * @param array $cols_n_data columns and values to change/update - * - * @return EE_Transaction|false. - */ - public function update_object( $TXN_ID, $cols_n_data ) { - //all the stuff for updating an transaction. - $transaction = EEM_Transaction::instance()->get_one_by_ID( $TXN_ID ); - if ( ! $transaction instanceof EE_Transaction ) { - return null; - } - foreach ( $cols_n_data as $key => $val ) { - $transaction->set( $key, $val ); - } - $success = $transaction->save(); - return $success ? $transaction : false; - } - - - - /** - * return the transaction object for a given transaction ID. - * - * @since 4.3.0 - * - * @param int $TXN_ID the transaction id for the transaction to attempt to retrieve - * - * @return mixed null|EE_Transaction - */ - public function get_object_by_id( $TXN_ID ) { - return EEM_Transaction::instance()->get_one_by_ID( $TXN_ID ); - } - - - - -} -// End of file EE_UnitTest_Factory_For_Transaction.class.php -// Location: /EE_UnitTest_Factory_For_Transaction.class.php \ No newline at end of file diff --git a/tests/includes/factories/EE_UnitTest_Factory_For_Venue.class.php b/tests/includes/factories/EE_UnitTest_Factory_For_Venue.class.php deleted file mode 100644 index 2a8a600da49..00000000000 --- a/tests/includes/factories/EE_UnitTest_Factory_For_Venue.class.php +++ /dev/null @@ -1,83 +0,0 @@ -default_generation_definitions = array( - 'VNU_name' => new WP_UnitTest_Generator_Sequence( 'Venue %s' ), - 'VNU_desc' => new WP_UnitTest_Generator_Sequence( 'Venue content %s' ), - 'VNU_short_desc' => new WP_UnitTest_Generator_Sequence( 'Venue excerpt %s' ), - ); - } - - - - /** - * used by factory to create venue object - * - * @since 4.3.0 - * - * @param array $args Incoming field values to set on the new object - * - * @return EE_Venue|false - */ - public function create_object( $args ) { - $venue = EE_Venue::new_instance( $args ); - $venID = $venue->save(); - return $venID ? $venue : false; - } - - - - /** - * Update venue object for given venue - * - * @since 4.3.0 - * - * @param int $VNU_ID Venue ID for the event to update - * @param array $cols_n_data columns and values to change/update - * - * @return EE_Venue|false - */ - public function update_object( $VNU_ID, $cols_n_data ) { - //all the stuff for updating an event. - $venue = EEM_Venue::instance()->get_one_by_ID( $VNU_ID ); - if ( ! $venue instanceof EE_Venue ) { - return null; - } - foreach ( $cols_n_data as $key => $val ) { - $venue->set( $key, $val ); - } - $success = $venue->save(); - return $success ? $venue : false; - } - - - - /** - * return the venue object for a given venue ID - * - * @since 4.3.0 - * - * @param int $VNU_ID the venue id for the venue to attempt to retrieve - * - * @return mixed null|EE_Venue - */ - public function get_object_by_id( $VNU_ID ) { - return EEM_Venue::instance()->get_one_by_ID( $VNU_ID ); - } - - - -} -// End of file EE_UnitTest_Factory_For_Venue.class.php -// Location: /EE_UnitTest_Factory_For_Venue.class.php \ No newline at end of file diff --git a/tests/includes/factories/EE_UnitTest_Factory_for_Specific_Builds.php b/tests/includes/factories/EE_UnitTest_Factory_for_Specific_Builds.php deleted file mode 100644 index 89a05ee3016..00000000000 --- a/tests/includes/factories/EE_UnitTest_Factory_for_Specific_Builds.php +++ /dev/null @@ -1,94 +0,0 @@ -_factory = $factory; - } - - - /** - * This method builds the EE_Base_Class objects and their relationships - * - * @param array $build_artifact This is an array in a specific format: - * array( - * //each top level element represents the object being parsed - * 'Ticket' => array( - * 0 => array( - * //fields are optional - * 'fields' => array( - * //an array of fields to be used for the instantiated object - * 'TKT_name' => 'Title of ticket' - * ); - * 'relations' => array( - * //this is an array of relations this particular object will be attached to. - * //the key is the class name for the EE_Base_Class object to be attached to. - * //the value is an array with the indexes of what the objects that get attached that are - * //found in the parent 'relations' array item in this main array. - * 'Datetime' => array( 0, 1 ) - * ) - * ) - * ), - * 'Datetime' => array( - * 0 => array(), - * 1 => array() - * ) - * ) - * @param bool $save_to_db Whether to save the objects to the database or not - * - * @throws Exception - * @return array() an array of EE_Base_Class objects created indexed by model object name. - */ - public function build( $build_artifact, $save_to_db = true ) { - $built_objects = array(); - - //first build all the individual objects. - foreach ( $build_artifact as $model_name => $model_objects ) { - $model_property = strtolower( $model_name ); - if ( ! property_exists( $this->_factory, $model_property ) ) { - throw new Exception( sprintf( 'Unable to construct object because %s is not a property on the EE_UnitTest_Factory' ), $model_name ); - } - foreach ( $model_objects as $index => $model_info ) { - $fields = isset( $model_info['fields'] ) ? $model_info['fields'] : array(); - $built_objects[ $model_name ][$index] = $this->_factory->{$model_property}->create( $fields ); - } - } - - //now setup the relations - foreach ( $build_artifact as $model_name => $model_objects ) { - foreach( $model_objects as $index => $model_info ) - if ( isset( $model_info['relations'] ) && is_array( $model_info['relations'] ) ) { - foreach( $model_info['relations'] as $model_relation_name => $model_relation_info ) { - $model_relation_info = (array) $model_relation_info; - foreach( $model_relation_info as $relation_index ) { - if ( isset( $built_objects[$model_name][$index] ) && isset( $built_objects[$model_relation_name][$relation_index] ) ) { - $built_objects[$model_name][$index]->_add_relation_to( $built_objects[$model_relation_name][$relation_index], $model_relation_name ); - if ( $save_to_db ) { - $built_objects[$model_name][$index]->save(); - } - } - } - } - } - } - return $built_objects; - } -} \ No newline at end of file diff --git a/tests/includes/mock-ee-fs.php b/tests/includes/mock-ee-fs.php deleted file mode 100644 index 9173e52d496..00000000000 --- a/tests/includes/mock-ee-fs.php +++ /dev/null @@ -1,527 +0,0 @@ -find_folder( $path ); - - // Perhaps the FTP folder is rooted at the WordPress install, Check for wp-includes folder in root, Could have some false positives, but rare. - if ( ! $folder && $this->is_dir('/wp-includes') ) - $folder = '/'; - return $folder; - } - - // Mock FS specific functions: - - /** - * Sets initial filesystem environment and/or clears the current environment. - * Can also be passed the initial filesystem to be setup which is passed to self::setfs() - */ - function init( $paths = '', $home_dir = '/' ) { - $this->fs = new MockFS_Directory_Node( '/' ); - $this->fs_map = array( - '/' => $this->fs, - ); - $this->cache = array(); // Used by find_folder() and friends - $this->cwd = isset( $this->fs_map[ $home_dir ] ) ? $this->fs_map[ $home_dir ] : '/'; - $this->setfs( $paths ); - $this->add_system_user( WP_Filesystem_MockFS_default_owner ); - } - - /** - * "Bulk Loads" a filesystem into the internal virtual filesystem - */ - function setfs( $paths ) { - if ( ! is_array($paths) ) - $paths = explode( "\n", $paths ); - - $paths = array_filter( array_map( 'trim', $paths ) ); - - foreach ( $paths as $path ) { - // Allow for comments - if ( '#' == $path[0] ) - continue; - - // Directories - if ( '/' == $path[ strlen($path) -1 ] ) - $this->mkdir( $path ); - else // Files (with dummy content for now) - $this->put_contents( $path, 'This is a test file' ); - } - - } - - /** - * Locates a filesystem "node" - * @return MockFS_Node - */ - private function locate_node( $path ) { - if( isset( $this->fs_map[ $path ] ) ) { - return $this->fs_map[ $path ]; - } elseif( isset( $this->fs_map[ $path . '/' ] ) ){ - return $this->fs_map[ $path . '/' ]; - } - return false; - } - - /** - * Locates a filesystem node for the parent of the given item - */ - private function locate_parent_node( $path ) { - $dirname = str_replace( '\\', '/', dirname( $path ) ); - return $this->locate_node( trailingslashit( $dirname ) ); - } - - // Here starteth the WP_Filesystem functions. - - function mkdir( $path, $chmod = false, $chown = false, $chgrp = false ) { - $path = trailingslashit( $path ); - //if the directory already exists, leave it alone - if( $this->is_dir( $path ) ){ - return FALSE; - } - - $parent_node = $this->locate_parent_node( $path ); - if ( ! $parent_node ) { - $dirname = str_replace( '\\', '/', dirname( $path ) ); - if( $dirname == '/' ){ - return FALSE; - } - $this->mkdir( $dirname ); - $parent_node = $this->locate_parent_node( $path ); - if ( ! $parent_node ) - return false; - } - - $node = new MockFS_Directory_Node( $path, $chmod, $chown, $chgrp ); - - $parent_node->children[ $node->name ] = $node; - $this->fs_map[ $path ] = $node; - - return true; - } - - function put_contents( $path, $contents = '', $mode = null ) { - if ( ! $this->is_dir( dirname( $path ) ) ) - $this->mkdir( dirname( $path ), $mode ); - - //if the file already exists, just change its contents - $new_file = $this->locate_node( $path ); - if( $new_file ){ - if( ! $new_file instanceof MockFS_File_Node ){ - return FALSE; - }else{ - $new_file->contents = $contents; - } - //if they specified what permissions to set, set them - if( $mode != NULL ){ - $new_file->perms = $mode; - } - return true; - }else{ - $parent = $this->locate_parent_node( $path ); - if( ! $parent ){ - return FALSE; - } - $new_file = new MockFS_File_Node( $path, $contents, $mode ); - $parent->children[ $new_file->name ] = $new_file; - $this->fs_map[ $path ] = $new_file; - return true; - } - } - - function get_contents( $file ) { - if ( ! $this->is_file( $file ) ) - return false; - return $this->fs_map[ $file ]->contents; - } - - function cwd() { - return $this->cwd->path; - } - - function chdir( $path ) { - if ( ! isset( $this->fs_map[ $path ] ) ) - return false; - - $this->cwd = $this->fs_map[ $path ]; - return true; - } - - function exists( $path ) { - return isset( $this->fs_map[ $path ] ) || isset( $this->fs_map[ trailingslashit( $path ) ] ); - } - - function is_file( $file ) { - return isset( $this->fs_map[ $file ] ) && $this->fs_map[ $file ]->is_file(); - } - - function is_dir( $path ) { - $path = trailingslashit( $path ); - - return isset( $this->fs_map[ $path ] ) && $this->fs_map[ $path ]->is_dir(); - } - - function dirlist( $path = '.', $include_hidden = true, $recursive = false ) { - $path = trailingslashit( $path ); - if ( empty( $path ) || '.' == $path ) - $path = $this->cwd(); - - if ( ! $this->exists( $path ) ) - return false; - - $limit_file = false; - if ( $this->is_file( $path ) ) { - $limit_file = $this->locate_node( $path )->name; - $path = dirname( $path ) . '/'; - } - - $ret = array(); - foreach ( $this->fs_map[ $path ]->children as $entry ) { - if ( '.' == $entry->name || '..' == $entry->name ) - continue; - - if ( ! $include_hidden && '.' == $entry->name ) - continue; - - if ( $limit_file && $entry->name != $limit_file ) - continue; - - $struc = array(); - $struc['name'] = $entry->name; - $struc['type'] = $entry->type; - - if ( 'd' == $struc['type'] ) { - if ( $recursive ) - $struc['files'] = $this->dirlist( trailingslashit( $path ) . trailingslashit( $struc['name'] ), $include_hidden, $recursive ); - else - $struc['files'] = array(); - } - - $ret[ $entry->name ] = $struc; - } - return $ret; - } - /** - * Changes the permissions - * @param string $file path to file/folder - * @param string $mode - * @param boolean $recursive - * @return boolean success - */ - public function chmod( $file, $mode = false, $recursive = false ) { - $node = $this->locate_node( $file ); - if( ! $node instanceof MockFS_Node ){ - return FALSE; - } - $node->perms = $mode; - if( $node instanceof MockFS_Directory_Node && $recursive ){ - foreach( $node->children as $child_node ){ - $this->chmod( $child_node->path, $mode, $recursive ); - } - } - return TRUE; - } - /** - * CHanges the owner - * @param string $file - * @param string $owner name of owner - * @param type $recursive - */ - public function chown( $file, $owner, $recursive = false ) { - $node = $this->locate_node( $file ); - if( ! $node instanceof MockFS_Node || ! $this->is_writable( $file ) ){ - return FALSE; - } - $node->owner = $owner; - if( $node instanceof MockFS_Directory_Node && $recursive ){ - foreach( $node->children as $child_node ){ - $this->chown( $child_node->path, $owner, $recursive ); - } - } - return TRUE; - } - /** - * Sets the group name - * @param string $file - * @param string $group - * @param boolean $recursive - * @return boolean success - */ - public function chgrp( $file, $group, $recursive = false ) { - $node = $this->locate_node( $file ); - if( ! $node instanceof MockFS_Node || ! $this->is_writable( $file ) ){ - return FALSE; - } - $node->group = $group; - if( $node instanceof MockFS_Directory_Node && $recursive ){ - foreach( $node->children as $child_node ){ - $this->chgrp( $child_node->path, $group, $recursive ); - } - } - return TRUE; - } - - /** - * - * @param type $file - * @return string | false on error - */ - function owner( $file ) { - $node = $this->locate_node( $file ); - if( ! $node instanceof MockFS_Node || ! $this->is_writable( $file ) ){ - return FALSE; - }else{ - return $node->owner(); - } - } - - /** - * - * @param type $file - * @return string | false on error - */ - function group( $file ) { - $node = $this->locate_node( $file ); - if( ! $node instanceof MockFS_Node ){ - return FALSE; - }else{ - return $node->group(); - } - } - - /** - * Gets the permissions on the file - * @return string | false on error - */ - public function getchmod( $file ){ - $node = $this->locate_node( $file ); - if( ! $node instanceof MockFS_Node ){ - return FALSE; - }else{ - return $node->perms(); - } - } - - /** - * Users to swithch to - * @param string $new_username - * @return boolean success - */ - public function change_current_system_user( $new_username ){ - if( isset( $this->_system_users[ $new_username ] ) ){ - $this->_current_system_user_name = $new_username; - }else{ - return FALSE; - } - } - /** - * Gets the current mock FS system user, or FALSE if none has been set - * @return MockFS_System_User - */ - public function get_current_system_user(){ - if( isset( $this->_system_users[ $this->_current_system_user_name ] ) ){ - return $this->_system_users[ $this->_current_system_user_name ]; - }else{ - return FALSE; - } - } - - /** - * Adds the specified user. Returns that new user obejct or FALSE - * @param string $username - * @param string $groupname - * @return boolean|\MockFS_System_User - */ - function add_system_user( $username, $groupname = NULL ){ - if( isset( $this->_system_users[ $username ] ) ){ - return FALSE; - } - if( ! $groupname ){ - $groupname = WP_Filesystem_MockFS_default_group; - } - $user = new MockFS_System_User( $username, $groupname ); - $this->_current_system_user_name = $user->username; - $this->_system_users[ $user->username ] = $user; - return $user; - } - - function is_readable( $file ) { - $user = $this->get_current_system_user(); - $file_node = $this->locate_node( $file ); - if( ! $file_node ){ - return FALSE; - } - $perms = intval( $file_node->perms(), 8 ) ; - //owned by this user - if( $file_node->owner() == $user->username ) { - if( $perms & 0400 ){ -// echo "\r\n " . $user->username . " has permision to read " . $file_node->name . " because its perms are :" . $perms; - return TRUE; - } - } - //owned by this group? - if( $file_node->group == $user->groupname ) { - if( $perms & 0040 ) { -// echo "\r\n " . $user->groupname . " has permision to read " . $file_node->name . " because its perms are :" . $perms; - return TRUE; - } - } - if( $perms & 0004){ -// echo "\r\n anyone has permision to read " . $file_node->name . " because its perms are :" . $perms; - return TRUE; - }else{ - return FALSE; - } - } - function is_writable( $file ) { - $user = $this->get_current_system_user(); - $file_node = $this->locate_node( $file ); - if( ! $file_node ){ - return FALSE; - } - $perms = intval( $file_node->perms(), 8 ) ; - //owned by this user - if( $file_node->owner() == $user->username ) { - if( $perms & 0200 ){ -// echo "\r\n " . $user->username . " has permision to read " . $file_node->name . " because its perms are :" . $perms; - return TRUE; - } - } - //owned by this group? - if( $file_node->group == $user->groupname ) { - if( $perms & 0020 ) { -// echo "\r\n " . $user->groupname . " has permision to read " . $file_node->name . " because its perms are :" . $perms; - return TRUE; - } - } - if( $perms & 0002){ -// echo "\r\n anyone has permision to read " . $file_node->name . " because its perms are :" . $perms; - return TRUE; - }else{ - return FALSE; - } - } - /** - * - * @param type $path - * @param type $time - * @param type $atime - * @return boolean - */ - function touch( $path, $time = 0, $atime = 0 ) { - if( ! $this->exists( $path ) ){ - $this->put_contents($path); - return TRUE; - }else{ - //if we kept track of when a file was last edited we would update it - return TRUE; - } - } - - - -} - -class MockFS_Node { - public $name; // The "name" of the entry, does not include a slash (exception, root) - public $type; // The type of the entry 'f' for file, 'd' for Directory - public $path; // The full path to the entry. - public $perms; //permissions associated with this file or folder - public $owner; //the owner name of the file or folder - public $group; //the group of this file or folder - - function __construct( $path, $chmod = NULL, $chown = NULL, $chgrp = NULL ) { - $this->path = $path; - $this->name = basename( $path ); - if( ! $chmod ) { - $chmod = WP_Filesystem_MockFS_default_perms; - } - if( ! $chown ) { - $chown = WP_Filesystem_MockFS_default_owner; - } - if( ! $chgrp ) { - $chgrp = WP_Filesystem_MockFS_default_group; - } - $this->perms = $chmod; - $this->owner = $chown; - $this->group = $chgrp; - } - - function is_file() { - return $this->type == 'f'; - } - - function is_dir() { - return $this->type == 'd'; - } - /** - * - * @return string @see http://en.wikipedia.org/wiki/File_system_permissions#Numeric_notation - */ - function perms(){ - return $this->perms; - } - function owner(){ - return $this->owner; - } - function group(){ - return $this->group; - } -} - -class MockFS_Directory_Node extends MockFS_Node { - public $type = 'd'; - public $children = array(); // The child nodes of this directory -} - -class MockFS_File_Node extends MockFS_Node { - public $type = 'f'; - public $contents = ''; // The contents of the file - - function __construct( $path, $contents = '', $chmod = NULL, $chown = NULL, $chgrp = NULL ) { - parent::__construct( $path, $chmod, $chown, $chgrp ); - $this->contents = $contents; - } -} - -class MockFS_System_User{ - public $username; - public $groupname; - function __construct( $username, $groupname = NULL) { - $this->username = $username; - if( ! $groupname ){ - $groupname = WP_Filesystem_MockFS_default_group; - } - $this->groupname = $groupname; - } -} \ No newline at end of file diff --git a/tests/includes/scenarios/EE_Datetime_Scenario_A.scenario.php b/tests/includes/scenarios/EE_Datetime_Scenario_A.scenario.php deleted file mode 100644 index 0f9e7e05c5f..00000000000 --- a/tests/includes/scenarios/EE_Datetime_Scenario_A.scenario.php +++ /dev/null @@ -1,109 +0,0 @@ -type = 'datetime'; - $this->name = 'Datetime Scenario A'; - parent::__construct( $eetest ); - } - - - protected function _set_up_expected() { - // array of Datetime IDs => available ticket quantities - $this->_expected_values = array( - 'sum_tickets_currently_available_at_datetime' => 0, - 'datetime_id_to_tickets_map' => array( - 1 => 0, - 2 => 0, - 3 => 0, - ), - ); - } - - - protected function _set_up_scenario() { - $build_artifact = array( - 'Datetime' => array( - 1 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 1', - 'DTT_reg_limit' => 5, - 'DTT_sold' => 5, - ) - ), - 2 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 2', - 'DTT_reg_limit' => 20, - 'DTT_sold' => 3, - ) - ), - 3 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 3', - 'DTT_reg_limit' => 3, - 'DTT_sold' => 3, - ) - ) - ), - 'Ticket' => array( - 'A' => array( - 'fields' => array( - 'TKT_name' => 'Ticket A', - 'TKT_qty' => EE_INF, - 'TKT_sold' => 3, - ), - 'relations' => array( - 'Datetime' => array( 1, 2, 3 ) - ) - ), - 'B' => array( - 'fields' => array( - 'TKT_name' => 'Ticket B', - 'TKT_qty' => 15, - 'TKT_sold' => 0, - ), - 'relations' => array( - 'Datetime' => array( 1, 2 ) - ) - ), - 'C' => array( - 'fields' => array( - 'TKT_name' => 'Ticket C', - 'TKT_qty' => 20, - 'TKT_sold' => 2, - ), - 'relations' => array( - 'Datetime' => array( 1 ) - ) - ), - ), - ); - $build_objects = $this->_eeTest->factory->complex_factory->build( $build_artifact ); - //assign the first datetime object as the scenario object (it's the one that will be used for tests. - $this->_scenario_object = reset( $build_objects['Datetime'] ); - } - - - protected function _get_scenario_object() { - return $this->_scenario_object; - } -} \ No newline at end of file diff --git a/tests/includes/scenarios/EE_Datetime_Scenario_B.scenario.php b/tests/includes/scenarios/EE_Datetime_Scenario_B.scenario.php deleted file mode 100644 index 341307994a6..00000000000 --- a/tests/includes/scenarios/EE_Datetime_Scenario_B.scenario.php +++ /dev/null @@ -1,153 +0,0 @@ -type = 'datetime'; - $this->name = 'Datetime Scenario B - Ticket 8997'; - parent::__construct( $eetest ); - } - - - - protected function _set_up_expected() { - // array of Datetime IDs => available ticket quantities - $this->_expected_values = array( - 'sum_tickets_currently_available_at_datetime' => 5, - 'datetime_id_to_tickets_map' => array( - 1 => 1, - 2 => 1, - 3 => 1, - ), - ); - } - - - - protected function _set_up_scenario() { - $build_artifact = array( - 'Datetime' => array( - 1 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 1', - 'DTT_reg_limit' => 9, - 'DTT_sold' => 8, - ) - ), - 2 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 2', - 'DTT_reg_limit' => 9, - 'DTT_sold' => 8, - ) - ), - 3 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 3', - 'DTT_reg_limit' => 9, - 'DTT_sold' => 8, - ) - ) - ), - 'Ticket' => array( - 'A' => array( - 'fields' => array( - 'TKT_name' => 'Ticket A', - 'TKT_qty' => 9, - 'TKT_sold' => 4, - ), - 'relations' => array( - 'Datetime' => array( 1, 2, 3 ) - ) - ), - 'B' => array( - 'fields' => array( - 'TKT_name' => 'Ticket B', - 'TKT_qty' => 9, - 'TKT_sold' => 3, - ), - 'relations' => array( - 'Datetime' => array( 1, 2, 3 ) - ) - ), - 'C' => array( - 'fields' => array( - 'TKT_name' => 'Ticket C', - 'TKT_qty' => 9, - 'TKT_sold' => 1, - ), - 'relations' => array( - 'Datetime' => array( 1, 2, 3 ) - ) - ), - 'D' => array( - 'fields' => array( - 'TKT_name' => 'Ticket D', - 'TKT_qty' => 9, - 'TKT_sold' => 0, - ), - 'relations' => array( - 'Datetime' => array( 1, 2, 3 ) - ) - ), - 'E' => array( - 'fields' => array( - 'TKT_name' => 'Ticket E', - 'TKT_qty' => 9, - 'TKT_sold' => 0, - ), - 'relations' => array( - 'Datetime' => array( 1, 2, 3 ) - ) - ), - ), - ); - $build_objects = $this->_eeTest->factory->complex_factory->build( $build_artifact ); - //assign the first datetime object as the scenario object (it's the one that will be used for tests. - $this->_scenario_object = reset( $build_objects[ 'Datetime' ] ); - } - - - - protected function _get_scenario_object() { - return $this->_scenario_object; - } - - - -} -// End of file EE_Datetime_Scenario_B.scenario.php -// Location: /tests/includes/scenarios/EE_Datetime_Scenario_B.scenario.php \ No newline at end of file diff --git a/tests/includes/scenarios/EE_Event_Scenario_A.scenario.php b/tests/includes/scenarios/EE_Event_Scenario_A.scenario.php deleted file mode 100644 index 98ed47c3a61..00000000000 --- a/tests/includes/scenarios/EE_Event_Scenario_A.scenario.php +++ /dev/null @@ -1,128 +0,0 @@ -type = 'event'; - $this->name = 'Event Scenario A'; - parent::__construct( $eetest ); - } - - protected function _set_up_expected(){ - $this->_expected_values = array( - 'total_available_spaces' => 15, - 'total_remaining_spaces' => 15, - ); - } - - - protected function _set_up_scenario(){ - $build_artifact = array( - 'Event' => array( - 0 => array( - 'fields' => array( 'EVT_name' => 'Test Scenario EVT A' ) - ) - ), - 'Datetime' => array( - 0 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 1', - 'DTT_reg_limit' => 5 - ), - 'relations' => array( - 'Event' => array( 0 ) - ) - ), - 1 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 2', - 'DTT_reg_limit' => 20 - ), - 'relations' => array( - 'Event' => array( 0 ) - ) - ), - 2 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 3', - 'DTT_reg_limit' => 12 - ), - 'relations' => array( - 'Event' => array( 0 ) - ) - ), - ), - 'Ticket' => array( - 0 => array( - 'fields' => array( - 'TKT_name' => 'Ticket A', - 'TKT_qty' => 30 - ), - 'relations' => array( - 'Datetime' => array( 0, 1, 2 ) - ) - ), - 1 => array( - 'fields' => array( - 'TKT_name' => 'Ticket B', - 'TKT_qty' => 5 - ), - 'relations' => array( - 'Datetime' => array( 0, 1 ) - ) - ), - 2 => array( - 'fields' => array( - 'TKT_name' => 'Ticket C', - 'TKT_qty' => 15 - ), - 'relations' => array( - 'Datetime' => array( 0 ) - ) - ), - 3 => array( - 'fields' => array( - 'TKT_name' => 'Ticket D', - 'TKT_qty' => 10 - ), - 'relations' => array( - 'Datetime' => array( 1, 2 ) - ) - ), - ) - ); - - $build_objects = $this->_eeTest->factory->complex_factory->build( $build_artifact ); - - //assign the event object as the scenario object - $this->_scenario_object = reset( $build_objects['Event'] ); - } - - - - protected function _get_scenario_object(){ - return $this->_scenario_object; - } -} diff --git a/tests/includes/scenarios/EE_Event_Scenario_B.scenario.php b/tests/includes/scenarios/EE_Event_Scenario_B.scenario.php deleted file mode 100644 index 17c0fbdd7e9..00000000000 --- a/tests/includes/scenarios/EE_Event_Scenario_B.scenario.php +++ /dev/null @@ -1,112 +0,0 @@ -type = 'event'; - $this->name = 'Event Scenario B'; - parent::__construct( $eetest ); - } - - protected function _set_up_expected(){ - $this->_expected_values = array( - 'total_available_spaces' => 22, - 'total_remaining_spaces' => 22 - ); - } - - - protected function _set_up_scenario(){ - $build_artifact = array( - - 'Event' => array( - 0 => array( - 'fields' => array( 'EVT_name' => 'Test Scenario EVT B' ) - ) - ), - - 'Datetime' => array( - 0 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 1', - 'DTT_reg_limit' => 15 - ), - 'relations' => array( - 'Event' => array( 0 ) - ) - ), - 1 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 2', - 'DTT_reg_limit' => 17 - ), - 'relations' => array( - 'Event' => array( 0 ) - ) - ) - ), - - 'Ticket' => array( - 0 => array( - 'fields' => array( - 'TKT_name' => 'Ticket A', - 'TKT_qty' => 23 - ), - 'relations' => array( - 'Datetime' => array( 0, 1 ) - ) - ), - 1 => array( - 'fields' => array( - 'TKT_name' => 'Ticket B', - 'TKT_qty' => 5 - ), - 'relations' => array( - 'Datetime' => array( 0 ) - ) - ), - 2 => array( - 'fields' => array( - 'TKT_name' => 'Ticket C', - 'TKT_qty' => 15 - ), - 'relations' => array( - 'Datetime' => array( 1 ) - ) - ) - ) - ); - - $build_objects = $this->_eeTest->factory->complex_factory->build( $build_artifact ); - - //assign the event object as the scenario object - $this->_scenario_object = reset( $build_objects['Event'] ); - } - - - - protected function _get_scenario_object(){ - return $this->_scenario_object; - } -} diff --git a/tests/includes/scenarios/EE_Event_Scenario_C.scenario.php b/tests/includes/scenarios/EE_Event_Scenario_C.scenario.php deleted file mode 100644 index 04f8153e2ac..00000000000 --- a/tests/includes/scenarios/EE_Event_Scenario_C.scenario.php +++ /dev/null @@ -1,112 +0,0 @@ -type = 'event'; - $this->name = 'Event Scenario C'; - parent::__construct( $eetest ); - } - - protected function _set_up_expected(){ - $this->_expected_values = array( - 'total_available_spaces' => 17, - 'total_remaining_spaces' => 17 - ); - } - - - protected function _set_up_scenario(){ - $build_artifact = array( - - 'Event' => array( - 0 => array( - 'fields' => array( 'EVT_name' => 'Test Scenario EVT C' ) - ) - ), - - 'Datetime' => array( - 0 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 1', - 'DTT_reg_limit' => 15 - ), - 'relations' => array( - 'Event' => array( 0 ) - ) - ), - 1 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 2', - 'DTT_reg_limit' => 17 - ), - 'relations' => array( - 'Event' => array( 0 ) - ) - ) - ), - - 'Ticket' => array( - 0 => array( - 'fields' => array( - 'TKT_name' => 'Ticket A', - 'TKT_qty' => 23 - ), - 'relations' => array( - 'Datetime' => array( 0, 1 ) - ) - ), - 1 => array( - 'fields' => array( - 'TKT_name' => 'Ticket B', - 'TKT_qty' => 5 - ), - 'relations' => array( - 'Datetime' => array( 0, 1 ) - ) - ), - 2 => array( - 'fields' => array( - 'TKT_name' => 'Ticket C', - 'TKT_qty' => 15 - ), - 'relations' => array( - 'Datetime' => array( 1 ) - ) - ) - ) - ); - - $build_objects = $this->_eeTest->factory->complex_factory->build( $build_artifact ); - - //assign the event object as the scenario object - $this->_scenario_object = reset( $build_objects['Event'] ); - } - - - - protected function _get_scenario_object(){ - return $this->_scenario_object; - } -} diff --git a/tests/includes/scenarios/EE_Event_Scenario_D.scenario.php b/tests/includes/scenarios/EE_Event_Scenario_D.scenario.php deleted file mode 100644 index 409ac33db41..00000000000 --- a/tests/includes/scenarios/EE_Event_Scenario_D.scenario.php +++ /dev/null @@ -1,129 +0,0 @@ -type = 'event'; - $this->name = 'Event Scenario D'; - parent::__construct( $eetest ); - } - - protected function _set_up_expected(){ - $this->_expected_values = array( - 'total_available_spaces' => 12, - 'total_remaining_spaces' => 12 - ); - } - - - protected function _set_up_scenario(){ - $build_artifact = array( - 'Event' => array( - 0 => array( - 'fields' => array( 'EVT_name' => 'Test Scenario EVT D' ) - ) - ), - 'Datetime' => array( - 0 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 1', - 'DTT_reg_limit' => 5 - ), - 'relations' => array( - 'Event' => array( 0 ) - ) - ), - 1 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 2', - 'DTT_reg_limit' => 20 - ), - 'relations' => array( - 'Event' => array( 0 ) - ) - ), - 2 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 3', - 'DTT_reg_limit' => 12 - ), - 'relations' => array( - 'Event' => array( 0 ) - ) - ), - ), - 'Ticket' => array( - 0 => array( - 'fields' => array( - 'TKT_name' => 'Ticket A', - 'TKT_qty' => 5 - ), - 'relations' => array( - 'Datetime' => array( 0, 1, 2 ) - ) - ), - 1 => array( - 'fields' => array( - 'TKT_name' => 'Ticket B', - 'TKT_qty' => 5 - ), - 'relations' => array( - 'Datetime' => array( 0, 1 ) - ) - ), - 2 => array( - 'fields' => array( - 'TKT_name' => 'Ticket C', - 'TKT_qty' => 5 - ), - 'relations' => array( - 'Datetime' => array( 0, 2 ) - ) - ), - 3 => array( - 'fields' => array( - 'TKT_name' => 'Ticket D', - 'TKT_qty' => 10 - ), - 'relations' => array( - 'Datetime' => array( 1, 2 ) - ) - ), - ) - ); - - $build_objects = $this->_eeTest->factory->complex_factory->build( $build_artifact ); - - //assign the event object as the scenario object - $this->_scenario_object = reset( $build_objects['Event'] ); - } - - - - protected function _get_scenario_object(){ - return $this->_scenario_object; - } -} diff --git a/tests/includes/scenarios/EE_Event_Scenario_E.scenario.php b/tests/includes/scenarios/EE_Event_Scenario_E.scenario.php deleted file mode 100644 index 6e40371be8d..00000000000 --- a/tests/includes/scenarios/EE_Event_Scenario_E.scenario.php +++ /dev/null @@ -1,150 +0,0 @@ -type = 'event'; - $this->name = 'Event Scenario E'; - parent::__construct( $eetest ); - } - - protected function _set_up_expected(){ - $this->_expected_values = array( - 'total_available_spaces' => 42, - 'total_remaining_spaces' => 42 - ); - } - - - protected function _set_up_scenario(){ - $build_artifact = array( - 'Event' => array( - 0 => array( - 'fields' => array( 'EVT_name' => 'Test Scenario EVT E' ) - ) - ), - 'Datetime' => array( - 0 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 1', - 'DTT_reg_limit' => 55 - ), - 'relations' => array( - 'Event' => array( 0 ) - ) - ), - 1 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 2', - 'DTT_reg_limit' => 20 - ), - 'relations' => array( - 'Event' => array( 0 ) - ) - ), - 2 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 3', - 'DTT_reg_limit' => 12 - ), - 'relations' => array( - 'Event' => array( 0 ) - ) - ), - 3 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 4', - 'DTT_reg_limit' => 30 - ), - 'relations' => array( - 'Event' => array( 0 ) - ) - ), - ), - 'Ticket' => array( - 0 => array( - 'fields' => array( - 'TKT_name' => 'Ticket A', - 'TKT_qty' => 12 - ), - 'relations' => array( - 'Datetime' => array( 0, 1, 2 ) - ) - ), - 1 => array( - 'fields' => array( - 'TKT_name' => 'Ticket B', - 'TKT_qty' => 20 - ), - 'relations' => array( - 'Datetime' => array( 0, 1, 3 ) - ) - ), - 2 => array( - 'fields' => array( - 'TKT_name' => 'Ticket C', - 'TKT_qty' => 30 - ), - 'relations' => array( - 'Datetime' => array( 0, 3 ) - ) - ), - 3 => array( - 'fields' => array( - 'TKT_name' => 'Ticket D', - 'TKT_qty' => 12 - ), - 'relations' => array( - 'Datetime' => array( 0, 2, 3 ) - ) - ), - 4 => array( - 'fields' => array( - 'TKT_name' => 'Ticket E', - 'TKT_qty' => 30 - ), - 'relations' => array( - 'Datetime' => array( 3 ) - ) - ), - ) - ); - - $build_objects = $this->_eeTest->factory->complex_factory->build( $build_artifact ); - - //assign the event object as the scenario object - $this->_scenario_object = reset( $build_objects['Event'] ); - } - - - - protected function _get_scenario_object(){ - return $this->_scenario_object; - } -} diff --git a/tests/includes/scenarios/EE_Event_Scenario_F.scenario.php b/tests/includes/scenarios/EE_Event_Scenario_F.scenario.php deleted file mode 100644 index 83d7aeab60c..00000000000 --- a/tests/includes/scenarios/EE_Event_Scenario_F.scenario.php +++ /dev/null @@ -1,132 +0,0 @@ -type = 'event'; - $this->name = 'Event Scenario F'; - parent::__construct( $eetest ); - } - - protected function _set_up_expected(){ - $this->_expected_values = array( - 'total_available_spaces' => 20, - 'total_remaining_spaces' => 20 - ); - } - - - protected function _set_up_scenario(){ - $build_artifact = array( - 'Event' => array( - 0 => array( - 'fields' => array( 'EVT_name' => 'Test Scenario EVT D' ) - ) - ), - 'Datetime' => array( - 0 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 1', - 'DTT_reg_limit' => 5 - ), - 'relations' => array( - 'Event' => array( 0 ) - ) - ), - 1 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 2', - 'DTT_reg_limit' => 20 - ), - 'relations' => array( - 'Event' => array( 0 ) - ) - ), - 2 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 3' - ), - 'relations' => array( - 'Event' => array( 0 ) - ) - ), - ), - 'Ticket' => array( - 0 => array( - 'fields' => array( - 'TKT_name' => 'Ticket A', - 'TKT_qty' => 5 - ), - 'relations' => array( - 'Datetime' => array( 0, 1, 2 ) - ) - ), - 1 => array( - 'fields' => array( - 'TKT_name' => 'Ticket B', - 'TKT_qty' => 15 - ), - 'relations' => array( - 'Datetime' => array( 1, 2 ) - ) - ), - 2 => array( - 'fields' => array( - 'TKT_name' => 'Ticket C', - 'TKT_qty' => 5 - ), - 'relations' => array( - 'Datetime' => array( 0, 2 ) - ) - ), - 3 => array( - 'fields' => array( - 'TKT_name' => 'Ticket D', - 'TKT_qty' => 5 - ), - 'relations' => array( - 'Datetime' => array( 1 ) - ) - ), - ) - ); - - $build_objects = $this->_eeTest->factory->complex_factory->build( $build_artifact ); - - //assign the event object as the scenario object - $this->_scenario_object = reset( $build_objects['Event'] ); - } - - - - protected function _get_scenario_object(){ - return $this->_scenario_object; - } -} diff --git a/tests/includes/scenarios/EE_Event_Scenario_G.scenario.php b/tests/includes/scenarios/EE_Event_Scenario_G.scenario.php deleted file mode 100644 index b7da5e380bb..00000000000 --- a/tests/includes/scenarios/EE_Event_Scenario_G.scenario.php +++ /dev/null @@ -1,133 +0,0 @@ -type = 'event'; - $this->name = 'Event Scenario G'; - parent::__construct( $eetest ); - } - - protected function _set_up_expected(){ - $this->_expected_values = array( - 'total_available_spaces' => 3, - 'total_remaining_spaces' => 1 - ); - } - - - protected function _set_up_scenario(){ - $build_artifact = array( - 'Event' => array( - 1 => array( - 'fields' => array( 'EVT_name' => 'Test Scenario EVT G' ) - ) - ), - 'Datetime' => array( - 1 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 1', - 'DTT_reg_limit' => 3, - 'DTT_sold' => 2, - ), - 'relations' => array( - 'Event' => array( 1 ) - ) - ), - 2 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 2', - 'DTT_reg_limit' => 2, - 'DTT_sold' => 2, - ), - 'relations' => array( - 'Event' => array( 1 ) - ) - ), - 3 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 3', - 'DTT_reg_limit' => 10 - ), - 'relations' => array( - 'Event' => array( 1 ) - ) - ), - ), - 'Ticket' => array( - 1 => array( - 'fields' => array( - 'TKT_name' => 'Ticket 1', - 'TKT_qty' => 2 - ), - 'relations' => array( - 'Datetime' => array( 1, 3 ) - ) - ), - 2 => array( - 'fields' => array( - 'TKT_name' => 'Ticket 2', - 'TKT_qty' => 2 - ), - 'relations' => array( - 'Datetime' => array( 2 ) - ) - ), - 3 => array( - 'fields' => array( - 'TKT_name' => 'Ticket 3', - 'TKT_qty' => 2, - 'TKT_sold' => 2, - ), - 'relations' => array( - 'Datetime' => array( 1, 2 ) - ) - ), - 4 => array( - 'fields' => array( - 'TKT_name' => 'Ticket 4', - 'TKT_qty' => 2 - ), - 'relations' => array( - 'Datetime' => array( 1, 3 ) - ) - ), - ) - ); - - $build_objects = $this->_eeTest->factory->complex_factory->build( $build_artifact ); - //assign the event object as the scenario object - $this->_scenario_object = reset( $build_objects['Event'] ); - } - - - - protected function _get_scenario_object(){ - return $this->_scenario_object; - } - -} - -// Location:/tests/includes/scenarios/EE_Event_Scenario_G.scenario.php diff --git a/tests/includes/scenarios/EE_Event_Scenario_H.scenario.php b/tests/includes/scenarios/EE_Event_Scenario_H.scenario.php deleted file mode 100644 index f2a54f8638e..00000000000 --- a/tests/includes/scenarios/EE_Event_Scenario_H.scenario.php +++ /dev/null @@ -1,134 +0,0 @@ -type = 'event'; - $this->name = 'Event Scenario H - Two Classes'; - $this->_skip = true; - parent::__construct( $eetest ); - } - - protected function _set_up_expected(){ - $this->_expected_values = array( - 'total_available_spaces' => 12, - 'total_remaining_spaces' => 6, - 'total_remaining_spaces_4' => 4, - 'total_remaining_spaces_2' => 2, - 'total_remaining_spaces_0' => 0, - ); - } - - - - /** - * @throws \Exception - */ - protected function _set_up_scenario(){ - $build_artifact = array( - 'Event' => array( - 1 => array( - 'fields' => array( - 'EVT_name' => 'Test Scenario EVT H - Two Classes', - 'status' => 'publish', - ) - ) - ), - 'Datetime' => array( - 1 => array( - 'fields' => array( - 'DTT_name' => 'Class 1 of 2', - 'DTT_EVT_start' => time() + ( 7 * DAY_IN_SECONDS ), - 'DTT_EVT_end' => time() + ( 7.5 * DAY_IN_SECONDS ), - 'DTT_reg_limit' => 12, - 'DTT_sold' => 0, - ), - 'relations' => array( - 'Event' => array( 1 ) - ) - ), - 2 => array( - 'fields' => array( - 'DTT_name' => 'Class 2 of 2', - 'DTT_EVT_start' => time() + ( 14 * DAY_IN_SECONDS ), - 'DTT_EVT_end' => time() + ( 14.5 * DAY_IN_SECONDS ), - 'DTT_reg_limit' => 12, - 'DTT_sold' => 0, - ), - 'relations' => array( - 'Event' => array( 1 ) - ) - ) - ), - 'Ticket' => array( - 1 => array( - 'fields' => array( - 'TKT_name' => 'Ticket 1', - 'TKT_qty' => 12, - 'TKT_sold' => 0, - ), - 'relations' => array( - 'Datetime' => array( 1, 2 ) - ) - ), - ), - ); - - $build_objects = $this->_eeTest->factory->complex_factory->build( $build_artifact ); - //assign the event object as the scenario object - $this->_scenario_object = reset( $build_objects['Event'] ); - $this->_sell_tickets( $this->_get_event_ticket() , 6 ); - } - - - - protected function _get_scenario_object(){ - return $this->_scenario_object; - } - - - - /** - * @return EE_Ticket|null - */ - protected function _get_event_ticket() { - $ticket = null; - if ( $this->_scenario_object instanceof EE_Event ) { - $tickets = $this->_scenario_object->tickets(); - $ticket = reset( $tickets ); - } - return $ticket; - } - - - - /** - * run_additional_logic - * - * @param array $arguments - */ - public function run_additional_logic( $arguments = array() ) { - $qty = isset( $arguments['qty'] ) ? $arguments[ 'qty' ] : 0; - if ( $qty ) { - $this->_sell_tickets( $this->_get_event_ticket(), $qty ); - } - } - - -} - -// Location:/tests/includes/scenarios/EE_Event_Scenario_H.scenario.php \ No newline at end of file diff --git a/tests/includes/scenarios/EE_Event_Scenario_I.scenario.php b/tests/includes/scenarios/EE_Event_Scenario_I.scenario.php deleted file mode 100644 index 25a9d6daaa2..00000000000 --- a/tests/includes/scenarios/EE_Event_Scenario_I.scenario.php +++ /dev/null @@ -1,162 +0,0 @@ -type = 'event'; - $this->name = 'Event Scenario I - Four Tickets One Date'; - $this->_skip = true; - parent::__construct( $eetest ); - } - - protected function _set_up_expected(){ - $this->_expected_values = array( - 'total_available_spaces' => 24, - 'total_remaining_spaces' => 24, - 'total_remaining_spaces_20' => 20, - 'total_remaining_spaces_16' => 16, - 'total_remaining_spaces_12' => 12, - 'total_remaining_spaces_8' => 8, - 'total_remaining_spaces_4' => 4, - 'total_remaining_spaces_0' => 0, - ); - } - - - - /** - * @throws \Exception - */ - protected function _set_up_scenario(){ - $build_artifact = array( - 'Event' => array( - 1 => array( - 'fields' => array( - 'EVT_name' => 'Test Scenario EVT H - Four Tickets One Date', - 'status' => 'publish', - ) - ) - ), - 'Datetime' => array( - 1 => array( - 'fields' => array( - 'DTT_name' => 'D1', - 'DTT_EVT_start' => time() + ( 7 * DAY_IN_SECONDS ), - 'DTT_EVT_end' => time() + ( 7.5 * DAY_IN_SECONDS ), - 'DTT_reg_limit' => 25, - 'DTT_sold' => 0, - ), - 'relations' => array( - 'Event' => array( 1 ) - ) - ), - ), - 'Ticket' => array( - 1 => array( - 'fields' => array( - 'TKT_name' => 'Ticket 1', - 'TKT_qty' => 6, - 'TKT_sold' => 0, - ), - 'relations' => array( - 'Datetime' => array( 1 ) - ) - ), - 2 => array( - 'fields' => array( - 'TKT_name' => 'Ticket 2', - 'TKT_qty' => 6, - 'TKT_sold' => 0, - ), - 'relations' => array( - 'Datetime' => array( 1 ) - ) - ), - 3 => array( - 'fields' => array( - 'TKT_name' => 'Ticket 3', - 'TKT_qty' => 6, - 'TKT_sold' => 0, - ), - 'relations' => array( - 'Datetime' => array( 1 ) - ) - ), - 4 => array( - 'fields' => array( - 'TKT_name' => 'Ticket 4', - 'TKT_qty' => 6, - 'TKT_sold' => 0, - ), - 'relations' => array( - 'Datetime' => array( 1 ) - ) - ), - ), - ); - - $build_objects = $this->_eeTest->factory->complex_factory->build( $build_artifact ); - //assign the event object as the scenario object - $this->_scenario_object = reset( $build_objects['Event'] ); - } - - - - protected function _get_scenario_object(){ - return $this->_scenario_object; - } - - - - /** - * @param int $tkt_id - * @return \EE_Ticket|null - */ - protected function _get_event_ticket( $tkt_id = 0 ) { - $ticket = null; - if ( $this->_scenario_object instanceof EE_Event ) { - $tickets = $this->_scenario_object->tickets(); - foreach ( $tickets as $tkt ) { - if ( $tkt instanceof EE_Ticket ) { - $ticket = $tkt->name() === 'Ticket ' . $tkt_id ? $tkt : $ticket; - } - } - } - return $ticket; - } - - - - /** - * run_additional_logic - * - * @param array $arguments - */ - public function run_additional_logic( $arguments = array() ) { - $qty = isset( $arguments['qty'] ) ? $arguments[ 'qty' ] : 0; - $tkt_id = isset( $arguments['tkt_id'] ) ? $arguments[ 'tkt_id' ] : 0; - if ( $qty && $tkt_id ) { - $this->_sell_tickets( $this->_get_event_ticket( $tkt_id ), $qty ); - } - } - - -} - -// Location:/tests/includes/scenarios/EE_Event_Scenario_H.scenario.php \ No newline at end of file diff --git a/tests/includes/scenarios/EE_Event_Scenario_J.scenario.php b/tests/includes/scenarios/EE_Event_Scenario_J.scenario.php deleted file mode 100644 index 4e4248088ea..00000000000 --- a/tests/includes/scenarios/EE_Event_Scenario_J.scenario.php +++ /dev/null @@ -1,108 +0,0 @@ -type = 'event'; - $this->name = 'Event Scenario J'; - parent::__construct( $eetest ); - } - - protected function _set_up_expected(){ - $this->_expected_values = array( - 'total_available_spaces' => 18, - 'total_remaining_spaces' => 8 - ); - } - - - protected function _set_up_scenario(){ - $build_artifact = array( - 'Event' => array( - 1 => array( - 'fields' => array( 'EVT_name' => 'Test Scenario EVT J' ) - ) - ), - 'Datetime' => array( - 1 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 1', - 'DTT_reg_limit' => 18, - ), - 'relations' => array( - 'Event' => array( 1 ) - ) - ) - ), - 'Ticket' => array( - 1 => array( - 'fields' => array( - 'TKT_name' => 'Ticket 1', - 'TKT_qty' => 18 - ), - 'relations' => array( - 'Datetime' => array( 1 ) - ) - ), - 2 => array( - 'fields' => array( - 'TKT_name' => 'Ticket 2', - 'TKT_qty' => 18 - ), - 'relations' => array( - 'Datetime' => array( 1 ) - ) - ) - ) - ); - - $build_objects = $this->_eeTest->factory->complex_factory->build( $build_artifact ); - // simulate 6 sales for ticket 1, which will also increase sold qty for D1 - if ( - isset( $build_objects['Ticket'], $build_objects['Ticket'][1] ) - && $build_objects['Ticket'][1] instanceof EE_Ticket - ) { - /** @type EE_Ticket $ticket */ - $ticket = $build_objects['Ticket'][1]; - $ticket->increase_sold( 6 ); - } - // and 4 sales for ticket 2, which will also increase sold qty for D1 - if ( - isset( $build_objects['Ticket'], $build_objects['Ticket'][2] ) - && $build_objects['Ticket'][2] instanceof EE_Ticket - ) { - /** @type EE_Ticket $ticket */ - $ticket = $build_objects['Ticket'][2]; - $ticket->increase_sold( 4 ); - } - //EEH_Debug_Tools::printr( $build_objects['Datetime'], 'Datetimes', __FILE__, __LINE__ ); - //assign the event object as the scenario object - $this->_scenario_object = reset( $build_objects['Event'] ); - } - - - - protected function _get_scenario_object(){ - return $this->_scenario_object; - } - -} - -// Location:/tests/includes/scenarios/EE_Event_Scenario_J.scenario.php diff --git a/tests/includes/scenarios/EE_Event_Scenario_K.scenario.php b/tests/includes/scenarios/EE_Event_Scenario_K.scenario.php deleted file mode 100644 index b23300706b2..00000000000 --- a/tests/includes/scenarios/EE_Event_Scenario_K.scenario.php +++ /dev/null @@ -1,117 +0,0 @@ -type = 'event'; - $this->name = 'Event Scenario K'; - parent::__construct($eetest); - } - - protected function _set_up_expected() - { - $this->_expected_values = array( - 'total_available_spaces' => 22, - 'total_remaining_spaces' => 1, - ); - } - - - protected function _set_up_scenario() - { - $build_artifact = array( - 'Event' => array( - 0 => array( - 'fields' => array('EVT_name' => 'Test Scenario EVT K'), - ), - ), - 'Datetime' => array( - 0 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 1', - 'DTT_reg_limit' => 10, - 'DTT_sold' => 10, - ), - 'relations' => array( - 'Event' => array(0), - ), - ), - 1 => array( - 'fields' => array( - 'DTT_name' => 'Datetime 2', - 'DTT_reg_limit' => 12, - 'DTT_sold' => 11, - ), - 'relations' => array( - 'Event' => array(0), - ), - ), - ), - 'Ticket' => array( - 0 => array( - 'fields' => array( - 'TKT_name' => 'Ticket A', - 'TKT_qty' => 10, - 'TKT_sold' => 0, - ), - 'relations' => array( - 'Datetime' => array(0), - ), - ), - 1 => array( - 'fields' => array( - 'TKT_name' => 'Ticket B', - 'TKT_qty' => 12, - 'TKT_sold' => 1, - ), - 'relations' => array( - 'Datetime' => array(1), - ), - ), - 2 => array( - 'fields' => array( - 'TKT_name' => 'Ticket C', - 'TKT_qty' => 10, - 'TKT_sold' => 10, - ), - 'relations' => array( - 'Datetime' => array(0, 1), - ), - ), - ), - ); - $build_objects = $this->_eeTest->factory->complex_factory->build($build_artifact); - //assign the event object as the scenario object - $this->_scenario_object = reset($build_objects['Event']); - } - - - - protected function _get_scenario_object() - { - return $this->_scenario_object; - } -} -// Location: EE_Event_Scenario_K.scenario.php diff --git a/tests/includes/scenarios/EE_Test_Scenario_Classes.php b/tests/includes/scenarios/EE_Test_Scenario_Classes.php deleted file mode 100644 index fdde13bb9af..00000000000 --- a/tests/includes/scenarios/EE_Test_Scenario_Classes.php +++ /dev/null @@ -1,413 +0,0 @@ -type = empty( $this->type ) ? 'Unknown' : $this->type; - $this->name = empty( $this->name ) ? get_class( $this ) : $this->name; - $this->_eeTest = $eeTest; - } - - - /** - * Add an expected key/value pair to the $expected property. - * - * @param string $key a reference for the expected $key - * @param mixed $value the expected value. - */ - public function add_expected( $key, $value ) { - $this->_expected_values[$key] = $value; - } - - - /** - * Returns whether the scenario has been initialized or not. - * @return bool - */ - public function is_initialized() { - return $this->_initialized; - } - - - /** - * Used to initialize the scenario (does nothing if its been initialized. - */ - public function initialize() { - if ( $this->is_initialized() ) { - return; - } - $this->_set_up_scenario(); - $this->_set_up_expected(); - $this->_initialized = true; - } - - - /** - * Reset the scenario to non-initialized state. Note this does not do any cleanup - */ - public function reset() { - $this->_initialized = false; - $this->_scenario_object = null; - } - - - - - - /** - * Used to retrieve the expected value for a given key on the scenario. - * - * @param string $key - * @return mixed - */ - public function get_expected( $key ) { - return isset( $this->_expected_values[$key] ) ? $this->_expected_values[$key] : false; - } - - - - - /** - * Return the test_scenario_object - * @return mixed - */ - public function get_scenario_object() { - if (empty( $this->_scenario_object) ) { - $this->_scenario_object = $this->_get_scenario_object(); - } - return $this->_scenario_object; - } - - - - /** - * simulate six sales for an event's ticket, which will also increase sold qty for D1 & D2 - * - * @param \EE_Ticket $ticket - * @param int $qty - * @throws \EE_Error - */ - protected function _sell_tickets( EE_Ticket $ticket, $qty = 1 ) { - if ( $ticket instanceof EE_Ticket ) { - $transaction = EE_Transaction::new_instance( - array( - 'STS_ID' => EEM_Transaction::complete_status_code, - 'TXN_timestamp' => time() - DAY_IN_SECONDS, - 'TXN_total' => 0, - 'TXN_paid' => 0, - ) - ); - $transaction->save(); - for ( $x = 1; $x <= $qty; $x++ ) { - $registration = EE_Registration::new_instance( - array( - 'STS_ID' => EEM_Registration::status_id_pending_payment, - 'REG_date' => time() - DAY_IN_SECONDS, - 'REG_code' => $transaction->ID() . "-" . $ticket->ID() . "-$x-test", - 'TXN_ID' => $transaction->ID(), - 'EVT_ID' => $ticket->get_event_ID(), - 'TKT_ID' => $ticket->ID(), - ) - ); - $registration->save(); - // upgrade status to RAP so that ticket and datetime sold values get incremented - $registration->set_status( EEM_Registration::status_id_approved ); - $registration->save(); - } - } - } - - - - /** - * @return boolean - */ - public function skip() { - return $this->_skip; - } - - - - /** - * Child classes are required to setup the initial "expected" property. - * - */ - abstract protected function _set_up_expected(); - - - - /** - * This method should contain all the code for setting up the scenario. - */ - abstract protected function _set_up_scenario(); - - - /** - * Used to return the main object(s) being setup for the test scenario. - * Test cases will likely want access to this for setting up the test! - * @return object | object[] - */ - abstract protected function _get_scenario_object(); - - - - /** - * Can be overridden in child classes for doing additional "stuff" during tests. - * - * @param array $arguments - */ - public function run_additional_logic( $arguments = array() ) { - } - - -} - - -/** - * This is used to store the EE_Test_Scenario collection for use by unit test cases. - * - * @package Event Espresso - * @subpackage tests - * @author Darren Ethier - */ -class EE_Test_Scenario_Collection extends EE_Object_Collection { - - - public function __construct() { - $this->interface = 'EE_Test_Scenario'; - } - - - - /** - * @param \EE_Test_Scenario $test_scenario - * @return bool - */ - public function add_test_scenario( EE_Test_Scenario $test_scenario ) { - return $this->add( $test_scenario, array( - 'type' => $test_scenario->type, - 'name' => $test_scenario->name - ) ); - } - - - - /** - * @param string $type - * @return array - */ - public function get_scenarios_by_type( $type ) { - return $this->getObjectByInfoArray( $type, 'type' ); - } - - - - /** - * @param string $name - * @return mixed - */ - public function get_scenario_by_name( $name ) { - $objects = $this->getObjectByInfoArray( $name, 'name' ); - return reset( $objects ); - } - - - /** - * @param mixed $info The value to check for. - * @param $key - * - * @return array - */ - protected function getObjectByInfoArray( $info, $key ) { - $objects = array(); - $this->rewind(); - while( $this->valid() ) { - $currentInfo = $this->getInfo(); - if ( ! is_array( $currentInfo ) ) { - $this->next(); - continue; - } - if ( isset( $currentInfo[$key] ) && $currentInfo[$key] === $info ) { - $objects[] = $this->current(); - $this->next(); - continue; - } - $this->next(); - } - $this->rewind(); - return $objects; - } - -} - - -/** - * This checks for all test scenarios in the tests/includes/scenarios/ folder - * and adds them to the EE_Test_Scenario repository. - * @package Event Espresso - * @subpackage tests - * @author Darren Ethier - */ -class EE_Test_Scenario_Factory { - - /** - * This will hold the collection containing all the test scenarios. - * @var EE_Test_Scenario_Collection - */ - protected $_collection; - - - /** - * @var EE_UnitTestCase - */ - protected $_eeTest; - - - - public function __construct( EE_UnitTestCase $eeTest ) { - $this->_eeTest = $eeTest; - } - - - protected function _build_scenarios() { - $scenario_files = glob( EE_TESTS_DIR . 'includes/scenarios/*.scenario.php' ); - - if ( ! empty( $scenario_files ) ) { - foreach ( $scenario_files as $scenario_file ) { - require_once $scenario_file; - $class_name = str_replace( '.scenario.php', '', basename( $scenario_file ) ); - if ( class_exists( $class_name ) ) { - $scenario = new $class_name( $this->_eeTest ); - $this->_collection->add_test_scenario( $scenario ); - } - } - } - } - - - /** - * This returns the EE_Test_Scenario collection - * @return EE_Test_Scenario_Collection - */ - public function get_collection() { - if ( ! $this->_collection instanceof EE_Test_Scenario_Collection ) { - $this->_collection = new EE_Test_Scenario_Collection(); - $this->_build_scenarios(); - } - return $this->_collection; - } - - - /** - * Return specific scenarios by type. - * - * @param string $type Type represents the type of EE_Test_Scenarios to return. - * @param bool $initialize Whether to initialize the scenarios or just return them uninitialized. (default is to - * initialize) - * - * @return EE_Test_Scenario[] - */ - public function get_scenarios_by_type( $type, $initialize = true ) { - $this->get_collection(); - $scenarios = $this->_collection->get_scenarios_by_type( $type ); - if ( $scenarios && $initialize) { - foreach ( $scenarios as $scenario ) { - if ( $scenario instanceof EE_Test_Scenario ) { - $scenario->initialize(); - } - } - } - return $scenarios; - } - - - /** - * Return specific scenario by name; - * - * @param string $name The specific name to return the scenario for. - * @param bool $initialize Whether to initialize the scenarios or just return them uninitialized. (default is to - * initialize). - * @return EE_Test_Scenario - */ - public function get_scenario_by_name( $name, $initialize = true ) { - $this->get_collection(); - $scenario = $this->_collection->get_scenario_by_name( $name ); - if ( $scenario instanceof EE_Test_Scenario && $initialize ) { - $scenario->initialize(); - } - return $scenario; - } - -} diff --git a/tests/includes/speed-trap-listener.php b/tests/includes/speed-trap-listener.php deleted file mode 100644 index dc5bc3d19d2..00000000000 --- a/tests/includes/speed-trap-listener.php +++ /dev/null @@ -1,326 +0,0 @@ -loadOptions($options); - } - - /** - * An error occurred. - * - * @param PHPUnit_Framework_Test $test - * @param Exception $e - * @param float $time - */ - public function addError(PHPUnit_Framework_Test $test, Exception $e, $time) - { - } - - /** - * A warning occurred. - * - * @param PHPUnit_Framework_Test $test - * @param PHPUnit_Framework_Warning $e - * @param float $time - * @since Method available since Release 5.1.0 - */ - public function addWarning(PHPUnit_Framework_Test $test, PHPUnit_Framework_Warning $e, $time) - { - } - - /** - * A failure occurred. - * - * @param PHPUnit_Framework_Test $test - * @param PHPUnit_Framework_AssertionFailedError $e - * @param float $time - */ - public function addFailure(PHPUnit_Framework_Test $test, PHPUnit_Framework_AssertionFailedError $e, $time) - { - } - - /** - * Incomplete test. - * - * @param PHPUnit_Framework_Test $test - * @param Exception $e - * @param float $time - */ - public function addIncompleteTest(PHPUnit_Framework_Test $test, Exception $e, $time) - { - } - - /** - * Risky test. - * - * @param PHPUnit_Framework_Test $test - * @param Exception $e - * @param float $time - * @since Method available since Release 4.0.0 - */ - public function addRiskyTest(PHPUnit_Framework_Test $test, Exception $e, $time) - { - } - - /** - * Skipped test. - * - * @param PHPUnit_Framework_Test $test - * @param Exception $e - * @param float $time - */ - public function addSkippedTest(PHPUnit_Framework_Test $test, Exception $e, $time) - { - } - - /** - * A test started. - * - * @param PHPUnit_Framework_Test $test - */ - public function startTest(PHPUnit_Framework_Test $test) - { - } - - /** - * A test ended. - * - * @param PHPUnit_Framework_Test $test - * @param float $time - */ - public function endTest(PHPUnit_Framework_Test $test, $time) - { - if (!$test instanceof PHPUnit_Framework_TestCase) return; - - $time = $this->toMilliseconds($time); - $threshold = $this->getSlowThreshold($test); - - if ($this->isSlow($time, $threshold)) { - $this->addSlowTest($test, $time); - } - } - - /** - * A test suite started. - * - * @param PHPUnit_Framework_TestSuite $suite - */ - public function startTestSuite(PHPUnit_Framework_TestSuite $suite) - { - $this->suites++; - } - - /** - * A test suite ended. - * - * @param PHPUnit_Framework_TestSuite $suite - */ - public function endTestSuite(PHPUnit_Framework_TestSuite $suite) - { - $this->suites--; - - if (0 === $this->suites && $this->hasSlowTests()) { - arsort($this->slow); // Sort longest running tests to the top - - $this->renderHeader(); - $this->renderBody(); - $this->renderFooter(); - } - } - - /** - * Whether the given test execution time is considered slow. - * - * @param int $time Test execution time in milliseconds - * @param int $slowThreshold Test execution time at which a test should be considered slow (milliseconds) - * @return bool - */ - protected function isSlow($time, $slowThreshold) - { - return $time >= $slowThreshold; - } - - /** - * Stores a test as slow. - * - * @param PHPUnit_Framework_TestCase $test - * @param int $time Test execution time in milliseconds - */ - protected function addSlowTest(PHPUnit_Framework_TestCase $test, $time) - { - $label = $this->makeLabel($test); - - $this->slow[$label] = $time; - } - - /** - * Whether at least one test has been considered slow. - * - * @return bool - */ - protected function hasSlowTests() - { - return !empty($this->slow); - } - - /** - * Convert PHPUnit's reported test time (microseconds) to milliseconds. - * - * @param float $time - * @return int - */ - protected function toMilliseconds($time) - { - return (int) round($time * 1000); - } - - /** - * Label for describing a test. - * - * @param PHPUnit_Framework_TestCase $test - * @return string - */ - protected function makeLabel(PHPUnit_Framework_TestCase $test) - { - return sprintf('%s:%s', get_class($test), $test->getName()); - } - - /** - * Calculate number of slow tests to report about. - * - * @return int - */ - protected function getReportLength() - { - return min(count($this->slow), $this->reportLength); - } - - /** - * Find how many slow tests occurred that won't be shown due to list length. - * - * @return int Number of hidden slow tests - */ - protected function getHiddenCount() - { - $total = count($this->slow); - $showing = $this->getReportLength($this->slow); - - $hidden = 0; - if ($total > $showing) { - $hidden = $total - $showing; - } - - return $hidden; - } - - /** - * Renders slow test report header. - */ - protected function renderHeader() - { - echo sprintf("\n\nYou should really fix these slow tests (>%sms)...\n", $this->slowThreshold); - } - - /** - * Renders slow test report body. - */ - protected function renderBody() - { - $slowTests = $this->slow; - - $length = $this->getReportLength($slowTests); - for ($i = 1; $i <= $length; ++$i) { - $label = key($slowTests); - $time = array_shift($slowTests); - - echo sprintf(" %s. %sms to run %s\n", $i, $time, $label); - } - } - - /** - * Renders slow test report footer. - */ - protected function renderFooter() - { - if ($hidden = $this->getHiddenCount($this->slow)) { - echo sprintf("...and there %s %s more above your threshold hidden from view", $hidden == 1 ? 'is' : 'are', $hidden); - } - } - - /** - * Populate options into class internals. - * - * @param array $options - */ - protected function loadOptions(array $options) - { - $this->slowThreshold = isset($options['slowThreshold']) ? $options['slowThreshold'] : 500; - $this->reportLength = isset($options['reportLength']) ? $options['reportLength'] : 10; - } - - /** - * Get slow test threshold for given test. A TestCase can override the - * suite-wide slow threshold by using the annotation @slowThreshold with - * the threshold value in milliseconds. - * - * The following test will only be considered slow when its execution time - * reaches 5000ms (5 seconds): - * - * - * @slowThreshold 5000 - * public function testLongRunningProcess() {} - * - * - * @param PHPUnit_Framework_TestCase $test - * @return int - */ - protected function getSlowThreshold(PHPUnit_Framework_TestCase $test) - { - $ann = $test->getAnnotations(); - - return isset($ann['method']['slowThreshold'][0]) ? $ann['method']['slowThreshold'][0] : $this->slowThreshold; - } -} diff --git a/tests/javascript-config/unit/jest.config.json b/tests/javascript-config/unit/jest.config.json deleted file mode 100644 index ba132b93dec..00000000000 --- a/tests/javascript-config/unit/jest.config.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "rootDir": "../../../", - "collectCoverageFrom": [ - "assets/src/**/*.js", - "!**/node_modules/**", - "!**/vendor/**", - "!**/test/**" - ], - "moduleNameMapper": { - "@eventespresso\\/(eejs)": "$1" - }, - "setupFiles": [ - "/tests/javascript-config/unit/setup-globals.js" - ], - "preset": "@wordpress/jest-preset-default", - "testPathIgnorePatterns": [ - "/node_modules/", - "/test/e2e" - ] -} diff --git a/tests/javascript-config/unit/setup-globals.js b/tests/javascript-config/unit/setup-globals.js deleted file mode 100644 index f1abdf83b22..00000000000 --- a/tests/javascript-config/unit/setup-globals.js +++ /dev/null @@ -1,10 +0,0 @@ -/** - * Setup globals used in various tests - */ -// Setup eejsdata global. This is something set in EE core via -// wp_localize_script so its outside of the build process. -global.eejsdata = { - data: { - testData: true - }, -}; \ No newline at end of file diff --git a/tests/kint/.gitignore b/tests/kint/.gitignore deleted file mode 100644 index 21a62842326..00000000000 --- a/tests/kint/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ - -/config.php -/.idea \ No newline at end of file diff --git a/tests/kint/Kint.class.php b/tests/kint/Kint.class.php deleted file mode 100644 index 95418859b61..00000000000 --- a/tests/kint/Kint.class.php +++ /dev/null @@ -1,742 +0,0 @@ - 0 ) { - self::$enabled = $value; - return; - } - - # ...and a getter - return self::$enabled; - } - - public static function _init() - { - # init settings - if ( isset( $GLOBALS['_kint_settings'] ) ) { - foreach ( $GLOBALS['_kint_settings'] as $key => $val ) { - self::$$key = $val; - } - } - - require KINT_DIR . 'decorators/rich.php'; - require KINT_DIR . 'decorators/concise.php'; - } - - /** - * Prints a debug backtrace - * - * @param array $trace [OPTIONAL] you can pass your own trace, otherwise, `debug_backtrace` will be called - * - * @return void - */ - public static function trace( $trace = null ) - { - if ( !Kint::enabled() ) return; - - echo Kint_Decorators_Rich::_css(); - - isset( $trace ) or $trace = debug_backtrace( true ); - - $output = array(); - foreach ( $trace as $step ) { - self::$traceCleanupCallback and $step = call_user_func( self::$traceCleanupCallback, $step ); - - # if the user defined trace cleanup function returns null, skip this line - if ( $step === null ) { - continue; - } - - if ( !isset( $step['function'] ) ) { - # invalid trace step - continue; - } - - if ( isset( $step['file'] ) AND isset( $step['line'] ) ) { - # include the source of this step - $source = self::_showSource( $step['file'], $step['line'] ); - } - - if ( isset( $step['file'] ) ) { - $file = $step['file']; - - if ( isset( $step['line'] ) ) { - $line = $step['line']; - } - } - - - $function = $step['function']; - - if ( in_array( $step['function'], self::$_statements ) ) { - if ( empty( $step['args'] ) ) { - # no arguments - $args = array(); - } else { - # sanitize the file path - $args = array( self::shortenPath( $step['args'][0] ) ); - } - } elseif ( isset( $step['args'] ) ) { - if ( empty( $step['class'] ) && !function_exists( $step['function'] ) ) { - # introspection on closures or language constructs in a stack trace is impossible before PHP 5.3 - $params = null; - } else { - try { - if ( isset( $step['class'] ) ) { - if ( method_exists( $step['class'], $step['function'] ) ) { - $reflection = new ReflectionMethod( $step['class'], $step['function'] ); - } else if ( isset( $step['type'] ) && $step['type'] == '::' ) { - $reflection = new ReflectionMethod( $step['class'], '__callStatic' ); - } else { - $reflection = new ReflectionMethod( $step['class'], '__call' ); - } - } else { - $reflection = new ReflectionFunction( $step['function'] ); - } - - # get the function parameters - $params = $reflection->getParameters(); - } catch ( Exception $e ) { - $params = null; # avoid various PHP version incompatibilities - } - } - - $args = array(); - foreach ( $step['args'] as $i => $arg ) { - if ( isset( $params[$i] ) ) { - # assign the argument by the parameter name - $args[$params[$i]->name] = $arg; - } else { - # assign the argument by number - $args[$i] = $arg; - } - } - } - - if ( isset( $step['class'] ) ) { - # Class->method() or Class::method() - $function = $step['class'] . $step['type'] . $step['function']; - } - - if ( isset( $step['object'] ) ) { - $function = $step['class'] . $step['type'] . $step['function']; - } - - $output[] = array( - 'function' => $function, - 'args' => isset( $args ) ? $args : null, - 'file' => isset( $file ) ? $file : null, - 'line' => isset( $line ) ? $line : null, - 'source' => isset( $source ) ? $source : null, - 'object' => isset( $step['object'] ) ? $step['object'] : null, - ); - - unset( $function, $args, $file, $line, $source ); - } - - require KINT_DIR . 'view/trace.phtml'; - } - - /** - * dump information about variables - * - * @param mixed $data - * - * @return void|string - */ - public static function dump( $data = null ) - { - if ( !Kint::enabled() ) return; - - # find caller information - $trace = debug_backtrace(); - list( $names, $modifier, $callee, $previousCaller ) = self::_getPassedNames( $trace ); - if ( $names === array( null ) && func_num_args() === 1 && $data === 1 ) { - $call = reset( $trace ); - if ( !isset( $call['file'] ) && isset( $call['class'] ) && $call['class'] === __CLASS__ ) { - array_shift( $trace ); - $call = reset( $trace ); - } - - while ( isset( $call['file'] ) && $call['file'] === __FILE__ ) { - array_shift( $trace ); - $call = reset( $trace ); - } - - self::trace( $trace ); - return; - } - - # process modifiers: @, + and - - switch ( $modifier ) { - case '-': - self::$_firstRun = true; - while ( ob_get_level() ) { - ob_end_clean(); - } - break; - - case '!': - self::$expandedByDefault = true; - break; - case '+': - $maxLevelsOldValue = self::$maxLevels; - self::$maxLevels = false; - break; - case '@': - $firstRunOldValue = self::$_firstRun; - self::$_firstRun = true; - break; - } - - - $data = func_num_args() === 0 - ? array( "[[no arguments passed]]" ) - : func_get_args(); - - - $output = Kint_Decorators_Rich::_css(); - $output .= Kint_Decorators_Rich::_wrapStart( $callee ); - - foreach ( $data as $k => $argument ) { - $output .= self::_dump( $argument, $names[$k] ); - } - $output .= Kint_Decorators_Rich::_wrapEnd( $callee, $previousCaller ); - - self::$_firstRun = false; - - switch ( $modifier ) { - case '+': - self::$maxLevels = $maxLevelsOldValue; - echo $output; - break; - case '@': - self::$_firstRun = $firstRunOldValue; - return $output; - break; - default: - echo $output; - break; - } - - return ''; - } - - protected static function _dump( $var, $name = '' ) - { - kintParser::reset(); - return Kint_Decorators_Rich::decorate( - kintParser::factory( $var, $name ) - ); - } - - - /** - * generic path display callback, can be configured in the settings - * - * @param string $file - * @param int $line [OPTIONAL] - * - * @return string - */ - public static function shortenPath( $file, $line = null ) - { - $file = str_replace( '\\', '/', $file ); - $shortenedName = $file; - foreach ( self::$appRootDirs as $path => $replaceString ) { - $path = str_replace( '\\', '/', $path ); - - if ( strpos( $file, $path ) === 0 ) { - $shortenedName = $replaceString . substr( $file, strlen( $path ) ); - break; - } - } - - - if ( !$line ) { # means this is called from resource type dump - return $shortenedName; - } - - if ( !self::$fileLinkFormat ) { - return "{$shortenedName} line {$line}"; - } - - $url = str_replace( array( '%f', '%l' ), array( $file, $line ), self::$fileLinkFormat ); - $class = ( strpos( $url, 'http://' ) === 0 ) ? 'class="kint-ide-link"' : ''; - - return "{$shortenedName} line {$line}"; - } - - - /** - * trace helper, shows the place in code inline - * - * @param string $file full path to file - * @param int $lineNumber the line to display - * @param int $padding surrounding lines to show besides the main one - * - * @return bool|string - */ - private static function _showSource( $file, $lineNumber, $padding = 7 ) - { - if ( !$file OR !is_readable( $file ) ) { - # continuing will cause errors - return false; - } - - # open the file and set the line position - $file = fopen( $file, 'r' ); - $line = 0; - - # Set the reading range - $range = array( - 'start' => $lineNumber - $padding, - 'end' => $lineNumber + $padding - ); - - # set the zero-padding amount for line numbers - $format = '% ' . strlen( $range['end'] ) . 'd'; - - $source = ''; - while ( ( $row = fgets( $file ) ) !== false ) { - # increment the line number - if ( ++$line > $range['end'] ) { - break; - } - - if ( $line >= $range['start'] ) { - # make the row safe for output - $row = htmlspecialchars( $row, ENT_NOQUOTES ); - - # trim whitespace and sanitize the row - $row = '' . sprintf( $format, $line ) . ' ' . $row; - - if ( $line === $lineNumber ) { - # apply highlighting to this row - $row = '
' . $row . '
'; - } else { - $row = '
' . $row . '
'; - } - - # add to the captured source - $source .= $row; - } - } - - # close the file - fclose( $file ); - - return $source; - } - - - /** - * returns parameter names that the function was passed, as well as any predefined symbols before function - * call (modifiers) - * - * @param array $trace - * - * @return array( $parameters, $modifier, $callee, $previousCaller ) - */ - private static function _getPassedNames( $trace ) - { - $previousCaller = array(); - while ( $callee = array_pop( $trace ) ) { - if ( strtolower( $callee['function'] ) === 'd' || - strtolower( $callee['function'] ) === 'dd' || - ( isset( $callee['class'] ) && strtolower( $callee['class'] ) === strtolower( __CLASS__ ) - && strtolower( $callee['function'] ) === 'dump' ) - ) { - break; - } else { - $previousCaller = $callee; - } - } - - if ( !isset( $callee['file'] ) || !is_readable( $callee['file'] ) ) { - return false; - } - - # open the file and read it up to the position where the function call expression ended - $file = fopen( $callee['file'], 'r' ); - $line = 0; - $source = ''; - while ( ( $row = fgets( $file ) ) !== false ) { - if ( ++$line > $callee['line'] ) break; - $source .= $row; - } - fclose( $file ); - $source = self::_removeAllButCode( $source ); - - - $codePattern = empty( $callee['class'] ) - ? $callee['function'] - : $callee['class'] . "\x07*" . $callee['type'] . "\x07*" . $callee['function']; - # get the position of the last call to the function - preg_match_all( "#[\x07{(](\\+|-|!|@)?{$codePattern}\x07*(\\()#i", $source, $matches, PREG_OFFSET_CAPTURE ); - $match = end( $matches[2] ); - $modifier = end( $matches[1] ); - $modifier = $modifier[0]; - - $passedParameters = str_replace( "\x07", '', substr( $source, $match[1] + 1 ) ); - # we now have a string like this: - # ); - - # remove everything in brackets and quotes, we don't need nested statements nor literal strings which would - # only complicate separating individual arguments - $c = strlen( $passedParameters ); - $inString = $escaped = false; - $i = 0; - $inBrackets = 0; - while ( $i < $c ) { - $letter = $passedParameters[$i]; - if ( $inString === false ) { - if ( $letter === '\'' || $letter === '"' ) { - $inString = $letter; - } elseif ( $letter === '(' ) { - $inBrackets++; - } elseif ( $letter === ')' ) { - $inBrackets--; - if ( $inBrackets === -1 ) { # this means we are out of the brackets that denote passed parameters - $passedParameters = substr( $passedParameters, 0, $i ); - break; - } - } - } elseif ( $letter === $inString && !$escaped ) { - $inString = false; - } - - # place an untype-able character instead of whatever was inside quotes or brackets, we don't - # need that info. We'll later replace it with '...' - if ( $inBrackets > 0 ) { - if ( $inBrackets > 1 || $letter !== '(' ) { - $passedParameters[$i] = "\x07"; - } - } - if ( $inString !== false ) { - if ( $letter !== $inString || $escaped ) { - $passedParameters[$i] = "\x07"; - } - } - - $escaped = !$escaped && ( $letter === '\\' ); - $i++; - } - - # by now we have an unnested arguments list, lets make it to an array for processing further - $arguments = explode( ',', preg_replace( "#\x07+#", '...', $passedParameters ) ); - - # test each argument whether it was passed literary or was it an expression or a variable name - $parameters = array(); - $blacklist = array( 'null', 'true', 'false', 'array(...)', 'array()', '"..."', 'b"..."', ); - foreach ( $arguments as $argument ) { - - if ( is_numeric( $argument ) - || in_array( str_replace( "'", '"', strtolower( $argument ) ), $blacklist, true ) - ) { - $parameters[] = null; - } else { - $parameters[] = trim( $argument ); - } - } - - return array( $parameters, $modifier, $callee, $previousCaller ); - } - - /** - * removes comments and zaps whitespace & true, T_INLINE_HTML => true, T_DOC_COMMENT => true ); - - defined( 'T_NS_SEPARATOR' ) or define( 'T_NS_SEPARATOR', 380 ); - - $whiteSpaceTokens = array( - T_WHITESPACE => true, T_CLOSE_TAG => true, - T_OPEN_TAG => true, T_OPEN_TAG_WITH_ECHO => true, - ); - - foreach ( $tokens as $token ) { - if ( is_array( $token ) ) { - if ( isset( $commentTokens[$token[0]] ) ) continue; - - if ( $token[0] === T_NEW ) { - $token = 'new '; - } elseif ( $token[0] === T_NS_SEPARATOR ) { - $token = "\\\x07"; - } elseif ( isset( $whiteSpaceTokens[$token[0]] ) ) { - $token = "\x07"; - } else { - $token = $token[1]; - } - } elseif ( $token === ';' ) { - $token = "\x07"; - } - - $newStr .= $token; - } - return $newStr; - } -} - - -if ( !function_exists( 'd' ) ) { - /** - * Alias of Kint::dump() - * - * @return string - */ - function d() - { - if ( !Kint::enabled() ) return null; - - $args = func_get_args(); - return call_user_func_array( array( 'Kint', 'dump' ), $args ); - } -} - -if ( !function_exists( 'dd' ) ) { - /** - * Alias of Kint::dump() - * [!!!] IMPORTANT: execution will halt after call to this function - * - * @return string - */ - function dd() - { - if ( !Kint::enabled() ) return; - - $args = func_get_args(); - call_user_func_array( array( 'Kint', 'dump' ), $args ); - die; - } -} - -if ( !function_exists( 's' ) ) { - - /** - * Alias of kintLite() - * - * @return string - */ - function s() - { - if ( !Kint::enabled() ) return; - - $argv = func_get_args(); - echo '
';
-		foreach ( $argv as $k => $v ) {
-			$k && print( "\n\n" );
-			echo kintLite( $v );
-		}
-		echo '
' . "\n"; - } - - /** - * Alias of kintLite() - * [!!!] IMPORTANT: execution will halt after call to this function - * - * @return string - */ - function sd() - { - if ( !Kint::enabled() ) return; - - echo '
';
-		foreach ( func_get_args() as $k => $v ) {
-			$k && print( "\n\n" );
-			echo kintLite( $v );
-		}
-		echo '
'; - die; - - } - -} - - -/** - * lightweight version of Kint::dump(). Uses whitespace for formatting instead of html - * sadly not DRY yet - * - * @param $var - * @param int $level - * - * @return string - */ -function kintLite( &$var, $level = 0 ) -{ - - // initialize function names into variables for prettier string output (html and implode are also DRY) - $html = "htmlspecialchars"; - $implode = "implode"; - $strlen = "strlen"; - $count = "count"; - $getClass = "get_class"; - - - if ( $var === null ) { - return 'NULL'; - } elseif ( is_bool( $var ) ) { - return 'bool ' . ( $var ? 'TRUE' : 'FALSE' ); - } elseif ( is_float( $var ) ) { - return 'float ' . $var; - } elseif ( is_int( $var ) ) { - return 'integer ' . $var; - } elseif ( is_resource( $var ) ) { - if ( ( $type = get_resource_type( $var ) ) === 'stream' AND $meta = stream_get_meta_data( $var ) ) { - - if ( isset( $meta['uri'] ) ) { - $file = $meta['uri']; - - return "resource ({$type}) {$html( $file, 0 )}"; - } else { - return "resource ({$type})"; - } - } else { - return "resource ({$type})"; - } - } elseif ( is_string( $var ) ) { - return "string ({$strlen( $var )}) \"{$html( $var )}\""; - } elseif ( is_array( $var ) ) { - $output = array(); - $space = str_repeat( $s = ' ', $level ); - - static $marker; - - if ( $marker === null ) { - // Make a unique marker - $marker = uniqid( "\x00" ); - } - - if ( empty( $var ) ) { - return "array()"; - } elseif ( isset( $var[$marker] ) ) { - $output[] = "[\n$space$s*RECURSION*\n$space]"; - } elseif ( $level < 7 ) { - $isSeq = array_keys( $var ) === range( 0, count( $var ) - 1 ); - - $output[] = "["; - - $var[$marker] = true; - - - foreach ( $var as $key => &$val ) { - if ( $key === $marker ) continue; - - $key = $space . $s . ( $isSeq ? "" : "'{$html( $key, 0 )}' => " ); - - $dump = kintLite( $val, $level + 1 ); - $output[] = "{$key}{$dump}"; - } - - unset( $var[$marker] ); - $output[] = "$space]"; - - } else { - $output[] = "[\n$space$s*depth too great*\n$space]"; - } - return "array({$count( $var )}) {$implode( "\n", $output )}"; - } elseif ( is_object( $var ) ) { - if ( $var instanceof SplFileInfo ) { - return "object SplFileInfo " . $var->getRealPath(); - } - - // Copy the object as an array - $array = (array)$var; - - $output = array(); - $space = str_repeat( $s = ' ', $level ); - - $hash = spl_object_hash( $var ); - - // Objects that are being dumped - static $objects = array(); - - if ( empty( $array ) ) { - return "object {$getClass( $var )} {}"; - } elseif ( isset( $objects[$hash] ) ) { - $output[] = "{\n$space$s*RECURSION*\n$space}"; - } elseif ( $level < 7 ) { - $output[] = "{"; - $objects[$hash] = true; - - foreach ( $array as $key => & $val ) { - if ( $key[0] === "\x00" ) { - - $access = $key[1] === "*" ? "protected" : "private"; - - // Remove the access level from the variable name - $key = substr( $key, strrpos( $key, "\x00" ) + 1 ); - } else { - $access = "public"; - } - - $output[] = "$space$s$access $key -> " . kintLite( $val, $level + 1 ); - } - unset( $objects[$hash] ); - $output[] = "$space}"; - - } else { - $output[] = "{\n$space$s*depth too great*\n$space}"; - } - - return "object {$getClass( $var )} ({$count( $array )}) {$implode( "\n", $output )}"; - } else { - return gettype( $var ) . htmlspecialchars( var_export( $var, true ), ENT_NOQUOTES ); - } -} - -Kint::_init(); diff --git a/tests/kint/LICENCE b/tests/kint/LICENCE deleted file mode 100644 index 936fe1f168f..00000000000 --- a/tests/kint/LICENCE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 Rokas Šleinius (raveren@gmail.com) - -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. \ No newline at end of file diff --git a/tests/kint/README.md b/tests/kint/README.md deleted file mode 100644 index 9fa5b480333..00000000000 --- a/tests/kint/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# Kint - debugging helper for PHP developers - -[![Total Downloads](https://poser.pugx.org/raveren/kint/downloads.png)](https://packagist.org/packages/raveren/kint) - -http://raveren.github.com/kint/ - -![Screenshot](http://raveren.github.com/kint/img/preview.png) - -Kint for PHP is a powerful and modern, zero-setup replacement for **[var_dump()](http://php.net/manual/en/function.var-dump.php)**, **[print_r()](http://php.net/manual/en/function.print-r.php)** and **[debug_backtrace()](http://php.net/manual/en/function.debug-backtrace.php)**. You'll wonder how you developed without it. - - ----- - - -## Installation and usage -```php -=5.2.0" - }, - "autoload": { - "files": ["Kint.class.php"] - } -} \ No newline at end of file diff --git a/tests/kint/config.default.php b/tests/kint/config.default.php deleted file mode 100644 index 004bb03a100..00000000000 --- a/tests/kint/config.default.php +++ /dev/null @@ -1,130 +0,0 @@ - '<ROOT>' ) - * - * [!] EXAMPLE (for Kohana framework): - * - * $_kintSettings['appRootDirs'] = array( - * APPPATH => 'APPPATH', // make sure the constants are already defined at the time of including this config file - * SYSPATH => 'SYSPATH', - * MODPATH => 'MODPATH', - * DOCROOT => 'DOCROOT', - * ); - * - * [!] EXAMPLE #2 (for a semi-universal approach) - * - * $_kintSettings['appRootDirs'] = array( - * realpath( __DIR__ . '/../../..' ) => 'ROOT', // go up as many levels as needed in the realpath() param - * ); - * - * $_kintSettings['fileLinkFormat'] = 'http://localhost:8091/?message=%f:%l'; - * - */ -$_kintSettings['appRootDirs'] = array( - $_SERVER['DOCUMENT_ROOT'] => '<ROOT>' -); - - -/** - * @var callable|null - * - * @param array $step each step of the backtrace is passed to this callback to clean it up or skip it entirely - * - * @return array|null you can return null if you want to bypass outputting this step - * - * [!] EXAMPLE: - * - * $_kintSettings['traceCleanupCallback'] = function( $traceStep ) { - * if ( isset( $traceStep['class'] ) && strtolower( $traceStep['class'] ) === 'errorHandler' ) { - * return null; - * } - * - * if ( isset( $traceStep['function'] ) && strtolower( $traceStep['function'] ) === '__tostring' ) { - * $traceStep['function'] = "[object converted to string]"; - * } - * - * return $traceStep; - * }; - */ -$_kintSettings['traceCleanupCallback'] = null; - - -/** @var int max length of string before it is truncated and displayed separately in full. Zero or false to disable */ -$_kintSettings['maxStrLength'] = 60; - -/** @var array possible alternative char encodings in order of probability, eg. array('windows-1251') */ -$_kintSettings['charEncodings'] = array(); - - -/** @var int max array/object levels to go deep, if zero no limits are applied */ -$_kintSettings['maxLevels'] = 8; - - -/** @var bool whether dumped indexed arrays that are in ideal sequence are displayed */ -$_kintSettings['hideSequentialKeys'] = true; - - -/** @var string name of theme for rich view */ -$_kintSettings['theme'] = 'original'; - - -/** - * @var callback filters array/object keys before outputting; return false if you do not wish to see it in the output - * - * @param string $key the key being output - * @param mixed $val the contents of the dumped element in case you need it - * - * @return bool return false to skip displaying - * - * [!] EXAMPLE: - * - * $_kintSettings['keyFilterCallback'] = function( $key, $val ) { - * if ( preg_match( '#_mt$#', $key ) ) { - * return false; - * } - * - * if ( $val === '--testing--' ) { - * return false; - * } - * - * // no need to return true to continue output - * }; - * - */ -$_kintSettings['keyFilterCallback'] = null; - - -/** @var bool only set to true if you want to develop kint and know what you're doing */ -$_kintSettings['devel'] = false; - - -unset( $_kintSettings ); \ No newline at end of file diff --git a/tests/kint/decorators/concise.php b/tests/kint/decorators/concise.php deleted file mode 100644 index 43858457f53..00000000000 --- a/tests/kint/decorators/concise.php +++ /dev/null @@ -1,58 +0,0 @@ -extendedValue - * - * @param kintVariableData $kintVar - * - * @return string - */ - public static function decorate( kintVariableData $kintVar ) - { - if ( $kintVar->extendedValue !== null || !empty( $kintVar->alternatives ) ) { - return Kint_Decorators_Rich::decorate( $kintVar ); - } - - if ( $kintVar->value !== null ) { - $output = 'name !== null ) { - $output .= $kintVar->name . " "; - } - - if ( $kintVar->type !== null ) { - $output .= $kintVar->type; - if ( $kintVar->subtype !== null ) { - $output .= " " . $kintVar->subtype; - } - $output .= " "; - } - - if ( $kintVar->operator !== null ) { - $output .= $kintVar->operator . ""; - } - - if ( $kintVar->size !== null ) { - $output .= "(" . $kintVar->size . ") "; - } - - $output = trim( $output ) . '">' . $kintVar->value . ''; - } else { - $output = 'NULL'; - } - - return $output; - } -} \ No newline at end of file diff --git a/tests/kint/decorators/plain.php b/tests/kint/decorators/plain.php deleted file mode 100644 index 203e60caf94..00000000000 --- a/tests/kint/decorators/plain.php +++ /dev/null @@ -1,54 +0,0 @@ -'; - - $extendedPresent = $kintVar->extendedValue !== null || $kintVar->alternatives !== null; - - if ( $extendedPresent ) { - $class = 'kint-parent'; - if ( Kint::$expandedByDefault ) { - $class .= ' kint-show'; - } - $output .= '
'; - } else { - $output .= '
'; - } - - $output .= self::_drawHeader( $kintVar ) . $kintVar->value . '
'; - - - if ( $extendedPresent ) { - $output .= '
'; - } - - if ( isset( $kintVar->extendedValue ) ) { - - if ( is_array( $kintVar->extendedValue ) ) { - foreach ( $kintVar->extendedValue as $v ) { - $output .= self::decorate( $v ); - } - } elseif ( is_string( $kintVar->extendedValue ) ) { - $output .= '
' . $kintVar->extendedValue . '
'; - } else { - $output .= self::decorate( $kintVar->extendedValue ); //it's kint's container - } - - } elseif ( isset( $kintVar->alternatives ) ) { - $output .= "
    "; - - foreach ( $kintVar->alternatives as $k => $var ) { - $active = $k === 0 ? ' class="kint-active-tab"' : ''; - $output .= "" . self::_drawHeader( $var, false ) . ''; - } - - $output .= "
    "; - - foreach ( $kintVar->alternatives as $var ) { - $output .= "
  • "; - - $var = $var->value; - - if ( is_array( $var ) ) { - foreach ( $var as $v ) { - $output .= self::decorate( $v ); - } - } elseif ( is_string( $var ) ) { - $output .= '
    ' . $var . '
    '; - } elseif ( isset( $var ) ) { - throw new Exception( - 'Kint has encountered an error, ' - . 'please paste this report to https://github.com/raveren/kint/issues
    ' - . 'Error encountered at ' . basename( __FILE__ ) . ':' . __LINE__ . '
    ' - . ' variables: ' - . htmlspecialchars( var_export( $kintVar->alternatives, true ), ENT_QUOTES ) - ); - } - - $output .= "
  • "; - } - - $output .= "
"; - } - if ( $extendedPresent ) { - $output .= '
'; - } - - $output .= ''; - - return $output; - } - - private static function _drawHeader( kintVariableData $kintVar, $verbose = true ) - { - $output = ''; - if ( $verbose ) { - if ( $kintVar->access !== null ) { - $output .= "" . $kintVar->access . " "; - } - - if ( $kintVar->name !== null && $kintVar->name !== '' ) { - $output .= "" . $kintVar->name . " "; - } - - if ( $kintVar->operator !== null ) { - $output .= $kintVar->operator . " "; - } - } - - if ( $kintVar->type !== null ) { - $output .= "" . $kintVar->type; - if ( $kintVar->subtype !== null ) { - $output .= " " . $kintVar->subtype; - } - $output .= " "; - } - - - if ( $kintVar->size !== null ) { - $output .= "(" . $kintVar->size . ") "; - } - - return $output; - } - - - /** - * produces css and js required for display. May be called multiple times, will only produce output once per - * pageload or until `-` or `@` modifier is used - * - * @return string - */ - protected static function _css() - { - if ( !self::$_firstRun ) return ''; - self::$_firstRun = false; - - $baseDir = KINT_DIR . 'view/inc/'; - - if ( !is_readable( $cssFile = $baseDir . self::$theme . '.css' ) ) { - $cssFile = $baseDir . 'original.css'; - } - - return '' - . '\n"; - } - - - /** - * called for each dump, opens the html tag - * - * @param array $callee caller information taken from debug backtrace - * - * @return string - */ - protected static function _wrapStart( $callee ) - { - // colors looping outputs the same (i.e. if same line in code dumps variables multiple time, - // we assume it's in a loop) - - $uid = isset( $callee['file'] ) ? crc32( $callee['file'] . $callee['line'] ) : 'no-file'; - - if ( isset( self::$_usedColors[$uid] ) ) { - $class = self::$_usedColors[$uid]; - } else { - $class = sizeof( self::$_usedColors ); - self::$_usedColors[$uid] = $class; - } - - $class = "kint_{$class}"; - - - return "
"; - } - - - /** - * closes Kint::_wrapStart() started html tags and displays callee information - * - * @param array $callee caller information taken from debug backtrace - * @param array $prevCaller previous caller information taken from debug backtrace - * - * @return string - */ - protected static function _wrapEnd( $callee, $prevCaller ) - { - if ( !Kint::$displayCalledFrom ) { - return '
'; - } - - $callingFunction = ''; - if ( isset( $prevCaller['class'] ) ) { - $callingFunction = $prevCaller['class']; - } - if ( isset( $prevCaller['type'] ) ) { - $callingFunction .= $prevCaller['type']; - } - if ( isset( $prevCaller['function'] ) && !in_array( $prevCaller['function'], Kint::$_statements ) ) { - $callingFunction .= $prevCaller['function'] . '()'; - } - $callingFunction and $callingFunction = " in ({$callingFunction})"; - - - $calleeInfo = isset( $callee['file'] ) - ? 'Called from ' . self::shortenPath( $callee['file'], $callee['line'] ) - : ''; - - - return $calleeInfo || $callingFunction - ? "
{$calleeInfo}{$callingFunction}
" - : ""; - } - -} \ No newline at end of file diff --git a/tests/kint/parsers/custom/arrayobject.php b/tests/kint/parsers/custom/arrayobject.php deleted file mode 100644 index 4c15e29fa1b..00000000000 --- a/tests/kint/parsers/custom/arrayobject.php +++ /dev/null @@ -1,26 +0,0 @@ -getParentClass(); - - if ( $parentClass !== false && $parentClass->name === 'ArrayObject' ) { - $arrayCopy = $variable->getArrayCopy(); - foreach ( $arrayCopy as $k => $var ) { - $t = kintParser::factory( $var ); - $t->name = "'{$k}'"; - $t->operator = '=>'; - $this->value[] = $t; - } - - $this->type = 'ArrayObject contents'; - $this->size = count( $arrayCopy ); - } else { - return false; - } - } -} diff --git a/tests/kint/parsers/custom/classmethods.php b/tests/kint/parsers/custom/classmethods.php deleted file mode 100644 index 58c7f4c7f1a..00000000000 --- a/tests/kint/parsers/custom/classmethods.php +++ /dev/null @@ -1,151 +0,0 @@ -getMethods() as $method) { - $params = array(); - - // Access type - $access = implode(' ', \Reflection::getModifierNames($method->getModifiers())); - - // Method parameters - foreach($method->getParameters() as $param) { - $paramString = ''; - - if ( $param->isArray() ) { - $paramString .= 'array '; - } else { - try { - if (( $paramClassName = $param->getClass() )) { - $paramString .= $paramClassName->name . ' '; - } - } catch ( ReflectionException $e ) { - preg_match( '/\[\s\<\w+?>\s([\w]+)/s', $param->__toString(), $matches ); - $paramClassName = isset( $matches[1] ) ? $matches[1] : ''; - - $paramString .= ' UNDEFINED CLASS (' . $paramClassName . ') '; - } - } - - $paramString .= ($param->isPassedByReference() ? '&' : '') . '$' . $param->getName(); - - if($param->isDefaultValueAvailable()) { - if(is_array($param->getDefaultValue())) { - $arrayValues = array(); - foreach($param->getDefaultValue() as $key => $value) { - $arrayValues[] = $key . ' => ' . $value; - } - - $defaultValue = 'array(' . implode(', ', $arrayValues) . ')'; - } elseif($param->getDefaultValue() === null){ - $defaultValue = 'NULL'; - } elseif($param->getDefaultValue() === false){ - $defaultValue = 'false'; - } elseif($param->getDefaultValue() === true){ - $defaultValue = 'true'; - } elseif($param->getDefaultValue() === ''){ - $defaultValue = '""'; - } else { - $defaultValue = $param->getDefaultValue(); - } - - $paramString .= ' = ' . $defaultValue; - } - - $params[] = $paramString; - } - - $output = new \kintVariableData(); - - // Simple DocBlock parser, look for @return - if(($docBlock = $method->getDocComment())) { - $matches = array(); - if(preg_match_all('/@(\w+)\s+(.*)\r?\n/m', $docBlock, $matches)) { - $lines = array_combine($matches[1], $matches[2]); - if(isset($lines['return'])) { - $output->operator = '->'; - # since we're outputting code, assumption that the string is utf8 is most likely correct - # and saves resources - $output->type = self::_escape( $lines['return'], 'UTF-8' ); - } - } - } - - $output->name = ($method->returnsReference() ? '&' : '') . $method->getName() . '(' - . implode(', ', $params) . ')'; - $output->access = $access; - - if(is_string($docBlock)) { - $lines = array(); - foreach(explode("\n", $docBlock) as $line) { - $line = trim($line); - - if(in_array($line, array('/**', '/*', '*/'))) { - continue; - }elseif(strpos($line, '*') === 0) { - $line = substr($line, 1); - } - - $lines[] = self::_escape( trim( $line ), 'UTF-8' ); - } - - $output->extendedValue = implode("\n", $lines) . "\n\n"; - } - - $declaringClass = $method->getDeclaringClass(); - $declaringClassName = $declaringClass->getName(); - - if($declaringClassName !== $className) { - $output->extendedValue .= "Inherited from {$declaringClassName}\n"; - } - - $fileName = \Kint::shortenPath($method->getFileName(), $method->getStartLine()); - - if($fileName) { - $output->extendedValue .= "Defined in {$fileName}"; - } - - $sortName = $access . $method->getName(); - - if($method->isPrivate()) { - $private[$sortName] = $output; - } elseif($method->isProtected()) { - $protected[$sortName] = $output; - } else { - $public[$sortName] = $output; - } - } - - if(!$private && !$protected && !$public) { - self::$cache[$className] = false; - } - - ksort($public); - ksort($protected); - ksort($private); - - self::$cache[$className] = $public + $protected + $private; - } - - $this->value = self::$cache[$className]; - $this->type = 'Available methods'; - $this->size = count(self::$cache[$className]); - } -} \ No newline at end of file diff --git a/tests/kint/parsers/custom/classstatics.php b/tests/kint/parsers/custom/classstatics.php deleted file mode 100644 index 1c6d0e48c0a..00000000000 --- a/tests/kint/parsers/custom/classstatics.php +++ /dev/null @@ -1,54 +0,0 @@ -getProperties( ReflectionProperty::IS_STATIC ) as $property ) { - if ( $property->isPrivate() ) { - if ( !method_exists( $property, 'setAccessible' ) ) { - break; - } - $property->setAccessible( true ); - $access = "private"; - } elseif ( $property->isProtected() ) { - $property->setAccessible( true ); - $access = "protected"; - } else { - $access = 'public'; - } - - if ( Kint::$keyFilterCallback - && call_user_func( Kint::$keyFilterCallback, $property->getName(), $property->getValue() ) === false - ) { - continue; - } - - $_ = $property->getValue(); - $output = kintParser::factory( $_, '$' . $property->getName() ); - - $output->access = $access; - $output->operator = '::'; - $extendedValue[] = $output; - } - - foreach ( $reflection->getConstants() as $constant => $val ) { - $output = kintParser::factory( $val, $constant ); - - $output->access = 'constant'; - $output->operator = '::'; - $extendedValue[] = $output; - } - - if ( empty( $extendedValue ) ) return false; - - $this->value = $extendedValue; - $this->type = 'Static class properties'; - $this->size = count( $extendedValue ); - } -} \ No newline at end of file diff --git a/tests/kint/parsers/custom/color.php b/tests/kint/parsers/custom/color.php deleted file mode 100644 index 21d1f391179..00000000000 --- a/tests/kint/parsers/custom/color.php +++ /dev/null @@ -1,400 +0,0 @@ -'#f0f8ff','antiquewhite'=>'#faebd7','aqua'=>'#00ffff','aquamarine'=>'#7fffd4','azure'=>'#f0ffff', - 'beige'=>'#f5f5dc','bisque'=>'#ffe4c4','black'=>'#000000','blanchedalmond'=>'#ffebcd','blue'=>'#0000ff', - 'blueviolet'=>'#8a2be2','brown'=>'#a52a2a','burlywood'=>'#deb887','cadetblue'=>'#5f9ea0','chartreuse'=>'#7fff00', - 'chocolate'=>'#d2691e','coral'=>'#ff7f50','cornflowerblue'=>'#6495ed','cornsilk'=>'#fff8dc','crimson'=>'#dc143c', - 'cyan'=>'#00ffff','darkblue'=>'#00008b','darkcyan'=>'#008b8b','darkgoldenrod'=>'#b8860b','darkgray'=>'#a9a9a9', - 'darkgrey'=>'#a9a9a9','darkgreen'=>'#006400','darkkhaki'=>'#bdb76b','darkmagenta'=>'#8b008b', - 'darkolivegreen'=>'#556b2f','darkorange'=>'#ff8c00','darkorchid'=>'#9932cc','darkred'=>'#8b0000', - 'darksalmon'=>'#e9967a','darkseagreen'=>'#8fbc8f','darkslateblue'=>'#483d8b','darkslategray'=>'#2f4f4f', - 'darkslategrey'=>'#2f4f4f','darkturquoise'=>'#00ced1','darkviolet'=>'#9400d3','deeppink'=>'#ff1493', - 'deepskyblue'=>'#00bfff','dimgray'=>'#696969','dimgrey'=>'#696969','dodgerblue'=>'#1e90ff', - 'firebrick'=>'#b22222','floralwhite'=>'#fffaf0','forestgreen'=>'#228b22','fuchsia'=>'#ff00ff', - 'gainsboro'=>'#dcdcdc','ghostwhite'=>'#f8f8ff','gold'=>'#ffd700','goldenrod'=>'#daa520','gray'=>'#808080', - 'grey'=>'#808080','green'=>'#008000','greenyellow'=>'#adff2f','honeydew'=>'#f0fff0','hotpink'=>'#ff69b4', - 'indianred'=>'#cd5c5c','indigo'=>'#4b0082','ivory'=>'#fffff0','khaki'=>'#f0e68c','lavender'=>'#e6e6fa', - 'lavenderblush'=>'#fff0f5','lawngreen'=>'#7cfc00','lemonchiffon'=>'#fffacd','lightblue'=>'#add8e6', - 'lightcoral'=>'#f08080','lightcyan'=>'#e0ffff','lightgoldenrodyellow'=>'#fafad2','lightgray'=>'#d3d3d3', - 'lightgrey'=>'#d3d3d3','lightgreen'=>'#90ee90','lightpink'=>'#ffb6c1','lightsalmon'=>'#ffa07a', - 'lightseagreen'=>'#20b2aa','lightskyblue'=>'#87cefa','lightslategray'=>'#778899','lightslategrey'=>'#778899', - 'lightsteelblue'=>'#b0c4de','lightyellow'=>'#ffffe0','lime'=>'#00ff00','limegreen'=>'#32cd32','linen'=>'#faf0e6', - 'magenta'=>'#ff00ff','maroon'=>'#800000','mediumaquamarine'=>'#66cdaa','mediumblue'=>'#0000cd', - 'mediumorchid'=>'#ba55d3','mediumpurple'=>'#9370d8','mediumseagreen'=>'#3cb371','mediumslateblue'=>'#7b68ee', - 'mediumspringgreen'=>'#00fa9a','mediumturquoise'=>'#48d1cc','mediumvioletred'=>'#c71585', - 'midnightblue'=>'#191970','mintcream'=>'#f5fffa','mistyrose'=>'#ffe4e1','moccasin'=>'#ffe4b5', - 'navajowhite'=>'#ffdead','navy'=>'#000080','oldlace'=>'#fdf5e6','olive'=>'#808000','olivedrab'=>'#6b8e23', - 'orange'=>'#ffa500','orangered'=>'#ff4500','orchid'=>'#da70d6','palegoldenrod'=>'#eee8aa','palegreen'=>'#98fb98', - 'paleturquoise'=>'#afeeee','palevioletred'=>'#d87093','papayawhip'=>'#ffefd5','peachpuff'=>'#ffdab9', - 'peru'=>'#cd853f','pink'=>'#ffc0cb','plum'=>'#dda0dd','powderblue'=>'#b0e0e6','purple'=>'#800080', - 'red'=>'#ff0000','rosybrown'=>'#bc8f8f','royalblue'=>'#4169e1','saddlebrown'=>'#8b4513','salmon'=>'#fa8072', - 'sandybrown'=>'#f4a460','seagreen'=>'#2e8b57','seashell'=>'#fff5ee','sienna'=>'#a0522d','silver'=>'#c0c0c0', - 'skyblue'=>'#87ceeb','slateblue'=>'#6a5acd','slategray'=>'#708090','slategrey'=>'#708090','snow'=>'#fffafa', - 'springgreen'=>'#00ff7f','steelblue'=>'#4682b4','tan'=>'#d2b48c','teal'=>'#008080','thistle'=>'#d8bfd8', - 'tomato'=>'#ff6347','turquoise'=>'#40e0d0','violet'=>'#ee82ee','wheat'=>'#f5deb3','white'=>'#ffffff', - 'whitesmoke'=>'#f5f5f5','yellow'=>'#ffff00','yellowgreen'=>'#9acd32' - ); - - - protected function _parse( & $variable ) - { - if ( !self::_fits( $variable ) ) return false; - - $this->type = 'CSS color'; - $variants = self::_convert( $variable ); - $this->value = - "
{$variable}
" . - "hex : {$variants['hex']}\n" . - "rgb : {$variants['rgb']}\n" . - ( isset( $variants['name'] ) ? "name: {$variants['name']}\n" : '' ) . - "hsl : {$variants['hsl']}"; - } - - - private static function _fits( $variable ) - { - if ( !is_string( $variable ) ) return false; - - $var = strtolower( trim( $variable ) ); - - return isset( self::$_css3Named[$var] ) - || preg_match( - '/^(?:#[0-9A-Fa-f]{3}|#[0-9A-Fa-f]{6}|(?:rgb|hsl)a?\s*\((?:\s*[0-9.%]+\s*,?){3,4}\))$/', - $var - ); - } - - private static function _convert( $color ) - { - $color = strtolower( $color ); - $decimalColors = array(); - $variants = array( - 'hex' => null, - 'rgb' => null, - 'name' => null, - 'hsl' => null, - ); - - if ( isset( self::$_css3Named[$color] ) ) { - $variants['name'] = $color; - $color = self::$_css3Named[$color]; - } - - if ( $color{0} === '#' ) { - $variants['hex'] = $color; - $color = substr( $color, 1 ); - if ( strlen( $color ) === 6 ) { - $colors = str_split( $color, 2 ); - } else { - $colors = array( - $color{0} . $color{0}, - $color{1} . $color{1}, - $color{2} . $color{2}, - ); - } - - $decimalColors = array_map( 'hexdec', $colors ); - } elseif ( substr( $color, 0, 3 ) === 'rgb' ) { - $variants['rgb'] = $color; - preg_match_all( '#([0-9.%]+)#', $color, $matches ); - $decimalColors = $matches[1]; - foreach ( $decimalColors as &$color ) { - if ( strpos( $color, '%' ) !== false ) { - $color = str_replace( '%', '', $color ) * 2.55; - } - } - - - } elseif ( substr( $color, 0, 3 ) === 'hsl' ) { - $variants['hsl'] = $color; - preg_match_all( '#([0-9.%]+)#', $color, $matches ); - - $colors = $matches[1]; - $colors[0] /= 360; - $colors[1] = str_replace( '%', '', $colors[1] ) / 100; - $colors[2] = str_replace( '%', '', $colors[2] ) / 100; - - $decimalColors = self::_HSLtoRGB( $colors ); - if ( isset( $colors[3] ) ) { - $decimalColors[] = $colors[3]; - } - } - - if ( isset( $decimalColors[3] ) ) { - $alpha = $decimalColors[3]; - unset( $decimalColors[3] ); - } else { - $alpha = null; - } - foreach ( $variants as $type => &$variant ) { - if ( isset( $variant ) ) continue; - - switch ( $type ) { - case 'hex': - $variant = '#'; - foreach ( $decimalColors as &$color ) { - $variant .= str_pad( dechex( $color ), 2, "0", STR_PAD_LEFT ); - } - $variant .= isset( $alpha ) ? ' (alpha omitted)' : ''; - break; - case 'rgb': - $rgb = $decimalColors; - if ( isset( $alpha ) ) { - $rgb[] = $alpha; - $a = 'a'; - } else { - $a = ''; - } - $variant = "rgb{$a}( " . implode( ', ', $rgb ) . " )"; - break; - case 'hsl': - $rgb = self::_RGBtoHSL( $decimalColors ); - if ( $rgb === null ) { - unset( $variants[$type] ); - break; - } - if ( isset( $alpha ) ) { - $rgb[] = $alpha; - $a = 'a'; - } else { - $a = ''; - } - - $variant = "hsl{$a}( " . implode( ', ', $rgb ) . " )"; - break; - case 'name': - // [!] name in initial variants array must go after hex - if ( ( $key = array_search( $variants['hex'], self::$_css3Named, true ) ) !== false ) { - $variant = $key; - } else { - unset( $variants[$type] ); - } - break; - } - - } - - return $variants; - } - - - private static function _HSLtoRGB( array $hsl ) - { - list( $h, $s, $l ) = $hsl; - $m2 = ( $l <= 0.5 ) ? $l * ( $s + 1 ) : $l + $s - $l * $s; - $m1 = $l * 2 - $m2; - return array( - round( self::_hue2rgb( $m1, $m2, $h + 0.33333 ) * 255 ), - round( self::_hue2rgb( $m1, $m2, $h ) * 255 ), - round( self::_hue2rgb( $m1, $m2, $h - 0.33333 ) * 255 ), - ); - } - - - /** - * Helper function for _color_hsl2rgb(). - */ - private static function _hue2rgb( $m1, $m2, $h ) - { - $h = ( $h < 0 ) ? $h + 1 : ( ( $h > 1 ) ? $h - 1 : $h ); - if ( $h * 6 < 1 ) return $m1 + ( $m2 - $m1 ) * $h * 6; - if ( $h * 2 < 1 ) return $m2; - if ( $h * 3 < 2 ) return $m1 + ( $m2 - $m1 ) * ( 0.66666 - $h ) * 6; - return $m1; - } - - - private static function _RGBtoHSL( array $rgb ) - { - list( $clrR, $clrG, $clrB ) = $rgb; - - $clrMin = min( $clrR, $clrG, $clrB ); - $clrMax = max( $clrR, $clrG, $clrB ); - $deltaMax = $clrMax - $clrMin; - - $L = ( $clrMax + $clrMin ) / 510; - - if ( 0 == $deltaMax ) { - $H = 0; - $S = 0; - } else { - if ( 0.5 > $L ) { - $S = $deltaMax / ( $clrMax + $clrMin ); - } else { - $S = $deltaMax / ( 510 - $clrMax - $clrMin ); - } - - if ( $clrMax == $clrR ) { - $H = ( $clrG - $clrB ) / ( 6.0 * $deltaMax ); - } else if ( $clrMax == $clrG ) { - $H = 1 / 3 + ( $clrB - $clrR ) / ( 6.0 * $deltaMax ); - } else { - $H = 2 / 3 + ( $clrR - $clrG ) / ( 6.0 * $deltaMax ); - } - - if ( 0 > $H ) $H += 1; - if ( 1 < $H ) $H -= 1; - } - return array( - round( $H * 360 ), - round( $S * 100 ) . '%', - round( $L * 100 ) . '%' - ); - - } -} - -/* ************* - * TEST DATA - * -dd(array( -'hsl(0, 100%,50%)', -'hsl(30, 100%,50%)', -'hsl(60, 100%,50%)', -'hsl(90, 100%,50%)', -'hsl(120,100%,50%)', -'hsl(150,100%,50%)', -'hsl(180,100%,50%)', -'hsl(210,100%,50%)', -'hsl(240,100%,50%)', -'hsl(270,100%,50%)', -'hsl(300,100%,50%)', -'hsl(330,100%,50%)', -'hsl(360,100%,50%)', -'hsl(120,100%,25%)', -'hsl(120,100%,50%)', -'hsl(120,100%,75%)', -'hsl(120,100%,50%)', -'hsl(120, 67%,50%)', -'hsl(120, 33%,50%)', -'hsl(120, 0%,50%)', -'hsl(120, 60%,70%)', -'#f03', -'#F03', -'#ff0033', -'#FF0033', -'rgb(255,0,51)', -'rgb(255, 0, 51)', -'rgb(100%,0%,20%)', -'rgb(100%, 0%, 20%)', -'hsla(240,100%,50%,0.05)', -'hsla(240,100%,50%, 0.4)', -'hsla(240,100%,50%, 0.7)', -'hsla(240,100%,50%, 1)', -'rgba(255,0,0,0.1)', -'rgba(255,0,0,0.4)', -'rgba(255,0,0,0.7)', -'rgba(255,0,0, 1)', -'black', -'silver', -'gray', -'white', -'maroon', -'red', -'purple', -'fuchsia', -'green', -'lime', -'olive', -'yellow', -'navy', -'blue', -'teal', -'aqua', -'orange', -'aliceblue', -'antiquewhite', -'aquamarine', -'azure', -'beige', -'bisque', -'blanchedalmond', -'blueviolet', -'brown', -'burlywood', -'cadetblue', -'chartreuse', -'chocolate', -'coral', -'cornflowerblue', -'cornsilk', -'crimson', -'darkblue', -'darkcyan', -'darkgoldenrod', -'darkgray', -'darkgreen', -'darkgrey', -'darkkhaki', -'darkmagenta', -'darkolivegreen', -'darkorange', -'darkorchid', -'darkred', -'darksalmon', -'darkseagreen', -'darkslateblue', -'darkslategray', -'darkslategrey', -'darkturquoise', -'darkviolet', -'deeppink', -'deepskyblue', -'dimgray', -'dimgrey', -'dodgerblue', -'firebrick', -'floralwhite', -'forestgreen', -'gainsboro', -'ghostwhite', -'gold', -'goldenrod', -'greenyellow', -'grey', -'honeydew', -'hotpink', -'indianred', -'indigo', -'ivory', -'khaki', -'lavender', -'lavenderblush', -'lawngreen', -'lemonchiffon', -'lightblue', -'lightcoral', -'lightcyan', -'lightgoldenrodyellow', -'lightgray', -'lightgreen', -'lightgrey', -'lightpink', -'lightsalmon', -'lightseagreen', -'lightskyblue', -'lightslategray', -'lightslategrey', -'lightsteelblue', -'lightyellow', -'limegreen', -'linen', -'mediumaquamarine', -'mediumblue', -'mediumorchid', -'mediumpurple', -'mediumseagreen', -'mediumslateblue', -'mediumspringgreen', -'mediumturquoise', -'mediumvioletred', -'midnightblue', -'mintcream', -'mistyrose', -'moccasin', -'navajowhite', -'oldlace', -'olivedrab', -));*/ \ No newline at end of file diff --git a/tests/kint/parsers/custom/json.php b/tests/kint/parsers/custom/json.php deleted file mode 100644 index 03274682c7b..00000000000 --- a/tests/kint/parsers/custom/json.php +++ /dev/null @@ -1,17 +0,0 @@ -value = kintParser::factory( $val )->extendedValue; - $this->type = 'JSON'; - } -} \ No newline at end of file diff --git a/tests/kint/parsers/custom/microtime.php b/tests/kint/parsers/custom/microtime.php deleted file mode 100644 index a51a051b561..00000000000 --- a/tests/kint/parsers/custom/microtime.php +++ /dev/null @@ -1,54 +0,0 @@ -value = @date( 'Y-m-d H:i:s', $sec ) . '.' . substr( $usec, 2, 4 ); - - $numberOfCalls = count( self::$_times ); - if ( $numberOfCalls > 0 ) { # meh, faster than count($times) > 1 - $lap = $time - end( self::$_times ); - self::$_laps[] = $lap; - - $this->value .= "\nSINCE LAST CALL: " . round( $lap, 4 ) . 's.'; - if ( $numberOfCalls > 1 ) { - $this->value .= "\nSINCE START: " . round( $time - self::$_times[0], 4 ) . 's.'; - $this->value .= "\nAVERAGE DURATION: " - . round( array_sum( self::$_laps ) / $numberOfCalls, 4 ) . 's.'; - } - } - - $unit = array( 'B', 'KB', 'MB', 'GB', 'TB' ); - $this->value .= "\nMEMORY USAGE: " . $size . " bytes (" - . round( $size / pow( 1024, ( $i = floor( log( $size, 1024 ) ) ) ), 3 ) . ' ' . $unit[$i] . ")"; - - self::$_times[] = $time; - $this->type = 'Stats'; - } - - /* - function test() { - $x = ''; - d( microtime() ); - for ( $i = 0; $i < 10; $i++ ) { - $x .= str_repeat( 'x', mt_rand( 128 * 1024, 5 * 1024 * 1024 ) ); - usleep( mt_rand( 0, 1000 * 1000 ) ); - d( microtime() ); - } - unset( $x ); - dd( microtime() ); - } - */ -} \ No newline at end of file diff --git a/tests/kint/parsers/custom/splfileinfo.php b/tests/kint/parsers/custom/splfileinfo.php deleted file mode 100644 index 6b14f679ccd..00000000000 --- a/tests/kint/parsers/custom/splfileinfo.php +++ /dev/null @@ -1,12 +0,0 @@ -type = 'object'; - $this->subtype = 'SplFileInfo'; - $this->value = Kint::shortenPath( $variable->getRealPath() ); - } -} \ No newline at end of file diff --git a/tests/kint/parsers/custom/splobjectstorage.php b/tests/kint/parsers/custom/splobjectstorage.php deleted file mode 100644 index c3557713e7f..00000000000 --- a/tests/kint/parsers/custom/splobjectstorage.php +++ /dev/null @@ -1,20 +0,0 @@ -rewind(); - while ( $variable->valid() ) { - $current = $variable->current(); - $this->value[] = kintParser::factory( $current ); - $variable->next(); - } - - $this->type = 'Storage contents'; - $this->size = $variable->count(); - } -} \ No newline at end of file diff --git a/tests/kint/parsers/custom/timestamp.php b/tests/kint/parsers/custom/timestamp.php deleted file mode 100644 index 4c5f4872751..00000000000 --- a/tests/kint/parsers/custom/timestamp.php +++ /dev/null @@ -1,22 +0,0 @@ -type = 'timestamp'; - # avoid dreaded "Timezone must be set" error - $this->value = @date( 'Y-m-d H:i:s', $variable ); - } -} \ No newline at end of file diff --git a/tests/kint/parsers/custom/xml.php b/tests/kint/parsers/custom/xml.php deleted file mode 100644 index 50d0def14ce..00000000000 --- a/tests/kint/parsers/custom/xml.php +++ /dev/null @@ -1,18 +0,0 @@ -value = kintParser::factory( $xml )->extendedValue; - $this->type = 'XML'; - } -} \ No newline at end of file diff --git a/tests/kint/parsers/parser.class.php b/tests/kint/parsers/parser.class.php deleted file mode 100644 index 6dd4ef6a91c..00000000000 --- a/tests/kint/parsers/parser.class.php +++ /dev/null @@ -1,571 +0,0 @@ - self::$_level, - 'objects' => self::$_objects, - ); - - self::$_level++; - - $name = self::_escape( $name ); - $varData = new kintVariableData; - $varData->name = $name; - - # first parse the variable based on its type - $varType = gettype( $variable ); - $varType === 'unknown type' and $varType = 'unknown'; # PHP 5.4 inconsistency - $methodName = '_parse_' . $varType; - - # base type parser returning false means "stop processing further": e.g. recursion - if ( self::$methodName( $variable, $varData ) === false ) { - self::$_level--; - return $varData; - } - - if ( !self::$_skipAlternatives) { - # if an alternative returns something that can be represented in an alternative way, don't :) - self::$_skipAlternatives = true; - - # now check whether the variable can be represented in a different way - foreach ( self::$_customDataTypes as $parserClass ) { - $className = 'Kint_Parsers_' . $parserClass; - - /** @var $object kintParser */ - $object = new $className; - $object->name = $name; # the parser may overwrite the name value, so set it first - - if ( $object->_parse( $variable ) !== false ) { - $varData->alternatives[] = $object; - } - } - - - # combine extended values with alternative representations if applicable - if ( !empty( $varData->alternatives ) && isset( $varData->extendedValue ) ) { - $a = new kintVariableData; - - $a->value = $varData->extendedValue; - $a->type = $varData->type; - $a->size = $varData->size; - - array_unshift( $varData->alternatives, $a ); - $varData->extendedValue = null; - } - - self::$_skipAlternatives = false; - } - - self::$_level = $revert['level']; - self::$_objects = $revert['objects']; - return $varData; - } - - private static function _checkDepth() - { - return Kint::$maxLevels != 0 && self::$_level > Kint::$maxLevels; - } - - private static function _isArrayTabular( $variable ) - { - foreach ( $variable as $row ) { - if ( is_array( $row ) && !empty( $row ) ) { - if ( isset( $keys ) ) { - if ( $keys === array_keys( $row ) ) { // two rows have same keys in a row? Close enough. - return true; - } - } else { - - foreach ( $row as $col ) { - if ( !is_scalar( $col ) && $col !== null ) { - break 2; - } - } - - $keys = array_keys( $row ); - } - } else { - break; - } - } - - return false; - } - - private static $_dealingWithGlobals = false; - - private static function _parse_array( &$variable, kintVariableData $variableData ) - { - isset( self::$_marker ) or self::$_marker = "\x00" . uniqid(); - - # naturally, $GLOBALS variable is an intertwined recursion nightmare, use black magic - $globalsDetector = false; - if ( array_key_exists( 'GLOBALS', $variable ) && is_array( $variable['GLOBALS'] ) ) { - $globalsDetector = "\x01" . uniqid(); - - $variable['GLOBALS'][$globalsDetector] = true; - if ( isset( $variable[$globalsDetector] ) ) { - unset( $variable[$globalsDetector] ); - self::$_dealingWithGlobals = true; - } else { - unset( $variable['GLOBALS'][$globalsDetector] ); - $globalsDetector = false; - } - } - - $variableData->type = 'array'; - $variableData->size = count( $variable ); - - if ( $variableData->size === 0 ) { - return; - } - if ( isset( $variable[self::$_marker] ) ) { # recursion; todo mayhaps show from where - if ( self::$_dealingWithGlobals ) { - $variableData->value = '*RECURSION*'; - } else { - unset( $variable[self::$_marker] ); - $variableData->value = self::$_marker; - } - return false; - } - if ( self::_checkDepth() ) { - $variableData->extendedValue = "*DEPTH TOO GREAT*"; - return false; - } - - $isSequential = self::_isSequential( $variable ); - - $tabular = self::_isArrayTabular( $variable ); - if ( $tabular ) { - - $firstRow = true; - $extendedValue = ''; - $arrayKeys = array(); - - - // assure no values are unreported if an extra key appears in one of the lines - foreach ( $variable as $row ) { - // todo process all keys in _isArrayTabular() - if ( !is_array( $row ) ) { - $tabular = false; - break; - } - $arrayKeys = array_unique( array_merge( $arrayKeys, array_keys( $row ) ) ); - - if ( Kint::$keyFilterCallback ) { - foreach ( $arrayKeys as $k => $key ) { - if ( call_user_func( Kint::$keyFilterCallback, $key ) === false ) { - unset( $arrayKeys[$k] ); - } - } - } - } - } - - - if ( $tabular ) { - $variable[self::$_marker] = true; - foreach ( $variable as $rowIndex => &$row ) { - if ( $rowIndex === self::$_marker ) continue; - - if ( isset( $row[self::$_marker] ) ) { - $variableData->value = "*RECURSION*"; - return false; - } - - - $extendedValue .= ''; - $output = ''; - if ( $firstRow ) { - $extendedValue .= ''; - } - - foreach ( $arrayKeys as $key ) { - if ( $firstRow ) { - $extendedValue .= ''; - } - - if ( !array_key_exists( $key, $row ) ) { - $output .= ''; - continue; - } - - # display strings in their full length so as not to trigger rich decoration - $maxStrLength = kint::$maxStrLength; - kint::$maxStrLength = false; - $var = kintParser::factory( $row[$key] ); - kint::$maxStrLength = $maxStrLength; - - if ( $var->value === self::$_marker ) { - $variableData->value = '*RECURSION*'; - return false; - } elseif ( $var->value === '*RECURSION*' ) { - $output .= ''; - } else { - $output .= ''; - } - unset( $var ); - } - - if ( $firstRow ) { - $extendedValue .= ''; - $firstRow = false; - } - - $extendedValue .= $output . ''; - } - - $variableData->extendedValue = $extendedValue . '
' . ( $isSequential ? '#' . ( $rowIndex + 1 ) : $rowIndex ) . '' . htmlspecialchars( $key ) . '' . Kint_Decorators_Concise::decorate( $var ) . '' . Kint_Decorators_Concise::decorate( $var ) . '
'; - - } else { - $variable[self::$_marker] = true; - $extendedValue = array(); - - foreach ( $variable as $key => & $val ) { - if ( $key === self::$_marker - || ( Kint::$keyFilterCallback && call_user_func( Kint::$keyFilterCallback, $key, $val ) === false ) - ) { - continue; - } - - - $output = kintParser::factory( $val, $isSequential ? null : "'{$key}'" ); - if ( $output->value === self::$_marker ) { - $variableData->value = "*RECURSION*"; // recursion occurred on a higher level, thus $this is recursion - return false; - } - if ( !$isSequential ) { - $output->operator = '=>'; - } - $extendedValue[] = $output; - } - $variableData->extendedValue = $extendedValue; - } - - if ( $globalsDetector ) { - self::$_dealingWithGlobals = false; - } - - unset( $variable[self::$_marker] ); - } - - - private static function _parse_object( &$variable, kintVariableData $variableData ) - { - - // copy the object as an array - $array = (array)$variable; - $hash = spl_object_hash( $variable ); - - - $variableData->type = 'object'; - $variableData->subtype = get_class( $variable ); - $variableData->size = count( $array ); - - if ( isset( self::$_objects[$hash] ) ) { - $variableData->value = '*RECURSION*'; - return false; - } - if ( self::_checkDepth() ) { - $variableData->extendedValue = "*DEPTH TOO GREAT*"; - return false; - } - - self::$_objects[$hash] = true; - - - if ( empty( $array ) ) return; - - - $extendedValue = array(); - foreach ( $array as $key => & $value ) { - if ( Kint::$keyFilterCallback - && call_user_func_array( Kint::$keyFilterCallback, array( $key, $value ) ) === false - ) { - continue; - } - - /* casting object to array: - * integer properties are inaccessible; - * private variables have the class name prepended to the variable name; - * protected variables have a '*' prepended to the variable name. - * These prepended values have null bytes on either side. - * http://www.php.net/manual/en/language.types.array.php#language.types.array.casting - */ - if ( $key[0] === "\x00" ) { - - $access = $key[1] === "*" ? "protected" : "private"; - - // Remove the access level from the variable name - $key = substr( $key, strrpos( $key, "\x00" ) + 1 ); - } else { - $access = "public"; - } - - $key = self::_escape( $key ); - $output = kintParser::factory( $value, $key ); - $output->access = $access; - $output->operator = '->'; - $extendedValue[] = $output; - } - - $variableData->extendedValue = $extendedValue; - } - - - private static function _parse_boolean( &$variable, kintVariableData $variableData ) - { - $variableData->type = 'bool'; - $variableData->value = $variable ? 'TRUE' : 'FALSE'; - } - - private static function _parse_double( &$variable, kintVariableData $variableData ) - { - $variableData->type = 'float'; - $variableData->value = $variable; - } - - private static function _parse_integer( &$variable, kintVariableData $variableData ) - { - $variableData->type = 'integer'; - $variableData->value = $variable; - } - - private static function _parse_null( &$variable, kintVariableData $variableData ) - { - $variableData->type = 'NULL'; - } - - private static function _parse_resource( &$variable, kintVariableData $variableData ) - { - $variableData->type = 'resource'; - $variableData->subtype = get_resource_type( $variable ); - - if ( $variableData->subtype === 'stream' && $meta = stream_get_meta_data( $variable ) ) { - - if ( isset( $meta['uri'] ) ) { - $file = $meta['uri']; - - if ( function_exists( 'stream_is_local' ) ) { - // Only exists on PHP >= 5.2.4 - if ( stream_is_local( $file ) ) { - $file = Kint::shortenPath( $file ); - } - } - - $variableData->value = $file; - } - } - } - - private static function _parse_string( &$variable, kintVariableData $variableData ) - { - $variableData->type = 'string'; - - $encoding = self::_detectEncoding( $variable ); - if ( $encoding !== 'ASCII' ) { - $variableData->subtype = $encoding; - } - - $variableData->size = self::_strlen( $variable, $encoding ); - $strippedString = self::_stripWhitespace( $variable ); - if ( Kint::$maxStrLength && $variableData->size > Kint::$maxStrLength ) { - - // encode and truncate - $variableData->value = '"' - . self::_escape( self::_substr( $strippedString, Kint::$maxStrLength, $encoding ), $encoding ) - . ' …"'; - $variableData->extendedValue = self::_escape( $variable, $encoding ); - - } elseif ( $variable !== $strippedString ) { // omit no data from display - - $variableData->value = '"' . self::_escape( $variable, $encoding ) . '"'; - $variableData->extendedValue = self::_escape( $variable, $encoding ); - } else { - $variableData->value = '"' . self::_escape( $variable, $encoding ) . '"'; - } - } - - private static function _parse_unknown( &$variable, kintVariableData $variableData ) - { - $variableData->type = "UNKNOWN"; - $variableData->subtype = gettype( $variable ); - $variableData->value = var_export( $variable, true ); - } - -} - - -class kintVariableData -{ - /** @var string */ - public $type; - /** @var string */ - public $access; - /** @var string */ - public $name; - /** @var string */ - public $operator; - /** @var string */ - public $subtype; - /** @var int */ - public $size; - /** - * @var kintVariableData[] array of kintVariableData objects or strings; displayed collapsed, each element from - * the array is a separate possible representation of the dumped var - */ - public $extendedValue; - /** @var kintVariableData[] array of alternative representations for same variable */ - public $alternatives; - /** @var string inline value */ - public $value; - - - /* ******************************************* - * HELPERS - */ - - protected static function _escape( $value, $encoding = null ) - { - $encoding or $encoding = self::_detectEncoding( $value ); - - if ( $encoding === 'UTF-8' ) { - # when possible force invisible characters to have some sort of display - $value = preg_replace( '/[\x00-\x08\x0B\x0C\x0E-\x1F\x80-\x9F]/u', '�', $value ); - } - - $value = htmlspecialchars( $value, ENT_QUOTES ); - if ( function_exists( 'mb_encode_numericentity' ) ) { - return mb_encode_numericentity( - $value, - array( 0x80, 0xffff, 0, 0xffff, ), - $encoding - ); - } else { - return $value; - } - } - - protected static function _detectEncoding( $value ) - { - if ( function_exists( 'mb_detect_encoding' ) ) { - $mbDetected = mb_detect_encoding( $value ); - if ( $mbDetected === 'ASCII' ) { - return 'ASCII'; - } - } - - if ( empty( Kint::$charEncodings ) || !function_exists( 'iconv' ) ) { - return !empty( $mbDetected ) ? $mbDetected : 'UTF-8'; - } - - $md5 = md5( $value ); - foreach ( array_merge( array( 'UTF-8' ), Kint::$charEncodings ) as $encoding ) { - # fuck knows why, //IGNORE and //TRANSLIT still throw notice - if ( md5( @iconv( $encoding, $encoding, $value ) ) === $md5 ) { - return $encoding; - } - } - - return 'ASCII'; - } - - /** - * zaps all excess whitespace from string, compacts it but hurts readability - * - * @param string $string - * - * @return string - */ - protected static function _stripWhitespace( $string ) - { - return preg_replace( '[\s+]', ' ', $string ); - } - - - /** - * returns whether the array: - * 1) is numeric and - * 2) in sequence starting from zero - * - * @param array $array - * - * @return bool - */ - protected static function _isSequential( array $array ) - { - return Kint::$hideSequentialKeys - ? array_keys( $array ) === range( 0, count( $array ) - 1 ) - : false; - } - - protected static function _strlen( $string, $encoding = null ) - { - $encoding or $encoding = self::_detectEncoding( $string ); - - return function_exists( 'mb_strlen' ) - ? mb_strlen( $string, $encoding ) - : strlen( $string ); - } - - protected static function _substr( $string, $end, $encoding = null ) - { - $encoding or $encoding = self::_detectEncoding( $string ); - - return function_exists( 'mb_substr' ) - ? mb_substr( $string, 0, $end, $encoding ) - : substr( $string, 0, $end ); - } -} diff --git a/tests/kint/scripts/source.reg b/tests/kint/scripts/source.reg deleted file mode 100644 index 3d80930a378..00000000000 --- a/tests/kint/scripts/source.reg +++ /dev/null @@ -1,12 +0,0 @@ -REGEDIT4 - -[HKEY_CLASSES_ROOT\source] -@="URL:source Protocol" -"URL Protocol"="" - -[HKEY_CLASSES_ROOT\source\shell] - -[HKEY_CLASSES_ROOT\source\shell\open] - -[HKEY_CLASSES_ROOT\source\shell\open\command] -@="wscript.exe \"C:\\Program Files\\bin\\source.vbs\" \"%1\"" \ No newline at end of file diff --git a/tests/kint/scripts/source.vbs b/tests/kint/scripts/source.vbs deleted file mode 100644 index 3345dbe1ad2..00000000000 --- a/tests/kint/scripts/source.vbs +++ /dev/null @@ -1,80 +0,0 @@ -'INSTALLATION: -'set editor link format to 'source::' -'move this file to C:\Program Files\bin\source.vbs and run source.reg -'customize directory mappings and editor command below - -'***************** -'start of settings -'***************** -Dim command, protocol, change_slashes, debug -Set dirmap = CreateObject("Scripting.Dictionary") - -'list of server paths (as regular expressions) -'and matching local paths (as regexp replace strings) -'use this to replace the beginning of the path -'if none of the regular expressions match, the script will show an error - -'local setup, when PHP and editor runs from the same machine -dirmap.Add "^([C-Z]:\\)", "$1" - -'a typical remote Linux setup -'dirmap.Add "^/var/www/", "C:\Projects\" -'dirmap.Add "^/usr/share/php5/", "C:\Projects\debug-source" - -'command to execute; %f is the file name, %l is the line number -'dont forget to quote file names (quotes can be escaped by writing twice) -command = """C:\Program Files\Notepad++\notepad++.exe"" -n%l ""%f""" - -'if true, forward slashes will be changed to backslashes in the filename -'(after the regex replacements) -change_slashes = True - -'protocol name used in the source edit links -protocol = "source" - -'if true, alerts the command before executing it -debug = False - -'*************** -'end of settings -'*************** - -Select Case WScript.Arguments.Count - Case 0 - WScript.Echo "Wrong source link" - WScript.Quit -End Select - -Dim link, split, file, line, found, strArgs - -link = Mid(WScript.Arguments.Item(0), Len(protocol) + 2) -split = InStrRev(link, ":") -file = Left(link, split - 1) -line = Mid(link, split + 1) - -found = False -For Each serverPath In dirmap - Set regexp = New RegExp - regexp.Pattern = serverPath - If regexp.Test(file) Then - found = True - Exit For - End If -Next -If Not found Then - WScript.Echo "don't know where to find " & file & " locally" - WScript.Quit -End If -file = regexp.Replace(file, dirmap.Item(serverPath)) -if change_slashes Then - file = Replace(file, "/", "\") -End If - -strArgs = command -strArgs = Replace(strArgs, "%l", line) -strArgs = Replace(strArgs, "%f", file) -If debug Then - WScript.Echo strArgs -End If -Set oShell = CreateObject ("Wscript.Shell") -oShell.Run strArgs, 0, false \ No newline at end of file diff --git a/tests/kint/view/inc/kint.js b/tests/kint/view/inc/kint.js deleted file mode 100644 index 753740f0d83..00000000000 --- a/tests/kint/view/inc/kint.js +++ /dev/null @@ -1,8 +0,0 @@ -(function(){var e=!1; -if("undefined"===typeof kintInitialized){kintInitialized=1;var f=[],g=-1,h=function(b,a){"undefined"===typeof a&&(a="kint-show");return RegExp("(\\s|^)"+a+"(\\s|$)").test(b.className)},k=function(b,a){"undefined"===typeof a&&(a="kint-show");j(b,a).className+=" "+a},j=function(b,a){"undefined"===typeof a&&(a="kint-show");b.className=b.className.replace(RegExp("(\\s|^)"+a+"(\\s|$)")," ");return b},l=function(b){do b=b.nextElementSibling;while("dd"!==b.nodeName.toLowerCase());return b},m=function(b,a){var c= -l(b);"undefined"===typeof a&&(a=h(b));a?j(b):k(b);1===c.childNodes.length&&(c=c.childNodes[0].childNodes[0],h(c,"kint-parent")&&m(c,a))},n=function(b,a){var c=l(b).getElementsByClassName("kint-parent"),d=c.length;for("undefined"===typeof a&&(a=h(b));d--;)m(c[d],a);m(b,a)},p=function(b){var a=b,c=0;b.parentNode.getElementsByClassName("kint-active-tab")[0].className="";for(b.className="kint-active-tab";a=a.previousSibling;)1===a.nodeType&&c++;b=b.parentNode.nextSibling.childNodes;for(var d=0;dli:not(.kint-active-tab)"),0).forEach(function(b){(0!==b.offsetWidth||0!==b.offsetHeight)&&f.push(b)})},s=function(b){var a=document.querySelector(".kint-focused");a&&j(a,"kint-focused");if(-1!== -b){a=f[b];k(a,"kint-focused");var c=function(a){return a.offsetTop+(a.offsetParent?c(a.offsetParent):0)};window.scrollTo(0,c(a)-window.innerHeight/2)}g=b},t=function(b,a){b?0>--a&&(a=f.length-1):++a>=f.length&&(a=0);s(a);return e};window.addEventListener("click",function(b){var a=b.target,c=a.nodeName.toLowerCase();if(q(a)){if("dfn"===c){var d=a,u=window.getSelection(),v=document.createRange();v.selectNodeContents(d);u.removeAllRanges();u.addRange(v);a=a.parentNode}else"var"===c&&(a=a.parentNode, -c=a.nodeName.toLowerCase());if("li"===c&&"kint-tabs"===a.parentNode.className)return"kint-active-tab"!==a.className&&(p(a),-1!==g&&r()),e;if("nav"===c)return setTimeout(function(){0dl dl{padding:0 0 0 15px;border-left:1px dashed #b6cedb}.kint nav{display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle;content:' ';cursor:pointer;background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAA8CAMAAACO5hB7AAAACVBMVEX///82b4tctzBls0NMAAAAQklEQVR42rWRIQ4AAAgCwf8/2qgER2BeuwJsgAqIzekMfMryPL9XQSkobE6vwKcsz/N7FfPvh09lnPf/b+7673+f0uHuAZ/EdkNQAAAAAElFTkSuQmCC") no-repeat scroll 0 0 transparent}.kint dt.kint-parent:hover nav{background-position:0 -15px}.kint dt.kint-parent.kint-show:hover>nav{background-position:0 -45px}.kint dt.kint-show>nav{background-position:0 -30px}.kint dt.kint-parent+dd{display:none}.kint dt.kint-parent.kint-show+dd{display:block}.kint var{color:#0092db;font-style:normal}.kint dt:hover var{color:#5cb730}.kint dfn{font-style:normal;font-family:monospace;color:#1d1e1e}.kint pre{color:#1d1e1e;margin:0 0 0 15px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #b6cedb;background:#e0eaef;display:block}.kint footer{padding:0 3px 3px;font-size:.7em}.kint a{color:#1d1e1e;text-shadow:none}.kint a:hover{color:#1d1e1e;border-bottom:1px dotted #1d1e1e}.kint ul{list-style:none;padding-left:12px}.kint ul.kint-tabs{margin:0 0 0 12px;padding-left:0;background:#e0eaef;border:1px solid #b6cedb;border-top:0}.kint ul.kint-tabs li{background:#c1d4df;cursor:pointer;display:inline-block;height:23px;line-height:23px;margin:0 4px 4px;padding:0 10px 2px;border:1px solid #b6cedb}.kint ul.kint-tabs li:hover{border:1px solid #0092db}.kint ul.kint-tabs li:hover var{color:#5cb730}.kint ul.kint-tabs li.kint-active-tab{background:#e0eaef;border:1px solid #b6cedb;border-top:0;font-weight:bold;margin-top:-1px;padding-bottom:2px;padding-top:4px;border-right:1px solid #b6cedb}.kint ul.kint-tabs li+li{margin-left:0}.kint dt:hover+dd>ul>li.kint-active-tab{border-color:#0092db}.kint dt:hover+dd>ul>li.kint-active-tab var{color:#5cb730}.kint ul:not(.kint-tabs)>li:not(:first-child){display:none}.kint-report{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-report *{text-align:left;padding:0;margin:0;font-size:9pt;overflow:hidden;font-family:Consolas,"Courier New",monospace;color:#1d1e1e}.kint-report dt{padding:0;border:0;background:0}.kint-report dt.kint-parent{max-width:180px;min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-report dt.kint-parent.kint-show{border-bottom:1px solid #b6cedb}.kint-report td,.kint-report th{border:1px solid #b6cedb;vertical-align:top}.kint-report td{background:#e0eaef;white-space:pre}.kint-report td>dl{border:0;padding:0}.kint-report dl,.kint-report pre,.kint-report label{padding:0}.kint-report pre{border-top:0;border-bottom:0;border-right:0}.kint-report label[for]:before{display:none}.kint-report th:first-child{background:0;border:0}.kint-report td:first-child,.kint-report th{font-weight:bold;background:#c1d4df;color:#1d1e1e}.kint-report td.kint-empty{background:#d33682!important}.kint-report tr:hover>td{box-shadow:0 0 1px 0 #0092db inset}.kint-report tr:hover var{color:#5cb730}.kint-trace .kint-source{line-height:1.08em}.kint-trace .kint-source span{padding-right:1px;border-right:3px inset #0092db}.kint-trace .kint-source .kint-highlight{background:#c1d4df}.kint-trace .kint-parent>b{min-width:18px;display:inline-block;text-align:right;color:#1d1e1e}.kint-trace var{margin-right:5px}.kint-focused{box-shadow:0 0 3px 2px #5cb730}.kint-color-preview{box-shadow:0 0 2px 0 #b6cedb;height:16px;text-align:center;text-shadow:-1px 0 #839496,0 1px #839496,1px 0 #839496,0 -1px #839496;width:230px;color:#fdf6e3}.kint>dl>dt{background:-webkit-linear-gradient(top,#e3ecf0 0,#c0d4df 100%);background:linear-gradient(to bottom,#e3ecf0 0,#c0d4df 100%)}.kint ul.kint-tabs{background:-webkit-linear-gradient(top,#9dbed0 0,#b2ccda 100%);background:linear-gradient(to bottom,#9dbed0 0,#b2ccda 100%)}.kint:not(.kint-trace)>dl>dd>ul.kint-tabs li{background:#e0eaef}.kint:not(.kint-trace)>dl>dd>ul.kint-tabs li.kint-active-tab{background:#c1d4df}.kint.kint-trace>dl>dt{background:-webkit-linear-gradient(top,#c0d4df 0,#e3ecf0 100%);background:linear-gradient(to bottom,#c0d4df 0,#e3ecf0 100%)}.kint .kint-source .kint-highlight{background:#f0eb96} \ No newline at end of file diff --git a/tests/kint/view/inc/solarized-dark.css b/tests/kint/view/inc/solarized-dark.css deleted file mode 100644 index 58c2958bb63..00000000000 --- a/tests/kint/view/inc/solarized-dark.css +++ /dev/null @@ -1 +0,0 @@ -.kint::selection{background:#268bd2;color:#839496}.kint::-moz-selection{background:#268bd2;color:#839496}.kint::-webkit-selection{background:#268bd2;color:#839496}.kint{font-family:Consolas,"Courier New",monospace;color:#839496;padding:0;margin:10px 0;font-size:10pt;line-height:15px;white-space:nowrap;overflow-x:auto;text-align:left}.kint *{float:none!important;padding:0;margin:0}.kint dt{background:#002b36;border:1px solid #586e75;color:#839496;display:block;font-weight:bold;list-style:none outside none;padding:5px}.kint dt:hover{border-color:#268bd2}.kint>dl dl{padding:0 0 0 15px;border-left:1px dashed #586e75}.kint nav{display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle;content:' ';cursor:pointer;background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAA8CAMAAACO5hB7AAAA7VBMVEVYbnWToaH///9YbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnWToaFYbnVYbnWToaGToaFYbnWToaFYbnWToaFYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnWToaEeRtj1AAAATXRSTlMAAACLab0B7iP2R7CL9iPuaUewAb36F0/QnPoX0JxPYQaurepi6QV8FhV7MzFhM6586RYFMa3qYnsVBpNQ+ZGOGJ3PkM9QkZAY+Y6TnV7gnYsAAAEcSURBVHhebdHVbgMxEEBRu8sUZmqapBBoSuGUmWb+/3NayxtrLOe+Hck745XZgd6/eb3CVcKt7HmR+gKxlCGOETG5vFbOoahR6NxI5zHt6nuq+2dqnqfzzH3mfcz70vb8H6MJt5u6a96hS30E4PjEFgAEp2fKNojKUfVEOoS044ex7u3YPE/nmfvM+5j3pe17T9oe/77O41w+n4vnrbrwZxbTshVhvtx5Kb8vliRLRWmeSQSTjJq/El5x5fUXYmNN9hcQC5y4g/hGvVksNtT8451rns2IScb7mn567ll2GNpWr9YWfvQgzWsKs8HOA/m960g6rjTzA8HAV/NHwiOmPLwDKA/J/gggYsRVgFvqbr/fpWYv90zzZKKs9Qfx00Jx65oxLAAAAABJRU5ErkJggg==") no-repeat scroll 0 0 transparent}.kint dt.kint-parent:hover nav{background-position:0 -15px}.kint dt.kint-parent.kint-show:hover>nav{background-position:0 -45px}.kint dt.kint-show>nav{background-position:0 -30px}.kint dt.kint-parent+dd{display:none}.kint dt.kint-parent.kint-show+dd{display:block}.kint var{color:#268bd2;font-style:normal}.kint dt:hover var{color:#2aa198}.kint dfn{font-style:normal;font-family:monospace;color:#93a1a1}.kint pre{color:#839496;margin:0 0 0 15px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #586e75;background:#002b36;display:block}.kint footer{padding:0 3px 3px;font-size:.7em}.kint a{color:#839496;text-shadow:none}.kint a:hover{color:#93a1a1;border-bottom:1px dotted #93a1a1}.kint ul{list-style:none;padding-left:15px}.kint ul.kint-tabs{margin:0 0 0 15px;padding-left:0;background:#002b36;border:1px solid #586e75;border-top:0}.kint ul.kint-tabs li{background:#073642;cursor:pointer;display:inline-block;height:24px;line-height:24px;margin:0 5px 5px;padding:0 12px 3px;border:1px solid #586e75}.kint ul.kint-tabs li:hover{border:1px solid #268bd2}.kint ul.kint-tabs li:hover var{color:#2aa198}.kint ul.kint-tabs li.kint-active-tab{background:#002b36;border:1px solid #586e75;border-top:0;font-weight:bold;margin-top:-1px;padding-bottom:3px;padding-top:4px;border-right:1px solid #586e75}.kint ul.kint-tabs li+li{margin-left:0}.kint dt:hover+dd>ul>li.kint-active-tab{border-color:#268bd2}.kint dt:hover+dd>ul>li.kint-active-tab var{color:#2aa198}.kint ul:not(.kint-tabs)>li:not(:first-child){display:none}.kint-report{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-report *{text-align:left;padding:0;margin:0;font-size:9pt;overflow:hidden;font-family:Consolas,"Courier New",monospace;color:#839496}.kint-report dt{padding:0;border:0;background:0}.kint-report dt.kint-parent{max-width:180px;min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-report dt.kint-parent.kint-show{border-bottom:1px solid #586e75}.kint-report td,.kint-report th{border:1px solid #586e75;vertical-align:top}.kint-report td{background:#002b36;white-space:pre}.kint-report td>dl{border:0;padding:0}.kint-report dl,.kint-report pre,.kint-report label{padding:0}.kint-report pre{border-top:0;border-bottom:0;border-right:0}.kint-report label[for]:before{display:none}.kint-report th:first-child{background:0;border:0}.kint-report td:first-child,.kint-report th{font-weight:bold;background:#073642;color:#93a1a1}.kint-report td.kint-empty{background:#d33682!important}.kint-report tr:hover>td{box-shadow:0 0 1px 0 #268bd2 inset}.kint-report tr:hover var{color:#2aa198}.kint-trace .kint-source{line-height:1.1em}.kint-trace .kint-source span{padding-right:1px;border-right:3px inset #268bd2}.kint-trace .kint-source .kint-highlight{background:#073642}.kint-trace .kint-parent>b{min-width:18px;display:inline-block;text-align:right;color:#93a1a1}.kint-trace var{margin-right:5px}.kint-focused{box-shadow:0 0 3px 2px #859900 inset;border-radius:7px}.kint-color-preview{box-shadow:0 0 2px 0 #b6cedb;height:16px;text-align:center;text-shadow:-1px 0 #839496,0 1px #839496,1px 0 #839496,0 -1px #839496;width:230px;color:#fdf6e3}body{background:#073642;color:#fff}.kint{background:#073642;box-shadow:0 0 5px 3px #073642}.kint>dl>dt,.kint ul.kint-tabs{box-shadow:4px 0 2px -3px #268bd2 inset} \ No newline at end of file diff --git a/tests/kint/view/inc/solarized.css b/tests/kint/view/inc/solarized.css deleted file mode 100644 index 1519cbae5e1..00000000000 --- a/tests/kint/view/inc/solarized.css +++ /dev/null @@ -1 +0,0 @@ -.kint::selection{background:#268bd2;color:#657b83}.kint::-moz-selection{background:#268bd2;color:#657b83}.kint::-webkit-selection{background:#268bd2;color:#657b83}.kint{font-family:Consolas,"Courier New",monospace;color:#657b83;padding:0;margin:10px 0;font-size:10pt;line-height:15px;white-space:nowrap;overflow-x:auto;text-align:left}.kint *{float:none!important;padding:0;margin:0}.kint dt{background:#fdf6e3;border:1px solid #93a1a1;color:#657b83;display:block;font-weight:bold;list-style:none outside none;padding:5px}.kint dt:hover{border-color:#268bd2}.kint>dl dl{padding:0 0 0 15px;border-left:1px dashed #93a1a1}.kint nav{display:inline-block;height:15px;width:15px;margin-right:3px;vertical-align:middle;content:' ';cursor:pointer;background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAA8CAMAAACO5hB7AAAA7VBMVEVYbnWToaH///9YbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnWToaFYbnVYbnWToaGToaFYbnWToaFYbnWToaFYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnWToaEeRtj1AAAATXRSTlMAAACLab0B7iP2R7CL9iPuaUewAb36F0/QnPoX0JxPYQaurepi6QV8FhV7MzFhM6586RYFMa3qYnsVBpNQ+ZGOGJ3PkM9QkZAY+Y6TnV7gnYsAAAEcSURBVHhebdHVbgMxEEBRu8sUZmqapBBoSuGUmWb+/3NayxtrLOe+Hck745XZgd6/eb3CVcKt7HmR+gKxlCGOETG5vFbOoahR6NxI5zHt6nuq+2dqnqfzzH3mfcz70vb8H6MJt5u6a96hS30E4PjEFgAEp2fKNojKUfVEOoS044ex7u3YPE/nmfvM+5j3pe17T9oe/77O41w+n4vnrbrwZxbTshVhvtx5Kb8vliRLRWmeSQSTjJq/El5x5fUXYmNN9hcQC5y4g/hGvVksNtT8451rns2IScb7mn567ll2GNpWr9YWfvQgzWsKs8HOA/m960g6rjTzA8HAV/NHwiOmPLwDKA/J/gggYsRVgFvqbr/fpWYv90zzZKKs9Qfx00Jx65oxLAAAAABJRU5ErkJggg==") no-repeat scroll 0 0 transparent}.kint dt.kint-parent:hover nav{background-position:0 -15px}.kint dt.kint-parent.kint-show:hover>nav{background-position:0 -45px}.kint dt.kint-show>nav{background-position:0 -30px}.kint dt.kint-parent+dd{display:none}.kint dt.kint-parent.kint-show+dd{display:block}.kint var{color:#268bd2;font-style:normal}.kint dt:hover var{color:#2aa198}.kint dfn{font-style:normal;font-family:monospace;color:#586e75}.kint pre{color:#657b83;margin:0 0 0 15px;padding:5px;overflow-y:hidden;border-top:0;border:1px solid #93a1a1;background:#fdf6e3;display:block}.kint footer{padding:0 3px 3px;font-size:.7em}.kint a{color:#657b83;text-shadow:none}.kint a:hover{color:#586e75;border-bottom:1px dotted #586e75}.kint ul{list-style:none;padding-left:15px}.kint ul.kint-tabs{margin:0 0 0 15px;padding-left:0;background:#fdf6e3;border:1px solid #93a1a1;border-top:0}.kint ul.kint-tabs li{background:#eee8d5;cursor:pointer;display:inline-block;height:24px;line-height:24px;margin:0 5px 5px;padding:0 12px 3px;border:1px solid #93a1a1}.kint ul.kint-tabs li:hover{border:1px solid #268bd2}.kint ul.kint-tabs li:hover var{color:#2aa198}.kint ul.kint-tabs li.kint-active-tab{background:#fdf6e3;border:1px solid #93a1a1;border-top:0;font-weight:bold;margin-top:-1px;padding-bottom:3px;padding-top:4px;border-right:1px solid #93a1a1}.kint ul.kint-tabs li+li{margin-left:0}.kint dt:hover+dd>ul>li.kint-active-tab{border-color:#268bd2}.kint dt:hover+dd>ul>li.kint-active-tab var{color:#2aa198}.kint ul:not(.kint-tabs)>li:not(:first-child){display:none}.kint-report{border-collapse:collapse;empty-cells:show;border-spacing:0}.kint-report *{text-align:left;padding:0;margin:0;font-size:9pt;overflow:hidden;font-family:Consolas,"Courier New",monospace;color:#657b83}.kint-report dt{padding:0;border:0;background:0}.kint-report dt.kint-parent{max-width:180px;min-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.kint-report dt.kint-parent.kint-show{border-bottom:1px solid #93a1a1}.kint-report td,.kint-report th{border:1px solid #93a1a1;vertical-align:top}.kint-report td{background:#fdf6e3;white-space:pre}.kint-report td>dl{border:0;padding:0}.kint-report dl,.kint-report pre,.kint-report label{padding:0}.kint-report pre{border-top:0;border-bottom:0;border-right:0}.kint-report label[for]:before{display:none}.kint-report th:first-child{background:0;border:0}.kint-report td:first-child,.kint-report th{font-weight:bold;background:#eee8d5;color:#586e75}.kint-report td.kint-empty{background:#d33682!important}.kint-report tr:hover>td{box-shadow:0 0 1px 0 #268bd2 inset}.kint-report tr:hover var{color:#2aa198}.kint-trace .kint-source{line-height:1.1em}.kint-trace .kint-source span{padding-right:1px;border-right:3px inset #268bd2}.kint-trace .kint-source .kint-highlight{background:#eee8d5}.kint-trace .kint-parent>b{min-width:18px;display:inline-block;text-align:right;color:#586e75}.kint-trace var{margin-right:5px}.kint-focused{box-shadow:0 0 3px 2px #859900 inset;border-radius:7px}.kint-color-preview{box-shadow:0 0 2px 0 #b6cedb;height:16px;text-align:center;text-shadow:-1px 0 #839496,0 1px #839496,1px 0 #839496,0 -1px #839496;width:230px;color:#fdf6e3}.kint>dl>dt,.kint ul.kint-tabs{box-shadow:4px 0 2px -3px #268bd2 inset} \ No newline at end of file diff --git a/tests/kint/view/js/_kint.js b/tests/kint/view/js/_kint.js deleted file mode 100644 index b2720627711..00000000000 --- a/tests/kint/view/js/_kint.js +++ /dev/null @@ -1,344 +0,0 @@ -/** -java -jar compiler.jar --js $FileName$ --js_output_file ../inc/kint.js --compilation_level ADVANCED_OPTIMIZATIONS --output_wrapper "(function(){%output%})()" -*/ - -if ( typeof kintInitialized === 'undefined' ) { - kintInitialized = 1; - var kint = { - visiblePluses : [], // all visible toggle carets - currentPlus : -1, // currently selected caret - - selectText : function( element ) { - var selection = window.getSelection(), - range = document.createRange(); - - range.selectNodeContents(element); - selection.removeAllRanges(); - selection.addRange(range); - }, - - hasClass : function( target, className ) { - if ( typeof className === 'undefined' ) { - className = 'kint-show'; - } - - return new RegExp('(\\s|^)' + className + '(\\s|$)').test(target.className); - }, - - addClass : function( ele, className ) { - if ( typeof className === 'undefined' ) { - className = 'kint-show'; - } - - kint.removeClass(ele, className).className += (" " + className); - }, - - removeClass : function( ele, className ) { - if ( typeof className === 'undefined' ) { - className = 'kint-show'; - } - - ele.className = ele.className.replace( - new RegExp('(\\s|^)' + className + '(\\s|$)'), ' ' - ); - return ele; - }, - - next : function( element ) { - do { - element = element.nextElementSibling; - } while ( element.nodeName.toLowerCase() !== 'dd' ); - - return element; - }, - - toggle : function( element, hide ) { - var parent = kint.next(element); - - if ( typeof hide === 'undefined' ) { - hide = kint.hasClass(element); - } - - if ( hide ) { - kint.removeClass(element); - } else { - kint.addClass(element); - } - - if ( parent.childNodes.length === 1 ) { - parent = parent.childNodes[0].childNodes[0]; // reuse variable cause I can - - if ( kint.hasClass(parent, 'kint-parent') ) { - kint.toggle(parent, hide) - } - } - }, - - toggleChildren : function( element, hide ) { - var parent = kint.next(element) - , nodes = parent.getElementsByClassName('kint-parent') - , i = nodes.length; - - if ( typeof hide === 'undefined' ) { - hide = kint.hasClass(element); - } - - while ( i-- ) { - kint.toggle(nodes[i], hide); - } - kint.toggle(element, hide); - }, - - toggleAll : function( caret ) { - var elements = document.getElementsByClassName('kint-parent'), - i = elements.length, - visible = kint.hasClass(caret.parentNode); - - while ( i-- ) { - kint.toggle(elements[i], visible); - } - }, - - switchTab : function( target ) { - var lis, el = target, index = 0; - - target.parentNode.getElementsByClassName('kint-active-tab')[0].className = ''; - target.className = 'kint-active-tab'; - - // take the index of clicked title tab and make the same n-th content tab visible - while ( el = el.previousSibling ) el.nodeType === 1 && index++; - lis = target.parentNode.nextSibling.childNodes; - for ( var i = 0; i < lis.length; i++ ) { - if ( i === index ) { - lis[i].style.display = 'block'; - - if ( lis[i].childNodes.length === 1 ) { - el = lis[i].childNodes[0].childNodes[0]; - - if ( kint.hasClass(el, 'kint-parent') ) { - kint.toggle(el, false) - } - } - } else { - lis[i].style.display = 'none'; - } - } - }, - - isSibling : function( el ) { - for ( ; ; ) { - el = el.parentNode; - if ( !el || kint.hasClass(el, 'kint') ) { - break; - } - } - - return !!el; - }, - - fetchVisiblePluses : function() { - kint.visiblePluses = []; - Array.prototype.slice.call(document.querySelectorAll('.kint nav, .kint-tabs>li:not(.kint-active-tab)'), 0) - .forEach( - function( el ) { - if ( el.offsetWidth !== 0 || el.offsetHeight !== 0 ) { - kint.visiblePluses.push(el) - } - } - ); - }, - - keyCallBacks : { - cleanup : function( i ) { - var focusedClass = 'kint-focused'; - var prevElement = document.querySelector('.' + focusedClass); - prevElement && kint.removeClass(prevElement, focusedClass); - - if ( i !== -1 ) { - var el = kint.visiblePluses[i]; - kint.addClass(el, focusedClass); - - - var offsetTop = function( el ) { - return el.offsetTop + ( el.offsetParent ? offsetTop(el.offsetParent) : 0 ); - }; - - var top = offsetTop(el) - (window.innerHeight / 2 ); - window.scrollTo(0, top); - } - - kint.currentPlus = i; - }, - - moveCursor : function( up, i ) { - // todo make the first VISIBLE plus active - if ( up ) { - if ( --i < 0 ) { - i = kint.visiblePluses.length - 1; - } - } else { - if ( ++i >= kint.visiblePluses.length ) { - i = 0; - } - } - - kint.keyCallBacks.cleanup(i); - return false; - } - } - }; - - window.addEventListener("click", function( e ) { - var target = e.target - , nodeName = target.nodeName.toLowerCase(); - - if ( !kint.isSibling(target) ) return; - - // auto-select name of variable - if ( nodeName === 'dfn' ) { - kint.selectText(target); - target = target.parentNode; - } else if ( nodeName === 'var' ) { // stupid workaround for misc elements - target = target.parentNode; // to not stop event from further propagating - nodeName = target.nodeName.toLowerCase() - } - - // switch tabs - if ( nodeName === 'li' && target.parentNode.className === 'kint-tabs' ) { - if ( target.className !== 'kint-active-tab' ) { - kint.switchTab(target); - if ( kint.currentPlus !== -1 ) kint.fetchVisiblePluses(); - } - return false; - } - - // handle clicks on the navigation caret - if ( nodeName === 'nav' ) { - // ensure doubleclick has different behaviour, see below - setTimeout(function() { - var timer = parseInt(target.kintTimer, 10); - if ( timer > 0 ) { - target.kintTimer--; - } else { - kint.toggleChildren(target.parentNode); //
- if ( kint.currentPlus !== -1 ) kint.fetchVisiblePluses(); - } - }, 300); - e.stopPropagation(); - return false; - } else if ( kint.hasClass(target, 'kint-parent') ) { - kint.toggle(target); - if ( kint.currentPlus !== -1 ) kint.fetchVisiblePluses(); - return false; - } else if ( kint.hasClass(target, 'kint-ide-link') ) { - e.preventDefault(); - var ajax = new XMLHttpRequest(); // add ajax call to contact editor but prevent link default action - ajax.open('GET', target.href); - ajax.send(null); - return false; - } - }, false); - - window.addEventListener("dblclick", function( e ) { - var target = e.target; - if ( !kint.isSibling(target) ) return; - - - if ( target.nodeName.toLowerCase() === 'nav' ) { - target.kintTimer = 2; - kint.toggleAll(target); - if ( kint.currentPlus !== -1 ) kint.fetchVisiblePluses(); - e.stopPropagation(); - } - }, false); - - // keyboard navigation - window.onkeydown = function( e ) { - - // do nothing if alt key is pressed or if we're actually typing somewhere - if ( e.target !== document.body || e.altKey ) return; - - var keyCode = e.keyCode - , shiftKey = e.shiftKey - , i = kint.currentPlus; - - - if ( keyCode === 68 ) { // 'd' : toggles navigation on/off - if ( i === -1 ) { - kint.fetchVisiblePluses(); - return kint.keyCallBacks.moveCursor(false, i); - } else { - kint.keyCallBacks.cleanup(-1); - return false; - } - } else { - if ( i === -1 ) return; - - if ( keyCode === 9 ) { // TAB : moves up/down depending on shift key - return kint.keyCallBacks.moveCursor(shiftKey, i); - } else if ( keyCode === 38 ) { // ARROW UP : moves up - return kint.keyCallBacks.moveCursor(true, i); - } else if ( keyCode === 40 ) { // ARROW DOWN : down - return kint.keyCallBacks.moveCursor(false, i); - } else { - if ( i === -1 ) { - return; - } - } - } - - - var kintNode = kint.visiblePluses[i]; - if ( kintNode.nodeName.toLowerCase() === 'li' ) { // we're on a trace tab - if ( keyCode === 32 || keyCode === 13 ) { // SPACE/ENTER - kint.switchTab(kintNode); - kint.fetchVisiblePluses(); - return kint.keyCallBacks.moveCursor(true, i); - } else if ( keyCode === 39 ) { // arrows - return kint.keyCallBacks.moveCursor(false, i); - } else if ( keyCode === 37 ) { - return kint.keyCallBacks.moveCursor(true, i); - } - } - - kintNode = kintNode.parentNode; // simple dump - if ( keyCode === 32 || keyCode === 13 ) { // SPACE/ENTER : toggles - kint.toggle(kintNode); - kint.fetchVisiblePluses(); - return false; - } else if ( keyCode === 39 || keyCode === 37 ) { // ARROW LEFT/RIGHT : respectively hides/shows and traverses - var visible = kint.hasClass(kintNode); - var hide = keyCode === 37; - - if ( visible ) { - kint.toggleChildren(kintNode, hide); // expand/collapse all children if immediate ones are showing - } else { - if ( hide ) { // LEFT - // traverse to parent and THEN hide - do {kintNode = kintNode.parentNode} while ( kintNode && kintNode.nodeName.toLowerCase() !== 'dd' ); - - if ( kintNode ) { - kintNode = kintNode.previousElementSibling; - - i = -1; - var parentPlus = kintNode.querySelector('nav'); - while ( parentPlus !== kint.visiblePluses[++i] ) {} - kint.keyCallBacks.cleanup(i) - } else { // we are at root - kintNode = kint.visiblePluses[i].parentNode; - } - } - kint.toggle(kintNode, hide); - } - kint.fetchVisiblePluses(); - return false; - } - }; -} - -// debug purposes only, removed in minified source -function clg( i ) { - if ( !window.console )return; - var l = arguments.length, o = 0; - while ( o < l )console.log(arguments[o++]) -} diff --git a/tests/kint/view/less/_kint.less b/tests/kint/view/less/_kint.less deleted file mode 100644 index 7fed5d03c2c..00000000000 --- a/tests/kint/view/less/_kint.less +++ /dev/null @@ -1,340 +0,0 @@ -@border: 1px solid @border-color; - -.selection() { - background : @border-color-hover; - color : @text-color; -} - -// -// BASE STYLES -// -------------------------------------------------- - -.kint::selection { .selection() } - -.kint::-moz-selection { .selection() } - -.kint::-webkit-selection { .selection() } - -.kint { - font-family : @default-font; - color : @text-color; - padding : 0; - margin : 10px 0; - font-size : 10pt; - line-height : 15px; - white-space : nowrap; - overflow-x : auto; - text-align : left; - - * { - float : none !important; - padding : 0; - margin : 0; - } - - dt { - background : @main-background; - border : @border; - color : @text-color; - display : block; - font-weight : bold; - list-style : none outside none; - padding : @spacing * 1px; - - &:hover { - border-color : @border-color-hover; - } - } - - > dl dl { - padding : 0 0 0 15px; - border-left : 1px dashed @border-color; - } - -// -// DROPDOWN CARET -// -------------------------------------------------- - - nav { - display : inline-block; - height : 15px; - width : 15px; - margin-right : 3px; - vertical-align : middle; - content : ' '; - cursor : pointer; - background : @caret-image no-repeat scroll 0 0 transparent; - } - - dt.kint-parent:hover nav { - background-position : 0 -15px; - } - - dt.kint-parent.kint-show:hover > nav { - background-position : 0 -45px; - } - - dt.kint-show > nav { - background-position : 0 -30px; - } - - dt.kint-parent + dd { - display : none; - } - - dt.kint-parent.kint-show + dd { - display : block; - } - -// -// INDIVIDUAL ITEMS -// -------------------------------------------------- - - var { - color : @variable-type-color; - font-style : normal; - } - - dt:hover var { - color : @variable-type-color-hover; - } - - dfn { - font-style : normal; - font-family : monospace; - color : @variable-name-color; - } - - pre { - color : @text-color; - margin : 0 0 0 15px; - padding : 5px; - overflow-y : hidden; - border-top : 0; - border : @border; - background : @main-background; - display : block; - } - - footer { - padding : 0 3px 3px; - font-size : .7em - } - - a { - color : @text-color; - text-shadow : none; - - &:hover { - color : @variable-name-color; - border-bottom : 1px dotted @variable-name-color; - } - } - -// -// TABS -// -------------------------------------------------- - - ul { - list-style : none; - padding-left : @spacing * 3px; - } - - ul.kint-tabs { - margin : 0 0 0 @spacing * 3px; - padding-left : 0; - background : @main-background; - border : @border; - border-top : 0; - - li { - background : @secondary-background; - cursor : pointer; - display : inline-block; - height : 16px + ceil(8px * (@spacing / 5)); - line-height : 16px + ceil(8px * (@spacing / 5)); - margin : 0 @spacing * 1px @spacing * 1px; - padding : 0 2px + @spacing * 2px floor(3px * (@spacing / 5)); - border : @border; - - &:hover { - border : 1px solid @border-color-hover; - } - - &:hover var { - color : @variable-type-color-hover; - } - - &.kint-active-tab { - background : @main-background; - border : @border; - border-top : 0; - font-weight : bold; - margin-top : -1px; - padding-bottom : floor(3px * (@spacing / 5)); - padding-top : 1px + ceil(3px * (@spacing / 5)); - border-right : @border; - } - } - - li+li { - margin-left : 0 - } - } - - dt:hover + dd > ul > li.kint-active-tab { - border-color : @border-color-hover; - } - - dt:hover + dd > ul > li.kint-active-tab var { - color : @variable-type-color-hover; - } - - ul:not(.kint-tabs)>li:not(:first-child) { - display : none; - } -} - -// -// REPORT -// -------------------------------------------------- - -.kint-report { - border-collapse : collapse; - empty-cells : show; - border-spacing : 0; - - * { - text-align : left; - padding : 0; - margin : 0; - font-size : 9pt; - overflow : hidden; - font-family : @default-font; - color : @text-color; - } - - dt { - padding : 0; - border : 0; - background: none; - } - - dt.kint-parent { - max-width : 180px; - min-width : 100%; - overflow : hidden; - text-overflow : ellipsis; - white-space : nowrap; - } - - dt.kint-parent.kint-show { - border-bottom: @border; - } - - td, - th { - border : @border; - vertical-align : top; - } - - td { - background : @main-background; - white-space : pre; - } - - td > dl { - border : 0; - padding : 0; - } - - dl, - pre, - label { - padding : 0; - } - - pre { - border-top : 0; - border-bottom : 0; - border-right : 0; - } - - label[for]:before { - display : none; - } - - th:first-child { - background : 0; - border : 0; - } - - td:first-child, - th { - font-weight : bold; - background : @secondary-background; - color : @variable-name-color; - } - - td.kint-empty { - background : #d33682 !important; - } - - tr:hover { - > td { - box-shadow : 0px 0px 1px 0px @border-color-hover inset; - } - - var { - color: @variable-type-color-hover; - } - - } -} - -// -// TRACE -// -------------------------------------------------- -.kint-trace { - .kint-source { - line-height : 1em + 0.02 * @spacing - } - - .kint-source span { - padding-right : 1px; - border-right : 3px inset @variable-type-color; - } - - .kint-source .kint-highlight { - background : @secondary-background; - } - - .kint-parent > b { - min-width : 18px; - display : inline-block; - text-align : right; - color : @variable-name-color; - } - - var { - margin-right : 5px; - } -} - -// -// MISC -// -------------------------------------------------- - -// keyboard navigation caret -.kint-focused { - .keyboard-caret -} - -.kint-color-preview { - box-shadow : 0 0 2px 0 #b6cedb; - height : 16px; - text-align : center; - text-shadow : -1px 0 #839496, 0 1px #839496, 1px 0 #839496, 0 -1px #839496; - width : 230px; - color : #fdf6e3; -} \ No newline at end of file diff --git a/tests/kint/view/less/original.less b/tests/kint/view/less/original.less deleted file mode 100644 index 9da7ba91e5e..00000000000 --- a/tests/kint/view/less/original.less +++ /dev/null @@ -1,49 +0,0 @@ -@import "_kint.less"; - -@default-font: Consolas, "Courier New", monospace; -@spacing : 4; - -@main-background: #e0eaef; -@secondary-background : #c1d4df; - -@text-color: #1d1e1e; -@variable-name-color: #1d1e1e; -@variable-type-color: #0092db; -@variable-type-color-hover: #5cb730; - -@border-color: #b6cedb; -@border-color-hover: #0092db; - -@caret-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAA8CAMAAACO5hB7AAAACVBMVEX///82b4tctzBls0NMAAAAQklEQVR42rWRIQ4AAAgCwf8/2qgER2BeuwJsgAqIzekMfMryPL9XQSkobE6vwKcsz/N7FfPvh09lnPf/b+7673+f0uHuAZ/EdkNQAAAAAElFTkSuQmCC"); - -.keyboard-caret() { - box-shadow : 0 0 3px 2px #5cb730; -} - -.kint { - > dl > dt { - background : -webkit-linear-gradient(top, #e3ecf0 0, #c0d4df 100%); - background : linear-gradient(to bottom, #e3ecf0 0, #c0d4df 100%); - } - - ul.kint-tabs { - background : -webkit-linear-gradient(top, #9dbed0 0px, #b2ccda 100%); - background : linear-gradient(to bottom, #9dbed0 0px, #b2ccda 100%); - } - - &:not(.kint-trace) > dl > dd > ul.kint-tabs li { - background : @main-background; - &.kint-active-tab { - background : @secondary-background; - } - } - - &.kint-trace > dl > dt { - background : -webkit-linear-gradient(top, #c0d4df 0px, #e3ecf0 100%); - background : linear-gradient(to bottom, #c0d4df 0px, #e3ecf0 100%); - } - - .kint-source .kint-highlight { - background : #f0eb96; - } -} \ No newline at end of file diff --git a/tests/kint/view/less/solarized-dark.less b/tests/kint/view/less/solarized-dark.less deleted file mode 100644 index 64ec8fd61fb..00000000000 --- a/tests/kint/view/less/solarized-dark.less +++ /dev/null @@ -1,37 +0,0 @@ -@import "_kint"; - -@default-font: Consolas, "Courier New", monospace; -@spacing : 5; - -@main-background: #002b36; // base 03 -@secondary-background : #073642; // base 02 - -@text-color: #839496; // base 0 -@variable-name-color: #93a1a1; // base 1 -@variable-type-color: #268bd2; // blue -@variable-type-color-hover: #2aa198; // cyan - -@border-color: #586e75; // base 01 -@border-color-hover: #268bd2; // blue - -@caret-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAA8CAMAAACO5hB7AAAA7VBMVEVYbnWToaH///9YbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnWToaFYbnVYbnWToaGToaFYbnWToaFYbnWToaFYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnWToaEeRtj1AAAATXRSTlMAAACLab0B7iP2R7CL9iPuaUewAb36F0/QnPoX0JxPYQaurepi6QV8FhV7MzFhM6586RYFMa3qYnsVBpNQ+ZGOGJ3PkM9QkZAY+Y6TnV7gnYsAAAEcSURBVHhebdHVbgMxEEBRu8sUZmqapBBoSuGUmWb+/3NayxtrLOe+Hck745XZgd6/eb3CVcKt7HmR+gKxlCGOETG5vFbOoahR6NxI5zHt6nuq+2dqnqfzzH3mfcz70vb8H6MJt5u6a96hS30E4PjEFgAEp2fKNojKUfVEOoS044ex7u3YPE/nmfvM+5j3pe17T9oe/77O41w+n4vnrbrwZxbTshVhvtx5Kb8vliRLRWmeSQSTjJq/El5x5fUXYmNN9hcQC5y4g/hGvVksNtT8451rns2IScb7mn567ll2GNpWr9YWfvQgzWsKs8HOA/m960g6rjTzA8HAV/NHwiOmPLwDKA/J/gggYsRVgFvqbr/fpWYv90zzZKKs9Qfx00Jx65oxLAAAAABJRU5ErkJggg=="); - -.keyboard-caret() { - box-shadow : 0 0 3px 2px #859900 inset; // green - border-radius : 7px; -} - -body { - background : @secondary-background; - color : #fff; // for non-kint elements to remain at least semi-readable -} - -.kint { - background : @secondary-background; - box-shadow : 0 0 5px 3px @secondary-background; - - > dl > dt, - ul.kint-tabs { - box-shadow : 4px 0 2px -3px @variable-type-color inset; - } -} \ No newline at end of file diff --git a/tests/kint/view/less/solarized.less b/tests/kint/view/less/solarized.less deleted file mode 100644 index 9a761817267..00000000000 --- a/tests/kint/view/less/solarized.less +++ /dev/null @@ -1,27 +0,0 @@ -@import "_kint.less"; - -@default-font: Consolas, "Courier New", monospace; -@spacing : 5; - -@main-background: #fdf6e3; // base 3 -@secondary-background : #eee8d5; // base 2 - -@text-color: #657b83; // base 00 -@variable-name-color: #586e75; // base 01 -@variable-type-color: #268bd2; // blue -@variable-type-color-hover: #2aa198; // cyan - -@border-color: #93a1a1; // base 1 -@border-color-hover: #268bd2; // blue - -@caret-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAA8CAMAAACO5hB7AAAA7VBMVEVYbnWToaH///9YbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnWToaFYbnVYbnWToaGToaFYbnWToaFYbnWToaFYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnVYbnWToaGToaGToaGToaGToaGToaGToaGToaGToaFYbnWToaEeRtj1AAAATXRSTlMAAACLab0B7iP2R7CL9iPuaUewAb36F0/QnPoX0JxPYQaurepi6QV8FhV7MzFhM6586RYFMa3qYnsVBpNQ+ZGOGJ3PkM9QkZAY+Y6TnV7gnYsAAAEcSURBVHhebdHVbgMxEEBRu8sUZmqapBBoSuGUmWb+/3NayxtrLOe+Hck745XZgd6/eb3CVcKt7HmR+gKxlCGOETG5vFbOoahR6NxI5zHt6nuq+2dqnqfzzH3mfcz70vb8H6MJt5u6a96hS30E4PjEFgAEp2fKNojKUfVEOoS044ex7u3YPE/nmfvM+5j3pe17T9oe/77O41w+n4vnrbrwZxbTshVhvtx5Kb8vliRLRWmeSQSTjJq/El5x5fUXYmNN9hcQC5y4g/hGvVksNtT8451rns2IScb7mn567ll2GNpWr9YWfvQgzWsKs8HOA/m960g6rjTzA8HAV/NHwiOmPLwDKA/J/gggYsRVgFvqbr/fpWYv90zzZKKs9Qfx00Jx65oxLAAAAABJRU5ErkJggg=="); - -.keyboard-caret() { - box-shadow : 0 0 3px 2px #859900 inset; // green - border-radius : 7px; -} - -.kint > dl > dt, -.kint ul.kint-tabs { - box-shadow : 4px 0 2px -3px @variable-type-color inset; -} \ No newline at end of file diff --git a/tests/kint/view/trace.phtml b/tests/kint/view/trace.phtml deleted file mode 100644 index 364186269af..00000000000 --- a/tests/kint/view/trace.phtml +++ /dev/null @@ -1,77 +0,0 @@ - Kint::$enabled, - 'displayCalledFrom' => Kint::$displayCalledFrom, -); -Kint::$enabled = true; -Kint::$displayCalledFrom = false; - -echo '
'; - -foreach ( $output as $i => $step ) { - echo '
' - . '' . ( $i + 1 ) . ' ' - . '' - . ''; - - if ( isset( $step['file'] ) ) { - echo Kint::shortenPath( $step['file'], $step['line'] ); - } else { - echo 'PHP internal call'; - } - - echo ''; - - echo $step['function']; - - if ( isset( $step['args'] ) ) { - echo '(' . implode( ', ', array_keys( $step['args'] ) ) . ')'; - } - echo '
'; - $firstTab = ' class="kint-active-tab"'; - echo '
    '; - - if ( !empty( $step['source'] ) ) { - echo "Source"; - $firstTab = ''; - } - - if ( !empty( $step['args'] ) ) { - echo "Arguments"; - $firstTab = ''; - } - - if ( !empty( $step['object'] ) ) { - kintParser::reset(); - $calleDump = kintParser::factory( $step['object'] ); - - echo "Callee object [{$calleDump->subtype}]"; - $firstTab = ''; - } - - - echo '
    '; - - - if ( !empty( $step['source'] ) ) { - echo "
  • {$step['source']}
  • "; - } - - if ( !empty( $step['args'] ) ) { - echo "
  • "; - foreach ( $step['args'] as $k => $arg ) { - kintParser::reset(); - echo Kint_Decorators_Rich::decorate( kintParser::factory( $arg, $k ) ); - } - echo "
  • "; - } - if ( !empty( $step['object'] ) ) { - echo "
  • " . Kint_Decorators_Rich::decorate( $calleDump ) . "
  • "; - } - - echo '
'; -} -echo '
'; -Kint::$enabled = $settings['enabled']; -Kint::$displayCalledFrom = $settings['displayCalledFrom']; -unset( $settings ); diff --git a/tests/mocks/addons/EE_NewAddonMock.class.php b/tests/mocks/addons/EE_NewAddonMock.class.php deleted file mode 100644 index 39725bc491d..00000000000 --- a/tests/mocks/addons/EE_NewAddonMock.class.php +++ /dev/null @@ -1,88 +0,0 @@ - 'EE_NewAddonMock', - 'plugin_slug' => 'eea-new-addon-mock', - 'min_core_version' => '4.0.0', - 'version' => '1.0.0.rc.000', - 'main_file_path' => __FILE__, - 'pue_options' => true - ); - } - - - - /** - * @return array - */ - public static function getCurrentOptions() - { - return self::$options; - } - - - /** - * @return string - */ - public static function getCurrentName() - { - return self::$addon_name; - } -} diff --git a/tests/mocks/addons/eea-new-addon/.gitignore b/tests/mocks/addons/eea-new-addon/.gitignore deleted file mode 100644 index 85e7c1dfcb7..00000000000 --- a/tests/mocks/addons/eea-new-addon/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/.idea/ diff --git a/tests/mocks/addons/eea-new-addon/.travis.yml b/tests/mocks/addons/eea-new-addon/.travis.yml deleted file mode 100644 index fbfaf925020..00000000000 --- a/tests/mocks/addons/eea-new-addon/.travis.yml +++ /dev/null @@ -1,73 +0,0 @@ -language: php -cache: - apt: true -env: - global: - - EE_VERSION=master - matrix: - - WP_VERSION=latest WP_MULTISITE=0 - - WP_VERSION=latest WP_MULTISITE=1 - - WP_VERSION=4.1 WP_MULTISITE=0 - - WP_VERSION=4.1 WP_MULTISITE=1 -php: -- 5.3 -- 5.4 -- 5.5 -- 5.6 -- 7.0 -- 7.1 -matrix: - exclude: - - php: 5.3 - env: WP_VERSION=4.1 WP_MULTISITE=1 - - php: 5.3 - env: WP_VERSION=latest WP_MULTISITE=1 - - php: 5.4 - env: WP_VERSION=4.1 WP_MULTISITE=1 - - php: 5.4 - env: WP_VERSION=latest WP_MULTISITE=1 - - php: 5.5 - env: WP_VERSION=4.1 WP_MULTISITE=1 - - php: 5.5 - env: WP_VERSION=latest WP_MULTISITE=1 - - php: 7.1 - env: WP_VERSION=4.1 WP_MULTISITE=0 - - php: 7.1 - env: WP_VERSION=4.1 WP_MULTISITE=1 - - php: 7.0 - env: WP_VERSION=4.1 WP_MULTISITE=0 - - php: 7.0 - env: WP_VERSION=4.1 WP_MULTISITE=1 - - php: hhvm - env: WP_VERSION=4.1 WP_MULTISITE=0 - - php: hhvm - env: WP_VERSION=4.1 WP_MULTISITE=1 - fast_finish: true -before_install: -- | - if [[ "$SKIP_XDEBUG_REMOVE" != "true" ]]; then - phpenv config-rm xdebug.ini - echo "xdebug removed"; - fi -before_script: -- bash tests/bin/install-wp-tests.sh wordpress_test root '' localhost $WP_VERSION -- . tests/bin/setup-addon-tests.sh -- export PATH="$HOME/.composer/vendor/bin:$PATH" -- | - if [[ ${TRAVIS_PHP_VERSION:0:2} == "7." ]]; then - composer global require "phpunit/phpunit=5.7.*" - else - composer global require "phpunit/phpunit=4.8.*" - fi -- mysql --version -- phpunit --version -- phpenv versions -script: cd tests; phpunit; -notifications: - slack: - rooms: - secure: cVmCG8hUp59UAdx3OBmEweIVqKUr1sYhnWGCdRiylUJtSTP+ehSpfsNLZLfv1ntNlTlA/Iw+8bQbKOeRYCyuWA1FQ7QdZ3Y66jRpyT3AXcT+oKomGogKFY2yLQt2P58uXIyVVt8H9U4xrAM8t8gvARq7asUtbOGnt+1LbbHhUXKXiB6PLkRdGSSL/jFJKLfYyzfD0r43KTYl1e9MhpbO6nzPKGz2vejtA8sdTsfiOj7tQqyf9xydz51PlSic2YWwYoSMH9SjkQX+mPBz7JQHhJiZ9srh0AyVPZDNe03bTUv1D8ICuS7nqQYXpa3RePD12IA4nCvKG/Akn2pxrJtDQPuiYpTyjvuDvgNbg/ET86WBUjvzKKbZYP5QDx7XFf38NdUw9NjfqYR6pJzoX3dPXXwgRHLATBqjlZ4xKHKkUBWxJO8asCkUKDb9/bvjGxL057IqpWmVemmK44uwtPSdw9ml46PakWdbXq3KKtWM6VESFakCsw17O88csywUcPuACHlFUjWTUq9bUsq3ZNryezAfeg4b0Pbwr1JIqt0kOE2yc4YF6TOH+XKIuKS8dLvSqiCHUNstGOSu5DzqsIi5qDUIGn6QHumVc7wFC8o3Db7Fcq1zcFMsWB4t0cm15ZDc1uyBR9QkM8svN8oPYjimEJpYc3nn8kRwmzZm3bemBzk= - on_success: change - on_failure: always - on_start: always - diff --git a/tests/mocks/addons/eea-new-addon/EED_New_Addon.module.php b/tests/mocks/addons/eea-new-addon/EED_New_Addon.module.php deleted file mode 100644 index c074bf38957..00000000000 --- a/tests/mocks/addons/eea-new-addon/EED_New_Addon.module.php +++ /dev/null @@ -1,123 +0,0 @@ - 'ok', 'details' => 'you have made an ajax request!') ); - die; - } - - - - /** - * config - * - * @return EE_New_Addon_Config - */ - public function config(){ - // config settings are setup up individually for EED_Modules via the EE_Configurable class that all modules inherit from, so - // $this->config(); can be used anywhere to retrieve it's config, and: - // $this->_update_config( $EE_Config_Base_object ); can be used to supply an updated instance of it's config object - // to piggy back off of the config setup for the base EE_New_Addon class, just use the following (note: updates would have to occur from within that class) - return EE_Registry::instance()->addons->EE_New_Addon->config(); - } - - - - - - - /** - * run - initial module setup - * - * @access public - * @param WP $WP - * @return void - */ - public function run( $WP ) { - add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' )); - } - - - - - - - /** - * enqueue_scripts - Load the scripts and css - * - * @access public - * @return void - */ - public function enqueue_scripts() { - //Check to see if the new_addon css file exists in the '/uploads/espresso/' directory - if ( is_readable( EVENT_ESPRESSO_UPLOAD_DIR . "css/new_addon.css")) { - //This is the url to the css file if available - wp_register_style( 'espresso_new_addon', EVENT_ESPRESSO_UPLOAD_URL . 'css/espresso_new_addon.css' ); - } else { - // EE new_addon style - wp_register_style( 'espresso_new_addon', EE_NEW_ADDON_URL . 'css/espresso_new_addon.css' ); - } - // new_addon script - wp_register_script( 'espresso_new_addon', EE_NEW_ADDON_URL . 'scripts/espresso_new_addon.js', array( 'jquery' ), EE_NEW_ADDON_VERSION, TRUE ); - - // is the shortcode or widget in play? - if ( EED_New_Addon::$shortcode_active ) { - wp_enqueue_style( 'espresso_new_addon' ); - wp_enqueue_script( 'espresso_new_addon' ); - } - } - } -// End of file EED_New_Addon.module.php -// Location: /wp-content/plugins/eea-new-addon/EED_New_Addon.module.php diff --git a/tests/mocks/addons/eea-new-addon/EES_New_Addon.shortcode.php b/tests/mocks/addons/eea-new-addon/EES_New_Addon.shortcode.php deleted file mode 100644 index 84dd2007bd0..00000000000 --- a/tests/mocks/addons/eea-new-addon/EES_New_Addon.shortcode.php +++ /dev/null @@ -1,89 +0,0 @@ -REQ->set( 'ee', 'new_addon' ); - EED_New_Addon::$shortcode_active = TRUE; - } - - - - /** - * process_shortcode - * - * [ESPRESSO_NEW_ADDON] - * - * @access public - * @param array $attributes - * @return void - */ - public function process_shortcode( $attributes = array() ) { - // make sure $attributes is an array - $attributes = array_merge( - // defaults - array(), - (array)$attributes - ); - return EE_Registry::instance()->modules['new_addon']->display_new_addon( $attributes ); - } - - -} -// End of file EES_New_Addon.shortcode.php -// Location: /wp-content/plugins/eea-new-addon/EES_New_Addon.shortcode.php \ No newline at end of file diff --git a/tests/mocks/addons/eea-new-addon/EEW_New_Addon.widget.php b/tests/mocks/addons/eea-new-addon/EEW_New_Addon.widget.php deleted file mode 100644 index 126513c894b..00000000000 --- a/tests/mocks/addons/eea-new-addon/EEW_New_Addon.widget.php +++ /dev/null @@ -1,146 +0,0 @@ - __( 'Displays Espresso New Addon in a widget.', 'event_espresso' ) - ), - array( - 'width' => 300, - 'height' => 350, - 'id_base' => 'ee-new_addon-widget' - ) - ); - } - - - - /** - * Back-end widget form. - * - * @see WP_Widget::form() - * - * @param array $instance Previously saved values from database. - * @return string|void - */ - public function form( $instance ) { - - EE_Registry::instance()->load_class( 'Question_Option', array(), FALSE, FALSE, TRUE ); - - // Set up some default widget settings. - $defaults = array( - 'title' => 'New Addon' - ); - - $instance = wp_parse_args((array) $instance, $defaults); - - add_filter( 'FHEE__EEH_Form_Fields__label_html', '__return_empty_string' ); - $yes_no_values = array( - EE_Question_Option::new_instance( array( 'QSO_value' => 0, 'QSO_desc' => __('No', 'event_espresso'))), - EE_Question_Option::new_instance( array( 'QSO_value' => 1, 'QSO_desc' => __('Yes', 'event_espresso'))) - ); - - ?> - -

- - -

-

- - get_field_name('yes_or_no_question'), - $this->get_field_id('yes_or_no_question') - ); - ?> -

-post_content )) { - // check the post content for the short code - if ( strpos( $post->post_content, '[ESPRESSO_NEW_ADDON') === FALSE ) { - EED_New_Addon::$shortcode_active = TRUE; - // Before widget (defined by themes). - echo $args['before_widget']; - // Title of widget (before and after defined by themes). - $title = apply_filters( 'widget_title', $instance['title'] ); - if ( ! empty( $title )) { - echo $args['before_title'] . $title . $args['after_title']; - } - // load scripts - EE_New_Addon::instance()->enqueue_scripts(); - // settings - $attributes = array(); - echo EE_New_Addon::instance()->display_new_addon( $attributes ); - // After widget (defined by themes). - echo $args['after_widget']; - } - } - } - - - - - - -} - -// End of file EEW_New_Addon.widget.php -// Location: /wp-content/plugins/eea-new-addon/EEW_New_Addon.widget.php \ No newline at end of file diff --git a/tests/mocks/addons/eea-new-addon/EE_New_Addon.class.php b/tests/mocks/addons/eea-new-addon/EE_New_Addon.class.php deleted file mode 100644 index 1b1985aad51..00000000000 --- a/tests/mocks/addons/eea-new-addon/EE_New_Addon.class.php +++ /dev/null @@ -1,134 +0,0 @@ - EE_NEW_ADDON_VERSION, - 'plugin_slug' => 'espresso_new_addon', - 'min_core_version' => EE_NEW_ADDON_CORE_VERSION_REQUIRED, - 'main_file_path' => EE_NEW_ADDON_PLUGIN_FILE, - 'namespace' => array( - 'FQNS' => 'EventEspresso\NewAddon', - 'DIR' => __DIR__, - ), - 'admin_path' => EE_NEW_ADDON_ADMIN, - 'admin_callback' => '', - 'config_class' => 'EE_New_Addon_Config', - 'config_name' => 'EE_New_Addon', - 'autoloader_paths' => array( - 'EE_New_Addon_Config' => EE_NEW_ADDON_PATH . 'EE_New_Addon_Config.php', - 'New_Addon_Admin_Page' => EE_NEW_ADDON_ADMIN . 'New_Addon_Admin_Page.core.php', - 'New_Addon_Admin_Page_Init' => EE_NEW_ADDON_ADMIN . 'New_Addon_Admin_Page_Init.core.php', - ), - 'dms_paths' => array( EE_NEW_ADDON_PATH . 'core' . DS . 'data_migration_scripts' . DS ), - 'module_paths' => array( EE_NEW_ADDON_PATH . 'EED_New_Addon.module.php' ), - 'shortcode_paths' => array( EE_NEW_ADDON_PATH . 'EES_New_Addon.shortcode.php' ), - 'widget_paths' => array( EE_NEW_ADDON_PATH . 'EEW_New_Addon.widget.php' ), - // if plugin update engine is being used for auto-updates. not needed if PUE is not being used. - 'pue_options' => array( - 'pue_plugin_slug' => 'eea-new-addon', - 'plugin_basename' => EE_NEW_ADDON_BASENAME, - 'checkPeriod' => '24', - 'use_wp_update' => false, - ), - 'capabilities' => array( - 'administrator' => array( - 'edit_thing', - 'edit_things', - 'edit_others_things', - 'edit_private_things', - ), - ), - 'capability_maps' => array( - 'EE_Meta_Capability_Map_Edit' => array( - 'edit_thing', - array( 'New_Addon_Thing', 'edit_things', 'edit_others_things', 'edit_private_things' ), - ), - ), - 'class_paths' => EE_NEW_ADDON_PATH . 'core' . DS . 'db_classes', - 'model_paths' => EE_NEW_ADDON_PATH . 'core' . DS . 'db_models', - 'class_extension_paths' => EE_NEW_ADDON_PATH . 'core' . DS . 'db_class_extensions', - 'model_extension_paths' => EE_NEW_ADDON_PATH . 'core' . DS . 'db_model_extensions', - //note for the mock we're not actually adding any custom cpt stuff yet. - 'custom_post_types' => array(), - 'custom_taxonomies' => array(), - 'default_terms' => array(), - ) - ); - } - - - - /** - * uncomment this method and use it as - * a safe space to add additional logic like setting hooks - * that will run immediately after addon registration - * making this a great place for code that needs to be "omnipresent" - * - * @since 4.9.26 - */ - public function after_registration() - { - // your logic here - } - - - -} -// End of file EE_New_Addon.class.php -// Location: wp-content/plugins/eea-new-addon/EE_New_Addon.class.php diff --git a/tests/mocks/addons/eea-new-addon/EE_New_Addon_Config.php b/tests/mocks/addons/eea-new-addon/EE_New_Addon_Config.php deleted file mode 100644 index 27ce6014ca0..00000000000 --- a/tests/mocks/addons/eea-new-addon/EE_New_Addon_Config.php +++ /dev/null @@ -1,38 +0,0 @@ - - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - {description} - Copyright (C) {year} {fullname} - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - {signature of Ty Coon}, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. \ No newline at end of file diff --git a/tests/mocks/addons/eea-new-addon/README.md b/tests/mocks/addons/eea-new-addon/README.md deleted file mode 100644 index e25fb994982..00000000000 --- a/tests/mocks/addons/eea-new-addon/README.md +++ /dev/null @@ -1,60 +0,0 @@ -New EE4 Add-on Starter Template -========= - -[![Latest Release](https://img.shields.io/github/tag/eventespresso/eea-new-addon.svg?style=flat&label=Latest%20Release)](https://github.com/eventespresso/eea-new-addon/releases) -[![Travis](https://travis-ci.org/eventespresso/eea-new-addon.svg?branch=master)](https://travis-ci.org/eventespresso/eea-new-addon) -[![License](https://img.shields.io/badge/License-GPLv2-blue.svg?style=flat)](https://www.gnu.org/licenses/gpl-2.0.html) -[![Event Espresso Addon](https://img.shields.io/badge/Addon%20For-Event%20Espresso-blue.svg)](https://github.com/eventespresso/event-espresso-core) -[![Minimum EE Core Version:](https://img.shields.io/badge/Minimum%20EE%20core%20ver-4.9.37.p-red.svg)](https://github.com/eventespresso/event-espresso-core/releases/tag/4.9.37.p) - -This add-on adds some extra groovy features to [Event Espresso](https://eventespresso.com). - -> Note, there is **no usage support** provided here. Please read the entire contents of this document before posting any issues. If we encounter issues that give evidence of this document not having been read the issue _will be closed_. - -| **Some Links**| | -|---- | --- | -**Support License** | Support for this add-on is not provided through this repository. For support you can purchase a [Premium Support License](https://eventespresso.com/product/eea-new-addon?ee_ver=ee4&utm_source=github&utm_medium=link&utm_campaign=ee_addon_description_readme&utm_content=premium+support+license). -**Documentation** | [View Documentation →](https://eventespresso.com/wiki/eea-new-addon?utm_source=github&utm_medium=link&utm_campaign=ee_addon_description_readme&utm_content=view+addon+documentation) -**Newsletter** | Be the first to know when we ship new features ... [signup here](https://eventespresso.com/newsletter/). -**Community Chat** | Join a real-time community chat group for professionals that are leading the way in events from event management, event technology and event marketing to work-life balance. [Join the Discussion →](https://eventsmart.com/contact/community-chat/?utm_source=github&utm_medium=link&utm_campaign=ee_addon_description_read_me&utm_content=community+chat) - -## Developers -**This is the full version of the add-on** and provides its full feature set. The repository is provided to assist you with evaluating whether it will solve your use-case. -> We ask if you are using this to provide a solution for clients that you (or your client) [purchase a support license](https://eventespresso.com/product/eea-new-addon?ee_ver=ee4&utm_source=github&utm_medium=link&utm_campaign=ee_addon_description_readme&utm_content=premium+support+license) for this add-on. - -**No Usage Support** is provided in this repository. - -### Add-on Releases and Development -We follow a set pattern for releases and development of all our official add-ons: -1. Active development for new features happens on a **FET-{ticket-number}-{brief-description}** branch. We continually merge master into the feature branch while it's in development. Once it's complete, then testing is done on it and it's merged back to master ready for release. -2. Bug fixes are done on a **BUG-{ticket-number}-{brief-description}** branch. Same methodology is used as with feature branches. -3. Master is technically always production ready and release ready but may not be equal to what the current stable release is for. -4. When we do an official release of an add-on, the current master is tagged and the release is the zip for that tag. - -### Testing -For all testers of this add-on, please take note of the following when reporting issues. -1. There is a difference between a feature and a bug, we consider a bug is something that reveals brokenness in intended functionality. A feature, is something beyond intended functionality. To help determine the difference, think about your issue like this, "I know A does C, however I *wish* it did D." If you find yourself saying that, its a feature. This repository is **not** the place to suggest a new feature UNLESS you've already got a pull request to implement it (see pull requests section below). Info on sponsoring new features can [be found here](https://eventespresso.com/rich-features/sponsor-new-features/). If you aren't sure whether something is a feature or bug feel free to post the issue - however we give priority to bug issues here. -2. UI/UX issues may be considered a bug but not if it requires a major change in design. Feel free to report things you find confusing or needing improvement however reports accompanied by a pull request will likely get faster attention. -3. Report your issue as clearly as possible. By "clear" we mean: - - i. Specify the branch this occurred in. - - ii. Be specific about the steps you took to reproduce. - - iii. Feel free to use screenshots/screencasts to illustrate - - iv. Use URLs for the page the issue to place on where possible. - -1. Don't "bump" bug reports if we don't respond right away. We see every report coming in, but we'll only reply if we need clarification or if we think its invalid. Otherwise, we're likely working on a fix and the issue will be updated when the fix is complete. - -### Pull Requests -One of the reasons we created this private repo on GitHub is because we wanted to open up EE development to 3rd party developers who might want to contribute to the codebase. GitHub makes this really easy to do so via pull requests. If you don't know what pull requests are, please read up on them via the GitHub help/documentation. - -Here's how we deal with pull requests for our repo: - -1. Any new FEATURES in a pull request should be based off of the *master* branch. If your feature pull request is based off any other branch it will not be considered. -2. Any BUGFIX pull requests should be based off of the branch the bug was found. Please verify if it is in master before submitting the pull request. If it is in reproducible on master, then the pull-request should be based off of master. -3. We greatly appreciate any pull-requests submitted for consideration, but please understand we are very selective in what we decide to include in our official add-ons. If the "feature" is something that expands too much on our design decisions for this add-on then we may suggest you develop your pull request into a different add-on for EE. - - -You may find [our post on contributing to open source software](https://eventespresso.com/2017/02/5-tips-for-contributing-to-open-source-software-like-event-espresso/) helpful. \ No newline at end of file diff --git a/tests/mocks/addons/eea-new-addon/admin/new_addon/New_Addon_Admin_Page.core.php b/tests/mocks/addons/eea-new-addon/admin/new_addon/New_Addon_Admin_Page.core.php deleted file mode 100644 index c0b3b611ff2..00000000000 --- a/tests/mocks/addons/eea-new-addon/admin/new_addon/New_Addon_Admin_Page.core.php +++ /dev/null @@ -1,218 +0,0 @@ -page_slug = NEW_ADDON_PG_SLUG; - $this->page_label = NEW_ADDON_LABEL; - $this->_admin_base_url = EE_NEW_ADDON_ADMIN_URL; - $this->_admin_base_path = EE_NEW_ADDON_ADMIN; - } - - - - - protected function _ajax_hooks() {} - - - - - - protected function _define_page_props() { - $this->_admin_page_title = NEW_ADDON_LABEL; - $this->_labels = array( - 'publishbox' => __('Update Settings', 'event_espresso') - ); - } - - - - - protected function _set_page_routes() { - $this->_page_routes = array( - 'default' => '_basic_settings', - 'update_settings' => array( - 'func' => '_update_settings', - 'noheader' => TRUE - ), - 'usage' => '_usage' - ); - } - - - - - - protected function _set_page_config() { - - $this->_page_config = array( - 'default' => array( - 'nav' => array( - 'label' => __('Settings', 'event_espresso'), - 'order' => 10 - ), - 'metaboxes' => array_merge( $this->_default_espresso_metaboxes, array( '_publish_post_box') ), - 'require_nonce' => FALSE - ), - 'usage' => array( - 'nav' => array( - 'label' => __('New Addon Usage', 'event_espresso'), - 'order' => 30 - ), - 'require_nonce' => FALSE - ) - ); - } - - - protected function _add_screen_options() {} - protected function _add_screen_options_default() {} - protected function _add_feature_pointers() {} - - public function load_scripts_styles() { - wp_register_script( 'espresso_new_addon_admin', EE_NEW_ADDON_ADMIN_ASSETS_URL . 'espresso_new_addon_admin.js', array( 'espresso_core' ), EE_NEW_ADDON_VERSION, TRUE ); - wp_enqueue_script( 'espresso_new_addon_admin'); - } - - public function admin_init() { - EE_Registry::$i18n_js_strings[ 'confirm_reset' ] = __( 'Are you sure you want to reset ALL your Event Espresso New Addon Information? This cannot be undone.', 'event_espresso' ); - } - - public function admin_notices() {} - public function admin_footer_scripts() {} - - - - - - - protected function _basic_settings() { - $this->_settings_page( 'new_addon_basic_settings.template.php' ); - } - - - - - /** - * _settings_page - * @param $template - */ - protected function _settings_page( $template ) { - $this->_template_args['new_addon_config'] = EE_Config::instance()->get_config( 'addons', 'EED_New_Addon', 'EE_New_Addon_Config' ); - add_filter( 'FHEE__EEH_Form_Fields__label_html', '__return_empty_string' ); - $this->_template_args['yes_no_values'] = array( - EE_Question_Option::new_instance( array( 'QSO_value' => 0, 'QSO_desc' => __('No', 'event_espresso'))), - EE_Question_Option::new_instance( array( 'QSO_value' => 1, 'QSO_desc' => __('Yes', 'event_espresso'))) - ); - - $this->_template_args['return_action'] = $this->_req_action; - $this->_template_args['reset_url'] = EE_Admin_Page::add_query_args_and_nonce( array('action'=> 'reset_settings','return_action'=>$this->_req_action), EE_NEW_ADDON_ADMIN_URL ); - $this->_set_add_edit_form_tags( 'update_settings' ); - $this->_set_publish_post_box_vars( NULL, FALSE, FALSE, NULL, FALSE); - $this->_template_args['admin_page_content'] = EEH_Template::display_template( EE_NEW_ADDON_ADMIN_TEMPLATE_PATH . $template, $this->_template_args, TRUE ); - $this->display_admin_page_with_sidebar(); - } - - - protected function _usage() { - $this->_template_args['admin_page_content'] = EEH_Template::display_template( EE_NEW_ADDON_ADMIN_TEMPLATE_PATH . 'new_addon_usage_info.template.php', array(), TRUE ); - $this->display_admin_page_with_no_sidebar(); - } - - protected function _update_settings(){ - if(isset($_POST['reset_new_addon']) && $_POST['reset_new_addon'] == '1'){ - $config = new EE_New_Addon_Config(); - $count = 1; - }else{ - $config = EE_Config::instance()->get_config( 'addons', 'EED_New_Addon', 'EE_New_Addon_Config' ); - $count=0; - //otherwise we assume you want to allow full html - foreach($this->_req_data['new_addon'] as $top_level_key => $top_level_value){ - if(is_array($top_level_value)){ - foreach($top_level_value as $second_level_key => $second_level_value){ - if ( EEH_Class_Tools::has_property( $config, $top_level_key ) && EEH_Class_Tools::has_property( $config->{$top_level_key}, $second_level_key ) && $second_level_value != $config->{$top_level_key}->{$second_level_key} ) { - $config->{$top_level_key}->{$second_level_key} = $this->_sanitize_config_input( $top_level_key, $second_level_key, $second_level_value ); - $count++; - } - } - }else{ - if ( EEH_Class_Tools::has_property($config, $top_level_key) && $top_level_value != $config->{$top_level_key}){ - $config->{$top_level_key} = $this->_sanitize_config_input($top_level_key, NULL, $top_level_value); - $count++; - } - } - } - } - EE_Config::instance()->update_config( 'addons', 'EED_New_Addon', $config ); - $this->_redirect_after_action( $count, 'Settings', 'updated', array('action' => $this->_req_data['return_action'])); - } - - /** - * resets the new_addon data and redirects to where they came from - */ -// protected function _reset_settings(){ -// EE_Config::instance()->addons['new_addon'] = new EE_New_Addon_Config(); -// EE_Config::instance()->update_espresso_config(); -// $this->_redirect_after_action(1, 'Settings', 'reset', array('action' => $this->_req_data['return_action'])); -// } - private function _sanitize_config_input( $top_level_key, $second_level_key, $value ){ - $sanitization_methods = array( - 'display'=>array( - 'enable_new_addon'=>'bool', -// 'new_addon_height'=>'int', -// 'enable_new_addon_filters'=>'bool', -// 'enable_category_legend'=>'bool', -// 'use_pickers'=>'bool', -// 'event_background'=>'plaintext', -// 'event_text_color'=>'plaintext', -// 'enable_cat_classes'=>'bool', -// 'disable_categories'=>'bool', -// 'show_attendee_limit'=>'bool', - ) - ); - $sanitization_method = NULL; - if(isset($sanitization_methods[$top_level_key]) && - $second_level_key === NULL && - ! is_array($sanitization_methods[$top_level_key]) ){ - $sanitization_method = $sanitization_methods[$top_level_key]; - }elseif(is_array($sanitization_methods[$top_level_key]) && isset($sanitization_methods[$top_level_key][$second_level_key])){ - $sanitization_method = $sanitization_methods[$top_level_key][$second_level_key]; - } -// echo "$top_level_key [$second_level_key] with value $value will be sanitized as a $sanitization_method
"; - switch($sanitization_method){ - case 'bool': - return (boolean)intval($value); - case 'plaintext': - return wp_strip_all_tags($value); - case 'int': - return intval($value); - case 'html': - return $value; - default: - $input_name = $second_level_key == NULL ? $top_level_key : $top_level_key."[".$second_level_key."]"; - EE_Error::add_error(sprintf(__("Could not sanitize input '%s' because it has no entry in our sanitization methods array", "event_espresso"),$input_name), __FILE__, __FUNCTION__, __LINE__ ); - return NULL; - - } - } - - - - - -} -// End of file New_Addon_Admin_Page.core.php -// Location: /wp-content/plugins/eea-new-addon/admin/new_addon/New_Addon_Admin_Page.core.php \ No newline at end of file diff --git a/tests/mocks/addons/eea-new-addon/admin/new_addon/New_Addon_Admin_Page_Init.core.php b/tests/mocks/addons/eea-new-addon/admin/new_addon/New_Addon_Admin_Page_Init.core.php deleted file mode 100644 index 2aeb1eed0eb..00000000000 --- a/tests/mocks/addons/eea-new-addon/admin/new_addon/New_Addon_Admin_Page_Init.core.php +++ /dev/null @@ -1,72 +0,0 @@ -_folder_path = EE_NEW_ADDON_ADMIN; - - } - - - - - - protected function _set_init_properties() { - $this->label = NEW_ADDON_LABEL; - } - - - - /** - * _set_menu_map - * - * @access protected - * @return void - */ - protected function _set_menu_map() { - $this->_menu_map = new EE_Admin_Page_Sub_Menu( array( - 'menu_group' => 'addons', - 'menu_order' => 25, - 'show_on_menu' => EE_Admin_Page_Menu_Map::BLOG_ADMIN_ONLY, - 'parent_slug' => 'espresso_events', - 'menu_slug' => NEW_ADDON_PG_SLUG, - 'menu_label' => NEW_ADDON_LABEL, - 'capability' => 'administrator', - 'admin_init_page' => $this - )); - } - - - -} -// End of file New_Addon_Admin_Page_Init.core.php -// Location: /wp-content/plugins/eea-new-addon/admin/new_addon/New_Addon_Admin_Page_Init.core.php diff --git a/tests/mocks/addons/eea-new-addon/admin/new_addon/assets/espresso_new_addon_admin.js b/tests/mocks/addons/eea-new-addon/admin/new_addon/assets/espresso_new_addon_admin.js deleted file mode 100644 index 0f35089c8cf..00000000000 --- a/tests/mocks/addons/eea-new-addon/admin/new_addon/assets/espresso_new_addon_admin.js +++ /dev/null @@ -1,4 +0,0 @@ -jQuery(document).ready(function($){ - - -}); diff --git a/tests/mocks/addons/eea-new-addon/admin/new_addon/espresso_events_New_Addon_Hooks.class.php b/tests/mocks/addons/eea-new-addon/admin/new_addon/espresso_events_New_Addon_Hooks.class.php deleted file mode 100644 index 41e118c6fa3..00000000000 --- a/tests/mocks/addons/eea-new-addon/admin/new_addon/espresso_events_New_Addon_Hooks.class.php +++ /dev/null @@ -1,27 +0,0 @@ -_name = 'new_addon'; - } - - public function _redirect_action_early_update_category( $redirection_query_args ) { } - - public function _redirect_action_early_insert_category( $redirection_query_args ) { } - -} -// End of file espresso_events_New_Addon_Hooks.class.php -// Location: /wp-content/plugins/eea-new-addon/admin/new_addon/espresso_events_New_Addon_Hooks.class.php \ No newline at end of file diff --git a/tests/mocks/addons/eea-new-addon/admin/new_addon/new_addon_help.php b/tests/mocks/addons/eea-new-addon/admin/new_addon/new_addon_help.php deleted file mode 100644 index e54f193db50..00000000000 --- a/tests/mocks/addons/eea-new-addon/admin/new_addon/new_addon_help.php +++ /dev/null @@ -1,24 +0,0 @@ -
- -
-
-

- -

-

- -

-

- -

-

- ', '' ); ?> -

-
-
- -
diff --git a/tests/mocks/addons/eea-new-addon/admin/new_addon/templates/new_addon_basic_settings.template.php b/tests/mocks/addons/eea-new-addon/admin/new_addon/templates/new_addon_basic_settings.template.php deleted file mode 100644 index f15dddd7b32..00000000000 --- a/tests/mocks/addons/eea-new-addon/admin/new_addon/templates/new_addon_basic_settings.template.php +++ /dev/null @@ -1,27 +0,0 @@ - -
-

- -

- - - - - - - - - -
-
- - - -
- -
- - - diff --git a/tests/mocks/addons/eea-new-addon/admin/new_addon/templates/new_addon_usage_info.template.php b/tests/mocks/addons/eea-new-addon/admin/new_addon/templates/new_addon_usage_info.template.php deleted file mode 100644 index 0f4765dfea5..00000000000 --- a/tests/mocks/addons/eea-new-addon/admin/new_addon/templates/new_addon_usage_info.template.php +++ /dev/null @@ -1,17 +0,0 @@ -
-
    -
  • - - -
    - -
  • -
  • - - -
    - [ESPRESSO_NEW_ADDON] -
  • -
-
- \ No newline at end of file diff --git a/tests/mocks/addons/eea-new-addon/circle.yml b/tests/mocks/addons/eea-new-addon/circle.yml deleted file mode 100644 index 54dfc03ff63..00000000000 --- a/tests/mocks/addons/eea-new-addon/circle.yml +++ /dev/null @@ -1,33 +0,0 @@ -## Customize the test machine -machine: - - timezone: - America/Denver # Set the timezone - - # Version of php to use - php: - version: 5.4.21 - - # Add some environment variables - environment: - CIRCLE_ENV: test - WP_VERSION: 3.8.1 - WP_MULTISITE: 0 - WP_CORE_DIR: /home/ubuntu/wordpress-develop - WP_TESTS_DIR: /home/ubuntu/wordpress-develop/tests/phpunit - plugin_loc: /home/ubuntu/$CIRCLE_PROJECT_REPONAME - plugin_slug: $CIRCLE_PROJECT_REPONAME - plugin_dir: /home/ubuntu/wordpress-develop/src/wp-content/plugins/$plugin_slug - plugin_tests_dir: /home/ubuntu/wordpress-develop/src/wp-content/plugins/$plugin_slug/tests - event_espresso_core_dir: /home/ubuntu/wordpress-develop/src/wp-content/plugins/event-espresso-core - - -## Customize dependencies -dependencies: - pre: - - . $plugin_loc/tests/bin/setup-addon-tests.sh - -##tests override. -test: - override: - - cd $plugin_tests_dir; phpunit --log-junit $CIRCLE_TEST_REPORTS/phpunit/junit.xml diff --git a/tests/mocks/addons/eea-new-addon/core/data_migration_scripts/EE_DMS_New_Addon_1_0_0.dms.php b/tests/mocks/addons/eea-new-addon/core/data_migration_scripts/EE_DMS_New_Addon_1_0_0.dms.php deleted file mode 100644 index 318867d946c..00000000000 --- a/tests/mocks/addons/eea-new-addon/core/data_migration_scripts/EE_DMS_New_Addon_1_0_0.dms.php +++ /dev/null @@ -1,88 +0,0 @@ -_pretty_name = __("Data Migration to New Addon 0.0.2", "event_espresso"); - $this->_migration_stages = array( - /* - * add children of EE_Data_Migration_Script_Stage or EE_Data_Migration_Script_Stage_Table - * it's easiest to add these classes onto this same file, or use EEH_Autoloader to autoload them - * BEFORE declaring this class' name (because on some requests only THIS file is auto-loaded - * and the class is unserialized from the DB- ie used but NOT constructed) - */ - ); - parent::__construct(); - } - /** - * Indicates whether or not this data migration script should migrate data or not - * @param array $current_database_state_of keys are EE plugin slugs like - * 'Core', 'Calendar', 'Mailchimp',etc, Your addon's slug can be retrieved - * using $this->slug(). Your addon's entry database state is located - * at $current_database_state_of[ $this->slug() ] if it was previously - * intalled; if it wasn't previously installed its NOT in the array - * @return boolean - */ - public function can_migrate_from_version($current_database_state_of) { - /* NOTE: if this is your addon's only DMS and your addon will NOT be migrating data from pre-event-espresso-4, - * then this should just return FALSE. Eg, if there is NO EQUIVALENT EE3 addon, - * then return FALSE. If there was, and this DMS will be migrating data from it, - * then we should return TRUE if we know the old data exists in this system, otherwise FALSE. - */ - if( isset( $current_database_state_of[ $this->slug() ] ) ) { - if( version_compare( '1.0.0.dev.000', $current_database_state_of[ $this->slug() ], '>')) { - //db state is old. this applies - return TRUE; - } else { - //db state is at 1.0.0.dev.000 or higher. this doesnt apply - return FALSE; - - } - } else { - /* apparently this EE4 addon was never installed previously. - * If there was an EE3 equivalent, you could use \EventEspresso\core\services\database\TableAnalysis::tableExists(), - * and EE_Data_Migration_Manager::get_migration_ran() to see if the old - * EE3 tables exist and if the core DMS migrated core data from EE3. - * If so, you probably want to migrate (return TRUE). - * If there was NO EE3 equivalent addon, return FALSE (indicating you don't want - * to migrate. Normal activation processes will take care of calling the most - * up-to-date DMS's schema_changes_before_migration() and schema_changes_after_migration() - * for your addon to setup your database.) - */ - return FALSE; - } - } - - public function schema_changes_after_migration() { - - } - - public function schema_changes_before_migration() { - $this->_table_is_new_in_this_version('esp_new_addon_thing', ' - NEW_ID int(10) unsigned NOT NULL AUTO_INCREMENT, - NEW_name VARCHAR(10) NOT NULL, - NEW_wp_user bigint unsigned NOT NULL, - PRIMARY KEY (NEW_ID)' - ); - $this->_table_is_new_in_this_version('esp_new_addon_attendee_meta', ' - NATT_ID int(10) unsigned NOT NULL AUTO_INCREMENT, - ATT_ID int(10) unsigned NOT NULL, - ATT_foobar int(10) unsigned NOT NULL, - PRIMARY KEY (NATT_ID)' - ); - } -} - -// End of file EE_DMS_New_Addon_0_0_1.dms.php \ No newline at end of file diff --git a/tests/mocks/addons/eea-new-addon/core/db_class_extensions/EEE_New_Addon_Attendee.class_ext.php b/tests/mocks/addons/eea-new-addon/core/db_class_extensions/EEE_New_Addon_Attendee.class_ext.php deleted file mode 100644 index e056fea1fe1..00000000000 --- a/tests/mocks/addons/eea-new-addon/core/db_class_extensions/EEE_New_Addon_Attendee.class_ext.php +++ /dev/null @@ -1,34 +0,0 @@ -_model_name_extended = 'Attendee'; - parent::__construct(); - } - - /** - * Samples function that can be called on any EE_Attendee when this class extension - * is registered - * @param type $txn_id - * @return boolean - */ - function ext_foobar( $txn_id = FALSE ){ - return TRUE; - } -} - -// End of file EEE_Mock_Attendee.php \ No newline at end of file diff --git a/tests/mocks/addons/eea-new-addon/core/db_classes/EE_New_Addon_Thing.class.php b/tests/mocks/addons/eea-new-addon/core/db_classes/EE_New_Addon_Thing.class.php deleted file mode 100644 index cf34404d3c4..00000000000 --- a/tests/mocks/addons/eea-new-addon/core/db_classes/EE_New_Addon_Thing.class.php +++ /dev/null @@ -1,33 +0,0 @@ -_model_name_extended = 'Attendee'; - $this->_extra_tables = array( - 'New_Addon_Attendee_Meta' => new EE_Secondary_Table('esp_new_addon_attendee_meta', 'NATT_ID', 'ATT_ID') - ); - $this->_extra_fields = array('New_Addon_Attendee_Meta'=>array( - 'NATT_ID'=> new EE_DB_Only_Int_Field('NATT_ID', __('New Addon Attendee Meta Row ID','event_espresso'), false), - 'NATT_ID_fk'=>new EE_DB_Only_Int_Field('ATT_ID', __("Foreign Key to Attendee in Post Table", "event_espresso"), false), - 'ATT_foobar'=>new EE_Foreign_Key_Int_Field('ATT_foobar', __("Foobar", 'event_espresso'), true,0,'New_Addon_Thing'))); - $this->_extra_relations = array('New_Addon_Thing'=>new EE_Belongs_To_Relation()); - parent::__construct(); - } - function ext_get_all_new_things( $arg1 = FALSE ){ - return $this->_->get_all(array(array('New_Addon_Thing.NEW_ID'=>$arg1))); - } -} - -// End of file EEME_Mock_Attendee.model_ext.php \ No newline at end of file diff --git a/tests/mocks/addons/eea-new-addon/core/db_models/EEM_New_Addon_Thing.model.php b/tests/mocks/addons/eea-new-addon/core/db_models/EEM_New_Addon_Thing.model.php deleted file mode 100644 index 7fcc7a6be4e..00000000000 --- a/tests/mocks/addons/eea-new-addon/core/db_models/EEM_New_Addon_Thing.model.php +++ /dev/null @@ -1,38 +0,0 @@ -_tables = array( - 'New_Addon_Thing'=>new EE_Primary_Table('esp_new_addon_thing', 'NEW_ID') - ); - $this->_fields = array( - 'New_Addon_Thing'=>array( - 'NEW_ID'=>new EE_Primary_Key_Int_Field('NEW_ID', __("New Addon Thing ID", 'event_espresso')), - 'NEW_name' => new EE_Plain_Text_Field('NEW_name', __('Name', 'event_espresso'), false), - 'NEW_wp_user' => new EE_WP_User_Field( 'NEW_wp_user', __( 'Things Creator', 'event_espresso' ), false ) - ) - ); - $this->_model_relations = array( - 'Attendee' => new EE_Has_Many_Relation(), - 'WP_User' => new EE_Belongs_To_Relation() - ); - parent::__construct($timezone); - } -} - -// End of file EEM_New_Addon_Thing.model.php diff --git a/tests/mocks/addons/eea-new-addon/css/espresso_new_addon.css b/tests/mocks/addons/eea-new-addon/css/espresso_new_addon.css deleted file mode 100644 index d11b1f58151..00000000000 --- a/tests/mocks/addons/eea-new-addon/css/espresso_new_addon.css +++ /dev/null @@ -1,25 +0,0 @@ -/* ------------------------------------------------------------------------- - * Event Espresso New_Addon Stylesheet - * (c) 2014 Event Espresso - * -------------------------------------------------------------------------*/ - -/* -General Styles ----------------------------------------------------------------------------------------------------- */ - - -/* Media Query for screens smaller then 768px (iPad portrait) ----------------------------------------------------------------------------------------------------- */ - -@media only screen and (max-width: 767px) { -} - -@media only screen and (max-width: 600px) and (min-width: 481px) { -} - -@media only screen and (max-width: 540px) and (min-width: 480px) { -} - -@media only screen and (max-width: 480px) { -} - diff --git a/tests/mocks/addons/eea-new-addon/eea-new-addon.php b/tests/mocks/addons/eea-new-addon/eea-new-addon.php deleted file mode 100644 index 6a9fe56ff28..00000000000 --- a/tests/mocks/addons/eea-new-addon/eea-new-addon.php +++ /dev/null @@ -1,109 +0,0 @@ - -
-

-
- [db-host] [wp-version]" - exit 1 -fi - -DB_NAME=$1 -DB_USER=$2 -DB_PASS=$3 -DB_HOST=${4-localhost} -WP_VERSION=${5-latest} - -WP_TESTS_DIR=${WP_TESTS_DIR-/tmp/wordpress-tests-lib} -WP_CORE_DIR=${WP_CORE_DIR-/tmp/wordpress/} - -download() { - if [ `which curl` ]; then - curl -s "$1" > "$2"; - elif [ `which wget` ]; then - wget -nv -O "$2" "$1" - fi -} - -if [[ $WP_VERSION =~ [0-9]+\.[0-9]+(\.[0-9]+)? ]]; then - WP_TESTS_TAG="tags/$WP_VERSION" -else - # http serves a single offer, whereas https serves multiple. we only want one - download http://api.wordpress.org/core/version-check/1.7/ /tmp/wp-latest.json - grep '[0-9]+\.[0-9]+(\.[0-9]+)?' /tmp/wp-latest.json - LATEST_VERSION=$(grep -o '"version":"[^"]*' /tmp/wp-latest.json | sed 's/"version":"//') - if [[ -z "$LATEST_VERSION" ]]; then - echo "Latest WordPress version could not be found" - exit 1 - fi - WP_TESTS_TAG="tags/$LATEST_VERSION" -fi - -set -ex - -install_wp() { - - if [ -d $WP_CORE_DIR ]; then - return; - fi - - mkdir -p $WP_CORE_DIR - - if [ $WP_VERSION == 'latest' ]; then - local ARCHIVE_NAME='latest' - else - local ARCHIVE_NAME="wordpress-$WP_VERSION" - fi - - download https://wordpress.org/${ARCHIVE_NAME}.tar.gz /tmp/wordpress.tar.gz - tar --strip-components=1 -zxmf /tmp/wordpress.tar.gz -C $WP_CORE_DIR - - download https://raw.github.com/markoheijnen/wp-mysqli/master/db.php $WP_CORE_DIR/wp-content/db.php -} - -install_test_suite() { - # portable in-place argument for both GNU sed and Mac OSX sed - if [[ $(uname -s) == 'Darwin' ]]; then - local ioption='-i .bak' - else - local ioption='-i' - fi - - # set up testing suite if it doesn't yet exist - if [ ! -d $WP_TESTS_DIR ]; then - # set up testing suite - mkdir -p $WP_TESTS_DIR - svn co --quiet https://develop.svn.wordpress.org/${WP_TESTS_TAG}/tests/phpunit/includes/ $WP_TESTS_DIR/includes - fi - - cd $WP_TESTS_DIR - - if [ ! -f wp-tests-config.php ]; then - download https://develop.svn.wordpress.org/${WP_TESTS_TAG}/wp-tests-config-sample.php "$WP_TESTS_DIR"/wp-tests-config.php - sed $ioption "s:dirname( __FILE__ ) . '/src/':'$WP_CORE_DIR':" "$WP_TESTS_DIR"/wp-tests-config.php - sed $ioption "s/youremptytestdbnamehere/$DB_NAME/" "$WP_TESTS_DIR"/wp-tests-config.php - sed $ioption "s/yourusernamehere/$DB_USER/" "$WP_TESTS_DIR"/wp-tests-config.php - sed $ioption "s/yourpasswordhere/$DB_PASS/" "$WP_TESTS_DIR"/wp-tests-config.php - sed $ioption "s|localhost|${DB_HOST}|" "$WP_TESTS_DIR"/wp-tests-config.php - fi - -} - -install_db() { - # parse DB_HOST for port or socket references - local PARTS=(${DB_HOST//\:/ }) - local DB_HOSTNAME=${PARTS[0]}; - local DB_SOCK_OR_PORT=${PARTS[1]}; - local EXTRA="" - - if ! [ -z $DB_HOSTNAME ] ; then - if [ $(echo $DB_SOCK_OR_PORT | grep -e '^[0-9]\{1,\}$') ]; then - EXTRA=" --host=$DB_HOSTNAME --port=$DB_SOCK_OR_PORT --protocol=tcp" - elif ! [ -z $DB_SOCK_OR_PORT ] ; then - EXTRA=" --socket=$DB_SOCK_OR_PORT" - elif ! [ -z $DB_HOSTNAME ] ; then - EXTRA=" --host=$DB_HOSTNAME --protocol=tcp" - fi - fi - - # create database - mysqladmin create $DB_NAME --user="$DB_USER" --password="$DB_PASS"$EXTRA -} - -install_wp -install_test_suite -install_db diff --git a/tests/mocks/addons/eea-new-addon/tests/bin/setup-addon-tests.sh b/tests/mocks/addons/eea-new-addon/tests/bin/setup-addon-tests.sh deleted file mode 100644 index 308fc98f410..00000000000 --- a/tests/mocks/addons/eea-new-addon/tests/bin/setup-addon-tests.sh +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env bash - -## if there is a BUILD_BRANCH build environment variable then we use that for what branch of -## ee core to checkout, otherwise master. -if [ -n "$RELEASE_BUILD" ]; then - CORE_TAG=$RELEASE_BUILD -else - CORE_TAG="master" -fi - -# EE_VERSION is used in travis and should override what may be set for CORE_TAG -if [ -n "$EE_VERSION" ]; then - CORE_TAG=$EE_VERSION -fi - -# EE_BRANCH overrides EE_VERSION and RELEASE_BUILD -if [ -n "$EE_BRANCH" ]; then - CORE_TAG=$EE_BRANCH -fi - -#Make sure directory vars are set -if [ -z "$plugin_loc" ]; then - EE_TESTS_DIR="/tmp/event-espresso-core/tests" -fi - -if [ -z "$event_espresso_core_dir" ]; then - event_espresso_core_dir="/tmp/event-espresso-core" -fi - -# commands taking care of WordPress setup -function wpCoreSetup { - ## only run this is in circle env. - if [ -z "$CIRCLE_ENV" ]; then - return - fi - git clone git://develop.git.wordpress.org/ $WP_CORE_DIR - cd $WP_CORE_DIR - cp wp-tests-config-sample.php wp-tests-config.php - sed -i "s/youremptytestdbnamehere/wordpress_test/" wp-tests-config.php - sed -i "s/yourusernamehere/root/" wp-tests-config.php - sed -i "s/yourpasswordhere//" wp-tests-config.php -} - -# commands taking care of ee core setup -# receives an argument indicating what branch to checkout. -function eeCoreSetup { - local BRANCH=$1 - git clone https://github.com/eventespresso/event-espresso-core.git $event_espresso_core_dir - cd $event_espresso_core_dir/tests - if [ "$BRANCH" = "master" ] || [ -n "$EE_BRANCH" ]; then - git checkout $BRANCH - else - git fetch --tags - git checkout tags/$BRANCH -b $BRANCH - fi - #back to previous directory - cd - - echo "Building against EE core" $BRANCH -} - -# commands taking care of addon setup -function addOnSetup { - ## only run this is in circle env. - if [ -z "$CIRCLE_ENV" ]; then - return - fi - mv $plugin_loc $plugin_dir -} - -# commands taking care of creating the WordPress test db. -function createDB { - ## only run this is in circle env. - if [ -z "$CIRCLE_ENV" ]; then - return - fi - mysql -e 'CREATE DATABASE wordpress_test;' -uroot; -} - -# commands taking care of setting up phpunit -function setupPhpUnit { - ## no need to setup if not on circle - if [ -z "$CIRCLE_ENV" ]; then - return - fi - wget --no-check-certificate https://phar.phpunit.de/phpunit-old.phar - chmod +x phpunit-old.phar - mv phpunit-old.phar /home/ubuntu/.phpenv/shims/phpunit -} - -wpCoreSetup -eeCoreSetup $CORE_TAG -addOnSetup -createDB -setupPhpUnit \ No newline at end of file diff --git a/tests/mocks/addons/eea-new-addon/tests/bootstrap.php b/tests/mocks/addons/eea-new-addon/tests/bootstrap.php deleted file mode 100644 index b4da9f49679..00000000000 --- a/tests/mocks/addons/eea-new-addon/tests/bootstrap.php +++ /dev/null @@ -1,23 +0,0 @@ -init(); diff --git a/tests/mocks/addons/eea-new-addon/tests/phpunit.xml b/tests/mocks/addons/eea-new-addon/tests/phpunit.xml deleted file mode 100644 index 33ee6e9b133..00000000000 --- a/tests/mocks/addons/eea-new-addon/tests/phpunit.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - ./testcases/ - - - diff --git a/tests/mocks/addons/eea-new-addon/tests/testcases/espresso_addon_skeleton.php b/tests/mocks/addons/eea-new-addon/tests/testcases/espresso_addon_skeleton.php deleted file mode 100644 index 06a6d1c20c8..00000000000 --- a/tests/mocks/addons/eea-new-addon/tests/testcases/espresso_addon_skeleton.php +++ /dev/null @@ -1,29 +0,0 @@ -assertEquals( has_action('AHEE__EE_System__load_espresso_addons', 'load_espresso_new_addon'), 10 ); - $this->assertTrue( class_exists( 'EE_New_Addon' ) ); - } -} diff --git a/tests/mocks/addons/new-messages-template-pack-variation/lang/.makesurefoldercommits b/tests/mocks/addons/new-messages-template-pack-variation/lang/.makesurefoldercommits deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/mocks/addons/new-messages-template-pack-variation/new-messages-template-pack-variation.php b/tests/mocks/addons/new-messages-template-pack-variation/new-messages-template-pack-variation.php deleted file mode 100644 index bb3a82a9f6f..00000000000 --- a/tests/mocks/addons/new-messages-template-pack-variation/new-messages-template-pack-variation.php +++ /dev/null @@ -1,78 +0,0 @@ - __('Blue Lagoon', 'ee-new-variations-test' ), - 'new_variation_test_sunset_red' => __('Sunset Red', 'ee-new-variations-test' ) - ); - } - - $variations_setup = array( - 'base_path' => EE_NEW_VARIATIONS_PATH, - 'base_url' => EE_NEW_VARIATIONS_URL, - 'variations' => array( - 'default' => array( - 'email' => $vtions - ) - ) - ); - EE_Register_Messages_Template_Variations::register( 'ee_new_variations_test', $variations_setup ); -} -add_action( 'EE_Brewing_Regular___messages_caf', 'ee_new_variations_test_register_new_variation' ); diff --git a/tests/mocks/addons/new-messages-template-pack-variation/variations/email_main_new_variation_test_blue_lagoon.css b/tests/mocks/addons/new-messages-template-pack-variation/variations/email_main_new_variation_test_blue_lagoon.css deleted file mode 100644 index bcb159f88ac..00000000000 --- a/tests/mocks/addons/new-messages-template-pack-variation/variations/email_main_new_variation_test_blue_lagoon.css +++ /dev/null @@ -1,241 +0,0 @@ -/* ------------------------------------- - Attention! This CSS file is used for generating the final messages that are sent to the attendees and admins. -------------------------------------- */ -/* ------------------------------------- - GLOBAL -------------------------------------- */ -* { - margin:0; - padding:0; -} -* { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; } - -img { - max-width: 100%; -} -.collapse { - margin:0; - padding:0; -} -body { - -webkit-font-smoothing:antialiased; - -webkit-text-size-adjust:none; - width: 100%!important; - height: 100%; -} - - -/* ------------------------------------- - ELEMENTS -------------------------------------- */ -a { color: #2b66cb;} - -.btn { - text-decoration:none; - color: #FFF; - background-color: #666; - padding:10px 16px; - font-weight:bold; - margin-right:10px; - text-align:center; - cursor:pointer; - display: inline-block; -} - -p.callout { - padding:15px; - background-color:#7bcaf9; - margin-bottom: 15px; -} -.callout a { - font-weight:bold; - color: #2b66cb; -} - -table.social { -/* padding:15px; */ - background-color: #ebebeb; - -} -.social .soc-btn { - padding: 3px 7px; - font-size:12px; - margin-bottom:10px; - text-decoration:none; - color: #FFF;font-weight:bold; - display:block; - text-align:center; -} -a.fb { background-color: #3B5998!important; } -a.tw { background-color: #1daced!important; } -a.gp { background-color: #DB4A39!important; } -a.ms { background-color: #000!important; } - -.sidebar .soc-btn { - display:block; - width:100%; -} - -/* ------------------------------------- - HEADER -------------------------------------- */ -table.head-wrap { width: 100%;} - -.header.container table td.logo { padding: 15px; } -.header.container table td.label { padding: 15px; padding-left:0px;} - - -/* ------------------------------------- - BODY -------------------------------------- */ -table.body-wrap { width: 100%;} - - -/* ------------------------------------- - FOOTER -------------------------------------- */ -table.footer-wrap { width: 100%; clear:both!important; -} -.footer-wrap .container td.content p { border-top: 1px solid rgb(215,215,215); padding-top:15px;} -.footer-wrap .container td.content p { - font-size:10px; - font-weight: bold; - -} - - -/* ------------------------------------- - TYPOGRAPHY -------------------------------------- */ -h1,h2,h3,h4,h5,h6 { -font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; padding-bottom:15px; padding-top:10px; color:#000; -} -h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { font-size: 60%; color: #6f6f6f; line-height: 0; text-transform: none; } - -h1 { font-weight:200; font-size: 36px;} -h2 { font-weight:200; font-size: 30px;} -h3 { font-weight:500; font-size: 24px;} -h4 { font-weight:500; font-size: 19px;} -h5 { font-weight:900; font-size: 16px;} -h6 { font-weight:900; font-size: 14px; text-transform: uppercase; color:#444;} - -h4.attendee-name { - margin: 10px 0; -} -.collapse { margin:0!important;} - -p, ul { - margin-bottom: 10px; - font-weight: normal; - font-size:14px; - line-height:1.6; -} -p.lead { font-size:17px; } -p.last { margin-bottom:0px;} - -ul li { - margin-left:5px; - padding-bottom: 5px; - list-style-position: inside; - list-style-type: none; -} - -ul.question-list li, ol.datetime-list li { - margin-left:10px; - padding-bottom: 5px; - list-style-position: inside; - list-style-type: none; -} -li.ticket-name em, li.question-item em {padding-left: 15px;} -hr { - margin: 10px 0; -} - -/* ------------------------------------- - SIDEBAR -------------------------------------- */ -ul.sidebar { - background:#ebebeb; - display:block; - list-style-type: none; -} -#ee-message-preview-container ul.sidebar li { display: block; margin:0; padding:10px 16px;} -#ee-message-preview-container ul.sidebar li h5 { - text-decoration:none; - color: #000; - padding:10px 0 20px 0; - display:block; - margin:0; -} -ul.sidebar li a.last { border-bottom-width:0px;} -ul.sidebar li a h1,ul.sidebar li a h2,ul.sidebar li a h3,ul.sidebar li a h4,ul.sidebar li a h5,ul.sidebar li a h6,ul.sidebar li a p { margin-bottom:0!important;} - - - -/* --------------------------------------------------- - RESPONSIVENESS - Nuke it from orbit. It's the only way to be sure. ------------------------------------------------------- */ - -/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */ -.container { - display:block!important; - max-width:600px!important; - margin:0 auto!important; /* makes it centered */ - clear:both!important; -} - -/* This should also be a block element, so that it will fill 100% of the .container */ -.content { - padding:15px; - max-width:600px; - margin:0 auto; - display:block; -} - -/* Let's make sure tables in the content area are 100% wide */ -.content table { width: 100%; } - - -/* Odds and ends */ -.column { - width: 300px; - float:left; -} -.column tr td { padding: 15px; } -.column-wrap { - padding:0!important; - margin:0 auto; - max-width:600px!important; -} -.column table { width:100%;} -.social .column { - width: 280px; - min-width: 279px; - float:left; -} -.column-large { - width: 550px; - margin:0 auto; - padding-left: 10px; -} -/* Be sure to place a .clear element after each set of columns, just to be safe */ -.clear { display: block; clear: both; } - - -/* ------------------------------------------- - PHONE - For clients that support media queries. - Nothing fancy. --------------------------------------------- */ -@media only screen and (max-width: 600px) { - - a[class="btn"] { display:block!important; margin-bottom:10px!important; background-image:none!important; margin-right:0!important;} - - div[class="column"] { width: auto!important; float:none!important;} - - table.social div[class="column"] { - width:auto!important; - } - -} diff --git a/tests/mocks/addons/new-messages-template-pack-variation/variations/email_main_new_variation_test_sunset_red.css b/tests/mocks/addons/new-messages-template-pack-variation/variations/email_main_new_variation_test_sunset_red.css deleted file mode 100644 index 446a1c794cb..00000000000 --- a/tests/mocks/addons/new-messages-template-pack-variation/variations/email_main_new_variation_test_sunset_red.css +++ /dev/null @@ -1,241 +0,0 @@ -/* ------------------------------------- - Attention! This CSS file is used for generating the final messages that are sent to the attendees and admins. -------------------------------------- */ -/* ------------------------------------- - GLOBAL -------------------------------------- */ -* { - margin:0; - padding:0; -} -* { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; } - -img { - max-width: 100%; -} -.collapse { - margin:0; - padding:0; -} -body { - -webkit-font-smoothing:antialiased; - -webkit-text-size-adjust:none; - width: 100%!important; - height: 100%; -} - - -/* ------------------------------------- - ELEMENTS -------------------------------------- */ -a { color: #cc6e2e;} - -.btn { - text-decoration:none; - color: #FFF; - background-color: #7e4646; - padding:10px 16px; - font-weight:bold; - margin-right:10px; - text-align:center; - cursor:pointer; - display: inline-block; -} - -p.callout { - padding:15px; - background-color:#eac6a1; - margin-bottom: 15px; -} -.callout a { - font-weight:bold; - color: #cc6e2e; -} - -table.social { -/* padding:15px; */ - background-color: #ebebeb; - -} -.social .soc-btn { - padding: 3px 7px; - font-size:12px; - margin-bottom:10px; - text-decoration:none; - color: #FFF;font-weight:bold; - display:block; - text-align:center; -} -a.fb { background-color: #3B5998!important; } -a.tw { background-color: #1daced!important; } -a.gp { background-color: #DB4A39!important; } -a.ms { background-color: #000!important; } - -.sidebar .soc-btn { - display:block; - width:100%; -} - -/* ------------------------------------- - HEADER -------------------------------------- */ -table.head-wrap { width: 100%;} - -.header.container table td.logo { padding: 15px; } -.header.container table td.label { padding: 15px; padding-left:0px;} - - -/* ------------------------------------- - BODY -------------------------------------- */ -table.body-wrap { width: 100%;} - - -/* ------------------------------------- - FOOTER -------------------------------------- */ -table.footer-wrap { width: 100%; clear:both!important; -} -.footer-wrap .container td.content p { border-top: 1px solid rgb(215,215,215); padding-top:15px;} -.footer-wrap .container td.content p { - font-size:10px; - font-weight: bold; - -} - - -/* ------------------------------------- - TYPOGRAPHY -------------------------------------- */ -h1,h2,h3,h4,h5,h6 { -font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; padding-bottom:15px; padding-top:10px; color:#000; -} -h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { font-size: 60%; color: #6f6f6f; line-height: 0; text-transform: none; } - -h1 { font-weight:200; font-size: 36px;} -h2 { font-weight:200; font-size: 30px;} -h3 { font-weight:500; font-size: 24px;} -h4 { font-weight:500; font-size: 19px;} -h5 { font-weight:900; font-size: 16px;} -h6 { font-weight:900; font-size: 14px; text-transform: uppercase; color:#444;} - -h4.attendee-name { - margin: 10px 0; -} -.collapse { margin:0!important;} - -p, ul { - margin-bottom: 10px; - font-weight: normal; - font-size:14px; - line-height:1.6; -} -p.lead { font-size:17px; } -p.last { margin-bottom:0px;} - -ul li { - margin-left:5px; - padding-bottom: 5px; - list-style-position: inside; - list-style-type: none; -} - -ul.question-list li, ol.datetime-list li { - margin-left:10px; - padding-bottom: 5px; - list-style-position: inside; - list-style-type: none; -} -li.ticket-name em, li.question-item em {padding-left: 15px;} -hr { - margin: 10px 0; -} - -/* ------------------------------------- - SIDEBAR -------------------------------------- */ -ul.sidebar { - background:#ebebeb; - display:block; - list-style-type: none; -} -#ee-message-preview-container ul.sidebar li { display: block; margin:0; padding:10px 16px;} -#ee-message-preview-container ul.sidebar li h5 { - text-decoration:none; - color: #000; - padding:10px 0 20px 0; - display:block; - margin:0; -} -ul.sidebar li a.last { border-bottom-width:0px;} -ul.sidebar li a h1,ul.sidebar li a h2,ul.sidebar li a h3,ul.sidebar li a h4,ul.sidebar li a h5,ul.sidebar li a h6,ul.sidebar li a p { margin-bottom:0!important;} - - - -/* --------------------------------------------------- - RESPONSIVENESS - Nuke it from orbit. It's the only way to be sure. ------------------------------------------------------- */ - -/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */ -.container { - display:block!important; - max-width:600px!important; - margin:0 auto!important; /* makes it centered */ - clear:both!important; -} - -/* This should also be a block element, so that it will fill 100% of the .container */ -.content { - padding:15px; - max-width:600px; - margin:0 auto; - display:block; -} - -/* Let's make sure tables in the content area are 100% wide */ -.content table { width: 100%; } - - -/* Odds and ends */ -.column { - width: 300px; - float:left; -} -.column tr td { padding: 15px; } -.column-wrap { - padding:0!important; - margin:0 auto; - max-width:600px!important; -} -.column table { width:100%;} -.social .column { - width: 280px; - min-width: 279px; - float:left; -} -.column-large { - width: 550px; - margin:0 auto; - padding-left: 10px; -} -/* Be sure to place a .clear element after each set of columns, just to be safe */ -.clear { display: block; clear: both; } - - -/* ------------------------------------------- - PHONE - For clients that support media queries. - Nothing fancy. --------------------------------------------- */ -@media only screen and (max-width: 600px) { - - a[class="btn"] { display:block!important; margin-bottom:10px!important; background-image:none!important; margin-right:0!important;} - - div[class="column"] { width: auto!important; float:none!important;} - - table.social div[class="column"] { - width:auto!important; - } - -} diff --git a/tests/mocks/addons/new-messages-template-pack-variation/variations/email_preview_new_variation_test_blue_lagoon.css b/tests/mocks/addons/new-messages-template-pack-variation/variations/email_preview_new_variation_test_blue_lagoon.css deleted file mode 100644 index fa832b617bf..00000000000 --- a/tests/mocks/addons/new-messages-template-pack-variation/variations/email_preview_new_variation_test_blue_lagoon.css +++ /dev/null @@ -1,239 +0,0 @@ -/* ------------------------------------- - Attention! This CSS file is used for generating the preview messages. -------------------------------------- */ -/* ------------------------------------- - GLOBAL -------------------------------------- */ -#ee-message-preview-container * { - margin:0; - padding:0; -} -#ee-message-preview-container * { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; } - -#ee-message-preview-container img { - max-width: 100%; -} -#ee-message-preview-container .collapse { - margin:0; - padding:0; -} -#ee-message-preview-container body { - -webkit-font-smoothing:antialiased; - -webkit-text-size-adjust:none; - width: 100%!important; - height: 100%; -} - - -/* ------------------------------------- - ELEMENTS -------------------------------------- */ -#ee-message-preview-container a { color: #2b66cb;} - -#ee-message-preview-container .btn { - text-decoration:none; - color: #FFF; - background-color: #666; - padding:10px 16px; - font-weight:bold; - margin-right:10px; - text-align:center; - cursor:pointer; - display: inline-block; -} - -#ee-message-preview-container p.callout { - padding:15px; - background-color:#7bcaf9; - margin-bottom: 15px; -} -#ee-message-preview-container .callout a { - font-weight:bold; - color: #2b66cb; -} - -#ee-message-preview-container table.social { -/* padding:15px; */ - background-color: #ebebeb; - -} -#ee-message-preview-container .social .soc-btn { - padding: 3px 7px; - font-size:12px; - margin-bottom:10px; - text-decoration:none; - color: #FFF;font-weight:bold; - display:block; - text-align:center; -} -#ee-message-preview-container a.fb { background-color: #3B5998!important; } -#ee-message-preview-container a.tw { background-color: #1daced!important; } -#ee-message-preview-container a.gp { background-color: #DB4A39!important; } -#ee-message-preview-container a.ms { background-color: #000!important; } - -#ee-message-preview-container .sidebar .soc-btn { - display:block; - width:100%; -} - -/* ------------------------------------- - HEADER -------------------------------------- */ -#ee-message-preview-container table.head-wrap { width: 100%;} - -#ee-message-preview-container .header.container table td.logo { padding: 15px; } -#ee-message-preview-container .header.container table td.label { padding: 15px; padding-left:0px;} - - -/* ------------------------------------- - BODY -------------------------------------- */ -#ee-message-preview-container table.body-wrap { width: 100%;} - - -/* ------------------------------------- - FOOTER -------------------------------------- */ -#ee-message-preview-container table.footer-wrap { width: 100%; clear:both!important; -} -#ee-message-preview-container .footer-wrap .container td.content p { border-top: 1px solid rgb(215,215,215); padding-top:15px;} -#ee-message-preview-container .footer-wrap .container td.content p { - font-size:10px; - font-weight: bold; - -} - - -/* ------------------------------------- - TYPOGRAPHY -------------------------------------- */ -#ee-message-preview-container h1,#ee-message-preview-container h2,#ee-message-preview-container h3,#ee-message-preview-container h4,#ee-message-preview-container h5,#ee-message-preview-container h6 { -font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; padding-bottom:15px; padding-top:10px; color:#000; -} -#ee-message-preview-container h1 small, #ee-message-preview-container h2 small, #ee-message-preview-container h3 small, #ee-message-preview-container h4 small, #ee-message-preview-container h5 small, #ee-message-preview-container h6 small { font-size: 60%; color: #6f6f6f; line-height: 0; text-transform: none; } - -#ee-message-preview-container h1 { font-weight:200; font-size: 36px;} -#ee-message-preview-container h2 { font-weight:200; font-size: 30px;} -#ee-message-preview-container h3 { font-weight:500; font-size: 24px;} -#ee-message-preview-container h4 { font-weight:500; font-size: 19px;} -#ee-message-preview-container h5 { font-weight:900; font-size: 16px;} -#ee-message-preview-container h6 { font-weight:900; font-size: 14px; text-transform: uppercase; color:#444;} -#ee-message-preview-container h4.attendee-name {margin: 10px 0;} -#ee-message-preview-container .collapse { margin:0!important;} - -#ee-message-preview-container p, #ee-message-preview-container ul { - margin-bottom: 10px; - font-weight: normal; - font-size:14px; - line-height:1.6; -} -#ee-message-preview-container p.lead { font-size:17px; } -#ee-message-preview-container p.last { margin-bottom:0px;} - -#ee-message-preview-container ul li { - margin-left:5px; - padding-bottom: 5px; - list-style-position: inside; - list-style-type: none; -} -#ee-message-preview-container ol.datetime-list li { - margin-left:10px; - padding-bottom: 5px; - list-style-position: inside; - list-style-type: none; -} -#ee-message-preview-container li.ticket-name em {padding-left: 15px;} -#ee-message-preview-container hr { - margin: 10px 0; -} - -/* ------------------------------------- - SIDEBAR -------------------------------------- */ -#ee-message-preview-container ul.sidebar { - background:#ebebeb; - display:block; - list-style-type: none; -} -#ee-message-preview-container ul.sidebar li { display: block; margin:0; padding:10px 16px;} -#ee-message-preview-container ul.sidebar li h5 { - text-decoration:none; - color: #000; - padding:10px 0 20px 0; - display:block; - margin:0; -} -#ee-message-preview-container ul.sidebar li a.last { border-bottom-width:0px;} -#ee-message-preview-container ul.sidebar li a h1,#ee-message-preview-container ul.sidebar li a h2,#ee-message-preview-container ul.sidebar li a h3,#ee-message-preview-container ul.sidebar li a h4,#ee-message-preview-container ul.sidebar li a h5,#ee-message-preview-container ul.sidebar li a h6,#ee-message-preview-container ul.sidebar li a p { margin-bottom:0!important;} - - - -/* --------------------------------------------------- - RESPONSIVENESS - Nuke it from orbit. It's the only way to be sure. ------------------------------------------------------- */ - -/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */ -#ee-message-preview-container .container { - display:block!important; - max-width:600px!important; - margin:0 auto!important; /* makes it centered */ - clear:both!important; -} - -/* This should also be a block element, so that it will fill 100% of the .container */ -#ee-message-preview-container .content { - padding:15px; - max-width:600px; - margin:0 auto; - display:block; -} - -/* Let's make sure tables in the content area are 100% wide */ -#ee-message-preview-container .content table { width: 100%; } - - -/* Odds and ends */ -#ee-message-preview-container .column { - width: 300px; - float:left; -} -#ee-message-preview-container .column tr td { padding: 15px; } -#ee-message-preview-container .column-wrap { - padding:0!important; - margin:0 auto; - max-width:600px!important; -} -#ee-message-preview-container .column table { width:100%;} -#ee-message-preview-container .social .column { - width: 280px; - min-width: 279px; - float:left; -} - -#ee-message-preview-container .column-large { - width: 550px; - margin:0 auto; - padding-left: 10px; -} - -/* Be sure to place a .clear element after each set of columns, just to be safe */ -.clear { display: block; clear: both; } - - -/* ------------------------------------------- - PHONE - For clients that support media queries. - Nothing fancy. --------------------------------------------- */ -@media only screen and (max-width: 600px) { - - #ee-message-preview-container a[class="btn"] { display:block!important; margin-bottom:10px!important; background-image:none!important; margin-right:0!important;} - - #ee-message-preview-container div[class="column"] { width: auto!important; float:none!important;} - - #ee-message-preview-container table.social div[class="column"] { - width:auto!important; - } - -} diff --git a/tests/mocks/addons/new-messages-template-pack-variation/variations/email_preview_new_variation_test_sunset_red.css b/tests/mocks/addons/new-messages-template-pack-variation/variations/email_preview_new_variation_test_sunset_red.css deleted file mode 100644 index c0bd48ca274..00000000000 --- a/tests/mocks/addons/new-messages-template-pack-variation/variations/email_preview_new_variation_test_sunset_red.css +++ /dev/null @@ -1,239 +0,0 @@ -/* ------------------------------------- - Attention! This CSS file is used for generating the preview messages. -------------------------------------- */ -/* ------------------------------------- - GLOBAL -------------------------------------- */ -#ee-message-preview-container * { - margin:0; - padding:0; -} -#ee-message-preview-container * { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; } - -#ee-message-preview-container img { - max-width: 100%; -} -#ee-message-preview-container .collapse { - margin:0; - padding:0; -} -#ee-message-preview-container body { - -webkit-font-smoothing:antialiased; - -webkit-text-size-adjust:none; - width: 100%!important; - height: 100%; -} - - -/* ------------------------------------- - ELEMENTS -------------------------------------- */ -#ee-message-preview-container a { color: #cc6e2e;} - -#ee-message-preview-container .btn { - text-decoration:none; - color: #FFF; - background-color: #7e4646; - padding:10px 16px; - font-weight:bold; - margin-right:10px; - text-align:center; - cursor:pointer; - display: inline-block; -} - -#ee-message-preview-container p.callout { - padding:15px; - background-color:#eac6a1; - margin-bottom: 15px; -} -#ee-message-preview-container .callout a { - font-weight:bold; - color: #cc6e2e; -} - -#ee-message-preview-container table.social { -/* padding:15px; */ - background-color: #ebebeb; - -} -#ee-message-preview-container .social .soc-btn { - padding: 3px 7px; - font-size:12px; - margin-bottom:10px; - text-decoration:none; - color: #FFF;font-weight:bold; - display:block; - text-align:center; -} -#ee-message-preview-container a.fb { background-color: #3B5998!important; } -#ee-message-preview-container a.tw { background-color: #1daced!important; } -#ee-message-preview-container a.gp { background-color: #DB4A39!important; } -#ee-message-preview-container a.ms { background-color: #000!important; } - -#ee-message-preview-container .sidebar .soc-btn { - display:block; - width:100%; -} - -/* ------------------------------------- - HEADER -------------------------------------- */ -#ee-message-preview-container table.head-wrap { width: 100%;} - -#ee-message-preview-container .header.container table td.logo { padding: 15px; } -#ee-message-preview-container .header.container table td.label { padding: 15px; padding-left:0px;} - - -/* ------------------------------------- - BODY -------------------------------------- */ -#ee-message-preview-container table.body-wrap { width: 100%;} - - -/* ------------------------------------- - FOOTER -------------------------------------- */ -#ee-message-preview-container table.footer-wrap { width: 100%; clear:both!important; -} -#ee-message-preview-container .footer-wrap .container td.content p { border-top: 1px solid rgb(215,215,215); padding-top:15px;} -#ee-message-preview-container .footer-wrap .container td.content p { - font-size:10px; - font-weight: bold; - -} - - -/* ------------------------------------- - TYPOGRAPHY -------------------------------------- */ -#ee-message-preview-container h1,#ee-message-preview-container h2,#ee-message-preview-container h3,#ee-message-preview-container h4,#ee-message-preview-container h5,#ee-message-preview-container h6 { -font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; padding-bottom:15px; padding-top:10px; color:#000; -} -#ee-message-preview-container h1 small, #ee-message-preview-container h2 small, #ee-message-preview-container h3 small, #ee-message-preview-container h4 small, #ee-message-preview-container h5 small, #ee-message-preview-container h6 small { font-size: 60%; color: #6f6f6f; line-height: 0; text-transform: none; } - -#ee-message-preview-container h1 { font-weight:200; font-size: 36px;} -#ee-message-preview-container h2 { font-weight:200; font-size: 30px;} -#ee-message-preview-container h3 { font-weight:500; font-size: 24px;} -#ee-message-preview-container h4 { font-weight:500; font-size: 19px;} -#ee-message-preview-container h5 { font-weight:900; font-size: 16px;} -#ee-message-preview-container h6 { font-weight:900; font-size: 14px; text-transform: uppercase; color:#444;} -#ee-message-preview-container h4.attendee-name {margin: 10px 0;} -#ee-message-preview-container .collapse { margin:0!important;} - -#ee-message-preview-container p, #ee-message-preview-container ul { - margin-bottom: 10px; - font-weight: normal; - font-size:14px; - line-height:1.6; -} -#ee-message-preview-container p.lead { font-size:17px; } -#ee-message-preview-container p.last { margin-bottom:0px;} - -#ee-message-preview-container ul li { - margin-left:5px; - padding-bottom: 5px; - list-style-position: inside; - list-style-type: none; -} -#ee-message-preview-container ol.datetime-list li { - margin-left:10px; - padding-bottom: 5px; - list-style-position: inside; - list-style-type: none; -} -#ee-message-preview-container li.ticket-name em {padding-left: 15px;} -#ee-message-preview-container hr { - margin: 10px 0; -} - -/* ------------------------------------- - SIDEBAR -------------------------------------- */ -#ee-message-preview-container ul.sidebar { - background:#ebebeb; - display:block; - list-style-type: none; -} -#ee-message-preview-container ul.sidebar li { display: block; margin:0; padding:10px 16px;} -#ee-message-preview-container ul.sidebar li h5 { - text-decoration:none; - color: #000; - padding:10px 0 20px 0; - display:block; - margin:0; -} -#ee-message-preview-container ul.sidebar li a.last { border-bottom-width:0px;} -#ee-message-preview-container ul.sidebar li a h1,#ee-message-preview-container ul.sidebar li a h2,#ee-message-preview-container ul.sidebar li a h3,#ee-message-preview-container ul.sidebar li a h4,#ee-message-preview-container ul.sidebar li a h5,#ee-message-preview-container ul.sidebar li a h6,#ee-message-preview-container ul.sidebar li a p { margin-bottom:0!important;} - - - -/* --------------------------------------------------- - RESPONSIVENESS - Nuke it from orbit. It's the only way to be sure. ------------------------------------------------------- */ - -/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */ -#ee-message-preview-container .container { - display:block!important; - max-width:600px!important; - margin:0 auto!important; /* makes it centered */ - clear:both!important; -} - -/* This should also be a block element, so that it will fill 100% of the .container */ -#ee-message-preview-container .content { - padding:15px; - max-width:600px; - margin:0 auto; - display:block; -} - -/* Let's make sure tables in the content area are 100% wide */ -#ee-message-preview-container .content table { width: 100%; } - - -/* Odds and ends */ -#ee-message-preview-container .column { - width: 300px; - float:left; -} -#ee-message-preview-container .column tr td { padding: 15px; } -#ee-message-preview-container .column-wrap { - padding:0!important; - margin:0 auto; - max-width:600px!important; -} -#ee-message-preview-container .column table { width:100%;} -#ee-message-preview-container .social .column { - width: 280px; - min-width: 279px; - float:left; -} - -#ee-message-preview-container .column-large { - width: 550px; - margin:0 auto; - padding-left: 10px; -} - -/* Be sure to place a .clear element after each set of columns, just to be safe */ -.clear { display: block; clear: both; } - - -/* ------------------------------------------- - PHONE - For clients that support media queries. - Nothing fancy. --------------------------------------------- */ -@media only screen and (max-width: 600px) { - - #ee-message-preview-container a[class="btn"] { display:block!important; margin-bottom:10px!important; background-image:none!important; margin-right:0!important;} - - #ee-message-preview-container div[class="column"] { width: auto!important; float:none!important;} - - #ee-message-preview-container table.social div[class="column"] { - width:auto!important; - } - -} diff --git a/tests/mocks/addons/new-messages-template-pack-variation/variations/email_wpeditor_new_variation_test_blue_lagoon.css b/tests/mocks/addons/new-messages-template-pack-variation/variations/email_wpeditor_new_variation_test_blue_lagoon.css deleted file mode 100644 index f7446578647..00000000000 --- a/tests/mocks/addons/new-messages-template-pack-variation/variations/email_wpeditor_new_variation_test_blue_lagoon.css +++ /dev/null @@ -1,224 +0,0 @@ -/* ------------------------------------- - GLOBAL -------------------------------------- */ -.mceContentBody * { - margin:0; - padding:0; -} -.mceContentBody * { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; } - -.mceContentBody img { - max-width: 100%; -} -.mceContentBody .collapse { - margin:0; - padding:0; -} -.mceContentBody body { - -webkit-font-smoothing:antialiased; - -webkit-text-size-adjust:none; - width: 100%!important; - height: 100%; -} - - -/* ------------------------------------- - ELEMENTS -------------------------------------- */ -.mceContentBody a { color: #2b66cb;} - -.mceContentBody .btn { - text-decoration:none; - color: #FFF; - background-color: #666; - padding:10px 16px; - font-weight:bold; - margin-right:10px; - text-align:center; - cursor:pointer; - display: inline-block; -} - -.mceContentBody p.callout { - padding:15px; - background-color:#7bcaf9; - margin-bottom: 15px; -} -.mceContentBody .callout a { - font-weight:bold; - color: #2b66cb; -} - -.mceContentBody table.social { -/* padding:15px; */ - background-color: #ebebeb; - -} -.mceContentBody .social .soc-btn { - padding: 3px 7px; - font-size:12px; - margin-bottom:10px; - text-decoration:none; - color: #FFF;font-weight:bold; - display:block; - text-align:center; -} -.mceContentBody a.fb { background-color: #3B5998!important; } -.mceContentBody a.tw { background-color: #1daced!important; } -.mceContentBody a.gp { background-color: #DB4A39!important; } -.mceContentBody a.ms { background-color: #000!important; } - -.mceContentBody .sidebar .soc-btn { - display:block; - width:100%; -} - -/* ------------------------------------- - HEADER -------------------------------------- */ -.mceContentBody table.head-wrap { width: 100%;} - -.mceContentBody .header.container table td.logo { padding: 15px; } -.mceContentBody .header.container table td.label { padding: 15px; padding-left:0px;} - - -/* ------------------------------------- - BODY -------------------------------------- */ -.mceContentBody table.body-wrap { width: 100%;} - - -/* ------------------------------------- - FOOTER -------------------------------------- */ -.mceContentBody table.footer-wrap { width: 100%; clear:both!important; -} -.mceContentBody .footer-wrap .container td.content p { border-top: 1px solid rgb(215,215,215); padding-top:15px;} -.mceContentBody .footer-wrap .container td.content p { - font-size:10px; - font-weight: bold; - -} - - -/* ------------------------------------- - TYPOGRAPHY -------------------------------------- */ -.mceContentBody h1,.mceContentBody h2,.mceContentBody h3,.mceContentBody h4,.mceContentBody h5,.mceContentBody h6 { -font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; color:#000; -} -.mceContentBody h1 small, .mceContentBody h2 small, .mceContentBody h3 small, .mceContentBody h4 small, .mceContentBody h5 small, .mceContentBody h6 small { font-size: 60%; color: #6f6f6f; line-height: 0; text-transform: none; } - -.mceContentBody h1 { font-weight:200; font-size: 44px;} -.mceContentBody h2 { font-weight:200; font-size: 37px;} -.mceContentBody h3 { font-weight:500; font-size: 27px;} -.mceContentBody h4 { font-weight:500; font-size: 23px;} -.mceContentBody h5 { font-weight:900; font-size: 17px;} -.mceContentBody h6 { font-weight:900; font-size: 14px; text-transform: uppercase; color:#444;} - -.mceContentBody .collapse { margin:0!important;} - -.mceContentBody p, .mceContentBody ul { - margin-bottom: 10px; - font-weight: normal; - font-size:14px; - line-height:1.6; -} -.mceContentBody p.lead { font-size:17px; } -.mceContentBody p.last { margin-bottom:0px;} - -.mceContentBody ul li { - margin-left:5px; - list-style-position: inside; -} - -/* ------------------------------------- - SIDEBAR -------------------------------------- */ -.mceContentBody ul.sidebar { - background:#ebebeb; - display:block; - list-style-type: none; -} -.mceContentBody ul.sidebar li { display: block; margin:0;} -.mceContentBody ul.sidebar li a { - text-decoration:none; - color: #666; - padding:10px 16px; -/* font-weight:bold; */ - margin-right:10px; -/* text-align:center; */ - cursor:pointer; - border-bottom: 1px solid #777777; - border-top: 1px solid #FFFFFF; - display:block; - margin:0; -} -.mceContentBody ul.sidebar li a.last { border-bottom-width:0px;} -.mceContentBody ul.sidebar li a h1,.mceContentBody ul.sidebar li a h2,.mceContentBody ul.sidebar li a h3,.mceContentBody ul.sidebar li a h4,.mceContentBody ul.sidebar li a h5,.mceContentBody ul.sidebar li a h6,.mceContentBody ul.sidebar li a p { margin-bottom:0!important;} - - - -/* --------------------------------------------------- - RESPONSIVENESS - Nuke it from orbit. It's the only way to be sure. ------------------------------------------------------- */ - -/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */ -.mceContentBody .container { - display:block!important; - max-width:600px!important; - margin:0 auto!important; /* makes it centered */ - clear:both!important; -} - -/* This should also be a block element, so that it will fill 100% of the .container */ -.mceContentBody .content { - padding:15px; - max-width:600px; - margin:0 auto; - display:block; -} - -/* Let's make sure tables in the content area are 100% wide */ -.mceContentBody .content table { width: 100%; } - - -/* Odds and ends */ -.mceContentBody .column { - width: 300px; - float:left; -} -.mceContentBody .column tr td { padding: 15px; } -.mceContentBody .column-wrap { - padding:0!important; - margin:0 auto; - max-width:600px!important; -} -.mceContentBody .column table { width:100%;} -.mceContentBody .social .column { - width: 280px; - min-width: 279px; - float:left; -} - -/* Be sure to place a .clear element after each set of columns, just to be safe */ -.clear { display: block; clear: both; } - - -/* ------------------------------------------- - PHONE - For clients that support media queries. - Nothing fancy. --------------------------------------------- */ -@media only screen and (max-width: 600px) { - - .mceContentBody a[class="btn"] { display:block!important; margin-bottom:10px!important; background-image:none!important; margin-right:0!important;} - - .mceContentBody div[class="column"] { width: auto!important; float:none!important;} - - .mceContentBody table.social div[class="column"] { - width:auto!important; - } - -} diff --git a/tests/mocks/addons/new-messages-template-pack-variation/variations/email_wpeditor_new_variation_test_sunset_red.css b/tests/mocks/addons/new-messages-template-pack-variation/variations/email_wpeditor_new_variation_test_sunset_red.css deleted file mode 100644 index dec172a3a64..00000000000 --- a/tests/mocks/addons/new-messages-template-pack-variation/variations/email_wpeditor_new_variation_test_sunset_red.css +++ /dev/null @@ -1,224 +0,0 @@ -/* ------------------------------------- - GLOBAL -------------------------------------- */ -.mceContentBody * { - margin:0; - padding:0; -} -.mceContentBody * { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; } - -.mceContentBody img { - max-width: 100%; -} -.mceContentBody .collapse { - margin:0; - padding:0; -} -.mceContentBody body { - -webkit-font-smoothing:antialiased; - -webkit-text-size-adjust:none; - width: 100%!important; - height: 100%; -} - - -/* ------------------------------------- - ELEMENTS -------------------------------------- */ -.mceContentBody a { color: #cc6e2e;} - -.mceContentBody .btn { - text-decoration:none; - color: #FFF; - background-color: #7e4646; - padding:10px 16px; - font-weight:bold; - margin-right:10px; - text-align:center; - cursor:pointer; - display: inline-block; -} - -.mceContentBody p.callout { - padding:15px; - background-color:#eac6a1; - margin-bottom: 15px; -} -.mceContentBody .callout a { - font-weight:bold; - color: #cc6e2e; -} - -.mceContentBody table.social { -/* padding:15px; */ - background-color: #ebebeb; - -} -.mceContentBody .social .soc-btn { - padding: 3px 7px; - font-size:12px; - margin-bottom:10px; - text-decoration:none; - color: #FFF;font-weight:bold; - display:block; - text-align:center; -} -.mceContentBody a.fb { background-color: #3B5998!important; } -.mceContentBody a.tw { background-color: #1daced!important; } -.mceContentBody a.gp { background-color: #DB4A39!important; } -.mceContentBody a.ms { background-color: #000!important; } - -.mceContentBody .sidebar .soc-btn { - display:block; - width:100%; -} - -/* ------------------------------------- - HEADER -------------------------------------- */ -.mceContentBody table.head-wrap { width: 100%;} - -.mceContentBody .header.container table td.logo { padding: 15px; } -.mceContentBody .header.container table td.label { padding: 15px; padding-left:0px;} - - -/* ------------------------------------- - BODY -------------------------------------- */ -.mceContentBody table.body-wrap { width: 100%;} - - -/* ------------------------------------- - FOOTER -------------------------------------- */ -.mceContentBody table.footer-wrap { width: 100%; clear:both!important; -} -.mceContentBody .footer-wrap .container td.content p { border-top: 1px solid rgb(215,215,215); padding-top:15px;} -.mceContentBody .footer-wrap .container td.content p { - font-size:10px; - font-weight: bold; - -} - - -/* ------------------------------------- - TYPOGRAPHY -------------------------------------- */ -.mceContentBody h1,.mceContentBody h2,.mceContentBody h3,.mceContentBody h4,.mceContentBody h5,.mceContentBody h6 { -font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; color:#000; -} -.mceContentBody h1 small, .mceContentBody h2 small, .mceContentBody h3 small, .mceContentBody h4 small, .mceContentBody h5 small, .mceContentBody h6 small { font-size: 60%; color: #6f6f6f; line-height: 0; text-transform: none; } - -.mceContentBody h1 { font-weight:200; font-size: 44px;} -.mceContentBody h2 { font-weight:200; font-size: 37px;} -.mceContentBody h3 { font-weight:500; font-size: 27px;} -.mceContentBody h4 { font-weight:500; font-size: 23px;} -.mceContentBody h5 { font-weight:900; font-size: 17px;} -.mceContentBody h6 { font-weight:900; font-size: 14px; text-transform: uppercase; color:#444;} - -.mceContentBody .collapse { margin:0!important;} - -.mceContentBody p, .mceContentBody ul { - margin-bottom: 10px; - font-weight: normal; - font-size:14px; - line-height:1.6; -} -.mceContentBody p.lead { font-size:17px; } -.mceContentBody p.last { margin-bottom:0px;} - -.mceContentBody ul li { - margin-left:5px; - list-style-position: inside; -} - -/* ------------------------------------- - SIDEBAR -------------------------------------- */ -.mceContentBody ul.sidebar { - background:#ebebeb; - display:block; - list-style-type: none; -} -.mceContentBody ul.sidebar li { display: block; margin:0;} -.mceContentBody ul.sidebar li a { - text-decoration:none; - color: #7e4646; - padding:10px 16px; -/* font-weight:bold; */ - margin-right:10px; -/* text-align:center; */ - cursor:pointer; - border-bottom: 1px solid #777777; - border-top: 1px solid #FFFFFF; - display:block; - margin:0; -} -.mceContentBody ul.sidebar li a.last { border-bottom-width:0px;} -.mceContentBody ul.sidebar li a h1,.mceContentBody ul.sidebar li a h2,.mceContentBody ul.sidebar li a h3,.mceContentBody ul.sidebar li a h4,.mceContentBody ul.sidebar li a h5,.mceContentBody ul.sidebar li a h6,.mceContentBody ul.sidebar li a p { margin-bottom:0!important;} - - - -/* --------------------------------------------------- - RESPONSIVENESS - Nuke it from orbit. It's the only way to be sure. ------------------------------------------------------- */ - -/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */ -.mceContentBody .container { - display:block!important; - max-width:600px!important; - margin:0 auto!important; /* makes it centered */ - clear:both!important; -} - -/* This should also be a block element, so that it will fill 100% of the .container */ -.mceContentBody .content { - padding:15px; - max-width:600px; - margin:0 auto; - display:block; -} - -/* Let's make sure tables in the content area are 100% wide */ -.mceContentBody .content table { width: 100%; } - - -/* Odds and ends */ -.mceContentBody .column { - width: 300px; - float:left; -} -.mceContentBody .column tr td { padding: 15px; } -.mceContentBody .column-wrap { - padding:0!important; - margin:0 auto; - max-width:600px!important; -} -.mceContentBody .column table { width:100%;} -.mceContentBody .social .column { - width: 280px; - min-width: 279px; - float:left; -} - -/* Be sure to place a .clear element after each set of columns, just to be safe */ -.clear { display: block; clear: both; } - - -/* ------------------------------------------- - PHONE - For clients that support media queries. - Nothing fancy. --------------------------------------------- */ -@media only screen and (max-width: 600px) { - - .mceContentBody a[class="btn"] { display:block!important; margin-bottom:10px!important; background-image:none!important; margin-right:0!important;} - - .mceContentBody div[class="column"] { width: auto!important; float:none!important;} - - .mceContentBody table.social div[class="column"] { - width:auto!important; - } - -} diff --git a/tests/mocks/addons/new-messages-template-pack/EE_Messages_Template_Pack_New_Template_Pack.class.php b/tests/mocks/addons/new-messages-template-pack/EE_Messages_Template_Pack_New_Template_Pack.class.php deleted file mode 100644 index 1f4d0e58507..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/EE_Messages_Template_Pack_New_Template_Pack.class.php +++ /dev/null @@ -1,41 +0,0 @@ -label = __('Test Pack', 'event_espresso'); - $this->dbref = 'new_template_pack'; - $this->description = __('This is a new template pack included as part of an example template pack for demonstration purposes.', 'event_espresso'); - $this->_base_url = EE_NEW_TP_URL . 'templates/'; - $this->_base_path = EE_NEW_TP_PATH . 'templates/'; - - //note in this example we're stating that this template pack JUST supports the email messenger and the payment message types. - $this->_supports = array( - 'email' => array( - 'payment_declined', 'payment', 'payment_refund', 'payment_reminder', 'newsletter' - ) - ); - - //here we list what variations are supported. This example demonstration doesn't support any extra variations. - //Remember that ALL variations for your template pack must be in a folder located at $this->_base_path '/variations'. The variation file names should match what each messenger expects. So you may need to look at the messenger classes for the messengers you support to see what possible variations might be requested by the messenger. - $this->_variations = array(); - - //all template packs can define the default variation. You may want to override the label that describes this default, and you do so via this property. Indexes are the messenger you wish to override the default label for and values are the new label. - $this->_default_variation_labels = array( 'email' => __('New Pack Default', 'event_espresso' ) ); - } -} diff --git a/tests/mocks/addons/new-messages-template-pack/new-messages-template-pack.php b/tests/mocks/addons/new-messages-template-pack/new-messages-template-pack.php deleted file mode 100644 index 79adc061849..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/new-messages-template-pack.php +++ /dev/null @@ -1,61 +0,0 @@ - rtrim(EE_NEW_TP_PATH, '/'), - 'classname' => 'EE_Messages_Template_Pack_New_Template_Pack', - ); - EE_Register_Messages_Template_Pack::register( 'ee_new_template_pack', $setup ); -} -add_action( 'EE_Brewing_Regular___messages_caf', 'ee_new_template_pack_test_register_new_variation' ); diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_newsletter_content.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_newsletter_content.template.php deleted file mode 100644 index 832818771ff..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_newsletter_content.template.php +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - - - - -
-
- - - - - - - -
[CO_LOGO] -
[COMPANY]
-
-
-
- - - - - - - - - - -
-
- - - - - - -
-

-

-

This is a custom template pack.

-
- [NEWSLETTER_CONTENT] -
-
-
-
- - - - - - - - - - - - - diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_newsletter_newsletter_content.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_newsletter_newsletter_content.template.php deleted file mode 100644 index 8b29e3daf40..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_newsletter_newsletter_content.template.php +++ /dev/null @@ -1 +0,0 @@ -

diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_newsletter_subject.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_newsletter_subject.template.php deleted file mode 100644 index db544c09be6..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_newsletter_subject.template.php +++ /dev/null @@ -1 +0,0 @@ -CFG->organization->get_pretty( 'name' ) ); ?> diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_attendee_list_admin.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_attendee_list_admin.template.php deleted file mode 100644 index 70ef0cfef80..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_attendee_list_admin.template.php +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_content.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_content.template.php deleted file mode 100644 index f4f551eab64..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_content.template.php +++ /dev/null @@ -1,100 +0,0 @@ - - - - - - - - - -
-
- - - - - - - -
[CO_LOGO] -
[COMPANY]
-
-
- - - - - - - - - - - -
-
- - - - - - -
-

-

- -

-
    -
  • -
  • [PAYMENT_STATUS]
  • -
  • [TOTAL_OWING]
  • -
-[EVENT_LIST] -
-
- - - - - - - - - - - - diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_content_admin.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_content_admin.template.php deleted file mode 100644 index 1ba07904d20..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_content_admin.template.php +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - -
-
- - - - - - - -
[CO_LOGO] -
[COMPANY]
-
-
- - - - - - - - - - -
-
- - - - - - -
-

- -

-
    -
  • -
  • [PAYMENT_STATUS]
  • -
  • [TXN_ID]
  • -
  • [PAYMENT_GATEWAY]
  • -
  • [TOTAL_COST]
  • -
  • [AMOUNT_PAID]
  • -
  • [TOTAL_OWING]
  • -
-
-
-
-

-

[PRIMARY_REGISTRANT_FNAME] [PRIMARY_REGISTRANT_LNAME]: [PRIMARY_REGISTRANT_EMAIL]

-
-
- diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_declined_content.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_declined_content.template.php deleted file mode 100644 index a2f814655d2..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_declined_content.template.php +++ /dev/null @@ -1,108 +0,0 @@ - - - - - - - - - -
-
- - - - - - - -
[CO_LOGO] -
[COMPANY]
-
-
- - - - - - - - - - - -
-
- - - - - - -
-

-

DECLINED for the following transaction and ticket purchases:', 'ee-new-messages-template-pack-test'); ?>

-

-
    -
  • -
  • [PAYMENT_STATUS]
  • -
  • [TXN_ID]
  • -
  • [TOTAL_COST]
  • -
  • [PAYMENT_GATEWAY]
  • -
  • [AMOUNT_PAID]
  • -
  • [TOTAL_OWING]
  • -
- -

', '' ); ?>

- -[EVENT_LIST] - -

', '' ); ?>

-
-
- - - - - - - - - - - - diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_declined_content_admin.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_declined_content_admin.template.php deleted file mode 100644 index 2b6164a74dd..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_declined_content_admin.template.php +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - -
-
- - - - - - - -
[CO_LOGO] -
[COMPANY]
-
-
- - - - - - - - - - -
-
- - - - - - -
-

- -

-
    -
  • -
  • [PAYMENT_STATUS]
  • -
  • [TXN_ID]
  • -
  • [PAYMENT_GATEWAY]
  • -
  • [TOTAL_COST]
  • -
  • [AMOUNT_PAID]
  • -
  • [TOTAL_OWING]
  • -
-
-
-
-

-

[PRIMARY_REGISTRANT_FNAME] [PRIMARY_REGISTRANT_LNAME]: [PRIMARY_REGISTRANT_EMAIL]

-
-
- diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_declined_event_list.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_declined_event_list.template.php deleted file mode 100644 index 1522b26661c..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_declined_event_list.template.php +++ /dev/null @@ -1,6 +0,0 @@ - -

[EVENT_LINK]

- -
- [TICKET_LIST] -
diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_declined_subject.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_declined_subject.template.php deleted file mode 100644 index d0e5e644c86..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_declined_subject.template.php +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_event_list.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_event_list.template.php deleted file mode 100644 index 4c456d59d64..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_event_list.template.php +++ /dev/null @@ -1,6 +0,0 @@ - -

[EVENT_LINK]

- -
- [TICKET_LIST] -
diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_event_list_admin.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_event_list_admin.template.php deleted file mode 100644 index 70ef0cfef80..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_event_list_admin.template.php +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_from.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_from.template.php deleted file mode 100644 index ade4fada4e4..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_from.template.php +++ /dev/null @@ -1 +0,0 @@ -[CO_FORMATTED_EMAIL] diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_refund_content.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_refund_content.template.php deleted file mode 100644 index 258a181acdb..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_refund_content.template.php +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - -
-
- - - - - - - -
[CO_LOGO] -
[COMPANY]
-
-
- - - - - - - - - - - -
-
- - - - - - -
-

-

-

-
    -
  • -
  • [PAYMENT_STATUS]
  • -
  • [TXN_ID]
  • -
  • [TOTAL_COST]
  • -
  • [AMOUNT_PAID]
  • -
-[EVENT_LIST] -
-
- - - - - - - - - - - - diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_refund_content_admin.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_refund_content_admin.template.php deleted file mode 100644 index 5239094a963..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_refund_content_admin.template.php +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - -
-
- - - - - - - -
[CO_LOGO] -
[COMPANY]
-
-
- - - - - - - - - - -
-
- - - - - - -
-

- -

-
    -
  • -
  • [PAYMENT_STATUS]
  • -
  • [TXN_ID]
  • -
  • [PAYMENT_GATEWAY]
  • -
  • [TOTAL_COST]
  • -
  • [AMOUNT_PAID]
  • -
-
-
-
-

-

[PRIMARY_REGISTRANT_FNAME] [PRIMARY_REGISTRANT_LNAME]: [PRIMARY_REGISTRANT_EMAIL]

-
-
- diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_refund_subject.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_refund_subject.template.php deleted file mode 100644 index 149e2aee492..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_refund_subject.template.php +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_reminder_content.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_reminder_content.template.php deleted file mode 100644 index 2056fe30108..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_reminder_content.template.php +++ /dev/null @@ -1,107 +0,0 @@ - - - - - - - - - -
-
- - - - - - - -
[CO_LOGO] -
[COMPANY]
-
-
- - - - - - - - - - - -
-
- - - - - - -
-

-

-

-
    -
  • -
  • [PAYMENT_STATUS]
  • -
  • [TXN_ID]
  • -
  • [TOTAL_COST]
  • -
  • [AMOUNT_PAID]
  • -
  • [TOTAL_OWING]
  • -
- -

', '' ); ?>

- -[EVENT_LIST] - -

', '' ); ?>

-
-
- - - - - - - - - - - - diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_reminder_content_admin.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_reminder_content_admin.template.php deleted file mode 100644 index e4ac96a173a..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_reminder_content_admin.template.php +++ /dev/null @@ -1,61 +0,0 @@ - - - - - - - - - -
-
- - - - - - - -
[CO_LOGO] -
[COMPANY]
-
-
- - - - - - - - - - -
-
- - - - - - -
-

- -

-
    -
  • -
  • [PAYMENT_STATUS]
  • -
  • [TXN_ID]
  • -
  • [PAYMENT_GATEWAY]
  • -
  • [TOTAL_COST]
  • -
  • [AMOUNT_PAID]
  • -
  • [TOTAL_OWING]
  • -
-
-
-
-

-

[PRIMARY_REGISTRANT_FNAME] [PRIMARY_REGISTRANT_LNAME]: [PRIMARY_REGISTRANT_EMAIL]

-
-
- diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_reminder_event_list.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_reminder_event_list.template.php deleted file mode 100644 index 1522b26661c..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_reminder_event_list.template.php +++ /dev/null @@ -1,6 +0,0 @@ - -

[EVENT_LINK]

- -
- [TICKET_LIST] -
diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_reminder_subject.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_reminder_subject.template.php deleted file mode 100644 index bdffda71858..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_reminder_subject.template.php +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_subject.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_subject.template.php deleted file mode 100644 index 27a69829bee..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_subject.template.php +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_ticket_list.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_ticket_list.template.php deleted file mode 100644 index 91a1930efc2..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_ticket_list.template.php +++ /dev/null @@ -1,6 +0,0 @@ -
    -
  • [TICKET_NAME]
    [TICKET_DESCRIPTION]
  • -
  • [TICKET_PRICE]
  • -
  • [TKT_QTY_PURCHASED]
  • -
-
diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_ticket_list_admin.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_ticket_list_admin.template.php deleted file mode 100644 index 70ef0cfef80..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_ticket_list_admin.template.php +++ /dev/null @@ -1 +0,0 @@ - diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_to.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_to.template.php deleted file mode 100644 index e46b537052d..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_to.template.php +++ /dev/null @@ -1 +0,0 @@ -[RECIPIENT_EMAIL] diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_to_admin.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_to_admin.template.php deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_to_primary_attendee.template.php b/tests/mocks/addons/new-messages-template-pack/templates/email_payment_to_primary_attendee.template.php deleted file mode 100644 index 53432b13beb..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/email_payment_to_primary_attendee.template.php +++ /dev/null @@ -1 +0,0 @@ -[PRIMARY_REGISTRANT_EMAIL] diff --git a/tests/mocks/addons/new-messages-template-pack/templates/variations/email_main_default.css b/tests/mocks/addons/new-messages-template-pack/templates/variations/email_main_default.css deleted file mode 100644 index 3a16e62a816..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/variations/email_main_default.css +++ /dev/null @@ -1,241 +0,0 @@ -/* ------------------------------------- - Attention! This CSS file is used for generating the final messages that are sent to the attendees and admins. -------------------------------------- */ -/* ------------------------------------- - GLOBAL -------------------------------------- */ -* { - margin:0; - padding:0; -} -* { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; } - -img { - max-width: 100%; -} -.collapse { - margin:0; - padding:0; -} -body { - -webkit-font-smoothing:antialiased; - -webkit-text-size-adjust:none; - width: 100%!important; - height: 100%; -} - - -/* ------------------------------------- - ELEMENTS -------------------------------------- */ -a { color: #2BA6CB;} - -.btn { - text-decoration:none; - color: #FFF; - background-color: #666; - padding:10px 16px; - font-weight:bold; - margin-right:10px; - text-align:center; - cursor:pointer; - display: inline-block; -} - -p.callout { - padding:15px; - background-color:#ECF8FF; - margin-bottom: 15px; -} -.callout a { - font-weight:bold; - color: #2BA6CB; -} - -table.social { -/* padding:15px; */ - background-color: #ebebeb; - -} -.social .soc-btn { - padding: 3px 7px; - font-size:12px; - margin-bottom:10px; - text-decoration:none; - color: #FFF;font-weight:bold; - display:block; - text-align:center; -} -a.fb { background-color: #3B5998!important; } -a.tw { background-color: #1daced!important; } -a.gp { background-color: #DB4A39!important; } -a.ms { background-color: #000!important; } - -.sidebar .soc-btn { - display:block; - width:100%; -} - -/* ------------------------------------- - HEADER -------------------------------------- */ -table.head-wrap { width: 100%;} - -.header.container table td.logo { padding: 15px; } -.header.container table td.label { padding: 15px; padding-left:0px;} - - -/* ------------------------------------- - BODY -------------------------------------- */ -table.body-wrap { width: 100%;} - - -/* ------------------------------------- - FOOTER -------------------------------------- */ -table.footer-wrap { width: 100%; clear:both!important; -} -.footer-wrap .container td.content p { border-top: 1px solid rgb(215,215,215); padding-top:15px;} -.footer-wrap .container td.content p { - font-size:10px; - font-weight: bold; - -} - - -/* ------------------------------------- - TYPOGRAPHY -------------------------------------- */ -h1,h2,h3,h4,h5,h6 { -font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; padding-bottom:15px; padding-top:10px; color:#000; -} -h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { font-size: 60%; color: #6f6f6f; line-height: 0; text-transform: none; } - -h1 { font-weight:200; font-size: 36px;} -h2 { font-weight:200; font-size: 30px;} -h3 { font-weight:500; font-size: 24px;} -h4 { font-weight:500; font-size: 19px;} -h5 { font-weight:900; font-size: 16px;} -h6 { font-weight:900; font-size: 14px; text-transform: uppercase; color:#444;} - -h4.attendee-name { - margin: 10px 0; -} -.collapse { margin:0!important;} - -p, ul { - margin-bottom: 10px; - font-weight: normal; - font-size:14px; - line-height:1.6; -} -p.lead { font-size:17px; } -p.last { margin-bottom:0px;} - -ul li { - margin-left:5px; - padding-bottom: 5px; - list-style-position: inside; - list-style-type: none; -} - -ul.question-list li, ol.datetime-list li { - margin-left:10px; - padding-bottom: 5px; - list-style-position: inside; - list-style-type: none; -} -li.ticket-name em, li.question-item em {padding-left: 15px;} -hr { - margin: 10px 0; -} - -/* ------------------------------------- - SIDEBAR -------------------------------------- */ -ul.sidebar { - background:#ebebeb; - display:block; - list-style-type: none; -} -#ee-message-preview-container ul.sidebar li { display: block; margin:0; padding:10px 16px;} -#ee-message-preview-container ul.sidebar li h5 { - text-decoration:none; - color: #000; - padding:10px 0 20px 0; - display:block; - margin:0; -} -ul.sidebar li a.last { border-bottom-width:0px;} -ul.sidebar li a h1,ul.sidebar li a h2,ul.sidebar li a h3,ul.sidebar li a h4,ul.sidebar li a h5,ul.sidebar li a h6,ul.sidebar li a p { margin-bottom:0!important;} - - - -/* --------------------------------------------------- - RESPONSIVENESS - Nuke it from orbit. It's the only way to be sure. ------------------------------------------------------- */ - -/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */ -.container { - display:block!important; - max-width:600px!important; - margin:0 auto!important; /* makes it centered */ - clear:both!important; -} - -/* This should also be a block element, so that it will fill 100% of the .container */ -.content { - padding:15px; - max-width:600px; - margin:0 auto; - display:block; -} - -/* Let's make sure tables in the content area are 100% wide */ -.content table { width: 100%; } - - -/* Odds and ends */ -.column { - width: 300px; - float:left; -} -.column tr td { padding: 15px; } -.column-wrap { - padding:0!important; - margin:0 auto; - max-width:600px!important; -} -.column table { width:100%;} -.social .column { - width: 280px; - min-width: 279px; - float:left; -} -.column-large { - width: 550px; - margin:0 auto; - padding-left: 10px; -} -/* Be sure to place a .clear element after each set of columns, just to be safe */ -.clear { display: block; clear: both; } - - -/* ------------------------------------------- - PHONE - For clients that support media queries. - Nothing fancy. --------------------------------------------- */ -@media only screen and (max-width: 600px) { - - a[class="btn"] { display:block!important; margin-bottom:10px!important; background-image:none!important; margin-right:0!important;} - - div[class="column"] { width: auto!important; float:none!important;} - - table.social div[class="column"] { - width:auto!important; - } - -} diff --git a/tests/mocks/addons/new-messages-template-pack/templates/variations/email_preview_default.css b/tests/mocks/addons/new-messages-template-pack/templates/variations/email_preview_default.css deleted file mode 100644 index cc2b630ba95..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/variations/email_preview_default.css +++ /dev/null @@ -1,239 +0,0 @@ -/* ------------------------------------- - Attention! This CSS file is used for generating the preview messages. -------------------------------------- */ -/* ------------------------------------- - GLOBAL -------------------------------------- */ -#ee-message-preview-container * { - margin:0; - padding:0; -} -#ee-message-preview-container * { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; } - -#ee-message-preview-container img { - max-width: 100%; -} -#ee-message-preview-container .collapse { - margin:0; - padding:0; -} -#ee-message-preview-container body { - -webkit-font-smoothing:antialiased; - -webkit-text-size-adjust:none; - width: 100%!important; - height: 100%; -} - - -/* ------------------------------------- - ELEMENTS -------------------------------------- */ -#ee-message-preview-container a { color: #2BA6CB;} - -#ee-message-preview-container .btn { - text-decoration:none; - color: #FFF; - background-color: #666; - padding:10px 16px; - font-weight:bold; - margin-right:10px; - text-align:center; - cursor:pointer; - display: inline-block; -} - -#ee-message-preview-container p.callout { - padding:15px; - background-color:#ECF8FF; - margin-bottom: 15px; -} -#ee-message-preview-container .callout a { - font-weight:bold; - color: #2BA6CB; -} - -#ee-message-preview-container table.social { -/* padding:15px; */ - background-color: #ebebeb; - -} -#ee-message-preview-container .social .soc-btn { - padding: 3px 7px; - font-size:12px; - margin-bottom:10px; - text-decoration:none; - color: #FFF;font-weight:bold; - display:block; - text-align:center; -} -#ee-message-preview-container a.fb { background-color: #3B5998!important; } -#ee-message-preview-container a.tw { background-color: #1daced!important; } -#ee-message-preview-container a.gp { background-color: #DB4A39!important; } -#ee-message-preview-container a.ms { background-color: #000!important; } - -#ee-message-preview-container .sidebar .soc-btn { - display:block; - width:100%; -} - -/* ------------------------------------- - HEADER -------------------------------------- */ -#ee-message-preview-container table.head-wrap { width: 100%;} - -#ee-message-preview-container .header.container table td.logo { padding: 15px; } -#ee-message-preview-container .header.container table td.label { padding: 15px; padding-left:0px;} - - -/* ------------------------------------- - BODY -------------------------------------- */ -#ee-message-preview-container table.body-wrap { width: 100%;} - - -/* ------------------------------------- - FOOTER -------------------------------------- */ -#ee-message-preview-container table.footer-wrap { width: 100%; clear:both!important; -} -#ee-message-preview-container .footer-wrap .container td.content p { border-top: 1px solid rgb(215,215,215); padding-top:15px;} -#ee-message-preview-container .footer-wrap .container td.content p { - font-size:10px; - font-weight: bold; - -} - - -/* ------------------------------------- - TYPOGRAPHY -------------------------------------- */ -#ee-message-preview-container h1,#ee-message-preview-container h2,#ee-message-preview-container h3,#ee-message-preview-container h4,#ee-message-preview-container h5,#ee-message-preview-container h6 { -font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; padding-bottom:15px; padding-top:10px; color:#000; -} -#ee-message-preview-container h1 small, #ee-message-preview-container h2 small, #ee-message-preview-container h3 small, #ee-message-preview-container h4 small, #ee-message-preview-container h5 small, #ee-message-preview-container h6 small { font-size: 60%; color: #6f6f6f; line-height: 0; text-transform: none; } - -#ee-message-preview-container h1 { font-weight:200; font-size: 36px;} -#ee-message-preview-container h2 { font-weight:200; font-size: 30px;} -#ee-message-preview-container h3 { font-weight:500; font-size: 24px;} -#ee-message-preview-container h4 { font-weight:500; font-size: 19px;} -#ee-message-preview-container h5 { font-weight:900; font-size: 16px;} -#ee-message-preview-container h6 { font-weight:900; font-size: 14px; text-transform: uppercase; color:#444;} -#ee-message-preview-container h4.attendee-name {margin: 10px 0;} -#ee-message-preview-container .collapse { margin:0!important;} - -#ee-message-preview-container p, #ee-message-preview-container ul { - margin-bottom: 10px; - font-weight: normal; - font-size:14px; - line-height:1.6; -} -#ee-message-preview-container p.lead { font-size:17px; } -#ee-message-preview-container p.last { margin-bottom:0px;} - -#ee-message-preview-container ul li { - margin-left:5px; - padding-bottom: 5px; - list-style-position: inside; - list-style-type: none; -} -#ee-message-preview-container ol.datetime-list li { - margin-left:10px; - padding-bottom: 5px; - list-style-position: inside; - list-style-type: none; -} -#ee-message-preview-container li.ticket-name em {padding-left: 15px;} -#ee-message-preview-container hr { - margin: 10px 0; -} - -/* ------------------------------------- - SIDEBAR -------------------------------------- */ -#ee-message-preview-container ul.sidebar { - background:#ebebeb; - display:block; - list-style-type: none; -} -#ee-message-preview-container ul.sidebar li { display: block; margin:0; padding:10px 16px;} -#ee-message-preview-container ul.sidebar li h5 { - text-decoration:none; - color: #000; - padding:10px 0 20px 0; - display:block; - margin:0; -} -#ee-message-preview-container ul.sidebar li a.last { border-bottom-width:0px;} -#ee-message-preview-container ul.sidebar li a h1,#ee-message-preview-container ul.sidebar li a h2,#ee-message-preview-container ul.sidebar li a h3,#ee-message-preview-container ul.sidebar li a h4,#ee-message-preview-container ul.sidebar li a h5,#ee-message-preview-container ul.sidebar li a h6,#ee-message-preview-container ul.sidebar li a p { margin-bottom:0!important;} - - - -/* --------------------------------------------------- - RESPONSIVENESS - Nuke it from orbit. It's the only way to be sure. ------------------------------------------------------- */ - -/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */ -#ee-message-preview-container .container { - display:block!important; - max-width:600px!important; - margin:0 auto!important; /* makes it centered */ - clear:both!important; -} - -/* This should also be a block element, so that it will fill 100% of the .container */ -#ee-message-preview-container .content { - padding:15px; - max-width:600px; - margin:0 auto; - display:block; -} - -/* Let's make sure tables in the content area are 100% wide */ -#ee-message-preview-container .content table { width: 100%; } - - -/* Odds and ends */ -#ee-message-preview-container .column { - width: 300px; - float:left; -} -#ee-message-preview-container .column tr td { padding: 15px; } -#ee-message-preview-container .column-wrap { - padding:0!important; - margin:0 auto; - max-width:600px!important; -} -#ee-message-preview-container .column table { width:100%;} -#ee-message-preview-container .social .column { - width: 280px; - min-width: 279px; - float:left; -} - -#ee-message-preview-container .column-large { - width: 550px; - margin:0 auto; - padding-left: 10px; -} - -/* Be sure to place a .clear element after each set of columns, just to be safe */ -.clear { display: block; clear: both; } - - -/* ------------------------------------------- - PHONE - For clients that support media queries. - Nothing fancy. --------------------------------------------- */ -@media only screen and (max-width: 600px) { - - #ee-message-preview-container a[class="btn"] { display:block!important; margin-bottom:10px!important; background-image:none!important; margin-right:0!important;} - - #ee-message-preview-container div[class="column"] { width: auto!important; float:none!important;} - - #ee-message-preview-container table.social div[class="column"] { - width:auto!important; - } - -} diff --git a/tests/mocks/addons/new-messages-template-pack/templates/variations/email_wpeditor_default.css b/tests/mocks/addons/new-messages-template-pack/templates/variations/email_wpeditor_default.css deleted file mode 100644 index 240a7df0e89..00000000000 --- a/tests/mocks/addons/new-messages-template-pack/templates/variations/email_wpeditor_default.css +++ /dev/null @@ -1,224 +0,0 @@ -/* ------------------------------------- - GLOBAL -------------------------------------- */ -.mceContentBody * { - margin:0; - padding:0; -} -.mceContentBody * { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; } - -.mceContentBody img { - max-width: 100%; -} -.mceContentBody .collapse { - margin:0; - padding:0; -} -.mceContentBody body { - -webkit-font-smoothing:antialiased; - -webkit-text-size-adjust:none; - width: 100%!important; - height: 100%; -} - - -/* ------------------------------------- - ELEMENTS -------------------------------------- */ -.mceContentBody a { color: #2BA6CB;} - -.mceContentBody .btn { - text-decoration:none; - color: #FFF; - background-color: #666; - padding:10px 16px; - font-weight:bold; - margin-right:10px; - text-align:center; - cursor:pointer; - display: inline-block; -} - -.mceContentBody p.callout { - padding:15px; - background-color:#ECF8FF; - margin-bottom: 15px; -} -.mceContentBody .callout a { - font-weight:bold; - color: #2BA6CB; -} - -.mceContentBody table.social { -/* padding:15px; */ - background-color: #ebebeb; - -} -.mceContentBody .social .soc-btn { - padding: 3px 7px; - font-size:12px; - margin-bottom:10px; - text-decoration:none; - color: #FFF;font-weight:bold; - display:block; - text-align:center; -} -.mceContentBody a.fb { background-color: #3B5998!important; } -.mceContentBody a.tw { background-color: #1daced!important; } -.mceContentBody a.gp { background-color: #DB4A39!important; } -.mceContentBody a.ms { background-color: #000!important; } - -.mceContentBody .sidebar .soc-btn { - display:block; - width:100%; -} - -/* ------------------------------------- - HEADER -------------------------------------- */ -.mceContentBody table.head-wrap { width: 100%;} - -.mceContentBody .header.container table td.logo { padding: 15px; } -.mceContentBody .header.container table td.label { padding: 15px; padding-left:0px;} - - -/* ------------------------------------- - BODY -------------------------------------- */ -.mceContentBody table.body-wrap { width: 100%;} - - -/* ------------------------------------- - FOOTER -------------------------------------- */ -.mceContentBody table.footer-wrap { width: 100%; clear:both!important; -} -.mceContentBody .footer-wrap .container td.content p { border-top: 1px solid rgb(215,215,215); padding-top:15px;} -.mceContentBody .footer-wrap .container td.content p { - font-size:10px; - font-weight: bold; - -} - - -/* ------------------------------------- - TYPOGRAPHY -------------------------------------- */ -.mceContentBody h1,.mceContentBody h2,.mceContentBody h3,.mceContentBody h4,.mceContentBody h5,.mceContentBody h6 { -font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; color:#000; -} -.mceContentBody h1 small, .mceContentBody h2 small, .mceContentBody h3 small, .mceContentBody h4 small, .mceContentBody h5 small, .mceContentBody h6 small { font-size: 60%; color: #6f6f6f; line-height: 0; text-transform: none; } - -.mceContentBody h1 { font-weight:200; font-size: 44px;} -.mceContentBody h2 { font-weight:200; font-size: 37px;} -.mceContentBody h3 { font-weight:500; font-size: 27px;} -.mceContentBody h4 { font-weight:500; font-size: 23px;} -.mceContentBody h5 { font-weight:900; font-size: 17px;} -.mceContentBody h6 { font-weight:900; font-size: 14px; text-transform: uppercase; color:#444;} - -.mceContentBody .collapse { margin:0!important;} - -.mceContentBody p, .mceContentBody ul { - margin-bottom: 10px; - font-weight: normal; - font-size:14px; - line-height:1.6; -} -.mceContentBody p.lead { font-size:17px; } -.mceContentBody p.last { margin-bottom:0px;} - -.mceContentBody ul li { - margin-left:5px; - list-style-position: inside; -} - -/* ------------------------------------- - SIDEBAR -------------------------------------- */ -.mceContentBody ul.sidebar { - background:#ebebeb; - display:block; - list-style-type: none; -} -.mceContentBody ul.sidebar li { display: block; margin:0;} -.mceContentBody ul.sidebar li a { - text-decoration:none; - color: #666; - padding:10px 16px; -/* font-weight:bold; */ - margin-right:10px; -/* text-align:center; */ - cursor:pointer; - border-bottom: 1px solid #777777; - border-top: 1px solid #FFFFFF; - display:block; - margin:0; -} -.mceContentBody ul.sidebar li a.last { border-bottom-width:0px;} -.mceContentBody ul.sidebar li a h1,.mceContentBody ul.sidebar li a h2,.mceContentBody ul.sidebar li a h3,.mceContentBody ul.sidebar li a h4,.mceContentBody ul.sidebar li a h5,.mceContentBody ul.sidebar li a h6,.mceContentBody ul.sidebar li a p { margin-bottom:0!important;} - - - -/* --------------------------------------------------- - RESPONSIVENESS - Nuke it from orbit. It's the only way to be sure. ------------------------------------------------------- */ - -/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */ -.mceContentBody .container { - display:block!important; - max-width:600px!important; - margin:0 auto!important; /* makes it centered */ - clear:both!important; -} - -/* This should also be a block element, so that it will fill 100% of the .container */ -.mceContentBody .content { - padding:15px; - max-width:600px; - margin:0 auto; - display:block; -} - -/* Let's make sure tables in the content area are 100% wide */ -.mceContentBody .content table { width: 100%; } - - -/* Odds and ends */ -.mceContentBody .column { - width: 300px; - float:left; -} -.mceContentBody .column tr td { padding: 15px; } -.mceContentBody .column-wrap { - padding:0!important; - margin:0 auto; - max-width:600px!important; -} -.mceContentBody .column table { width:100%;} -.mceContentBody .social .column { - width: 280px; - min-width: 279px; - float:left; -} - -/* Be sure to place a .clear element after each set of columns, just to be safe */ -.clear { display: block; clear: both; } - - -/* ------------------------------------------- - PHONE - For clients that support media queries. - Nothing fancy. --------------------------------------------- */ -@media only screen and (max-width: 600px) { - - .mceContentBody a[class="btn"] { display:block!important; margin-bottom:10px!important; background-image:none!important; margin-right:0!important;} - - .mceContentBody div[class="column"] { width: auto!important; float:none!important;} - - .mceContentBody table.social div[class="column"] { - width:auto!important; - } - -} diff --git a/tests/mocks/addons/new-payment-method/.gitignore b/tests/mocks/addons/new-payment-method/.gitignore deleted file mode 100644 index 85e7c1dfcb7..00000000000 --- a/tests/mocks/addons/new-payment-method/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/.idea/ diff --git a/tests/mocks/addons/new-payment-method/EE_New_Payment_Method.class.php b/tests/mocks/addons/new-payment-method/EE_New_Payment_Method.class.php deleted file mode 100644 index 974f94f0ac3..00000000000 --- a/tests/mocks/addons/new-payment-method/EE_New_Payment_Method.class.php +++ /dev/null @@ -1,91 +0,0 @@ - EE_NEW_PAYMENT_METHOD_VERSION, - 'min_core_version' => '4.6.0.dev.000', - 'main_file_path' => EE_NEW_PAYMENT_METHOD_PLUGIN_FILE, - 'admin_callback' => 'additional_admin_hooks', - // if plugin update engine is being used for auto-updates. not needed if PUE is not being used. - 'pue_options' => array( - 'pue_plugin_slug' => 'espresso_new_payment_method', - 'plugin_basename' => EE_NEW_PAYMENT_METHOD_BASENAME, - 'checkPeriod' => '24', - 'use_wp_update' => FALSE, - ), - 'payment_method_paths' => array( - EE_NEW_PAYMENT_METHOD_PATH . 'payment_methods' . DS . 'New_Payment_Method_Onsite', - EE_NEW_PAYMENT_METHOD_PATH . 'payment_methods' . DS . 'New_Payment_Method_Offsite', - ), - )); - } - - - - /** - * additional_admin_hooks - * - * @access public - * @return void - */ - public function additional_admin_hooks() { - // is admin and not in M-Mode ? - if ( is_admin() && ! EE_Maintenance_Mode::instance()->level() ) { - add_filter( 'plugin_action_links', array( $this, 'plugin_actions' ), 10, 2 ); - } - } - - - - /** - * plugin_actions - * - * Add a settings link to the Plugins page, so people can go straight from the plugin page to the settings page. - * @param $links - * @param $file - * @return array - */ - public function plugin_actions( $links, $file ) { - if ( $file == EE_NEW_PAYMENT_METHOD_BASENAME ) { - // before other links - array_unshift( $links, '' . __('Settings') . '' ); - } - return $links; - } - - - - - - -} -// End of file EE_New_Payment_Method.class.php -// Location: wp-content/plugins/espresso-new-payment-method/EE_New_Payment_Method.class.php diff --git a/tests/mocks/addons/new-payment-method/LICENSE b/tests/mocks/addons/new-payment-method/LICENSE deleted file mode 100644 index 22fbe5dbacb..00000000000 --- a/tests/mocks/addons/new-payment-method/LICENSE +++ /dev/null @@ -1,339 +0,0 @@ -GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - {description} - Copyright (C) {year} {fullname} - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - {signature of Ty Coon}, 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. \ No newline at end of file diff --git a/tests/mocks/addons/new-payment-method/README.md b/tests/mocks/addons/new-payment-method/README.md deleted file mode 100644 index eee0c4a4a36..00000000000 --- a/tests/mocks/addons/new-payment-method/README.md +++ /dev/null @@ -1,7 +0,0 @@ -New EE4 Addon Starter Template -========= - -A set of files and classes to use as a template for creating a New Event Espresso Addon - -This plugin/addon needs to be uploaded to the "/wp-content/plugins/" directory on your server or installed using the WordPress plugins installer. - diff --git a/tests/mocks/addons/new-payment-method/circle.yml b/tests/mocks/addons/new-payment-method/circle.yml deleted file mode 100644 index 097e7761ed1..00000000000 --- a/tests/mocks/addons/new-payment-method/circle.yml +++ /dev/null @@ -1,48 +0,0 @@ -## Customize the test machine -machine: - - timezone: - America/Denver # Set the timezone - - # Version of php to use - php: - version: 5.4.21 - - # Add some environment variables - environment: - CIRCLE_ENV: test - WP_VERSION: 3.8.1 - WP_MULTISITE: 0 - WP_CORE_DIR: /home/ubuntu/wordpress-develop - WP_TESTS_DIR: /home/ubuntu/wordpress-develop/tests/phpunit - plugin_loc: /home/ubuntu/$CIRCLE_PROJECT_REPONAME - plugin_slug: $CIRCLE_PROJECT_REPONAME - plugin_dir: /home/ubuntu/wordpress-develop/src/wp-content/plugins/$plugin_slug - plugin_tests_dir: /home/ubuntu/wordpress-develop/src/wp-content/plugins/$plugin_slug/tests - event_espresso_core_dir: /home/ubuntu/wordpress-develop/src/wp-content/plugins/event-espresso-core - - -## Customize dependencies -dependencies: - pre: - #setup WP install - - git clone git://develop.git.wordpress.org/ $WP_CORE_DIR; - - cd $WP_CORE_DIR && cp wp-tests-config-sample.php wp-tests-config.php && sed -i "s/youremptytestdbnamehere/wordpress_test/" wp-tests-config.php && sed -i "s/yourusernamehere/root/" wp-tests-config.php && sed -i "s/yourpasswordhere//" wp-tests-config.php; - # move plugin into tests/src - - mv $plugin_loc $plugin_dir; - #pull in event-espresso-core master branch - #note by using $CIRCLE_BRANCH the addon is being tested against the corresponding branch of event-espresso-core. So development branch of addon will be development branch of core. - - git clone git@github.com:eventespresso/event-espresso-core.git $event_espresso_core_dir; - - cd $event_espresso_core_dir; git checkout $CIRCLE_BRANCH; - # set up database - - mysql -e 'CREATE DATABASE wordpress_test;' -uroot; - # setup phpunit - - wget https://phar.phpunit.de/phpunit.phar && chmod +x phpunit.phar && mv phpunit.phar /home/ubuntu/.phpenv/shims/phpunit - -##tests override. Note you'll want to make sure that the addon is tested against all ee core main branches. -test: - override: - - cd $event_espresso_core_dir; git checkout development; cd $plugin_tests_dir; phpunit -d display_errors=On - - cd $event_espresso_core_dir; git checkout alpha; cd $plugin_tests_dir; phpunit -d display_errors=On - - cd $event_espresso-core_dir; git checkout beta; cd $plugin_tests_dir; phpunit -d display_errors=On - - cd $event_espresso_core_dir; git checkout master; cd $plugin_tests_dir; phpunit -d display_errors=On diff --git a/tests/mocks/addons/new-payment-method/css/espresso_new_payment_method.css b/tests/mocks/addons/new-payment-method/css/espresso_new_payment_method.css deleted file mode 100644 index e27c3235b25..00000000000 --- a/tests/mocks/addons/new-payment-method/css/espresso_new_payment_method.css +++ /dev/null @@ -1,25 +0,0 @@ -/* ------------------------------------------------------------------------- - * Event Espresso New_Payment_Method Stylesheet - * (c) 2014 Event Espresso - * -------------------------------------------------------------------------*/ - -/* -General Styles ----------------------------------------------------------------------------------------------------- */ - - -/* Media Query for screens smaller then 768px (iPad portrait) ----------------------------------------------------------------------------------------------------- */ - -@media only screen and (max-width: 767px) { -} - -@media only screen and (max-width: 600px) and (min-width: 481px) { -} - -@media only screen and (max-width: 540px) and (min-width: 480px) { -} - -@media only screen and (max-width: 480px) { -} - diff --git a/tests/mocks/addons/new-payment-method/css/index.php b/tests/mocks/addons/new-payment-method/css/index.php deleted file mode 100644 index 0dc63376116..00000000000 --- a/tests/mocks/addons/new-payment-method/css/index.php +++ /dev/null @@ -1,2 +0,0 @@ -set_uses_separate_IPN_request( false ) ; - parent::__construct(); - } - - /** - * Override's parent so this gateway integration class can act like one that uses - * a separate IPN or not, depending on what is set in the payment methods settings form - * @return boolean - */ - public function uses_separate_IPN_request() { - if( $this->_override_use_separate_IPN_request !== null ) { - $this->set_uses_separate_IPN_request( $this->_override_use_separate_IPN_request ); - } - return parent::uses_separate_IPN_request(); - } - - /** - * - * @param arrat $update_info { - * @type string $gateway_txn_id - * @type string status an EEMI_Payment status - * } - * @param type $transaction - * @return EEI_Payment - */ - public function handle_payment_update($update_info, $transaction) { - if( ! isset( $update_info[ 'gateway_txn_id' ] ) ){ - return NULL; - } - $payment = $this->_pay_model->get_payment_by_txn_id_chq_nmbr($update_info[ 'gateway_txn_id' ] ); - if($payment instanceof EEI_Payment && isset( $update_info[ 'status' ] ) ){ - if( $update_info[ 'status' ] == $this->_pay_model->approved_status() ){ - $payment->set_status( $this->_pay_model->approved_status() ); - $payment->set_gateway_response( __( 'Payment Approved', 'event_espresso' )); - }elseif( $update_info[ 'status' ] == $this->_pay_model->pending_status() ){ - $payment->set_status( $this->_pay_model->pending_status() ); - $payment->set_gateway_response( __( 'Payment Pending', 'event_espresso' )); - }else{ - $payment->set_status( $this->_pay_model->failed_status() ); - $payment->set_gateway_response( __( 'Payment Failed', 'event_espresso' ) ); - } - } - return $payment; - } - - /** - * - * @param EEI_Payment $payment - * @param type $billing_info - * @param type $return_url - * @param type $cancel_url - */ - public function set_redirection_info($payment, $billing_info = array(), $return_url = NULL, $notify_url = NULL, $cancel_url = NULL) { - global $auto_made_thing_seed; - if( empty( $auto_made_thing_seed ) ) { - $auto_made_thing_seed = rand(1,1000000); - } - $payment->set_txn_id_chq_nmbr( $auto_made_thing_seed++ ); - - $payment->set_redirect_url( EE_NEW_PAYMENT_METHOD_URL . DS . 'payment_methods' . DS . 'New_Payment_Method_Offsite' . DS . 'pretend_offsite_page.php' ); - $payment->set_redirect_args( array( - 'amount' => $payment->amount(), - 'gateway_txn_id' => $payment->txn_id_chq_nmbr(), - 'return_url' => $return_url, - 'uses_separate_IPN_request' => $this->uses_separate_IPN_request(), - 'ipn_url' => $notify_url, - )); - return $payment; - } -} - -// End of file EEG_Mock_Onsite.php \ No newline at end of file diff --git a/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Offsite/EE_PMT_New_Payment_Method_Offsite.pm.php b/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Offsite/EE_PMT_New_Payment_Method_Offsite.pm.php deleted file mode 100644 index afa7bdfbfad..00000000000 --- a/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Offsite/EE_PMT_New_Payment_Method_Offsite.pm.php +++ /dev/null @@ -1,78 +0,0 @@ -file_folder().'EEG_New_Payment_Method_Offsite.gateway.php'); - $this->_gateway = new EEG_New_Payment_Method_Offsite(); - $this->_pretty_name = __("New Payment Method Offsite", 'event_espresso'); - parent::__construct($pm_instance); - } - - /** - * Adds the help tab - * @see EE_PMT_Base::help_tabs_config() - * @return array - */ - public function help_tabs_config(){ - return array( - $this->get_help_tab_name() => array( - 'title' => __('New Payment Method Offsite Settings', 'event_espresso'), - 'filename' => 'new_payment_method_offsite', - 'template_args' => array( - 'variable_x' => 'VARIABLE X', - ) - ), - ); - } - - - - /** - * Creates the billing form for this payment method type - * @param \EE_Transaction $transaction - * @return NULL - */ - public function generate_new_billing_form( EE_Transaction $transaction = NULL ) { - return NULL; - } - - /** - * Gets the form for all the settings related to this payment method type - * @return EE_Payment_Method_Form - */ - public function generate_new_settings_form() { - $form = new EE_Payment_Method_Form(array( - 'extra_meta_inputs'=>array( - 'login_id'=>new EE_Text_Input(array( - 'html_label_text'=> sprintf(__("Login ID %s", "event_espresso"), $this->get_help_tab_link() ) - )), - 'override_use_separate_IPN_request' => new EE_Yes_No_Input( array( - 'html_label_text' => __('Use Separate IPN', 'event_espresso'), - 'html_help_text' => __( 'Instruct the gateway to send a separate IPN request, or send payment data back with the user upon return.', 'event_espresso' ), - ))))); - return $form; - } - -} - -// End of file EE_PMT_Onsite.php \ No newline at end of file diff --git a/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Offsite/help_tabs/index.php b/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Offsite/help_tabs/index.php deleted file mode 100644 index 0dc63376116..00000000000 --- a/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Offsite/help_tabs/index.php +++ /dev/null @@ -1,2 +0,0 @@ -

-

- -

-

- -

-

-
    -
  • -
    - -
  • -
  • -
    - -
  • -
  • -
    - -
  • -
  • -
    - -
  • -
\ No newline at end of file diff --git a/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Offsite/index.php b/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Offsite/index.php deleted file mode 100644 index 0dc63376116..00000000000 --- a/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Offsite/index.php +++ /dev/null @@ -1,2 +0,0 @@ -Welcome to the Pretend Offsite Page. -

This page is actually hosted locally, just not accessed through Wordpress (it's a static php file).

-

If you are making your own offsite payment gateway integration you obviously dont need this file and should delete it.

- -
- -
- '>
- - (then press back in your browser and return to this page, and then Return to Event Espresso to view your transaction) - - - -
\ No newline at end of file diff --git a/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Offsite/templates/new_payment_method_offsite_intro.template.php b/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Offsite/templates/new_payment_method_offsite_intro.template.php deleted file mode 100644 index e09f680c848..00000000000 --- a/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Offsite/templates/new_payment_method_offsite_intro.template.php +++ /dev/null @@ -1,7 +0,0 @@ -log( $billing_info, $payment ); - switch( $billing_info[ 'status' ] ){ - case 'Approved': - $payment->set_status( $this->_pay_model->approved_status() ); - $payment->set_gateway_response( "Payment accepted"); - break; - case 'Pending': - $payment->set_status( $this->_pay_model->pending_status() ); - $payment->set_gateway_response( "WE are on vacation, we will process your payment when we get back."); - break; - case 'Declined': - $payment->set_status( $this->_pay_model->declined_status() ); - $payment->set_gateway_response( "You don't have enough spunk, payment was declined"); - break; - case 'Failed': - $payment->set_status( $this->_pay_model->failed_status() ); - $payment->set_gateway_response( "Mice got into our servers. The exterminator will be over after he finishes his day job. Sorry"); - } - return $payment; - } -} - -// End of file EEG_New_Payment_Method_Onsite.php \ No newline at end of file diff --git a/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Onsite/EE_PMT_New_Payment_Method_Onsite.pm.php b/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Onsite/EE_PMT_New_Payment_Method_Onsite.pm.php deleted file mode 100644 index c3be8fd7eab..00000000000 --- a/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Onsite/EE_PMT_New_Payment_Method_Onsite.pm.php +++ /dev/null @@ -1,98 +0,0 @@ -file_folder().'EEG_New_Payment_Method_Onsite.gateway.php'); - $this->_gateway = new EEG_New_Payment_Method_Onsite(); - $this->_pretty_name = __("New Payment Method Onsite", 'event_espresso'); - $this->_requires_https = true; - parent::__construct($pm_instance); - } - - /** - * Adds the help tab - * @see EE_PMT_Base::help_tabs_config() - * @return array - */ - public function help_tabs_config(){ - return array( - $this->get_help_tab_name() => array( - 'title' => __('New Payment Method Onsite Settings', 'event_espresso'), - 'filename' => 'new_payment_method_onsite' - ), - ); - } - - /** - * @param \EE_Transaction $transaction - * @return \EE_Billing_Attendee_Info_Form - */ - public function generate_new_billing_form( EE_Transaction $transaction = null ) { - $form = new EE_Billing_Attendee_Info_Form( $this->_pm_instance, array( - 'name' => 'New_Payment_Method_Onsite_Form', - 'subsections' => array( - //this will become the payments status when processing payments on this mock object - 'status' => new EE_Select_Input( - array( - 'Approved' => 'Approved', - 'Pending' => 'Pending', - 'Declined' => 'Declined', - 'Failed' => 'Failed' - ), - array( 'html_help_text' => __( 'What the payment status will be set to', 'event_espresso' ) ) - ), - 'credit_card' => new EE_Credit_Card_Input( array( - 'required' => false, - 'html_label_text' => __( 'Credit Card', 'event_espresso' ), - ) ), - 'exp_month' => new EE_Credit_Card_Month_Input( true, array( - 'required' => false, - 'html_label_text' => __( 'Expiry Month', 'event_espresso' ) - ) ), - 'exp_year' => new EE_Credit_Card_Year_Input( array( - 'required' => false, - 'html_label_text' => __( 'Expiry Year', 'event_espresso' ), - ) ), - 'cvv' => new EE_CVV_Input( array( - 'required' => false, - 'html_label_text' => __( 'CVV', 'event_espresso' ) - ) ), - ) - ) ); - return $form; - } - - /** - * Gets the form for all the settings related to this payment method type - * @return EE_Payment_Method_Form - */ - public function generate_new_settings_form() { - $form = new EE_Payment_Method_Form(array( - 'extra_meta_inputs'=>array( - 'login_id'=>new EE_Text_Input(array( - 'html_label_text'=> sprintf(__("Login ID %s", "event_espresso"), $this->get_help_tab_link() ) - ))))); - return $form; - } -} -// End of file EE_PMT_Onsite.php \ No newline at end of file diff --git a/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Onsite/help_tabs/index.php b/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Onsite/help_tabs/index.php deleted file mode 100644 index 0dc63376116..00000000000 --- a/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Onsite/help_tabs/index.php +++ /dev/null @@ -1,2 +0,0 @@ -

-

- -

-

- -

-

-
    -
  • -
    - -
  • -
  • -
    - -
  • -
  • -
    - -
  • -
\ No newline at end of file diff --git a/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Onsite/index.php b/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Onsite/index.php deleted file mode 100644 index 0dc63376116..00000000000 --- a/tests/mocks/addons/new-payment-method/payment_methods/New_Payment_Method_Onsite/index.php +++ /dev/null @@ -1,2 +0,0 @@ - - - - ./testcases/ - - - diff --git a/tests/mocks/addons/new-payment-method/tests/testcases/espresso_addon_skeleton.php b/tests/mocks/addons/new-payment-method/tests/testcases/espresso_addon_skeleton.php deleted file mode 100644 index e5ed014401d..00000000000 --- a/tests/mocks/addons/new-payment-method/tests/testcases/espresso_addon_skeleton.php +++ /dev/null @@ -1,29 +0,0 @@ -assertEquals( has_action('AHEE__EE_System__load_espresso_addons', 'load_espresso_new_payment_method'), 10 ); - $this->assertTrue( class_exists( 'EE_New_Payment_Method' ) ); - } -} diff --git a/tests/mocks/admin/EE_Admin_Mocks.php b/tests/mocks/admin/EE_Admin_Mocks.php deleted file mode 100644 index 9d9348410b0..00000000000 --- a/tests/mocks/admin/EE_Admin_Mocks.php +++ /dev/null @@ -1,208 +0,0 @@ -load_core('Admin_Page'); -EE_Registry::instance()->load_core('Admin_Hooks'); -EE_Registry::instance()->load_core('Admin_Page_Init'); - -/** - * Mocks an invalid hooks class - * - * @since 4.3.0 - */ -class dummy_not_exist_Hooks extends EE_Admin_Hooks { - protected function _set_hooks_properties() { - $this->_name = NULL; - } - - public function verify_page_object() { - return $this->_page_object; - } -} - - - -/** - * Mocks a valid hooks class - * - * @since 4.3.0 - */ -class mock_valid_admin_page_Admin_Mock_Valid_Hooks extends EE_Admin_Hooks { - - public $extended_properties = FALSE; - public $route_callback = FALSE; - public $redirect_action_early_callback = FALSE; - public $redirect_action_callback = FALSE; - public $redirect_filter_callback = FALSE; - public $default_admin_callback = FALSE; - public $FHEE_list_table_views_route_callback = FALSE; - public $FHEE_list_table_views_page_callback = FALSE; - public $FHEE_list_table_views_global_callback = FALSE; - public $modify_metaboxes_callback = FALSE; - public $ajax_test = FALSE; - - protected function _set_hooks_properties() { - $this->_name = 'admin_mock_valid'; - $this->_init_func = array( - 'default' => 'init_callback_test' - ); - $this->_ajax_func = array( - 'ajax_test' => 'ajax_test_callback' - ); - $this->_metaboxes = array( - 0 => array( - 'page_route' => array('default'), - 'func' => 'test_metabox', - 'label' => __('Test Metabox', 'event_espresso'), - 'priority' => 'high', - 'context' => 'normal' - ) - ); - $this->_scripts_styles = array( - 'registers' => array( - 'test-css' => array( - 'url' => 'test.css', - 'type' => 'css' - ), - 'test-js' => array( - 'url' => 'test.js', - 'depends' => array('jquery') - ) - ), - 'deregisters' => array( - 'event-editor-css' => array('type' => 'css' ) - ), - 'enqueues' => array( - 'test-css' => array( 'default' ), - 'test-js' => array( 'default' ) - ), - 'localize' => array( - 'test-js' => array( - 'TEST_ITEM' => 'this is a test' ) - ) - ); - } - - public function test_metabox() { - return true; - } - - protected function _extend_properties() { - $this->extended_properties = TRUE; - } - - - public function verify_adminpage_obj() { - return $this->_adminpage_obj; - } - - public function verify_page_object() { - return $this->_page_object; - } - - public function verify_current_route() { - return $this->_current_route; - } - - - public function verify_extend() { - return $this->_extend; - } - - public function init_callback_test() { - return true; - } - - public function default_callback() { - $this->route_callback = TRUE; - } - - public function _redirect_action_early_default() { - $this->redirect_action_early_callback = TRUE; - } - - public function _redirect_action_default() { - $this->redirect_action_callback = TRUE; - } - - public function _redirect_filter_default() { - $this->redirect_filter_callback = TRUE; - } - - - public function default_admin_footer() { - $this->default_admin_callback = TRUE; - } - - public function default_FHEE_list_table_views_mock_valid_admin_page_default() { - $this->FHEE_list_table_views_route_callback = TRUE; - } - - public function default_FHEE_list_table_views_mock_valid_admin_page() { - $this->FHEE_list_table_views_page_callback = TRUE; - } - - public function default_FHEE_list_table_views() { - $this->FHEE_list_table_views_global_callback = TRUE; - } - - public function default_AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes() { - $this->modify_metaboxes_callback = TRUE; - } - - public function ajax_test_callback() { - $this->ajax_test = TRUE; - } - - - /** - * Method for setting protected properties for testing - * - * @since 4.3.0 - * - * @param string $property The name of the property to set - * @param mixed $value The value to give the property - */ - public function set_property( $property = '', $value = NULL ) { - $this->{$property} = $value; - } - - - - /** - * Method for getting protected properties for testing - * - * @since 4.3.0 - * - * @param string $property The name of the property to get.] - * @return mixed - */ - public function get_property( $property = '' ) { - return $this->{$property}; - } - - - /** - * wrapper for calling protected/private methods. - * - * @since 4.3.0 - * - * @param string $method the protected method - * to call - * @return mixed - */ - public function call_method( $method ) { - return $this->{$method}(); - } -} diff --git a/tests/mocks/admin/admin_mock_valid/Admin_Mock_Valid_Admin_Page.core.php b/tests/mocks/admin/admin_mock_valid/Admin_Mock_Valid_Admin_Page.core.php deleted file mode 100644 index 765fe0a94a1..00000000000 --- a/tests/mocks/admin/admin_mock_valid/Admin_Mock_Valid_Admin_Page.core.php +++ /dev/null @@ -1,58 +0,0 @@ -page_slug = 'mock_valid_admin_page'; - $this->page_label = __('Mock Valid Admin Page'); - $this->_admin_base_url = admin_url('admin.php?page=mock_valid_admin_page'); - $this->_admin_base_path = dirname( __FILE__ ); - } - - protected function _define_page_props() { - $this->_admin_page_title = $this->page_label; - $this->_labels = array( - 'label' => __('Some Label') - ); - } - - - protected function _set_page_routes() { - $this->_page_routes = array( - 'default' => 'default_route_callback' - ); - } - - - - protected function _set_page_config() { - $this->_page_config = array( - 'nav' => array( - 'label' => __('Mock Valid Admin Page'), - 'order' => 10 - ) - ); - } - - - public function default_route_callback() { - return true; - } - - protected function _ajax_hooks(){} - protected function _add_screen_options() {} - protected function _add_feature_pointers() {} - public function load_scripts_styles() {} - public function admin_init() {} - public function admin_notices() {} - public function admin_footer_scripts() {} -} diff --git a/tests/mocks/admin/events/Events_Admin_Page_Mock.php b/tests/mocks/admin/events/Events_Admin_Page_Mock.php deleted file mode 100644 index fcac562b0a5..00000000000 --- a/tests/mocks/admin/events/Events_Admin_Page_Mock.php +++ /dev/null @@ -1,51 +0,0 @@ -_default_tickets_update( $evtobj, $data ); - } - - - - - /** - * Mock for the _delete_event method that will handle setting up things for testing event deletes via the admin page. - * @param $EVT_ID_to_delete - */ - public function delete_event( $EVT_ID_to_delete ) { - //set request data for event - $this->_req_data['EVT_ID'] = $EVT_ID_to_delete; - $this->_delete_event( false ); - } - -} //end class Events_Admin_Page_Mock diff --git a/tests/mocks/admin/messages/Messages_Admin_Page_Mock.php b/tests/mocks/admin/messages/Messages_Admin_Page_Mock.php deleted file mode 100644 index edbaffc7139..00000000000 --- a/tests/mocks/admin/messages/Messages_Admin_Page_Mock.php +++ /dev/null @@ -1,61 +0,0 @@ -_activate_messenger( $messenger_name ); - } - - - public function activate_message_type_for_messenger( $messenger_name, $message_type_name ) { - return $this->_activate_message_type_for_messenger( $messenger_name, $message_type_name ); - } - - - public function deactivate_messenger( $messenger_name ) { - return $this->_deactivate_messenger( $messenger_name ); - } - - - public function deactivate_message_type_for_messenger( $messenger_name, $message_type_name ) { - return $this->_deactivate_message_type_for_messenger( $messenger_name, $message_type_name ); - } - -} //end class Registrations_Admin_Page_Mock \ No newline at end of file diff --git a/tests/mocks/admin/pricing/espresso_events_Pricing_Hooks_Mock.php b/tests/mocks/admin/pricing/espresso_events_Pricing_Hooks_Mock.php deleted file mode 100644 index 88cce7498bd..00000000000 --- a/tests/mocks/admin/pricing/espresso_events_Pricing_Hooks_Mock.php +++ /dev/null @@ -1,52 +0,0 @@ -_date_format_strings = $format_strings; - } - - - - - - public function update_dtts( $evt_obj, $data ) { - return $this->_update_datetimes( $evt_obj, $data ); - } - - - - public function update_tkts( $evtobj, $saved_dtts, $data ) { - return $this->_update_tickets( $evtobj, $saved_dtts, $data ); - } - - -} //end espresso_events_Pricing_Hooks_mock diff --git a/tests/mocks/admin/registrations/EE_Registrations_List_Table_Mock.php b/tests/mocks/admin/registrations/EE_Registrations_List_Table_Mock.php deleted file mode 100644 index 2626d3a3e41..00000000000 --- a/tests/mocks/admin/registrations/EE_Registrations_List_Table_Mock.php +++ /dev/null @@ -1,38 +0,0 @@ -_total_registrations_this_month(); - } - - public function total_registrations_today() { - return $this->_total_registrations_today(); - } -} diff --git a/tests/mocks/admin/registrations/Registrations_Admin_Page_Mock.php b/tests/mocks/admin/registrations/Registrations_Admin_Page_Mock.php deleted file mode 100644 index 55bad1f5992..00000000000 --- a/tests/mocks/admin/registrations/Registrations_Admin_Page_Mock.php +++ /dev/null @@ -1,118 +0,0 @@ -_req_data = array_merge($_POST, $_REQUEST); - return parent::_set_registration_status_from_request($status, $notify); - } - - public function add_event_id_to_where_conditions(array $req) - { - return $this->_add_event_id_to_where_conditions($req); - } - - - public function add_category_id_to_where_conditions(array $req) - { - return $this->_add_category_id_to_where_conditions($req); - } - - - public function add_datetime_id_to_where_conditions(array $req) - { - return $this->_add_datetime_id_to_where_conditions($req); - } - - - public function add_registration_status_to_where_conditions(array $req) - { - return $this->_add_registration_status_to_where_conditions($req); - } - - - public function add_date_to_where_conditions($req) - { - return $this->_add_date_to_where_conditions($req); - } - - - public function add_search_to_where_conditions(array $req) - { - return $this->_add_search_to_where_conditions($req); - } - - - public function get_orderby_for_registrations_query() - { - return $this->_get_orderby_for_registrations_query(); - } - - - public function get_limit($per_page) - { - return $this->_get_limit($per_page); - } - -} //end class Registrations_Admin_Page_Mock diff --git a/tests/mocks/admin/transactions/Transactions_Admin_Page_Mock.php b/tests/mocks/admin/transactions/Transactions_Admin_Page_Mock.php deleted file mode 100644 index 43ec0cf2ba3..00000000000 --- a/tests/mocks/admin/transactions/Transactions_Admin_Page_Mock.php +++ /dev/null @@ -1,184 +0,0 @@ -_req_data += $request_data; - } - - - - /** - * create_payment_from_request_data - * - * @param int $PAY_ID - * @return \EE_Payment - */ - public function create_payment_from_request_data( $PAY_ID = 0 ) { - return $this->_create_payment_from_request_data( $PAY_ID ); - } - - - - /** - * _process_transaction_payments - * - * @param \EE_Transaction $transaction - * @return array - */ - public function process_transaction_payments( EE_Transaction $transaction ) { - return $this->_process_transaction_payments( $transaction ); - } - - - - /** - * _get_REG_IDs_to_apply_payment_to - * - * returns a list of registration IDs that the payment will apply to - * - * @param \EE_Payment $payment - * @return array - */ - public function get_REG_IDs_to_apply_payment_to( EE_Payment $payment ) { - return $this->_get_REG_IDs_to_apply_payment_to( $payment ); - } - - - - /** - * _get_existing_reg_payment_REG_IDs - * - * returns a list of registration IDs that the payment is currently related to - * as recorded in the database - * - * @param \EE_Payment $payment - * @return array - */ - public function get_existing_reg_payment_REG_IDs( EE_Payment $payment ) { - return $this->_get_existing_reg_payment_REG_IDs( $payment ); - } - - - - /** - * _remove_existing_registration_payments - * - * this calculates the difference between existing relations - * to the supplied payment and the new list registration IDs, - * removes any related registrations that no longer apply, - * and then updates the registration paid fields - * - * @param \EE_Payment $payment - * @param int $PAY_ID - * @return bool; - */ - public function remove_existing_registration_payments( EE_Payment $payment, $PAY_ID = 0 ) { - return $this->_remove_existing_registration_payments( $payment, $PAY_ID ); - } - - - - /** - * _update_registration_payments - * - * this applies the payments to the selected registrations - * but only if they have not already been paid for - * - * @param EE_Transaction $transaction - * @param \EE_Payment $payment - * @param array $REG_IDs - * @return void - */ - public function update_registration_payments( EE_Transaction $transaction, EE_Payment $payment, $REG_IDs = array() ) { - $this->_update_registration_payments( $transaction, $payment, $REG_IDs ); - } - - - - /** - * _process_registration_status_change - * - * This processes requested registration status changes for all the registrations - * on a given transaction and (optionally) sends out notifications for the changes. - * - * @param EE_Transaction $transaction - * @param array $REG_IDs - * @return bool - */ - public function process_registration_status_change( EE_Transaction $transaction, $REG_IDs = array() ) { - return $this->_process_registration_status_change( $transaction, $REG_IDs ); - } - - - - /** - * _build_payment_json_response - * - * @access public - * @param \EE_Payment $payment - * @param array $REG_IDs - * @param bool | null $delete_txn_reg_status_change - * @return array - */ - public function build_payment_json_response( EE_Payment $payment, $REG_IDs = array(), $delete_txn_reg_status_change = null ) { - return $this->_build_payment_json_response( $payment, $REG_IDs, $delete_txn_reg_status_change ); - } - - - - /** - * _registration_payment_data_array - * adds info for 'owing' and 'paid' for each registration to the json response - * - * @param array $REG_IDs - * @return array - */ - public function registration_payment_data_array( $REG_IDs ) { - return $this->_registration_payment_data_array( $REG_IDs ); - } - - - -} //end class Registrations_Admin_Page_Mock diff --git a/tests/mocks/core/EE_Base_Class_Repository_Mock.php b/tests/mocks/core/EE_Base_Class_Repository_Mock.php deleted file mode 100644 index a1bf2a0b83f..00000000000 --- a/tests/mocks/core/EE_Base_Class_Repository_Mock.php +++ /dev/null @@ -1,28 +0,0 @@ -interface = 'EE_Ticket'; - parent::__construct(); - } - - -} -// End of file EE_Base_Class_Repository_Mock.php -// Location: /tests/mocks/core//EE_Base_Class_Repository_Mock.php \ No newline at end of file diff --git a/tests/mocks/core/EE_Class_For_Testing_Loading.core.php b/tests/mocks/core/EE_Class_For_Testing_Loading.core.php deleted file mode 100644 index 0d48bb6d23b..00000000000 --- a/tests/mocks/core/EE_Class_For_Testing_Loading.core.php +++ /dev/null @@ -1,24 +0,0 @@ -interface = 'EE_Ticket'; - } - -} -// End of file EE_Object_Collection_Mock.php -// Location: /tests/mocks/EE_Object_Collection_Mock.php \ No newline at end of file diff --git a/tests/mocks/core/EE_Object_Repository_Mock.php b/tests/mocks/core/EE_Object_Repository_Mock.php deleted file mode 100644 index bdb3767c7c4..00000000000 --- a/tests/mocks/core/EE_Object_Repository_Mock.php +++ /dev/null @@ -1,26 +0,0 @@ -interface = 'EE_Ticket'; - $this->persist_method = 'save'; - } - - -} -// End of file EE_Object_Repository_Mock.php -// Location: /tests/mocks/EE_Object_Repository_Mock.php \ No newline at end of file diff --git a/tests/mocks/core/EE_Registry_Mock.core.php b/tests/mocks/core/EE_Registry_Mock.core.php deleted file mode 100644 index 9c9399ad868..00000000000 --- a/tests/mocks/core/EE_Registry_Mock.core.php +++ /dev/null @@ -1,235 +0,0 @@ -_load($file_paths, $class_prefix, $class_name, $type, $arguments, $from_db, $cache, $load_only); - } - - - /** - * @access public - * @param string $class_name - * @param string $class_prefix - * @return null|object - */ - public function get_cached_class($class_name, $class_prefix = '', $arguments = array()) - { - return $this->_get_cached_class($class_name, $class_prefix, $arguments); - } - - - /** - * @access public - * @param string $class_name - * @param string $type - * @param array $file_paths - * @return string - */ - public function resolve_path($class_name, $type = '', $file_paths = array()) - { - return $this->_resolve_path($class_name, $type, $file_paths); - } - - - /** - * @access public - * @param string $path - * @param string $class_name - * @param string $type - * @param array $file_paths - * @return void - * @throws ReflectionException - * @throws EE_Error - */ - public function require_file($path, $class_name, $type = '', $file_paths = array()) - { - $this->_require_file($path, $class_name, $type, $file_paths); - } - - - /** - * @access public - * @param string $class_name - * @param array $arguments - * @param string $type - * @param bool $from_db - * @return null | object - * @throws ReflectionException - * @throws InvalidArgumentException - * @throws InvalidInterfaceException - * @throws InvalidDataTypeException - * @throws EE_Error - */ - public function create_object($class_name, $arguments = array(), $type = 'core', $from_db = false) - { - //echo "\n create_object"; - //echo "\n $class_name"; - //echo "\n resolve_dependencies: "; - //var_dump( $resolve_dependencies ); - return $this->_create_object($class_name, $arguments, $type, $from_db); - } - - - /** - * @access public - * @param object $class_obj - * @param string $class_name - * @param string $class_prefix - * @param bool $from_db - * @return void - */ - public function set_cached_class($class_obj, $class_name, $class_prefix = '', $from_db = false) - { - $this->_set_cached_class($class_obj, $class_name, $class_prefix, $from_db); - } - - - /** - * @access public - * @param array $array - * @return bool - */ - public function array_is_numerically_and_sequentially_indexed(array $array) - { - return $this->_array_is_numerically_and_sequentially_indexed($array); - } - - - /** - * @access public - * @param string $class_name - * @return bool - */ - public function dependency_map_has($class_name = '') - { - return $this->_dependency_map->has($class_name); - } - - - /** - * @access public - * @param string $class_name - * @param string $dependency - * @return bool - */ - public function has_dependency_for_class($class_name = '', $dependency = '') - { - return $this->_dependency_map->has_dependency_for_class($class_name, $dependency); - } - - - /** - * @access public - * @param string $class_name - * @param string $dependency - * @return bool - */ - public function loading_strategy_for_class_dependency($class_name = '', $dependency = '') - { - return $this->_dependency_map->loading_strategy_for_class_dependency($class_name, $dependency); - } - - - /** - * @access public - * @param string $class_name - * @return bool - */ - public function dependency_map_class_loader($class_name = '') - { - return $this->_dependency_map->class_loader($class_name); - } -} - - - -// End of file EE_Registry_Mock.core.php -// Location: /tests/mocks/core/EE_Registry_Mock.core.php diff --git a/tests/mocks/core/EE_Session_Mock.core.php b/tests/mocks/core/EE_Session_Mock.core.php deleted file mode 100644 index 02cf81a5fb6..00000000000 --- a/tests/mocks/core/EE_Session_Mock.core.php +++ /dev/null @@ -1,249 +0,0 @@ -cache_storage = $cache_storage; - $this->request = $request; - $this->encryption = $encryption; - } - - - public function lifespan() { - return 60 * MINUTE_IN_SECONDS; - } - - - - /** - * @return EE_Encryption - */ - public function encryption() { - return $this->encryption; - } - - - /** - * @param null $key - * @param bool $reset_cache - * @return array - */ - public function get_session_data($key = null, $reset_cache = false) - { - if ($reset_cache) { - $this->clear_session(); - } - if (! empty($key)) { - return isset($this->session_data[ $key ]) ? $this->session_data[ $key ] : null; - } - return $this->session_data; - } - - - /** - * set session data - * - * @access public - * @param array $data - * @return TRUE on success, FALSE on fail - */ - public function set_session_data($data) - { - foreach ($data as $key => $value) { - $this->session_data[ $key ] = $value; - } - return true; - } - - - public function clear_session($class = '', $function = '') - { - $this->session_data = array(); - } - - - /** - * @param \EE_Cart $cart - * @return bool - */ - public function set_cart(EE_Cart $cart) - { - $this->session_data['cart'] = $cart; - return true; - } - - - /** - * reset_cart - */ - public function reset_cart() - { - $this->session_data['cart'] = null; - } - - - /** - * @return \EE_Cart - */ - public function cart() - { - return isset($this->session_data['cart']) && $this->session_data['cart'] instanceof EE_Cart - ? $this->session_data['cart'] - : null; - } - - - /** - * @param \EE_Checkout $checkout - * @return bool - */ - public function set_checkout(EE_Checkout $checkout) - { - $this->session_data['checkout'] = $checkout; - return true; - } - - - /** - * reset_checkout - */ - public function reset_checkout() - { - $this->session_data['checkout'] = null; - } - - - /** - * @return \EE_Checkout - */ - public function checkout() - { - return isset($this->session_data['checkout']) && $this->session_data['checkout'] instanceof EE_Checkout - ? $this->session_data['checkout'] - : null; - } - - - /** - * @param \EE_Transaction $transaction - * @return bool - * @throws EE_Error - */ - public function set_transaction(EE_Transaction $transaction) - { - // first remove the session from the transaction before we save the transaction in the session - $transaction->set_txn_session_data(null); - $this->session_data['transaction'] = $transaction; - return true; - } - - - /** - * reset_transaction - */ - public function reset_transaction() - { - $this->session_data['transaction'] = null; - } - - - /** - * @return \EE_Transaction - */ - public function transaction() - { - return isset($this->session_data['transaction']) - && $this->session_data['transaction'] instanceof EE_Transaction - ? $this->session_data['transaction'] - : null; - } -} -// End of file EE_Session_Mock.core.php -// Location: /tests/mocks/core/EE_Session_Mock.core.php diff --git a/tests/mocks/core/Psr4AutoloaderMock.php b/tests/mocks/core/Psr4AutoloaderMock.php deleted file mode 100644 index 286a1f66dc1..00000000000 --- a/tests/mocks/core/Psr4AutoloaderMock.php +++ /dev/null @@ -1,24 +0,0 @@ -files = $files; - } - - - - protected function requireFile( $file ) { - return in_array( $file, $this->files ); - } - -} -// End of file Psr4AutoloaderMock.php -// Location: /tests/mocks/core/Psr4AutoloaderMock.php \ No newline at end of file diff --git a/tests/mocks/core/data_migration_scripts/EE_DMS_Core_1_0_0.dms.php b/tests/mocks/core/data_migration_scripts/EE_DMS_Core_1_0_0.dms.php deleted file mode 100644 index 3caf05bb8de..00000000000 --- a/tests/mocks/core/data_migration_scripts/EE_DMS_Core_1_0_0.dms.php +++ /dev/null @@ -1,41 +0,0 @@ - '3.1.26' ){ -// echo "$version_string can be migrated fro"; - return true; - }elseif( ! $version_string ){ -// echo "no version string provided: $version_string"; - //no version string provided... this must be pre 4.1 - //because since 4.1 we're - return false;//changed mind. dont want people thinking they should migrate yet because they cant - }else{ -// echo "$version_string doesnt apply"; - return false; - } - } - - public function schema_changes_after_migration() { - - } - - public function schema_changes_before_migration() { - - } -} - -// End of file EE_4_1_0_Mock.dms.php \ No newline at end of file diff --git a/tests/mocks/core/data_migration_scripts/EE_DMS_Core_5_0_0.dms.php b/tests/mocks/core/data_migration_scripts/EE_DMS_Core_5_0_0.dms.php deleted file mode 100644 index a04c1d08e52..00000000000 --- a/tests/mocks/core/data_migration_scripts/EE_DMS_Core_5_0_0.dms.php +++ /dev/null @@ -1,44 +0,0 @@ - '4.0.0' ){ -// echo "$version_string can be migrated fro"; - return true; - }elseif( ! $version_string ){ -// echo "no version string provided: $version_string"; - //no version string provided... this must be pre 4.1 - //because since 4.1 we're - return false;//changed mind. dont want people thinking they should migrate yet because they cant - }else{ -// echo "$version_string doesnt apply"; - return false; - } - } - - public function schema_changes_after_migration() { - - } - - public function schema_changes_before_migration() { - - } -} - -// End of file EE_4_1_0_Mock.dms.php \ No newline at end of file diff --git a/tests/mocks/core/db_class_extensions/EEE_Mock_Attendee.class_ext.php b/tests/mocks/core/db_class_extensions/EEE_Mock_Attendee.class_ext.php deleted file mode 100644 index 86af8e5a013..00000000000 --- a/tests/mocks/core/db_class_extensions/EEE_Mock_Attendee.class_ext.php +++ /dev/null @@ -1,34 +0,0 @@ -_model_name_extended = 'Attendee'; - parent::__construct(); - } - - /** - * Samples function that can be called on any EE_Attendee when this class extension - * is registered - * @param type $txn_id - * @return boolean - */ - function ext_foobar( $txn_id = FALSE ){ - return TRUE; - } -} - -// End of file EEE_Mock_Attendee.php \ No newline at end of file diff --git a/tests/mocks/core/db_classes/EE_Mock.class.php b/tests/mocks/core/db_classes/EE_Mock.class.php deleted file mode 100644 index 6ef45ee05a7..00000000000 --- a/tests/mocks/core/db_classes/EE_Mock.class.php +++ /dev/null @@ -1,50 +0,0 @@ -_fields[$field_name]) - ? $this->_fields[$field_name] - : null; - } -} diff --git a/tests/mocks/core/db_model_extensions/EEME_Mock_Attendee.model_ext.php b/tests/mocks/core/db_model_extensions/EEME_Mock_Attendee.model_ext.php deleted file mode 100644 index a31d584dbd0..00000000000 --- a/tests/mocks/core/db_model_extensions/EEME_Mock_Attendee.model_ext.php +++ /dev/null @@ -1,34 +0,0 @@ -_model_name_extended = 'Attendee'; - $this->_extra_tables = array( - 'Mock_Attendee_Meta' => new EE_Secondary_Table('esp_mock_attendee_meta', 'MATTM_ID', 'ATT_ID' ) - ); - $this->_extra_fields = array('Mock_Attendee_Meta'=>array( - 'MATTM_ID'=> new EE_DB_Only_Int_Field('MATTM_ID', __('Mock Attendee Meta Row ID','event_espresso'), false), - 'MATT_ID_fk'=>new EE_DB_Only_Int_Field('ATT_ID', __("Foreign Key to Attendee in Post Table", "event_espresso"), false), - 'ATT_foobar'=>new EE_Foreign_Key_Int_Field('ATT_foobar', __("Foobar", 'event_espresso'), true,0,'Transaction'))); - $this->_extra_relations = array('Transaction'=>new EE_Belongs_To_Relation()); - parent::__construct(); - } - function ext_foobar( $arg1 = FALSE ){ - return $this->_->get_all(array(array('Transaction.TXN_ID'=>$arg1))); - } -} - -// End of file EEME_Mock_Attendee.model_ext.php \ No newline at end of file diff --git a/tests/mocks/core/db_models/EEM_Mock.model.php b/tests/mocks/core/db_models/EEM_Mock.model.php deleted file mode 100644 index 3c01ade75b2..00000000000 --- a/tests/mocks/core/db_models/EEM_Mock.model.php +++ /dev/null @@ -1,39 +0,0 @@ -_tables = array( - 'Mock' => new EE_Primary_Table('esp_mock', 'MCK_ID'), - ); - $this->_fields = array( - 'Mock' => array( - 'MCK_ID' => new EE_Primary_Key_Int_Field('MCK_ID', "Mock Object ID"), - 'MCK_value' => new EE_Plain_Text_Field('MCK_value', 'Mock Object Value', true), - 'MCK_datetime' => new EE_DateTime_Field('MCK_datetime', 'Mock Datetime', false, EE_Datetime_Field::now) - ), - ); - parent::__construct($timezone); - } -} \ No newline at end of file diff --git a/tests/mocks/core/db_models/fields/EE_Datetime_Field_Mock.php b/tests/mocks/core/db_models/fields/EE_Datetime_Field_Mock.php deleted file mode 100644 index 99986bcb0c7..00000000000 --- a/tests/mocks/core/db_models/fields/EE_Datetime_Field_Mock.php +++ /dev/null @@ -1,48 +0,0 @@ -{$field}; - } - - - public function set_nullable() { - $this->_nullable = true; - } - - - public function prepare_for_display( $DateTime, $schema = false ) { - return $this->_prepare_for_display( $DateTime, $schema ); - } - - - - public function get_date_object( $date_string ) { - return parent::_get_date_object( $date_string ); - } - - - -} diff --git a/tests/mocks/core/domain/DomainMock.php b/tests/mocks/core/domain/DomainMock.php deleted file mode 100644 index d9d1a19eee4..00000000000 --- a/tests/mocks/core/domain/DomainMock.php +++ /dev/null @@ -1,28 +0,0 @@ -capability; - } - - - - /** - * @return string - */ - public function context() - { - return $this->context; - } - - - - /** - * @return int|string - */ - public function ID() - { - return $this->ID; - } -} diff --git a/tests/mocks/core/domain/services/capabilities/CapabilitiesCheckerMock.php b/tests/mocks/core/domain/services/capabilities/CapabilitiesCheckerMock.php deleted file mode 100644 index 27fbb2db0d1..00000000000 --- a/tests/mocks/core/domain/services/capabilities/CapabilitiesCheckerMock.php +++ /dev/null @@ -1,63 +0,0 @@ -cap_check_passes) { - throw new InsufficientPermissionsException($cap_check->context()); - } - return true; - } - - - - /** - * @param string $capability - the capability to be checked, like: 'ee_edit_registrations' - * @param string $context - what the user is attempting to do, like: 'Edit Registration' - * @param int $ID - (optional) ID for item where current_user_can is being called from - * @return bool - * @throws InsufficientPermissionsException - * @throws InvalidClassException - */ - public function process($capability, $context, $ID = 0) - { - return $this->processCapCheck(new CapCheckMock()); - } -} -// End of file CapabilitiesCheckerMock.php -// Location: EventEspresso\tests\mocks\core\domain\services\capabilities/CapabilitiesCheckerMock.php \ No newline at end of file diff --git a/tests/mocks/core/domain/services/custom_post_types/RegisterCustomPostTypesMock.php b/tests/mocks/core/domain/services/custom_post_types/RegisterCustomPostTypesMock.php deleted file mode 100644 index dfd9fa0e88a..00000000000 --- a/tests/mocks/core/domain/services/custom_post_types/RegisterCustomPostTypesMock.php +++ /dev/null @@ -1,49 +0,0 @@ -_is_conditional_shortcode($shortcode); - } -} \ No newline at end of file diff --git a/tests/mocks/core/libraries/batch/JobHandlers/DatetimeOffsetFixMock.php b/tests/mocks/core/libraries/batch/JobHandlers/DatetimeOffsetFixMock.php deleted file mode 100644 index 9cc3401c7d2..00000000000 --- a/tests/mocks/core/libraries/batch/JobHandlers/DatetimeOffsetFixMock.php +++ /dev/null @@ -1,26 +0,0 @@ -_ready_queue; - } -} \ No newline at end of file diff --git a/tests/mocks/core/libraries/messages/validators/EE_Messages_Validator_Mock.php b/tests/mocks/core/libraries/messages/validators/EE_Messages_Validator_Mock.php deleted file mode 100644 index d3a03d77aa9..00000000000 --- a/tests/mocks/core/libraries/messages/validators/EE_Messages_Validator_Mock.php +++ /dev/null @@ -1,41 +0,0 @@ - 'something', - * '[ANOTHER_SHORTCODE]' => 'something else' - * ) - * - * @return string|bool If there are invalid shortcodes then a string of those shortcodes are - * returned. Otherwise false is returned. - */ - public function invalid_shortcodes( $value, $valid_shortcodes ) { - return $this->_invalid_shortcodes( $value, $valid_shortcodes ); - } - - - protected function _modify_validator() {} -} diff --git a/tests/mocks/core/libraries/shortcodes/EE_Shortcodes_Mock.php b/tests/mocks/core/libraries/shortcodes/EE_Shortcodes_Mock.php deleted file mode 100644 index 48b6f4f5ac6..00000000000 --- a/tests/mocks/core/libraries/shortcodes/EE_Shortcodes_Mock.php +++ /dev/null @@ -1,87 +0,0 @@ -label = 'Shortcodes Mock Parser'; - $this->description = 'Shortcodes Mock Description'; - $this->_shortcodes = array( - '[MOCK_A]' => 'MOCK A shortcode', - '[MOCK_B]' => 'MOCK B shortcode' - ); - } - - - /** - * This method will give parsing instructions for each shortcode defined in the _shortcodes array. Child methods - * will have to take care of handling. - * - * @access protected - * @param string $shortcode the shortcode to be parsed. - * @param mixed (object|array) $data incoming data for the parser. The data could be either an object or - * array because there are some shortcodes that might be replaced by - * prepared data that has multiple items in a list (i.e. list of attendees - * in an event and we're showing fname/lname for each attendee). In this - * case data will be in an array. Otherwise the data shoudl be in a - * properly formatted object. The EEH_Parse_Shortcodes.helper.php describes - * the data object we're expecting. - * @return string parsed shortcode - */ - protected function _parser($shortcode) - { - switch($shortcode) { - case '[MOCK_A]': - return 'parsed MOCK_A'; - break; - case '[MOCK_B]': - return 'parsed MOCK_B'; - break; - default: - return ''; - } - } - - - /** - * Note this is overriding the parent parser class so don't use this mock to test - * Any actual parser setup/verification. It's only used to directly test the _parser method in here. - * - * @param string $shortcode - * @param array $data Make sure you send in `template` and `data` as keys on this if you want them tested. - * @param array $extra_data Make sure you send in `messenger`, `message_type`, and `message` as keys on this if you - * want them tested. - * @return string - */ - public function parser($shortcode, $data = array(), $extra_data = array()) - { - $this->_data = $data; //make sure you send in template on this if you want to test template parsing - $this->_extra_data = $extra_data; - $this->_set_messages_properties(); - return $this->_parser($shortcode); - } - - - /** - * Use to test parent protected method. - * @param string $shortcode - * @param string $closing_tag - * @param bool $show - * @return string - */ - public function mutate_conditional_block_in_template($shortcode, $show = true) - { - return parent::_mutate_conditional_block_in_template( - $shortcode, - $show - ); - } -} \ No newline at end of file diff --git a/tests/mocks/core/services/EE_Injector_Tester_With_Array_Session_Int_Constructor_Params.class.php b/tests/mocks/core/services/EE_Injector_Tester_With_Array_Session_Int_Constructor_Params.class.php deleted file mode 100644 index 512265776ff..00000000000 --- a/tests/mocks/core/services/EE_Injector_Tester_With_Array_Session_Int_Constructor_Params.class.php +++ /dev/null @@ -1,71 +0,0 @@ -array_property = $some_array; - $this->session_property = $session; - $this->integer_property = $some_int; - } - - - - /** - * @return array - */ - public function array_property() { - return $this->array_property; - } - - - - /** - * @return \EE_Session_Mock - */ - public function session_property() { - return $this->session_property; - } - - - - /** - * @return int - */ - public function integer_property() { - return $this->integer_property; - } - - - -} -// End of file EE_Injector_Tester_With_Array_Session_Int_Constructor_Params.class.php -// Location: tests/mocks/core/services/EE_Injector_Tester_With_Array_Session_Int_Constructor_Params.class.php \ No newline at end of file diff --git a/tests/mocks/core/services/cache/CacheStorageMock.php b/tests/mocks/core/services/cache/CacheStorageMock.php deleted file mode 100644 index d5e888a2237..00000000000 --- a/tests/mocks/core/services/cache/CacheStorageMock.php +++ /dev/null @@ -1,93 +0,0 @@ -storage[$key] = new stdClass(); - $this->storage[$key]->data = $data; - $this->storage[$key]->expiration = $expiration; - return true; - } - - - /** - * retrieves cache data - * should automatically trigger early cache refresh for standard cache items - * in order to avoid cache stampedes on busy sites. - * For non-standard cache items like PHP Session data where early refreshing is not wanted, - * the $standard_cache parameter should be set to false when retrieving data - * - * @param string $key [required] - * @param bool $standard_cache - * @return mixed - */ - public function get($key, $standard_cache = true) - { - return $this->storage[$key]->expiration > time() - ? $this->storage[$key]->data - : null; - } - - - /** - * delete a single cached item - * - * @param string $key [required] full or partial cache key to be deleted - */ - public function delete($key) - { - unset($this->storage[$key]); - } - - - /** - * delete multiple cached items - * - * @param array $keys [required] array of full or partial cache keys to be deleted - * @param bool $force_delete [optional] if true, then will not check incoming keys against those being tracked - * and proceed directly to deleting those entries from the cache storage - */ - public function deleteMany(array $keys, $force_delete = false) - { - foreach ($keys as $key) { - $this->delete($key); - } - } - - -} -// Location: CacheStorageMock.php diff --git a/tests/mocks/core/services/cache/PostRelatedCacheManagerMock.php b/tests/mocks/core/services/cache/PostRelatedCacheManagerMock.php deleted file mode 100644 index 8a206597add..00000000000 --- a/tests/mocks/core/services/cache/PostRelatedCacheManagerMock.php +++ /dev/null @@ -1,40 +0,0 @@ -command_handler; - } - - - - /** - * @param \EventEspresso\core\services\commands\CommandInterface $command - * @return mixed - */ - public function execute($command) - { - return $this->results; - } - -} -// End of file CommandBusMock.php -// Location: EventEspresso\tests\mocks\core\services\commands/CommandBusMock.php \ No newline at end of file diff --git a/tests/mocks/core/services/commands/CommandHandlerManagerMock.php b/tests/mocks/core/services/commands/CommandHandlerManagerMock.php deleted file mode 100644 index 95a6bde21ba..00000000000 --- a/tests/mocks/core/services/commands/CommandHandlerManagerMock.php +++ /dev/null @@ -1,58 +0,0 @@ -command_handler[$fqcn_for_command] = $command_handler; - } - - - - /** - * @param CommandInterface $command - * @param CommandBusInterface $command_bus - * @return mixed - */ - public function getCommandHandler(CommandInterface $command, CommandBusInterface $command_bus = null) - { - $command_name = get_class($command); - $handler = $this->command_handler[$command_name]; - if ($handler instanceof CompositeCommandHandler) { - $handler->setCommandBus($command_bus); - } - return $handler; - } -} -// End of file CommandHandlerManagerMock.php -// Location: EventEspresso\core\services\commands/CommandHandlerManagerMock.php \ No newline at end of file diff --git a/tests/mocks/core/services/commands/MockCommand.php b/tests/mocks/core/services/commands/MockCommand.php deleted file mode 100644 index b4e4b22b206..00000000000 --- a/tests/mocks/core/services/commands/MockCommand.php +++ /dev/null @@ -1,25 +0,0 @@ -results; - } -} -// End of file MockCommandHandler.php -// Location: testcases/tests/testcases/core/services/commands/MockCommandHandler.php \ No newline at end of file diff --git a/tests/mocks/core/services/commands/MockCompositeCommand.php b/tests/mocks/core/services/commands/MockCompositeCommand.php deleted file mode 100644 index 5f85ab64a3b..00000000000 --- a/tests/mocks/core/services/commands/MockCompositeCommand.php +++ /dev/null @@ -1,26 +0,0 @@ -results; - } -} -// End of file MockCompositeCommandHandler.php -// Location: EventEspresso\tests\mocks\core\services\commands/MockCompositeCommandHandler.php \ No newline at end of file diff --git a/tests/mocks/core/services/commands/RequiresCapCheckMockCommand.php b/tests/mocks/core/services/commands/RequiresCapCheckMockCommand.php deleted file mode 100644 index 660e8e91222..00000000000 --- a/tests/mocks/core/services/commands/RequiresCapCheckMockCommand.php +++ /dev/null @@ -1,34 +0,0 @@ -beans = $beans; - } - - - - /** - * @return string - */ - public function getBeans() - { - return $this->beans; - } - -} -// End of file Coffee.php -// Location: /Coffee.php \ No newline at end of file diff --git a/tests/mocks/core/services/container/HonduranBean.php b/tests/mocks/core/services/container/HonduranBean.php deleted file mode 100644 index 1b9bc026595..00000000000 --- a/tests/mocks/core/services/container/HonduranBean.php +++ /dev/null @@ -1,31 +0,0 @@ -identifier(); - } - - - /** - * @return array - */ - public function getAcceptableValues() - { - return $this->acceptableValues(); - } - - - /** - * @return Closure - */ - public function getEvaluationCallback() - { - return $this->evaluationCallback(); - } - -} -// Location: ContextCheckerMock.php diff --git a/tests/mocks/core/services/loaders/CachingLoaderMock.php b/tests/mocks/core/services/loaders/CachingLoaderMock.php deleted file mode 100644 index ebef8fe4503..00000000000 --- a/tests/mocks/core/services/loaders/CachingLoaderMock.php +++ /dev/null @@ -1,35 +0,0 @@ -cache; - } - - - -} -// End of file CachingLoaderMock.php -// Location: EventEspresso\tests\mocks\core\services\loaders/CachingLoaderMock.php \ No newline at end of file diff --git a/tests/mocks/core/services/loaders/ClassToLoad.php b/tests/mocks/core/services/loaders/ClassToLoad.php deleted file mode 100644 index c721dcc6a76..00000000000 --- a/tests/mocks/core/services/loaders/ClassToLoad.php +++ /dev/null @@ -1,47 +0,0 @@ -args = $args; - } - - - /** - * @return array - */ - public function args() - { - return $this->args; - } - - - public function sameInstance(ClassToLoad $other_class) - { - return $other_class === $this; - } -} diff --git a/tests/mocks/core/services/loaders/NewClassToLoad.php b/tests/mocks/core/services/loaders/NewClassToLoad.php deleted file mode 100644 index 7f91f546679..00000000000 --- a/tests/mocks/core/services/loaders/NewClassToLoad.php +++ /dev/null @@ -1,19 +0,0 @@ -processRequestStack($request, $response); - } -} diff --git a/tests/mocks/core/services/request/ObiWanKenobiWare.php b/tests/mocks/core/services/request/ObiWanKenobiWare.php deleted file mode 100644 index 3961cf60ab8..00000000000 --- a/tests/mocks/core/services/request/ObiWanKenobiWare.php +++ /dev/null @@ -1,16 +0,0 @@ -processRequestStack($request, $response); - } -} diff --git a/tests/mocks/core/services/request/RequestStackBuilderMock.php b/tests/mocks/core/services/request/RequestStackBuilderMock.php deleted file mode 100644 index 17e570c8688..00000000000 --- a/tests/mocks/core/services/request/RequestStackBuilderMock.php +++ /dev/null @@ -1,30 +0,0 @@ -int = (int) $int_value; - } - - - public function intValue() - { - return $this->int; - } -} \ No newline at end of file diff --git a/tests/mocks/modules/EED_Single_Page_Checkout_Mock.php b/tests/mocks/modules/EED_Single_Page_Checkout_Mock.php deleted file mode 100644 index a0165b6b542..00000000000 --- a/tests/mocks/modules/EED_Single_Page_Checkout_Mock.php +++ /dev/null @@ -1,18 +0,0 @@ -_is_reg_checkout(); - } -} \ No newline at end of file diff --git a/tests/mocks/payment_methods/Mock_Offsite/EEG_Mock_Offsite.gateway.php b/tests/mocks/payment_methods/Mock_Offsite/EEG_Mock_Offsite.gateway.php deleted file mode 100644 index b763ab0d98a..00000000000 --- a/tests/mocks/payment_methods/Mock_Offsite/EEG_Mock_Offsite.gateway.php +++ /dev/null @@ -1,66 +0,0 @@ -_pay_model->get_payment_by_txn_id_chq_nmbr($update_info[ 'gateway_txn_id' ] ); - if($payment instanceof EEI_Payment && isset( $update_info[ 'status' ] ) ){ - if( $update_info[ 'status' ] == $this->_pay_model->approved_status() ){ - $payment->set_status( $this->_pay_model->approved_status() ); - }elseif( $update_info[ 'status' ] == $this->_pay_model->pending_status() ){ - $payment->set_status( $this->_pay_model->pending_status() ); - }else{ - $payment->set_status( $this->_pay_model->failed_status() ); - } - } - return $payment; - } - - - - /** - * - * @param EEI_Payment $payment - * @param array $billing_info - * @param string $return_url - * @param string $notify_url - * @param string $cancel_url - * @return \EE_Payment|\EEI_Payment - */ - public function set_redirection_info( $payment, $billing_info = array(), $return_url = NULL, $notify_url = NULL, $cancel_url = NULL ) { - global $auto_made_thing_seed; - $payment->set_redirect_url('http://google.com'); - $payment->set_txn_id_chq_nmbr( $auto_made_thing_seed++ ); - return $payment; - } -} - -// End of file EEG_Mock_Onsite.php \ No newline at end of file diff --git a/tests/mocks/payment_methods/Mock_Offsite/EE_PMT_Mock_Offsite.pm.php b/tests/mocks/payment_methods/Mock_Offsite/EE_PMT_Mock_Offsite.pm.php deleted file mode 100644 index 570aa7f5286..00000000000 --- a/tests/mocks/payment_methods/Mock_Offsite/EE_PMT_Mock_Offsite.pm.php +++ /dev/null @@ -1,59 +0,0 @@ -file_folder().'EEG_Mock_Offsite.gateway.php'); - $this->_gateway = new EEG_Mock_Offsite(); - $this->_pretty_name = __("Mock Offsite", 'event_espresso'); - parent::__construct($pm_instance); - } - - /** - * Creates the billing form for this payment method type - * @param \EE_Transaction $transaction - * @return NULL - */ - public function generate_new_billing_form( EE_Transaction $transaction = NULL ) { - return NULL; - } - - /** - * Gets the form for all the settings related to this payment method type - * @return EE_Payment_Method_Form - */ - public function generate_new_settings_form() { - $form = new EE_Payment_Method_Form(array( - 'extra_meta_inputs'=>array( - 'login_id'=>new EE_Text_Input(array( - 'html_label_text'=> sprintf(__("Login ID %s", "event_espresso"), EEH_Template::get_help_tab_link(self::help_tab_link)) - ))))); - return $form; - } - - - -} - -// End of file EE_PMT_Onsite.php \ No newline at end of file diff --git a/tests/mocks/payment_methods/Mock_Onsite/EEG_Mock_Onsite.gateway.php b/tests/mocks/payment_methods/Mock_Onsite/EEG_Mock_Onsite.gateway.php deleted file mode 100644 index 47631264031..00000000000 --- a/tests/mocks/payment_methods/Mock_Onsite/EEG_Mock_Onsite.gateway.php +++ /dev/null @@ -1,33 +0,0 @@ -log( $billing_info, $payment ); - $payment->set_status( $billing_info[ 'status' ] ); - return $payment; - } -} - -// End of file EEG_Mock_Onsite.php \ No newline at end of file diff --git a/tests/mocks/payment_methods/Mock_Onsite/EE_PMT_Mock_Onsite.pm.php b/tests/mocks/payment_methods/Mock_Onsite/EE_PMT_Mock_Onsite.pm.php deleted file mode 100644 index 41dfcee8cde..00000000000 --- a/tests/mocks/payment_methods/Mock_Onsite/EE_PMT_Mock_Onsite.pm.php +++ /dev/null @@ -1,69 +0,0 @@ -file_folder().'EEG_Mock_Onsite.gateway.php'); - $this->_gateway = new EEG_Mock_Onsite(); - $this->_pretty_name = __("Mock Onsite", 'event_espresso'); - parent::__construct($pm_instance); - } - - /** - * @param \EE_Transaction $transaction - * @return \EE_Billing_Attendee_Info_Form - */ - public function generate_new_billing_form( EE_Transaction $transaction = NULL ) { - $form = new EE_Billing_Attendee_Info_Form($this->_pm_instance,array( - 'name'=>'Mock_Onsite_Form', - 'subsections'=>array( - 'status' => new EE_Text_Input(),//this will become the payments status when processing payments on this mock object - 'credit_card'=>new EE_Credit_Card_Input(array( - 'required'=>false - )), - 'exp_month'=>new EE_Month_Input(true, array( - 'required'=>false - )), - 'exp_year'=>new EE_Year_Input(), - 'cvv'=>new EE_CVV_Input(), - ) - )); - return $form; - } - - /** - * Gets the form for all the settings related to this payment method type - * @return EE_Payment_Method_Form - */ - public function generate_new_settings_form() { - $form = new EE_Payment_Method_Form(array( - 'extra_meta_inputs'=>array( - 'login_id'=>new EE_Text_Input(array( - 'html_label_text'=> sprintf(__("Login ID %s", "event_espresso"), EEH_Template::get_help_tab_link(self::help_tab_link)) - ))))); - return $form; - } -} - -// End of file EE_PMT_Onsite.php \ No newline at end of file diff --git a/tests/phpunit.xml b/tests/phpunit.xml deleted file mode 100644 index 81c2f0473d7..00000000000 --- a/tests/phpunit.xml +++ /dev/null @@ -1,53 +0,0 @@ - - - - ../ - - ../acceptance_tests - ../assets - ../bin - ../docs - ../eslint - ../languages - ../node_modules - ../public - ../tests - ../vendor - ../wp-assets - - - - - - ./testcases/ - - - - - ignore - live - big_rest_tests - - - - - - - - 2000 - - - - - - - - - diff --git a/tests/testcases/admin_pages/events/Events_Admin_Page_Test.php b/tests/testcases/admin_pages/events/Events_Admin_Page_Test.php deleted file mode 100644 index e0f1feead05..00000000000 --- a/tests/testcases/admin_pages/events/Events_Admin_Page_Test.php +++ /dev/null @@ -1,61 +0,0 @@ -delayedAdminPageMocks( 'events' ); - } - - - - protected function _load_requirements( $timezone = 'America/Vancouver' ) { - $this->_admin_page = new Events_Admin_Page_Mock(); - $this->_event = $this->factory->event->create(); - $this->_event->set_timezone( $timezone ); - $this->_event->save(); - $this->_set_default_dates( $timezone ); - } - - - - - /** - * Tests the _delete_event method via the mock - * @see https://events.codebasehq.com/projects/event-espresso/tickets/9699 - * @group 9699 - */ - public function test_delete_event() { - $this->_load_requirements(); - //let's delete the event - $this->_admin_page->delete_event( $this->_event->ID() ); - - //assert it got deleted! - $this->assertEmpty( EEM_Event::instance()->get_one_by_ID( $this->_event->ID() ) ); - } -} \ No newline at end of file diff --git a/tests/testcases/admin_pages/events_decaf/Events_Admin_Page_Decaf_Test.php b/tests/testcases/admin_pages/events_decaf/Events_Admin_Page_Decaf_Test.php deleted file mode 100644 index 7f998f95d65..00000000000 --- a/tests/testcases/admin_pages/events_decaf/Events_Admin_Page_Decaf_Test.php +++ /dev/null @@ -1,227 +0,0 @@ -delayedAdminPageMocks( 'decaf_events' ); - } - - - /** - * loader for setting the $_admin_page_property - * - * @param string $timezone Timezone string to initialize the times in. - * @since 4.6 - */ - protected function _load_requirements( $timezone = 'America/Vancouver' ) { - $this->_admin_page = new Events_Admin_Page_Mock(); - $this->_event = $this->factory->event->create(); - $this->_event->set_timezone( $timezone ); - $this->_event->save(); - $this->_set_default_dates( $timezone ); - } - - - - - /** - * tests the decaf datetime and tickets update method for Events Admin Page. - * - *@since 4.6 - */ - public function test_default_tickets_update() { - //first test is just with default data - $this->_load_requirements(); - $this->_testing_updates( "Tests with Default Data\n" ); - - //next test is with empty TKT_start and TKT_end dates. - $replacement['edit_tickets']['1']['TKT_start_date'] = null; - $replacement['edit_tickets']['1']['TKT_end_date'] = null; - - //override _default_dates because we expect something different. - $this->_default_dates = array(); - $this->_load_requirements(); - $this->_default_dates['TKT_start'] = new DateTime( 'now', new DateTimeZone( 'America/Vancouver' ) ); - - /** - * TKT_start is set in the decaf ticket saves without seconds, so we need to set the seconds to zero as well for comparison. - */ - $this->_default_dates['TKT_start']->setTime( $this->_default_dates['TKT_start']->format( 'H' ), $this->_default_dates['TKT_start']->format( 'i' ), 0 ); - /** - * tkt end date is the same as start date because here's the code execution in Events_Admin_page::default_tickets_update: - * 1. If no TKT_end_date, then set to DTT_EVT_start. - * 2. However, this means that DTT_EVT_start (because its static) will always be earlier than what the value for TKT_start_date is. - * 3. So later the code changes TKT_end_date to be the SAME as TKT_start_date and then sets it forward by a day. So that's what our expected value will be. - */ - $this->_default_dates['TKT_end'] = clone $this->_default_dates['TKT_start']; - $this->_default_dates['TKT_end'] = $this->_default_dates['TKT_end']->add( new DateInterval( 'P1D' ) ); - $this->_testing_updates( "Tests with unset tkt start and end date\n", $replacement ); - - } - - - - - /** - * This is a common looped to test saves of ticket and datetime data. - * - * @param string $context_for_error_messages Used this to add context to any failed tests so - * you can easily verify what triggered it. - * @param array $data_to_replace An array of replacements for the default data. - * Use null to indicate you want the key unset. - * @since 4.6 - */ - protected function _testing_updates( $context_for_error_messages, $data_to_replace = array() ) { - $formats_to_test = $this->date_formats_to_test(); - - $saved_dtts_for_tickets = $formats_for_compare = $saved_tkts = array(); - - /** - * Note: Keep in mind, decaf does NOT provide the ability to choose the format that the dates are - * displayed in for the event editor. So when we test comparing formats, it is important to set the - * format on the objects before retrieval. Also important is that only the 'Y-m-d h:i a' format is used - * on the decaf editor form. So we make sure the all the dates going in for the data are in the same format. - */ - - foreach( $formats_to_test['date'] as $date_format ) { - foreach( $formats_to_test['time'] as $time_format ) { - $full_format = $date_format . ' ' . $time_format; - $decaf_date_format = 'Y-m-d h:i a'; - $data = $this->_get_save_data( $decaf_date_format ); - - //is there any data to unset/replace? - if ( ! empty( $data_to_replace ) ) { - //any data to unset? - foreach( $data_to_replace as $top_level => $second_level ) { - if ( is_array( $second_level ) ) { - foreach ( $second_level as $third_level => $fourth_level ) - if ( is_array( $fourth_level ) ) { - foreach ( $fourth_level as $fifth_level => $sixth_level ) { - if ( is_null( $sixth_level ) ) { - unset( $data_to_replace[$top_level][$third_level][$fifth_level] ); - unset( $data[$top_level][$third_level][$fifth_level] ); - - } - } - } else if ( is_null( $fourth_level ) ) { - unset( $data_to_replace[$top_level][$third_level] ); - unset( $data[$top_level][$third_level] ); - } - } else { - if ( is_null( $second_level ) ) { - unset( $data_to_replace[$top_level] ); - unset( $data[$top_level] ); - } - } - } - //moige - $data = array_merge( $data, $data_to_replace ); - } - - - - $saved_data = $this->_admin_page->default_tickets_update( $this->_event, $data ); - $dtt = $saved_data[0]; - $tkts = $saved_data[1]; - - //verify datetime. - $this->assertInstanceof( 'EE_Datetime', $dtt ); - //verify start and date - $this->assertEquals( $dtt->start_date_and_time( $date_format, $time_format ), $this->_default_dates['DTT_start']->format( $full_format ), $context_for_error_messages . sprintf( 'Start Date Format Tested: %s', $full_format ) ); - $this->assertEquals( $dtt->end_date_and_time( $date_format, $time_format ), $this->_default_dates['DTT_end']->format( $full_format ), $context_for_error_messages . sprintf( 'End Date Format Tested: %s', $full_format ) ); - - $saved_dtts_for_tickets[$full_format] = $dtt; - $formats_for_compare[$dtt->ID()] = array( $date_format, $time_format ); - - //verify tkts - foreach ( $tkts as $tkt ) { - $this->assertInstanceof( 'EE_Ticket', $tkt, $context_for_error_messages . sprintf( 'Format: %s', $full_format ) ); - - //verify start and date - //Note: currently this test sometimes fails depending on the timing of when it happens and how fast - // the server is. Whenever I've seen this fail its been off by 1 minute and that's because when the - // default dates for testing were created, they likely happened at the second turnover. - $this->assertDateWithinOneMinute( $tkt->start_date( $date_format, $time_format ), $this->_default_dates['TKT_start']->format( $full_format ), $full_format, $context_for_error_messages . sprintf( 'Start Ticket DateFormat Tested: %s', $full_format ) ); - $this->assertDateWithinOneMinute( $tkt->end_date( $date_format, $time_format ), $this->_default_dates['TKT_end']->format( $full_format ), $full_format, $context_for_error_messages . sprintf( 'End Ticket Date Format Tested: %s', $full_format ) ); - - $saved_tkts[$full_format] = $tkt; - } - } - } - - - //now let's verify these items were saved corectly in the db. - /*$new_tkts = $new_dtts = array(); - foreach ( $tkt as $format => $tkt ) { - $new_tkts[$format] = EEM_Ticket::instance()->refresh_entity_map_from_db( $tkt->ID() ); - } - - foreach ( $saved_dtts_for_tickets[$full_format] as $format => $dtt ) { - $new_dtts[$format] = EEM_Datetime::instance()->refresh_entity_map_from_db( $dtt->ID() ); - }/**/ - - $new_event = EEM_Event::instance()->refresh_entity_map_from_db( $this->_event->ID() ); - $new_event->set_timezone( 'America/Vancouver' ); - - $evt_dtts = $new_event->datetimes_ordered(); - - //now let's do comparisons. - foreach( $evt_dtts as $edtt ) { - $formats = $formats_for_compare[$edtt->ID()]; - $format = $formats[0] . ' ' . $formats[1]; - $this->assertEquals( $edtt->start_date_and_time( $formats[0], $formats[1] ), $this->_default_dates['DTT_start']->format( $format), $context_for_error_messages . sprintf( 'DB DTT/Default DTT Start Date Format Checked: %s', $format ) ); - $this->assertEquals( $edtt->end_date_and_time( $formats[0], $formats[1] ), $this->_default_dates['DTT_end']->format( $format ), $context_for_error_messages . sprintf( 'DB DTT/Default DTT End Date Format Checked: %s', $format ) ); - $this->assertEquals( $edtt->start_date_and_time( $formats[0], $formats[1] ), $saved_dtts_for_tickets[$format]->start_date_and_time( $formats[0], $formats[1] ), $context_for_error_messages . sprintf( 'DB DTT/Orig DTT Start Date Format Checked: %s', $format ) ); - $this->assertEquals( $edtt->end_date_and_time( $formats[0], $formats[1] ), $saved_dtts_for_tickets[$format]->end_date_and_time( $formats[0], $formats[1] ), $context_for_error_messages . sprintf( 'DB DTT/Orig DTT End Date Format Checked: %s', $format ) ); - - //get related ticket on this $edtt - $evt_tkt = $edtt->get_first_related( 'Ticket' ); - $this->assertDateWithinOneMinute( $evt_tkt->start_date( $formats[0], $formats[1] ), $this->_default_dates['TKT_start']->format( $format ), $format, $context_for_error_messages . sprintf( 'DB TKT/Default TKT Start Date Format Checked: %s', $format ) ); - $this->assertDateWithinOneMinute( $evt_tkt->end_date( $formats[0], $formats[1] ), $this->_default_dates['TKT_end']->format( $format ), $format, $context_for_error_messages . sprintf( 'DB TKT/Default TKT End Date Format Checked: %s', $format ) ); - $this->assertDateWithinOneMinute( $evt_tkt->start_date( $formats[0], $formats[1] ), $saved_tkts[$format]->start_date( $formats[0], $formats[1] ), $format, $context_for_error_messages . sprintf( 'DB TKT/Orig TKT Start Date Format Checked: %s', $format ) ); - $this->assertDateWithinOneMinute( $evt_tkt->end_date( $formats[0], $formats[1] ), $saved_tkts[$format]->end_date( $formats[0], $formats[1] ), $format, $context_for_error_messages . sprintf( 'DB TKT/Orig TKT End Date Format Checked: %s', $format ) ); - } - } - - - - - -} -// end class Events_Admin_Page_Decaf -// Location: testcases/admin_pages/events_decaf/Events_Admin_Page_Decaf_Test.php diff --git a/tests/testcases/admin_pages/messages/Messages_Admin_Page_Test.php b/tests/testcases/admin_pages/messages/Messages_Admin_Page_Test.php deleted file mode 100644 index 5a1d65d60d3..00000000000 --- a/tests/testcases/admin_pages/messages/Messages_Admin_Page_Test.php +++ /dev/null @@ -1,79 +0,0 @@ -delayedAdminPageMocks( 'messages' ); - $this->_load_requirements(); - } - - - - protected function _load_requirements() { - $this->_MessagesAdminPage = new Messages_Admin_Page_Mock(); - $this->_MessageResourceManager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' ); - } - - - /** - * This is testing that the active messenger settings option in the db does not get corrupted when activating a messenger. - * @group 9330 - */ - public function test_activate_messenger_with_invalid_messenger() { - $original_active_messenger_settings = $this->_MessageResourceManager->get_active_messengers_option( true ); - - //activate a dummy messenger - $activated = $this->_MessagesAdminPage->activate_messenger( 'dummy_messenger' ); - $this->assertFalse( $activated ); - - //verify that the new active_messenger_settings is the same as the original so no corruption. - $updated_active_messenger_settings = $this->_MessageResourceManager->get_active_messengers_option( true ); - $this->assertEquals( $original_active_messenger_settings, $updated_active_messenger_settings ); - //lets just reset notices because we don't care about them for this test. This prevents a fail from automatically firing. - EE_Error::reset_notices(); - } - - - - - /** - * This is testing that the active messenger settings option in the db does not get corrupted when activating a messenger. - * @group 9330 - */ - public function test_deactivate_messenger_with_valid_messenger() { - $original_active_messenger_settings = $this->_MessageResourceManager->get_active_messengers_option( true ); - $this->assertTrue( isset( $original_active_messenger_settings['html'] ) ); - //unset manually the html messenger from this array so we'll have our expected array. - unset( $original_active_messenger_settings['html'] ); - - //deactivate an actual messenger - $deactivated = $this->_MessagesAdminPage->deactivate_messenger( 'html' ); - - $this->assertTrue( $deactivated ); - $updated_active_messenger_settings = $this->_MessageResourceManager->get_active_messengers_option( true ); - - $this->assertEquals( $original_active_messenger_settings, $updated_active_messenger_settings ); - //lets just reset notices because we don't care about them for this test. This prevents a fail from automatically firing. - EE_Error::reset_notices(); - } -} \ No newline at end of file diff --git a/tests/testcases/admin_pages/pricing/espresso_events_Pricing_Hooks_Test.php b/tests/testcases/admin_pages/pricing/espresso_events_Pricing_Hooks_Test.php deleted file mode 100644 index c86965dca03..00000000000 --- a/tests/testcases/admin_pages/pricing/espresso_events_Pricing_Hooks_Test.php +++ /dev/null @@ -1,191 +0,0 @@ -loadAdminMocks(); - } - - - - /** - * loads the pricing mock object for tests - * - * @param string $timezone Timezone string to initialize the times in. - * @throws EE_Error - * @since 4.6 - */ - protected function _load_pricing_mock($timezone = 'America/Vancouver') - { - $this->_pricingMock = new espresso_events_Pricing_Hooks_Mock(); - $this->_event = $this->factory->event->create(); - $this->_event->set_timezone($timezone); - $this->_event->save(); - $this->_set_default_dates($timezone); - } - - - - /** - * Contains tests for the update_dtts method and update_tkts method. - * - * @since 4.6 - */ - public function test_update_dtts_and_update_tkts() - { - $this->_load_pricing_mock(); - $formats_to_test = $this->date_formats_to_test(); - $saved_dtts_for_tickets = $formats_for_compare = $saved_tkts = array(); - //test each date and time format combination for creating datetime objects - foreach ($formats_to_test['date'] as $date_format) { - foreach ($formats_to_test['time'] as $time_format) { - $full_format = $date_format . ' ' . $time_format; - $this->_pricingMock->set_date_format_strings(array('date' => $date_format, 'time' => $time_format)); - $data = $this->_get_save_data($full_format); - $dtts = $this->_pricingMock->update_dtts($this->_event, $data); - foreach ($dtts as $dtt) { - $this->assertInstanceOf('EE_Datetime', $dtt); - /** @var EE_Datetime $dtt */ - //verify start and date - $this->assertEquals( - $dtt->start_date_and_time(), - $this->_default_dates['DTT_start']->format($full_format), - sprintf('Start Date Format Tested: %s', $full_format) - ); - $this->assertEquals( - $dtt->end_date_and_time(), - $this->_default_dates['DTT_end']->format($full_format), - sprintf('End Date Format Tested: %s', $full_format) - ); - $saved_dtts_for_tickets[$full_format] = $dtt; - $formats_for_compare[$dtt->ID()] = array($date_format, $time_format); - } - } - } - //test each date and time format combination for creating ticket objects - foreach ($formats_to_test['date'] as $date_format) { - foreach ($formats_to_test['time'] as $time_format) { - $full_format = $date_format . ' ' . $time_format; - $this->_pricingMock->set_date_format_strings(array('date' => $date_format, 'time' => $time_format)); - $data = $this->_get_save_data($full_format); - $dtt_for_ticket['1'] = $saved_dtts_for_tickets[$full_format]; - $tkts = $this->_pricingMock->update_tkts($this->_event, $dtt_for_ticket, $data); - foreach ($tkts as $tkt) { - $this->assertInstanceOf('EE_Ticket', $tkt, sprintf('Format: %s', $full_format)); - //verify start and date - $this->assertEquals( - $tkt->start_date(), - $this->_default_dates['TKT_start']->format($full_format), - sprintf('Start Ticket DateFormat Tested: %s', $full_format) - ); - $this->assertEquals( - $tkt->end_date(), - $this->_default_dates['TKT_end']->format($full_format), - sprintf('End Ticket Date Format Tested: %s', $full_format) - ); - $saved_tkts[$full_format] = $tkt; - } - } - } - //now let's verify these items were saved correctly in the db. - /*$new_tkts = $new_dtts = array(); - foreach ( $tkt as $format => $tkt ) { - $new_tkts[$format] = EEM_Ticket::instance()->refresh_entity_map_from_db( $tkt->ID() ); - } - - foreach ( $saved_dtts_for_tickets[$full_format] as $format => $dtt ) { - $new_dtts[$format] = EEM_Datetime::instance()->refresh_entity_map_from_db( $dtt->ID() ); - }/**/ - /** @var EE_Event $new_event */ - $new_event = EEM_Event::instance()->refresh_entity_map_from_db($this->_event->ID()); - $new_event->set_timezone('America/Vancouver'); - $evt_dtts = $new_event->datetimes_ordered(); - //now let's do comparisons. - foreach ($evt_dtts as $edtt) { - if(!$edtt instanceof EE_Datetime) { - continue; - } - $formats = $formats_for_compare[$edtt->ID()]; - $format = $formats[0] . ' ' . $formats[1]; - $this->assertEquals( - $edtt->start_date_and_time($formats[0], $formats[1]), - $this->_default_dates['DTT_start']->format($format), - sprintf('DB DTT/Default DTT Start Date Format Checked: %s', $format) - ); - $this->assertEquals( - $edtt->end_date_and_time($formats[0], $formats[1]), - $this->_default_dates['DTT_end']->format($format), - sprintf('DB DTT/Default DTT End Date Format Checked: %s', $format) - ); - $this->assertEquals( - $edtt->start_date_and_time($formats[0], $formats[1]), - $saved_dtts_for_tickets[$format]->start_date_and_time(), - sprintf('DB DTT/Orig DTT Start Date Format Checked: %s', $format) - ); - $this->assertEquals( - $edtt->end_date_and_time($formats[0], $formats[1]), - $saved_dtts_for_tickets[$format]->end_date_and_time(), - sprintf('DB DTT/Orig DTT End Date Format Checked: %s', $format) - ); - //get related ticket on this $edtt - $evt_tkt = $edtt->get_first_related('Ticket'); - $this->assertEquals( - $evt_tkt->start_date($formats[0], $formats[1]), - $this->_default_dates['TKT_start']->format($format), - sprintf('DB TKT/Default TKT Start Date Format Checked: %s', $format) - ); - $this->assertEquals( - $evt_tkt->end_date($formats[0], $formats[1]), - $this->_default_dates['TKT_end']->format($format), - sprintf('DB TKT/Default TKT End Date Format Checked: %s', $format) - ); - $this->assertEquals( - $evt_tkt->start_date($formats[0], $formats[1]), - $saved_tkts[$format]->start_date($formats[0], $formats[1]), - sprintf('DB TKT/Orig TKT Start Date Format Checked: %s', $format) - ); - $this->assertEquals( - $evt_tkt->end_date($formats[0], $formats[1]), - $saved_tkts[$format]->end_date($formats[0], $formats[1]), - sprintf('DB TKT/Orig TKT End Date Format Checked: %s', $format) - ); - } - } - - -} -//end class espresso_events_Pricing_Hooks_Test -// Location: tests/testcases/admin_pages/pricing/espresso_events_Pricing_Hooks_Test.php diff --git a/tests/testcases/admin_pages/registrations/EE_Registrations_List_Table_Test.php b/tests/testcases/admin_pages/registrations/EE_Registrations_List_Table_Test.php deleted file mode 100644 index 8798c0198f6..00000000000 --- a/tests/testcases/admin_pages/registrations/EE_Registrations_List_Table_Test.php +++ /dev/null @@ -1,105 +0,0 @@ -loadAdminMocks(); - } - - - - - public function _load_mock() { - $this->_mock = new EE_Registrations_List_Table_Mock(''); - } - - - - - - /** - * @since 4.6.0 - */ - public function test_total_registrations_this_month() { - $this->_load_mock(); - //baseline dates - $now = new DateTime( 'now' ); - - //let's setup some registrations to test. Setting status as not approved to avoid the incomplete exclusion on the method tested. - $registrations = $this->factory->registration->create_many( 4, array( 'STS_ID' => EEM_Registration::status_id_not_approved ) ); - - $this->assertEquals( 4, count( $registrations ) ); - - //let's modify the first registration so it happened two months ago. Note, the reason why I am doing this - //instead of one month is because if today's date is March 31st, March 30th, or March 29th. There is - //wierd PHP behaviour where subtracting one month will result in a date remaining in March. - //@see http://php.net/manual/en/datetime.sub.php#example-2469 - $first_registration = reset( $registrations ); - $first_registration->set( 'REG_date', $now->sub( new DateInterval('P2M') )->format('U') ); - $first_registration->save(); - - //modify the last registration so it happens next month. - $last_registration = end( $registrations ); - $last_registration->set( 'REG_date', $now->add( new DateInterval('P3M') )-> format( 'U' ) ); - - $last_registration->save(); - - //now let's test the method. - $this->assertEquals(2, $this->_mock->total_registrations_this_month() ); - - - } - - - - /** - * @since 4.6.x - */ - public function test_total_registrations_today() { - $this->_load_mock(); - //baseline dates - $now = new DateTime( 'now' ); - $nowEST = new DateTime( 'now', new DateTimeZone( 'America/Toronto' ) ); - - //let's setup some registrations to test. Setting status as not approved to avoid the incomplete exclusion on the method tested. - $registrations = $this->factory->registration->create_many( 4, array( 'STS_ID' => EEM_Registration::status_id_not_approved ) ); - - $this->assertEquals( 4, count( $registrations ) ); - - //let's modify the first registration so it happened last month. - $first_registration = reset( $registrations ); - $first_registration->set( 'REG_date', $now->sub( new DateInterval('P1M') )->format('U') ); - $first_registration->save(); - - //modify the last registration so it happens next month. - $last_registration = end( $registrations ); - $last_registration->set( 'REG_date', $now->add( new DateInterval('P2M') )-> format( 'U' ) ); - $last_registration->save(); - - //now let's test the method. - $this->assertEquals(2, $this->_mock->total_registrations_today() ); - } - -} //end class EE_Registrations_List_Table_Test diff --git a/tests/testcases/admin_pages/registrations/Registrations_Admin_Page_Test.php b/tests/testcases/admin_pages/registrations/Registrations_Admin_Page_Test.php deleted file mode 100644 index 3509add73ec..00000000000 --- a/tests/testcases/admin_pages/registrations/Registrations_Admin_Page_Test.php +++ /dev/null @@ -1,498 +0,0 @@ -original_timezone_string = get_option('timezone_string'); - //set timezone of site to 'America/Vancouver' for tests. - update_option('timezone_string', 'America/Vancover'); - $this->delayedAdminPageMocks('registrations'); - //need to set a user with registration privileges for default queries in the admin. - $user = $this->factory->user->create_and_get(); - $user->add_role('administrator'); - wp_set_current_user( $user->ID ); - } - - - public function tearDown() - { - //restore timezone to original setting - update_option('timezone_string', $this->original_timezone_string); - parent::tearDown(); - } - - - /** - * loader for setting the $_admin_page_property - * - * @since 4.6 - */ - protected function _load_requirements() - { - $this->_admin_page = new Registrations_Admin_Page_Mock(); - } - - - /** - * This is a utility method for this test suite to generate a url to use with the _GOTO method for testing - * functionality. - * @param array $extra_query_params - */ - protected function _get_reg_admin_url( $extra_query_params = array() ) { - return add_query_arg( - array_merge( - array( 'page' => 'espresso_registrations' ), - $extra_query_params - ), - admin_url() - ); - } - - - /** - * @since 4.6.x - * -- testing today queries - * -- testing this month queries - * -- testing month range queries. - * @throws \EE_Error - */ - public function test_get_registrations() - { - // to view how dates are added or subtracted, uncomment the following - /*foreach( array( '01', '15', '31' ) as $day ) { - echo "\n\n\n ADD DATES"; - $date = "2015-01-{$day}"; - $now = DateTime::createFromFormat( 'Y-m-d', $date ); - echo "\n\n starting : " . $now->format( 'M d, Y' ); - for ( $x = 1; $x <= 12; $x++ ) { - echo "\n\n now : " . $now->format( 'M d, Y' ); - $prev_month = $this->_get_date_one_month_ago( $now ); - echo "\n prev: " . $prev_month->format( 'M d, Y' ); - $next_month = $this->_get_date_one_month_from_now( $now ); - echo "\n next: " . $next_month->format( 'M d, Y' ); - $year = (int)$now->format( 'Y' ); - $month = (int)$now->format( 'n' ); - $month++; - $days_in_month = (int)$next_month->format( 't' ); - $now_day = $day > $days_in_month ? $days_in_month : $day; - $now = DateTime::createFromFormat( 'Y-m-d', "{$year}-{$month}-{$now_day}" ); - - } - echo "\n\n\n SUBTRACT DATES"; - $now = DateTime::createFromFormat( 'Y-m-d', $date ); - echo "\n\n starting : " . $now->format( 'M d, Y' ); - for ( $x = 12; $x > 0; $x-- ) { - echo "\n\n now : " . $now->format( 'M d, Y' ); - $prev_month = $this->_get_date_one_month_ago( $now ); - echo "\n prev: " . $prev_month->format( 'M d, Y' ); - $next_month = $this->_get_date_one_month_from_now( $now ); - echo "\n next: " . $next_month->format( 'M d, Y' ); - $year = (int)$now->format( 'Y' ); - $month = (int)$now->format( 'n' ); - $month++; - $days_in_month = (int)$next_month->format( 't' ); - $now_day = $day > $days_in_month ? $days_in_month : $day; - $now = DateTime::createFromFormat( 'Y-m-d', "{$year}-{$month}-{$now_day}" ); - } - }*/ - // baseline DateTime objects - $now = new DateTime('now', new DateTimeZone('America/Vancouver')); - $prev_month = $this->_get_date_one_month_ago($now); - $next_month = $this->_get_date_one_month_from_now($now); - // echo "\n\n now : " . $now->format( 'M j, Y g:i a' ); - // echo "\n prev: " . $prev_month->format( 'M j, Y g:i a' ); - // echo "\n next: " . $next_month->format( 'M j, Y g:i a' ); - - //let's setup some registrations to test. - // first create a txn - /** @var EE_Transaction $transaction */ - $transaction = $this->factory->transaction->create(); - $registrations = $this->factory->registration->create_many(4, array('TXN_ID' => $transaction->ID())); - $this->assertCount( - 4, - $registrations, - 'there should be 4 registrations in total, not ' . count($registrations) - . "\nHere are the registrations: " . $this->reg_debug($registrations, true) - ); - - //create an event and add to the registrations - $event = $this->factory->event->create(array('EVT_wp_user' => get_current_user_id())); - if ($event instanceof EE_Event) { - foreach ($registrations as $registration) { - if ($registration instanceof EE_Registration) { - $registration->_add_relation_to($transaction, 'Transaction'); - $registration->_add_relation_to($event, 'Event'); - $registration->set('STS_ID', EEM_Registration::status_id_pending_payment); - $registration->save(); - } - } - } - // let's modify the first registration so it happened one months ago, - $first_registration = reset($registrations); - $first_registration->set('REG_date', $prev_month->format('U')); - $first_registration->save(); - // modify the last registration so it happens next month. - $last_registration = end($registrations); - $last_registration->set('REG_date', $next_month->format('U')); - $last_registration->save(); - // $this->reg_debug( $registrations ); - //let's test queries for today - $this->go_to( - $this->_get_reg_admin_url(array('status'=>'today')) - ); - $this->_load_requirements(); - $registrations = $this->_admin_page->get_registrations(); - // echo "\n\n " . __LINE__ . ") " . __METHOD__ . "() STATUS: " . $_GET['status']; - // $this->reg_debug( $registrations ); - $this->assertCount( - 2, - $registrations, - 'there should be 2 registrations for today, not ' . count($registrations) - . "\nHere are the registrations: " . $this->reg_debug($registrations, true) - ); - //test queries for this month - $this->go_to( - $this->_get_reg_admin_url(array('status'=>'month')) - ); - $this->_load_requirements(); - $registrations = $this->_admin_page->get_registrations(); - // echo "\n\n " . __LINE__ . ") " . __METHOD__ . "() STATUS: " . $_GET['status']; - // $this->reg_debug( $registrations ); - $this->assertCount( - 2, - $registrations, - 'there should be 2 registrations for this month, not ' . count($registrations) - . "\nHere are the registrations: " . $this->reg_debug($registrations, true) - ); - // test queries for month range using last month - $this->go_to( - $this->_get_reg_admin_url(array('month_range' => $prev_month->format('F Y'))) - ); - $this->_load_requirements(); - $this->_admin_page->get_registrations(); - $registrations = $this->_admin_page->get_registrations(); - // echo "\n\n " . __LINE__ . ") " . __METHOD__ . "() MONTH_RANGE: " . $_GET[ 'month_range' ]; - // $this->reg_debug( $registrations ); - $this->assertCount( - 1, - $registrations, - 'there should be 1 registration for ' . $_GET['month_range'] . ', not ' . count($registrations) - . "\nHere are the registrations: " . $this->reg_debug($registrations, true) - ); - } - - - /** - * @param EE_Registration[] $registrations - * @param bool $return - * @return string - */ - public function reg_debug($registrations, $return = false) - { - $result = "\n\n " . __LINE__ . ") " . __METHOD__ . "()"; - $result .= "\n registration count: " . count($registrations); - foreach ($registrations as $registration) { - if ($registration instanceof EE_Registration) { - $result .= "\n registration date: " . $registration->date(); - } - } - if ($return) { - return $result; - } - echo $result; - return ''; - } - - - /** - * @since 4.8.10.rc.10 - * @group integration - * @throws \EE_Error - */ - public function test__set_registration_status_from_request_for_single_registration() - { - //first setup a registration - /** @var EE_Registration $testing_registration */ - $testing_registration = $this->factory->registration->create(array('STS_ID' => EEM_Registration::status_id_pending_payment)); - // and a txn - $testing_registration->_add_relation_to($this->factory->transaction->create(), 'Transaction'); - $_REQUEST['_REG_ID'] = $testing_registration->ID(); - $this->_load_requirements(); - $success = $this->_admin_page->set_registration_status_from_request(EEM_Registration::status_id_not_approved); - $this->assertArrayHasKey('success', $success); - $this->assertTrue($success['success']); - $this->assertArrayHasKey('REG_ID', $success); - $this->assertArrayContains($testing_registration->ID(), $success['REG_ID']); - - //verify registration got changed to not approved. - /** @var EE_Registration $actual_registration */ - $actual_registration = EEM_Registration::reset()->instance()->get_one_by_ID($testing_registration->ID()); - $this->assertEquals(EEM_Registration::status_id_not_approved, $actual_registration->status_ID()); - } - - - /** - * @since 4.8.10.rc.10 - * @group integration - * @throws \EE_Error - */ - public function test__set_registration_status_from_request_for_multiple_registrations() - { - /** @var EE_Transaction $txn */ - $txn = $this->factory->transaction->create(); - /** @var EE_Line_Item $tli */ - $tli = EEH_Line_Item::create_total_line_item($txn); - $tli->save(); - /** @var EE_Ticket $tkt */ - $tkt = $this->factory->ticket_chained->create(); - EEH_Line_Item::add_ticket_purchase($tli, $tkt); - //basically the same as the prior test except here we're testing multiple registrations. - /** @var EE_Registration $registration_a */ - $registration_a = $this->factory->registration->create( - array( - 'STS_ID' => EEM_Registration::status_id_cancelled, - 'TXN_ID' => $txn->ID(), - 'TKT_ID' => $tkt->ID(), - ) - ); - $registration_a->save(); - /** @var EE_Registration $registration_b */ - $registration_b = $this->factory->registration->create( - array( - 'STS_ID' => EEM_Registration::status_id_pending_payment, - 'TXN_ID' => $txn->ID(), - 'TKT_ID' => $tkt->ID(), - ) - ); - $registration_b->save(); - /** @var EE_Registration $registration_c */ - $registration_c = $this->factory->registration->create( - array( - 'STS_ID' => EEM_Registration::status_id_not_approved, - 'TXN_ID' => $txn->ID(), - 'TKT_ID' => $tkt->ID(), - ) - ); - $registration_c->save(); - - $expected_ids = array($registration_a->ID(), $registration_b->ID(), $registration_c->ID()); - $_REQUEST['_REG_ID'] = $expected_ids; - $this->_load_requirements(); - $success = $this->_admin_page->set_registration_status_from_request(EEM_Registration::status_id_not_approved); - $this->assertArrayHasKey('success', $success); - $this->assertTrue($success['success']); - $this->assertArrayHasKey('REG_ID', $success); - $this->assertCount(3, $success['REG_ID']); - $this->assertEquals($expected_ids, $success['REG_ID']); - - //verify registrations got changed to approved (or stayed there). - $registrations = EEM_Registration::reset()->instance()->get_all(array(array('STS_ID' => EEM_Registration::status_id_not_approved))); - $this->assertCount(3, $registrations); - $this->assertEquals($expected_ids, array_keys($registrations)); - } - - - - public function test_add_event_id_to_where_conditions() - { - $this->go_to( - $this->_get_reg_admin_url(array('event_id' => 42)) - ); - $this->_load_requirements(); - $where = $this->_admin_page->add_event_id_to_where_conditions($this->_admin_page->get_request_data()); - $this->assertCount(1, $where); - $this->assertArrayHasKey('EVT_ID', $where); - $this->assertEquals(42, $where['EVT_ID']); - } - - - - public function test_add_category_id_to_where_conditions() - { - $this->go_to( - $this->_get_reg_admin_url(array('EVT_CAT' => 42)) - ); - $this->_load_requirements(); - $where = $this->_admin_page->add_category_id_to_where_conditions($this->_admin_page->get_request_data()); - $this->assertCount(1, $where); - $this->assertArrayHasKey('Event.Term_Taxonomy.term_id', $where); - $this->assertEquals(42,$where['Event.Term_Taxonomy.term_id']); - } - - - public function test_add_datetime_id_to_where_conditions() - { - $this->go_to( - $this->_get_reg_admin_url(array('datetime_id' => 42)) - ); - $this->_load_requirements(); - $where = $this->_admin_page->add_datetime_id_to_where_conditions($this->_admin_page->get_request_data()); - $this->assertCount(1, $where); - $this->assertArrayHasKey('Ticket.Datetime.DTT_ID', $where); - $this->assertEquals(42, $where['Ticket.Datetime.DTT_ID']); - } - - public function test_add_registration_status_to_where_conditions_no_status_not_trash_view() - { - $this->_load_requirements(); - $where = $this->_admin_page->add_registration_status_to_where_conditions($this->_admin_page->get_request_data()); - $this->assertCount(1, $where); - $this->assertArrayHasKey('STS_ID', $where); - $this->assertTrue(is_array($where['STS_ID'])); - $this->assertArrayContains('!=', $where['STS_ID']); - $this->assertArrayContains(EEM_Registration::status_id_incomplete, $where['STS_ID']); - } - - - - public function test_add_registration_status_to_where_conditions_no_status_trash_view(){ - $this->_load_requirements(); - $req = $this->_admin_page->get_request_data(); - $req['status'] = 'trash'; - $where = $this->_admin_page->add_registration_status_to_where_conditions($req); - $this->assertEquals(array( 'REG_deleted' => true ), $where); - } - - - public function test_add_registration_status_to_where_conditions_with_status_and_incomplete_view() - { - $this->go_to( - $this->_get_reg_admin_url(array('_reg_status'=>EEM_Registration::status_id_approved)) - ); - $this->_load_requirements(); - $req = $this->_admin_page->get_request_data(); - $req['status'] = 'incomplete'; - $where = $this->_admin_page->add_registration_status_to_where_conditions($req); - $this->assertCount(1, $where); - $this->assertArrayHasKey('STS_ID',$where); - $this->assertEquals(EEM_Registration::status_id_approved, $where['STS_ID']); - } - - - public function test_add_registration_status_to_where_conditions_no_status_and_incomplete_view() - { - $this->_load_requirements(); - $req = $this->_admin_page->get_request_data(); - $req['status'] = 'incomplete'; - $where = $this->_admin_page->add_registration_status_to_where_conditions($req); - $this->assertCount(1, $where); - $this->assertArrayHasKey('STS_ID',$where); - $this->assertEquals(EEM_Registration::status_id_incomplete, $where['STS_ID']); - } - - - public function test_add_registration_status_to_where_conditions_with_status() - { - $this->go_to( - $this->_get_reg_admin_url(array('_reg_status'=>EEM_Registration::status_id_approved)) - ); - $this->_load_requirements(); - $where = $this->_admin_page->add_registration_status_to_where_conditions($this->_admin_page->get_request_data()); - $this->assertCount(1, $where); - $this->assertArrayHasKey('STS_ID',$where); - $this->assertEquals(EEM_Registration::status_id_approved,$where['STS_ID']); - } - - - - public function test_add_date_to_where_conditions_for_this_month() - { - $this->_load_requirements(); - $current_year_and_month = date('Y-m', current_time('timestamp')); - $days_this_month = date('t', current_time('timestamp')); - $expected_start_date = date_create_from_format( 'Y-m-d H:i:s', $current_year_and_month . '-01 00:00:00' ); - $expected_end_date = date_create_from_format( 'Y-m-d H:i:s', $current_year_and_month . '-' . $days_this_month . ' 23:59:59' ); - $req = $this->_admin_page->get_request_data(); - $req['status'] = 'month'; - $where = $this->_admin_page->add_date_to_where_conditions($req); - $this->assertCount(1,$where); - $this->assertArrayHasKey('REG_date',$where); - $this->assertCount(2,$where['REG_date']); - $this->assertContains('BETWEEN',$where['REG_date']); - $this->assertInstanceOf('Datetime',$where['REG_date'][1][0]); - $this->assertInstanceOf('Datetime',$where['REG_date'][1][1]); - $actual_start_date = $where['REG_date'][1][0]; - $actual_end_date = $where['REG_date'][1][1]; - $this->assertEquals($expected_start_date->format('Y-m-d H:i'), $actual_start_date->format('Y-m-d H:i')); - $this->assertEquals($expected_end_date->format('Y-m-d H:i'), $actual_end_date->format('Y-m-d H:i')); - } - - - - public function test_add_search_to_where_conditions() - { - $this->go_to( - $this->_get_reg_admin_url(array('s'=>'gogogo')) - ); - $this->_load_requirements(); - $where = $this->_admin_page->add_search_to_where_conditions($this->_admin_page->get_request_data()); - $this->assertCount(1,$where); - $this->assertArrayHasKey('OR*search_conditions',$where); - $this->assertArrayHasKey('Event.EVT_name',$where['OR*search_conditions']); - $this->assertTrue(is_array($where['OR*search_conditions']['Event.EVT_name'])); - $this->assertEquals('%gogogo%',$where['OR*search_conditions']['Event.EVT_name'][1]); - } - - - public function test_get_orderby_for_registrations_query_none_specified() - { - $this->_load_requirements(); - $orderby = $this->_admin_page->get_orderby_for_registrations_query(); - $this->assertCount(1,$orderby); - $this->assertArrayHasKey('order_by',$orderby); - $this->assertTrue(is_array($orderby['order_by'])); - $this->assertArrayHasKey('REG_date',$orderby['order_by']); - $this->assertEquals('DESC',$orderby['order_by']['REG_date']); - } - - - - public function test_get_orderby_for_registrations_query_specified_orderby_and_order() - { - $this->go_to( - $this->_get_reg_admin_url(array('orderby'=>'_Reg_status','order'=>'ASC')) - ); - $this->_load_requirements(); - $orderby = $this->_admin_page->get_orderby_for_registrations_query(); - $this->assertCount(1,$orderby); - $this->assertArrayHasKey('order_by',$orderby); - $this->assertTrue(is_array($orderby['order_by'])); - $this->assertArrayHasKey('STS_ID',$orderby['order_by']); - $this->assertEquals('ASC',$orderby['order_by']['STS_ID']); - } -} -//end Registrations_Admin_Page_Test -// Location: /tests/testcases/admin_pages/registrations/Registrations_Admin_Page_Test.php diff --git a/tests/testcases/admin_pages/transactions/Transactions_Admin_Page_Test.php b/tests/testcases/admin_pages/transactions/Transactions_Admin_Page_Test.php deleted file mode 100644 index d70ed98c786..00000000000 --- a/tests/testcases/admin_pages/transactions/Transactions_Admin_Page_Test.php +++ /dev/null @@ -1,759 +0,0 @@ -delayedAdminPageMocks('transactions'); - } - - - /** - * _generate_transaction_and_registrations - * - * @since 4.8 - * @param float $txn_total - * @param int $reg_count - * @return \EE_Transaction - */ - protected function _generate_transaction_and_registrations($txn_total = 10.00, $reg_count = 0) - { - /** @type EE_Transaction $transaction */ - $transaction = $this->new_model_obj_with_dependencies( - 'Transaction', - array( - 'STS_ID' => EEM_Transaction::incomplete_status_code, - 'TXN_total' => $txn_total, - 'TXN_paid' => 0, - ) - ); - if ($reg_count) { - $registrations = $this->factory->registration->create_many( - $reg_count, - array( - 'STS_ID' => EEM_Registration::status_id_pending_payment, - 'REG_final_price' => $txn_total / $reg_count, - ) - ); - foreach ($registrations as $registration) { - if ($registration instanceof EE_Registration) { - $transaction->_add_relation_to($registration, 'Registration'); - $registration->save(); - } - } - } - $transaction->save(); - return $transaction; - } - - - /** - * _get_registrations_from_transaction - * - * @since 4.8 - * @param \EE_Transaction $transaction - * @param int $reg_count - * @return \EE_Registration[] - */ - protected function _get_x_number_of_registrations_from_transaction(EE_Transaction $transaction, $reg_count = 0) - { - $registrations = $transaction->registrations(); - return array_slice($registrations, 0, $reg_count, true); - } - - - /** - * _payment_method - * - * @since 4.8 - * @return EE_Payment_Method - */ - protected function _payment_method() - { - if ($this->_payment_method === null) { - switch (rand(1, 3)) { - case 1 : - $type = 'Mock_Onsite'; - break; - case 2 : - $type = 'Mock_Offsite'; - break; - case 3 : - default : - $type = 'Mock_Offline'; - break; - } - $this->_payment_method = $this->new_model_obj_with_dependencies( - 'Payment_Method', - array( - 'PMD_type' => $type, - ) - ); - } - return $this->_payment_method; - } - - - /** - * _generate_payment_details_array - * - * @since 4.8 - * @param EE_Transaction $transaction - * @param float $amount - * @param int $PAY_ID - * @param bool $refund - * @return array - */ - protected function _generate_details_array_for_payment_or_refund( - EE_Transaction $transaction, - $amount = 10.00, - $PAY_ID = null, - $refund = false - ) { - return array( - 'type' => $refund !== true ? 1 : -1, - 'PAY_ID' => $PAY_ID, - 'TXN_ID' => $transaction->ID(), - 'PMD_ID' => $this->_payment_method()->ID(), - 'STS_ID' => EEM_Payment::status_id_approved, - 'PAY_source' => EEM_Payment_Method::scope_admin, - 'PAY_details' => array(), - 'PAY_amount' => $amount, - 'PAY_timestamp' => time() - 86400, - 'PAY_po_number' => rand(100, 1000), - 'PAY_extra_accntng' => rand(100, 1000), - 'PAY_txn_id_chq_nmbr' => rand(100, 1000), - 'PAY_gateway_response' => 'You are a true champion!', - ); - } - - - /** - * test_create_new_payment_or_refund_from_request_data - * used for tests that just need an EE_Payment object - * - * @since 4.8 - * @param array $payment_details - * @return EE_Payment - */ - protected function _generate_payment($payment_details) - { - // make sure refunds have a negative amount - $payment_details['PAY_amount'] = $payment_details['type'] < 0 ? $payment_details['PAY_amount'] * -1 : $payment_details['PAY_amount']; - // then remove 'type' from the payment details since it's not an EEM_Payment field - unset($payment_details['type']); - return EE_Payment::new_instance($payment_details, '', array('Y-m-d', 'H:i a')); - } - - - /** - * test_create_new_payment_or_refund_from_request_data - * used for tests that need payment details passed via $_REQUEST data - * - * @since 4.8 - * @param EE_Transaction $transaction - * @return array - */ - protected function _generate_request_data_for_new_payment_or_refund(EE_Transaction $transaction) - { - $payment_details = $this->_generate_details_array_for_payment_or_refund($transaction); - $request_data['txn_admin_payment'] = array( - 'type' => $payment_details['type'], - 'TXN_ID' => $payment_details['TXN_ID'], - 'PAY_ID' => $payment_details['PAY_ID'], - 'PMD_ID' => $payment_details['PMD_ID'], - 'status' => $payment_details['STS_ID'], - 'date' => $payment_details['PAY_timestamp'], - 'amount' => $payment_details['PAY_amount'], - 'po_number' => $payment_details['PAY_po_number'], - 'accounting' => $payment_details['PAY_extra_accntng'], - 'txn_id_chq_nmbr' => $payment_details['PAY_txn_id_chq_nmbr'], - ); - $this->_admin_page->set_request_data($request_data); - return $request_data; - } - - - /** - * _setup_standard_transaction_and_payment - * uses the above methods to create a transaction with related registrations, and a payment - * - * @since 4.8 - * @param float $txn_total - * @param int $reg_count - * @param float $payment_amount - */ - protected function _setup_standard_transaction_and_payment( - $txn_total = 10.00, - $reg_count = 0, - $payment_amount = 10.00 - ) { - $this->_transaction = $this->_generate_transaction_and_registrations($txn_total, $reg_count); - $this->_payment = $this->_generate_payment( - $this->_generate_details_array_for_payment_or_refund($this->_transaction, $payment_amount) - ); - } - - - /** - * _apply_payment_to_registrations - * - * @since 4.8 - * @param \EE_Registration[] $registrations - */ - protected function _apply_payment_to_registrations($registrations) - { - //echo "\n\n " . __METHOD__ . "() \n"; - // reset reg_payment_REG_IDs - $this->_admin_page->set_existing_reg_payment_REG_IDs(); - $available_payment = $this->_payment->amount(); - foreach ($registrations as $registration) { - if ($registration instanceof EE_Registration) { - if ($available_payment > 0) { - $owing = $registration->final_price() - $registration->paid(); - if ($owing > 0) { - // don't allow payment amount to exceed the available payment amount, OR the amount owing - $payment_amount = min($available_payment, $owing); - // update $available_payment_amount - $available_payment = $available_payment - $payment_amount; - //calculate and set new REG_paid - $registration->set_paid($registration->paid() + $payment_amount); - //$registration->set_paid( $available_payment ); - $registration->_add_relation_to($this->_payment, 'Payment', - array('RPY_amount' => $this->_payment->amount())); - $registration->save(); - } - } - } - } - /** @type EE_Payment $payment */ - $payment = EEM_Payment::instance()->get_one_by_ID($this->_payment->ID()); - $registration_payments = $payment->registration_payments(); - $this->assertNotEmpty($registration_payments); - } - - - - //public function test_apply_payments_or_refunds() {} - - - /** - * test_create_new_payment_or_refund_from_request_data - * - * @since 4.8 - * @group 8620 - */ - public function test_create_new_payment_or_refund_from_request_data() - { - $this->_admin_page = new Transactions_Admin_Page_Mock(); - //echo "\n\n " . __METHOD__ . "() \n"; - $transaction = $this->_generate_transaction_and_registrations(); - $request_data = $this->_generate_request_data_for_new_payment_or_refund($transaction); - $payment = $this->_admin_page->create_payment_from_request_data($request_data['txn_admin_payment']['PAY_ID']); - $this->assertInstanceOf('EE_Payment', $payment); - } - - - /** - * test_get_REG_IDs_to_apply_payment_to_for_specific_registrations_and_new_payment - * - * @since 4.8 - * @group 8620 - */ - public function test_get_REG_IDs_to_apply_payment_to_for_specific_registrations_and_new_payment() - { - $this->_admin_page = new Transactions_Admin_Page_Mock(); - //echo "\n\n " . __METHOD__ . "() \n"; - $this->_setup_standard_transaction_and_payment(40.00, 4, 10.00); - // get 2 out of the four registrations - $registrations = $this->_get_x_number_of_registrations_from_transaction($this->_transaction, 2); - // pass those REG IDs via the $_REQUEST data - $this->_admin_page->set_request_data( - array( - 'txn_admin_payment' => array( - 'registrations' => array_keys($registrations), - ), - ) - ); - $REG_IDs = $this->_admin_page->get_REG_IDs_to_apply_payment_to($this->_payment); - foreach ($registrations as $registration) { - if ($registration instanceof EE_Registration) { - $this->assertContains($registration->ID(), $REG_IDs); - } - } - } - - - /** - * test_get_REG_IDs_to_apply_payment_to_for_all_registrations_and_new_payment - * - * @since 4.8 - * @group 8620 - */ - public function test_get_REG_IDs_to_apply_payment_to_for_all_registrations_and_new_payment() - { - $this->_admin_page = new Transactions_Admin_Page_Mock(); - //echo "\n\n " . __METHOD__ . "() \n"; - $this->_setup_standard_transaction_and_payment(40.00, 4, 10.00); - $REG_IDs = $this->_admin_page->get_REG_IDs_to_apply_payment_to($this->_payment); - foreach ($this->_transaction->registrations() as $registration) { - if ($registration instanceof EE_Registration) { - $this->assertContains($registration->ID(), $REG_IDs); - } - } - } - - - /** - * test_get_existing_reg_payment_REG_IDs - * - * @since 4.8 - * @group 8620 - */ - public function test_get_existing_reg_payment_REG_IDs() - { - $this->_admin_page = new Transactions_Admin_Page_Mock(); - //echo "\n\n " . __METHOD__ . "() \n"; - $this->_setup_standard_transaction_and_payment(40.00, 4, 15.00); - // get 2 out of the four registrations - $registrations = $this->_get_x_number_of_registrations_from_transaction($this->_transaction, 2); - $this->_apply_payment_to_registrations($registrations); - $REG_IDs = $this->_admin_page->get_existing_reg_payment_REG_IDs($this->_payment); - $registrations = $this->_transaction->registrations(); - // $15 payment should have applied $10 to first reg and $5 to second reg - $this->assertContains(reset($registrations)->ID(), $REG_IDs); - $this->assertContains(next($registrations)->ID(), $REG_IDs); - // and nothing to the last two registrations - $this->assertNotContains(next($registrations)->ID(), $REG_IDs); - $this->assertNotContains(next($registrations)->ID(), $REG_IDs); - } - - - /** - * test_remove_existing_registration_payments - * - * @since 4.8 - * @group 8620 - */ - public function test_remove_existing_registration_payments() - { - $this->_admin_page = new Transactions_Admin_Page_Mock(); - //echo "\n\n " . __METHOD__ . "() \n"; - $this->_setup_standard_transaction_and_payment(40.00, 4, 10.00); - $registrations = $this->_get_x_number_of_registrations_from_transaction($this->_transaction, 2); - $this->_apply_payment_to_registrations($registrations); - $removed = $this->_admin_page->remove_existing_registration_payments($this->_payment, $this->_payment->ID()); - $this->assertTrue($removed); - // update payment from db - /** @type EE_Payment $payment */ - $payment = EEM_Payment::instance()->get_one_by_ID($this->_payment->ID()); - $registration_payments = $payment->registration_payments(); - $this->assertEmpty($registration_payments); - - } - - - /** - * test_update_registration_payments - * - * @since 4.8 - * @group 8620 - */ - public function test_update_registration_payments_one_reg_paid_in_full() - { - $this->_admin_page = new Transactions_Admin_Page_Mock(); - $this->_setup_standard_transaction_and_payment(40.00, 4, 10.00); - $this->_admin_page->set_existing_reg_payment_REG_IDs(); - $registrations = $this->_get_x_number_of_registrations_from_transaction($this->_transaction, 2); - $this->_admin_page->update_registration_payments($this->_transaction, $this->_payment, - array_keys($registrations)); - $registrations = $this->_transaction->registrations(); - $this->assertEquals(10.00, reset($registrations)->paid()); - $this->assertEquals(0, next($registrations)->paid()); - $this->assertEquals(0, next($registrations)->paid()); - $this->assertEquals(0, next($registrations)->paid()); - } - - - /** - * test_update_registration_payments - * - * @since 4.8 - * @group 8620 - */ - public function test_update_registration_payments_one_reg_paid_in_full_one_partial() - { - $this->_admin_page = new Transactions_Admin_Page_Mock(); - $this->_setup_standard_transaction_and_payment(40.00, 4, 15.00); - $this->_admin_page->set_existing_reg_payment_REG_IDs(); - $registrations = $this->_get_x_number_of_registrations_from_transaction($this->_transaction, 2); - $this->_admin_page->update_registration_payments($this->_transaction, $this->_payment, - array_keys($registrations)); - // now get ALL registrations - $registrations = $this->_transaction->registrations(); - $this->assertEquals(10.00, reset($registrations)->paid()); - $this->assertEquals(5.00, next($registrations)->paid()); - $this->assertEquals(0, next($registrations)->paid()); - $this->assertEquals(0, next($registrations)->paid()); - } - - - /** - * test_update_registration_payments - * - * @since 4.8 - * @group 8620 - */ - public function test_update_registration_payments_last_reg_paid_in_full() - { - $this->_admin_page = new Transactions_Admin_Page_Mock(); - $this->_setup_standard_transaction_and_payment(40.00, 4, 10.00); - $this->_admin_page->set_existing_reg_payment_REG_IDs(); - $registrations = $this->_transaction->registrations(); - $this->_admin_page->update_registration_payments($this->_transaction, $this->_payment, - array(end($registrations)->ID())); - // ref - //$registrations = $this->_transaction->registrations(); - $this->assertEquals(0, reset($registrations)->paid()); - $this->assertEquals(0, next($registrations)->paid()); - $this->assertEquals(0, next($registrations)->paid()); - $this->assertEquals(10.00, next($registrations)->paid()); - } - - - /** - * test_update_registration_payments - * - * @since 4.8 - * @group 8620 - */ - public function test_update_registration_payments_all_paid_in_full() - { - $this->_admin_page = new Transactions_Admin_Page_Mock(); - $this->_setup_standard_transaction_and_payment(40.00, 4, 40.00); - $this->_admin_page->set_existing_reg_payment_REG_IDs(); - $registrations = $this->_transaction->registrations(); - $this->_admin_page->update_registration_payments($this->_transaction, $this->_payment, - array_keys($registrations)); - $this->assertEquals(10.00, reset($registrations)->paid()); - $this->assertEquals(10.00, next($registrations)->paid()); - $this->assertEquals(10.00, next($registrations)->paid()); - $this->assertEquals(10.00, next($registrations)->paid()); - } - - - /** - * test_update_registration_payments - * - * @since 4.8 - * @group 8620 - */ - public function test_update_registration_payments_two_payments() - { - $this->_admin_page = new Transactions_Admin_Page_Mock(); - $this->_setup_standard_transaction_and_payment(40.00, 4, 10.00); - $this->_admin_page->set_existing_reg_payment_REG_IDs(); - $registrations = $this->_transaction->registrations(); - $reg_IDs = array_keys($registrations); - $this->_admin_page->update_registration_payments($this->_transaction, $this->_payment, $reg_IDs); - $this->assertEquals(10.00, reset($registrations)->paid()); - $this->assertEquals(0, next($registrations)->paid()); - $this->assertEquals(0, next($registrations)->paid()); - $this->assertEquals(0, next($registrations)->paid()); - // second payment - $this->_payment = $this->_generate_payment( - $this->_generate_details_array_for_payment_or_refund($this->_transaction, 15.00) - ); - // reset reg IDs - $this->_admin_page->set_existing_reg_payment_REG_IDs(); - $this->_admin_page->update_registration_payments($this->_transaction, $this->_payment, $reg_IDs); - $this->assertEquals(10.00, reset($registrations)->paid()); - $this->assertEquals(10.00, next($registrations)->paid()); - $this->assertEquals(5.00, next($registrations)->paid()); - $this->assertEquals(0, next($registrations)->paid()); - } - - - /** - * test_update_registration_payments - * - * @since 4.8 - * @group 8620 - */ - public function test_update_registration_payments_three_payments_all_paid() - { - $this->_admin_page = new Transactions_Admin_Page_Mock(); - $this->_setup_standard_transaction_and_payment(40.00, 4, 10.00); - $this->_admin_page->set_existing_reg_payment_REG_IDs(); - $registrations = $this->_transaction->registrations(); - $reg_IDs = array_keys($registrations); - $this->_admin_page->update_registration_payments($this->_transaction, $this->_payment, $reg_IDs); - $this->assertEquals(10.00, reset($registrations)->paid()); - $this->assertEquals(0, next($registrations)->paid()); - $this->assertEquals(0, next($registrations)->paid()); - $this->assertEquals(0, next($registrations)->paid()); - // second payment - $this->_payment = $this->_generate_payment( - $this->_generate_details_array_for_payment_or_refund($this->_transaction, 15.00) - ); - // reset reg IDs - $this->_admin_page->set_existing_reg_payment_REG_IDs(); - $this->_admin_page->update_registration_payments($this->_transaction, $this->_payment, $reg_IDs); - $this->assertEquals(10.00, reset($registrations)->paid()); - $this->assertEquals(10.00, next($registrations)->paid()); - $this->assertEquals(5.00, next($registrations)->paid()); - $this->assertEquals(0, next($registrations)->paid()); - // third and final payment - $this->_payment = $this->_generate_payment( - $this->_generate_details_array_for_payment_or_refund($this->_transaction, 15.00) - ); - // reset reg IDs - $this->_admin_page->set_existing_reg_payment_REG_IDs(); - $this->_admin_page->update_registration_payments($this->_transaction, $this->_payment, $reg_IDs); - $this->assertEquals(10.00, reset($registrations)->paid()); - $this->assertEquals(10.00, next($registrations)->paid()); - $this->assertEquals(10.00, next($registrations)->paid()); - $this->assertEquals(10.00, next($registrations)->paid()); - } - - - /** - * test_process_registration_status_change_set_all_registrations_approved - * - * @since 4.8 - * @group 8620 - */ - public function test_process_registration_status_change_set_all_registrations_approved() - { - $this->_admin_page = new Transactions_Admin_Page_Mock(); - // first we need to setup an admin with EE caps - global $current_user; - $current_user = $this->wp_admin_with_ee_caps(); - $this->_setup_standard_transaction_and_payment(40.00, 4, 40.00); - $this->_admin_page->set_existing_reg_payment_REG_IDs(); - // going to need the registration to have an EE_Ticket for this test - $ticket = $this->new_ticket( - array( - 'ticket_price' => 10.00, - 'ticket_taxable' => false, - ) - ); - $registrations = $this->_transaction->registrations(); - foreach ($registrations as $registration) { - if ($registration instanceof EE_Registration) { - $registration->_add_relation_to($ticket, 'Ticket'); - $registration->_add_relation_to($ticket->get_related_event(), 'Event'); - $registration->save(); - $this->assertEquals(EEM_Registration::status_id_pending_payment, $registration->status_ID()); - } - } - // set $_REQUEST data - $this->_admin_page->set_request_data( - array( - 'txn_reg_status_change' => array( - 'reg_status' => EEM_Registration::status_id_approved, - ), - ) - ); - $status_updates = $this->_admin_page->process_registration_status_change($this->_transaction, - array_keys($registrations)); - $this->assertTrue($status_updates); - foreach ($registrations as $registration) { - if ($registration instanceof EE_Registration) { - $this->assertEquals(EEM_Registration::status_id_approved, $registration->status_ID()); - } - } - } - - - /** - * test_process_registration_status_change_set_two_registrations_approved - * - * @since 4.8 - * @group 8620 - */ - public function test_process_registration_status_change_set_two_registrations_approved() - { - $this->_admin_page = new Transactions_Admin_Page_Mock(); - // first we need to setup an admin with EE caps - global $current_user; - $current_user = $this->wp_admin_with_ee_caps(); - $this->_setup_standard_transaction_and_payment(40.00, 4, 20.00); - $reg_IDs = array_keys($this->_transaction->registrations()); - $registrations = $this->_get_x_number_of_registrations_from_transaction($this->_transaction, 2); - $this->_apply_payment_to_registrations($registrations); - //$this->_admin_page->set_existing_reg_payment_REG_IDs(); - // going to need the registration to have an EE_Ticket for this test - $ticket = $this->new_ticket( - array( - 'ticket_price' => 10.00, - 'ticket_taxable' => false, - ) - ); - //$registrations = $this->_transaction->registrations(); - foreach ($registrations as $registration) { - if ($registration instanceof EE_Registration) { - $registration->_add_relation_to($ticket, 'Ticket'); - $registration->_add_relation_to($ticket->get_related_event(), 'Event'); - $registration->save(); - $this->assertEquals(EEM_Registration::status_id_pending_payment, $registration->status_ID()); - } - } - // set $_REQUEST data - $this->_admin_page->set_request_data( - array( - 'txn_reg_status_change' => array( - 'reg_status' => EEM_Registration::status_id_approved, - ), - ) - ); - $status_updates = $this->_admin_page->process_registration_status_change($this->_transaction, - array_keys($registrations)); - $this->assertTrue($status_updates); - // re-query for ALL of the registrations - $registrations = $this->_transaction->registrations(array(array('REG_ID' => array('IN', $reg_IDs)))); - $this->assertEquals(EEM_Registration::status_id_approved, reset($registrations)->status_ID()); - $this->assertEquals(EEM_Registration::status_id_approved, next($registrations)->status_ID()); - $this->assertEquals(EEM_Registration::status_id_pending_payment, next($registrations)->status_ID()); - $this->assertEquals(EEM_Registration::status_id_pending_payment, next($registrations)->status_ID()); - } - - - /** - * test_build_payment_json_response_for_payment - * - * @since 4.8 - * @group 8620 - */ - public function test_build_payment_json_response_for_payment() - { - $this->_admin_page = new Transactions_Admin_Page_Mock(); - $this->_setup_standard_transaction_and_payment(40.00, 4, 15.00); - // need to make sure relation is set between payment and payment method - $this->_payment->_add_relation_to($this->_payment_method(), 'Payment_Method'); - $registrations = $this->_get_x_number_of_registrations_from_transaction($this->_transaction, 1); - $this->_apply_payment_to_registrations($registrations); - $json_response_data = $this->_admin_page->build_payment_json_response($this->_payment); - $pay_status = EEM_Payment::instance()->status_array(true); - $this->assertEquals(15.00, $json_response_data['amount']); - // total paid is still zero, because we haven't actually updated the TXN with the payment info - $this->assertEquals(0, $json_response_data['total_paid']); - $this->assertEquals(EEM_Transaction::incomplete_status_code, $json_response_data['txn_status']); - $this->assertEquals(EEM_Payment::status_id_approved, $json_response_data['pay_status']); - $this->assertEquals(EEM_Payment::status_id_approved, $json_response_data['STS_ID']); - $this->assertEquals($pay_status[EEM_Payment::status_id_approved], $json_response_data['status']); - $this->assertEquals($this->_payment->ID(), $json_response_data['PAY_ID']); - $this->assertEquals($this->_payment->timestamp('Y-m-d', 'h:i a'), $json_response_data['date']); - $this->assertEquals(strtoupper($this->_payment->source()), $json_response_data['method']); - $this->assertEquals($this->_payment_method()->ID(), $json_response_data['PM_ID']); - $this->assertEquals($this->_payment_method()->admin_name(), $json_response_data['gateway']); - $this->assertEquals($this->_payment->gateway_response(), $json_response_data['gateway_response']); - $this->assertEquals($this->_payment->txn_id_chq_nmbr(), $json_response_data['txn_id_chq_nmbr']); - $this->assertEquals($this->_payment->po_number(), $json_response_data['po_number']); - $this->assertEquals($this->_payment->extra_accntng(), $json_response_data['extra_accntng']); - $this->assertEquals($this->_payment->extra_accntng(), $json_response_data['extra_accntng']); - // will validate $json_response_data[ 'registrations' ] in test_registration_payment_data_array() - } - - - /** - * test_build_payment_json_response_for_deleted_payment - * - * @since 4.8 - * @group 8620 - */ - public function test_build_payment_json_response_for_deleted_payment() - { - $this->_admin_page = new Transactions_Admin_Page_Mock(); - $this->_setup_standard_transaction_and_payment(40.00, 4, 15.00); - // need to make sure relation is set between payment and payment method - $this->_payment->_add_relation_to($this->_payment_method(), 'Payment_Method'); - $registrations = $this->_get_x_number_of_registrations_from_transaction($this->_transaction, 1); - $this->_apply_payment_to_registrations($registrations); - $json_response_data = $this->_admin_page->build_payment_json_response($this->_payment, array(), true); - $this->assertEquals($this->_payment->ID(), $json_response_data['PAY_ID']); - $this->assertEquals(15.00, $json_response_data['amount']); - // total paid is still zero, because we haven't actually updated the TXN with the payment info - $this->assertEquals(0, $json_response_data['total_paid']); - $this->assertEquals(EEM_Transaction::incomplete_status_code, $json_response_data['txn_status']); - $this->assertEquals(EEM_Payment::status_id_approved, $json_response_data['pay_status']); - $this->assertTrue($json_response_data['delete_txn_reg_status_change']); - // will validate $json_response_data[ 'registrations' ] in test_registration_payment_data_array() - } - - - /** - * test_registration_payment_data_array - * - * @since 4.8 - * @group 8620 - */ - public function test_registration_payment_data_array() - { - $this->_admin_page = new Transactions_Admin_Page_Mock(); - $this->_setup_standard_transaction_and_payment(40.00, 4, 25.00); - $registrations = $this->_transaction->registrations(); - $this->_apply_payment_to_registrations($registrations); - $registration_payment_data_array = $this->_admin_page->registration_payment_data_array(array_keys($registrations)); - // format the payment values - $ten_dollars = EEH_Template::format_currency(10.00); - $five_dollars = EEH_Template::format_currency(5.00); - $no_dollars = EEH_Template::format_currency(0.00); - // reg # 1 paid $10, owes 0 - $registration_payment_data = reset($registration_payment_data_array); - $this->assertEquals($ten_dollars, $registration_payment_data['paid']); - $this->assertEquals($no_dollars, $registration_payment_data['owing']); - // reg # 2 paid $10, owes 0 - $registration_payment_data = next($registration_payment_data_array); - $this->assertEquals($ten_dollars, $registration_payment_data['paid']); - $this->assertEquals($no_dollars, $registration_payment_data['owing']); - // reg # 3 paid $5, owes $5 - $registration_payment_data = next($registration_payment_data_array); - $this->assertEquals($five_dollars, $registration_payment_data['paid']); - $this->assertEquals($five_dollars, $registration_payment_data['owing']); - // reg # 4 paid $0, owes $10 - $registration_payment_data = next($registration_payment_data_array); - $this->assertEquals($no_dollars, $registration_payment_data['paid']); - $this->assertEquals($ten_dollars, $registration_payment_data['owing']); - } - - -} -// End of file Transactions_Admin_Page_Test.php -// Location: /tests/testcases/admin_pages/transactions/Transactions_Admin_Page_Test.php \ No newline at end of file diff --git a/tests/testcases/core/EE_Addon_Test.php b/tests/testcases/core/EE_Addon_Test.php deleted file mode 100644 index 9397c554491..00000000000 --- a/tests/testcases/core/EE_Addon_Test.php +++ /dev/null @@ -1,131 +0,0 @@ -_main_file_path = EE_TESTS_DIR . 'mocks/addons/eea-new-addon/eea-new-addon.php'; - require_once $this->_main_file_path; - //loading that file adds a hook, but we want to control when it hooks in - remove_action( 'AHEE__EE_System__load_espresso_addons', 'load_espresso_new_addon' ); - $this->_table_analysis = new \EventEspresso\core\services\database\TableAnalysis(); - $this->_table_manager = new \EventEspresso\core\services\database\TableManager( $this->_table_analysis ); - parent::__construct($name, $data, $dataName); - } - public function setUp(){ - parent::setUp(); - //let's just make a generic addon, but not bother registering it - $loader = EventEspresso\core\services\loaders\LoaderFactory::getLoader(); - require_once dirname($this->_main_file_path) . '/EE_New_Addon.class.php'; - $this->_addon = $loader->getShared( - 'EE_New_Addon', - array( - $loader->getShared('EE_Dependency_Map'), - null, - 'EE_Registry::create(addon)' => true - ) - ); - $this->_addon->set_name( 'New_Addon' ); - $this->_addon->set_main_plugin_file( $this->_main_file_path ); - $this->_addon->set_version( '1.0.0' ); - $this->_addon->set_min_core_version( '4.0.0' ); - add_filter( 'FHEE__EEH_Activation__create_table__short_circuit', array( $this, 'dont_short_circuit_new_addon_table' ), 20, 3 ); - } - - public function tearDown(){ - //drop all the temporary tables we created during this test, because each subsequent test expects them to be gone - $this->_table_manager->dropTables( $this->_temp_tables_added_by_addon ); - parent::tearDown(); - } - - - - /** - * OK's the creation of the esp_new_addon table, because this hooks in AFTER EE_UNitTestCase's callback on this same hook - * - * @param bool $short_circuit - * @param string $table_name - * @param string $create_sql - * @return boolean - */ - public function dont_short_circuit_new_addon_table( $short_circuit = false, $table_name = '', $create_sql = '' ){ - if ( - in_array( $table_name, $this->_temp_tables_added_by_addon ) - ) { -// echo "\r\n\r\nDONT short circuit $sql"; - //it's not altering. it's ok to allow this - return false; - }else{ -// echo "3\r\n\r\n short circuit:$sql"; - return $short_circuit; - } - } - - public function test_update_list_of_installed_versions(){ - $initial_activation_history = $this->_addon->get_activation_history(); - $this->assertEmpty( $initial_activation_history ); - $now_string = substr( date( 'Y-m-d H:i:s', time() ), 0, -1); - //now update the list - $this->_addon->update_list_of_installed_versions( $initial_activation_history, '2.0.0' ); - //now let's try adding more to it - $this->_addon->update_list_of_installed_versions( $initial_activation_history, '3.0.0' ); - $new_activation_history = $this->_addon->get_activation_history(); - $version_number = key($new_activation_history); - $times_installed = array_shift($new_activation_history); - $this->assertEquals('2.0.0',$version_number); - $this->assertTrue( is_array( $times_installed ) ); - $time_first_installed = array_shift( $times_installed ); - $this->assertEquals( $now_string, substr( $time_first_installed, 0, -1) ); - - $second_version_number = key($new_activation_history); - $times_second_v_installed = array_shift($new_activation_history); - $this->assertEquals('3.0.0',$second_version_number); - $this->assertTrue( is_array( $times_second_v_installed ) ); - $time_second_v_first_installed = array_shift( $times_second_v_installed ); - $this->assertEquals($now_string, substr( $time_second_v_first_installed, 0, -1) ); - } - - public function test_get_main_plugin_file(){ - $this->assertEquals($this->_main_file_path,$this->_addon->get_main_plugin_file() ); - } - - public function test_get_main_plugin_file_basename(){ - $this->assertEquals(plugin_basename($this->_main_file_path ), $this->_addon->get_main_plugin_file_basename() ); - } - public function test_get_main_plugin_file_dirname(){ - $this->assertEquals( dirname($this->_main_file_path ), $this->_addon->get_main_plugin_file_dirname() ); - } - - - -} - -// End of file EE_Addon_Test.php diff --git a/tests/testcases/core/EE_Base_Class_Repository_Test.php b/tests/testcases/core/EE_Base_Class_Repository_Test.php deleted file mode 100644 index 6e54ba536ed..00000000000 --- a/tests/testcases/core/EE_Base_Class_Repository_Test.php +++ /dev/null @@ -1,127 +0,0 @@ -repository = new EE_Base_Class_Repository_Mock(); - } - - public function test_save() { - $ticket_1 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_price' => '5' ), false ); - $this->repository->add( $ticket_1 ); - $this->assertEquals( $ticket_1->ID(), 0 ); - $saved = false; - $this->repository->rewind(); - while ( $this->repository->valid() ) { - if ( $this->repository->current() === $ticket_1 ) { - $saved = $this->repository->save(); - $this->assertNotEquals( $this->repository->current()->ID(), 0 ); - $this->assertEquals( $this->repository->current()->ID(), $ticket_1->ID() ); - break; - } - $this->repository->next(); - } - $this->assertNotEquals( $saved, false ); - } - - public function test_save_all() { - $ticket_1 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_price' => '5' ), false ); - $ticket_2 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_price' => '6' ), false ); - $this->repository->add( $ticket_1 ); - $this->repository->add( $ticket_2 ); - $this->assertEquals( count( $this->repository ), 2 ); - $this->assertEquals( $ticket_1->ID(), 0 ); - $this->assertEquals( $ticket_2->ID(), 0 ); - $saved = $this->repository->save_all(); - $this->assertEquals( $saved, true ); - $this->assertNotEquals( $ticket_1->ID(), 0 ); - $this->assertNotEquals( $ticket_2->ID(), 0 ); - } - - public function test_delete() { - $ticket_1 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_price' => '5' ), false ); - $this->repository->add( $ticket_1 ); - $this->assertTrue( $this->repository->has( $ticket_1 ) ); - $this->repository->rewind(); - while ( $this->repository->valid() ) { - if ( $this->repository->current() === $ticket_1 ) { - $this->repository->save(); - $this->assertEquals( $this->repository->current()->ID(), $ticket_1->ID() ); - break; - } - $this->repository->next(); - } - $ticket_1_ID = $ticket_1->ID(); - $this->assertNotEquals( $ticket_1_ID, 0 ); - // now test that we can delete the ticket and remove it from the repo - $this->repository->rewind(); - while ( $this->repository->valid() ) { - if ( $this->repository->current() === $ticket_1 ) { - $deleted = $this->repository->delete(); - $this->assertTrue( $deleted ); - break; - } - $this->repository->next(); - } - $this->assertFalse( $this->repository->has( $ticket_1 ) ); - $this->assertEquals( count( $this->repository ), 0 ); - // because tickets are soft deletable - $ticket1_from_db = EEM_Ticket::instance()->get_one_by_ID( $ticket_1_ID ); - $this->assertTrue( $ticket1_from_db->deleted() ); - } - - - - - public function test_delete_all() { - $ticket_1 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_price' => '5' ), false ); - $ticket_2 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_price' => '6' ), false ); - $this->repository->add( $ticket_1 ); - $this->repository->add( $ticket_2 ); - $this->assertTrue( $this->repository->has( $ticket_1 ) ); - $this->assertTrue( $this->repository->has( $ticket_2 ) ); - $this->assertEquals( count( $this->repository ), 2 ); - $this->assertEquals( $ticket_1->ID(), 0 ); - $this->assertEquals( $ticket_2->ID(), 0 ); - $saved = $this->repository->save_all(); - $this->assertEquals( $saved, true ); - $ticket_1_ID = $ticket_1->ID(); - $ticket_2_ID = $ticket_2->ID(); - $this->assertNotEquals( $ticket_1_ID, 0 ); - $this->assertNotEquals( $ticket_2_ID, 0 ); - // now test that we can delete the tickets and remove them from the repo - $deleted = $this->repository->delete_all(); - $this->assertTrue( $deleted ); - $this->assertFalse( $this->repository->has( $ticket_1 ) ); - $this->assertFalse( $this->repository->has( $ticket_2 ) ); - // and the total count - $this->assertEquals( count( $this->repository ), 0 ); - // because tickets are soft deletable - $ticket1_from_db = EEM_Ticket::instance()->get_one_by_ID( $ticket_1_ID ); - $this->assertTrue( $ticket1_from_db->deleted() ); - $ticket2_from_db = EEM_Ticket::instance()->get_one_by_ID( $ticket_2_ID ); - $this->assertTrue( $ticket2_from_db->deleted() ); - } - - - -} -// End of file EE_Base_Class_Repository_Test.php -// Location: /tests/testcases/core/EE_Base_Class_Repository_Test.php \ No newline at end of file diff --git a/tests/testcases/core/EE_Capabilities_Test.php b/tests/testcases/core/EE_Capabilities_Test.php deleted file mode 100644 index f80be272155..00000000000 --- a/tests/testcases/core/EE_Capabilities_Test.php +++ /dev/null @@ -1,340 +0,0 @@ -CAPS = EE_Registry::instance()->CAP; - } - - - - /** - * test the get_ee_capabilities method on EE_Capabilities class. - * - * @since 4.5.0 - */ - public function test_get_ee_capabilities() - { - //test getting admin capabilities (default) - $admin_capabilities = $this->CAPS->get_ee_capabilities(); - $this->assertFalse(isset($admin_capabilities[self::ADMINISTRATOR_ROLE])); - $this->assertTrue(is_array($admin_capabilities) && isset($admin_capabilities[0])); - $first_cap = $admin_capabilities[0]; - $this->assertEquals('ee_read_ee', $first_cap); - - //test getting all capabilities - $all_caps = $this->CAPS->get_ee_capabilities(''); - $this->assertArrayHasKey(self::ADMINISTRATOR_ROLE, $all_caps); - - //test getting invalid capability - $caps = $this->CAPS->get_ee_capabilities('no_exist'); - $this->assertEmpty($caps); - } - - - - public function test_add_new_capabilities_via_filtering_init_caps() - { - global $wp_roles; - //check the current user is an admin - $user = $this->factory->user->create_and_get(); - $this->assertInstanceOf('WP_User', $user); - $this->assertFalse($this->CAPS->user_can($user, 'ee_new_cap', 'test')); - - //ok now add another cap, and re-init stuff and verify it got added correctly - //add a new cap - add_filter('FHEE__EE_Capabilities__init_caps_map__caps', array($this, 'add_new_caps')); - // but we'll need to set the reset flag to true if we want to do things this way - $this->CAPS->init_caps(true); - //check it got added - $this->assertArrayContains('ee_new_cap', $this->CAPS->get_ee_capabilities(self::ADMINISTRATOR_ROLE)); - $user->add_role(self::ADMINISTRATOR_ROLE); - $this->assertTrue($this->CAPS->user_can($user, 'ee_new_cap', 'test')); - //then check newly-created users get that new role - //refresh the roles' caps and the user object - $wp_roles = new WP_Roles(); - $user_refreshed = get_user_by('id', $user->ID); - $this->assertTrue($this->CAPS->user_can($user_refreshed, 'ee_new_cap', 'test')); - } - - public function add_new_caps($existing_caps) - { - $existing_caps[self::ADMINISTRATOR_ROLE][] = 'ee_new_cap'; - return $existing_caps; - } - - - - public function testAddCaps() - { - $this->CAPS->init_caps(true); - global $wp_roles; - //check the current user is an admin - $user = $this->factory->user->create_and_get(); - $this->assertInstanceOf('WP_User', $user); - $this->assertFalse($this->CAPS->user_can($user, 'ee_new_cap', 'test')); - // ok now add a new cap, but this time using addCaps - $this->CAPS->addCaps(array(self::ADMINISTRATOR_ROLE => array('ee_new_cap'))); - //check it got added - $this->assertArrayContains('ee_new_cap', $this->CAPS->get_ee_capabilities(self::ADMINISTRATOR_ROLE)); - $user->add_role(self::ADMINISTRATOR_ROLE); - $this->assertTrue($this->CAPS->user_can($user, 'ee_new_cap', 'test')); - //then check newly-created users get that new role - //refresh the roles' caps and the user object - $wp_roles = new WP_Roles(); - $user_refreshed = get_user_by('id', $user->ID); - $this->assertTrue($this->CAPS->user_can($user_refreshed, 'ee_new_cap', 'test')); - } - - - - public function test_add_cap_to_role() - { - $this->CAPS->init_caps(true); - global $wp_roles; - //check the current user is an admin - $user = $this->factory->user->create_and_get(); - $this->assertInstanceOf('WP_User', $user); - $this->assertFalse($this->CAPS->user_can($user, 'ee_new_cap', 'test')); - // ok now add a new cap, but this time using addCaps - $this->CAPS->add_cap_to_role(self::ADMINISTRATOR_ROLE, 'ee_new_cap'); - //check it got added - $this->assertArrayContains('ee_new_cap', $this->CAPS->get_ee_capabilities(self::ADMINISTRATOR_ROLE)); - $user->add_role(self::ADMINISTRATOR_ROLE); - $this->assertTrue($this->CAPS->user_can($user, 'ee_new_cap', 'test')); - //then check newly-created users get that new role - //refresh the roles' caps and the user object - $wp_roles = new WP_Roles(); - $user_refreshed = get_user_by('id', $user->ID); - $this->assertTrue($this->CAPS->user_can($user_refreshed, 'ee_new_cap', 'test')); - } - - - - /** - * @since 4.5.0 - */ - public function test_current_user_can_and_user_can() - { - global $current_user; - //setup our user and set as current user. - $user = $this->factory->user->create_and_get(); - $this->assertInstanceOf('WP_User', $user); - $user->add_role(self::ADMINISTRATOR_ROLE); - $current_user = $user; - - //check what should be a valid cap - $this->assertTrue($this->CAPS->current_user_can('ee_read_ee', 'tests')); - $this->assertTrue($this->CAPS->user_can($user, 'ee_read_ee', 'tests')); - - //check what should be an invalid cap - $this->assertFalse($this->CAPS->current_user_can('invalid_cap', 'tests')); - $this->assertFalse($this->CAPS->user_can($user, 'invalid_cap', 'tests')); - - //test context filter - function test_custom_filter($cap, $id) - { - if ($cap == 'ee_read_ee') { - return 'need_this_instead'; - } - - return $cap; - } - - add_filter('FHEE__EE_Capabilities__current_user_can__cap__tests', 'test_custom_filter', 10, 2); - add_filter('FHEE__EE_Capabilities__user_can__cap__tests', 'test_custom_filter', 10, 2); - - $this->assertFalse($this->CAPS->current_user_can('ee_read_ee', 'tests')); - $this->assertFalse($this->CAPS->user_can($user, 'ee_read_ee', 'tests')); - - //test global filter - function test_global_filter($filtered_cap, $context, $cap, $id) - { - if ($cap == 'ee_read_ee' && $context == 'tests') { - return 'ee_read_ee'; //override what was set by custom filter - } - - return $cap; - } - - add_filter('FHEE__EE_Capabilities__current_user_can__cap', 'test_global_filter', 10, 4); - add_filter('FHEE__EE_Capabilities__user_can__cap', 'test_global_filter', 10, 4); - - $this->assertTrue($this->CAPS->current_user_can('ee_read_ee', 'tests')); - $this->assertTrue($this->CAPS->user_can($user, 'ee_read_ee', 'tests')); - } - - - - public function testRemoveCaps() - { - $this->CAPS->init_caps(true); - /** @var WP_Role $administrator_role */ - $administrator_role = get_role(self::ADMINISTRATOR_ROLE); - $this->assertInstanceOf('WP_Role', $administrator_role); - // verify two ways that cap exists - $this->assertTrue(isset($administrator_role->capabilities['ee_manage_gateways'])); - $this->assertTrue($administrator_role->has_cap('ee_manage_gateways')); - // for whatever reason, this site wants to have all gateways - // under control of someone other than the standard administrator - // so they want to remove the 'ee_manage_gateways' cap from the above administrator role - $this->CAPS->removeCaps(array(self::ADMINISTRATOR_ROLE => array('ee_manage_gateways'))); - $user = $this->setupAdminUserAndTestCapDoesNOtExist('ee_manage_gateways'); - $this->assertFalse( - $this->CAPS->user_can($user, 'ee_manage_gateways', 'test'), - 'The admin user should NOT have the "ee_manage_gateways" capability because it was removed!' - ); - } - - - - public function test_remove_cap_from_role() - { - $this->CAPS->init_caps(true); - /** @var WP_Role $administrator_role */ - $administrator_role = get_role(self::ADMINISTRATOR_ROLE); - $this->assertInstanceOf('WP_Role', $administrator_role); - // verify that cap exists - $this->assertTrue($administrator_role->has_cap('ee_manage_gateways')); - // for whatever reason, this site wants to have all gateways - // under control of someone other than the standard administrator - // so they want to remove the 'ee_manage_gateways' cap from the above administrator role - $this->CAPS->remove_cap_from_role(self::ADMINISTRATOR_ROLE, 'ee_manage_gateways'); - $user = $this->setupAdminUserAndTestCapDoesNOtExist('ee_manage_gateways'); - $this->assertFalse( - $this->CAPS->user_can($user, 'ee_manage_gateways', 'test'), - 'The admin user should NOT have the "ee_manage_gateways" capability because it was removed!' - ); - } - - - - private function setupAdminUserAndTestCapDoesNOtExist($cap_to_test = '') - { - /** @var WP_User $user */ - $user = $this->factory->user->create_and_get(); - $this->assertInstanceOf('WP_User', $user); - // verify they don't have the $cap_to_test YET... - $this->assertFalse( - $this->CAPS->user_can($user, $cap_to_test, 'test'), - 'The admin user should NOT have the "'. $cap_to_test .'" capability YET!' - ); - // first remove the existing default role - $user->remove_role(self::SUBSCRIBER_ROLE); - // verify that no other roles exist that could be granting caps - $this->assertEmpty($user->roles); - // now make this user an administrator - $user->add_role(self::ADMINISTRATOR_ROLE); - $this->assertEquals(self::ADMINISTRATOR_ROLE, reset($user->roles)); - return $user; - } - - - public function testPaymentMethodCaps() - { - // we're going to fake the activation of the Mock_Onsite payment method - // which should bestow the following capability to administrators - $mock_onsite_capability = 'ee_payment_method_mock_onsite'; - // but first we need to fake being in the admin - $this->go_to(admin_url()); - // first let's verify that admins do not currently have this cap - /** @var WP_Role $administrator_role */ - $administrator_role = get_role(self::ADMINISTRATOR_ROLE); - $this->assertInstanceOf('WP_Role', $administrator_role); - // verify two ways that cap does not exist YET... - $this->assertFalse(isset($administrator_role->capabilities[$mock_onsite_capability])); - $this->assertFalse($administrator_role->has_cap($mock_onsite_capability)); - // now create an admin user - $user = $this->setupAdminUserAndTestCapDoesNOtExist($mock_onsite_capability); - // and fake activation of the Mock Onsite Payment Method - $this->_pretend_addon_hook_time(); - EE_Register_Payment_Method::register( - 'onsite', - array( - 'payment_method_paths' => array( - EE_TESTS_DIR . 'mocks' . DS . 'payment_methods' . DS . 'Mock_Onsite', - ), - ) - ); - // to complete the fake PM registration, we need to reset the EE_Payment_Method_Manager - // which will take care of injecting all Payment Method caps into the default cap map - // normally we wouldn't do this because the PM would get registered before the caps get initialized - EE_Payment_Method_Manager::reset(); - // and confirm that the admin role now has that cap - $this->assertTrue( - $administrator_role->has_cap($mock_onsite_capability), - 'The admin user should have the "' . $mock_onsite_capability . '" capability!' - ); - // but it appears caps are only added when the role is assigned - // (that's really clever WordPress what's the point of having roles then?) - // turns out we can call the protected _init_caps() method, to reset the caps - $this->refreshRolesForUser($user); - // then verify the user also has the cap - $this->assertTrue( - $this->CAPS->user_can($user, $mock_onsite_capability, 'test'), - 'The admin user should have the "' . $mock_onsite_capability . '" capability!' - ); - // now deactivate the Mock Onsite PM - EE_Register_Payment_Method::deregister('onsite'); - //deregister will just set the hook to run on `AHEE__EE_System__core_loaded_and_ready` so we need to call that - //hook - do_action('AHEE__EE_System__core_loaded_and_ready'); - // and confirm that the admin role now has lost that cap - $this->assertFalse( - $administrator_role->has_cap($mock_onsite_capability), - 'The admin user should NOT have the "' . $mock_onsite_capability . '" capability!' - ); - $this->refreshRolesForUser($user); - // then verify the user also has also lost the cap - $this->assertFalse( - $this->CAPS->user_can($user, $mock_onsite_capability, 'test'), - 'The admin user should have the "' . $mock_onsite_capability . '" capability!' - ); - } - - - - public function testAddNewRoleWhenAddingCap() - { - $this->CAPS->init_caps(true); - $jedi_master = 'ee_jedi_master'; - /** @var WP_Role $jedi_master_role */ - $jedi_master_role = get_role($jedi_master); - $this->assertNull($jedi_master_role); - $this->CAPS->add_cap_to_role($jedi_master, 'ee_use_the_force'); - /** @var WP_Role $jedi_master_role */ - $jedi_master_role = get_role($jedi_master); - $this->assertInstanceOf('WP_Role', $jedi_master_role); - } -} -// end EE_Capabilities_Test class -// Location: testcases/core/EE_Capabilities_Test.php diff --git a/tests/testcases/core/EE_Cart_Test.php b/tests/testcases/core/EE_Cart_Test.php deleted file mode 100644 index 538ec212da0..00000000000 --- a/tests/testcases/core/EE_Cart_Test.php +++ /dev/null @@ -1,200 +0,0 @@ -_session = LoaderFactory::getLoader()->getShared('EE_Session_Mock'); - EE_Cart::reset( null, $this->_session ); - } - - public function test_get_cart_from_txn(){ - $transaction = $this->new_typical_transaction(); - $grand_total_line_item = $transaction->total_line_item(); - $cart = EE_Cart::reset( null, $this->_session ); - $this->assertNotEquals( $cart->get_grand_total()->ID(), $grand_total_line_item->ID() ); - $cart = EE_Cart::get_cart_from_txn( $transaction, $this->_session ); - $this->assertEquals( $cart->get_grand_total()->ID(), $grand_total_line_item->ID() ); - } - - public function test_get_tickets(){ - $transaction = $this->new_typical_transaction(); - $plain_line_items = EEM_Line_Item::instance()->get_all_of_type_for_transaction( EEM_Line_Item::type_line_item, $transaction ); - $cart = EE_Cart::get_cart_from_txn( $transaction, $this->_session ); - $this->assertNotEmpty( $cart->get_tickets() ); - $this->assertEEModelObjectsEquals( $plain_line_items, $cart->get_tickets() ); - } - - public function test_all_ticket_quantity_count(){ - $transaction = $this->new_typical_transaction(); - EEM_Line_Item::instance()->get_all_of_type_for_transaction( EEM_Line_Item::type_line_item, $transaction ); - $cart = EE_Cart::get_cart_from_txn( $transaction, $this->_session ); - $this->assertEquals( 1, $cart->all_ticket_quantity_count() ); - } - - public function test_get_taxes(){ - $transaction = $this->new_typical_transaction(); - $taxes = EEM_Line_Item::instance()->get_all_of_type_for_transaction( EEM_Line_Item::type_tax, $transaction ); - $cart = EE_Cart::get_cart_from_txn( $transaction, $this->_session ); - $this->assertEEModelObjectsEquals( $taxes, $cart->get_taxes() ); - } - public function test_get_grand_total(){ - $transaction = $this->new_typical_transaction(); - $cart = EE_Cart::get_cart_from_txn( $transaction, $this->_session ); - $this->assertEEModelObjectsEquals( $transaction->total_line_item(), $cart->get_grand_total() ); - } - public function test_add_ticket_to_cart(){ - //let's make an interesting ticket, with multiple datetimes, multiple prices etc - $quantity_purchased = 4; - /** @type EE_Ticket $ticket */ - $ticket = $this->new_model_obj_with_dependencies('Ticket', array( 'TKT_price' => '16.5', 'TKT_taxable' => FALSE ) ); - $base_price_type = EEM_Price_Type::instance()->get_one( array( array('PRT_name' => 'Base Price' ) ) ); - $dollar_surcharge_price_type = EEM_Price_Type::instance()->get_one( array( array( 'PRT_name' => 'Dollar Surcharge' ) ) ); - $percent_surcharge_price_type = EEM_Price_Type::instance()->get_one( array( array( 'PRT_name' => 'Percent Surcharge' ) ) ); - $this->assertInstanceOf( 'EE_Price_Type', $base_price_type ); - $this->assertInstanceOf( 'EE_Price_Type', $dollar_surcharge_price_type ); - $this->assertInstanceOf( 'EE_Price_Type', $percent_surcharge_price_type ); - /** @type EE_Price $base_price */ - $base_price = $this->new_model_obj_with_dependencies( 'Price', array( 'PRC_amount' => 10, 'PRT_ID' => $base_price_type->ID() ) ); - /** @type EE_Price $dollar_surcharge */ - $dollar_surcharge = $this->new_model_obj_with_dependencies( 'Price', array( 'PRC_amount' => 5, 'PRT_ID' => $dollar_surcharge_price_type->ID() ) ); - /** @type EE_Price $percent_surcharge */ - $percent_surcharge = $this->new_model_obj_with_dependencies( 'Price', array( 'PRC_amount' => 10, 'PRT_ID' => $percent_surcharge_price_type->ID() ) ); - $ticket->_add_relation_to( $base_price, 'Price' ); - $ticket->_add_relation_to( $dollar_surcharge, 'Price' ); - $ticket->_add_relation_to( $percent_surcharge, 'Price' ); - $this->assertArrayContains( $base_price, $ticket->prices() ); - $this->assertArrayContains( $dollar_surcharge, $ticket->prices() ); - $this->assertArrayContains( $percent_surcharge, $ticket->prices() ); - $event = $this->new_model_obj_with_dependencies( 'Event' ); - $ddt1 = $this->new_model_obj_with_dependencies( 'Datetime', array( 'EVT_ID'=> $event->ID() ) ); - $ddt2 = $this->new_model_obj_with_dependencies( 'Datetime', array( 'EVT_ID'=> $event->ID() ) ); - $ticket->_add_relation_to( $ddt1, 'Datetime' ); - $ticket->_add_relation_to( $ddt2, 'Datetime' ); - $this->assertArrayContains( $ddt1, $ticket->datetimes() ); - $this->assertArrayContains( $ddt2, $ticket->datetimes() ); - // reset cart - $cart = EE_Cart::reset( null, $this->_session ); - $cart->add_ticket_to_cart( $ticket, $quantity_purchased ); - $total_line_item = $cart->get_grand_total(); - $subtotals = $total_line_item->children(); - $this->assertNotEmpty( $subtotals ); - $items_purchased = $total_line_item->get_items(); - $this->assertEquals(1, count( $items_purchased ) ); - $item_purchased = array_shift( $items_purchased ); - $this->assertEquals( $ticket->name(), $item_purchased->name() ); - $this->assertEquals( $item_purchased->total(), $total_line_item->total() ); - $sub_line_items = $item_purchased->children(); - $this->assertEquals( count( $ticket->prices() ), count( $sub_line_items ) ); - //the first one should be the base price - $base_price_sli = array_shift( $sub_line_items ); - $this->assertEquals( $base_price->amount() * 4, $base_price_sli->total() ); - $dollar_surcharge_sli = array_shift( $sub_line_items ); - $this->assertEquals( $dollar_surcharge->amount() * 4, $dollar_surcharge_sli->total( - ) ); - $percent_surcharge_sli = array_shift( $sub_line_items ); - $this->assertEquals( $percent_surcharge->amount(), $percent_surcharge_sli->percent() ); - $this->assertEquals( ($base_price->amount() + $dollar_surcharge->amount() )* $percent_surcharge->amount() / 100 * $quantity_purchased, $percent_surcharge_sli->total() ); - $this->assertEquals($ticket->price() * $quantity_purchased, $cart->get_cart_grand_total() ); - - } - - public function test_get_cart_total_before_tax(){ - $transaction = $this->new_typical_transaction(); - $cart = EE_Cart::get_cart_from_txn( $transaction, $this->_session ); - $this->assertEquals( 10, $cart->get_cart_total_before_tax() ); - } - - public function test_get_applied_taxes(){ - $transaction = $this->new_typical_transaction(); - $cart = EE_Cart::get_cart_from_txn( $transaction, $this->_session ); - $this->assertEquals( 1.5, $cart->get_applied_taxes() ); - } - - public function test_get_cart_grand_total(){ - $transaction = $this->new_typical_transaction(); - $cart = EE_Cart::get_cart_from_txn( $transaction, $this->_session ); - $this->assertEquals( 11.5, $cart->get_cart_grand_total() ); - } - - public function test_delete_items(){ - //known to fail - $ticket_types = 4; - $transaction = $this->new_typical_transaction( array( 'ticket_types' => $ticket_types ) ); - /** @type EE_Line_Item $latest_line_item */ - $latest_line_item = EEM_Line_Item::instance()->get_one( array( - array( 'LIN_type' => EEM_Line_Item::type_line_item ), - 'order_by' => array( 'LIN_ID'=>'DESC' ) ) ); - $cart = EE_Cart::get_cart_from_txn( $transaction, $this->_session ); - - $removals = $cart->delete_items( array( $latest_line_item->code() ) ); - //should remove the ticket line item and its sub-line-item for the price - $this->assertEquals( 2, $removals ); - $this->assertEquals( $ticket_types - 1, $cart->all_ticket_quantity_count() ); - $cart_items = $cart->get_tickets(); - $this->assertArrayDoesNotContain( $latest_line_item, $cart_items ); - } - - public function test_empty_cart(){ - $transaction = $this->new_typical_transaction(); - $cart = EE_Cart::get_cart_from_txn( $transaction, $this->_session ); - $this->assertEEModelObjectsEquals( $transaction->total_line_item(), $cart->get_grand_total() ); - - $cart->empty_cart(); - $this->assertNotEquals( $transaction->total_line_item(), $cart->get_grand_total() ); - } - - public function test_set_grand_total_line_item(){ - $t1 = $this->new_typical_transaction(); - $t1_line_item = $t1->total_line_item(); - $t2 = $this->new_typical_transaction( array( 'ticket_types' => 2) ); - $cart = EE_Cart::get_cart_from_txn( $t2, $this->_session ); - $this->assertNotEquals( $t1_line_item, $cart->get_grand_total() ); - EE_Cart::instance( null, $this->_session )->set_grand_total_line_item( $t1_line_item ); - $this->assertEEModelObjectsEquals( $t1_line_item, $cart->get_grand_total() ); - } - - public function test_save_cart(){ - $t2 = $this->new_typical_transaction( array( 'ticket_types' => 2) ); - $cart = EE_Cart::get_cart_from_txn( $t2, $this->_session ); - $this->_session->reset_data( array( 'cart' ) ); - $this->assertNotEquals( $this->_session->get_session_data( 'cart' ), $cart ); - - $cart->save_cart(); - - $this->assertEquals( $this->_session->get_session_data( 'cart' ), $cart ); - } - - - -} -// End of file EE_Cart_Test.php -// Location: /tests/testcases/core/EE_Cart_Test.php diff --git a/tests/testcases/core/EE_Data_Migration_Manager_Test.php b/tests/testcases/core/EE_Data_Migration_Manager_Test.php deleted file mode 100644 index 7657dc28242..00000000000 --- a/tests/testcases/core/EE_Data_Migration_Manager_Test.php +++ /dev/null @@ -1,246 +0,0 @@ -get_all_data_migration_scripts_available(); - $this->assertArrayHasKey('EE_DMS_Core_4_1_0', $dms_classpaths); - $this->assertArrayHasKey('EE_DMS_Core_1_0_0',$dms_classpaths); - $this->assertArrayHasKey('EE_DMS_Core_4_2_0', $dms_classpaths); - $this->assertArrayHasKey('EE_DMS_Core_4_3_0', $dms_classpaths); -} - public function test_ensure_current_database_state_is_set(){ - $this->_pretend_current_code_state_is_at(espresso_version()); - $this->_pretend_current_db_state_is_at(); - $db_state = EE_Data_Migration_Manager::instance()->ensure_current_database_state_is_set(); - $this->assertArrayHasKey('Core',$db_state); - $this->assertEquals(espresso_version(), $db_state['Core']); - } - public function test_check_for_applicable_data_migration_scripts(){ - add_filter('FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',array($this,'add_mock_dms')); - $this->_pretend_current_db_state_is_at('3.1.37.7'); - $dmss = EE_Data_Migration_Manager::reset()->check_for_applicable_data_migration_scripts(); - //check it contains the DMSs that apply, and that they're ordered correctly - $this->assertInstanceOf( 'EE_DMS_Core_1_0_0', array_shift($dmss)); - $this->assertInstanceOf( 'EE_DMS_Core_4_1_0', array_shift($dmss)); - //pretend we already ran one DMS - $dms_done = EE_Registry::instance()->load_dms( 'Core_4_1_0' ); - $dms_done->set_completed(); - $this->_pretend_ran_dms($dms_done); - $dmss = EE_Data_Migration_Manager::instance()->check_for_applicable_data_migration_scripts(); - $this->assertArrayNotHasKey('EE_DMS_Core_4_1_0',$dmss); - $this->assertArrayHasKey('EE_DMS_Core_1_0_0',$dmss); - - //now pretend we're elsewhere in the migration where 4.2 should be ran - $this->_pretend_current_db_state_is_at('4.1.1'); - $dmss = EE_Data_Migration_Manager::instance()->check_for_applicable_data_migration_scripts(); - $this->assertArrayHasKey('EE_DMS_Core_4_2_0',$dmss); - - } - public function test_parse_dms_classname(){ - $details = EE_Data_Migration_Manager::instance()->parse_dms_classname("EE_DMS_Funky_4_8_12"); - $this->assertEquals("Funky",$details['slug']); - $this->assertEquals(4,$details['major_version']); - $this->assertEquals(8,$details['minor_version']); - $this->assertEquals(12,$details['micro_version']); - } - public function test_get_data_migrations_ran(){ - //make sure all DMSs are autoloaded - EE_Data_Migration_Manager::instance()->get_all_data_migration_scripts_available(); - $dms1 = EE_Registry::instance()->load_dms( 'Core_4_1_0' ); - $dms1->set_completed(); - $this->_pretend_ran_dms($dms1); - $dms_ran = EE_Data_Migration_Manager::instance()->get_data_migrations_ran(); - $this->assertArrayHasKey('Core', $dms_ran); - $this->assertArrayhasKey('4.1.0',$dms_ran['Core']); - } - public function test_get_most_up_to_date_dms(){ - EE_Data_Migration_Manager::reset(); - $dms_classname = EE_Data_Migration_Manager::instance()->get_most_up_to_date_dms(); - //yes, this test will need to be updated everytime we add a new core DMS - $this->assertEquals('EE_DMS_Core_4_9_0',$dms_classname); - } - - /** - * @group 7120 - */ - public function test_reattempt(){ - $dms41 = EE_Registry::instance()->load_dms( 'Core_4_1_0' ); - $dms41->set_completed(); - $dms42 = EE_Registry::instance()->load_dms( 'Core_4_2_0' ); - $dms42->set_broken(); - $this->_pretend_ran_dms($dms41); - $this->_pretend_ran_dms($dms42); - $last_ran_script = EE_Data_Migration_Manager::reset()->get_last_ran_script(); - $this->assertEquals($dms42,$last_ran_script); - $this->assertTrue( $last_ran_script->is_broken() ); - EE_Data_Migration_Manager::instance()->reattempt(); - $this->assertFalse( $last_ran_script->is_broken() ); - - - } - - public function test_get_last_ran_script(){ - $dms41 = EE_Registry::instance()->load_dms( 'Core_4_1_0' ); - $dms41->set_completed(); - $dms42 = EE_Registry::instance()->load_dms( 'Core_4_2_0' ); - $this->_pretend_ran_dms($dms41); - $this->_pretend_ran_dms($dms42); - $last_ran_script = EE_Data_Migration_Manager::reset()->get_last_ran_script(); - $this->assertEquals($dms42,$last_ran_script); - - //now if it's borked, we still should have found dms42 - $dms42->set_broken(); - $this->_pretend_ran_dms($dms42); - $last_ran_script = EE_Data_Migration_Manager::reset()->get_last_ran_script(); - $this->assertEquals($dms42,$last_ran_script); - - //all DMSs are complete, so we shouldn't find a current one - $dms42->set_completed(); - $this->_pretend_ran_dms($dms42); - $last_ran_script = EE_Data_Migration_Manager::reset()->get_last_ran_script(); - $this->assertNull($last_ran_script); - - //now what we're ok with finding a complete dms (we're not searching - //for a currently-executing one) - $last_ran_script = EE_Data_Migration_Manager::reset()->get_last_ran_script(TRUE); - $this->assertEquals($dms42,$last_ran_script); - } - - - - private function _pretend_ran_dms(EE_Data_Migration_Script_Base $dms_class){ - $details = EE_Data_Migration_Manager::instance()->parse_dms_classname(get_class($dms_class)); - $plugin_slug_for_use_in_option_name = $details['slug']."."; - $version_string = $details['major_version'].".".$details['minor_version'].".".$details['micro_version']; - update_option(EE_Data_Migration_Manager::data_migration_script_option_prefix.$plugin_slug_for_use_in_option_name.$version_string,$dms_class->properties_as_array()); - } - private function _pretend_current_code_state_is_at($code_version = NULL){ - if($code_version){ - $code_version_array = array($code_version => current_time('timestamp') - 1000); - update_option('espresso_db_update',$code_version_array); - }else{ - delete_option('espresso_db_update'); - } - } - private function _pretend_current_db_state_is_at($core_version = NULL){ - if( $core_version ){ - $current_db_state = array('Core'=>$core_version); - update_option(EE_Data_Migration_Manager::current_database_state,$current_db_state); - }else{ - delete_option(EE_Data_Migration_Manager::current_database_state); - } - } - private function _add_mock_dms(){ - add_filter('FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',array($this,'add_mock_dms')); - EE_Data_Migration_Manager::reset(); - } - private function _remove_mock_dms(){ - remove_filter('FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders',array($this,'add_mock_dms')); - } - public function add_mock_dms($dms_folders){ - $dms_folders[] = EE_TESTS_DIR . 'mocks/core/data_migration_scripts'; - return $dms_folders; - } - public function test_script_migrates_to_version(){ - $migrates_to = EE_Data_Migration_Manager::instance()->script_migrates_to_version('EE_DMS_Core_6_4_3'); - $this->assertEquals( 'Core', $migrates_to[ 'slug' ] ); - $this->assertEquals( '6.4.3', $migrates_to[ 'version' ] ); - } - - public function test_get_migration_ran(){ - $dms41 = EE_Registry::instance()->load_dms( 'Core_4_1_0' ); - $this->_pretend_ran_dms( $dms41 ); - $dms_found = EE_Data_Migration_Manager::reset()->get_migration_ran( '4.1.0', 'Core' ); - $this->assertEquals( $dms41->migrates_to_version(), $dms_found->migrates_to_version() ); - $dms_not_found = EE_Data_Migration_Manager::instance()->get_migration_ran( '4.2.0', 'Core' ); - $this->assertNull( $dms_not_found ); - } - - public function test_migration_has_run(){ - $dms41 = EE_Registry::instance()->load_dms( 'Core_4_1_0' ); - $this->_pretend_ran_dms( $dms41 ); - $this->assertTrue( EE_Data_Migration_Manager::reset()->migration_has_ran( '4.1.0', 'Core' ) ); - $this->assertFalse( EE_Data_Migration_Manager::instance()->migration_has_ran( '4.2.0', 'Core' ) ); - } - - /** - * @group 6910 - */ - public function test_enqueue_db_initialization_for(){ - EE_Data_Migration_Manager::reset()->enqueue_db_initialization_for( 'Core' ); - EE_Data_Migration_Manager::instance()->enqueue_db_initialization_for( 'Mock' ); - $this->assertEquals( array( 'Core', 'Mock' ), EE_Data_Migration_Manager::instance()->get_db_initialization_queue() ); - } - - /** - * @group 6910 - */ - public function test_get_db_initialization_queue(){ - update_option( EE_Data_Migration_Manager::db_init_queue_option_name, array( 'MockA', 'MockB' ) ); - $this->assertEquals( array( 'MockA', 'MockB' ), EE_Data_Migration_Manager::instance()->get_db_initialization_queue() ); - } - - /** - * @group 8328 - */ - public function test_database_needs_updating_to__exact_matches(){ - EE_Data_Migration_Manager::instance()->update_current_database_state_to( array( 'slug' => 'Core', 'version' => '4.9.0' ) ); - $this->assertFalse( EE_Data_Migration_Manager::instance()->database_needs_updating_to( array( 'slug' => 'Core', 'version' => '4.9.0' ) ) ); - } - - /** - * @group 8328 - */ - public function test_database_needs_updating_to__first_3_version_parts_matches(){ - EE_Data_Migration_Manager::instance()->update_current_database_state_to( array( 'slug' => 'Core', 'version' => '4.9.0.dev.123' ) ); - $this->assertFalse( EE_Data_Migration_Manager::instance()->database_needs_updating_to( array( 'slug' => 'Core', 'version' => '4.9.0.beta.432' ) ) ); - } - /** - * @group 8328 - */ - public function test_database_needs_updating_to__current_version_is_greater(){ - EE_Data_Migration_Manager::instance()->update_current_database_state_to( array( 'slug' => 'Core', 'version' => '4.9.0.dev.123' ) ); - $this->assertTrue( EE_Data_Migration_Manager::instance()->database_needs_updating_to( array( 'slug' => 'Core', 'version' => '4.9.3.dev.123' ) ) ); - } - - /** - * @group 8328 - */ - public function test_database_needs_updating_to__current_version_is_lower(){ - EE_Data_Migration_Manager::instance()->update_current_database_state_to( array( 'slug' => 'Core', 'version' => '4.9.0' ) ); - $this->assertFalse( EE_Data_Migration_Manager::instance()->database_needs_updating_to( array( 'slug' => 'Core', 'version' => '4.4.0.p' ) ) ); - } -} - -// End of file EE_Data_Migration_Manager_Test.php diff --git a/tests/testcases/core/EE_Data_Migration_Script_Base_Test.php b/tests/testcases/core/EE_Data_Migration_Script_Base_Test.php deleted file mode 100644 index 8adb09b100a..00000000000 --- a/tests/testcases/core/EE_Data_Migration_Script_Base_Test.php +++ /dev/null @@ -1,53 +0,0 @@ -load_dms( 'EE_DMS_Core_4_1_0' ); - for( $i = 0; $i < 60; $i++ ){ - $dms->add_error( 'error ' . $i ); - } - //count should be 51 because once we get to 50, it should stop adding them - $this->assertEquals( 51, count( $dms->get_errors() ) ); - $dms->add_error( 'force', TRUE ); - //count should be (50 / 2) + 2 (because we should have wiped the first half, then added two - $this->assertEquals( 27, count( $dms->get_errors() ) ); - //and check that the first one should be... error 25 because - $errors = $dms->get_errors(); - $first_error = array_shift( $errors ); - $this->assertEquals( 'error 25', $first_error ); - } -} - -// End of file EE_Data_Migration_Script_Base.php diff --git a/tests/testcases/core/EE_Dependency_Map_Test.php b/tests/testcases/core/EE_Dependency_Map_Test.php deleted file mode 100644 index ce72bab4f30..00000000000 --- a/tests/testcases/core/EE_Dependency_Map_Test.php +++ /dev/null @@ -1,218 +0,0 @@ -_dependency_map = EE_Dependency_Map::instance(); - } - - - public function tearDown() { - $this->_dependency_map->reset(); - parent::tearDown(); - } - - - /** - * @since 4.9.62.p - * @throws PHPUnit_Framework_AssertionFailedError - */ - public function test_core_dependencies() { - $this->validate_core_dependency_map( $this->_dependency_map->dependency_map() ); - } - - - - /** - * @param $dependencies_or_load - * @param string $classname - * @throws PHPUnit_Framework_AssertionFailedError - */ - public function validate_core_dependency_map( $dependencies_or_load, $classname = '' ) { - if ( is_array( $dependencies_or_load ) ) { - foreach ( $dependencies_or_load as $class_name => $dependency ) { - if ( $dependency !== null ) { - $this->validate_core_dependency_map( $dependency, $class_name ); - } - } - } else { - $classname = $this->_dependency_map->getFqnForAlias($classname); - // verify that a valid class constant has been set for the value - $this->assertEquals( - EE_Dependency_Map::load_new_object || EE_Dependency_Map::load_from_cache, - $dependencies_or_load, - sprintf( 'The %s class has an invalid value in the EE_Dependency_Map.', $classname ) - ); - // if class is not using PSR-4 compatible namespacing - if (strpos($classname,'\\') === false) { - // verify that a loader exists for the class - $loader = $this->_dependency_map->class_loader($classname); - $this->assertNotEmpty( - $loader, - sprintf('A class loader should be set for "%s" but appears to be missing.', $classname) - ); - } - } - } - - - /** - * @since 4.9.62.p - * @throws \PHPUnit\Framework\AssertionFailedError - * @throws \PHPUnit\Framework\Exception - */ - public function test_core_class_loaders() { - $skip = array( - 'EE_Admin' => 'messes with other unit tests', - 'EE_Session' => 'session doesn\'t load during unit tests', - 'EE_Messages_Template_Defaults' => 'Closure has required arguments' - ); - //loop through and verify the class loader can successfully load the class it is set for - foreach ( $this->_dependency_map->class_loaders() as $class => $loader ) { - if ( isset( $skip[ $class ] ) || strpos( $class, 'Command' ) !== false ) { - continue; - } - $dependency = $loader instanceof Closure ? $loader() : EE_Registry::instance()->$loader( $class ); - // helpers are simply loaded and do not return an instance - if ( $loader === 'load_helper' ) { - $this->assertTrue( $dependency ); - } else { - $this->assertInstanceOf( - $class, - $dependency, - sprintf( - 'The "%1$s" class has "%2$s" set as its loader, but instead of an object, we received "%3$s"', - $class, - $loader instanceof Closure ? print_r( $loader, true ) : $loader, - print_r( $dependency, true ) - ) - ); - } - } - } - - - /** - * @since 4.9.62.p - * @throws EE_Error - * @throws InvalidArgumentException - * @throws ReflectionException - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException - * @throws \PHPUnit\Framework\Exception - */ - public function test_core_class_loader_for_EE_Messages_Template_Defaults() { - /** @type EE_Message_Resource_Manager $Message_Resource_Manager */ - $Message_Resource_Manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' ); - $loader = $this->_dependency_map->class_loader('EE_Messages_Template_Defaults'); - $this->assertInstanceOf( 'Closure', $loader ); - $Messages_Template_Defaults = $loader( - array( - $Message_Resource_Manager->valid_messenger( 'html' ), - $Message_Resource_Manager->valid_message_type( 'invoice' ) - ) - ); - $this->assertInstanceOf( 'EE_Messages_Template_Defaults', $Messages_Template_Defaults ); - } - - - /** - * @since 4.9.62.p - * @throws DomainException - * @throws \PHPUnit\Framework\AssertionFailedError - */ - public function test_register_class_loader() { - EE_Dependency_Map::register_class_loader( 'Dummy_Class', 'load_lib' ); - $actual_class_loader = $this->_dependency_map->class_loader( 'Dummy_Class' ); - $this->assertNotEmpty( $actual_class_loader ); - $this->assertEquals( 'load_lib', $actual_class_loader ); - - $this->setExpectedException( - 'DomainException', - esc_html__('"dummy_loader" is not a valid loader method on EE_Registry.', 'event_espresso') - ); - EE_Dependency_Map::register_class_loader( 'Dummy_Class', 'dummy_loader' ); - } - - - /** - * @since 4.9.62.p - * @throws \PHPUnit\Framework\AssertionFailedError - */ - public function test_register_dependency() { - //test a successful registration. - $registered = EE_Dependency_Map::register_dependencies( 'Dummy_Class', array( 'EE_Something', 'EE_Something_Else' ) ); - $this->assertTrue( $registered ); - $actual_dependency_map = $this->_dependency_map->dependency_map(); - $this->assertTrue( isset( $actual_dependency_map['Dummy_Class'] ) ); - $this->assertEquals( array( 'EE_Something', 'EE_Something_Else' ), $actual_dependency_map['Dummy_Class'] ); - - //test a unsuccessful registration (cannot override an existing dependency. - $registered = EE_Dependency_Map::register_dependencies( 'Dummy_Class', array() ); - $this->assertFalse( $registered ); - } - - - /** - * can't easily extend EE_Dep_Map so - * just going to test all three methods together - * - * @throws \PHPUnit\Framework\AssertionFailedError - * @throws \PHPUnit\Framework\AssertionFailedError - */ - public function test_add_has_get_alias() - { - $interface = 'Dummy_Interface'; - $class_name = 'Dummy_Class'; - $this->assertFalse($this->_dependency_map->isAlias($interface)); - $this->_dependency_map->add_alias($class_name, $interface); - $this->assertTrue($this->_dependency_map->isAlias($interface)); - $this->assertEquals( - $class_name, - $this->_dependency_map->getFqnForAlias($interface) - ); - } - - - /** - * can't easily extend EE_Dep_Map so - * just going to test all three methods together - * - * @throws \PHPUnit\Framework\AssertionFailedError - * @throws \PHPUnit\Framework\AssertionFailedError - */ - public function test_add_has_get_alias_for_class() - { - $interface = 'Dummy_Interface_2'; - $class_name = 'Dummy_Class_2'; - $for_class = 'Other_Class'; - $this->assertFalse($this->_dependency_map->isAlias($interface, $for_class)); - $this->_dependency_map->add_alias($class_name, $interface, $for_class); - $this->assertTrue($this->_dependency_map->isAlias($interface, $for_class)); - $this->assertEquals( - $class_name, - $this->_dependency_map->getFqnForAlias($interface, $for_class) - ); - } - - - -} -// Location: tests/testcases/core/EE_Dependency_Map_Test.php diff --git a/tests/testcases/core/EE_Encryption_Test.php b/tests/testcases/core/EE_Encryption_Test.php deleted file mode 100644 index 345c20c6253..00000000000 --- a/tests/testcases/core/EE_Encryption_Test.php +++ /dev/null @@ -1,350 +0,0 @@ -encryption = EE_Encryption_Mock::instance(); - } - - - - /** - * @param int $length - * @return string - */ - private function generateRandomString($length = 10) - { - $characters = '0123456789 abcd efg hijk lmnop qrs tuv wxyz ABCD EFG HIJK LMNOP QRS TUV WXYZ'; - $charactersLength = strlen($characters); - $randomString = ''; - for ($i = 0; $i < $length; $i++) { - $randomString .= $characters[mt_rand(0, $charactersLength - 1)]; - } - return $randomString; - } - - - - /** - * @return string - */ - private function generatePropertyOrKeyName() - { - $property = str_replace(' ', '', $this->generateRandomString(mt_rand(5, 10))); - if(empty($property)) { - return $this->generatePropertyOrKeyName(); - } - return $property; - } - - - - /** - * @return string - */ - private function getString() - { - return 'LPT: Change all of your passwords to "incorrect" so that your computer just tells you when you forget!'; - } - - - - /** - * @return array - */ - private function getArrayData() - { - $array = array(); - $array_size = mt_rand(5, 10); - for ($x = 0; $x <= $array_size; $x++) { - $key = mt_rand(0, 1) - ? $this->generatePropertyOrKeyName() - : count($array); - $array[$key] = $this->generateRandomString(mt_rand(10, 50)); - } - return $array; - } - - - - /** - * @return stdClass - */ - private function getObjectData() - { - $object = new stdClass(); - $array_size = mt_rand(5, 10); - for ($x = 0; $x <= $array_size; $x++) { - $property = $this->generatePropertyOrKeyName(); - $object->{$property} = $this->generateRandomString(mt_rand(10, 50)); - } - return $object; - } - - - /** - * @param string $encrypt - * @param string $decrypt - * @param $data - * @param string $cipher_method - */ - private function runEncryptionTest($encrypt, $decrypt, $data, $cipher_method = '') - { - if($cipher_method !== '') { - $this->assertEquals( - $data, - unserialize( - $this->encryption->{$decrypt}( - $this->encryption->{$encrypt}( - serialize($data), - $cipher_method - ), - $cipher_method - ) - ) - ); - } else { - $this->assertEquals( - $data, - unserialize( - $this->encryption->{$decrypt}( - $this->encryption->{$encrypt}( - serialize($data) - ) - ) - ) - ); - } - } - - - - /** - * @return void - */ - public function testGetEncryptionKey() - { - $key = $this->encryption->get_encryption_key(); - $this->assertEquals( - get_option(EE_Encryption::ENCRYPTION_OPTION_KEY, ''), - $key - ); - } - - - /** - * @requires function openssl_encrypt - * @return void - * @throws RuntimeException - */ - public function testOpensslEncryption() - { - // with strings - $this->assertEquals( - $this->getString(), - $this->encryption->openssl_decrypt( - $this->encryption->openssl_encrypt( - $this->getString() - ) - ) - ); - // with arrays - $this->runEncryptionTest( - 'openssl_encrypt', - 'openssl_decrypt', - $this->getArrayData() - ); - // with objects - $this->runEncryptionTest( - 'openssl_encrypt', - 'openssl_decrypt', - $this->getObjectData() - ); - } - - - /** - * @requires function openssl_encrypt - * @return void - * @throws RuntimeException - */ - public function testOpensslEncryptionWithCipherMethods() - { - $cipher_methods = openssl_get_cipher_methods(); - foreach ($cipher_methods as $cipher_method) { - // only use ciphers that produce a vector - if(openssl_cipher_iv_length($cipher_method) !== false){ - // with strings - $this->assertEquals( - $this->getString(), - $this->encryption->openssl_decrypt( - $this->encryption->openssl_encrypt( - $this->getString(), - $cipher_method - ), - $cipher_method - ) - ); - // with arrays - $this->runEncryptionTest( - 'openssl_encrypt', - 'openssl_decrypt', - $this->getArrayData(), - $cipher_method - ); - // with objects - $this->runEncryptionTest( - 'openssl_encrypt', - 'openssl_decrypt', - $this->getObjectData(), - $cipher_method - ); - } - } - } - - - - /** - * @requires function mcrypt_encrypt - * @return void - * @throws RuntimeException - */ - public function testMcryptEncryption() - { - if (PHP_VERSION_ID >= 70100) { - $this->markTestSkipped( - 'The mcrypt extension is deprecated in PHP version 7.1 and therefore can not be tested.' - ); - } - $this->assertEquals( - $this->getString(), - $this->encryption->m_decrypt( - $this->encryption->m_encrypt( - $this->getString() - ) - ) - ); - $this->runEncryptionTest( - 'm_encrypt', - 'm_decrypt', - $this->getArrayData() - ); - $this->runEncryptionTest( - 'm_encrypt', - 'm_decrypt', - $this->getObjectData() - ); - } - - - - /** - * @return void - * @throws RuntimeException - */ - public function testAcmeEncryption() - { - $this->assertEquals( - $this->getString(), - $this->encryption->acme_decrypt( - $this->encryption->acme_encrypt( - $this->getString() - ) - ) - ); - $this->runEncryptionTest( - 'acme_encrypt', - 'acme_decrypt', - $this->getArrayData() - ); - $this->runEncryptionTest( - 'acme_encrypt', - 'acme_decrypt', - $this->getObjectData() - ); - } - - - /** - * @return void - * @throws RuntimeException - */ - public function testBase64StringEncoding() - { - $this->assertEquals( - $this->getString(), - $this->encryption->base64_string_decode( - $this->encryption->base64_string_encode( - $this->getString() - ) - ) - ); - } - - - /** - * @return void - * @throws RuntimeException - */ - public function testBase64UrlEncoding() - { - $url = 'http://eventespresso.com'; - $this->assertEquals( - $url, - $this->encryption->base64_url_decode( - $this->encryption->base64_url_encode($url) - ) - ); - } - - - /** - * @throws PHPUnit_Framework_AssertionFailedError - * @throws \PHPUnit\Framework\AssertionFailedError - * @throws \PHPUnit\Framework\AssertionFailedError - */ - public function testValidBase64() - { - $this->assertTrue( - $this->encryption->valid_base_64( - $this->encryption->base64_string_encode( - $this->getString() - ) - ) - ); - $this->assertFalse( - $this->encryption->valid_base_64( - $this->getString() - ) - ); - } - - -} -// testcases/core/EE_Encryption_Test.php diff --git a/tests/testcases/core/EE_Maintenance_Mode_Test.php b/tests/testcases/core/EE_Maintenance_Mode_Test.php deleted file mode 100644 index 940e36d0318..00000000000 --- a/tests/testcases/core/EE_Maintenance_Mode_Test.php +++ /dev/null @@ -1,100 +0,0 @@ -assertEquals( EE_Maintenance_Mode::level_0_not_in_maintenance, EE_Maintenance_Mode::instance()->level() ); - - //the DB is up-to-date, so we shouldn't be put into mm - EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); - $this->assertEquals( EE_Maintenance_Mode::level_0_not_in_maintenance, EE_Maintenance_Mode::instance()->level() ); - } - - public function test_set_mm_if_bd_old__remove_mm(){ - //now pretend the DB got borked somehow and we're in mm2 when we shouldn't be. this should fix it - EE_Maintenance_Mode::instance()->set_maintenance_level( EE_Maintenance_Mode::level_2_complete_maintenance ); - $this->assertEquals( EE_Maintenance_Mode::level_2_complete_maintenance, EE_Maintenance_Mode::instance()->level() ); - EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); - $this->assertEquals( EE_Maintenance_Mode::level_0_not_in_maintenance, EE_Maintenance_Mode::instance()->level() ); - } - public function test_set_mm_if_db_old__success(){ - $this->assertEquals( EE_Maintenance_Mode::level_0_not_in_maintenance, EE_Maintenance_Mode::instance()->level() ); - //we pretend teh DB state is out-of-date, so we should be put into mm - $this->_pretend_current_db_state_is_at('3.1.37.7'); - EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); - $this->assertEquals( EE_Maintenance_Mode::level_2_complete_maintenance, EE_Maintenance_Mode::instance()->level() ); - } - public function test_set_mm_if_db_old__in_mm1(){ - //put the site into mm1 and verify it doesn't get swapped to mm0 when we call set_mm_if_db_old - $this->assertEquals( EE_Maintenance_Mode::level_0_not_in_maintenance, EE_Maintenance_Mode::instance()->real_level() ); - EE_Maintenance_Mode::instance()->set_maintenance_level( EE_Maintenance_Mode::level_1_frontend_only_maintenance ); - $this->assertEquals( EE_Maintenance_Mode::level_1_frontend_only_maintenance, EE_Maintenance_Mode::instance()->real_level() ); - EE_Maintenance_Mode::instance()->set_maintenance_mode_if_db_old(); - $this->assertEquals( EE_Maintenance_Mode::level_1_frontend_only_maintenance, EE_Maintenance_Mode::instance()->real_level() ); - } - - public function test_set_maintenance_level(){ - $this->assertEquals( EE_Maintenance_Mode::level_0_not_in_maintenance, EE_Maintenance_Mode::instance()->real_level() ); - EE_Maintenance_Mode::instance()->set_maintenance_level( EE_Maintenance_Mode::level_1_frontend_only_maintenance ); - $this->assertEquals( EE_Maintenance_Mode::level_1_frontend_only_maintenance, EE_Maintenance_Mode::instance()->real_level() ); - EE_Maintenance_Mode::instance()->set_maintenance_level( EE_Maintenance_Mode::level_2_complete_maintenance ); - $this->assertEquals( EE_Maintenance_Mode::level_2_complete_maintenance, EE_Maintenance_Mode::instance()->real_level() ); - } - /** - * tests that EE_Maintenance_Mode::level() correctly pretend a site is - * NOT in maintenance mode for admin users only on frontend and ajax requests - * @global type $current_user - */ - public function test_maintenance_level(){ - global $current_user; - $this->assertFalse( is_admin() ); - $this->assertFalse( current_user_can( 'administrator' ) ); - EE_Maintenance_Mode::instance()->set_maintenance_level( EE_Maintenance_Mode::level_1_frontend_only_maintenance ); - $this->assertEquals( EE_Maintenance_Mode::level_1_frontend_only_maintenance, EE_Maintenance_Mode::instance()->level() ); - //now make the current user an admin, and maintenance mode shoudl be detected as 0 - - $current_user = $this->factory->user->create_and_get( array( 'role' => 'administrator' ) ); - $this->assertEquals( EE_Maintenance_Mode::level_0_not_in_maintenance, EE_Maintenance_Mode::instance()->level() ); - - } - public function test_zz(){ - $this->assertFalse( current_user_can( 'administrator' ) ); - } - /** - * @see EE_Migration_Manager_Test::_pretend_current_db_state_is_at which this was - * copied from. If it's used again, we should put this function into EE_UnitTestCase - * @param type $core_version - */ - private function _pretend_current_db_state_is_at($core_version = NULL){ - if( $core_version ){ - $current_db_state = array('Core'=>$core_version); - update_option(EE_Data_Migration_Manager::current_database_state,$current_db_state); - }else{ - delete_option(EE_Data_Migration_Manager::current_database_state); - } - } - - /** - * the DMS manager maintains a bit of state in order to be more efficient, which we want to lose between tests - */ - public function setUp(){ - parent::setUp(); - EE_Data_Migration_Manager::reset(); - } -} - -// End of file EE_Maintenance_Mode_Test.php \ No newline at end of file diff --git a/tests/testcases/core/EE_Object_Collection_Test.php b/tests/testcases/core/EE_Object_Collection_Test.php deleted file mode 100644 index b88df05dba7..00000000000 --- a/tests/testcases/core/EE_Object_Collection_Test.php +++ /dev/null @@ -1,107 +0,0 @@ -collection = new EE_Object_Collection_Mock(); - } - - public function test_add() { - // add ticket 1 - $ticket_1 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_price' => '5' ) ); - $this->assertCount( 0, $this->collection ); - $this->collection->add( $ticket_1 ); - $this->assertCount( 1, $this->collection ); - $this->assertContains( $ticket_1, $this->collection ); - // add ticket 2 - $ticket_2 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_price' => '6' ) ); - $this->collection->add( $ticket_2 ); - $this->assertCount( 2, $this->collection ); - $this->assertContains( $ticket_2, $this->collection ); - } - - public function test_set_info() { - // add ticket 1 - $ticket_1 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_price' => '5' ) ); - $this->collection->add( $ticket_1 ); - $this->collection->set_info( $ticket_1, 'ticket_1' ); - $this->assertEquals( $this->collection[ $ticket_1 ], 'ticket_1' ); - } - - public function test_get_by_info() { - $ticket_1 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_price' => '5' ) ); - $this->collection->add( $ticket_1, 'ticket_1' ); - $T1 = $this->collection->get_by_info( 'ticket_1' ); - $this->assertEquals( $ticket_1, $T1 ); - } - - public function test_has() { - $ticket_1 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_price' => '5' ) ); - $this->collection->add( $ticket_1 ); - $exists = $this->collection->has( $ticket_1 ); - $this->assertEquals( $exists, true ); - } - - public function test_remove() { - // add ticket 1 - $ticket_1 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_price' => '5' ) ); - $this->collection->add( $ticket_1 ); - // add ticket 2 - $ticket_2 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_price' => '6' ) ); - $this->collection->add( $ticket_2 ); - $this->assertCount( 2, $this->collection ); - // remove ticket 1 - $this->collection->remove( $ticket_1 ); - $this->assertNotContains( $ticket_1, $this->collection ); - $this->assertCount( 1, $this->collection ); - // remove ticket 2 - $this->collection->remove( $ticket_2 ); - $this->assertNotContains( $ticket_2, $this->collection ); - $this->assertCount( 0, $this->collection ); - } - - public function test_set_current() { - $ticket_1 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_name' => 'ticket-1', 'TKT_price' => '5' ) ); - $ticket_2 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_name' => 'ticket-2', 'TKT_price' => '6' ) ); - $ticket_3 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_name' => 'ticket-3', 'TKT_price' => '7' ) ); - $this->collection->add( $ticket_1 ); - $this->collection->add( $ticket_2 ); - $this->collection->add( $ticket_3 ); - $this->collection->rewind(); - $this->collection->set_current( $ticket_3 ); - $this->assertEquals( $this->collection->current()->name(), 'ticket-3' ); - } - - public function test_set_current_by_info() { - $ticket_1 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_name' => 'ticket-1', 'TKT_price' => '5' ) ); - $ticket_2 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_name' => 'ticket-2', 'TKT_price' => '6' ) ); - $ticket_3 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_name' => 'ticket-3', 'TKT_price' => '7' ) ); - $this->collection->add( $ticket_1 ); - $this->collection->add( $ticket_2 ); - $this->collection->add( $ticket_3 ); - $this->collection->set_info( $ticket_3, '7-dollar-ticket' ); - $this->collection->rewind(); - $this->collection->set_current_by_info( '7-dollar-ticket' ); - $this->assertEquals( $this->collection->current()->name(), 'ticket-3' ); - } - -} -// End of file EE_Object_Collection_Test.php -// Location: /tests/testcases/core/EE_Object_Collection_Test.php \ No newline at end of file diff --git a/tests/testcases/core/EE_Object_Repository_Test.php b/tests/testcases/core/EE_Object_Repository_Test.php deleted file mode 100644 index 5310ba5a2d2..00000000000 --- a/tests/testcases/core/EE_Object_Repository_Test.php +++ /dev/null @@ -1,69 +0,0 @@ -repository = new EE_Object_Repository_Mock(); - } - - public function test_persist() { - $ticket_1 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_price' => '5' ), false ); - $this->repository->add( $ticket_1 ); - $this->assertTrue( $this->repository->has( $ticket_1 ) ); - $this->assertEquals( $ticket_1->ID(), 0 ); - $this->assertEquals( count( $this->repository ), 1 ); - $saved = false; - $this->repository->rewind(); - while ( $this->repository->valid() ) { - if ( $this->repository->current() === $ticket_1 ) { - $saved = $this->repository->persist(); - $this->assertNotEquals( $this->repository->current()->ID(), 0 ); - $this->assertEquals( $this->repository->current()->ID(), $ticket_1->ID() ); - break; - } - $this->repository->next(); - } - $this->assertNotEquals( $saved, false ); - } - - - - - public function test_persist_all() { - $ticket_1 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_price' => '5' ), false ); - $ticket_2 = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_price' => '6' ), false ); - $this->repository->add( $ticket_1 ); - $this->repository->add( $ticket_2 ); - $this->assertTrue( $this->repository->has( $ticket_1 ) ); - $this->assertTrue( $this->repository->has( $ticket_2 ) ); - $this->assertEquals( count( $this->repository ), 2 ); - $this->assertEquals( $ticket_1->ID(), 0 ); - $this->assertEquals( $ticket_2->ID(), 0 ); - $saved = $this->repository->persist_all(); - $this->assertEquals( $saved, true ); - $this->assertNotEquals( $ticket_1->ID(), 0 ); - $this->assertNotEquals( $ticket_2->ID(), 0 ); - } - - - -} -// End of file EE_Object_Repository_Test.php -// Location: /tests/testcases/core/EE_Object_Repository_Test.php \ No newline at end of file diff --git a/tests/testcases/core/EE_Payment_Processor_Test.php b/tests/testcases/core/EE_Payment_Processor_Test.php deleted file mode 100644 index 72f3365ab9f..00000000000 --- a/tests/testcases/core/EE_Payment_Processor_Test.php +++ /dev/null @@ -1,548 +0,0 @@ -_pretend_addon_hook_time(); - EE_Register_Payment_Method::register( - 'onsite', - array( - 'payment_method_paths' => array( - EE_TESTS_DIR . 'mocks' . DS . 'payment_methods' . DS . 'Mock_Onsite', - ), - ) - ); - EE_Register_Payment_Method::register( - 'offsite', - array( - 'payment_method_paths' => array( - EE_TESTS_DIR . 'mocks' . DS . 'payment_methods' . DS . 'Mock_Offsite', - ), - ) - ); - EE_Payment_Method_Manager::instance()->reset(); - //remove all actions that have been added by messages because we aren't testing them here. - remove_all_actions( 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful' ); - remove_all_actions( 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__no_payment_made' ); - remove_all_actions( 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__not_successful' ); - remove_all_actions( 'AHEE__EE_Payment_Processor__update_txn_based_on_payment' ); - } - - - - public function tearDown() { - EE_Register_Payment_Method::deregister( 'onsite' ); - EE_Register_Payment_Method::deregister( 'offsite' ); - parent::tearDown(); - } - - - - /** - * Creates a transaction with all valid data (ie, it's for an event that has - * datetimes and tickets etc) - * - * @return EE_Transaction - * @throws \EE_Error - */ - protected function _new_typical_transaction() { - /** @type EE_Transaction $transaction */ - $transaction = $this->new_model_obj_with_dependencies( 'Transaction', array( 'TXN_total' => 10.00 ) ); - $ticket = $this->get_ticket_mock(); - $user = $this->get_wp_user_mock( 'administrator' ); - $event = $this->get_event_mock( $user ); - $registration = $this->get_registration_mock( $transaction, $ticket, $event, 10.00 ); - $transaction->_add_relation_to( $registration, 'Registration' ); - /** @type EE_Datetime $dtt */ - $dtt = $this->new_model_obj_with_dependencies( - 'Datetime', - array( - 'EVT_ID' => $event->ID(), - 'DTT_EVT_start' => current_time( 'timestamp' ) + 60 * 60, - 'DTT_EVT_end' => current_time( 'timestamp' ) + 5 * 60 * 60, - ) - ); - $dtt->_add_relation_to( $ticket, 'Ticket' ); - $transaction->set_reg_steps( - array( - 'attendee_information' => true, - 'payment_options' => true, - 'finalize_registration' => current_time( 'timestamp' ), - ) - ); - return $transaction; - } - - - - /** - * @param string $role - * @return \WP_User - */ - public function get_wp_user_mock( $role = 'administrator' ) { - /** @type WP_User $user */ - $user = $this->factory->user->create_and_get(); - $user->add_role( $role ); - return $user; - } - - - - /** - * @param float $TKT_price - * @return \EE_Ticket - * @throws \EE_Error - */ - public function get_ticket_mock( $TKT_price = 10.00 ) { - return $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_price' => $TKT_price ) ); - } - - - - /** - * @param \WP_User $EVT_wp_user - * @return \EE_Event - * @throws \EE_Error - */ - public function get_event_mock( WP_User $EVT_wp_user = null ) { - return $this->new_model_obj_with_dependencies( 'Event', array( 'EVT_wp_user' => $EVT_wp_user->ID ) ); - } - - - - /** - * @param \EE_Transaction $transaction - * @param \EE_Ticket $ticket - * @param \EE_Event $event - * @param float $REG_final_price - * @return \EE_Registration - * @throws \EE_Error - */ - public function get_registration_mock( - EE_Transaction $transaction, - EE_Ticket $ticket, - EE_Event $event, - $REG_final_price = 10.00 - ) { - return $this->new_model_obj_with_dependencies( - 'Registration', - array( - 'TXN_ID' => $transaction->ID(), - 'TKT_ID' => $ticket->ID(), - 'EVT_ID' => $event->ID(), - 'REG_final_price' => $REG_final_price, - 'REG_count' => EEM_Registration::PRIMARY_REGISTRANT_COUNT, - ) - ); - } - - - - /** - * Gets the actual payment status in the database (useful for verifying a payment has actually been updated) - * - * @global WPDB $wpdb - * @param EE_Payment $payment - * @return string - * @throws \EE_Error - */ - protected function _get_payment_status_in_db( EE_Payment $payment ) { - global $wpdb; - $esp_payment = $payment->get_model()->table(); - return $wpdb->get_var( $wpdb->prepare( "SELECT STS_ID FROM $esp_payment WHERE PAY_ID = %d", $payment->ID() ) ); - } - - - - /** - * @group 7753 - * @throws \EE_Error - */ - public function test_process_payment__onsite__success() { - //setup all the $_REQUEST globals etc because messages require them - $this->go_to( 'http://localhost/' ); - /** @type EE_Payment_Method $pm */ - $pm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Mock_Onsite' ) ); - $transaction = $this->_new_typical_transaction(); - $billing_form = $pm->type_obj()->billing_form( $transaction ); - $billing_form->receive_form_submission( - array( - 'status' => EEM_Payment::status_id_approved, - 'credit_card' => '4111 1111 1111 1111', - 'exp_month' => '12', - 'exp_year' => '2032', - 'cvv' => '123', - ) - ); - global $wp_actions; - $successful_payment_actions = EEH_Array::is_set( - $wp_actions, - 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful', - 0 - ); - $payment_actions = EEH_Array::is_set( - $wp_actions, - 'AHEE__EE_Payment_Processor__update_txn_based_on_payment', - 0 - ); - add_action( - 'AHEE__EE_Payment_Processor__update_txn_based_on_payment', - array( $this, 'assert_payment_message_trigger_for_success' ), - 10, - 2 - ); - /** @type EE_Payment_Processor $payment_processor */ - $payment_processor = EE_Registry::instance()->load_core( 'Payment_Processor' ); - $payment = $payment_processor->process_payment( - $pm, - $transaction, - null, - $billing_form, - 'success', - 'CART', - true, - true - ); - $this->assertInstanceOf( 'EE_Payment', $payment ); - //verify it's already been saved - $this->assertNotEquals( 0, $payment->ID() ); - $this->assertEquals( EEM_Payment::status_id_approved, $payment->status() ); - $this->assertEquals( EEM_Payment::status_id_approved, $this->_get_payment_status_in_db( $payment ) ); - $this->assertEquals( - $successful_payment_actions + 1, - $wp_actions['AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful'] - ); - $this->assertEquals( - $payment_actions + 1, - $wp_actions['AHEE__EE_Payment_Processor__update_txn_based_on_payment'] - ); - } - - - - /** - * Asserts that the payment's status is approved when the hook is called - * - * @param EE_Payment $transaction - * @param EE_Payment $payment - */ - public function assert_payment_message_trigger_for_success( $transaction, $payment ) { - $this->assertEquals( EEM_Payment::status_id_approved, $payment->get( 'STS_ID' ) ); - } - - - - public function test_update_txn_based_on_payment() { - //create a txn, and an UNSAVED payment. then call this. - /** @type EE_Transaction $txn */ - $txn = $this->new_model_obj_with_dependencies( - 'Transaction', - array( - 'STS_ID' => EEM_Transaction::incomplete_status_code, - 'TXN_total' => 10.00, - ) - ); - $ticket = $this->get_ticket_mock(); - $user = $this->get_wp_user_mock( 'administrator' ); - $event = $this->get_event_mock( $user ); - $registration = $this->get_registration_mock( $txn, $ticket, $event, 10.00 ); - $txn->_add_relation_to( $registration, 'Registration' ); - /** @type EE_Payment $payment */ - $payment = $this->new_model_obj_with_dependencies( - 'Payment', - array( - 'TXN_ID' => $txn->ID(), - 'STS_ID' => EEM_Payment::status_id_approved, - 'PAY_amount' => 10.00, - ), - false - ); - // simulate payment save performed in EE_PMT_Base::process_payment() - $payment->save(); - //$this->new_model_obj_with_dependencies( 'Registration', array( 'TXN_ID' => $txn->ID(), 'REG_count' => 1 ) ); - $this->assertEquals( EEM_Payment::status_id_approved, $payment->status() ); - /** @type EE_Payment_Processor $payment_processor */ - $payment_processor = EE_Registry::instance()->load_core( 'Payment_Processor' ); - $payment_processor->update_txn_based_on_payment( $txn, $payment ); - //the payment should have been saved, and the txn appropriately updated - $this->assertEquals( EEM_Payment::status_id_approved, $payment->status() ); - $this->assertEquals( $payment, $txn->last_payment() ); - $this->assertEquals( 10.00, $payment->amount() ); - $this->assertEquals( $txn->ID(), $payment->get( 'TXN_ID' ) ); - /** @type EE_Transaction_Payments $transaction_payments */ - $transaction_payments = EE_Registry::instance()->load_class( 'Transaction_Payments' ); - $this->assertEquals( - 10.00, - $transaction_payments->recalculate_total_payments_for_transaction( - $txn, - EEM_Payment::status_id_approved - ) - ); - $this->assertEquals( 10.00, $txn->paid() ); - $this->assertEquals( EEM_Transaction::complete_status_code, $txn->status_ID() ); - } - - - - public function test_update_txn_based_on_payment__offline() { - //create a txn, and an UNSAVED payment. then call this. - /** @type EE_Transaction $txn */ - $txn = $this->new_model_obj_with_dependencies( - 'Transaction', - array( - 'STS_ID' => EEM_Transaction::incomplete_status_code, - 'TXN_total' => 10, - ) - ); - /** @type EE_Payment $payment */ - $payment = $this->new_model_obj_with_dependencies( - 'Payment', - array( - 'TXN_ID' => $txn->ID(), - 'STS_ID' => EEM_Payment::status_id_pending, - 'PAY_amount' => 0, - ), - false - ); - //because this is from an OFFLINE gateway, the payment shouldn't be saved - $this->assertEquals( EEM_Payment::status_id_pending, $payment->status() ); - /** @type EE_Payment_Processor $payment_processor */ - $payment_processor = EE_Registry::instance()->load_core( 'Payment_Processor' ); - $payment_processor->update_txn_based_on_payment( $txn, $payment ); - //the payment should have NOT been saved, and the txn appropriately updated - $this->assertEquals( EEM_Payment::status_id_pending, $payment->status() ); - $this->assertEquals( 0, $payment->ID() ); - $this->assertEquals( null, $txn->last_payment() ); - $this->assertEquals( 0, $payment->amount() ); - $this->assertEquals( $txn->ID(), $payment->get( 'TXN_ID' ) ); - /** @type EE_Transaction_Payments $transaction_payments */ - $transaction_payments = EE_Registry::instance()->load_class( 'Transaction_Payments' ); - $this->assertEquals( - 0, - $transaction_payments->recalculate_total_payments_for_transaction( - $txn, - EEM_Payment::status_id_approved - ) - ); - $this->assertEquals( 0, $txn->paid() ); - $this->assertEquals( EEM_Transaction::incomplete_status_code, $txn->status_ID() ); - } - - - - public function test_process_payment__onsite__declined() { - /** @type EE_Payment_Method $pm */ - $pm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Mock_Onsite' ) ); - $transaction = $this->_new_typical_transaction(); - $billing_form = $pm->type_obj()->billing_form( $transaction ); - $billing_form->receive_form_submission( - array( - 'status' => EEM_Payment::status_id_declined, - 'credit_card' => '4111 1111 1111 1111', - 'exp_month' => '12', - 'exp_year' => '2032', - 'cvv' => '123', - ) - ); - global $wp_actions; - $successful_payment_actions = EEH_Array::is_set( - $wp_actions, - 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful', - 0 - ); - /** @type EE_Payment_Processor $payment_processor */ - $payment_processor = EE_Registry::instance()->load_core( 'Payment_Processor' ); - $payment = $payment_processor->process_payment( - $pm, - $transaction, - null, - $billing_form, - 'success', - 'CART', - true, - true - ); - $this->assertInstanceOf( 'EE_Payment', $payment ); - //verify it's already been saved - $this->assertNotEquals( 0, $payment->ID() ); - $this->assertEquals( EEM_Payment::status_id_declined, $payment->status() ); - $this->assertEquals( EEM_Payment::status_id_declined, $this->_get_payment_status_in_db( $payment ) ); - $this->assertEquals( - $successful_payment_actions, - EEH_Array::is_set( - $wp_actions, - 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful', - 0 - ) - ); - } - - - - /** - * @throws \EE_Error - * @throws \Exception - */ - public function test_process_payment__offsite__declined_then_approved() { - global $wp_actions; - /** @type EE_Payment_Processor $payment_processor */ - $payment_processor = EE_Registry::instance()->load_core( 'Payment_Processor' ); - /** @type EE_Payment_Method $pm */ - $pm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Mock_Offsite' ) ); - $transaction = $this->_new_typical_transaction(); - $successful_payment_actions = EEH_Array::is_set( - $wp_actions, - 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful', - 0 - ); - $payment = $payment_processor->process_payment( $pm, $transaction, null, null, 'success', 'CART', true, true ); - $this->assertInstanceOf( 'EE_Payment', $payment ); - //verify it's already been saved - $this->assertNotEquals( 0, $payment->ID() ); - //assert that the payment still has its default status - $this->assertEquals( - EEM_Payment::instance()->field_settings_for( 'STS_ID' )->get_default_value(), - $payment->status() - ); - $this->assertEquals( - EEM_Payment::instance()->field_settings_for( 'STS_ID' )->get_default_value(), - $this->_get_payment_status_in_db( $payment ) - ); - //assert that the we haven't notified of successful payment JUST yet... - $this->assertEquals( - $successful_payment_actions, - EEH_Array::is_set( - $wp_actions, - 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful', - 0 - ) - ); - //PENDING IPN - $payment = $payment_processor->process_ipn( - array( 'status' => EEM_Payment::status_id_pending, 'gateway_txn_id' => $payment->txn_id_chq_nmbr() ), - $transaction, - $pm - ); - $this->assertEquals( EEM_Payment::status_id_pending, $payment->status() ); - $this->assertEquals( EEM_Payment::status_id_pending, $this->_get_payment_status_in_db( $payment ) ); - //and the payment-approved action should have NOT been triggered - $this->assertEquals( - $successful_payment_actions, - EEH_Array::is_set( - $wp_actions, - 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful', - 0 - ) - ); - //APPROVED IPN - $payment = $payment_processor->process_ipn( - array( 'status' => EEM_Payment::status_id_approved, 'gateway_txn_id' => $payment->txn_id_chq_nmbr() ), - $transaction, - $pm - ); - //payment should be what the gateway set it to be, which was approved - $this->assertEquals( EEM_Payment::status_id_approved, $payment->status() ); - $this->assertEquals( EEM_Payment::status_id_approved, $this->_get_payment_status_in_db( $payment ) ); - //and the payment-approved action should have been triggered - $this->assertEquals( - $successful_payment_actions + 1, - EEH_Array::is_set( - $wp_actions, - 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful', - 0 - ) - ); - //DUPLICATE SUCCESS IPN - //for this, we need to reset payment model so we fetch a NEW payment object, instead of reusing the old - //and because the payment method caches a payment method type which caches a gateway which caches the payment model, - //we also need to reset the payment method - EEM_Payment::reset(); - $pm = EEM_Payment_Method::reset()->get_one_by_ID( $pm->ID() ); - $payment = $payment_processor->process_ipn( - array( 'status' => EEM_Payment::status_id_approved, 'gateway_txn_id' => $payment->txn_id_chq_nmbr() ), - $transaction, - $pm - ); - //payment should be what the gateway set it to be, which was failed - $this->assertEquals( EEM_Payment::status_id_approved, $payment->status() ); - //and the payment-approved action should have NOT been triggered this time because it's a duplicate - $this->assertEquals( - $successful_payment_actions + 1, - EEH_Array::is_set( - $wp_actions, - 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful', - 0 - ) - ); - } - - - - public function test_process_payment__offline() { - /** @type EE_Payment_Method $pm */ - $pm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Admin_Only' ) ); - $transaction = $this->_new_typical_transaction(); - global $wp_actions; - $successful_payment_actions = EEH_Array::is_set( - $wp_actions, - 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__no_payment_made', - 0 - ); - /** @type EE_Payment_Processor $payment_processor */ - $payment_processor = EE_Registry::instance()->load_core( 'Payment_Processor' ); - $payment = $payment_processor->process_payment( $pm, $transaction, null, null, 'success', 'CART', true, true ); - // offline payments are not saved... because no payment ever actually happened - $this->assertEquals( 0, $payment->ID() ); - $this->assertEquals( EEM_Transaction::incomplete_status_code, $transaction->status_ID() ); - $this->assertEquals( - $successful_payment_actions + 1, - $wp_actions['AHEE__EE_Payment_Processor__update_txn_based_on_payment__no_payment_made'] - ); - } - - - - /** - * @group 7201 - * @throws \EE_Error - * @throws \Exception - */ - public function test_process_ipn() { - /** @type EE_Payment_Method $pm */ - $pm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Mock_Offsite' ) ); - $this->assertInstanceOf( 'EE_PMT_Mock_Offsite', $pm->type_obj() ); - $this->assertInstanceOf( 'EEG_Mock_Offsite', $pm->type_obj()->get_gateway() ); - $txn = $this->new_typical_transaction(); - //we don't want to bother sending messages. We're not wanting ot test that right now - remove_all_filters( 'AHEE__EE_Payment_Processor__update_txn_based_on_payment__successful' ); - $payment = EE_Payment_Processor::instance()->process_payment( $pm, $txn ); - $fake_req_data = array( - 'gateway_txn_id' => $payment->txn_id_chq_nmbr(), - 'status' => EEM_Payment::status_id_approved, - ); - $this->assertNotEmpty( $payment->ID() ); - $payment = EE_Payment_Processor::instance()->process_ipn( $fake_req_data, $txn, $pm->slug() ); - $this->assertInstanceOf( 'EE_Payment', $payment ); - $this->assertEquals( EEM_Payment::status_id_approved, $payment->STS_ID() ); - $this->assertEquals( EEM_Payment::status_id_approved, $this->_get_payment_status_in_db( $payment ) ); - } - - - -} -// End of file EE_Payment_Processor_Test.php -// Location: tests/testcases/core/EE_Payment_Processor_Test.php diff --git a/tests/testcases/core/EE_Payment_Processor_With_Messages_Test.php b/tests/testcases/core/EE_Payment_Processor_With_Messages_Test.php deleted file mode 100644 index 6c73eb1aea5..00000000000 --- a/tests/testcases/core/EE_Payment_Processor_With_Messages_Test.php +++ /dev/null @@ -1,54 +0,0 @@ -_pretend_addon_hook_time(); - EE_Register_Payment_Method::register('onsite', array( - 'payment_method_paths'=>array( - EE_TESTS_DIR . 'mocks' . DS . 'payment_methods' . DS . 'Mock_Onsite' - ) - )); - EE_Register_Payment_Method::register('offsite',array( - 'payment_method_paths' => array( - EE_TESTS_DIR . 'mocks' . DS . 'payment_methods' . DS . 'Mock_Offsite' - ) - )); - EE_Payment_Method_Manager::instance()->reset(); - - //unlike EE_Payment_Processor_With_Messages, this is integration testing - //and so we want to leave messages hooks in-place - - } - public function tearDown(){ - EE_Register_Payment_Method::deregister( 'onsite' ); - EE_Register_Payment_Method::deregister( 'offsite' ); - parent::tearDown(); - } -} - -// End of file EE_Payment_Processor_Test.php diff --git a/tests/testcases/core/EE_Registry_Test.php b/tests/testcases/core/EE_Registry_Test.php deleted file mode 100644 index da7e1bbe5d1..00000000000 --- a/tests/testcases/core/EE_Registry_Test.php +++ /dev/null @@ -1,758 +0,0 @@ - EE_Dependency_Map::load_from_cache, - 'EE_Encryption' => EE_Dependency_Map::load_from_cache - ) - ); - EE_Dependency_Map::register_dependencies( - 'EE_Injector_Tester_With_Array_Session_Int_Constructor_Params', - array( 'EE_Session_Mock' => EE_Dependency_Map::load_from_cache ) - ); - EE_Dependency_Map::register_class_loader( 'EE_Session_Mock' ); - EE_Dependency_Map::register_class_loader( 'EE_Injector_Tester_With_Array_Session_Int_Constructor_Params' ); - require_once EE_TESTS_DIR . 'mocks' . DS . 'core' . DS . 'EE_Registry_Mock.core.php'; - $loader = LoaderFactory::getLoader(); - EE_Registry_Mock::instance( - EE_Dependency_Map::instance(), - $loader->getShared('EventEspresso\core\services\container\Mirror'), - $loader->getShared('EventEspresso\core\services\loaders\ClassInterfaceCache'), - $loader->getShared('EventEspresso\core\services\loaders\ObjectIdentifier') - ); - EE_Registry_Mock::instance()->initialize(); - parent::setUp(); - } - - - - /** - * @param array $class_abbreviations - * @return array - */ - public function unit_test_registry_class_abbreviations( $class_abbreviations = array() ) { - $class_abbreviations[ 'EE_Session_Mock' ] = 'SSN'; - return $class_abbreviations; - } - - - - /** - * @param array $core_paths - * @return array - */ - public function unit_test_registry_core_paths( $core_paths = array() ) { - $core_paths[] = EE_TESTS_DIR . 'mocks' . DS . 'core' . DS; - return $core_paths; - } - - - - - /** - * this tests that objects cached using the EE_Registry class abbreviations can be retrieved - * - * @group 8284 - * @author Brent Christensen - */ - public function test_get_cached_class_abbreviations() { - // verify that EE_Network_Config has not already been loaded - $cached_class = EE_Registry_Mock::instance()->get_cached_class( 'EE_Network_Config' ); - $this->assertEquals( null, $cached_class ); - // create a stdClass object will use to mock the EE_Network_Config class - $orig_class = new stdClass(); - $orig_class->name = 'EE_Network_Config'; - // and manually cache it at EE_Registry_Mock::instance()->NET_CFG - EE_Registry_Mock::instance()->NET_CFG = $orig_class; - // now attempt to retrieve it - $cached_class = EE_Registry_Mock::instance()->get_cached_class( 'EE_Network_Config' ); - $this->assertEquals( $orig_class->name, $cached_class->name ); - // remove what we added - EE_Registry_Mock::instance()->NET_CFG = null; - } - - - - /** - * this tests that objects cached directly as EE_Registry_Mock properties can be retrieved - * - * @group 8284 - * @author Brent Christensen - */ - public function test_get_cached_class_property() { - // verify that "Some_Class" has not already been loaded - $cached_class = EE_Registry_Mock::instance()->get_cached_class( 'Some_Class' ); - $this->assertEquals( null, $cached_class ); - // create a stdClass object will use to mock the class - $orig_class = new stdClass(); - $orig_class->name = 'Some_Class'; - // and manually cache it at EE_Registry_Mock::instance()->Some_Class - EE_Registry_Mock::instance()->Some_Class = $orig_class; - // now attempt to retrieve it - $cached_class = EE_Registry_Mock::instance()->get_cached_class( 'Some_Class' ); - $this->assertEquals( $orig_class->name, $cached_class->name ); - } - - - - /** - * this tests that objects cached on EE_Registry->LIB can be retrieved - * - * @group 8284 - * @author Brent Christensen - */ - public function test_get_cached_class_library() { - // verify that "Library_Class" has not already been loaded - $cached_class = EE_Registry_Mock::instance()->get_cached_class( 'Library_Class' ); - $this->assertEquals( null, $cached_class ); - // create a stdClass object will use to mock the class - $orig_class = new stdClass(); - $orig_class->name = 'Library_Class'; - // and manually cache it at EE_Registry_Mock::instance()->Some_Class - EE_Registry_Mock::instance()->LIB->Library_Class = $orig_class; - // now attempt to retrieve it - $cached_class = EE_Registry_Mock::instance()->get_cached_class( 'Library_Class' ); - $this->assertEquals( $orig_class->name, $cached_class->name ); - } - - - - /** - * this tests that objects cached on EE_Registry->addons can be retrieved - * - * @group 8284 - * @author Brent Christensen - */ - public function test_get_cached_class_addon() { - // verify that "Addon_Class" has not already been loaded - $cached_class = EE_Registry_Mock::instance()->get_cached_class( 'Addon_Class', 'addon' ); - $this->assertEquals( null, $cached_class ); - // create a stdClass object will use to mock the class - $orig_class = new stdClass(); - $orig_class->name = 'Addon_Class'; - // and manually cache it at EE_Registry_Mock::instance()->addons->Addon_Class - EE_Registry_Mock::instance()->addons->Addon_Class = $orig_class; - // now attempt to retrieve it - $cached_class = EE_Registry_Mock::instance()->get_cached_class( 'Addon_Class', 'addon' ); - $this->assertEquals( $orig_class->name, $cached_class->name ); - } - - - /** - * This tests that the _file_loaded_for_class property is retrieved/utilized properly when load_only flag is set to - * true on the EE_Registry instance. - * @author Darren Ethier - */ - public function test__load_with_load_only_flag() { - // now do a object load request for EE_Answer - $class_loaded = EE_Registry_Mock::instance()->load_class( 'EE_Answer' ); - $this->assertInstanceOf( 'EE_Answer', $class_loaded ); - // now verify that with the $load_only flag set to true, that boolean true is returned - $file_loaded = EE_Registry_Mock::instance()->load( - array( EE_CLASSES ), - 'EE_', - 'EE_Answer', - 'class', - array(), - false, - true, - true // LOAD ONLY FLAG SET TO TRUE - ); - $this->assertTrue( $file_loaded ); - - } - - - /** - * Same as previous test except we do a load only call first. The second call should return the cached object - * and NOT true. - * @author Darren Ethier - * @group 9326 - */ - public function test__load_with_load_only_flag_set_true_on_first_load() { - //do load only - $loaded = EE_Registry_Mock::instance()->load_class( - 'EE_Answer', - array(), - false, - true, - true //load only set to true. - ); - - //should return true - $this->assertTrue( $loaded ); - //should be able to access the class now - $this->assertTrue( class_exists( 'EE_Answer', false ) ); - - //now try to grab an instance of EE_Answer - $class_instance = EE_Registry_Mock::instance()->load_class( 'EE_Answer' ); - $this->assertInstanceOf( 'EE_Answer', $class_instance ); - } - - - - - /** - * this tests that paths to EE class files can be resolved correctly - * - * @group 8284 - * @author Brent Christensen - */ - public function test_resolve_path(){ - // try to find the path to the EE_Session class - $this->assertEquals( - // expected - str_replace( array( '\\', '/' ), DS, EE_CORE . 'EE_Session.core.php' ), - // actual - EE_Registry_Mock::instance()->resolve_path( - 'EE_Session', - 'core', - array( - EE_CORE, - EE_ADMIN, - EE_CPTS, - EE_CORE . 'data_migration_scripts' . DS - ) - ) - ); - } - - - - - /** - * this tests that EE class files can be loaded correctly - * - * @group 8284 - * @author Brent Christensen - */ - public function test_require_file(){ - // first verify that EE_Class_For_Testing_Loading is not already loaded - // (made sure to set the class_exists() autoload param to false) - $this->assertEquals( false, class_exists( 'EE_Class_For_Testing_Loading', false ) ); - // let's attempt to load the EE_Cart - EE_Registry_Mock::instance()->require_file( - EE_MOCKS_DIR . 'core' . DS . 'EE_Class_For_Testing_Loading.core.php', - 'EE_Class_For_Testing_Loading', - 'core', - array( - EE_CORE, - EE_ADMIN, - EE_CORE . 'data_migration_scripts' . DS, - EE_MOCKS_DIR, - EE_MOCKS_DIR . 'core' . DS, - ) - ); - $this->assertEquals( true, class_exists( 'EE_Class_For_Testing_Loading', false ) ); - } - - - - - /** - * this tests that abstract EE class files are loaded but not instantiated - * - * @group 8284 - * @author Brent Christensen - */ - public function test_create_object_abstract(){ - // let's attempt to load the abstract EE_Addon class file - require_once( EE_CORE . 'EE_Addon.core.php' ); - $this->assertEquals( true, class_exists( 'EE_Addon' ) ); - // now attempt instantiation - $class_object = EE_Registry_Mock::instance()->create_object( 'EE_Addon' ); - // abstract classes only return true to denote that they have been loaded - $this->assertEquals( true, $class_object ); - } - - - - - /** - * this tests that EE model object classes can be instantiated correctly - * - * @group 8284 - * @author Brent Christensen - */ - public function test_create_object_new_instance_from_db() { - // let's attempt to load an instantiate an EE_Question object with ID=1 - require_once( EE_CLASSES . 'EE_Question.class.php' ); - $this->assertEquals( true, class_exists( 'EE_Question' ) ); - // now attempt instantiation - $class_object = EE_Registry_Mock::instance()->create_object( - 'EE_Question', - array( array( 'QST_ID' => 1 ) ), - 'class', - true // FROM DB FLAG SET TO TRUE - ); - $this->assertEquals( true, $class_object instanceof EE_Question ); - $this->assertEquals( 1, $class_object->ID() ); - } - - - - /** - * this tests that EE model object classes can be instantiated correctly - * - * @group 8284 - * @author Brent Christensen - */ - public function test_create_object_new_instance() { - // let's attempt to load an instantiate an EE_Question object with ID=1 - // despite the fact that we just loaded the file in a previous test, - // let's just double check that the class exists - require_once( EE_CLASSES . 'EE_Question.class.php' ); - $this->assertEquals( true, class_exists( 'EE_Question' ) ); - // now attempt instantiation - $class_object = EE_Registry_Mock::instance()->create_object( - 'EE_Question', - array(), - 'class' - ); - $this->assertEquals( true, $class_object instanceof EE_Question ); - $this->assertEquals( 0, $class_object->ID() ); - } - - - - /** - * this tests that EE class files can be instantiated correctly - * - * @group 8284 - * @author Brent Christensen - */ - public function test_create_object_isInstantiable(){ - // let's attempt to load the EE_Module_Request_Router class file - require_once( EE_CORE . 'EE_Module_Request_Router.core.php' ); - $this->assertEquals( true, class_exists( 'EE_Module_Request_Router' ) ); - // now attempt instantiation - $class_object = EE_Registry_Mock::instance()->create_object( 'EE_Module_Request_Router' ); - $this->assertEquals( true, $class_object instanceof EE_Module_Request_Router ); - } - - - - /** - * this tests that EE singleton classes can be instantiated correctly - * - * @group 8284 - * @author Brent Christensen - */ - public function test_create_object_singleton(){ - // let's attempt to load the EE_Capabilities class file - require_once(EE_CORE . 'EE_Capabilities.core.php' ); - $this->assertEquals( true, class_exists( 'EE_Capabilities' ) ); - // now attempt instantiation - $class_object = EE_Registry_Mock::instance()->create_object( 'EE_Capabilities' ); - $this->assertEquals( true, $class_object instanceof EE_Capabilities ); - } - - - - /** - * this tests that EE classes with core dependencies can be instantiated correctly - * - * @group 8284 - * @author Brent Christensen - */ - public function test_create_object_and_resolve_dependencies(){ - // let's attempt to load the EE_Front_Controller class file - require_once( EE_CORE . 'EE_Front_Controller.core.php' ); - $this->assertEquals( true, class_exists( 'EE_Front_Controller' ) ); - // now attempt instantiation knowing that the EE_Front_Controller class - // injects the EE_Module_Request_Router class in the constructor - /** @type EE_Front_Controller $class_object */ - $class_object = EE_Registry_Mock::instance()->create_object( 'EE_Front_Controller' ); - $this->assertInstanceOf( 'EE_Front_Controller', $class_object ); - //echo "\n Request_Handler: \n"; - //var_dump( $class_object->Request_Handler() ); - //echo "\n Module_Request_Router: \n"; - //var_dump( $class_object->Module_Request_Router() ); - $this->assertInstanceOf( 'EE_Request_Handler', $class_object->Request_Handler() ); - $this->assertInstanceOf( 'EE_Module_Request_Router', $class_object->Module_Request_Router() ); - } - - - - /** - * this tests that objects cached using the EE_Registry class abbreviations can be retrieved - * - * @group 8284 - * @author Brent Christensen - */ - public function test_set_cached_class_abbreviations() { - // create a stdClass object we'll use for a mock - $orig_class = new stdClass(); - $orig_class->name = 'If_This_Is_An_Abbreviated_Class_Name_Then_Why_Is_It_So_Long'; - // cache it at EE_Registry_Mock::instance()->NET_CFG - EE_Registry_Mock::instance()->set_cached_class( $orig_class, 'EE_Network_Config' ); - // now attempt to retrieve it - $cached_class = EE_Registry_Mock::instance()->NET_CFG; - $this->assertEquals( $orig_class, $cached_class ); - } - - - - /** - * this tests that objects cached directly as EE_Registry_Mock properties can be retrieved - * - * @group 8284 - * @author Brent Christensen - */ - public function test_set_cached_class_property() { - // create a stdClass object we'll use for a mock - $orig_class = new stdClass(); - $orig_class->name = 'Some_Class'; - // cache it at EE_Registry_Mock::instance()->CAP - EE_Registry_Mock::instance()->set_cached_class( $orig_class, 'Some_Class' ); - // now attempt to retrieve it - $cached_class = EE_Registry_Mock::instance()->Some_Class; - $this->assertEquals( $orig_class, $cached_class ); - } - - - - /** - * this tests that objects cached on EE_Registry->LIB can be retrieved - * - * @group 8284 - * @author Brent Christensen - */ - public function test_set_cached_class_library() { - // create a stdClass object we'll use for a mock - $orig_class = new stdClass(); - $orig_class->name = 'Library_Class'; - // cache it at EE_Registry_Mock::instance()->CAP - EE_Registry_Mock::instance()->set_cached_class( $orig_class, 'Library_Class' ); - // now attempt to retrieve it - $cached_class = EE_Registry_Mock::instance()->LIB->Library_Class; - $this->assertEquals( $orig_class, $cached_class ); - } - - - - /** - * this tests that objects cached on EE_Registry->addons can be retrieved - * - * @group 8284 - * @author Brent Christensen - */ - public function test_set_cached_class_addon() { - // create a stdClass object we'll use for a mock - $orig_class = new stdClass(); - $orig_class->name = 'Addon_Class'; - // cache it at EE_Registry_Mock::instance()->CAP - EE_Registry_Mock::instance()->set_cached_class( $orig_class, 'Addon_Class', 'addon' ); - // now attempt to retrieve it - $cached_class = EE_Registry_Mock::instance()->addons->Addon_Class; - $this->assertEquals( $orig_class, $cached_class ); - } - - - /** - * Checks to ensure that when we reset the registry with reset models to true, that the models are actually reset. - * @group 10109 - */ - public function test_reset_with_reset_models() { - $testing_model = EE_Registry_Mock::instance()->load_model( 'Event' ); - - //put something in the entity map - $e = $this->new_model_obj_with_dependencies( 'Event' ); - $this->assertNotNull( $testing_model->get_from_entity_map( $e->ID() ) ); - - //now let's do the full Registry reset including resetting the models. - EE_Registry_Mock::instance()->reset( false, true, true ); - - //after the reset, the entity map on the model SHOULD be empty. - $this->assertNull( EEM_Registration::instance()->get_from_entity_map( $e->ID() ) ); - $this->assertNull( $testing_model->get_from_entity_map( $e->ID() ) ); - } - - - - /** - * checks model resets happen properly: the model instance should NOT change - * (in case code anywhere has a direct reference to it) but its properties - * should be reset to their original settings - * @group 10107 - * @author Mike Nelson - */ - public function test_reset_model(){ - $model_a = EE_Registry_Mock::instance()->load_model('Event'); - $model_a2 = EE_Registry_Mock::instance()->load_model('Event'); - $model_a3 = EEM_Event::instance(); - //and put something in its entity map - $e = $this->new_model_obj_with_dependencies( 'Event' ); - $this->assertNotNull( $model_a->get_from_entity_map( $e->ID() ) ); - $this->assertEquals($model_a, $model_a2); - $this->assertEquals($model_a2, $model_a3); - //let's set a differnet WP timezone. When the model is reset, it - //should automatically use this new timezone - $new_timezone_string = 'America/Detroit'; - update_option( 'timezone_string', $new_timezone_string ); - $model_b1 = EEM_Event::reset(); - $this->assertEquals( $model_a, $model_b1); - $model_b2 = EE_Registry_Mock::instance()->reset_model('Event'); - $this->assertEquals( $model_a, $model_b2); - //verify the model now has the new wp timezone - $this->assertEquals( $new_timezone_string, $model_b1->get_timezone() ); - //and that the model's entity map has been reset - $this->assertNull( $model_b1->get_from_entity_map( $e->ID() ) ); - } - - - - /** - * test_array_is_numerically_and_sequentially_indexed - * - * @author Brent Christensen - */ - public function test_array_is_numerically_and_sequentially_indexed() { - // empty arrays should return true - $this->assertTrue( - EE_Registry_Mock::instance()->array_is_numerically_and_sequentially_indexed( array() ) - ); - // should also be fine - $this->assertTrue( - EE_Registry_Mock::instance()->array_is_numerically_and_sequentially_indexed( - array( array() ) - ) - ); - // beauty eh? - $this->assertTrue( - EE_Registry_Mock::instance()->array_is_numerically_and_sequentially_indexed( - array( 'a', 'b', 'c' ) - ) - ); - // numeric "string" keys will get typecast as integers - $this->assertTrue( - EE_Registry_Mock::instance()->array_is_numerically_and_sequentially_indexed( - array( "0" => 'a', "1" => 'b', "2" => 'c' ) - ) - ); - // arrays that are not zero-indexed should return false - $this->assertFalse( - EE_Registry_Mock::instance()->array_is_numerically_and_sequentially_indexed( - array( 1 => 'a', 2 => 'b', 3 => 'c' ) - ) - ); - // out of order - $this->assertFalse( - EE_Registry_Mock::instance()->array_is_numerically_and_sequentially_indexed( - array( "1" => 'a', "0" => 'b', "2" => 'c' ) - ) - ); - // oh come on now!!! Not even close ! - $this->assertFalse( - EE_Registry_Mock::instance()->array_is_numerically_and_sequentially_indexed( - array( "a" => 'a', "b" => 'b', "c" => 'c' ) - ) - ); - } - - - /** - * checks that type hinted classes in constructors are properly instantiated and passed - * without negatively affecting other constructor parameters - * - * @author Brent Christensen - */ - public function test_dependency_injection() { - // either need to set an autoloader for any dependency classes or just pre-load them - EE_Registry_Mock::instance()->load_core('EE_Session_Mock'); - add_filter( - 'FHEE__EE_Registry__load_service__service_paths', - function() { - return array( - EE_TESTS_DIR . 'mocks' . DS . 'core' . DS . 'services' . DS - ); - } - ); - // test EE_Injector_Tester_With_Array_Session_Int_Constructor_Params - // with NO passed arguments - /** @type EE_Injector_Tester_With_Array_Session_Int_Constructor_Params $class */ - $class = EE_Registry_Mock::instance()->load_service( - 'EE_Injector_Tester_With_Array_Session_Int_Constructor_Params' - ); - $this->assertEquals( array(), $class->array_property() ); - $this->assertInstanceOf( 'EE_Session_Mock', $class->session_property() ); - $this->assertEquals( 0, $class->integer_property() ); - // reset - EE_Registry_Mock::instance()->LIB->EE_Injector_Tester_With_Array_Session_Int_Constructor_Params = null; - // test EE_Injector_Tester_With_Array_Session_Int_Constructor_Params - // with numerically indexed array passed as argument 1 - $numerically_indexed_array = array( - 0 => 'zero', - 1 => 'one', - 2 => 'two', - 3 => 'three', - ); - /** @type EE_Injector_Tester_With_Array_Session_Int_Constructor_Params $class */ - $class = EE_Registry_Mock::instance()->load_service( - 'EE_Injector_Tester_With_Array_Session_Int_Constructor_Params', - array( $numerically_indexed_array ) - ); - $this->assertEquals( $numerically_indexed_array, $class->array_property() ); - $this->assertInstanceOf( 'EE_Session_Mock', $class->session_property() ); - $this->assertEquals( 0, $class->integer_property() ); - // reset - EE_Registry_Mock::instance()->LIB->EE_Injector_Tester_With_Array_Session_Int_Constructor_Params = null; - // test EE_Injector_Tester_With_Array_Session_Int_Constructor_Params - // with string indexed array passed as argument 1 - // and the integer 2 passed as argument 3 - $string_indexed_array = array( - 'zero' => 0, - 'one' => 1, - 'two' => 2, - 'three' => 3, - ); - /** @type EE_Injector_Tester_With_Array_Session_Int_Constructor_Params $class */ - $class = EE_Registry_Mock::instance()->load_service( - 'EE_Injector_Tester_With_Array_Session_Int_Constructor_Params', - array( $string_indexed_array, null, 2 ) - ); - $this->assertEquals( $string_indexed_array, $class->array_property() ); - $this->assertInstanceOf( 'EE_Session_Mock', $class->session_property() ); - $this->assertEquals( 2, $class->integer_property() ); - } - - - /** - * This test verifies that if a dependency map entry has more than one type of class listed as dependencies and they - * are both set as `load_new_object`, then they are actually two distinct objects when the parent object - * is instantiated. - * - * For this test we'll use EE_Messages_Generator because it expects two distinct EE_Message_Queue objects sent into its - * constructor via the dependency map. - * - * @group 9325 - * @author Darren Ethier - */ - public function test_multiple_duplicate_class_different_instance_on_construct_using_dependency_map() { - //first register our mock in the dependency map - $dependencies = array( - 'EE_Messages_Queue' => EE_Dependency_Map::load_new_object, - 'EE_Messages_Data_Handler_Collection' => EE_Dependency_Map::load_new_object, - 'EE_Message_Template_Group_Collection' => EE_Dependency_Map::load_new_object, - 'EEH_Parse_Shortcodes' => EE_Dependency_Map::load_from_cache, - ); - $registered = EE_Dependency_Map::register_dependencies( 'EE_Messages_Generator_Mock', $dependencies ); - $this->assertTrue( $registered ); - - $mock_paths[] = EE_TESTS_DIR . 'mocks/core/libraries/messages'; - - //load the mock generator - /** @var EE_Messages_Generator_Mock $generator */ - $generator = EE_Registry_Mock::instance()->load( $mock_paths, 'EE_', 'Messages_Generator_Mock', '' ); - - //verify both queues are distinct - $this->assertNotEquals( - spl_object_hash( $generator->generation_queue() ), - spl_object_hash( $generator->ready_queue() ) - ); - } - - - - /** - * This test verifies that any new dependencies registered - * on EE_Dependency_Map are immediately visible to EE_Registry. - * It may seem wrong because it appears to be testing methods that actually exist on EE_Dependency_Map, - * but they are all methods that are called via the \EE_Registry::$_dependency_map property. - * So this test is just verifying that EE_Registry and EE_Dependency_Map are in sync. - * - * Uses EE_Registry_Mock::dependency_map_has(), - * EE_Registry_Mock::has_dependency_for_class(), - * and EE_Registry_Mock::loading_strategy_for_class_dependency(), - * which all call methods via the EE_Dependency_Map property on EE_Registry - * - * @author Brent Christensen - */ - public function test_registry_can_see_newly_registered_dependencies() { - // first verify that dependency doesn't already exist - $this->assertFalse( - EE_Registry_Mock::instance()->dependency_map_has( 'Some_New_Class_Name' ) - ); - // then register it - EE_Dependency_Map::register_dependencies( - 'Some_New_Class_Name', - array( 'DependencyOne' => EE_Dependency_Map::load_new_object ) - ); - // and verify that it's now available - $this->assertTrue( - EE_Registry_Mock::instance()->dependency_map_has( 'Some_New_Class_Name' ) - ); - // verify loading strategy - $this->assertEquals( - EE_Dependency_Map::load_new_object, - EE_Registry_Mock::instance()->loading_strategy_for_class_dependency( 'Some_New_Class_Name', 'DependencyOne' ) - ); - } - - - - /** - * This test verifies that any new class loaders registered - * on EE_Dependency_Map are immediately visible to EE_Registry. - * It may seem wrong because it appears to be testing methods that actually exist on EE_Dependency_Map, - * but they are all methods that are called via the \EE_Registry::$_dependency_map property. - * So this test is just verifying that EE_Registry and EE_Dependency_Map are in sync. - * - * Uses EE_Registry_Mock::loading_strategy_for_class_dependency() - * which calls EE_Dependency_Map::loading_strategy_for_class_dependency() via the property on EE_Registry - * - * @author Brent Christensen - */ - public function test_registry_can_see_newly_registered_class_loaders() { - // first verify that class loader doesn't already exist - $this->assertEmpty( - EE_Registry_Mock::instance()->dependency_map_class_loader( 'DependencyOne' ) - ); - // then register it - EE_Dependency_Map::register_class_loader( 'DependencyOne', 'load_core' ); - // and verify that it's now available - $this->assertEquals( - 'load_core', - EE_Registry_Mock::instance()->dependency_map_class_loader( 'DependencyOne' ) - ); - } - - - -} -// End of file EE_Registry_Test.php -// Location: /tests/testcases/core/EE_Registry_Test.php diff --git a/tests/testcases/core/EE_System_Test.php b/tests/testcases/core/EE_System_Test.php deleted file mode 100644 index 348edb2350c..00000000000 --- a/tests/testcases/core/EE_System_Test.php +++ /dev/null @@ -1,383 +0,0 @@ -_original_espresso_db_update = get_option('espresso_db_update'); - $this->_original_db_state = get_option( EE_Data_Migration_Manager::current_database_state ); - EE_System::reset(); - } - public function test_detect_request_type(){ - - $this->_pretend_espresso_db_update_is(array( - espresso_version() => array(current_time('mysql')) - )); - $request_type = EE_System::reset()->detect_req_type(); - $this->assertEquals(EE_System::req_type_normal,$request_type); - //check that it detects an upgrade - $this->_pretend_espresso_db_update_is(array( - $this->_add_to_version(espresso_version(), '0.-1.0.0.0') => array(current_time('mysql')) - )); - $request_type = EE_System::reset()->detect_req_type(); - $this->assertEquals(EE_System::req_type_upgrade,$request_type); - //check that it detects activation - $this->_pretend_espresso_db_update_is(NULL); - $request_type = EE_System::reset()->detect_req_type(); - $this->assertEquals(EE_System::req_type_new_activation,$request_type); - //check that it detects downgrade, even though we don't really care atm -// EE_System::reset(); -// $this->_pretend_espresso_db_upgrade_is(array( -// $this->_add_to_version(espresso_version(), '0.1.0.0.0') => array(current_time('mysql')) -// )); -// $request_type = EE_System::instance()->detect_req_type(); -// $this->assertEquals(EE_System::req_type_downgrade,$request_type); - //lastly, check that we detect reactivations - update_option('ee_espresso_activation',true); - $this->_pretend_espresso_db_update_is(array( - espresso_version() => array(current_time('mysql')) - )); - $request_type = EE_System::reset()->detect_req_type(); - $this->assertEquals(EE_System::req_type_reactivation,$request_type); - } - /** - * just tests the EE_System_Test::_add_to_version private method to make sure it's working - * (because other tests depend on it) - */ - function test_add_to_version(){ - $version = '4.3.2.alpha.001'; - $version_to_add = '1.0.-1.1.1'; - $new_version = $this->_add_to_version($version, $version_to_add); - $this->assertEquals('5.3.1.alpha.002',$new_version); - } - /** - * check things turn out as expected for NORMAL REQUEST - */ - function test_detect_activation_or_upgrade__normal(){ - delete_option( 'ee_espresso_activation' ); - $pretend_activation_history = array( - espresso_version() => array(current_time('mysql')) - ); - $this->_pretend_espresso_db_update_is($pretend_activation_history); - $current_activation_history_before = get_option('espresso_db_update'); - $this->assertEquals(1,count($current_activation_history_before[espresso_version()])); - EE_System::instance()->detect_if_activation_or_upgrade(); - $current_activation_history_after = get_option('espresso_db_update'); - //this should have just added to the number of times this same verison was activated - $this->assertEquals(EE_System::req_type_normal,EE_System::instance()->detect_req_type()); - $this->assertArrayHasKey( espresso_version(), $current_activation_history_after ); - $this->assertTimeIsAbout(current_time( 'timestamp' ), $current_activation_history_after[ espresso_version() ][ 0 ] ); - - } - /** - * new activation - */ - function test_detect_activation_or_upgrade__new_install() { - $this->_pretend_espresso_db_update_is(NULL); - //pretend the activation indicator option was set (because it's really unusual - //for a plugin to be activated without having WP call its activation hook) - update_option('ee_espresso_activation',TRUE); - remove_action('AHEE__EE_System__perform_activations_upgrades_and_migrations',array(EE_System::instance(),'initialize_db_if_no_migrations_required')); - $this->assertWPOptionDoesNotExist('espresso_db_update'); - EE_System::reset()->detect_if_activation_or_upgrade(); - $current_activation_history = get_option('espresso_db_update'); - //check we've added this to the version history - //and that the hook for adding tables n stuff was added - $this->assertArrayHasKey( espresso_version(), $current_activation_history ); - $this->assertTimeIsAbout(current_time( 'timestamp' ), $current_activation_history[ espresso_version() ][ 0 ] ); - has_action('AHEE__EE_System__perform_activations_upgrades_and_migrations',array(EE_System::instance(),'initialize_db_if_no_migrations_required')); - //and the activation indicator option shoudl have been removed - $this->assertWPOptionDoesNotExist('ee_espresso_activation'); - } - - /** - * tests EE_SYstem_Test::assertTimeIsAbout - */ - public function test_assertTimeIsAbout(){ - //these tests should fail - try{ - $this->assertTimeIsAbout(current_time( 'timestamp' ), current_time( 'timestamp' ) + 6, 5 ); - }catch( PHPUnit_Framework_ExpectationFailedException $e ){ - $this->assertTrue( TRUE ); - } - try{ - $this->assertTimeIsAbout(current_time( 'timestamp' ), current_time( 'timestamp' ) - 6, 5 ); - }catch( PHPUnit_Framework_ExpectationFailedException $e ){ - $this->assertTrue( TRUE ); - } - $this->assertTimeIsAbout( current_time( 'timestamp' ), current_time( 'timestamp' ) + 4, 5 ); - $this->assertTimeIsAbout( current_time( 'timestamp' ), current_time( 'timestamp' ) - 3, 5 ); - } - - /** - * Asserts that there is at most $precision time difference between $expected_time and - * $actual_time, in either direction - * @param string|int $expected_time mysql or unix timestamp - * @param string|int $actual_time mysql or unix timestamp - * @param int $precision allowed number of seconds of time idfference without failing - */ - protected function assertTimeIsAbout($expected_time, $actual_time, $precision = 5) { - if( ! is_int( $expected_time ) ){ - $expected_time = strtotime( $expected_time ); - } - if( ! is_int( $actual_time ) ){ - $actual_time = strtotime( $actual_time ); - } - $this->assertLessThanOrEqual($precision, abs( $actual_time - $expected_time ) ); - } - /** - * tests we can detect an upgrade when the plugin is deactivated, then a new version of the plugin - * is uploaded, and then activated (ie, the plugin's activation hook was fired) - */ - function test_detect_activation_or_upgrade__upgrade_upon_activation(){ - $pretend_previous_version = $this->_add_to_version(espresso_version(),'0.-1.0.0.0'); - $this->_pretend_espresso_db_update_is(array( - $pretend_previous_version => array(current_time('mysql')) - )); - //pretend the activation indicator option was set (because it's really unusual - //for a plugin to be activated without having WP call its activation hook) - update_option('ee_espresso_activation',TRUE); - - EE_System::reset()->detect_if_activation_or_upgrade(); - $current_activation_history = get_option('espresso_db_update'); - $this->assertEquals(EE_System::req_type_upgrade,EE_System::instance()->detect_req_type()); - $this->assertArrayHasKey( $pretend_previous_version, $current_activation_history ); - $this->assertTimeIsAbout(current_time( 'timestamp' ), $current_activation_history[ $pretend_previous_version ][ 0 ] ); - $this->assertArrayHasKey( espresso_version(), $current_activation_history ); - $this->assertTimeIsAbout(current_time( 'timestamp' ), $current_activation_history[ espresso_version() ][ 0 ] ); - - $this->assertWPOptionDoesNotExist('ee_espresso_activation'); - } - /** - * tests we can detect an upgrade when the plugin files were automatically - * updated (ie, the plugins' activation hook wasn't called) - */ - function test_detect_activation_or_upgrade__upgrade_upon_normal_request(){ - $pretend_previous_version = $this->_add_to_version(espresso_version(),'0.-1.0.0.0'); - $this->_pretend_espresso_db_update_is(array( - $pretend_previous_version => array(current_time('mysql')) - )); - - $this->assertEquals(EE_System::req_type_upgrade,EE_System::reset()->detect_req_type()); - $current_activation_history = get_option('espresso_db_update'); - $this->assertArrayHasKey( $pretend_previous_version, $current_activation_history ); - $this->assertTimeIsAbout(current_time( 'timestamp' ), $current_activation_history[ $pretend_previous_version ][ 0 ] ); - $this->assertArrayHasKey( espresso_version(), $current_activation_history ); - $this->assertTimeIsAbout(current_time( 'timestamp' ), $current_activation_history[ espresso_version() ][ 0 ] ); - $this->assertWPOptionDoesNotExist('ee_espresso_activation'); - } - function test_detect_activation_or_upgrade__reactivation(){ - $this->_pretend_espresso_db_update_is(array( - espresso_version() => array(current_time('mysql')) - )); - update_option('ee_espresso_activation',true); - - $this->assertEquals(EE_System::req_type_reactivation,EE_System::reset()->detect_req_type()); - $current_activation_history = get_option('espresso_db_update'); -// $this->assertEquals(array(espresso_version() =>array(current_time('mysql'),current_time('mysql'))),$current_activation_history); - $this->assertArrayHasKey( espresso_version(), $current_activation_history ); - $this->assertTimeIsAbout(current_time( 'timestamp' ), $current_activation_history[ espresso_version() ][ 0 ] ); - $this->assertTimeIsAbout(current_time( 'timestamp' ), $current_activation_history[ espresso_version() ][ 1 ] ); - $this->assertWPOptionDoesNotExist('ee_espresso_activation'); - } - function test_detect_activation_or_upgrade__downgrade_upon_normal_request(){ - $pretend_previous_version = $this->_add_to_version(espresso_version(),'0.1.0.0.0'); - $this->_pretend_espresso_db_update_is(array( - $pretend_previous_version => array(current_time('mysql')) - )); - $this->assertEquals(EE_System::req_type_downgrade,EE_System::reset()->detect_req_type()); - $current_activation_history = get_option('espresso_db_update'); - $this->assertArrayHasKey( $pretend_previous_version, $current_activation_history ); - $this->assertTimeIsAbout(current_time( 'timestamp' ), $current_activation_history[ $pretend_previous_version ][ 0 ] ); - $this->assertArrayHasKey( espresso_version(), $current_activation_history ); - $this->assertTimeIsAbout(current_time( 'timestamp' ), $current_activation_history[ espresso_version() ][ 0 ] ); - $this->assertWPOptionDoesNotExist('ee_espresso_activation'); - } - /** - * tests that we're detecting request types correctly on normal requests (ie, NOT an activation request) - * A new install would only occur on a non-activation request because the site was previously in maintenance mode - * - */ - function test_detect_req_type_given_activation_history__on_normal_requests(){ - $activation_history = array(); - - //detect brand new activation BUT we're in maintenance mode, so it will be basically ignored - EE_Maintenance_Mode::instance()->set_maintenance_level( EE_Maintenance_Mode::level_2_complete_maintenance ); - $this->assertEquals( EE_System::req_type_new_activation, EE_System::detect_req_type_given_activation_history($activation_history, '', '1.0.0.dev.000' ) ); - EE_Maintenance_Mode::instance()->set_maintenance_level( EE_Maintenance_Mode::level_0_not_in_maintenance ); - - //detect brand new activation - $this->assertEquals( EE_System::req_type_new_activation, EE_System::detect_req_type_given_activation_history($activation_history, '', '1.0.0.dev.000' ) ); - $activation_history[ '1.0.0.dev.000'] = array( date( 'Y-m-d H:i:s' ) ); - - //detect upgrade to NEW version - $this->assertEquals( EE_System::req_type_upgrade, EE_System::detect_req_type_given_activation_history($activation_history, '', '1.2.0.dev.000' ) ); - $activation_history[ '1.2.0.dev.000' ] = array( date( 'Y-m-d H:i:s', time() + 1 ) ); - - //detect normal request - $this->assertEquals( EE_System::req_type_normal, EE_System::detect_req_type_given_activation_history($activation_history, '', '1.2.0.dev.000' ) ); - - //detect downgrade to NEW version - $this->assertEquals( EE_System::req_type_downgrade, EE_System::detect_req_type_given_activation_history($activation_history, '', '1.1.0.dev.000' ) ); - $activation_history[ '1.1.0.dev.000' ] = array( date( 'Y-m-d H:i:s', time() + 2 ) ); - - //detect downgrade to KNOWN version - $this->assertEquals( EE_System::req_type_downgrade, EE_System::detect_req_type_given_activation_history($activation_history, '', '1.0.0.dev.000' ) ); - $activation_history[ '1.0.0.dev.000' ][] = date( 'Y-m-d H:i:s', time() + 3 ) ; - - //detect upgrade to KNOWN version - $this->assertEquals( EE_System::req_type_upgrade, EE_System::detect_req_type_given_activation_history($activation_history, '', '1.1.0.dev.000' ) ); - $activation_history[ '1.1.0.dev.000' ][] = date( 'Y-m-d H:i:s', time() + 4 ) ; - } - - /** - * tests that we are detecting activations correctly even when the same version has - * been activated multiple times - */ - function test_detect_req_type_given_activation_history__multiple_activations(){ - $activation_history = array( - '3.1.36.5.P' => array( 'unknown-date' ), - '4.3.0.alpha.019' => array( '2014-06-09 18:10:35', ), - '4.6.0.dev.016' => array( - '2014-10-15 15:43:08', - '2014-10-15 18:16:41', - '2014-10-15 20:09:07' - ), - '4.5.0.beta.020' => array( - '2014-10-15 16:52:35', - ) - - ); - $this->assertEquals( EE_System::req_type_downgrade, EE_System::detect_req_type_given_activation_history($activation_history, '', '4.5.0.beta.020' ) ); - } - /** - * - */ - function test_detect_req_type_given_activation_history__on_activation(){ - $activation_history = array(); - update_option( 'test_activation_indicator_option', TRUE ); - - //detect brand new activation - $this->assertEquals( EE_System::req_type_new_activation, EE_System::detect_req_type_given_activation_history($activation_history, 'test_activation_indicator_option', '1.0.0.dev.000' ) ); - $activation_history[ '1.0.0.dev.000'] = array( date( 'Y-m-d H:i:s' ) ); - update_option( 'test_activation_indicator_option', TRUE ); - - //detect upgrade to NEW version - $this->assertEquals( EE_System::req_type_upgrade, EE_System::detect_req_type_given_activation_history($activation_history, 'test_activation_indicator_option', '1.2.0.dev.000' ) ); - $activation_history[ '1.2.0.dev.000' ] = array( date( 'Y-m-d H:i:s', time() + 1 ) ); - update_option( 'test_activation_indicator_option', TRUE ); - - //detect reactivation request; WOULD be a normal request if the activation indicator weren't set - $this->assertEquals( EE_System::req_type_reactivation, EE_System::detect_req_type_given_activation_history($activation_history, 'test_activation_indicator_option', '1.2.0.dev.000' ) ); - - //detect downgrade to NEW version - $this->assertEquals( EE_System::req_type_downgrade, EE_System::detect_req_type_given_activation_history($activation_history, 'test_activation_indicator_option', '1.1.0.dev.000' ) ); - $activation_history[ '1.1.0.dev.000' ] = array( date( 'Y-m-d H:i:s', time() + 2 ) ); - update_option( 'test_activation_indicator_option', TRUE ); - - //detect downgrade to KNOWN version - $this->assertEquals( EE_System::req_type_downgrade, EE_System::detect_req_type_given_activation_history($activation_history, 'test_activation_indicator_option', '1.0.0.dev.000' ) ); - $activation_history[ '1.0.0.dev.000' ][] = date( 'Y-m-d H:i:s', time() + 3 ) ; - update_option( 'test_activation_indicator_option', TRUE ); - - //detect upgrade to KNOWN version - $this->assertEquals( EE_System::req_type_upgrade, EE_System::detect_req_type_given_activation_history($activation_history, 'test_activation_indicator_option', '1.1.0.dev.000' ) ); - $activation_history[ '1.1.0.dev.000' ][] = date( 'Y-m-d H:i:s', time() + 4 ) ; - update_option( 'test_activation_indicator_option', TRUE ); - } - - /** - * @group 8154 - */ - function test__new_version_is_higher(){ - $class = new ReflectionClass("EE_System"); - $method = $class->getMethod("_new_version_is_higher"); - $method->setAccessible(true); - - $current_version = '4.7.0.rc.000'; - $activation_history = array( - $current_version => array( - '2015-03-12 04:53:12' - ), - '3.1.37.1.P' => - array( - 0 => 'unknown-date', - ), - ); - $this->assertEquals( 0, $method->invoke(EE_System::instance(), $activation_history, $current_version ) ); - $this->assertEquals( 1, $method->invoke( EE_System::instance(), $activation_history, '4.8.0.rc.000' ) ); - $this->assertEquals( -1, $method->invoke( EE_System::instance(), $activation_history, '4.4.0.rc.000' ) ); - $this->assertEquals( 1, $method->invoke( EE_System::instance(), array(), '4.8.0.rc.000' ) ); - } - - - /** - * Sets the wordpress option 'espresso_db_update' - * @param array $espresso_db_upgrade top-level-keys shoudl be version numbers, - * and their values should be an array of mysql datetimes when that version was activated - */ - private function _pretend_espresso_db_update_is($espresso_db_upgrade){ - if($espresso_db_upgrade === NULL){ - delete_option('espresso_db_update',$espresso_db_upgrade); - }else{ - update_option( 'espresso_db_update',$espresso_db_upgrade ); - } - } - - /** - * - * @param string $version_string eg "4.3.2.alpha.003 - * @param string $version_amount_to_add eg "0.0.0.0.1" - * @return string eg if given the mentioned inputs, would be "4.3.2.alpha.4"; - */ - private function _add_to_version($version_string,$version_amount_to_add = '0.1.0.0.0'){ - $version_parts = explode(".",$version_string); - $version_amount_to_add_parts = explode(".",$version_amount_to_add); - foreach($version_parts as $key => $version_part){ - if(is_numeric($version_part)){ - $characters_in_version_part = strlen( $version_part ); - $version_parts[$key] = str_pad( $version_parts[$key] + $version_amount_to_add_parts[$key], $characters_in_version_part, '0', STR_PAD_LEFT ); - } - } - return implode(".",$version_parts); - } - /** - * restore the epsresso_db_update option - */ - function tearDown() { - update_option('espresso_db_update',$this->_original_espresso_db_update); - EE_System::reset()->detect_req_type(); - EE_Data_Migration_Manager::reset(); - update_option( EE_Data_Migration_Manager::current_database_state, $this->_original_db_state ); - parent::tearDown(); - } -} - -// End of file EE_System_Test.php \ No newline at end of file diff --git a/tests/testcases/core/EE_System_Test_With_Addons.php b/tests/testcases/core/EE_System_Test_With_Addons.php deleted file mode 100644 index 41956f0b48b..00000000000 --- a/tests/testcases/core/EE_System_Test_With_Addons.php +++ /dev/null @@ -1,598 +0,0 @@ -_table_analysis = new TableAnalysis(); - $this->_table_manager = new TableManager($this->_table_analysis); - $this->_pretend_addon_hook_time(); - $mock_addon_path = EE_TESTS_DIR . 'mocks/addons/eea-new-addon/'; - EE_Registry::instance()->addons = new RegistryContainer(); - EE_Register_Addon::register( - $this->_addon_name, - array( - 'version' => '1.0.0.dev.000', - 'min_core_version' => '4.0.0', - 'main_file_path' => $mock_addon_path . 'eea-new-addon.php', - 'dms_paths' => $mock_addon_path . 'core/data_migration_scripts', - ) - ); - // now verify that this is the only addon - $this->assertCount(1, EE_Registry::instance()->addons); - //double-check that worked fine - $this->assertArrayHasKey( - 'EE_New_Addon', - EE_Registry::instance()->addons - ); - $this->assertInstanceOf( - 'EE_New_Addon', - EE_Registry::instance()->addons->EE_New_Addon - ); - $DMSs_available = EE_Data_Migration_Manager::reset()->get_all_data_migration_scripts_available(); - $this->assertArrayHasKey('EE_DMS_New_Addon_1_0_0', $DMSs_available); - $this->_addon = EE_Registry::instance()->addons->EE_New_Addon; - $this->assertInstanceOf('EE_New_Addon', $this->_addon); - $this->_addon_classname = get_class($this->_addon); - $this->_addon_activation_history = $this->_addon->get_activation_history(); - $this->_current_db_state = get_option(EE_Data_Migration_Manager::current_database_state); - delete_option(EE_Data_Migration_Manager::current_database_state); - update_option( - EE_Data_Migration_Manager::current_database_state, - array('Core' => espresso_version()) - ); - add_filter( - 'FHEE__EEH_Activation__create_table__short_circuit', - array($this, 'dont_short_circuit_new_addon_table'), - 20, - 2 - ); - } - - - public function tearDown() - { - //if somehow $this->_addon isn't set, we don't need to worry about deregistering it right? - if ($this->_addon instanceof EE_Addon) { - update_option( - $this->_addon->get_activation_history_option_name(), - $this->_addon_activation_history - ); - update_option( - EE_Data_Migration_Manager::current_database_state, - $this->_current_db_state - ); - EE_Register_Addon::deregister($this->_addon_name); - try { - EE_Registry::instance()->addons->EE_New_Addon; - $this->fail('EE_New_Addon is still registered. Deregister failed'); - } catch (Exception $e) { - $this->assertInstanceOf('OutOfBoundsException', $e); - } - //verify DMSs deregistered - $DMSs_available = EE_Data_Migration_Manager::reset()->get_all_data_migration_scripts_available(); - $this->assertArrayNotHasKey('EE_DMS_New_Addon_1_0_0', $DMSs_available); - $this->_stop_pretending_addon_hook_time(); - // drop all the temporary tables we created during this test, - // because each subsequent test expects them to be gone - $this->_table_manager->dropTables($this->_temp_tables_added_by_addon); - } - parent::tearDown(); - } - - - /** - * OK's the creation of the esp_new_addon table, because this hooks in AFTER EE_UNitTestCase's callback on this - * same hook - * - * @global wpdb $wpdb - * @param boolean $short_circuit whether or not to short-circuit - * @param string $table_name name we're about to create. Should NOT have the $wpdb->prefix on it - * @return array|bool - */ - public function dont_short_circuit_new_addon_table($short_circuit = false, $table_name = '') - { - //allow creation of new_addon tables. Unfortunately, this also allows their modification, which causes - //implicit commits. But I like allowing re-defining the tables on test - //test_detect_activations_or_upgrades__new_install_on_core_and_addon_simultaneously - //so we can confirm a notices are sent when attempting to redefine an addon table - if (in_array($table_name, $this->_temp_tables_added_by_addon, true)) { - //it's not altering. it's ok to allow this - return false; - } - return $short_circuit; - } - - - private function _add_mock_dms() - { - add_filter('FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders', array($this, 'add_mock_dms')); - EE_Data_Migration_Manager::reset(); - } - - - private function _remove_mock_dms() - { - remove_filter( - 'FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders', - array($this, 'add_mock_dms') - ); - EE_Data_Migration_Manager::reset(); - } - - - public function add_mock_dms($dms_folders) - { - $dms_folders[] = EE_TESTS_DIR . 'mocks/core/data_migration_scripts'; - return $dms_folders; - } - - - /** - * tests that we're correctly detecting activation or upgrades in registered - * addons. - * - * @group agg - * @group 8328 - */ - public function test_detect_activations_or_upgrades__new_install() - { - global $wp_actions; - //its activation history wp option shouldn't exist - $this->assertWPOptionDoesNotExist($this->_addon->get_activation_history_option_name()); - //and it also shouldn't be in the current db state - $current_db_state = get_option(EE_Data_Migration_Manager::current_database_state); - //just for assurance, make sure New Addon is the only existing addon - $this->assertArrayNotHasKey($this->_addon_name, $current_db_state); - $times_its_new_install_hook_fired_before = isset($wp_actions["AHEE__{$this->_addon_classname}__new_install"]) - ? $wp_actions["AHEE__{$this->_addon_classname}__new_install"] : 0; - //set the activator option - update_option($this->_addon->get_activation_indicator_option_name(), true); - $this->assertWPOptionExists($this->_addon->get_activation_indicator_option_name()); - $this->assertTableDoesNotExist('esp_new_addon_thing'); - //now check for activations/upgrades in addons - EE_System::reset(); - $this->assertEquals(EE_System::req_type_new_activation, $this->_addon->detect_req_type()); - $this->assertEquals( - $times_its_new_install_hook_fired_before + 1, - $wp_actions["AHEE__{$this->_addon_classname}__new_install"] - ); - $this->assertWPOptionDoesNotExist($this->_addon->get_activation_indicator_option_name()); - //now we also want to check that the addon will have created the necessary table - //that it needed upon new activation - $this->assertTableExists('esp_new_addon_thing'); - } - - - /** - * tests that we're correctly detecting activation or upgrades in registered - * addons. - * - * @group agg - */ - public function test_detect_activations_or_upgrades__new_install_on_core_and_addon_simultaneously() - { - global $wp_actions, $wpdb; - //pretend core was just activated - delete_option('espresso_db_update'); - update_option('ee_espresso_activation', true); - delete_option('ee_pers_admin_notices'); - //its activation history wp option shouldn't exist - $this->assertWPOptionDoesNotExist($this->_addon->get_activation_history_option_name()); - //and it also shouldn't be in the current db state - $current_db_state = get_option(EE_Data_Migration_Manager::current_database_state); - //just for assurance, make sure New Addon is the only existing addon - $this->assertArrayNotHasKey($this->_addon_name, $current_db_state); - $times_addon_new_install_hook_fired = isset($wp_actions["AHEE__{$this->_addon_classname}__new_install"]) - ? $wp_actions["AHEE__{$this->_addon_classname}__new_install"] - : 0; - $times_core_new_install_hook_fired = isset($wp_actions['AHEE__EE_System__detect_if_activation_or_upgrade__new_activation']) - ? $wp_actions['AHEE__EE_System__detect_if_activation_or_upgrade__new_activation'] - : 0; - //set the activator option - update_option($this->_addon->get_activation_indicator_option_name(), true); - $this->assertWPOptionExists($this->_addon->get_activation_indicator_option_name()); - $this->assertTableDoesNotExist('esp_new_addon_thing'); - EE_System::reset(); - $this->assertEquals(EE_System::req_type_new_activation, EE_System::instance()->detect_req_type()); - $this->assertEquals(EE_System::req_type_new_activation, $this->_addon->detect_req_type()); - $this->assertEquals( - $times_addon_new_install_hook_fired + 1, - $wp_actions["AHEE__{$this->_addon_classname}__new_install"] - ); - $this->assertEquals( - $times_core_new_install_hook_fired + 1, - $wp_actions['AHEE__EE_System__detect_if_activation_or_upgrade__new_activation'] - ); - $this->assertWPOptionDoesNotExist($this->_addon->get_activation_indicator_option_name()); - $this->assertWPOptionDoesNotExist('ee_espresso_activation'); - $this->assertTableExists('esp_new_addon_thing'); - //verify we haven't remarked that there we tried adding a duplicate table - $notices = get_option('ee_pers_admin_notices', array()); - $this->assertArrayNotHasKey('bad_table_' . $wpdb->prefix . 'esp_new_addon_thing_detected', $notices); - //double-check that when we intentionally try to add a table we just asserted exists - //that the warning gets sent out - global $track_it; - $track_it = true; - try { - EEH_Activation::create_table( - 'esp_new_addon_thing', - 'BORKED SQL', - 'ENGINE=MyISAM ', - true - ); - $this->fail('Borked SQL didn\'t cause EEH_Activation::create_table to throw an EE_Error. It should have'); - } catch (EE_Error $e) { - $this->assertTrue(true); - } - } - - - public function test_detect_activations_or_upgrades__upgrade_on_activation() - { - global $wp_actions; - $this->_addon_classname = get_class($this->_addon); - //first make sure the mock DMS can migrate from v 0.0.1 - $dms = new EE_DMS_New_Addon_1_0_0(); - $this->assertTrue( - $dms->can_migrate_from_version( - array($this->_addon_name => $this->_pretend_addon_previous_version) - ) - ); - //it should have an entry in its activation history and db state - $activation_history_option_name = $this->_addon->get_activation_history_option_name(); - update_option($activation_history_option_name, array($this->_pretend_addon_previous_version)); - $db_state = get_option(EE_Data_Migration_Manager::current_database_state); - $db_state[$this->_addon_name] = $this->_pretend_addon_previous_version; - update_option(EE_Data_Migration_Manager::current_database_state, $db_state); - //pretend the activation indicator option was set (by WP calling its activation hook) - update_option($this->_addon->get_activation_indicator_option_name(), true); - $times_its_new_install_hook_fired_before = isset($wp_actions["AHEE__{$this->_addon_classname}__upgrade"]) - ? $wp_actions["AHEE__{$this->_addon_classname}__upgrade"] : 0; - //the site shouldn't be in MM before - $this->assertEquals( - EE_Maintenance_Mode::level_0_not_in_maintenance, - EE_Maintenance_Mode::instance()->level() - ); - //now check for activations/upgrades in addons - EE_System::reset(); - $this->assertEquals(EE_System::req_type_upgrade, $this->_addon->detect_req_type()); - $this->assertEquals( - $times_its_new_install_hook_fired_before + 1, - $wp_actions["AHEE__{$this->_addon_classname}__upgrade"] - ); - //the fact that there's an applicable DMS means the site should be placed in maintenance mode - $this->assertEquals( - EE_Maintenance_Mode::level_2_complete_maintenance, - EE_Maintenance_Mode::instance()->level() - ); - //check that the activation indicator option was removed - $this->assertWPOptionDoesNotExist($this->_addon->get_activation_indicator_option_name()); - //ok all done - EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance); - } - - - /** - * tests we detect an upgrade even when the plugin isn't newly activated - * - * @global array $wp_actions - */ - public function test_detect_activations_or_upgrades__upgrade_on_normal_request() - { - global $wp_actions; - //first make sure the mock DMS can migrate from v 0.0.1 - $dms = new EE_DMS_New_Addon_1_0_0(); - $this->assertTrue( - $dms->can_migrate_from_version( - array($this->_addon_name => $this->_pretend_addon_previous_version) - ) - ); - //it should have an entry in its activation history and db state - $activation_history_option_name = $this->_addon->get_activation_history_option_name(); - update_option($activation_history_option_name, array($this->_pretend_addon_previous_version)); - $db_state = get_option(EE_Data_Migration_Manager::current_database_state); - $db_state[$this->_addon_name] = $this->_pretend_addon_previous_version; - update_option(EE_Data_Migration_Manager::current_database_state, $db_state); - $times_its_new_install_hook_fired_before = isset($wp_actions["AHEE__{$this->_addon_classname}__upgrade"]) - ? $wp_actions["AHEE__{$this->_addon_classname}__upgrade"] : 0; - //the site shouldn't be in MM before - $this->assertEquals( - EE_Maintenance_Mode::level_0_not_in_maintenance, - EE_Maintenance_Mode::instance()->level() - ); - //now check for activations/upgrades in addons - EE_System::reset(); - $this->assertEquals(EE_System::req_type_upgrade, $this->_addon->detect_req_type()); - $this->assertEquals( - $times_its_new_install_hook_fired_before + 1, - $wp_actions["AHEE__{$this->_addon_classname}__upgrade"] - ); - //the fact that there's an applicable DMS means the site should be placed in maintenance mode - $this->assertEquals( - EE_Maintenance_Mode::level_2_complete_maintenance, - EE_Maintenance_Mode::instance()->level() - ); - //ok all done - EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance); - } - - - public function test_detect_activations_or_upgrades__reactivation() - { - global $wp_actions; - $this->assertEquals( - EE_Maintenance_Mode::level_0_not_in_maintenance, - EE_Maintenance_Mode::instance()->level() - ); - //it should have an entry in its activation history and db state - $activation_history_option_name = $this->_addon->get_activation_history_option_name(); - update_option( - $activation_history_option_name, - array($this->_addon->version() => array(current_time('mysql'))) - ); - $db_state = get_option(EE_Data_Migration_Manager::current_database_state); - $db_state['New_Addon'] = $this->_addon->version(); - update_option(EE_Data_Migration_Manager::current_database_state, $db_state); - //set the activator option - update_option($this->_addon->get_activation_indicator_option_name(), true); - $this->assertWPOptionExists($this->_addon->get_activation_indicator_option_name()); - $times_its_new_install_hook_fired_before = isset($wp_actions["AHEE__{$this->_addon_classname}__reactivation"]) - ? $wp_actions["AHEE__{$this->_addon_classname}__reactivation"] : 0; - //now check for activations/upgrades in addons - EE_System::reset(); - $this->assertEquals(EE_System::req_type_reactivation, $this->_addon->detect_req_type()); - $this->assertEquals( - $times_its_new_install_hook_fired_before + 1, - $wp_actions["AHEE__{$this->_addon_classname}__reactivation"] - ); - $this->assertEquals( - EE_Maintenance_Mode::level_0_not_in_maintenance, - EE_Maintenance_Mode::instance()->level() - ); - $this->assertWPOptionDoesNotExist($this->_addon->get_activation_indicator_option_name()); - //ok all done - EE_Maintenance_Mode::instance()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance); - } - - - /** - * Checks that even though the addon was activated, because it happened during - * maintenance mode, we couldn't do any of its setup logic. (SO it should be run - * later, when the site is taken out of MM) - * - * @global array $wp_actions - * @group 6812 - * @group 6910 - */ - public function test_detect_actiavtions_or_upgrade__activation_during_maintenance_mode() - { - global $wp_actions; - //its activation history wp option shouldn't exist - delete_option($this->_addon->get_activation_history_option_name()); - //and it also shouldn't be in the current db state - $current_db_state = get_option(EE_Data_Migration_Manager::current_database_state); - //just for assurance, make sure New Addon is the only existing addon - unset($current_db_state[$this->_addon_name]); - update_option(EE_Data_Migration_Manager::current_database_state, $current_db_state); - $times_reactivation_hook_fired_before = isset($wp_actions["AHEE__{$this->_addon_classname}__new_install"]) - ? $wp_actions["AHEE__{$this->_addon_classname}__new_install"] : 0; - //set the activator option - update_option($this->_addon->get_activation_indicator_option_name(), true); - $this->assertWPOptionExists($this->_addon->get_activation_indicator_option_name()); - //lastly, and imporatntly ADD A DMS SO MAINTENANCE MODE will be set - $this->_add_mock_dms(); - //now check for activations/upgrades in addons - EE_System::reset(); - $this->assertEquals( - EE_Maintenance_Mode::level_2_complete_maintenance, - EE_Maintenance_Mode::instance()->level() - ); - $this->assertEquals(EE_System::req_type_new_activation, $this->_addon->detect_req_type()); - $this->assertEquals( - $times_reactivation_hook_fired_before + 1, - isset($wp_actions["AHEE__{$this->_addon_classname}__new_install"]) - ? $wp_actions["AHEE__{$this->_addon_classname}__new_install"] : 0 - ); - $this->assertArrayContains( - 'New_Addon', - EE_Data_Migration_Manager::instance()->get_db_initialization_queue() - ); - $this->assertWPOptionDoesNotExist($this->_addon->get_activation_indicator_option_name()); - $this->assertTableDoesNotExist('esp_new_addon_thing'); - //ok, now let's pretend the site was teaken out of MM because migrations were finished - $this->_remove_mock_dms(); - EE_Maintenance_Mode::reset()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance); - EE_Data_Migration_Manager::instance()->initialize_db_for_enqueued_ee_plugins(); - //now we also want to check that the addon will have created the necessary table - //that it needed upon new activation - $this->assertEquals( - array(), - EE_Data_Migration_Manager::instance()->check_for_applicable_data_migration_scripts() - ); - $this->assertEquals( - EE_Maintenance_Mode::level_0_not_in_maintenance, - EE_Maintenance_Mode::instance()->real_level() - ); - $this->assertTableExists('esp_new_addon_thing'); - //check for activations/upgrades again. It should be a normal request - EE_System::reset(); - $this->assertEquals(EE_System::req_type_normal, $this->_addon->detect_req_type()); - $this->assertEquals( - $times_reactivation_hook_fired_before + 1, - $wp_actions["AHEE__{$this->_addon_classname}__new_install"] - ); - $this->assertWPOptionDoesNotExist($this->_addon->get_activation_indicator_option_name()); - } - - - /** - * Checks that even though the addon was upgraded, because it happened during - * maintenance mode, we couldn't do any of its setup logic. (SO it should be run - * later, when the site is taken out of MM by the migration manager) - * - * @group 6910 - */ - public function test_detect_actiavtions_or_upgrade__upgrade_during_maintenance_mode() - { - global $wp_actions; - //pretend an older version of this addon was activated a while ago - $addon_activation_history = array( - '0.9.0.dev.000' => array( - date('Y-m-d H:i:s', current_time('timestamp') - DAY_IN_SECONDS * 10), - ), - ); - update_option($this->_addon->get_activation_history_option_name(), $addon_activation_history); - //and it also shouldn't be in the current db state - $current_db_state = get_option(EE_Data_Migration_Manager::current_database_state); - //just for assurance, make sure New Addon is the only existing addon - unset($current_db_state[$this->_addon_name]); - update_option(EE_Data_Migration_Manager::current_database_state, $current_db_state); - $times_reactivation_hook_fired_before = isset($wp_actions["AHEE__{$this->_addon_classname}__upgrade"]) - ? $wp_actions["AHEE__{$this->_addon_classname}__upgrade"] : 0; - //lastly, and importantly SET MAINTENANCE MODE LEVEL 2 - $this->_add_mock_dms(); - //now check for activations/upgrades in addons - EE_System::reset(); - $this->assertEquals( - EE_Maintenance_Mode::level_2_complete_maintenance, - EE_Maintenance_Mode::instance()->level() - ); - $this->assertEquals(EE_System::req_type_upgrade, $this->_addon->detect_req_type()); - $this->assertEquals( - $times_reactivation_hook_fired_before + 1, - isset($wp_actions["AHEE__{$this->_addon_classname}__upgrade"]) - ? $wp_actions["AHEE__{$this->_addon_classname}__upgrade"] : 0 - ); - $this->assertArrayContains( - 'New_Addon', - EE_Data_Migration_Manager::instance()->get_db_initialization_queue() - ); - $addon_activation_history = $this->_addon->get_activation_history(); - $this->assertArrayHasKey('0.9.0.dev.000', $addon_activation_history); - $this->assertArrayHasKey('1.0.0.dev.000', $addon_activation_history); - $this->assertTableDoesNotExist('esp_new_addon_thing'); - //ok, now let's pretend the site was taken out of MM because migrations were finished - $this->_remove_mock_dms(); - EE_Maintenance_Mode::reset()->set_maintenance_level(EE_Maintenance_Mode::level_0_not_in_maintenance); - EE_Data_Migration_Manager::instance()->initialize_db_for_enqueued_ee_plugins(); - //now we also want to check that the addon will have created the necessary table - //that it needed upon new activation - $this->assertEquals( - array(), - EE_Data_Migration_Manager::instance()->check_for_applicable_data_migration_scripts() - ); - $this->assertEquals( - EE_Maintenance_Mode::level_0_not_in_maintenance, - EE_Maintenance_Mode::instance()->real_level() - ); - $this->assertTableExists('esp_new_addon_thing'); - //check for activations/upgrades again. It should be a normal request - EE_System::reset(); - $this->assertEquals(EE_System::req_type_normal, $this->_addon->detect_req_type()); - $this->assertEquals( - $times_reactivation_hook_fired_before + 1, - $wp_actions["AHEE__{$this->_addon_classname}__upgrade"] - ); - $this->assertWPOptionDoesNotExist($this->_addon->get_activation_indicator_option_name()); - } -} - -// End of file EE_System_Test_With_Addons.php -// Location: tests/testcases/core/EE_System_Test_With_Addons.php diff --git a/tests/testcases/core/EeSystemWithAddonTest.php b/tests/testcases/core/EeSystemWithAddonTest.php deleted file mode 100644 index 6e6826b8031..00000000000 --- a/tests/testcases/core/EeSystemWithAddonTest.php +++ /dev/null @@ -1,38 +0,0 @@ -pretendReactivation(); - //do our assertions - $this->assertWPOptionExists($this->addon->get_activation_indicator_option_name()); - $this->assertEquals(EE_System::req_type_reactivation, $this->addon->detect_req_type()); - - //test EE_System reset which simulates activation/upgrades - //simulate activation process - EE_System::reset(); - $this->assertEquals( - $times_its_new_install_hook_fired_before + 1, - $wp_actions["AHEE__EE_NewAddonMock__reactivation"] - ); - $this->assertWPOptionDoesNotExist($this->addon->get_activation_indicator_option_name()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/Psr4AutoloaderTest.php b/tests/testcases/core/Psr4AutoloaderTest.php deleted file mode 100644 index 5c28056d037..00000000000 --- a/tests/testcases/core/Psr4AutoloaderTest.php +++ /dev/null @@ -1,90 +0,0 @@ -loader = new Psr4AutoloaderMock; - $this->loader->setFiles( array( - '/vendor/foo.bar/src/ClassName.php', - '/vendor/foo.bar/src/DoomClassName.php', - '/vendor/foo.bar/tests/ClassNameTest.php', - '/vendor/foo.bardoom/src/ClassName.php', - '/vendor/foo.bar.baz.dib/src/ClassName.php', - '/vendor/foo.bar.baz.dib.zim.gir/src/ClassName.php', - ) ); - $this->loader->addNamespace( - 'Foo\Bar', - '/vendor/foo.bar/src' - ); - $this->loader->addNamespace( - 'Foo\Bar', - '/vendor/foo.bar/tests' - ); - $this->loader->addNamespace( - 'Foo\BarDoom', - '/vendor/foo.bardoom/src' - ); - $this->loader->addNamespace( - 'Foo\Bar\Baz\Dib', - '/vendor/foo.bar.baz.dib/src' - ); - $this->loader->addNamespace( - 'Foo\Bar\Baz\Dib\Zim\Gir', - '/vendor/foo.bar.baz.dib.zim.gir/src' - ); - } - - - - public function testExistingFile() { - $actual = $this->loader->loadClass( 'Foo\Bar\ClassName' ); - $expect = '/vendor/foo.bar/src/ClassName.php'; - $this->assertSame( $expect, $actual ); - $actual = $this->loader->loadClass( 'Foo\Bar\ClassNameTest' ); - $expect = '/vendor/foo.bar/tests/ClassNameTest.php'; - $this->assertSame( $expect, $actual ); - } - - - - public function testMissingFile() { - $actual = $this->loader->loadClass( 'No_Vendor\No_Package\NoClass' ); - $this->assertFalse( $actual ); - } - - - - public function testDeepFile() { - $actual = $this->loader->loadClass( 'Foo\Bar\Baz\Dib\Zim\Gir\ClassName' ); - $expect = '/vendor/foo.bar.baz.dib.zim.gir/src/ClassName.php'; - $this->assertSame( $expect, $actual ); - } - - - - public function testConfusion() { - $actual = $this->loader->loadClass( 'Foo\Bar\DoomClassName' ); - $expect = '/vendor/foo.bar/src/DoomClassName.php'; - $this->assertSame( $expect, $actual ); - $actual = $this->loader->loadClass( 'Foo\BarDoom\ClassName' ); - $expect = '/vendor/foo.bardoom/src/ClassName.php'; - $this->assertSame( $expect, $actual ); - } - - - -} -// End of file Psr4AutoloaderTest.php -// Location: /tests/testcases/core/Psr4AutoloaderTest.php \ No newline at end of file diff --git a/tests/testcases/core/admin/EE_Admin_Hooks_Tests.php b/tests/testcases/core/admin/EE_Admin_Hooks_Tests.php deleted file mode 100644 index de59c6b9c66..00000000000 --- a/tests/testcases/core/admin/EE_Admin_Hooks_Tests.php +++ /dev/null @@ -1,220 +0,0 @@ -loadAdminMocks(); - $this->_eeAdminMock = new Admin_Mock_Valid_Admin_Page(false); - $this->_testRoute = admin_url('admin.php?page=mock_valid_admin_page'); - - //go to mock_valid_admin_page route for test - $this->go_to($this->_testRoute); - $this->defineAdminConstants(); - $this->_eeAdminHookMock = new mock_valid_admin_page_Admin_Mock_Valid_Hooks( $this->_eeAdminMock ); - } - - - /** - * This tests a valid admin hook construct. - * - * Not only will this catch anything wrong with constructing a - * Admin_Hook but we're also testing that public properties - * and methods perform as expected. - * - * @since 4.3.0 - */ - public function test_valid_constructor() { - //test things setup after construct - $this->assertTrue( $this->_eeAdminHookMock->verify_adminpage_obj() instanceof Admin_Mock_Valid_Admin_Page ); - $this->assertFalse( $this->_eeAdminHookMock->verify_extend() ); - } - - /** - * @since 4.3.0 - * @depends test_valid_constructor - */ - public function test_enqueue_scripts_styles() { - $this->_eeAdminHookMock->enqueue_scripts_styles(); - $this->assertTrue( wp_style_is( 'test-css', 'registered' ) ); - $this->assertTrue( wp_style_is( 'test-css' ) ); - $this->assertFalse( wp_style_is( 'event-editor-css', 'registered' ) ); - $this->assertTrue( wp_script_is( 'test-js', 'registered' ) ); - $this->assertTrue( wp_script_is( 'test-js' ) ); - - //test exception if no registers index in _scripts_styles property. - $scripts_styles_cache = $this->_eeAdminHookMock->get_property( '_scripts_styles' ); - - //let's set a scripts styles array with no registers. - $new_scripts_styles['something'] = 'fail'; - $this->_eeAdminHookMock->set_property( '_scripts_styles', $new_scripts_styles ); - $this->setExpectedException('EE_Error'); - $this->_eeAdminHookMock->enqueue_scripts_styles(); - - - //test for exception with missing params - $this->_eeAdminHookMock->set_property( '_scripts_styles', $scripts_styles_cache ); - $new_scripts_styles = $scripts_styles_cache; - unset( $new_scripts_styles['registers']['test-css']['url'] ); - $this->_eeAdminHookMock->set_property( '_scripts_styles', $new_scripts_styles ); - $this->setExpectedException('EE_Error'); - $this->_eeAdminHookMock->enqueue_scripts_styles(); - - //restore correct scripts styles - $this->_eeAdminHookMock->set_property( '_scripts_styles', $scripts_styles_cache ); - } - - - /** - * @since 4.3.0 - * @depends test_valid_constructor - */ - public function test__set_defaults() { - $this->assertEquals( 'default', $this->_eeAdminHookMock->verify_current_route() ); - $this->assertEquals( $this->_eeAdminHookMock->caller, 'mock_valid_admin_page_Admin_Mock_Valid_Hooks' ); - $this->assertFalse( $this->_eeAdminHookMock->verify_extend() ); - } - - - /** - * @since 4.3.0 - * @depends test_valid_constructor - */ - public function test__set_page_object() { - $this->assertTrue( $this->_eeAdminHookMock->verify_page_object() instanceof Admin_Mock_Valid_Admin_Page ); - - //test exception if _name is empty - $cached_name = $this->_eeAdminHookMock->get_property( '_name' ); - $this->_eeAdminHookMock->set_property( '_name', NULL ); - $this->setExpectedException( 'EE_Error' ); - $this->_eeAdminHookMock->call_method( '_set_page_object' ); - - //test exception if class does not exist - $this->_eeAdminHookMock->set_property( '_name', 'fail' ); - $this->setExpectedException( 'EE_Error' ); - $this->_eeAdminHookMock->call_method( '_set_page_object' ); - - //restore _name - $this->_eeAdminHookMock->set_property( '_name', $cached_name ); - } - - - /** - * @since 4.3.0 - * @depends test_valid_constructor - */ - public function test__init_hooks() { - $this->assertEquals( has_filter( 'admin_init', array( $this->_eeAdminHookMock, 'init_callback_test' ) ), 10 ); - - //test exception if method doesn't exist - $cached_init_func = $this->_eeAdminHookMock->get_property( '_init_func' ); - $this->_eeAdminHookMock->set_property( '_init_func', array( 'fail' => 'fail' ) ); - $this->setExpectedException( 'EE_Error' ); - $this->_eeAdminHookMock->call_method( '_init_hooks' ); - - //restore - $this->_eeAdminHookMock->set_property( '_init_func', $cached_init_func ); - } - - - - - /** - * This tests the addition of metaboxes which actually gets - * kicked off by the public add_metaboxes method. - * - * @since 4.3.0 - * @depends test_valid_constructor - */ - public function test__add_metabox() { - //test exception if the callback for the metabox doesn't exist - $cached_metabox = $this->_eeAdminHookMock->get_property( '_metaboxes' ); - $new_metabox = $cached_metabox; - $new_metabox[0]['func'] = 'invalid'; - $this->_eeAdminHookMock->set_property( '_metaboxes', $new_metabox ); - $this->setExpectedException( 'EE_Error' ); - $this->_eeAdminHookMock->add_metaboxes(); - //restore - $this->_eeAdminHookMock->set_property( '_metaboxes', $cached_metabox ); - } - - - - /** - * @since 4.3.0 - * @depends test_valid_constructor - */ - public function test__load_custom_methods() { - $this->assertTrue( $this->_eeAdminHookMock->route_callback ); - $this->assertEquals( has_action('AHEE__Admin_Mock_Valid_Admin_Page___redirect_after_action__before_redirect_modification_default', array( $this->_eeAdminHookMock, '_redirect_action_early_default' ) ), 10 ); - $this->assertEquals( has_action('AHEE_redirect_Admin_Mock_Valid_Admin_Pagedefault', array( $this->_eeAdminHookMock, '_redirect_action_default' ) ), 10 ); - $this->assertEquals( has_filter( 'FHEE_redirect_Admin_Mock_Valid_Admin_Pagedefault', array( $this->_eeAdminHookMock, '_redirect_filter_default' ) ), 10 ); - } - - - - /** - * @since 4.3.0 - * @depends test_valid_constructor - */ - public function test__load_routed_hooks() { - $this->assertEquals( has_action('admin_footer', array( $this->_eeAdminHookMock, 'default_admin_footer' ) ), 10 ); - $this->assertEquals( has_filter( 'FHEE_list_table_views_mock_valid_admin_page_default', array( $this->_eeAdminHookMock, 'default_FHEE_list_table_views_mock_valid_admin_page_default' ) ), 10 ); - $this->assertEquals( has_filter( 'FHEE_list_table_views_mock_valid_admin_page', array( $this->_eeAdminHookMock, 'default_FHEE_list_table_views_mock_valid_admin_page' ) ), 10 ); - $this->assertEquals( has_filter( 'FHEE_list_table_views', array( $this->_eeAdminHookMock, 'default_FHEE_list_table_views' ) ), 10 ); - $this->assertEquals( has_action( 'AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes', array( $this->_eeAdminHookMock, 'default_AHEE__EE_Admin_Page___display_admin_page__modify_metaboxes') ), 10 ); - } - - - - /** - * @since 4.3.0 - * @depends test_valid_constructor - */ - public function test__ajax_hooks() { - $this->assertEquals( has_action( 'wp_ajax_ajax_test', array( $this->_eeAdminHookMock, 'ajax_test_callback' ) ), 10 ); - } - - - - /** - * This tests the loading of an EE_Admin_Page_Hooks class that is setup incorrectly. (it'll just return really early). - * - * @since 4.3.0 - */ - public function test_invalid_constructor() { - $this->go_to( admin_url() ); - //go to mock_valid_admin_page route for test - $this->_eeAdminHookMock = new dummy_not_exist_Hooks( $this->_eeAdminMock ); - - //should have exited early so there should be no page object set. - $this->assertEmpty( $this->_eeAdminHookMock->verify_page_object() ); - } - - -} - -//class EE_Admin_Hook diff --git a/tests/testcases/core/admin/EE_Admin_Tests.php b/tests/testcases/core/admin/EE_Admin_Tests.php deleted file mode 100644 index 37154f5610a..00000000000 --- a/tests/testcases/core/admin/EE_Admin_Tests.php +++ /dev/null @@ -1,330 +0,0 @@ -load_core('EE_Admin'); - $this->assertInstanceOf('EE_Admin', $admin_instance); - - //tests filters have been added that are expected here. Remember the has_{filter/action} returns the priority set by the caller. - $this->assertEquals( has_filter('plugin_action_links', array($admin_instance, 'filter_plugin_actions') ), 10 ); - $this->assertEquals( has_action('AHEE__EE_System__core_loaded_and_ready', array($admin_instance, 'get_request') ), 10 ); - $this->assertEquals( has_action('AHEE__EE_System__initialize_last', array($admin_instance, 'init') ), 10 ); - $this->assertEquals( has_action('AHEE__EE_Admin_Page__route_admin_request', array($admin_instance, 'route_admin_request') ), 100 ); - $this->assertEquals( has_action('wp_loaded', array($admin_instance, 'wp_loaded') ), 100 ); - $this->assertEquals( has_action('admin_init', array($admin_instance, 'admin_init') ), 100 ); - $this->assertEquals( has_action('admin_enqueue_scripts', array($admin_instance, 'enqueue_admin_scripts') ), 20 ); - $this->assertEquals( has_action('admin_notices', array($admin_instance, 'display_admin_notices') ), 10 ); - $this->assertEquals( has_filter('admin_footer_text', array($admin_instance, 'espresso_admin_footer') ), 10 ); - } - - /** - * Tests constants that should be defined after EE_Admin::__construct() - * - * @since 4.3.0 - * - * @depends test_loading_admin - */ - public function test_define_all_constants() { - $this->assertTrue( defined('EE_ADMIN_URL') ); - $this->assertTrue( defined('EE_ADMIN_PAGES_URL') ); - $this->assertTrue( defined('EE_ADMIN_TEMPLATE') ); - $this->assertTrue( defined('WP_ADMIN_PATH' ) ); - $this->assertTrue( defined('WP_AJAX_URL') ); - } - - - - /** - * Tests that the filter_plugin_actions callback for plugin_action_links works as expected. - * - * @since 4.3.0 - * - * @depends test_loading_admin - */ - public function test_filter_plugin_actions() { - //make sure maintenance class is loaded and set to 0 - $this->setMaintenanceMode(); - $main_file = EE_PLUGIN_BASENAME; - $original_link = array('link'); - $expected = array('' . __( 'Settings', 'event_espresso' ) . '', '' . __( 'Events', 'event_espresso' ) . '', 'link'); - - //first test if plugin does NOT equal main file. - $filtered = EE_Admin::instance()->filter_plugin_actions( $original_link, 'fail' ); - $this->assertEquals( $original_link, $filtered ); - - //test if plugin DOES equal main file and maintenance mode level left at 0. - $filtered = EE_Admin::instance()->filter_plugin_actions( $original_link, $main_file ); - $this->assertEquals( $expected, $filtered ); - - //test if plugin DOES equal main file and maintenance mode level is 1. - $this->setMaintenanceMode(1); - $filtered = EE_Admin::instance()->filter_plugin_actions( $original_link, $main_file ); - $this->assertEquals( $expected, $filtered ); - - //test if plugin DOES equal main file and maintenance mode level is 2. - $this->setMaintenanceMode(2); - $expected = array('' . __('Maintenance Mode Active', 'event_espresso' ) . '', 'link'); - $filtered = EE_Admin::instance()->filter_plugin_actions($original_link, $main_file); - $this->assertEquals( $expected, $filtered ); - - //set maintenance mode back to normal. - $this->setMaintenanceMode(); - } - - - - - /** - * ensure that Request Handler and CPT_Strategy classes are loaded by the get_request method - * as expected. - * - * @since 4.3.0 - * - * @depends test_loading_admin - */ - public function test_get_request() { - EE_Admin::instance()->get_request(); - $this->assertTrue( class_exists('EE_Request_Handler') ); - $this->assertTrue( class_exists('EE_CPT_Strategy') ); - } - - - - - - /** - * This tests the init callback in EE_Admin. - * - * @since 4.3.0 - * - * @depends test_loading_admin - */ - public function test_init() { - $admin = EE_Admin::instance(); - - //test when maintenance mode is set at level 2 - $this->setMaintenanceMode(2); - $admin->init(); - $this->assertFalse( has_action('dashboard_glance_items', array( $admin, 'dashboard_glance_items' ) ) ); - $this->assertFalse( has_filter( 'get_edit_post_link', array( $admin, 'modify_edit_post_link') ) ); - //should happen with both conditions - $this->assertEquals( has_filter( 'content_save_pre', array( $admin, 'its_eSpresso' ) ), 10 ); - $this->assertEquals( has_action('admin_head', array( $admin, 'enable_hidden_ee_nav_menu_metaboxes' ) ), 10 ); - $this->assertEquals( has_action('admin_head', array( $admin, 'register_custom_nav_menu_boxes' ) ), 10 ); - $this->assertEquals( has_filter('nav_menu_meta_box_object', array( $admin, 'remove_pages_from_nav_menu' ) ), 10 ); - - //test when maintenance mode is set to something other than 2 - $this->setMaintenanceMode(); - //reset filters for test - $this->clearAllFilters( array('FHEE__EE_Admin_Page_Loader___get_installed_pages__installed_refs') ); - - $admin->init(); - - $this->assertFalse( has_filter('FHEE__EE_Admin_Page_Loader___get_installed_pages__installed_refs', array( $admin, 'hide_admin_pages_except_maintenance_mode' ) ) ); - $this->assertEquals( has_filter('content_save_pre', array( $admin, 'its_eSpresso' ) ), 10 ); - $this->assertEquals( has_action('dashboard_glance_items', array( $admin, 'dashboard_glance_items' ) ), 10 ); - //should happen with both conditions - $this->assertEquals( has_action('admin_head', array( $admin, 'enable_hidden_ee_nav_menu_metaboxes' ) ), 10 ); - $this->assertEquals( has_action('admin_head', array( $admin, 'register_custom_nav_menu_boxes' ) ), 10 ); - $this->assertEquals( has_filter('nav_menu_meta_box_object', array( $admin, 'remove_pages_from_nav_menu' ) ), 10 ); - $this->assertEquals( has_filter( 'get_edit_post_link', array( $admin, 'modify_edit_post_link') ), 10 ); - - //default should have Admin Page Loader loaded up. - $this->assertTrue( class_exists( 'EE_Admin_Page_Loader' ) ); - } - - - - - /** - * Test callback for removing pages from nav menu - * - * @since 4.3.0 - * @depends test_loading_admin - */ - public function test_remove_pages_from_nav_menu() { - //test non page post type object - $posttypeStub = new stdClass(); - $posttypeStub->name = 'non_page'; - $expected = 'non_page'; - $result = EE_Admin::instance()->remove_pages_from_nav_menu( $posttypeStub ); - $this->assertEquals( $expected, $result->name ); - - //test when posttype DOES equal page - $posttypeStub->name = 'page'; - $this->setCoreConfig(); - $expected = EE_Registry::instance()->CFG->core->get_critical_pages_array(); - $result = EE_Admin::instance()->remove_pages_from_nav_menu( $posttypeStub ); - $test_response = !empty( $result->_default_query['post__not_in'] ) ? $result->_default_query['post__not_in'] : NULL; - $this->assertEquals( $expected, $test_response ); - } - - - /** - * test enable_hidden_ee_nav_menu_metaboxes() - * - * @since 4.3.0 - * @depends test_loading_admin - */ - public function test_enable_hidden_ee_nav_menu_metaboxes() { - - //first we'll add dummy metabox to simulate our metaboxes. - add_meta_box( 'add-espresso_events', __('Event Espresso Pages', 'event_espresso'), '__return_true', 'nav-menus', 'side', 'core' ); - - //need to set the current user - //$current_user = get_current_user_id(); - wp_set_current_user( $this->factory->user->create( array( 'role' => 'administrator' ) ) ); - - //set the current page to the be the nav-menus.php page - global $pagenow; - $pagenow = 'nav-menus.php'; - - //run test - //should be a registered metabox with the add-espresso_events id. - global $wp_meta_boxes; - $this->assertArrayHasKey( 'add-espresso_events', $wp_meta_boxes['nav-menus']['side']['core'], 'There should be a registered metabox with the key add-espresso_events and there isn\'t' ); - - //now let's verify that the method being tested works as expected - EE_Admin::instance()->enable_hidden_ee_nav_menu_metaboxes(); - $hidden_metaboxes = get_user_option( get_current_user_id(), 'metaboxhidden_nav-menus' ); - $this->assertEmpty( $hidden_metaboxes ); - } - - - - /** - * testing output for the dashboard upcoming widget hook callback - * - * @since 4.3.0 - * @depends test_loading_admin - */ - public function test_dashboard_glance_items() { - //add some events and registrations - $this->factory->event->create_many(10); - $this->factory->registration->create_many(5, array( 'STS_ID' => EEM_Registration::status_id_not_approved ) ); - $this->factory->registration->create_many(3); - - //expected events dashboard items - $xpct_events_url = EEH_URL::add_query_args_and_nonce( array( 'page' => 'espresso_events'), admin_url('admin.php') ); - $xpct_events_text = sprintf( _n( '%s Event', '%s Events', 10 ), number_format_i18n( 10 ) ); - $xpct_events_title = __('Click to view all Events', 'event_espresso'); - $xpct_event_assembled = sprintf( '%s', $xpct_events_url, $xpct_events_title, $xpct_events_text ); - - //expected registration dashboard items - $xpct_registration_url = EEH_URL::add_query_args_and_nonce( array('page' => 'espresso_registrations' ), admin_url('admin.php') ); - $xpct_registration_text = sprintf( _n( '%s Registration', '%s Registrations', 5 ), number_format_i18n(5) ); - $xpct_registration_title = __('Click to view all registrations', 'event_espresso'); - $xpct_registration_assembled = sprintf( '%s', $xpct_registration_url, $xpct_registration_title, $xpct_registration_text ); - - $generated_items = EE_Admin::instance()->dashboard_glance_items( array() ); - //first assert the elements are an array. - $this->assertInternalType('array', $generated_items); - - //assert the count for the array is two - $this->assertCount( - 2, - $generated_items, - sprintf('$generated_items should have 2 elements: ', print_r($generated_items, true)) - ); - - //assert that the first item matches the xpctd event string. - $this->assertEquals( $xpct_event_assembled, $generated_items[0] ); - - //assert that the second item matches the xpctd registration string - $this->assertEquals( $xpct_registration_assembled, $generated_items[1] ); - } - - //@todo public methods to write tests for - - //function test_dashboard_glance_items() - //function test_parse_post_content_on_save() - - - /** - * Test its_eSpresso method that converts incorrect spelling of Espresso in shortcodes with the correct spelling. - * - * @since 4.3.0 - * @depends test_loading_admin - */ - public function test_its_eSpresso() { - //test works as expected with string to correct. - $expected = '[ESPRESSO_CONTENT]'; - $test = '[EXPRESSO_CONTENT]'; - $result = EE_Admin::instance()->its_eSpresso( $test ); - $this->assertEquals( $result, $expected ); - - //test works as expected with string that should NOT be corrected. - $expected = 'some_string'; - $result = EE_Admin::instance()->its_eSpresso('some_string'); - $this->assertEquals( $result, $expected ); - } - - - - - /** - * Test the powered by Event Espresso footer. - * - * @since 4.3.0 - * @depends test_loading_admin - */ - public function test_espresso_admin_footer() { - $actual = EE_Admin::instance()->espresso_admin_footer(); - //assert contains powered by text. - $this->assertContains('Online event registration and ticketing powered by ', $actual); - //assert contains eventespresso.com link - $this->assertContains('https://eventespresso.com/', $actual); - } - - - - /** - * Test the filter callback for get_edit_post_link - * - * @since 4.3.0 - * @depends test_loading_admin - */ - public function test_modify_edit_post_link() { - //add contact post - $attendee = EE_Attendee::new_instance( array( 'ATT_full_name' => 'Test Dude' ) ); - $attendee->save(); - $id = $attendee->ID(); - - //dummy link for testing - $orig_link = 'http://testdummylink.com'; - $expected_link = EEH_URL::add_query_args_and_nonce( array( 'action' => 'edit_attendee', 'post' => $id ), admin_url('admin.php?page=espresso_registrations' ) ); - - //first test that if the id given doesn't match our post type that the original link is returned. - $notmodified = EE_Admin::instance()->modify_edit_post_link( $orig_link, 5555, '' ); - $this->assertEquals( $orig_link, $notmodified ); - - //next test that if the id given matches our post type that the expected link is generated - $ismodified = EE_Admin::instance()->modify_edit_post_link( $orig_link, $id, '' ); - - $this->assertEquals( $expected_link, $ismodified ); - } - -} -// Location: testcases/core/admin/EE_Admin_Tests.php diff --git a/tests/testcases/core/business/EE_Registration_Processor_Test.php b/tests/testcases/core/business/EE_Registration_Processor_Test.php deleted file mode 100644 index 6fc79febda3..00000000000 --- a/tests/testcases/core/business/EE_Registration_Processor_Test.php +++ /dev/null @@ -1,41 +0,0 @@ -new_model_obj_with_dependencies( 'Transaction' , array( 'TXN_total' => 2.99)); - $regs = array(); - for( $i=0; $i<3; $i++ ) { - $regs[] = $this->new_model_obj_with_dependencies( 'Registration', array( 'REG_final_price' => 1, 'TXN_ID' => $txn->ID() ) ); - } - //ok so there's a 1 cent difference. The REG_final_price_sum should be 1 cent more than the transaction total - $reg_final_price_sum = EEM_Registration::instance()->sum( array( array( 'TXN_ID' => $txn->ID() ) ), 'REG_final_price' ); - $this->assertEquals( $txn->total() + 0.01, $reg_final_price_sum ); - - $reg_processor = EE_Registry::instance()->load_class( 'Registration_Processor' ); - $success = $reg_processor->fix_reg_final_price_rounding_issue( $txn ); - $this->assertTrue( $success ); - $new_reg_final_price_sum = EEM_Registration::instance()->sum( array( array( 'TXN_ID' => $txn->ID() ) ), 'REG_final_price' ); - $this->assertEquals( $txn->total(), $new_reg_final_price_sum ); - //specifically, the first reg should now be $0.99, but the others should still be $1 each - $this->assertEquals( .99, $regs[0]->final_price() ); - $this->assertEquals( 1, $regs[1]->final_price() ); - $this->assertEquals( 1, $regs[2]->final_price() ); - } -} - -// End of file EE_Registration_Processor_Test.php \ No newline at end of file diff --git a/tests/testcases/core/data_migration_scripts/EE_DMS_Core_4_1_0_Tests.php b/tests/testcases/core/data_migration_scripts/EE_DMS_Core_4_1_0_Tests.php deleted file mode 100644 index 96b575f920d..00000000000 --- a/tests/testcases/core/data_migration_scripts/EE_DMS_Core_4_1_0_Tests.php +++ /dev/null @@ -1,28 +0,0 @@ -assertTrue( $this->table_exists_check( 'esp_event_message_template' ) ); - } - - function table_exists_check( $name ) { - global $wpdb; - $table_name = $wpdb->prefix . $name; - return $wpdb->get_var( "SHOW TABLES LIKE '$table_name'" ) == $table_name; - } -} diff --git a/tests/testcases/core/data_migration_scripts/EE_DMS_Core_4_6_0_Tests.php b/tests/testcases/core/data_migration_scripts/EE_DMS_Core_4_6_0_Tests.php deleted file mode 100644 index 981c2d69a32..00000000000 --- a/tests/testcases/core/data_migration_scripts/EE_DMS_Core_4_6_0_Tests.php +++ /dev/null @@ -1,46 +0,0 @@ -new_model_obj_with_dependencies( 'Attendee' ); - $att1->update_post_meta( $postmeta_name, $billing_info ); - $att2 = $this->new_model_obj_with_dependencies( 'Attendee' ); - $att2->update_post_meta( $postmeta_name, $billing_info ); - - //load teh dms, which should autoload the stage we want to test - $script = EE_Registry::instance()->load_dms( 'EE_DMS_Core_4_6_0' ); - $stage = new EE_DMS_4_6_0_billing_info(); - $stage->_construct_finalize( $script ); - $this->assertEquals( 2, $stage->count_records_to_migrate() ); -// var_dump($stage); - $stage->migration_step( 1 ); - $this->assertEquals( 1, $stage->count_records_migrated() ); - //get that updated postmeta - $new_billing_info = $att1->get_post_meta( $postmeta_name, TRUE ); - $this->assertNotEquals( $billing_info, $new_billing_info ); - $this->assertArrayHasKey( 'first_name', $new_billing_info ); - //verify we only migrated what we said we would- the first item only - $this->assertEquals( $billing_info, $att2->get_post_meta( $postmeta_name, TRUE ) ); - - - //now migrate the next one - $stage->migration_step( 1 ); - } -} - -// End of file EE_DMS_Core_4_6_0_Tests.php \ No newline at end of file diff --git a/tests/testcases/core/data_migration_scripts/EE_DMS_Core_4_8_0_Tests.php b/tests/testcases/core/data_migration_scripts/EE_DMS_Core_4_8_0_Tests.php deleted file mode 100644 index 6681dcc0133..00000000000 --- a/tests/testcases/core/data_migration_scripts/EE_DMS_Core_4_8_0_Tests.php +++ /dev/null @@ -1,36 +0,0 @@ -load_dms( 'EE_DMS_Core_4_8_0' ); - $stage = new EE_DMS_4_8_0_pretax_totals(); - - // ok let's create a line item to with the LIN_code='tickets' - $tickets_subtotal = $this->new_model_obj_with_dependencies( 'Line_Item', array( 'LIN_code' => 'tickets' ) ); - // and another that DOESN"T match it - $other_line_item = $this->new_model_obj_with_dependencies( 'Line_Item', array( 'LIN_code' => 'not-tickets' ) ); - $stage->migration_step(); - $new_tickets_subtotal = EEM_Line_Item::instance()->refresh_entity_map_from_db( $tickets_subtotal->ID() ); - $this->assertEquals( 'pre-tax-subtotal', $new_tickets_subtotal->get( 'LIN_code' ) ); - - $new_other_line_item = EEM_Line_Item::instance()->refresh_entity_map_from_db( $other_line_item->ID() ); - $this->assertEquals( 'not-tickets', $new_other_line_item->get( 'LIN_code' ) ); - } -} - -// End of file EE_DMS_Core_4_8_0_Tests.php \ No newline at end of file diff --git a/tests/testcases/core/db_classes/EE_Attendee_Test.php b/tests/testcases/core/db_classes/EE_Attendee_Test.php deleted file mode 100644 index 03d262185eb..00000000000 --- a/tests/testcases/core/db_classes/EE_Attendee_Test.php +++ /dev/null @@ -1,102 +0,0 @@ -save(); - $this->assertNotEquals($a->ID(),0); - $e1 = EE_Event::new_instance(array('EVT_name'=>'1')); - $e1->save(); - $this->assertNotEquals($e1->ID(),0); - $e2 = EE_Event::new_instance(array('EVT_name'=>'2')); - $e2->save(); - $this->assertNotEquals($e2->ID(),0); - $e3 = EE_Event::new_instance(array('EVT_name'=>'3')); - $e3->save(); - $this->assertNotEquals($e3->ID(),0); - $r1 = EE_Registration::new_instance(array('EVT_ID'=>$e1->ID(),'ATT_ID'=>$a->ID())); - $r1->save(); - $this->assertNotEquals($r1->ID(),0); - $r2 = EE_Registration::new_instance(array('EVT_ID'=>$e2->ID(),'ATT_ID'=>$a->ID())); - $r2->save(); - $this->assertNotEquals($r2->ID(),0); - $events = $a->events(); - $this->assertArrayContains($e1,$events); - $this->assertArrayContains($e2,$events); - $this->assertArrayDoesNotContain($e3,$events); - } - - public function test_get_billing_info_postmeta_name(){ - /* - * @var $reg EE_Registration - */ - $reg = $this->new_model_obj_with_dependencies('Registration'); - - $att = $reg->attendee(); - $payment_method = $reg->transaction()->payment_method(); - $key = $att->get_billing_info_postmeta_name( $payment_method ); - $this->assertEquals('billing_info_Admin_Only', $key ); - } - public function test_save_and_clean_billing_info_for_payment_method(){ - $pm = EE_Payment_Method::new_instance(array( 'PMD_type'=>'Aim' ) ); - $pm->save(); - //reset the country model because it caches its list of countries which is used when - //making most billing forms - EEM_Country::reset(); - $form = $pm->type_obj()->billing_form(); - $form_name = $form->name(); - $form_values = array( - 'first_name' => 'e', - 'last_name' => 'e', - 'email' => 'developers@eventespresso.com', - 'address' => '123', - 'address2' => '', - 'city' => 'someville', - 'state' => 12, - 'country' => 'US', - 'zip' => '1235', - 'phone' => '9991231234', - 'credit_card'=>'4007000000027', - 'exp_month'=>'12', - 'exp_year'=>'2020', - 'cvv'=>'123', - ); - $form->receive_form_submission( array( $form_name => $form_values ) ); - $this->assertTrue( $form->is_valid(), 'error was: ' . $form->get_validation_error_string() ); - $p = $this->new_model_obj_with_dependencies('Payment', array( 'PMD_ID'=>$pm->ID() ) ); - $reg = $this->new_model_obj_with_dependencies('Registration',array( 'TXN_ID' => $p->TXN_ID() ) ); - $att = $reg->attendee(); - $att->save_and_clean_billing_info_for_payment_method( $form, $pm ); - //ok so now it should ahve been saved. Let's verify that - $billing_info_form = $att->billing_info_for_payment_method( $pm ); - $this->assertInstanceOf( 'EE_Billing_Attendee_Info_Form', $billing_info_form ); - //it should ahve been cleaned too, so lets tweak teh form values ot what they should be - $form_values[ 'credit_card' ] = 'XXXXXXXXX0027'; - $form_values[ 'cvv' ] = 'XXX'; - $form_values[ 'exp_month' ] = ''; - $form_values[ 'exp_year' ] = 0; - foreach($form_values as $input_name => $value){ - $input = $billing_info_form->get_input( $input_name); - $this->assertInstanceOf( 'EE_Form_Input_Base', $input ); - $this->assertEquals( $value, $input->raw_value(), $input_name ); - } - } -} - -// End of file tests/testcases/core/db_classes/EE_Attendee_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_classes/EE_Base_Class_Test.php b/tests/testcases/core/db_classes/EE_Base_Class_Test.php deleted file mode 100644 index ebd02f881fc..00000000000 --- a/tests/testcases/core/db_classes/EE_Base_Class_Test.php +++ /dev/null @@ -1,1131 +0,0 @@ - array(EE_MOCKS_DIR . 'core/db_models/'), - 'class_paths' => array(EE_MOCKS_DIR . 'core/db_classes/'), - ) - ); - } - - - public function tearDown() - { - EE_Register_Model::deregister('Mock'); - parent::tearDown(); - } - - static function setUpBeforeClass() - { - // EEH_Activation::create_table('esp_mock', - // "MCK_ID int(11) NOT NULL, - // PRIMARY KEY (MCK_ID)"); - // require_once(EE_TESTS_DIR.'mocks/core/db_models/EEM_Mock.model.php'); - // require_once(EE_TESTS_DIR.'mocks/core/db_classes/EE_Mock.class.php'); - parent::setUpBeforeClass(); - } - - - /** - * @return \EE_Attendee - */ - function test_new_instance() - { - $a = EE_Attendee::new_instance(); - $this->assertNotNull($a); - $this->assertInstanceOf('EE_Attendee', $a); - return $a; - } - - - /** - * @group 9273 - * @see https://events.codebasehq.com/projects/event-espresso/tickets/9273 - */ - function test_new_instance_with_existing_object_and_incoming_date_formats() - { - //setup a EE_Payment object and save - $payment_object = EE_Payment::new_instance(); - $payment_object->save(); - $payment_object_id = $payment_object->ID(); - //now let's setup a new payment object using that ID but with different formats than the defaults - //that way we can verify the timestamp gets set correctly. - $expected_date = '2016-24-01'; - $payment_object_to_test = EE_Payment::new_instance( - array( - 'PAY_ID' => $payment_object_id, - 'PAY_timestamp' => '2016-24-01 3:45 pm', - ), - '', - array('Y-d-m', 'g:i a') - ); - $this->assertEquals($expected_date, $payment_object_to_test->get_date('PAY_timestamp')); - } - - - function test_set_and_get() - { - $a = EE_Attendee::new_instance(); - $a->set('ATT_fname', 'value1'); - $this->assertEquals($a->get('ATT_fname'), 'value1'); - //verify that we can change it - $a->set('ATT_fname', 'value2'); - $this->assertEquals($a->get('ATT_fname'), 'value2'); - } - - - function test_set_and_get_with_caching() - { - $t = EE_Transaction::new_instance(); - $t->set('TXN_total', 10.53); - $this->assertEquals($t->get('TXN_total'), 10.53); - $this->assertEquals($t->get_pretty('TXN_total'), '$10.53 (USD)'); - //make sure the caching of pretty and normal fields doesn't mess us up - $this->assertEquals($t->get('TXN_total'), 10.53); - $t->set('TXN_total', 0.00); - $this->assertEquals($t->get('TXN_total'), 0); - $this->assertEquals($t->get_pretty('TXN_total'), '$0.00 (USD)'); - $this->assertEquals($t->get('TXN_total'), 0); - } - - - function test_save_string_pk() - { - //test saving something with an auto-increment PK - $c = EE_Country::new_instance(array('CNT_ISO' => '12')); - $results = $c->save(); - $this->assertEquals($results, $c->ID()); - $c->set('CNT_cur_code', 'FOO'); - $results2 = $c->save(); - $this->assertEquals(true, $results2); - } - - - function test_save_autoincrement_pk() - { - //test saving something with an auto-increment PK - $t = EE_Transaction::new_instance(); - $id = $t->save(); - $this->assertNotNull($id); - $this->assertEquals($t->ID(), $id); - $t2 = EEM_Transaction::instance()->get_one_by_ID($id); - $this->assertEquals($id, $t2->ID()); - //and check that its correctly saved to the model's entity map - $existing_t_in_entity_map = EEM_Transaction::instance()->get_from_entity_map($id); - $this->assertInstanceOf('EE_Transaction', $existing_t_in_entity_map); - } - - - /** - * @group 8622 - */ - function test_save__allow_persist_changed() - { - $t = EE_Transaction::new_instance(); - $t->set_allow_persist(false); - $result = $t->save(); - $this->assertEquals(0, $result); - $t->set_allow_persist(true); - $result2 = $t->save(); - $this->assertNotEquals(0, $result2); - } - - // function test_save_no_pk(){ - //@todo: make this test work - //the following is known to not work for the time-being (the models - //system should be improved to allow this, when we get time) - // $term_taxonomy = $this->new_model_obj_with_dependencies('Term_Taxonomy', array('taxonomy'=>'monkeys')); - // $e = $this->new_model_obj_with_dependencies('Event'); - // $tr = EE_Term_Relationship::new_instance(array('object_id'=>$e->ID())); - // $results = $tr->save(); - // $this->assertNotNull($results); - // } - /** - * @group 8686 - */ - function test_add_relation_to() - { - $t = EE_Transaction::new_instance(); - $t->save(); - $r = EE_Registration::new_instance(); - $r->save(); - //verify the relations - try { - $r->transaction(); - } catch (Exception $e) { - $this->assertTrue(true); - } - $rs_from_t = $t->registrations(); - $this->assertTrue(empty($rs_from_t)); - //add a relation and verify it changes the model object with the PK - $r->_add_relation_to($t, 'Transaction'); - $this->assertEquals($t->ID(), $r->get('TXN_ID')); - //and we get expected results when fetching using it - $t_from_r = $r->transaction(); - $this->assertEquals($t, $t_from_r); - $rs_from_t = $t->registrations(); - $this->assertFalse(empty($rs_from_t)); - } - - - /** - * @group 8686 - */ - function test_add_relation_to__unsaved() - { - $t = EE_Transaction::new_instance(); - $r = EE_Registration::new_instance(); - $t->_add_relation_to($r, 'Registration'); - $t_from_r = $r->transaction(); - $this->assertEquals($t, $t_from_r); - $rs_from_t = $t->registrations(); - $this->assertFalse(empty($rs_from_t)); - } - - - /** - * @group 7084 - */ - function test_set_defaults_on_unspecified_fields() - { - $r = EE_Registration::new_instance(array('TXN_ID' => 99)); - $this->assertEquals(99, $r->transaction_ID()); - //the STS_ID should have been set to the default, not left NULL - $this->assertEquals(EEM_Registration::instance()->field_settings_for('STS_ID')->get_default_value(), - $r->status_ID()); - } - - - function test_get_first_related() - { - $t = EE_Transaction::new_instance(); - $t->save(); - $r = EE_Registration::new_instance(); - $r->save(); - $t->_add_relation_to($r, 'Registration'); - $r_from_t = $t->get_first_related('Registration'); - $this->assertEquals($r->ID(), $r_from_t->ID()); - $t_from_r = $r->get_first_related('Transaction'); - $this->assertEquals($t->ID(), $t_from_r->ID()); - } - - - function test_get_many_related() - { - $t = EE_Transaction::new_instance(); - $t->save(); - $r = EE_Registration::new_instance(); - $r->save(); - $r2 = EE_Registration::new_instance(); - $r2->save(); - $t->_add_relation_to($r, 'Registration'); - $t->_add_relation_to($r2, 'Registration'); - $rs_from_t = $t->get_many_related('Registration'); - $this->assertCount(2, $rs_from_t); - foreach ($rs_from_t as $r_from_t) { - $this->assertInstanceOf('EE_Registration', $r_from_t); - } - } - - - function test_cache_related() - { - $t = EE_Transaction::new_instance(); - //note that we did NOT save it - $r = EE_Registration::new_instance(); - $t->_add_relation_to($r, 'Registration'); - $this->assertEquals($t->ID(), 0); - $this->assertEquals($r->ID(), 0); - //get the registration cached on the transaction - $r_from_t = $t->get_first_related('Registration'); - $this->assertEquals($r, $r_from_t); - } - - - /** - * @group 8686 - */ - function test_remove_relation_to() - { - $t = EE_Transaction::new_instance(); - $t->save(); - $r = EE_Registration::new_instance(array('TXN_ID' => $t->ID())); - $r->save(); - $t_from_r = $r->get_first_related('Transaction'); - $this->assertEquals($t, $t_from_r); - $rs_from_t = $t->get_many_related('Registration'); - $this->assertFalse(empty($rs_from_t)); - //remove the relation - $t_removed = $r->_remove_relation_to($t, 'Transaction'); - $this->assertEquals($t, $t_removed); - $t_from_r = $r->get_first_related('Transaction'); - $this->assertNull($t_from_r); - //and verify the cached reciprocal relation is updated too - $rs_from_t = $t->get_many_related('Registration'); - $this->assertTrue(empty($rs_from_t)); - } - - - /** - * @group 8686 - */ - function test_remove_relations() - { - $t = EE_Transaction::new_instance(); - $t->save(); - $r = EE_Registration::new_instance(array('TXN_ID' => $t->ID())); - $r->save(); - $t_from_r = $r->get_first_related('Transaction'); - $this->assertEquals($t, $t_from_r); - $rs_from_t = $t->get_many_related('Registration'); - $this->assertFalse(empty($rs_from_t)); - //ok now remove the relation between them - $r->_remove_relations('Transaction'); - $t_from_r = $r->get_first_related('Transaction'); - $this->assertNull($t_from_r); - //and verify the cached reciprocal relation is updated too - $rs_from_t = $t->get_many_related('Registration'); - $this->assertTrue(empty($rs_from_t)); - } - - - function test_count_related() - { - $e1 = EE_Event::new_instance(array('EVT_name' => '1')); - $e1->save(); - $this->assertNotEquals($e1->ID(), 0); - $e2 = EE_Event::new_instance(array('EVT_name' => '2')); - $e2->save(); - $this->assertNotEquals($e2->ID(), 0); - $e3 = EE_Event::new_instance(array('EVT_name' => '3')); - $e3->save(); - $v = EE_Venue::new_instance(array('VNU_name' => 'v1')); - $v->save(); - $v->_add_relation_to($e1, 'Event'); - $v->_add_relation_to($e2, 'Event'); - $this->assertEquals($v->count_related('Event'), 2); - } - - - function test_sum_related() - { - $t = EE_Transaction::new_instance(); - $t->save(); - $p1 = EE_Payment::new_instance(array('PAY_amount' => 1, 'TXN_ID' => $t->ID())); - $p1->save(); - $p2 = EE_Payment::new_instance(array('PAY_amount' => 2, 'TXN_ID' => $t->ID())); - $p2->save(); - $p1 = EE_Payment::new_instance(array('PAY_amount' => 1000, 'TXN_ID' => 0)); - $p1->save(); - $this->assertEquals($t->sum_related('Payment', array(), 'PAY_amount'), 3); - $t->_remove_relation_to($p2, 'Payment'); - $this->assertEquals($t->sum_related('Payment', array(), 'PAY_amount'), 1); - } - - - function test_cache_specifying_id() - { - $t = EE_Transaction::new_instance(); - $r = EE_Registration::new_instance(); - $t->cache('Registration', $r, 'r'); - $related_rs = $t->get_many_related('Registration'); - $this->assertArrayHasKey('r', $related_rs); - $this->assertArrayNotHasKey('r2', $related_rs); - $r_from_t = $t->get_one_from_cache('Registration'); - $this->assertEquals($r, $r_from_t); - $r2 = EE_Registration::new_instance(); - $t->cache('Registration', $r2, 'r2'); - $rs_from_t = $t->get_all_from_cache('Registration'); - $this->assertArrayContains($r, $rs_from_t); - $this->assertArrayContains($r2, $rs_from_t); - } - - - function test_update_cache_after_save() - { - $t = EE_Transaction::new_instance(); - $r = EE_Registration::new_instance(); - $t->cache('Registration', $r, 'monkey_code'); - $related_rs = $t->get_many_related('Registration'); - $this->assertArrayHasKey('monkey_code', $related_rs); - $r->save(); - $t->update_cache_after_object_save('Registration', $r, 'monkey_code'); - $related_rs = $t->get_many_related('Registration'); - $this->assertArrayHasKey($r->ID(), $related_rs); - $this->assertArrayNotHasKey('monkey_code', $related_rs); - } - - - function test_is_set() - { - $t = EE_Transaction::new_instance(); - $this->assertTrue($t->is_set('TXN_ID')); - $this->assertFalse($t->is_set('monkey_brains')); - } - - - /** - * tests that clearing all from a cache works as expected - */ - function test_clear_cache__all() - { - $t = EE_Transaction::new_instance(); - //test that clear cache for an item that ISN'T cached doesn't produce an error. - $response = $t->clear_cache('Registration'); - $this->assertNull($response); - $r = EE_Registration::new_instance(array('REG_code' => 'monkey1')); - $r2 = EE_Registration::new_instance(array('REG_code' => 'monkey2')); - $t->cache('Registration', $r); - $t->cache('Registration', $r2); - $rs_cached = $t->get_all_from_cache('Registration'); - $this->assertArrayContains($r, $rs_cached); - $this->assertArrayContains($r2, $rs_cached); - //ok but if we call clear cache again without specifying what we want, - //we should actually do nothing - $r_null = $t->clear_cache('Registration'); - $this->assertNull($r_null); - $this->assertArrayContains($r, $rs_cached); - $this->assertArrayContains($r2, $rs_cached); - //ok now clear everything - $success = $t->clear_cache('Registration', null, true); - $this->assertTrue($success); - $cached_regs = $t->get_all_from_cache('Registration'); - $this->assertEmpty($cached_regs); - } - - - /** - * test that after we've cached something, we can remove it specifically - * by only knowing the object - */ - function test_clear_cache__specific_object() - { - $t = EE_Transaction::new_instance(); - $r = EE_Registration::new_instance(array('REG_code' => 'monkey1')); - $r2 = EE_Registration::new_instance(array('REG_code' => 'monkey2')); - $t->cache('Registration', $r); - $t->cache('Registration', $r2); - $rs_cached = $t->get_all_from_cache('Registration'); - $this->assertArrayContains($r, $rs_cached); - $this->assertArrayContains($r2, $rs_cached); - $r_removed = $t->clear_cache('Registration', $r); - $this->assertEquals($r, $r_removed); - $this->assertArrayContains($r2, $t->get_all_from_cache('Registration')); - $this->assertArrayDoesNotContain($r, $t->get_all_from_cache('Registration')); - //now check if we clear the cache for an item that isn't in the cache, it returns null - $r3 = EE_Registration::new_instance(array('REG_code' => 'mystery monkey')); - $r_null = $t->clear_cache('Registration', $r3); - $this->assertNull($r_null); - } - - - /** - * test that after we've cached something using a specific index, - * we can remove it using a specific index - */ - function test_clear_cache__specific_index() - { - $t = EE_Transaction::new_instance(); - $r = EE_Registration::new_instance(array('REG_code' => 'monkey1')); - $r2 = EE_Registration::new_instance(array('REG_code' => 'monkey2')); - $t->cache('Registration', $r, 'monkey1'); - $t->cache('Registration', $r2, 'monkey2'); - $rs_cached = $t->get_all_from_cache('Registration'); - $this->assertArrayContains($r, $rs_cached); - $this->assertArrayContains($r2, $rs_cached); - $r_cached = $t->clear_cache('Registration', 'monkey1'); - $this->assertEquals($r, $r_cached); - $this->assertArrayDoesNotContain($r, $t->get_all_from_cache('Registration')); - //also check that if the index isn't set, we just return null - $r_null = $t->clear_cache('Registration', 'mystery monkey'); - $this->assertNull($r_null); - } - - - /** - * tests that clearing the cache on a belongsTo relation works - */ - function test_clear_cache__belongs_to() - { - $t = EE_Transaction::new_instance(array('TXN_total' => '99')); - $r = EE_Registration::new_instance(array('REG_code' => 'monkey1')); - $success = $r->cache('Transaction', $t); - $this->assertTrue($success); - $t_cached = $r->get_one_from_cache('Transaction'); - $this->assertEquals($t, $t_cached); - $t_removed = $r->clear_cache('Transaction'); - $this->assertEquals($t, $t_removed); - $t_null = $r->get_one_from_cache('Transaction'); - $this->assertNull($t_null); - } - - - function test_set_and_get_extra_meta() - { - $e = EE_Event::new_instance(); - $e->save(); - $e->update_extra_meta('monkey', 'baboon'); - $this->assertEquals('baboon', $e->get_extra_meta('monkey', true)); - $e->update_extra_meta('monkey', 'chimp'); - $this->assertEquals('chimp', $e->get_extra_meta('monkey', true)); - } - - - /** - * Created to attempt to reproduce a bug found when fixing - * https://events.codebasehq.com/projects/event-espresso/tickets/6373 - * - * @since 4.5.0 - */ - function test_set_primary_key_clear_relations() - { - /** @type EE_Event $event */ - $event = $this->factory->event->create(); - /** @type EE_Datetime $datetime */ - $datetime = $this->factory->datetime->create(); - $event->_add_relation_to($datetime, 'Datetime'); - $event->save(); - //now to reproduce we grab the event from the db. - $evt_from_db = EEM_Event::instance()->get_one_by_ID($event->ID()); - //clone event - $new_event = clone $evt_from_db; - //set pk to zero so we save new event and save. - $new_event->set('EVT_ID', 0); - $new_event->save(); - //now let's set the a clone of the dtt relation manually to the new event by cloning the dtt (which should work) - $orig_datetimes = $evt_from_db->get_many_related('Datetime'); - $this->assertEquals(1, count($orig_datetimes)); - /** @type EE_Datetime $new_datetime */ - $new_datetime = null; - foreach ($orig_datetimes as $orig_dtt) { - $new_datetime = clone $orig_dtt; - $new_datetime->set('DTT_ID', 0); - $new_datetime->set('EVT_ID', $new_event->ID()); - $new_datetime->save(); - } - $this->assertInstanceOf('EE_Datetime', $new_datetime); - //k now for the tests. first $new_event should NOT have the original datetime as a relation by default. When an object's id is set to 0 its relations should be cleared. - //get from db - /** @type EE_Event $test_cloned_event_from_db */ - $test_cloned_event_from_db = EEM_Event::instance()->get_one_by_ID($new_event->ID()); - $dtt_relation_on_clone = $test_cloned_event_from_db->first_datetime(); - $this->assertInstanceOf('EE_Datetime', $dtt_relation_on_clone); - $this->assertEquals($new_datetime->ID(), $dtt_relation_on_clone->ID()); - //test that the original event still has its relation to original EE_Datetime - /** @type EE_Event $orig_evt */ - $orig_evt = EEM_Event::instance()->get_one_by_ID($evt_from_db->ID()); - $dtt_relation_on_orig = $orig_evt->first_datetime(); - $this->assertInstanceOf('EE_Datetime', $dtt_relation_on_orig); - $this->assertEquals($dtt_relation_on_orig->ID(), $datetime->ID()); - } - - - /** - * @group 7151 - */ - public function test_in_entity_map() - { - $att = EE_Attendee::new_instance(array('ATT_fname' => 'mike')); - $this->assertFalse($att->in_entity_map()); - $att->save(); - $this->assertTrue($att->in_entity_map()); - EEM_Attendee::instance()->reset(); - //when we serialized it, it forgot if it was in the entity map or not - $this->assertFalse($att->in_entity_map()); - try { - //should throw an exception because we hate saving - //a model object that's not in the entity mapper - $att->save(); - } catch (EE_Error $e) { - $this->assertTrue(true); - } - EEM_Attendee::instance()->add_to_entity_map($att); - //we should all acknowledge it's in the entity map now - $this->assertTrue($att->in_entity_map()); - //we shouldn't complain at saving it now, it's in the entity map and so we're allowed - $att->save(); - //also, when we clone an item in the entity map, it shouldn't be considered in the entity map - $att2 = clone $att; - $this->assertFalse($att2->in_entity_map()); - } - - - /** - * @group 7151 - */ - public function test_refresh_from_db() - { - $att = EE_Attendee::new_instance(array('ATT_fname' => 'bob')); - try { - $att->refresh_from_db(); - } catch (EE_Error $e) { - $this->assertTrue(true); - } - $att->save(); - $att->refresh_from_db(); - EEM_Attendee::instance()->reset(); - try { - $att->refresh_from_db(); - } catch (EE_Error $e) { - $this->assertTrue(true); - } - } - - - public function test_delete_permanently_with_extra_meta() - { - $attendee = EE_Attendee::new_instance(array( - 'ATT_fname' => 'bob', - 'ATT_lname' => 'deleteme', - 'ATT_email' => 'ef@ew.dw', - )); - $attendee->save(); - $attendee->add_extra_meta('shouldnt_prevent_deletion', 'no_sirry'); - $this->assertEquals('no_sirry', $attendee->get_extra_meta('shouldnt_prevent_deletion', true)); - $attendee->delete_permanently(); - //if that didn't throw an error, we're good - } - - - /** - * @group 7358 - */ - public function test_get_raw() - { - $l2 = EE_Line_Item::new_instance(array()); - $this->assertTrue(1 == $l2->get_raw('LIN_quantity')); - $l2->save(); - $l2_from_db = EEM_Line_Item::reset()->get_one_by_ID($l2->ID()); - //double check its NULL in the DB - $qty_col_with_one_result = EEM_Line_Item::instance()->get_col(array(array('LIN_ID' => $l2->ID())), - 'LIN_quantity'); - $qty_col_in_db = reset($qty_col_with_one_result); - $this->assertTrue(1 == $qty_col_in_db); - //and now verify get_raw is returning that same value - $this->assertTrue(1 == $l2_from_db->get_raw('LIN_quantity')); - } - - - /** - * Tests when we set a field to INFINITY, it stays that way even after we re-fetch it from the db - * - * @group 7358 - */ - public function test_infinite_fields_stay_that_way() - { - /** @type EE_Datetime $datetime */ - $datetime = $this->new_model_obj_with_dependencies('Datetime'); - $datetime->set_reg_limit(EE_INF); - $datetime->save(); - /** @type EE_Datetime $datetime_from_db */ - $datetime_from_db = EEM_Datetime::reset()->get_one_by_ID($datetime->ID()); - $this->assertEquals($datetime->reg_limit(), $datetime_from_db->reg_limit()); - } - - - /** - * @since 4.6.12+ - */ - public function test_get_i18n_datetime() - { - //setup a datetime object with some known values for testing with. - $original_timezone = get_option('timezone_string'); - update_option('timezone_string', 'America/Toronto'); - $dateTimeZone = new DateTimeZone('America/Toronto'); - $currentTime = new DateTime("now", $dateTimeZone); - $futureTime = clone $currentTime; - $futureTime->add(new DateInterval('P2D')); - /** @type EE_Datetime $datetime */ - $datetime = $this->factory->datetime->create(array( - 'DTT_EVT_start' => $currentTime->format('Y-m-d H:i:s'), - 'DTT_EVT_end' => $futureTime->format('Y-m-d H:i:s'), - 'formats' => array('Y-m-d', 'H:i:s'), - )); - $this->assertInstanceOf('EE_Datetime', $datetime); - //test get_i18n_datetime - $this->assertEquals($currentTime->format('Y-m-d H:i:s'), $datetime->get_i18n_datetime('DTT_EVT_start')); - $this->assertEquals($futureTime->format('Y-m-d H:i:s'), $datetime->get_i18n_datetime('DTT_EVT_end')); - $id = $datetime->ID(); - //test when retrieved from the database. - EEM_Datetime::reset(); - $dbDatetime = EEM_Datetime::instance()->get_one_by_ID($id); - //set formats to match expected - $dbDatetime->set_date_format('Y-m-d'); - $dbDatetime->set_time_format('H:i:s'); - $this->assertEquals($currentTime->format('Y-m-d H:i:s'), $dbDatetime->get_i18n_datetime('DTT_EVT_start')); - $this->assertEquals($futureTime->format('Y-m-d H:i:s'), $dbDatetime->get_i18n_datetime('DTT_EVT_end')); - //restore timezone - update_option('timezone_string', $original_timezone); - } - - - /** - * @since 4.7.0 - * Note: in this test we're using EE_Datetime methods that utilize this method on - * EE_Base_Class - */ - public function test_set_date_time() - { - //setup a datetime object with some known values for testing with. - $original_timezone = get_option('timezone_string'); - update_option('timezone_string', 'America/Toronto'); - $dateTimeZone = new DateTimeZone('America/Toronto'); - $currentTime = new DateTime("now", $dateTimeZone); - $futureTime = clone $currentTime; - $futureTime->add(new DateInterval('P2D')); - /** @type EE_Datetime $datetime */ - $datetime = $this->factory->datetime->create( - array( - 'DTT_EVT_start' => $currentTime->format('Y-m-d H:i:s'), - 'DTT_EVT_end' => $futureTime->format('Y-m-d H:i:s'), - 'formats' => array('Y-m-d', 'H:i:s'), - ) - ); - $this->assertInstanceOf('EE_Datetime', $datetime); - //create a second datetime for polluting the formats on EE_Datetime_Field. - // Note: the purpose of this is to test that when th EE_Datetime_Field gets the new formats from this object, that they are NOT persisting to the original datetime created that has different formats (but utilizes the same EE_Date) - $this->factory->datetime->create( - array( - 'DTT_EVT_start' => $currentTime->format('d/m/Y g:i a'), - 'DTT_EVT_end' => $futureTime->format('d/m/Y g:i a'), - 'formats' => array('d/m/Y', 'g:i a'), - ) - ); - //test setting the time to 8am using a time string. - $datetime->set_start_time('8:00:00'); - $this->assertEquals($currentTime->setTime(8, 0, 0)->format('Y-m-d H:i:s'), $datetime->get('DTT_EVT_start')); - //test setting the time to 11pm using a date object - $currentTime->setTime(23, 0, 0); - $datetime->set_start_time($currentTime); - $this->assertEquals($currentTime->format('Y-m-d H:i:s'), $datetime->get('DTT_EVT_start')); - //test setting the date to 12-31-2012 on start date using a date string. - $currentTime->setDate('2012', '12', '31'); - $datetime->set_start_date('2012-12-31'); - $this->assertEquals($currentTime->format('Y-m-d H:i:s'), $datetime->get('DTT_EVT_start')); - //test setting the date to 12-15 using a date object. - $currentTime->setDate('2012', '12', '15'); - $datetime->set_start_date($currentTime); - $this->assertEquals($currentTime->format('Y-m-d H:i:s'), $datetime->get('DTT_EVT_start')); - //reset timezone_string back to original - update_option('timezone_string', $original_timezone); - } - - - /** - * @since 4.6.x - */ - public function test_next_x() - { - //create 5 events for testing with. - $events = $this->factory->event->create_many(5); - //grab the first event in the list as the reference - $event = reset($events); - $this->assertInstanceOf('EE_Event', $event); - //test method retrieving object - $next_events = $event->next_x('EVT_ID', 2); - //verify we have two returned. - $this->assertEquals(2, count($next_events)); - //loop through and verify the events returned are correct. - $pointer = 1; - foreach ($next_events as $next_event) { - $this->assertInstanceOf('EE_Event', $next_event); - $this->assertEquals($event->ID() + $pointer, $next_event->ID()); - $pointer++; - } - //test retrieving just ids - $next_events = $event->next_x('EVT_ID', 2, array(), 'EVT_ID'); - //verify we have two returned - $this->assertEquals(2, count($next_events)); - //loop through and verify the IDS returned are correct. - $pointer = 1; - foreach ($next_events as $next_event) { - $this->assertTrue(array_key_exists('EVT_ID', $next_event)); - $this->assertEquals($event->ID() + $pointer, $next_event['EVT_ID']); - $pointer++; - } - } - - - /** - * @since 4.6.x - */ - public function test_previous_x() - { - //create 5 events for testing with. - $events = $this->factory->event->create_many(5); - //grab the last event in the list as the reference - $event = end($events); - $this->assertInstanceOf('EE_Event', $event); - //test method retrieving object - $previous_events = $event->previous_x('EVT_ID', 2); - //verify we have two returned. - $this->assertEquals(2, count($previous_events)); - //loop through and verify the events returned are correct. - $pointer = 1; - foreach ($previous_events as $next_event) { - $this->assertInstanceOf('EE_Event', $next_event); - $this->assertEquals($event->ID() - $pointer, $next_event->ID()); - $pointer++; - } - //test retrieving just ids - $previous_events = $event->previous_x('EVT_ID', 2, array(), 'EVT_ID'); - //verify we have two returned - $this->assertEquals(2, count($previous_events)); - //loop through and verify the IDS returned are correct. - $pointer = 1; - foreach ($previous_events as $next_event) { - $this->assertTrue(array_key_exists('EVT_ID', $next_event)); - $this->assertEquals($event->ID() - $pointer, $next_event['EVT_ID']); - $pointer++; - } - } - - - /** - * @since 4.6.x - */ - public function test_next() - { - //create 5 events for testing with. - $events = $this->factory->event->create_many(5); - //grab the first event in the list as the reference - $event = reset($events); - $this->assertInstanceOf('EE_Event', $event); - //test method retrieving object - $next_event = $event->next('EVT_ID'); - //verify we have an event returned and that its the right one in sequence. - $this->assertInstanceOf('EE_Event', $next_event); - $this->assertEquals($event->ID() + 1, $next_event->ID()); - //test retrieving just id - $next_event = $event->next('EVT_ID', array(), 'EVT_ID'); - //verify the returned array has the right key and value. - $this->assertTrue(is_array($next_event)); - $this->assertTrue(array_key_exists('EVT_ID', $next_event)); - $this->assertEquals($event->ID() + 1, $next_event['EVT_ID']); - } - - - /** - * @since 4.6.x - */ - public function test_previous() - { - //create 5 events for testing with. - $events = $this->factory->event->create_many(5); - //grab the last event in the list as the reference - $event = end($events); - $this->assertInstanceOf('EE_Event', $event); - //test method retrieving object - $previous_event = $event->previous('EVT_ID'); - //verify we have an event returned and that its the right one in sequence. - $this->assertInstanceOf('EE_Event', $previous_event); - $this->assertEquals($event->ID() - 1, $previous_event->ID()); - //test retrieving just id - $previous_event = $event->previous('EVT_ID', array(), 'EVT_ID'); - //verify the returned array has the right key and value. - $this->assertTrue(is_array($previous_event)); - $this->assertTrue(array_key_exists('EVT_ID', $previous_event)); - $this->assertEquals($event->ID() - 1, $previous_event['EVT_ID']); - } - - - /** - * @group github-102 - * @group 8589 - */ - public function test_get__serialized_data__once() - { - $log_message = array( - 'key1' => 'value1', - 'key2' => 'value2', - ); - $log = EE_Change_Log::new_instance(); - $log->set('LOG_message', $log_message); - $log->save(); - //verify that when we get its LOG_message its still serialized - $this->assertTrue(is_array($log->get('LOG_message'))); - $this->assertEquals($log_message, $log->get('LOG_message')); - //now when we get it from the DB, and get its LOG_message, its still serialized - $log_id = $log->ID(); - EEM_Change_Log::reset(); - unset($log); - $log_from_db = EEM_Change_Log::instance()->get_one_by_ID($log_id); - $this->assertTrue(is_array($log_from_db->get('LOG_message'))); - $this->assertEquals($log_message, $log_from_db->get('LOG_message')); - } - - - /** - * @group github-102 - * @group 8589 - */ - public function test_get__serialized_data__twice() - { - $log_message = serialize(array( - 'key1' => 'value1', - 'key2' => 'value2', - )); - $log = EE_Change_Log::new_instance(); - $log->set('LOG_message', $log_message); - $log->save(); - //verify that when we get its LOG_message its still serialized - $this->assertTrue(is_array($log->get('LOG_message'))); - $this->assertEquals(unserialize($log_message), $log->get('LOG_message')); - //now when we get it from the DB, and get its LOG_message, its still serialized - $log_id = $log->ID(); - EEM_Change_Log::reset(); - unset($log); - $log_from_db = EEM_Change_Log::instance()->get_one_by_ID($log_id); - $this->assertTrue(is_array($log_from_db->get('LOG_message'))); - $this->assertEquals(unserialize($log_message), $log_from_db->get('LOG_message')); - } - - - /** - * @group 8686 - */ - public function test_delete__remove_from_related_items_in_entity_mapper() - { - $p = $this->new_model_obj_with_dependencies('Payment'); - $r = $this->new_model_obj_with_dependencies('Registration'); - $p->_add_relation_to($r, 'Registration'); - $reg_payments = $p->registration_payments(); - $this->assertFalse(empty($reg_payments)); - //now delete the relation entry - foreach ($p->registration_payments() as $registration_payment) { - if ($registration_payment instanceof EE_Registration_Payment) { - $this->assertEquals(1, $registration_payment->delete()); - } - } - //now there should eb no more registration payments on that payment right? - $reg_payments = $p->registration_payments(); - $this->assertTrue(empty($reg_payments)); - } - - - /** - * @group 8686 - */ - public function test_remove_relation_to__reciprocal() - { - $p = $this->new_model_obj_with_dependencies('Payment'); - $r = $this->new_model_obj_with_dependencies('Registration'); - $p->_add_relation_to($r, 'Registration'); - $regs_on_p = $p->get_many_related('Registration'); - $pays_on_r = $r->get_many_related('Payment'); - $this->assertFalse(empty($regs_on_p)); - $this->assertFalse(empty($pays_on_r)); - //now remove the relations - foreach ($p->get_many_related('Registration') as $registration) { - if ($registration instanceof EE_Registration) { - $this->assertEquals($registration, $p->_remove_relation_to($registration, 'Registration')); - } - } - //now there shoudl eb no more relations between those two right? - $regs_on_p = $p->get_many_related('Registration'); - $pays_on_r = $r->get_many_related('Payment'); - $this->assertTrue(empty($regs_on_p)); - $this->assertTrue(empty($pays_on_r)); - } - - /** - * Tests that if you create a model object and immediately change its timezone, the related model - * objects timezones should be changed too. But currently that isn't the case. - * - * @group 10751 - * @group 10905 - */ - public function test_automatically_set_timezone_on_related_model_obj__same_request() - { - //this is basically taken from https://github.com/eventespresso/event-espresso-core/blob/master/docs/F--Datetime-System/dates-times-timezones-in-models.md - $dtt = $this->new_model_obj_with_dependencies('Datetime'); - $event = EEM_Event::instance()->get_one_by_ID($dtt->get('EVT_ID')); - $event->set_timezone('Europe/London'); - $dtt = $event->get_first_related('Datetime'); - //first check we haven't accidentally changed the event's timezone - $this->assertEquals('Europe/London', $event->get_timezone()); - //then verify we successfully swapped the datetime's timezone - $this->assertEquals('Europe/London', $dtt->get_timezone()); - } - - - /** - * Verifies that when we set the timezone on a model object, related objects adopt that same timezone - * - * @group 10905 - */ - public function setTimezone() - { - $t = $this->new_typical_transaction(); - $datetime = EEM_Datetime::instance()->get_one(array(array('EVT_ID' => $t->primary_registration()->event_ID()))); - //set the timezone on the datetime, which should also set it on the ticket - $datetime->set_timezone('Europe/London'); - $ticket = $datetime->get_first_related('Ticket'); - $this->assertEquals('Europe/London', $ticket->get_timezone()); - - //now verify that if we change the timezone on the datetime, the ticket will also get changed - $datetime->set_timezone('America/New_York'); - $ticket = $datetime->get_first_related('Ticket'); - $this->assertEquals('America/New_York', $ticket->get_timezone()); - - } - - - /** - * Tests that if you save some model objects, and during a subsequent request change the timezone - * of one, its related model objects timezones will also be changed. - * This could be considered the same as E - * E_Base_Class_Test::test_automatically_set_timezone_on_related_model_obj__same_request - * except this one asserts setting the event's timezone changes the datetime's timezone when done - * across multiple requests. - * - * @group 10751 - */ - public function test_automatically_set_timezone_on_related_model_obj__separate_requests() - { - //this is basically taken from https://github.com/eventespresso/event-espresso-core/blob/master/docs/F--Datetime-System/dates-times-timezones-in-models.md - $dtt = $this->new_model_obj_with_dependencies('Datetime'); - //simulate a new request: forgot about these model objects from the entity map - //so we'll fetch them newly from the database after resetting their models - EEM_Datetime::reset(); - EEM_Event::reset(); - $event = EEM_Event::instance()->get_one_by_ID($dtt->get('EVT_ID')); - $event->set_timezone('Europe/London'); - $dtt = $event->get_first_related('Datetime'); - //first check we haven't accidentally changed the event's timezone - $this->assertEquals('Europe/London', $event->get_timezone()); - //then verify we successfully swapped the datetime's timezone - $this->assertEquals('Europe/London', $dtt->get_timezone()); - } - - - /** - * Tests that the f() function correctly escapes the value for display in a form input's value. - * - * @group 11195 - */ - public function testF() - { - $t = $this->new_model_obj_with_dependencies( - 'Ticket', - array( - 'TKT_description' => '"haha I echo this outside a form!', - ) - ); - ob_start(); - $t->f('TKT_description'); - $output = ob_get_clean(); - $this->assertEquals( - '"</textarea>haha I echo this outside a form!', - $output - ); - } - - - /** - * Tests if we prepare a model field with f(), then put in a form input, - * and the browser does it usual converting of HTML entities into what they represent - * when the form is submitted, that we end up with the same content that we started with. - * - * @group 11195 - */ - public function testFThenSetRoundTrip() - { - $original_value = 'my bold text "with quotes!" and "html entities" like'; - $t = $this->new_model_obj_with_dependencies( - 'Ticket', - array( - 'TKT_description' => $original_value, - ) - ); - $value_in_form = $t->get_pretty('TKT_description', 'form_input'); - //when it's rendered in the browser, they decode HTML entities. - // and the DECODED HTML entities get submitted in the form data - $submitted_value = html_entity_decode($value_in_form); - $t2 = EE_Ticket::new_instance( - array( - 'TKT_description' => $submitted_value, - ) - ); - $this->assertEquals( - $original_value, - $t2->get('TKT_description') - ); - } - - - /** - * @group 11344 - * @throws EE_Error - * @throws InvalidArgumentException - * @throws ReflectionException - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException - * @throws \PHPUnit\Framework\Exception - */ - public function testGetDateTimeObject() - { - //use EE_Mock (which simulates EE_Datetime) for tests - /** @var EE_Mock $ee_mock */ - $ee_mock = EE_Mock::new_instance(); - - //verify we get a DateTime object when requesting one - $this->assertInstanceOf('DateTime', $ee_mock->get_DateTime_object('MCK_datetime')); - - //verify we always get a different instance of datetime from what is stored internally when retrieving. - $this->assertNotEquals( - spl_object_hash($ee_mock->internalDateTimeObject('MCK_datetime')), - spl_object_hash($ee_mock->get_DateTime_object('MCK_datetime')) - ); - } - - - /** - * @group 11344 - * @throws EE_Error - * @throws InvalidArgumentException - * @throws ReflectionException - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException - */ - public function testClone() - { - /** @var EE_Mock $ee_mock */ - $ee_mock = EE_Mock::new_instance(); - $original_datetime = $ee_mock->internalDateTimeObject('MCK_datetime'); - - //clone our EE_Datetime and verify the DateTime for the same field is also a new instance. - $new_ee_datetime = clone $ee_mock; - - $this->assertEquals( - spl_object_hash($ee_mock->internalDateTimeObject('MCK_datetime')), - spl_object_hash($original_datetime) - ); - $this->assertNotEquals( - spl_object_hash($ee_mock->internalDateTimeObject('MCK_datetime')), - spl_object_hash($new_ee_datetime->internalDateTimeObject('MCK_datetime')) - ); - } -} diff --git a/tests/testcases/core/db_classes/EE_CPT_Base_Test.php b/tests/testcases/core/db_classes/EE_CPT_Base_Test.php deleted file mode 100644 index 89dc3ebc26f..00000000000 --- a/tests/testcases/core/db_classes/EE_CPT_Base_Test.php +++ /dev/null @@ -1,141 +0,0 @@ -'e1')); - $this->assertEquals('espresso_events',$e->post_type()); - $e->save(); - $this->assertEquals('espresso_events',$e->post_type()); - - $a = EE_Attendee::new_instance( array( 'ATT_fname' => 'mr', 'ATT_lname' => 'perfect' ) ); - $this->assertEquals('espresso_attendees',$a->post_type()); - $a->save(); - $this->assertEquals('espresso_attendees',$a->post_type()); - } - - - public function test_parent(){ - $e = EE_Event::new_instance(array('parent'=>12)); - $this->assertEquals($e->parent(),12); - } - - - - /** - * @group 10851 - */ - public function testWpPostSavedModelObj() - { - /** @var EE_Event $e */ - $e = $this->new_model_obj_with_dependencies('Event'); - $post = $e->wp_post(); - $this->assertEquals( - $e->ID(), - $post->ID - ); - $this->assertEquals( - $e->description(), - $post->post_content - ); - $this->assertEquals( - $e->get_datetime('EVT_created','Y-m-d', 'H:i:s'), - $post->post_date - ); - } - - - /** - * @group 10851 - */ - public function testWpPostUnsavedModelObj() - { - /** @var EE_Event $e */ - $e = $this->new_model_obj_with_dependencies('Event',null,false); - $post = $e->wp_post(); - $this->assertEquals( - $e->ID(), - $post->ID - ); - $this->assertEquals( - $e->description(), - $post->post_content - ); - $this->assertEquals( - $e->get_datetime('EVT_created','Y-m-d', 'H:i:s'), - $post->post_date - ); - } - - - /** - * Creates two events: one with registrations, the other without. - * Verify that if we loop over them and render their pretty content (which renders shortcodes) - * we don't accidentally cache the shortcode from one event to the other - * @group 10851 - */ - public function testGetPrettyCurrentPostRemainingTheSame() - { - $this->loadShortcodesManagerAndShortcodes(); - $transaction = $this->new_typical_transaction(); - $event_with_registrations = $transaction->primary_registration()->event(); - $event_with_registrations->set_description('[ESPRESSO_EVENT_ATTENDEES]'); - - $other_event = $this->new_model_obj_with_dependencies( - 'Event', - array( - 'EVT_desc' => '[ESPRESSO_EVENT_ATTENDEES]' - ) - ); - $dtt = $this->new_model_obj_with_dependencies('Datetime'); - $other_event->_add_relation_to( $dtt, 'Datetime' ); - $dtt->_add_relation_to( - $this->new_model_obj_with_dependencies('Ticket'), - 'Ticket' - ); - $event_with_reg_desc = $event_with_registrations->get_pretty('EVT_desc'); - $other_event_desc = $other_event->get_pretty('EVT_desc'); - - //the shortcode for each event should be different when rendered - $this->assertNotEquals( - $event_with_reg_desc, - $other_event_desc, - "'{$event_with_reg_desc}' should not be the same as '{$other_event_desc}'" - ); - } - - - /** - * @ticket 418 https://github.com/eventespresso/event-espresso-core/issues/418 - */ - public function testAddEventCategory() - { - $e = $this->new_model_obj_with_dependencies('Event'); - /** - * @var $e EE_Event - */ - $ee_term_taxonomy = $e->add_event_category( - 'Rebel Ships', - 'Events look at important Rebel Space Ships' - ); - $this->assertTrue($ee_term_taxonomy instanceof EE_Term_Taxonomy); - $this->assertNotEquals(0, $ee_term_taxonomy->get('term_count')); - } -} - -// End of file EE_CPT_Base_Test.php diff --git a/tests/testcases/core/db_classes/EE_Datetime_Test.php b/tests/testcases/core/db_classes/EE_Datetime_Test.php deleted file mode 100644 index cec818711a0..00000000000 --- a/tests/testcases/core/db_classes/EE_Datetime_Test.php +++ /dev/null @@ -1,233 +0,0 @@ -assertEquals($d->get('DTT_sold'),0); - $d->increase_sold(); - $this->assertEquals($d->get('DTT_sold'),1); - $d->increase_sold(2); - $this->assertEquals($d->get('DTT_sold'),3); - } - function test_decrease_sold(){ - $d = EE_Datetime::new_instance(array('DTT_sold'=>5)); - $d->decrease_sold(); - $this->assertEquals(4,$d->get('DTT_sold')); - $d->decrease_sold(2); - $this->assertEquals(2,$d->get('DTT_sold')); - } - /** - * because at one point EE_Datetime overrode ID() from its parent - * (not really for any good reason at the time of writing) - */ - function test_id(){ - $d = EE_Datetime::new_instance(); - $id = $d->save(); - $this->assertEquals($id,$d->ID()); - } - function test_start(){ - $start_time = new DateTime("now"); - $d = EE_Datetime::new_instance(array('DTT_EVT_start'=>$start_time->format('U'))); - $this->assertEquals($start_time->format('U'),$d->start()); - } - function test_end(){ - $end_time =new DateTime("now"); - $d = EE_Datetime::new_instance(array('DTT_EVT_end'=>$end_time->format('U'))); - $this->assertEquals($end_time->format('U'),$d->end()); - } - function test_reg_limit(){ - $d = EE_Datetime::new_instance(array('DTT_reg_limit'=>10)); - $this->assertEquals(10,$d->get('DTT_reg_limit')); - } - function test_sold(){ - $d = EE_Datetime::new_instance(array('DTT_sold'=>10)); - $this->assertEquals(10,$d->sold()); - } - function test_sold_out(){ - $d = EE_Datetime::new_instance(array('DTT_reg_limit'=>10)); - $this->assertFalse($d->sold_out()); - $d->set_sold(10); - $this->assertTrue($d->sold_out()); - $d->set('DTT_reg_limit',EE_INF); - $this->assertFalse($d->sold_out()); - } - function test_spaces_remaining(){ - $d = EE_Datetime::new_instance(array('DTT_reg_limit'=>20,'DTT_sold'=>5)); - $this->assertEquals(15,$d->spaces_remaining()); - } - function test_is_upcoming(){ - $d = EE_Datetime::new_instance(array('DTT_EVT_start'=>time() + 1000 )); - $this->assertTrue($d->is_upcoming()); - $d->set('DTT_EVT_start',time() - 1000 ); - $this->assertFalse($d->is_upcoming()); - } - function test_is_active(){ - $d = EE_Datetime::new_instance(array('DTT_EVT_start'=>time() - 1000, 'DTT_EVT_end'=>time() + 1000)); - $this->assertTrue($d->is_active()); - $d->set('DTT_EVT_start',time() + 500); - $this->assertFalse($d->is_active()); - } - function test_is_expired(){ - $d = EE_Datetime::new_instance(array('DTT_EVT_end'=>time() - 1000)); - $this->assertTrue($d->is_expired()); - $d->set('DTT_EVT_end',time() + 1000); - $this->assertFalse($d->is_expired()); - } - function test_get_dtt_display_name(){ - //test using actual dates because now could result in different results depending on what time of day it is - $base_date = date_create_from_format( 'Y-m-d H:i:s', '2015-01-01 00:00:00' ); - $testing_date = clone $base_date; - - //setup datetime with different months for start and end dates. - $testing_date->add( new DateInterval( 'P1M' ) ); - $d = EE_Datetime::new_instance(array('DTT_name'=>'monkey time', 'DTT_EVT_start'=>$base_date->format('U'), 'DTT_EVT_end'=>$testing_date->format('U'))); - $d->set_date_format( 'Y-m-d' ); - $d->set_time_format( 'h:i a' ); - $this->assertEquals( $base_date->format('M j\, Y g:i a') . ' - ' . $testing_date->format('M j\, Y g:i a'),$d->get_dtt_display_name()); - $this->assertEquals('monkey time',$d->get_dtt_display_name(true)); - - //setup datetime with start date and end date with same month but different days. - $testing_date->sub( new DateInterval( 'P15D' ) ); - $d = EE_Datetime::new_instance(array('DTT_name'=>'monkey time', 'DTT_EVT_start'=>$base_date->format('U'), 'DTT_EVT_end'=>$testing_date->format('U'))); - $d->set_date_format( 'Y-m-d' ); - $d->set_time_format( 'h:i a' ); - $this->assertEquals( $base_date->format( 'M j\, g:i a') . ' - ' . $testing_date->format( 'M j\, g:i a Y' ), $d->get_dtt_display_name() ); - - //setup datetime with start date and end date the same day but different times. - $testing_date = clone $base_date; - $testing_date->add( new DateInterval( 'PT1H' ) ); - $d = EE_Datetime::new_instance(array('DTT_name'=>'monkey time', 'DTT_EVT_start'=>$base_date->format('U'), 'DTT_EVT_end'=>$testing_date->format('U'))); - $d->set_date_format( 'Y-m-d' ); - $d->set_time_format( 'h:i a' ); - $this->assertEquals( $base_date->format( 'F j\, Y' ) . ' @ ' . $base_date->format( 'g:i a') . ' - ' . $testing_date->format( 'g:i a' ), $d->get_dtt_display_name() ); - } - - - - - /** - * This tests the ticket_types_available_for_purchase method. - * @since 4.6.0 - */ - public function test_ticket_types_available_for_purchase() { - //@todo remove once test fixed. - $this->markTestSkipped( - 'See https://events.codebasehq.com/projects/event-espresso/tickets/9635' - );/**/ - //setup some dates we'll use for testing with. - $timezone = new DateTimeZone( 'America/Toronto' ); - $upcoming_start_date = new DateTime( "now +1day", $timezone ); - $past_start_date = new DateTime( "now -2days", $timezone ); - $upcoming_end_date = new DateTime( "now +2days", $timezone ); - $current = new DateTime( "now", $timezone ); - $formats = array( 'Y-d-m', 'h:i a' ); - $full_format = implode( ' ', $formats ); - - //create some tickets - $tickets = array( - 'expired_ticket' => array( 'TKT_start_date' => $past_start_date->format($full_format), 'TKT_end_date' => $past_start_date->format($full_format), 'timezone' => 'America/Toronto', 'formats' =>$formats ), - 'upcoming_ticket' => array( 'TKT_start_date' => $past_start_date->format( $full_format ), 'TKT_end_date' => $upcoming_start_date->format( $full_format ), 'timezone' => 'America/Toronto', 'formats' => $formats ) - ); - - $datetimes = array( - 'expired_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $past_start_date->format( $full_format ), 'DTT_EVT_end' => $past_start_date->format( $full_format), 'timezone' => 'America/Toronto', 'formats' => $formats ) ), - 'upcoming_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $upcoming_start_date->format( $full_format ), 'DTT_EVT_end' => $upcoming_end_date->format( $full_format), 'timezone' => 'America/Toronto', 'formats' => $formats ) ), - 'active_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $current->format( $full_format ), 'DTT_EVT_end' => $upcoming_end_date->format( $full_format), 'timezone' => 'America/Toronto', 'formats' => $formats ) ), - 'sold_out_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $upcoming_start_date->format( $full_format ), 'DTT_EVT_end' => $upcoming_start_date->format( $full_format), 'DTT_reg_limit' => 10, 'DTT_sold' => 10, 'timezone' => 'America/Toronto', 'formats' => $formats ) ) - ); - - //assign tickets to all datetimes - foreach ( $datetimes as $datetime ) { - foreach( $tickets as $ticket_args ) { - $tkt = $this->factory->ticket->create ( $ticket_args ); - $datetime->_add_relation_to( $tkt, 'Ticket' ); - $datetime->save(); - } - } - - //okay NOW we have some objects for testing with. - - //test expired_datetime - $this->assertEmpty( $datetimes['expired_datetime']->ticket_types_available_for_purchase() ); - - //test upcoming datetime - $tickets = $datetimes['upcoming_datetime']->ticket_types_available_for_purchase(); - $this->assertEquals( 1, count( $tickets ) ); - $this->assertInstanceOf( 'EE_Ticket', reset( $tickets ) ); - - //test active datetime - $tickets = $datetimes['active_datetime']->ticket_types_available_for_purchase(); - $this->assertEquals( 1, count( $tickets ) ); - $this->assertInstanceOf( 'EE_Ticket', reset( $tickets ) ); - - //test sold out datetime - $this->assertEmpty( $datetimes['sold_out_datetime']->ticket_types_available_for_purchase() ); - } - - - - /** - * @since 4.6.x - */ - public function test_time_range() { - //setup a datetime for testing - $start_date = new DateTime( 'now' ); - $end_date = new DateTime( 'now + 3 hours' ); - $datetime = $this->factory->datetime->create( - array( - 'DTT_EVT_start' => $start_date->format( 'Y-m-d H:i:s' ), - 'DTT_EVT_end' => $end_date->format( 'Y-m-d H:i:s' ), - 'timezone' => 'UTC', 'formats' => array( 'Y-m-d', 'H:i:s' ) - ) - ); - - //assert we have a datetime - $this->assertInstanceOf( 'EE_Datetime', $datetime ); - - //verify that the expected time format is generated. - $this->assertEquals( $start_date->format( 'H:i:s' ) . ' - ' . $end_date->format( 'H:i:s' ), $datetime->time_range() ); - } - - - - /** - * @group 8861 - */ - public function test_tickets_remaining() { - $this->loadTestScenarios(); - $scenarios = $this->scenarios->get_scenarios_by_type( 'datetime' ); - foreach ( $scenarios as $scenario ) { - /* @type EE_Datetime $datetime */ - $datetime = $scenario->get_scenario_object(); - $datetime_id_to_tickets_map = $scenario->get_expected( 'datetime_id_to_tickets_map' ); - if ( isset( $datetime_id_to_tickets_map[ $datetime->ID() ] ) ) { - $tickets_remaining = $datetime->tickets_remaining(); - //echo "\n tickets_remaining: " . $tickets_remaining; - $tickets_expected = $datetime_id_to_tickets_map[ $datetime->ID() ]; - //echo "\n tickets_expected: " . $tickets_expected; - $this->assertEquals( $tickets_expected, $tickets_remaining ); - } - } - } - - -} - -// End of file EE_Datetime_Test.php -// Location: tests/testcases/core/db_classes/EE_Datetime_Test.php diff --git a/tests/testcases/core/db_classes/EE_Event_Test.php b/tests/testcases/core/db_classes/EE_Event_Test.php deleted file mode 100644 index d15f88881a7..00000000000 --- a/tests/testcases/core/db_classes/EE_Event_Test.php +++ /dev/null @@ -1,593 +0,0 @@ - 'power1')); - $e->save(); - $d = EE_Datetime::new_instance(array('EVT_ID' => $e->ID())); - $d->save(); - $primary_datetime = $e->primary_datetime(); - $this->assertEquals($d, $primary_datetime); - } - - - - public function test_datetimes_ordered() - { - $e = EE_Event::new_instance(array('EVT_name' => 'power1')); - $e->save(); - $d_exp = EE_Datetime::new_instance( - array( - 'EVT_ID' => $e->ID(), - 'DTT_EVT_start' => time() - 10, - 'DTT_EVT_end' => time() - 5, - ) - ); - $d_exp->save(); - $d_del = EE_Datetime::new_instance( - array( - 'EVT_ID' => $e->ID(), - 'DTT_EVT_start' => time() - 5, - 'DTT_EVT_end' => time() + 5, - 'DTT_deleted' => true, - ) - ); - $d_del->save(); - $d_ok = EE_Datetime::new_instance( - array( - 'EVT_ID' => $e->ID(), - 'DTT_EVT_start' => time() - 1, - 'DTT_EVT_end' => time() + 5, - ) - ); - $d_ok->save(); - $ds = $e->datetimes_ordered(); - $this->assertArrayContains($d_exp, $ds); - //$this->assertArrayDoesNotContain($d_del,$ds); @todo: bug, this assert actually fails because we have deactivated default where params - $this->assertArrayContains($d_ok, $ds); - //do it so it hides expired - $ds = $e->datetimes_ordered(false); - $this->assertArrayDoesNotContain($d_exp, $ds); -// $this->assertArrayDoesNotContain($d_del, $ds); @todo: bug, this assert actually fails because we have deactivated - $this->assertArrayContains($d_ok, $ds); - //do it so it hides expired but shows deleted - $ds = $e->datetimes_ordered(false, true); - $this->assertArrayDoesNotContain($d_exp, $ds); - $this->assertArrayContains($d_del, $ds); - $this->assertArrayContains($d_ok, $ds); - //do it so it shows the deleted one - $ds = $e->datetimes_ordered(true, true); - $this->assertArrayContains($d_exp, $ds); - $this->assertArrayContains($d_del, $ds); - $this->assertArrayContains($d_ok, $ds); - //double-check the ordering. - $first_d = array_shift($ds); - $this->assertEquals($d_exp, $first_d); - $second_d = array_shift($ds); - $this->assertEquals($d_del, $second_d); - $third_d = array_shift($ds); - $this->assertEquals($d_ok, $third_d); - } - - - - public function test_active_status() - { - /** @type EE_Event $e */ - $e = EE_Event::new_instance(array('status' => 'publish')); - $e->save(); - //echo "\n\n create Ticket"; - $t = EE_Ticket::new_instance( - array( - 'TKT_start_date' => time() - 100, - 'TKT_end_date' => time() + 50, - 'TKT_qty' => 100, - 'TKT_sold' => 0, - ) - ); - $t->save(); - $d_now = EE_Datetime::new_instance( - array( - 'EVT_ID' => $e->ID(), - 'DTT_EVT_start' => time() - 100, - 'DTT_EVT_end' => time() + 50, - ) - ); - $d_now->_add_relation_to($t, 'Ticket'); - $d_now->save(); - $d_exp = EE_Datetime::new_instance( - array( - 'EVT_ID' => $e->ID(), - 'DTT_EVT_start' => time() - 10, - 'DTT_EVT_end' => time() - 5, - ) - ); - $d_exp->_add_relation_to($t, 'Ticket'); - $d_exp->save(); - $d_upcoming = EE_Datetime::new_instance( - array( - 'EVT_ID' => $e->ID(), - 'DTT_EVT_start' => time() + 10, - 'DTT_EVT_end' => time() + 15, - ) - ); - $d_upcoming->_add_relation_to($t, 'Ticket'); - $d_upcoming->save(); - // add tickets - $ticket_1 = $this->new_model_obj_with_dependencies( - 'Ticket', array('TKT_qty' => '10', 'TKT_sold' => '5', 'TKT_reserved' => '0') - ); - $d_now->_add_relation_to($ticket_1, 'Ticket'); - $ticket_2 = $this->new_model_obj_with_dependencies( - 'Ticket', array('TKT_qty' => '10', 'TKT_sold' => '5', 'TKT_reserved' => '0') - ); - $d_exp->_add_relation_to($ticket_2, 'Ticket'); - $ticket_3 = $this->new_model_obj_with_dependencies( - 'Ticket', array('TKT_qty' => '10', 'TKT_sold' => '5', 'TKT_reserved' => '0') - ); - $d_upcoming->_add_relation_to($ticket_3, 'Ticket'); - //test - $this->assertEquals(EE_Datetime::active, $e->get_active_status(true)); - $e->_remove_relation_to($d_now, 'Datetime'); - $this->assertEquals(EE_Datetime::upcoming, $e->get_active_status(true)); - $e->_remove_relation_to($d_upcoming, 'Datetime'); - $this->assertEquals(EE_Datetime::expired, $e->get_active_status(true)); - } - - - - public function test_get_number_of_tickets_sold() - { - $e = EE_Event::new_instance(); - $e->save(); - $d_now = EE_Datetime::new_instance( - array( - 'EVT_ID' => $e->ID(), - 'DTT_EVT_start' => time() - 100, - 'DTT_EVT_end' => time() - 50, - 'DTT_sold' => 5, - ) - ); - $d_now->save(); - $d_exp = EE_Datetime::new_instance( - array( - 'EVT_ID' => $e->ID(), - 'DTT_EVT_start' => time() - 10, - 'DTT_EVT_end' => time() - 5, - 'DTT_sold' => 15, - ) - ); - $d_exp->save(); - $this->assertEquals(20, $e->get_number_of_tickets_sold()); - $e->_remove_relation_to($d_now, 'Datetime'); - $this->assertEquals(15, $e->get_number_of_tickets_sold()); - } - - - - /** - * @since 4.8.0 - */ - public function test_total_available_spaces() - { - $this->loadTestScenarios(); - //grab test scenarios. - $scenarios = $this->scenarios->get_scenarios_by_type('event'); - foreach ($scenarios as $scenario) { - $expected = $scenario->get_expected('total_available_spaces'); - if ($expected) { - /** @type EE_Event $event */ - $event = $scenario->get_scenario_object(); - $calculator = new EventEspresso\core\domain\services\event\EventSpacesCalculator($event); - $this->assertEquals( - $expected, - $event->total_available_spaces(), - 'Testing ' . $scenario->name . ' for "total_available_spaces"' - ); - $this->assertEquals( - $expected, - $calculator->totalSpacesAvailable(), - 'Testing ' . $scenario->name . ' for "totalSpacesAvailable"' - ); - } - } - } - - - - /** - * @since 4.8.0 - */ - public function test_spaces_remaining_for_sale() - { - $this->loadTestScenarios(); - //grab test scenarios - $scenarios = $this->scenarios->get_scenarios_by_type('event'); - foreach ($scenarios as $scenario) { - if ($scenario->skip()) { - continue; - } - $expected = $scenario->get_expected('total_remaining_spaces'); - if ($expected !== false) { - /** @type EE_Event $event */ - $event = $scenario->get_scenario_object(); - $calculator = new EventEspresso\core\domain\services\event\EventSpacesCalculator($event); - $this->assertEquals( - $expected, - $event->spaces_remaining_for_sale(), - 'Testing ' . $scenario->name . ' for "total_remaining_spaces"' - ); - $this->assertEquals( - $expected, - $calculator->spacesRemaining(), - 'Testing ' . $scenario->name . ' for "total_remaining_spaces"' - ); - } - } - } - - - - /** - * @since 4.8.0 - */ - public function test_spaces_remaining_for_sale_for_Event_Scenario_H() - { - $this->loadTestScenarios(); - //grab test scenario - $scenario = $this->scenarios->get_scenario_by_name('Event Scenario H - Two Classes'); - // verify - if ( - ! $scenario instanceof EE_Test_Scenario - || ( - $scenario instanceof EE_Test_Scenario - && $scenario->name !== 'Event Scenario H - Two Classes' - ) - ) { - return; - } - /** @type EE_Event $event */ - $event = $scenario->get_scenario_object(); - $calculator = new EventEspresso\core\domain\services\event\EventSpacesCalculator($event); - $expected = $scenario->get_expected('total_remaining_spaces'); - if ($expected !== false) { - $this->assertEquals( - $expected, - $event->spaces_remaining_for_sale(), - 'Testing ' . $scenario->name - ); - $this->assertEquals( - $expected, - $calculator->spacesRemaining(), - 'Testing ' . $scenario->name . ' for "total_remaining_spaces"' - ); - } - $this->assertEquals( - EE_Datetime::upcoming, - $event->get_active_status(true), - $scenario->name . ' active_status after initial 6 ticket sales' - ); - // now sell 2 more tickets - $scenario->run_additional_logic(array('qty' => 2)); - $expected = $scenario->get_expected('total_remaining_spaces_4'); - $this->assertEquals( - $expected, - $event->spaces_remaining_for_sale(), - 'Testing ' . $scenario->name . ' after selling an additional 2 tickets' - ); - $this->assertEquals( - $expected, - $calculator->spacesRemaining(), - 'Testing ' . $scenario->name . ' for "total_remaining_spaces" after selling an additional 2 tickets' - ); - $this->assertEquals( - EE_Datetime::upcoming, - $event->get_active_status(true), - $scenario->name . ' active_status after an additional 2 ticket sales' - ); - // now sell the last 4 tickets - $scenario->run_additional_logic(array('qty' => 4)); - $expected = $scenario->get_expected('total_remaining_spaces_0'); - $this->assertEquals( - $expected, - $event->spaces_remaining_for_sale(), - 'Testing ' . $scenario->name . ' after selling the last 4 tickets' - ); - $this->assertEquals( - $expected, - $calculator->spacesRemaining(), - 'Testing ' . $scenario->name . ' for "total_remaining_spaces" after selling the last 4 tickets' - ); - $this->assertEquals( - EE_Datetime::sold_out, - $event->get_active_status(true), - $scenario->name . ' active_status after selling the last 4 tickets' - ); - } - - - - /** - * @since 4.8.0 - */ - public function test_spaces_remaining_for_sale_for_Event_Scenario_I() - { - $this->loadTestScenarios(); - //grab test scenario - $scenario = $this->scenarios->get_scenario_by_name('Event Scenario I - Four Tickets One Date'); - // verify - if ( - ! $scenario instanceof EE_Test_Scenario - || ( - $scenario instanceof EE_Test_Scenario - && $scenario->name !== 'Event Scenario I - Four Tickets One Date' - ) - ) { - return; - } - /** @type EE_Event $event */ - $event = $scenario->get_scenario_object(); - $calculator = new EventEspresso\core\domain\services\event\EventSpacesCalculator($event); - $expected = $scenario->get_expected('total_remaining_spaces'); - if ($expected !== false) { - $this->assertEquals( - $expected, - $event->spaces_remaining_for_sale(), - 'Testing ' . $scenario->name - ); - $this->assertEquals( - $expected, - $calculator->spacesRemaining(), - 'Testing ' . $scenario->name . ' for "total_remaining_spaces"' - ); - } - $this->assertEquals( - EE_Datetime::upcoming, - $event->get_active_status(true), - $scenario->name . ' active_status after initial setup' - ); - // now sell first batch of tickets - $scenario->run_additional_logic(array('tkt_id' => 1, 'qty' => 2)); - $scenario->run_additional_logic(array('tkt_id' => 2, 'qty' => 2)); - $expected = $scenario->get_expected('total_remaining_spaces_20'); - $this->assertEquals( - $expected, - $event->spaces_remaining_for_sale(), - 'Testing ' . $scenario->name . ' after selling first 4 tickets' - ); - $this->assertEquals( - $expected, - $calculator->spacesRemaining(), - 'Testing ' . $scenario->name . ' for "total_remaining_spaces" after selling first 4 tickets' - ); - $this->assertEquals( - EE_Datetime::upcoming, - $event->get_active_status(true), - $scenario->name . ' active_status after selling first 4 tickets' - ); - // now sell second batch of tickets - THIS IS WHEN IT USED TO SELL OUT - $scenario->run_additional_logic(array('tkt_id' => 1, 'qty' => 2)); - $scenario->run_additional_logic(array('tkt_id' => 3, 'qty' => 1)); - $scenario->run_additional_logic(array('tkt_id' => 4, 'qty' => 1)); - $expected = $scenario->get_expected('total_remaining_spaces_16'); - $this->assertEquals( - $expected, - $event->spaces_remaining_for_sale(), - 'Testing ' . $scenario->name . ' after selling 8 tickets' - ); - $this->assertEquals( - $expected, - $calculator->spacesRemaining(), - 'Testing ' . $scenario->name . ' for "total_remaining_spaces" after selling 8 tickets' - ); - $this->assertEquals( - EE_Datetime::upcoming, - $event->get_active_status(true), - $scenario->name . ' active_status after selling 8 tickets' - ); - // now sell third batch of tickets - $scenario->run_additional_logic(array('tkt_id' => 1, 'qty' => 1)); - $scenario->run_additional_logic(array('tkt_id' => 2, 'qty' => 1)); - $scenario->run_additional_logic(array('tkt_id' => 3, 'qty' => 2)); - $expected = $scenario->get_expected('total_remaining_spaces_12'); - $this->assertEquals( - $expected, - $event->spaces_remaining_for_sale(), - 'Testing ' . $scenario->name . ' after selling 12 tickets' - ); - $this->assertEquals( - $expected, - $calculator->spacesRemaining(), - 'Testing ' . $scenario->name . ' for "total_remaining_spaces" after selling 12 tickets' - ); - $this->assertEquals( - EE_Datetime::upcoming, - $event->get_active_status(true), - $scenario->name . ' active_status after selling 12 tickets' - ); - // and a fourth batch of tickets - $scenario->run_additional_logic(array('tkt_id' => 1, 'qty' => 1)); - $scenario->run_additional_logic(array('tkt_id' => 2, 'qty' => 1)); - $scenario->run_additional_logic(array('tkt_id' => 3, 'qty' => 1)); - $scenario->run_additional_logic(array('tkt_id' => 4, 'qty' => 1)); - $expected = $scenario->get_expected('total_remaining_spaces_8'); - $this->assertEquals( - $expected, - $event->spaces_remaining_for_sale(), - 'Testing ' . $scenario->name . ' after selling 16 tickets' - ); - $this->assertEquals( - $expected, - $calculator->spacesRemaining(), - 'Testing ' . $scenario->name . ' for "total_remaining_spaces" after selling 16 tickets' - ); - $this->assertEquals( - EE_Datetime::upcoming, - $event->get_active_status(true), - $scenario->name . ' active_status after selling 16 tickets' - ); - // and a fifth - $scenario->run_additional_logic(array('tkt_id' => 2, 'qty' => 2)); - $scenario->run_additional_logic(array('tkt_id' => 3, 'qty' => 1)); - $scenario->run_additional_logic(array('tkt_id' => 4, 'qty' => 1)); - $expected = $scenario->get_expected('total_remaining_spaces_4'); - $this->assertEquals( - $expected, - $event->spaces_remaining_for_sale(), - 'Testing ' . $scenario->name . ' after selling 20 tickets' - ); - $this->assertEquals( - $expected, - $calculator->spacesRemaining(), - 'Testing ' . $scenario->name . ' for "total_remaining_spaces" after selling 20 tickets' - ); - $this->assertEquals( - EE_Datetime::upcoming, - $event->get_active_status(true), - $scenario->name . ' active_status after selling 20 tickets' - ); - // last batch - $scenario->run_additional_logic(array('tkt_id' => 3, 'qty' => 1)); - $scenario->run_additional_logic(array('tkt_id' => 4, 'qty' => 3)); - $expected = $scenario->get_expected('total_remaining_spaces_0'); - $this->assertEquals( - $expected, - $event->spaces_remaining_for_sale(), - 'Testing ' . $scenario->name . ' after selling all 24 tickets' - ); - $this->assertEquals( - $expected, - $calculator->spacesRemaining(), - 'Testing ' . $scenario->name . ' for "total_remaining_spaces" after selling all 24 tickets' - ); - $this->assertEquals( - EE_Datetime::sold_out, - $event->get_active_status(true), - $scenario->name . ' active_status after selling all 24 tickets' - ); - } - - - /** - * @group sold_out_status_check - * @throws DomainException - * @throws EE_Error - * @throws \EventEspresso\core\exceptions\UnexpectedEntityException - */ - public function test_perform_sold_out_status_check() - { - $this->markTestSkipped('Temporarily skipped because of sporadic, unexplained fails. See https://events.codebasehq.com/projects/event-espresso/tickets/11394'); - $event = EE_Event::new_instance( - array( - 'status' => 'publish' - ) - ); - $event->save(); - $datetime = EE_Datetime::new_instance( - array( - 'EVT_ID' => $event->ID(), - 'DTT_EVT_start' => time() + WEEK_IN_SECONDS, - 'DTT_EVT_end' => time() + WEEK_IN_SECONDS + DAY_IN_SECONDS, - 'DTT_reg_limit' => 4, - 'DTT_sold' => 2, - ) - ); - $datetime->save(); - $ticket_A = EE_Ticket::new_instance( - array( - 'TKT_name' => 'Ticket A', - 'TKT_qty' => 4, - 'TKT_sold' => 2, - ) - ); - $ticket_A->save(); - $ticket_A->_add_relation_to($datetime, 'Datetime'); - $this->assertEquals('publish', $event->status()); - $this->assertEquals(EE_Datetime::upcoming, $event->get_active_status()); - $ticket_A->increase_sold(2); - $this->assertEquals('publish', $event->status()); - $this->assertEquals(EE_Datetime::upcoming, $event->get_active_status(true)); - // now perform sold out check - $sold_out = $event->perform_sold_out_status_check(); - $this->assertTrue($sold_out); - $this->assertEquals(EEM_Event::sold_out, $event->status()); - $this->assertEquals(EE_Datetime::sold_out, $event->get_active_status(true)); - } - - - /** - * @group sold_out_status_check - * @throws DomainException - * @throws EE_Error - * @throws \EventEspresso\core\exceptions\UnexpectedEntityException - */ - public function test_perform_sold_out_status_check_with_expired_ticket() - { - $event = EE_Event::new_instance( - array( - 'status' => 'publish' - ) - ); - $event->save(); - $datetime = EE_Datetime::new_instance( - array( - 'EVT_ID' => $event->ID(), - 'DTT_EVT_start' => time() + WEEK_IN_SECONDS, - 'DTT_EVT_end' => time() + WEEK_IN_SECONDS + DAY_IN_SECONDS, - 'DTT_reg_limit' => 4, - 'DTT_sold' => 2, - ) - ); - $datetime->save(); - // expired early bird ticket - $ticket_A = EE_Ticket::new_instance( - array( - 'TKT_name' => 'Ticket A', - 'TKT_start_date' => time() - MONTH_IN_SECONDS, - 'TKT_end_date' => time() - WEEK_IN_SECONDS, - 'TKT_qty' => 4, - 'TKT_sold' => 2, - ) - ); - $ticket_A->save(); - $ticket_A->_add_relation_to($datetime, 'Datetime'); - // regular on sale ticket - $ticket_B = EE_Ticket::new_instance( - array( - 'TKT_name' => 'Ticket B', - 'TKT_start_date' => time() - WEEK_IN_SECONDS, - 'TKT_end_date' => time() + WEEK_IN_SECONDS, - 'TKT_qty' => 4, - 'TKT_sold' => 0, - ) - ); - $ticket_B->save(); - $ticket_B->_add_relation_to($datetime, 'Datetime'); - $this->assertEquals('publish', $event->status()); - $this->assertEquals(EE_Datetime::upcoming, $event->get_active_status()); - $ticket_B->increase_sold(2); - $this->assertEquals('publish', $event->status()); - $this->assertEquals(EE_Datetime::upcoming, $event->get_active_status(true)); - // now perform sold out check - $sold_out = $event->perform_sold_out_status_check(); - $this->assertTrue($sold_out); - $this->assertEquals(EEM_Event::sold_out, $event->status()); - $this->assertEquals(EE_Datetime::sold_out, $event->get_active_status(true)); - } -} -// End of file EE_Event_Test.php -// Location: /tests/testcases/core/db_classes/EE_Event_Test.php diff --git a/tests/testcases/core/db_classes/EE_Import_Test.php b/tests/testcases/core/db_classes/EE_Import_Test.php deleted file mode 100644 index 7666efa4864..00000000000 --- a/tests/testcases/core/db_classes/EE_Import_Test.php +++ /dev/null @@ -1,549 +0,0 @@ -new_model_obj_with_dependencies('Event'); - $original_datetime1 = clone $this->new_model_obj_with_dependencies( 'Datetime', array( 'EVT_ID' => $original_event1->ID() ) ); - $original_ticket1 = clone $this->new_model_obj_with_dependencies( 'Ticket' ); - $original_datetime_ticket = clone $this->new_model_obj_with_dependencies( 'Datetime_Ticket', array( 'DTT_ID' => $original_datetime1->ID(), 'TKT_ID' => $original_ticket1->ID() ) ); - - - //now let's make some model objects that AREN'T in this database - //that could confuse the importer - $other_db_event = $this->new_model_obj_with_dependencies('Event', array(), false ); - $other_db_event_props = $other_db_event->model_field_array(); - $other_db_event_props[ 'EVT_ID' ] = $original_event1->ID(); - - $other_db_event2 = $this->new_model_obj_with_dependencies( 'Event', array(), false ); - $other_db_event2_props = $other_db_event2->model_field_array(); - $other_db_event2_props[ 'EVT_ID' ] = 1000; - - $other_db_datetime = $this->new_model_obj_with_dependencies( 'Datetime', array( 'EVT_ID' => $original_event1->ID() ), false ); - $other_db_datetime_props = $other_db_datetime->model_field_array(); - $other_db_datetime_props[ 'DTT_ID' ] = $original_datetime1->ID(); - - $other_db_ticket = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_ID' => $original_ticket1->ID() ), false ); - $other_db_ticket_props = $other_db_ticket->model_field_array(); - $other_db_ticket_props[ 'TKT_ID' ] = $original_ticket1->ID(); - - $other_db_datetime_ticket = EE_Datetime_Ticket::new_instance( array( 'DTT_ID' => $original_datetime1->ID(), 'TKT_ID' => $original_ticket1->ID() ), false ); - $other_db_datetime_ticket_props = $other_db_datetime_ticket->model_field_array(); - $other_db_datetime_ticket_props[ 'DTK_ID' ] = $original_datetime_ticket->ID(); - - $event_count = EEM_Event::instance()->count(); - $datetime_count = EEM_Datetime::instance()->count(); - $ticket_count = EEM_Ticket::instance()->count(); - $datetime_ticket_count = EEM_Datetime_Ticket::instance()->count(); - - - $csv_data_rows = array( - 'Event' => array( - $other_db_event_props, - $other_db_event2_props - ), - 'Datetime' => array( - $other_db_datetime_props - ), - 'Ticket' => array( - $other_db_ticket_props - ), - 'Datetime_Ticket' => array( - $other_db_datetime_ticket_props - ) - ); - - //ok give it a whirl... - $new_mappings = EE_Import::instance()->save_data_rows_to_db($csv_data_rows, true, array() ); - //what should have happened: - //we should have a mapping for each newly-inserted - //events... - $this->assertNotEmpty( $new_mappings ); - $this->assertArrayHasKey( 'Event', $new_mappings ); - $event1_mapping = $new_mappings[ 'Event' ][ $original_event1->ID() ]; - $this->assertNotEmpty( $event1_mapping ); - $this->assertNotEquals( $original_event1->ID(), $event1_mapping ); - $event2_mapping = $new_mappings[ 'Event' ][ 1000 ]; - $this->assertNotEmpty( $event2_mapping ); - $this->assertNotEquals( 1000, $event1_mapping ); - //newly inerted datetime... - $this->assertNotEmpty( $new_mappings ); - $this->assertArrayHasKey( 'Datetime', $new_mappings ); - $datetime1_mapping = $new_mappings[ 'Datetime' ][ $original_datetime1->ID() ]; - $this->assertNotEmpty( $datetime1_mapping ); - $this->assertNotEquals( $original_datetime1->ID(), $datetime1_mapping ); - //newly inserted ticket - $this->assertNotEmpty( $new_mappings ); - $this->assertArrayHasKey( 'Ticket', $new_mappings ); - $ticket1_mapping = $new_mappings[ 'Ticket' ][ $original_ticket1->ID() ]; - $this->assertNotEmpty( $ticket1_mapping ); - $this->assertNotEquals( $original_ticket1->ID(), $ticket1_mapping ); - //and newly inserted datetime-ticke... - $this->assertNotEmpty( $new_mappings ); - $this->assertArrayHasKey( 'Datetime_Ticket', $new_mappings ); - $datetime_ticket_mapping = $new_mappings[ 'Datetime_Ticket' ][ $original_datetime_ticket->ID() ]; - $this->assertNotEmpty( $datetime_ticket_mapping ); - $this->assertNotEquals( $original_datetime_ticket->ID(), $datetime_ticket_mapping ); - - - //we should have inserted 2 new events, 1 new datetime, 1 new ticket and 1 new relation - $this->assertEquals( $event_count + 2, EEM_Event::instance()->count() ); - $this->assertEquals( $datetime_count + 1, EEM_Datetime::instance()->count() ); - $this->assertEquals( $ticket_count + 1, EEM_Ticket::instance()->count() ); - $this->assertEquals( $datetime_ticket_count + 1, EEM_Datetime_Ticket::instance()->count() ); - //the newly inserted datetime shoudl have bene associated to the new event for $other_db_event_props - $inserted_datetime_from_other_db = EEM_Datetime::instance()->get_one_by_ID( $datetime1_mapping ); - $this->assertEquals( $event1_mapping, $inserted_datetime_from_other_db->get('EVT_ID') ); - //there shoudl be a newly inserted ticket - $inserted_ticket_from_other_db = EEM_Ticket::instance()->get_one_by_ID( $ticket1_mapping ); - $this->assertNotNull( $inserted_ticket_from_other_db ); - //the newly inserted datetime-ticket should hae been associated with the newly inserted datetime and ticket - $inserted_datetime_ticket_from_other_db = EEM_Datetime_Ticket::instance()->get_one_by_ID( $datetime_ticket_mapping ); - $this->assertEquals( $ticket1_mapping, $inserted_datetime_ticket_from_other_db->get( 'TKT_ID' ) ); - $this->assertEquals( $datetime1_mapping, $inserted_datetime_ticket_from_other_db->get( 'DTT_ID' ) ); - //the original event shouldn't be affected, nor should it have more than the original datetime on it - $updated_event1 = EEM_Event::instance()->refresh_entity_map_from_db( $original_event1->ID() ); - $this->assertEEModelObjectsEquals( $original_event1, $updated_event1 ); - //the original datetime shoudln't be affected, nor shoudl it have more than the original ticket associagted with it - $updated_datetime1 = EEM_Datetime::instance()->refresh_entity_map_from_db( $original_datetime1->ID() ); - $this->assertEEModelObjectsEquals( $original_datetime1, $updated_datetime1 ); - } - - /** - * test we dont insert conflicting data (especially term-taxonomies) - */ - public function test_save_data_array_to_db__from_other_site__avoid_inserting_conflicting_data() { - $term_taxonomy = $this->new_model_obj_with_dependencies( 'Term_Taxonomy', array( 'taxonomy' => 'category', 'description' => 'original term-taxonomy' ) ); - $this->assertEquals( 'original term-taxonomy', $term_taxonomy->get( 'description' ) ); - $term_taxonomy_from_other_db = $this->new_model_obj_with_dependencies( 'Term_Taxonomy', - array( - 'term_id' => $term_taxonomy->get('term_id'), - 'taxonomy' => 'category', - 'description' => 'in other db' ), false ); - $country_usa = EEM_Country::instance()->get_one_by_ID( 'US' ); - $this->assertEquals( false, $country_usa->get( 'CNT_is_EU' ) ); - - //have the contry be slightly modified in the exporting site - $country_usa_props = $country_usa->model_field_array(); - $country_usa_props[ 'CNT_is_EU' ] = true; - $csv_data_rows = array( - 'Term_Taxonomy' => array( - $term_taxonomy_from_other_db->model_field_array() - ), - 'Country' => array( - $country_usa_props - ) - ); - $term_taxonomy_count = EEM_Term_Taxonomy::instance()->count(); - $country_count = EEM_Country::instance()->count(); - - //ok give it a whirl (keep the term-taxonomy's "term_id" the same by having it map to itself, obviously super unlikely but helps testing) - EE_Import::instance()->save_data_rows_to_db($csv_data_rows, true, array( 'Term' => array( $term_taxonomy->get( 'term_id' ) => $term_taxonomy->get( 'term_id' ) ) ) ); - - $this->assertEmpty( EE_Import::instance()->get_total_update_errors() ); - $this->assertEmpty( EE_Import::instance()->get_total_inserts() ); - $this->assertEmpty( EE_Import::instance()->get_total_insert_errors() ); - $this->assertEquals( 2, EE_Import::instance()->get_total_updates() ); - //there shouldn't be any new term taxonomies or countries - $this->assertEquals( $term_taxonomy_count, EEM_Term_Taxonomy::instance()->count() ); - $this->assertEquals( $country_count, EEM_Country::instance()->count() ); - //however, they should be updated - $updated_term_taxonomy = EEM_Term_Taxonomy::instance()->refresh_entity_map_from_db( $term_taxonomy->ID() ); - $this->assertEquals( 'in other db', $updated_term_taxonomy->get( 'description' ) ); - $updated_country = EEM_Country::instance()->refresh_entity_map_from_db( $country_usa->ID() ); - $this->assertEquals( true, $updated_country->get( 'CNT_is_EU' ) ); - } - /** - * test if an INT fk doesn't exist -> set it to NULL! - * if a STRING fk exists -> leave it alone - */ - public function test_save_data_array_to_db__from_other_site__fks_that_dont_exist() { - //model object with foreign key that's an INT (should be set to 0 or NULL) - $att = $this->new_model_obj_with_dependencies( 'Attendee', array( 'STA_ID' => 99999, 'CNT_ISO' => '77' ), false ); - $att_props = $att->model_field_array(); - $att_props[ 'ATT_ID' ] = 123; - $csv_data = array( - 'Attendee' => array( - $att_props - ) - ); - $att_count = EEM_Attendee::instance()->count(); - $mappings = EE_Import::instance()->save_data_rows_to_db($csv_data, true, array() ); - $this->assertEquals( $att_count + 1, EEM_Attendee::instance()->count() ); - //the STA_ID should ahve been set to 0, but teh CNT_ISO should have been left as-is - $att_id_in_db = $mappings[ 'Attendee' ][ 123 ]; - $att_in_db = EEM_Attendee::instance()->get_one_by_ID( $att_id_in_db ); - //model object with a foreign key that's a STRING (should be left as-is) - $this->assertEquals( 0, $att_in_db->get( 'STA_ID' ) ); - $this->assertEquals( '77', $att_in_db->get( 'CNT_ISO' ) ); - } - - /** - * @todo: if a foreign key can point to multiple models, only use mappings - * that apply - */ - public function test_save_data_array_to_db__from_other_site__fks_that_point_to_multiple_models() { - $this->markTestSkipped('addressed on ticket 7537.'); - //multiple types of fks that point ot multiple models: ones accompanied by a model name field and ones without - //using model name field: extra metas - //sans-model name field: term-relationships - $extra_meta_id = 1; - $extra_meta_id2 = 4; - $imaginary_txn_or_reg_id = 2; - - $an_event_id = 3; - - $csv_data = array( - 'Extra_Meta' => array( - //two extra meta rows, attached to different model objects - //but each coincidentally has the same ID - array( - 'EXM_ID' => $extra_meta_id, - 'OBJ_ID' => $imaginary_txn_or_reg_id, - 'EXM_type' => 'Transaction', - 'EXM_key' => 'foo', - 'EXM_value' => 'bar' - ), - array( - 'EXM_ID' => $extra_meta_id2, - 'OBJ_ID' => $imaginary_txn_or_reg_id, - 'EXM_type' => 'Registration', - 'EXM_key' => 'foo', - 'EXM_value' => 'bar' - ) - ), - 'Term_Relationship' => array( - array( - 'object_id' => $an_event_id,//an "event" - 'term_taxonomy_id' => 0, - 'term_order' => 1 - ) - ) - ); - - $mapped_txn_id = 4; - $mapped_reg_id = 124; - $mapped_event_id = 322; - $mappings = array( - 'Transaction' => array( - $imaginary_txn_or_reg_id => $mapped_txn_id - ), - 'Registration' => array( - $imaginary_txn_or_reg_id => $mapped_reg_id - ), - 'Event' => array( - $an_event_id => $mapped_event_id - ) - ); - //start test - $new_mappings = EE_Import::instance()->save_data_rows_to_db( $csv_data, true, $mappings ); - //ok, so we should have inserted 3 things, - $this->assertEquals( 2, count( $new_mappings[ 'Extra_Meta' ] ) ); - $this->assertEquals( 1, count( $new_mappings[ 'Term_Relationship' ] ) ); - //check that they correctly used the mappings that previously existed - $inserted_extra_meta_1_id = $new_mappings[ 'Extra_Meta' ][ $extra_meta_id ]; - $inserted_extra_meta_1 = EEM_Extra_Meta::instance()->get_one_by_ID( $inserted_extra_meta_1_id ); - $this->assertEquals( 'Transaction', $inserted_extra_meta_1->get( 'EXM_type' ) ); - $this->assertEquals( $mapped_txn_id, $inserted_extra_meta_1->get( 'OBJ_ID' ) ); - $inserted_extra_meta_2_id = $new_mappings[ 'Extra_Meta' ][ $extra_meta_id2 ]; - $inserted_extra_meta_2 = EEM_Extra_Meta::instance()->get_one_by_ID( $inserted_extra_meta_2_id ); - $this->assertEquals( 'Registration', $inserted_extra_meta_2->get( 'EXM_type' ) ); - $this->assertEquals( $mapped_reg_id, $inserted_extra_meta_2->get( 'OBJ_ID' ) ); - $inserted_term_r_id = $new_mappings[ 'Term_Relationship' ][ EEM_Term_Relationship::instance()->get_index_primary_key_string( $csv_data[ 'Term_Relationship' ][ 0 ])]; - $term_r = EEM_Term_Relationship::instance()->get_one_by_ID( $inserted_term_r_id ); - $this->assertInstanceOf( 'EE_Term_Relationship', $term_r); - $this->assertEquals( $mapped_event_id, $term_r->get('object_id' ) ); - - } - - /** - * test that term relationships are migrated ok if they would conflict with something already in the db - */ - function test_save_data_array_to_db__from_other_site__no_duplicate_term_relationships() { - /** - * @todo: unskip this once its working again - */ - $this->markTestSkipped('fixed on ticket 7537, https://events.codebasehq.com/projects/event-espresso/tickets/7537'); - $event_id_from_other_db = 122; - $term_tax_from_other_db = 32; - $old_term_r_order = 3; - $new_term_r_order = 123; - - $old_term_r_data = array( - 'object_id' => $event_id_from_other_db, - 'term_taxonomy_id' => $term_tax_from_other_db, - 'term_order' => $old_term_r_order - ); - - $a_real_event = $this->new_model_obj_with_dependencies( 'Event' ); - $a_real_term_taxonomy = $this->new_model_obj_with_dependencies( 'Term_Taxonomy' ); - $a_real_term_r = $this->new_model_obj_with_dependencies( 'Term_Relationship', array( 'object_id' => $a_real_event->ID(), 'term_taxonomy_id' => $a_real_term_taxonomy->ID(), 'term_order' => $new_term_r_order ) ); - - $csv_data = array( - 'Term_Relationship' => array( - $old_term_r_data - ) - ); - $mapping_data = array( - 'Event' => array( - $event_id_from_other_db => $a_real_event->ID() - ), - 'Term_Taxonomy' => array( - $term_tax_from_other_db => $a_real_term_taxonomy->ID() - ) - ); - $old_term_r_count = EEM_Term_Relationship::instance()->count(); - $new_mapping = EE_Import::instance()->save_data_rows_to_db( $csv_data, true, $mapping_data ); - $this->_assertNoImportErrors(); - //there should be NO new term relationships. it should have just been updated - $this->assertEquals( $old_term_r_count, EEM_Term_Relationship::instance()->count() ); - $this->assertEquals( 1, count( $new_mapping[ 'Term_Relationship' ] ) ); - $old_term_r_id = EEM_Term_Relationship::instance()->get_index_primary_key_string( $old_term_r_data ); - $new_term_r_id = $new_mapping[ 'Term_Relationship' ][ $old_term_r_id ]; - $new_term_r = EEM_Term_Relationship::instance()->get_one_by_ID( $new_term_r_id ); - $this->assertInstanceOf( 'EE_Term_Relationship', $new_term_r ); - $this->assertEquals( $old_term_r_order, $new_term_r->get('term_order' ) ); - - } - /** - * @todo: account for wp 4.2 term splitting (https://developer.wordpress.org/plugins/taxonomy/working-with-split-terms-in-wp-4-2/) - */ - function test_save_data_array_to_db__from_this_site__term_split(){ - //create term and term taxonomy - $term = $this->new_model_obj_with_dependencies( 'Term', array( 'name' => 'Jaguar', 'slug' => 'jag' ) ); - $ttcar = $this->new_model_obj_with_dependencies( 'Term_Taxonomy', array( 'term_id' => $term->ID(), 'taxonomy' => 'cars', 'description' => 'A fast car' ) ); - $ttcat = $this->new_model_obj_with_dependencies( 'Term_Taxonomy', array( 'term_id' => $term->ID(), 'taxonomy' => 'cats', 'description' => 'A large black cat that likes to swim' ) ); - //create "csv" data for it (pretend exported) - $csv_data = array( - 'Term' => array( - $term->model_field_array() - ), - 'Term_Taxonomy' => array( - $ttcar->model_field_array(), - $ttcat->model_field_array() - ) - ); - $this->assertEquals( $ttcat->get('term_id' ), $ttcar->get( 'term_id' ) ); - //split the term in the "wp" way. Our model objet $ttcar will NOT get updated on its own - $new_term_id_for_car = _split_shared_term( $term->ID(), $ttcar->ID() ); - $ttcar = EEM_Term_Taxonomy::instance()->refresh_entity_map_from_db( $ttcar->ID() ); -// echo "updated term taxonomy:";var_dump($ttcar->model_field_array()); - $this->assertNotEquals( $ttcat->get( 'term_id' ), $ttcar->get( 'term_id' ) ); - //import it - $new_mapping = EE_Import::instance()->save_data_rows_to_db( $csv_data, false, array() ); - - $ttcar = EEM_Term_Taxonomy::instance()->refresh_entity_map_from_db( $ttcar->ID() ); - - //when it's done importing, we should have saved a term-taxonomy for the new term, not re-inserted a term-taxonomy to the old term - //and because it used the models, the model objects we have in scope should already be up-to-date - $this->assertEquals( $new_term_id_for_car, $ttcar->get( 'term_id' ) ); - - } - /** - * in wp 4.1 there was no functions for term splitting. So let's add a filter - * to simulate that and mostly make sure there are no fatal errors - */ - function test_save_data_array_to_db__from_this_site__term_split__in_wp_41(){ - add_filter( 'FHEE__EE_Import__handle_split_term_ids__function_exists', '__return_false' ); - $term = $this->new_model_obj_with_dependencies( 'Term', array( 'name' => 'Jaguar', 'slug' => 'jag' ) ); - $ttcar = $this->new_model_obj_with_dependencies( 'Term_Taxonomy', array( 'term_id' => $term->ID(), 'taxonomy' => 'cars', 'description' => 'A fast car' ) ); - $ttcat = $this->new_model_obj_with_dependencies( 'Term_Taxonomy', array( 'term_id' => $term->ID(), 'taxonomy' => 'cats', 'description' => 'A large black cat that likes to swim' ) ); - //create "csv" data for it (pretend exported) - $csv_data = array( - 'Term' => array( - $term->model_field_array() - ), - 'Term_Taxonomy' => array( - $ttcar->model_field_array(), - $ttcat->model_field_array() - ) - ); - //now there should just not be any fatal errors when importing - EE_Import::instance()->save_data_rows_to_db( $csv_data, false, array() ); - $this->assertTrue( true ); - } - //@todo: test state which have int PKs, but should haev an unique index according to state abbrev and country - //@todo: test more regarding things with NO pks - //@todo: I suspect people will want to avoid duplicate states. This could be achieved by having the state abbrev and country ISO be a unique key - //@todo: add unit tests for inserting and updating models with no pks - -// public function test_save_data_array_to_db__from_other_site_second_time(){ -// //test that things in the mapping are remembered -// } -// -// public function test_save_data_array_to_db__from_same_site_first_time(){ -// //check for deleted things -// //should update old thing -// -// } -// public function test_save_data_array_to_db__from_same_site_second_time(){ -// //check -// } - - public function setUp(){ - parent::setUp(); - EE_Import::reset(); - } - protected function _assertNoImportErrors(){ - $notices = EE_Error::get_notices(false, false, true); - $this->assertEmpty( EE_Import::instance()->get_total_update_errors(), isset( $notices['errors'] ) ? $notices['errors'] : ''); - $this->assertEmpty( EE_Import::instance()->get_total_insert_errors(), isset( $notices['errors'] ) ? $notices['errors'] : '' ); - } -} -//in case this is run on WP 4.1, we'd still like to be able to test this WP 4.2 feature -if( ! function_exists( '_split_shared_term' ) ){ - /** - * Create a new term for a term_taxonomy item that currently shares its term with another term_taxonomy. - * - * @since 4.2.0 - * @access private - * - * @param int $term_id ID of the shared term. - * @param int $term_taxonomy_id ID of the term_taxonomy item to receive a new term. - * @return int|WP_Error When the current term does not need to be split (or cannot be split on the current database - * schema), `$term_id` is returned. When the term is successfully split, the new term_id is - * returned. A `WP_Error` is returned for miscellaneous errors. - */ - function _split_shared_term( $term_id, $term_taxonomy_id ) { - global $wpdb; - // Don't try to split terms if database schema does not support shared slugs. - $current_db_version = get_option( 'db_version' ); - if ( $current_db_version < 30133 ) { - return $term_id; - } - - // If there are no shared term_taxonomy rows, there's nothing to do here. - $shared_tt_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM $wpdb->term_taxonomy tt WHERE tt.term_id = %d AND tt.term_taxonomy_id != %d", $term_id, $term_taxonomy_id ) ); - if ( ! $shared_tt_count ) { - return $term_id; - } - - // Pull up data about the currently shared slug, which we'll use to populate the new one. - $shared_term = $wpdb->get_row( $wpdb->prepare( "SELECT t.* FROM $wpdb->terms t WHERE t.term_id = %d", $term_id ) ); - - $new_term_data = array( - 'name' => $shared_term->name, - 'slug' => $shared_term->slug, - 'term_group' => $shared_term->term_group, - ); - - if ( false === $wpdb->insert( $wpdb->terms, $new_term_data ) ) { - return new WP_Error( 'db_insert_error', __( 'Could not split shared term.' ), $wpdb->last_error ); - } - - $new_term_id = (int) $wpdb->insert_id; - - // Update the existing term_taxonomy to point to the newly created term. - $wpdb->update( $wpdb->term_taxonomy, - array( 'term_id' => $new_term_id ), - array( 'term_taxonomy_id' => $term_taxonomy_id ) - ); - - // Reassign child terms to the new parent. - $term_taxonomy = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $wpdb->term_taxonomy WHERE term_taxonomy_id = %d", $term_taxonomy_id ) ); - $children_tt_ids = $wpdb->get_col( $wpdb->prepare( "SELECT term_taxonomy_id FROM $wpdb->term_taxonomy WHERE taxonomy = %s AND parent = %d", $term_taxonomy->taxonomy, $term_id ) ); - - if ( ! empty( $children_tt_ids ) ) { - foreach ( $children_tt_ids as $child_tt_id ) { - $wpdb->update( $wpdb->term_taxonomy, - array( 'parent' => $new_term_id ), - array( 'term_taxonomy_id' => $child_tt_id ) - ); - clean_term_cache( $term_id, $term_taxonomy->taxonomy ); - } - } else { - // If the term has no children, we must force its taxonomy cache to be rebuilt separately. - clean_term_cache( $new_term_id, $term_taxonomy->taxonomy ); - } - - // Clean the cache for term taxonomies formerly shared with the current term. - $shared_term_taxonomies = $wpdb->get_row( $wpdb->prepare( "SELECT taxonomy FROM $wpdb->term_taxonomy WHERE term_id = %d", $term_id ) ); - if ( $shared_term_taxonomies ) { - foreach ( $shared_term_taxonomies as $shared_term_taxonomy ) { - clean_term_cache( $term_id, $shared_term_taxonomy ); - } - } - - // Keep a record of term_ids that have been split, keyed by old term_id. See {@see wp_get_split_term()}. - $split_term_data = get_option( '_split_terms', array() ); - if ( ! isset( $split_term_data[ $term_id ] ) ) { - $split_term_data[ $term_id ] = array(); - } - - $split_term_data[ $term_id ][ $term_taxonomy->taxonomy ] = $new_term_id; - - update_option( '_split_terms', $split_term_data ); - - /** - * Fires after a previously shared taxonomy term is split into two separate terms. - * - * @since 4.2.0 - * - * @param int $term_id ID of the formerly shared term. - * @param int $new_term_id ID of the new term created for the $term_taxonomy_id. - * @param int $term_taxonomy_id ID for the term_taxonomy row affected by the split. - * @param string $taxonomy Taxonomy for the split term. - */ - do_action( 'split_shared_term', $term_id, $new_term_id, $term_taxonomy_id, $term_taxonomy->taxonomy ); - - return $new_term_id; - } -} -if( ! function_exists( 'wp_get_split_terms' ) ) { - /** - * - * @param type $old_term_id - * @return int - */ - function wp_get_split_terms( $old_term_id ) { - $split_terms = get_option( '_split_terms', array() ); - - $terms = array(); - if ( isset( $split_terms[ $old_term_id ] ) ) { - $terms = $split_terms[ $old_term_id ]; - } - - return $terms; - } -} -if( ! function_exists( 'wp_get_split_term' ) ){ - /** - * Get the new term ID corresponding to a previously split term. - * - * @since 4.2.0 - * - * @param int $old_term_id Term ID. This is the old, pre-split term ID. - * @param string $taxonomy Taxonomy that the term belongs to. - * @return bool|int If a previously split term is found corresponding to the old term_id and taxonomy, the new term_id - * will be returned. If no previously split term is found matching the parameters, returns false. - */ - function wp_get_split_term( $old_term_id, $taxonomy ) { - $split_terms = wp_get_split_terms( $old_term_id ); - - $term_id = false; - if ( isset( $split_terms[ $taxonomy ] ) ) { - $term_id = (int) $split_terms[ $taxonomy ]; - } - - return $term_id; -} -} - -// End of file EE_Import_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_classes/EE_Line_Item_Test.php b/tests/testcases/core/db_classes/EE_Line_Item_Test.php deleted file mode 100644 index 04bc43228f1..00000000000 --- a/tests/testcases/core/db_classes/EE_Line_Item_Test.php +++ /dev/null @@ -1,679 +0,0 @@ -save(); - $l = EE_Line_Item::new_instance(array('OBJ_type' => 'Transaction', 'OBJ_ID' => $t->ID())); - $this->assertNotNull($l->generate_code()); - } - - function test_get_nearest_descendant_of_type() - { - $txn = $this->new_typical_transaction(); - $line_item = $txn->total_line_item(); - $old_tax_subtotal = EEH_Line_Item::get_nearest_descendant_of_type($line_item, EEM_Line_Item::type_tax_sub_total); - $this->assertInstanceOf('EE_Line_Item', $old_tax_subtotal); - $this->assertEquals(EEM_Line_Item::type_tax_sub_total, $old_tax_subtotal->type()); - $old_tax = EEH_Line_Item::get_nearest_descendant_of_type($line_item, EEM_Line_Item::type_tax); - $this->assertInstanceOf('EE_Line_Item', $old_tax_subtotal); - $this->assertEquals(EEM_Line_Item::type_tax, $old_tax->type()); - - } - - /** - * test that if you call this on the grand total, that it doesn't REMOVE the taxes from it - * @group 7026 - */ - function test_recalculate_pre_tax_total__dont_change_grand_total() - { - $txn = $this->new_typical_transaction(); - $total_line_item = $txn->total_line_item(); - $total_including_taxes = $total_line_item->total(); - $total_line_item->recalculate_pre_tax_total(); - $this->assertNotEquals(0, $txn->tax_total()); - $this->assertEquals($total_including_taxes, $total_line_item->total()); - } - - - /** - * @group 10654 - * Verifies that when we recalculate an event's subtotal, we also update its unit price right away. - * Otherwise it can lead to issues like reported on 10654. - */ - public function test_recalculate_pre_tax_total__dont_miss_updating_subtotal_unit_prices() - { - $txn = $this->new_typical_transaction(); - $total_line_item = $txn->total_line_item(); - $event_subtotal_array = EEH_Line_Item::get_event_subtotals($total_line_item); - $event_subtotal = reset($event_subtotal_array); - $original_event_subtotal_amount = $event_subtotal->total(); - $original_event_subtotal_unit_price = $event_subtotal->unit_price(); - // EEH_Line_Item::visualize($total_line_item); - //ok now let's add a discount, under the event subtotal - EEH_Line_Item::add_percentage_based_item( - $event_subtotal, - 'Some discount', - -50, - 'should affect event subtotals unit price' - ); - // EEH_Line_Item::visualize($total_line_item); - $total_line_item->recalculate_pre_tax_total(); - // EEH_Line_Item::visualize($total_line_item); - //so that should have reduced the event subtotal's total by half, AND its unit price - $this->assertEquals($original_event_subtotal_amount / 2, $event_subtotal->total()); - $this->assertEquals($original_event_subtotal_unit_price / 2, $event_subtotal->unit_price()); - } - - /** - * @group 11126 - */ - public function testRecaculatePreTaxTotalUpdatesLineItemSubtotalQuantitiesToZeroForNextRequest() - { - //verify that if we decrement the total of a li, and its subtotal li becomes 0 - $txn = $this->new_typical_transaction(); - $total_li = $txn->total_line_item(); - $event_subtotals = EEH_Line_Item::get_event_subtotals($total_li); - $event_subtotal = reset($event_subtotals); - $line_items = $event_subtotal->children(); - $ticket_li = reset($line_items); - $this->assertEquals(1, $event_subtotal->quantity()); - $this->assertEquals(1, $ticket_li->quantity()); - EEH_Line_Item::decrement_quantity($ticket_li); - $total_li->recalculate_total_including_taxes(); - $this->assertEquals(0, $ticket_li->quantity()); - $this->assertEquals(0, $event_subtotal->quantity()); - //pretend it's the next request and double-check the changes stuck - EEM_Line_Item::reset(); - $event_subtotal_from_db = EEM_Line_Item::instance()->get_one_by_ID($event_subtotal->ID()); - $ticket_li_from_db = EEM_Line_Item::instance()->get_one_by_ID($ticket_li->ID()); - $this->assertEquals(0, $event_subtotal_from_db->quantity()); - $this->assertEquals(0, $ticket_li_from_db->quantity()); - } - - - /** - * @group 11126 - */ - public function testRecaculatePreTaxTotalUpdatesLineItemSubtotalQuantitiesFromZero() - { - //verify that if we decrement the total of a li, and its subtotal li becomes 0 - $txn = $this->new_typical_transaction(); - $total_li = $txn->total_line_item(); - $event_subtotals = EEH_Line_Item::get_event_subtotals($total_li); - $event_subtotal = reset($event_subtotals); - $line_items = $event_subtotal->children(); - $ticket_li = reset($line_items); - $this->assertEquals(1, $event_subtotal->quantity()); - $this->assertEquals(1, $ticket_li->quantity()); - EEH_Line_Item::decrement_quantity($ticket_li); - $total_li->recalculate_total_including_taxes(); - $this->assertEquals(0, $ticket_li->quantity()); - $this->assertEquals(0, $event_subtotal->quantity()); - //ok now re-increase the quantity - EEH_Line_Item::increment_quantity($ticket_li); - $total_li->recalculate_total_including_taxes(); - $this->assertEquals(1, $ticket_li->quantity()); - $this->assertEquals(1, $event_subtotal->quantity()); - //ok bump it up again. But only events' quantity should increase (that's the current behaviour so may as well keep it) - EEH_Line_Item::increment_quantity($ticket_li); - $total_li->recalculate_total_including_taxes(); - $this->assertEquals(2, $ticket_li->quantity()); - $this->assertEquals(1, $event_subtotal->quantity()); - - } - - /** - * Verifies that after we update a line item and recalculate the total, the tax subtotal also gets updated - * @group 11126 - */ - public function testRecalculatePreTaxTotalAndUpdateTaxesToo() - { - $txn = $this->new_typical_transaction(); - $old_grant_total = $txn->total_line_item()->total(); - //make sure it has a tax on it - $taxes_subtotal_li = EEH_Line_Item::get_taxes_subtotal($txn->total_line_item()); - $old_taxes_subtotal_total = $taxes_subtotal_li->total(); - $taxes = $taxes_subtotal_li->children(); - $this->assertCount(1, $taxes); - $tax_li = reset($taxes); - $old_tax_li_total = $tax_li->total(); - $this->assertGreaterThan(0, $taxes_subtotal_li->total()); - //take note of the current ticket price - $ticket_lis = EEH_Line_Item::get_ticket_line_items($txn->total_line_item()); - $this->assertCount(1, $ticket_lis); - $ticket_li = reset($ticket_lis); - $ticket_li->set_quantity(2); - $old_ticket_li_total = $ticket_li->total(); - //modify the ticket price and recalculate the total - $subitem_lis = $ticket_li->children(); - $this->assertCount(1, $subitem_lis); - $txn->total_line_item()->recalculate_total_including_taxes(); - //ok now pretend it's a new request - EEM_Line_Item::reset(); - $ticket_li_from_db = EEM_Line_Item::instance()->get_one_by_ID($ticket_li->ID()); - $total_li_from_db = EEM_Line_Item::instance()->get_one_by_ID($txn->total_line_item()->ID()); - $tax_li_from_db = EEM_Line_Item::instance()->get_one_by_ID($tax_li->ID()); - $tax_subtotal_li_from_db = EEM_Line_Item::instance()->get_one_by_ID($taxes_subtotal_li->ID()); - //verify the total was changed - $this->assertEquals($old_ticket_li_total * 2, $ticket_li_from_db->total()); - $this->assertEquals($old_grant_total * 2, $total_li_from_db->total()); - //lastly, verify the tax and tax subtotals got updated - $this->assertEquals($old_tax_li_total * 2, $tax_li_from_db->total()); - $this->assertEquals($old_taxes_subtotal_total * 2, $tax_subtotal_li_from_db->total()); - } - - - /** - * @group 8964 - * Uses a particular number and quantity that has been shown to cause rounding problems - * prior to the work on 8964 (specifically, if you had 2 transactions for 1 ticket purchase each - * the total for both transactions was NOT the same as 1 transaction for 2 ticket purchases) - */ - function test_recalculate_pre_tax_total__rounding_issues() - { - $flat_base_price_type_id = EEM_Price_Type::instance()->get_var(array(array('PRT_name' => 'Base Price'))); - $percent_surcharge_price_type_id = EEM_Price_Type::instance()->get_var(array(array('PRT_name' => 'Percent Surcharge'))); - $base_price = $this->new_model_obj_with_dependencies( - 'Price', - array( - 'PRT_ID' => $flat_base_price_type_id, - 'PRC_amount' => 21.67 - )); - $percent_surcharge = $this->new_model_obj_with_dependencies( - 'Price', - array( - 'PRT_ID' => $percent_surcharge_price_type_id, - 'PRC_amount' => 20 - )); - $ticket = $this->new_model_obj_with_dependencies( - 'Ticket', - array( - 'TKT_price' => $base_price->amount() + ($base_price->amount() * $percent_surcharge->amount() / 100), - 'TKT_taxable' => false - )); - $ticket->_add_relation_to($base_price, 'Price'); - $ticket->_add_relation_to($percent_surcharge, 'Price'); - $event = $this->new_model_obj_with_dependencies('Event'); - $datetime = $this->new_model_obj_with_dependencies('Datetime'); - $ticket->_add_relation_to($datetime, 'Datetime'); - - $quantity = 2; - $total_line_item = EEH_Line_Item::add_ticket_purchase(EEH_Line_Item::create_total_line_item(), $ticket, $quantity); - - $this->assertEquals($ticket->price() * $quantity, $total_line_item->total()); - - } - - /** - * * also test that if you call this in order to get the taxable total, that it doesn't update - * the totals to ONLY be taxable totals - * @group 7026 - */ - function test_recalculate_pre_tax_total__dont_save_if_ignoring_nontaxables() - { - //make a txn where NOTHING is taxable - $txn = $this->new_typical_transaction(array('ticket_types' => 2, 'taxable_tickets' => 1)); - $proper_line_items = EEM_Line_Item::instance()->get_all_of_type_for_transaction(EEM_Line_Item::type_line_item, $txn->ID()); - $this->assertEquals(2, count($proper_line_items)); - $taxable_one = FALSE; - $nontaxable_one = FALSE; - $taxable_line_item = NULL; - foreach ($proper_line_items as $line_item) { - if ($line_item->is_taxable()) { - $taxable_one = TRUE; - $taxable_line_item = $line_item; - } else { - $nontaxable_one = TRUE; - } - } - $this->assertTrue($taxable_one); - $this->assertTrue($nontaxable_one); - $this->assertNotEquals(0, $txn->tax_total()); - - $total_line_item = $txn->total_line_item(); - $old_total = $total_line_item->total(); - //when we calculate the pre-tax, including only taxable items (ie, we're wanting - //to know how much to apply taxes to) we don't change the grand or ticket totals - $pretax_total = $total_line_item->taxable_total(); - //because there is only one taxable line item, the taxable total should equals its total - $this->assertEquals($taxable_line_item->total(), $pretax_total); - //check we didn't assign the taxable total to be the grand total - $this->assertNotEquals($pretax_total, $total_line_item->total()); - $this->assertEquals($old_total, $total_line_item->total()); - //find tickets subtotal and make sure it hasn't been assigned to be the taxable total either - //temporarily commented out because this throws an error. - //$this->assertNotEquals( $pretax_total, $total_line_item->get_child_line_item('tickets')->total() ); - } - - /** - * Create a line item tree with an initially empty subtotal. We shouldn't - * have trouble calculating its total with a percent line item. - * Also, we shouldn't need to set any totals: the call to recalculate_total_including_taxes - * should take care of setting them all - * @group 8566 - */ - function test_recalculate_total_including_taxes__unknown_subtotals_initially() - { - $event_subtotal = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'event1', - 'LIN_name' => 'EventA', - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'OBJ_type' => 'Event', - 'LIN_total' => 0, - )); - $event_subtotal->save(); - $normal_line_item = EE_Line_Item::new_instance( - array( - 'LIN_code' => '12354', - 'LIN_name' => 'ticketA', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'OBJ_type' => 'Ticket', - 'LIN_unit_price' => 10, - 'LIN_quantity' => 2, - 'LIN_order' => 1, - 'LIN_parent' => $event_subtotal->ID() - )); - $normal_line_item->save(); - $percent_line_item = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'dscntfry', - 'LIN_name' => 'Discounto', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'OBJ_type' => '', - 'LIN_unit_price' => null, - 'LIN_quantity' => null, - 'LIN_percent' => -25, - 'LIN_order' => 1000, - 'LIN_parent' => $event_subtotal->ID() - )); - $percent_line_item->save(); - $event_subtotal->recalculate_total_including_taxes(); -// EEH_Line_Item::visualize( $event_subtotal ); - $this->assertEquals(20, $normal_line_item->total()); - $this->assertEquals(15, $event_subtotal->total()); - $this->assertEquals(-5, $percent_line_item->total()); - - } - - /** - * Verifies that we fix sub line item quantities and line item unit prices - * @group 8566 - */ - function test_recalculate_total_including_taxes__fix_sub_line_item_quantities() - { - $line_item = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'ticket', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_quantity' => 2 - )); - $line_item->save(); - $flat_sub_line_item = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'flat', - 'LIN_type' => EEM_Line_Item::type_sub_line_item, - 'LIN_unit_price' => 10, - 'LIN_quantity' => 1,//it should match its parent, which is 2 - 'LIN_order' => 1, - 'LIN_parent' => $line_item->ID(), - )); - $flat_sub_line_item->save(); - $percent_sub_line_item = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'percent', - 'LIN_type' => EEM_Line_Item::type_sub_line_item, - 'LIN_quantity' => 0, - 'LIN_percent' => -25, - 'LIN_order' => 100, - 'LIN_parent' => $line_item->ID() - )); - $percent_sub_line_item->save(); - $line_item->recalculate_pre_tax_total(); - $this->assertEquals(2, $flat_sub_line_item->quantity()); - $this->assertEquals(1, $percent_sub_line_item->quantity()); - $this->assertEquals(20, $flat_sub_line_item->total()); - $this->assertEquals(-5, $percent_sub_line_item->total()); - $this->assertEquals(15, $line_item->total()); - $this->assertEquals(7.5, $line_item->unit_price()); - } - - /** - * Create a line item tree which was originaly for 6 tickets and a discount, - * but 2 got cancelled and so shouldn't count towards the grand total, - * and so the ticket line item's quantity should be 4 - * @group 5580 - */ - function test_recalculate_total_including_taxes__with_cancellations() - { - $event_subtotal = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'event1', - 'LIN_name' => 'EventA', - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'OBJ_type' => 'Event', - 'LIN_total' => 0, - )); - $event_subtotal->save(); - $normal_line_item = EE_Line_Item::new_instance( - array( - 'LIN_code' => '12354', - 'LIN_name' => 'ticketA', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'OBJ_type' => 'Ticket', - 'LIN_unit_price' => 10, - 'LIN_quantity' => 4, - 'LIN_order' => 1, - 'LIN_parent' => $event_subtotal->ID() - )); - $normal_line_item->save(); - $cancellation_subitem = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'cancellationoruny', - 'LIN_name' => 'cancellationOfA', - 'LIN_type' => EEM_Line_Item::type_cancellation, - 'OBJ_type' => '',//? - 'LIN_unit_price' => 10, - 'LIN_quantity' => 2, - 'LIN_order' => 1, - 'LIN_parent' => $normal_line_item->ID() - )); - $percent_line_item = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'dscntfry', - 'LIN_name' => 'Discounto', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'OBJ_type' => '', - 'LIN_unit_price' => null, - 'LIN_quantity' => null, - 'LIN_percent' => -25, - 'LIN_order' => 1000, - 'LIN_parent' => $event_subtotal->ID() - )); - $percent_line_item->save(); - $event_subtotal->recalculate_total_including_taxes(); -// EEH_Line_Item::visualize( $event_subtotal ); - $this->assertEquals(40, $normal_line_item->total()); - $this->assertEquals(30, $event_subtotal->total()); - $this->assertEquals(-10, $percent_line_item->total()); - - } - - /** - * @group 9439 - */ - function test_recalculate_total_including_taxes__incorrect_total_with_specific_numbers_and_promotion() - { - $total_li = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'total', - 'LIN_type' => EEM_Line_Item::type_total, - ) - ); - $total_li->save(); - - $pretax_subtotal = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'pretax', - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'LIN_code' => 'pre-tax-subtotal', - 'LIN_parent' => $total_li->ID(), - 'LIN_order' => 1 - ) - ); - $pretax_subtotal->save(); - $event_subtotal = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'subtotal', - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'LIN_parent' => $pretax_subtotal->ID(), - 'LIN_order' => 1 - - ) - ); - $event_subtotal->save(); - $line_item = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'ticket', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_quantity' => 1, - 'LIN_is_taxable' => true, - 'LIN_parent' => $event_subtotal->ID(), - 'LIN_order' => 1, - )); - $line_item->save(); - $flat_sub_line_item = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'flat', - 'LIN_type' => EEM_Line_Item::type_sub_line_item, - 'LIN_unit_price' => 21.01, - 'LIN_quantity' => 1, - 'LIN_order' => 1, - 'LIN_parent' => $line_item->ID(), - )); - $flat_sub_line_item->save(); - $percent_discount = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'flat', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_percent' => -50, - 'LIN_quantity' => 1, - 'LIN_order' => 10, - 'LIN_is_taxable' => true, - 'LIN_parent' => $event_subtotal->ID(), - )); - $percent_discount->save(); - $tax_subtotal = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'tax-sub-total', - 'LIN_code' => 'taxes', - 'LIN_type' => EEM_Line_Item::type_tax_sub_total, - 'LIN_order' => 100, - 'LIN_parent' => $total_li->ID(), - ) - ); - $tax_subtotal->save(); - $tax = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'tax', - 'LIN_code' => 'a_tax', - 'LIN_type' => EEM_Line_Item::type_tax, - 'LIN_percent' => 19, - 'LIN_parent' => $tax_subtotal->ID(), - ) - ); - $tax->save(); - $total_li->recalculate_total_including_taxes(); - $this->assertEquals($line_item->total() + $percent_discount->total(), $event_subtotal->total()); - $this->assertEquals(12.50, $total_li->total()); - $this->assertEquals($pretax_subtotal->total(), $total_li->get_items_total()); - } - - /** - * @group 8464 - * Verifies that if the line item is for a relation that isn't currently defined - * (and in core there is no promotion model) that we don't get an exception or warning, just null - */ - public function test_get_object__non_existent_model_name() - { - $li = $this->new_model_obj_with_dependencies('Line_Item', array('OBJ_ID' => 123, 'OBJ_type' => 'Promotion')); - $this->assertNull($li->get_object()); - } - - /** - * @group 8464 - * Verifies that if the line item is for a relation that isn't currently RELATED but IS defined - */ - public function test_get_object__non_related_model_name() - { - $li = $this->new_model_obj_with_dependencies('Line_Item', array('OBJ_ID' => 123, 'OBJ_type' => 'Answer')); - $this->assertNull($li->get_object()); - } - - /** - * @group 8488 - */ - public function test_taxable_total__percent_items() - { - $parent_li = $this->new_model_obj_with_dependencies('Line_Item', - array( - 'LIN_name' => 'total', - 'LIN_type' => EEM_Line_Item::type_sub_total, - )); - //create 2 childline items, one taxable and one not - $taxable = $this->new_model_obj_with_dependencies('Line_Item', - array( - 'LIN_name' => 'taxable', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_total' => 10, - 'LIN_unit_price' => 10, - 'LIN_percent' => 0, - 'LIN_quantity' => 1, - 'LIN_is_taxable' => true, - 'LIN_parent' => $parent_li->ID() - )); - $nontaxable = $this->new_model_obj_with_dependencies('Line_Item', - array( - 'LIN_name' => 'nontaxable', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_total' => 10, - 'LIN_unit_price' => 10, - 'LIN_percent' => 0, - 'LIN_quantity' => 1, - 'LIN_is_taxable' => false, - 'LIN_parent' => $parent_li->ID() - )); - //and then a percent line item that is taxable - $discount = $this->new_model_obj_with_dependencies('Line_Item', - array( - 'LIN_name' => 'discount', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_total' => -10, - 'LIN_unit_price' => 0, - 'LIN_percent' => -50, - 'LIN_quantity' => 1, - 'LIN_is_taxable' => true, - 'LIN_parent' => $parent_li->ID() - )); - //so when we ask their parent for the taxable total, it should only - //factor in the taxable portion of the percent item - //only half of the 10 dollar discount (so 5) should be facotred into taxes - //so the taxable total should be the taxable ticket (10) minus half the discount (5) - //so it should equal 5 - $this->assertEquals(5, $parent_li->taxable_total()); - } - - /** - * @group 8488 - */ - public function test_taxable_total__negative_total() - { - $parent_li = $this->new_model_obj_with_dependencies('Line_Item', - array( - 'LIN_name' => 'total', - 'LIN_type' => EEM_Line_Item::type_sub_total, - )); - //create a child line item that's NOT taxable - $taxable = $this->new_model_obj_with_dependencies('Line_Item', - array( - 'LIN_name' => 'taxable', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_total' => 10, - 'LIN_unit_price' => 10, - 'LIN_percent' => 0, - 'LIN_quantity' => 1, - 'LIN_is_taxable' => false, - 'LIN_parent' => $parent_li->ID() - )); - //and then a flat discount that is "taxable" (ie, taxes take it into account) - $discount = $this->new_model_obj_with_dependencies('Line_Item', - array( - 'LIN_name' => 'discount', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_total' => -10, - 'LIN_unit_price' => -10, - 'LIN_percent' => 0, - 'LIN_quantity' => 1, - 'LIN_is_taxable' => true, - 'LIN_parent' => $parent_li->ID() - )); - //so when we ask their parent for the taxable total, it should only - //factor in the taxable portion of the percent item - //only half of the 10 dollar discount (so 5) should be facotred into taxes - //so the taxable total should be the taxable ticket (10) minus half the discount (5) - //so it should equal 5 - $this->assertEquals(0, $parent_li->taxable_total()); - } - - /** - * @group 8572 - */ - public function test_set_parent() - { - $li1 = $this->new_model_obj_with_dependencies('Line_Item', array('LIN_parent' => null), false); - - $li2 = $this->new_model_obj_with_dependencies('Line_Item', array('LIN_parent' => null), false); - $this->assertEquals(null, $li1->parent()); - $this->assertEquals(array(), $li1->children()); - - //add a cached relation - $li1->add_child_line_item($li2); - $this->assertEquals(array($li2->code() => $li2), $li1->children()); - $this->assertEquals($li1, $li2->parent()); - //and let's change the parent - $li3 = $this->new_model_obj_with_dependencies('Line_Item', array('LIN_parent' => null), false); - $li3->add_child_line_item($li2); - $this->assertEquals($li3, $li2->parent()); - //and let's see if the relations are preserved when we save them - $li3->save_this_and_descendants_to_txn(); - $this->assertNotEquals(0, $li3->ID()); - $this->assertNotEquals(0, $li2->ID()); - $this->assertEquals($li3, $li2->parent()); - } - - - public function test_line_item_serialization() - { - if (version_compare(PHP_VERSION, '5.5', '<')) { - $this->markTestSkipped(); - } - $line_item = $this->new_model_obj_with_dependencies( - 'Line_Item', - array('LIN_parent' => null), - false - ); - $line_item = serialize($line_item); - $line_item = unserialize($line_item); - $this->assertInstanceOf( - 'EE_Line_Item', - $line_item - ); - /** @var EE_Line_Item $line_item */ - $datetime = $line_item->get_DateTime_object('LIN_timestamp'); - $this->assertInstanceOf( - 'Datetime', - $datetime - ); - } -} -// End of file EE_Line_Item_Test.php -// Location: testcases/core/db_classes/EE_Line_Item_Test.php diff --git a/tests/testcases/core/db_classes/EE_Message_Template_Group_Test.php b/tests/testcases/core/db_classes/EE_Message_Template_Group_Test.php deleted file mode 100644 index a5f1ee8abb9..00000000000 --- a/tests/testcases/core/db_classes/EE_Message_Template_Group_Test.php +++ /dev/null @@ -1,99 +0,0 @@ -message_template_group = EEM_Message_Template_Group::instance()->get_one( - array( - array( - 'MTP_messenger' => 'email', - 'MTP_message_type' => 'registration' - ) - ) - ); - } - - - public function tearDown() - { - parent::tearDown(); - $this->message_template_group = null; - } - - - /** - * This tests that a valid context that should be active on a fresh install is. - */ - public function testValidContextTemplateShouldBeActive() - { - $this->assertTrue( - $this->message_template_group->is_context_active( - 'admin' - ) - ); - } - - - /** - * @expectedException EventEspresso\core\exceptions\InvalidIdentifierException - */ - public function testInvalidContextTemplateForIsContextActive() - { - $this->message_template_group->is_context_active('bogus'); - } - - - - - public function testDeactivatingAndReactivatingValidContext() - { - //deactivate - $this->message_template_group->deactivate_context('admin'); - $this->assertFalse( - $this->message_template_group->is_context_active('admin') - ); - - //activate again - $this->message_template_group->activate_context('admin'); - $this->assertTrue( - $this->message_template_group->is_context_active('admin') - ); - } - - - /** - * @expectedException EventEspresso\core\exceptions\InvalidIdentifierException - */ - public function testActivatingInvalidContext() - { - $this->message_template_group->deactivate_context('bogus'); - } - - - /** - * @expectedException EventEspresso\core\exceptions\InvalidIdentifierException - */ - public function testDeactivatingInvalidContext() - { - $this->message_template_group->activate_context('bogus'); - } -} diff --git a/tests/testcases/core/db_classes/EE_Payment_Test.php b/tests/testcases/core/db_classes/EE_Payment_Test.php deleted file mode 100644 index 7ff89a98ac1..00000000000 --- a/tests/testcases/core/db_classes/EE_Payment_Test.php +++ /dev/null @@ -1,121 +0,0 @@ -assertFalse( $p1->just_approved() ); - $p1->set_status( EEM_Payment::status_id_approved ); - $this->assertTrue( $p1->just_approved() ); - $id = $p1->save(); - $this->assertTrue( $p1->just_approved() ); - - EEM_Payment::reset(); - //now try with a payment that began as approved - //note that we've reset EEM_payment so this is just like - //it had been created on a previous request - $p2 = EEM_Payment::instance()->get_one_by_ID( $id ); - $this->assertFalse( $p2->just_approved() ); - $p2->set_status( EEM_Payment::status_id_pending ); - $p2->save(); - - EEM_Payment::reset(); - //again, pretend this next part is a subsequent request - $p3 = EEM_Payment::instance()->get_one_by_ID( $id ); - $this->assertFalse( $p3->just_approved() ); - $p3->set_status( EEM_Payment::status_id_approved ); - $this->assertTrue( $p3->just_approved() ); - } - - /** - * @group 7653 - */ - function test_set_details(){ - $p = $this->new_model_obj_with_dependencies( 'Payment' ); - $cookie = new WP_Http_Cookie( array( - 'name' => 'something', - 'value' => 'somethingelse' - )); - $details_to_set = array( - 'headers' => array( - 'header1' => 'headervalue1', - 'header2' => 'headervalue2', - ), - 'body' => 'hello', - 'cookies' => array( - $cookie - ) - ); - //set the details with that object in there - $p->set_details( $details_to_set ); - //ok now verify that it's been converted into an array a-ok - $details_to_set['cookies'][0] = (array)$cookie; - //and we should have actually removed tags like we set out to do in that method - $details_to_set['body'] = 'hello'; - $this->assertEquals( $details_to_set, $p->details() ); - } - - - /** - * @group 9245 - */ - function test_redirect_form__with_redirect_args() { - $redirect_url = 'http://somesite.com'; - $redirect_args = array( 'arg1' => 'a', 'arg2' => 'b' ); - $p = $this->new_model_obj_with_dependencies( 'Payment', array( 'PAY_redirect_url' => $redirect_url, 'PAY_redirect_args' => $redirect_args ) ); - $html_form = $p->redirect_form(); - $this->assertContains( - '
', - $html_form - ); - foreach( $redirect_args as $name => $value ) { - $this->assertContains( - '', - $html_form - ); - } - } - - /** - * @group 9245 - */ - function test_redirect_form__with_redirect_NO_args() { - $redirect_url = 'http://somesite.com'; - $redirect_args = array( 'arg1' => 'a', 'arg2' => 'b' ); - $redirect_url_combined = $redirect_url .'?' . http_build_query( $redirect_args ); - $p = $this->new_model_obj_with_dependencies( 'Payment', - array( - 'PAY_redirect_url' => $redirect_url_combined, - 'PAY_redirect_args' => false //we want it to be a GET request, so leave this blank - ) - ); - $html_form = $p->redirect_form(); - $this->assertContains( - '', - $html_form ); - foreach( $redirect_args as $name => $value ) { - $this->assertContains( - '', - $html_form); - } - } -} - -// End of file EE_Payment_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_classes/EE_Price_Test.php b/tests/testcases/core/db_classes/EE_Price_Test.php deleted file mode 100644 index 7639627fa39..00000000000 --- a/tests/testcases/core/db_classes/EE_Price_Test.php +++ /dev/null @@ -1,25 +0,0 @@ -'let hte wookie win')); - $this->assertEquals('let hte wookie win',$p->desc()); - } -} - -// End of file EE_Price_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_classes/EE_Registration_Test.php b/tests/testcases/core/db_classes/EE_Registration_Test.php deleted file mode 100644 index c0123fb022d..00000000000 --- a/tests/testcases/core/db_classes/EE_Registration_Test.php +++ /dev/null @@ -1,139 +0,0 @@ - EEM_Transaction::complete_status_code)); - $t->save(); - $e = EE_Event::new_instance(); - $e->save(); - $tkt = EE_Ticket::new_instance(); - $tkt->save(); - $d = EE_Datetime::new_instance(array('EVT_ID'=>$e->ID())); - $d->save(); - $tkt->_add_relation_to($d, 'Datetime'); - /** @type EE_Registration_Processor $registration_processor */ - $registration_processor = EE_Registry::instance()->load_class( 'Registration_Processor' ); - $REG_url_link = new EventEspresso\core\domain\entities\RegUrlLink( - 1, - EE_Line_Item::new_instance( - array( - 'LIN_name' => $tkt->name(), - 'LIN_desc' => $tkt->description(), - 'LIN_unit_price' => $tkt->price(), - 'LIN_quantity' => 1, - 'LIN_is_taxable' => $tkt->taxable(), - 'LIN_order' => 0, - 'LIN_total' => $tkt->price(), - 'LIN_type' => EEM_Line_Item::type_line_item, - 'OBJ_ID' => $tkt->ID(), - 'OBJ_type' => 'Ticket' - ) - ) - ); - $r = EE_Registration::new_instance( - array( - 'EVT_ID' => $e->ID(), - 'TXN_ID' => $t->ID(), - 'TKT_ID' => $tkt->ID(), - 'STS_ID' => EEM_Registration::status_id_pending_payment, - 'REG_url_link' => $REG_url_link - ) - ); - - $r->set_reg_code( - new EventEspresso\core\domain\entities\RegCode( - $REG_url_link, - $r->transaction(), - $r->ticket() - ) - ); - $registration_processor->update_registration_after_checkout_or_payment( $r ); - $this->assertNotNull($r->reg_code()); - $this->assertEquals(EEM_Registration::status_id_approved,$r->status_ID()); - } - - function test_answer_value_to_question() { - /** @var EE_Registration $r */ - $r = $this->new_model_obj_with_dependencies( 'Registration' ); - $q1 = $this->new_model_obj_with_dependencies( 'Question' ); - //also grab the default first name question - $q2 = EEM_Question::instance()->get_Question_ID_from_system_string(EEM_Attendee::system_question_fname); - $this->assertNotNull($q2); - /** @var EE_Answer $a1 */ - $a1 = $this->new_model_obj_with_dependencies( 'Answer', array('REG_ID' =>$r->ID(), 'QST_ID' =>$q1->ID())); - $this->assertEquals( $a1->value(), $r->answer_value_to_question( $q1, false ) ); - $this->assertEquals($r->attendee()->fname(),$r->answer_value_to_question($q2,false)); - } - - - - /** - * This verifies the can_checkin() method in EE_registration - * - * @since 4.5.0 - * - * @return void - */ - function test_can_checkin() { - //setup a registration - $r = $this->new_model_obj_with_dependencies( 'Registration' ); - - $t = $this->new_ticket(); - - //let's assign the above ticket to our registration - $r->_add_relation_to( $t, 'Ticket' ); - $r->save(); - - $d = EEM_Datetime_Ticket::instance()->get_one( array( array( 'TKT_ID' => $r->get('TKT_ID') ) ) ); - $this->assertInstanceOf( 'EE_Datetime_Ticket', $d ); - $valid_DTT_ID = $d->get('DTT_ID'); - $invalid_DTT_ID = 99999; - - //k let's test the possible expected responses of can_checkin; - //IGNORING status - //test one: valid DTT and unapproved reg - $r->set_status( EEM_Registration::status_id_not_approved ); - $this->assertTrue( $r->can_checkin( $valid_DTT_ID, false ) ); - - //test two: invalid DTT and approved reg - $r->set_status( EEM_Registration::status_id_approved ); - $this->assertFalse( $r->can_checkin( $invalid_DTT_ID, false ) ); - - //including status - //test one: valid DTT and approved reg - $this->assertTrue( $r->can_checkin( $valid_DTT_ID ) ); - - //test two: invalid DTT and approved reg - $this->assertFalse( $r->can_checkin( $invalid_DTT_ID ) ); - - //test three: valid DTT and not approved reg - $r->set_status( EEM_Registration::status_id_not_approved ); - $this->assertFalse( $r->can_checkin( $valid_DTT_ID ) ); - - //test four: valid DTT and incomplete reg - $r->set_status( EEM_Registration::status_id_incomplete ); - $this->assertFalse( $r->can_checkin( $valid_DTT_ID ) ); - - //test five: invalid DTT and incomplete reg - $this->assertFalse( $r->can_checkin( $invalid_DTT_ID ) ); - } - -} - -// End of file EE_Registration_Test.php -// Location: /tests/testcases/core/db_classes/EE_Registration_Test.php diff --git a/tests/testcases/core/db_classes/EE_Ticket_Test.php b/tests/testcases/core/db_classes/EE_Ticket_Test.php deleted file mode 100644 index 226a572d830..00000000000 --- a/tests/testcases/core/db_classes/EE_Ticket_Test.php +++ /dev/null @@ -1,149 +0,0 @@ - time() - 100, - 'TKT_end_date' => time() + 200, - )); - $this->assertTrue($t->is_on_sale()); - $t->set('TKT_start_date', time() + 100); - $this->assertFalse($t->is_on_sale()); - } - - public function test_is_pending() - { - $t = EE_Ticket::new_instance(array( - 'TKT_start_date' => time() + 100, - 'TKT_end_date' => time() + 200, - )); - $this->assertTrue($t->is_pending()); - $t->set('TKT_start_date', time() - 100); - $this->assertFalse($t->is_pending()); - } - - public function test_is_expired() - { - $t = EE_Ticket::new_instance(array( - 'TKT_start_date' => time() - 200, - 'TKT_end_date' => time() - 100, - )); - $this->assertTrue($t->is_expired()); - $t->set('TKT_end_date', time() + 100); - $this->assertFalse($t->is_expired()); - } - - public function test_available() - { - $t = EE_Ticket::new_instance(array( - 'TKT_start_date' => time(), - 'TKT_end_date' => time(), - 'TKT_qty' => 10, - 'TKT_sold' => 0, - )); - $this->assertTrue($t->available()); - $t->set('TKT_sold', 10); - $t->save(); - $this->assertFalse($t->available()); - } - - public function test_remaining() - { - $t = EE_Ticket::new_instance(array( - 'TKT_start_date' => time(), - 'TKT_end_date' => time(), - 'TKT_qty' => 10, - 'TKT_sold' => 0, - )); - $t->save(); - $d = EE_Datetime::new_instance(); - $d->save(); - $t->_add_relation_to($d, 'Datetime'); - $this->assertEquals(10, $t->remaining()); - // simulate 5 ticket sales - $this->simulate_x_number_ticket_sales($t, 5); - $this->assertEquals(5, $t->remaining()); - } - - - public function test_ticket_status() - { - $t = EE_Ticket::new_instance(array( - 'TKT_start_date' => time() - 100, - 'TKT_end_date' => time() + 100, - 'TKT_qty' => 10, - 'TKT_sold' => 0, - 'TKT_deleted' => true, - )); - $t->save(); - $d = EE_Datetime::new_instance(); - $d->save(); - $t->_add_relation_to($d, 'Datetime'); - - $this->assertEquals(EE_Ticket::archived, $t->ticket_status()); - $t->set('TKT_deleted', false); - $this->assertEquals(EE_Ticket::onsale, $t->ticket_status()); - // simulate 10 ticket sales - $this->simulate_x_number_ticket_sales($t, 10); - $this->assertEquals(EE_Ticket::sold_out, $t->ticket_status()); - $this->reverse_x_number_ticket_sales($t, 10); - $d->set_reg_limit(10); - $d->save(); - $t->set('TKT_start_date', time() + 50); - $this->assertEquals(EE_Ticket::pending, $t->ticket_status()); - $t->set('TKT_start_date', time() - 100); - $t->set('TKT_end_date', time() - 50); - $this->assertEquals(EE_Ticket::expired, $t->ticket_status()); - } - - public function test_increase_and_decrease_sold() - { - $t = EE_Ticket::new_instance(array( - 'TKT_start_date' => time() - 100, - 'TKT_end_date' => time() + 100, - 'TKT_qty' => 10, - 'TKT_sold' => 0, - )); - $this->assertEquals(0, $t->sold()); - $t->increase_sold(); - $this->assertEquals(1, $t->sold()); - $t->increase_sold(2); - $this->assertEquals(3, $t->sold()); - //now try decreasing - $t->decrease_sold(); - $this->assertEquals(2, $t->sold()); - $t->decrease_sold(2); - $this->assertEquals(0, $t->sold()); - } - - - /** - * @group 10283 - * @expectedException \EventEspresso\core\exceptions\UnexpectedEntityException - */ - public function test_get_related_event_exception() - { - //create a ticket (it won't have any datetime). - /** @var EE_Ticket $ticket */ - $ticket = $this->factory->ticket->create(); - //the following should throw the exception - $ticket->get_related_event(); - } -} - -// End of file EE_Ticket_Test.php -// Location: tests/testcases/core/db_classes/EE_Ticket_Test.php diff --git a/tests/testcases/core/db_classes/EE_Transaction_Test.php b/tests/testcases/core/db_classes/EE_Transaction_Test.php deleted file mode 100644 index f9c8822fc00..00000000000 --- a/tests/testcases/core/db_classes/EE_Transaction_Test.php +++ /dev/null @@ -1,222 +0,0 @@ -new_model_obj_with_dependencies( 'Transaction', null, false ); - $this->assertEquals( 0, $t->ID() ); - /** @type EE_Registration $r */ - $r = $this->new_model_obj_with_dependencies( 'Registration', array( 'REG_count' => 1 ), false ); - $this->assertEquals( 0, $r->ID() ); - $t->_add_relation_to( $r, 'Registration' ); - $this->assertEquals( $r, $t->primary_registration() ); - $r->save(); - $this->assertNotEquals( 0, $r->ID() ); - $in_map = EE_Registry::instance()->load_model( 'Registration' )->get_from_entity_map( $r->ID() ); - $this->assertEquals( $r, $in_map ); - $this->assertEquals( $r, $t->primary_registration() ); - $this->assertEquals( 1, $r->count() ); - $r_in_db = EE_Registry::instance()->load_model( 'Registration' )->get_one_by_ID( $r->ID() ); - $this->assertEquals( $r, $r_in_db ); - $t->save(); - $this->assertEquals( $r, $t->primary_registration() ); - //why does the above fail? because we forgot to set the registration's TXN_ID! - //so it makes sense, but it sure would have been considerate of the transaction if, - //when it was saved, it would have set the ID on all foreign keys pointing to it - //on things it had cached on itself - } - - - - public function test_payment_method() { - /** @type EE_Transaction $t */ - $t = $this->new_model_obj_with_dependencies( 'Transaction' ); - $this->assertNotEquals( 0, $t->payment_method_ID() ); - $pm = $t->payment_method(); - $this->assertInstanceOf( 'EE_Payment_Method', $pm ); - //now if there is no explicit payment method on the transaction, use the first payment - $t->set( 'PMD_ID', 0 ); - $p = $this->new_model_obj_with_dependencies( 'Payment' ); - $t->_add_relation_to( $p, 'Payment' ); - $pm = $t->payment_method(); - $this->assertInstanceOf( 'EE_Payment_Method', $pm ); - } - - - - /** - * This tests the datetime method on EE_Transaction - * - * @since 4.6 - * @throws \EE_Error - */ - public function test_datetime() { - $now = new DateTime( "now", new DateTimeZone( 'America/Vancouver' ) ); - $DateTimeZoneAbbr = $now->format( 'T' ); - // Now get the transaction's time - $format_to_use = get_option( 'date_format' ) . ' ' . 'H:i:s'; - /** @type EE_Transaction $t */ - $t = $this->factory->transaction->create(); - $t->set_timezone( 'America/Vancouver' ); - /** - * just to standardize the two times because Unix timestamps are so precise, we'll use our expected - * time to set the time on the transaction. This still verifies the functionality of the class. - * Because time comparisons will be based on seconds (Unix timestamp), let's ensure we use a - * format with seconds as well - */ - $t->set_time_format( 'H:i:s' ); - $t->set( 'TXN_timestamp', $now->format( $t->get_format( $format_to_use ) ) ); - //test getting pretty (should return formatted item in the correct timezone) - $this->assertEquals( - $now->format( $format_to_use ) . ' (' . $DateTimeZoneAbbr . ')', - $t->datetime( true ), - 'datetime( true ) test' - ); - //test getting pretty with no_html - $this->assertEquals( - $now->format( $format_to_use ) . ' (' . $DateTimeZoneAbbr . ')', - $t->get_pretty( 'TXN_timestamp', 'no_html' ), - 'get_pretty, no_html test' - ); - //test getting raw Unix timestamp - $this->assertEquals( - $now->format( 'U' ), - $t->datetime( false, true ), - 'datetime( false, true) test' - ); - //test get() (time string with offset) - $this->assertEquals( $now->format( $format_to_use ), $t->datetime(), 'datetime() test' ); - } - - - - /** - * @throws \EE_Error - */ - public function test_is_locked() { - /** @type EE_Transaction $transaction */ - $transaction = $this->factory->transaction->create(); - // initial state should be unlocked - $locked = $transaction->get_extra_meta( 'lock', true, 0 ); - $this->assertEquals( 0, $locked ); - // is_locked() should equal $locked - $this->assertEquals( $locked, $transaction->is_locked() ); - // set a lock - $transaction->add_extra_meta( 'lock', time(), true ); - // now is_locked() should NOT equal $locked - $this->assertNotEquals( $locked, $transaction->is_locked() ); - // delete existing lock - $transaction->delete_extra_meta( 'lock' ); - // now set another lock, but with an expired timestamp - $transaction->add_extra_meta( 'lock', time() - HOUR_IN_SECONDS , true ); - // is_locked() should remove that lock and once again equal $locked - $this->assertEquals( $locked, $transaction->is_locked() ); - } - - - - public function test_lock() { - /** @type EE_Transaction $transaction */ - $transaction = $this->factory->transaction->create(); - // initial state should be unlocked - $locked = $transaction->get_extra_meta( 'lock', true, 0 ); - $this->assertEquals( 0, $locked ); - // now lock it - $transaction->lock(); - $locked = $transaction->get_extra_meta( 'lock', true, 0 ); - $this->assertNotEquals( 0, $locked ); - // delete existing lock - $transaction->delete_extra_meta( 'lock' ); - // now set another lock, but with an expired timestamp - $expired_timestamp = time() - HOUR_IN_SECONDS; - $transaction->add_extra_meta( 'lock', $expired_timestamp, true ); - // this time, lock() should remove the expired lock, and set a new one with a current timestamp - $transaction->lock(); - $locked = $transaction->get_extra_meta( 'lock', true, 0 ); - $this->assertNotEquals( 0, $locked ); - $this->assertGreaterThan( $expired_timestamp, $locked ); - } - - - - /** - * @throws \EE_Error - */ - public function test_unlock() { - /** @type EE_Transaction $transaction */ - $transaction = $this->factory->transaction->create(); - // initial state should be unlocked - $locked = $transaction->get_extra_meta( 'lock', true, 0 ); - $this->assertEquals( 0, $locked ); - // set a lock - $transaction->add_extra_meta( 'lock', time(), true ); - // unlock() should remove the above lock and return a value of 1 - $this->assertEquals( 1, $transaction->unlock() ); - } - - - - /** - * @see https://events.codebasehq.com/projects/event-espresso/tickets/10920 - * @group 10920 - */ - public function testTrashedRegistrationLoading() - { - /** @type EE_Transaction $transaction */ - $transaction = $this->new_model_obj_with_dependencies('Transaction', null); - /** @type EE_Registration[] $registrations */ - $registrations = array(); - for($x = 1; $x < 5; $x++) { - $registrations[$x] = $this->new_model_obj_with_dependencies( - 'Registration', - array( - 'REG_count' => $x, - 'STS_ID' => $x > 2 // true for registrations 3 && 4 - ? EEM_Registration::status_id_cancelled - : EEM_Registration::status_id_pending_payment, - 'REG_deleted' => $x > 2 // true for registrations 3 && 4 - ) - ); - $transaction->_add_relation_to($registrations[$x], 'Registration'); - } - // confirm setup worked correctly - for ($x = 1; $x < 5; $x++) { - $this->assertEquals( - $registrations[$x]->is_cancelled(), - $x > 2 // true for registrations 3 && 4 - ); - $this->assertEquals( - $registrations[$x]->deleted(), - $x > 2 // true for registrations 3 && 4 - ); - } - $this->assertCount(4, $registrations); - // should NOT return trashed registrations - $this->assertCount( - 2, - $transaction->registrations(array(array('REG_deleted' => false))), - 'There should only be two registrations returned' - ); - } - - -} -// End of file EE_Transaction_Test.php -// Location:/tests/testcases/core/db_classes/EE_Transaction_Test.php diff --git a/tests/testcases/core/db_classes/EE_Venue_Test.php b/tests/testcases/core/db_classes/EE_Venue_Test.php deleted file mode 100644 index fbc3ec00cde..00000000000 --- a/tests/testcases/core/db_classes/EE_Venue_Test.php +++ /dev/null @@ -1,72 +0,0 @@ - $this->factory->datetime->create( array( 'DTT_EVT_start' => $past_start_date->format( $full_format ), 'DTT_EVT_end' => $past_start_date->format( $full_format), 'timezone' => 'America/Toronto', 'formats' => $formats ) ), - 'upcoming_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $upcoming_start_date->format( $full_format ), 'DTT_EVT_end' => $upcoming_start_date->format( $full_format), 'timezone' => 'America/Toronto', 'formats' => $formats ) ), - 'active_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $current->format( $full_format ), 'DTT_EVT_end' => $current_end_date->format( $full_format), 'timezone' => 'America/Toronto', 'formats' => $formats ) ), - 'sold_out_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $upcoming_start_date->format( $full_format ), 'DTT_EVT_end' => $upcoming_start_date->format( $full_format), 'DTT_reg_limit' => 10, 'DTT_sold' => 10, 'timezone' => 'America/Toronto', 'formats' => $formats ) ) - ); - - - $venue = $this->factory->venue->create(); - //assign events to the datetimes and then the events to the venue. - foreach ( $datetimes as $type => $datetime ) { - $event = $this->factory->event->create(); - $event->set_timezone( 'America/Toronto' ); - $event->set('status', 'publish'); - $event->_add_relation_to( $datetime, 'Datetime' ); - $event->save(); - $venue->_add_relation_to($event, 'Event'); - $venue->save(); - } - - //test with upcoming as false. Should return 4 events. - $events = $venue->events(); - $this->assertEquals( 4, count($events) ); - $this->assertInstanceOf( 'EE_Event', reset($events) ); - - //test with upcoming as true. Should return 2 events. - $events = $venue->events(array(), true); - $this->assertEquals( 2, count($events) ); - $this->assertInstanceOf( 'EE_Event', reset($events) ); - - } - - - -}// end class EE_Venue_Test diff --git a/tests/testcases/core/db_models/EEM_Answer_Test.php b/tests/testcases/core/db_models/EEM_Answer_Test.php deleted file mode 100644 index 9f18a2b6979..00000000000 --- a/tests/testcases/core/db_models/EEM_Answer_Test.php +++ /dev/null @@ -1,85 +0,0 @@ -new_model_obj_with_dependencies('Registration'); - $a = $this->new_model_obj_with_dependencies('Answer',array('REG_ID'=>$r->ID())); - $q = EEM_Question::instance()->get_one_by_ID($a->question_ID()); - $this->assertNotNull($q); - $this->assertEquals( $a, EEM_Answer::instance()->get_registration_question_answer_object( $r, $a->question_ID() ) ); - } - function test_get_attendee_property_answer_value(){ - $r = $this->new_model_obj_with_dependencies( 'Registration' ); - global $wpdb; - $att = EEM_Attendee::reset()->get_one_by_ID( $r->attendee_ID() ); - $this->assertEquals( $r->attendee()->fname(), EEM_Answer::instance()->get_attendee_property_answer_value( $r, EEM_Attendee::system_question_fname ) ); - } - public function test_get_answer_value_to_question(){ - $r = $this->new_model_obj_with_dependencies('Registration'); - $a = $this->new_model_obj_with_dependencies('Answer',array('REG_ID'=>$r->ID())); - $this->assertEquals($a->value(),EEM_Answer::instance()->get_answer_value_to_question($r,$a->question_ID(),false)); - $this->assertEquals($r->attendee()->fname(),EEM_Answer::instance()->get_answer_value_to_question($r, EEM_Question::instance()->get_Question_ID_from_system_string( EEM_Attendee::system_question_fname ) ) ); - } - /** - * @group 8237 - */ - public function test_set_ANS_value__with_unsafe_html(){ - $a = $this->new_model_obj_with_dependencies( 'Answer', array( 'ANS_value' => '') ); - $this->assertEquals( '', $a->get_raw( 'ANS_value' ) ); - } - - /** - * @group 8237 - */ - public function test_get_ANS_value__with_unsafe_html_in_db() { - $a = $this->new_model_obj_with_dependencies( 'Answer' ); - global $wpdb; - //manually insert bad stuff into the answer - $success = $wpdb->update( - EEM_Answer::instance()->table(), - array( - 'ANS_value' => '' - ), - array( - 'ANS_ID' => $a->ID() - ), - array( - '%s',//ANS_value - ), - array( - '%s',//ANS_ID - ) - ); - $this->assertEquals( 1, $success ); - $this->assertEquals( - '', - EEM_Answer::instance()->get_var( - array( - array( - 'ANS_ID' => $a->ID() - ) - ), - 'ANS_value' )); - //ok so it's definetely got dangerous stuff in the db, but when we fetch it using the models it should be safe again - $a->refresh_from_db(); - $this->assertEquals( '', $a->get_raw( 'ANS_value' ) ); - } -} - -// End of file EEM_Answer_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/EEM_Attendee_Caps_Test.php b/tests/testcases/core/db_models/EEM_Attendee_Caps_Test.php deleted file mode 100644 index 79995341d6a..00000000000 --- a/tests/testcases/core/db_models/EEM_Attendee_Caps_Test.php +++ /dev/null @@ -1,44 +0,0 @@ -factory->user->create_and_get(); - $att = $this->new_model_obj_with_dependencies( 'Attendee' ); - $this->assertEquals( 0, EEM_Attendee::instance()->count( array( 'caps' => EEM_Base::caps_read ) ) ); - - //ok now log the user in - $current_user = $user; - - //and they still shouldn't be able to view the attendee - $this->assertEquals( 0, EEM_Attendee::instance()->count( array( 'caps' => EEM_Base::caps_read ) ) ); - - //ok now give them access to contacts - $current_user->add_cap( 'ee_read_contacts' ); - //and now they should be able to see it - $this->assertEquals( 1, EEM_Attendee::instance()->count( array( 'caps' => EEM_Base::caps_read ) ) ); - } -} - -// End of file EEM_Attendee_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/EEM_Base_Test.php b/tests/testcases/core/db_models/EEM_Base_Test.php deleted file mode 100644 index 457f0839bba..00000000000 --- a/tests/testcases/core/db_models/EEM_Base_Test.php +++ /dev/null @@ -1,1226 +0,0 @@ -markTestSkipped('If a multi-byte character gets chopped in half, EEM_Base::insert and update simply dont work. Avoid it by using mb_strcut instead of substr'); - $string_of_multibyte_chracters = 'event’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’’'; - $string_with_a_chopped_multibyte_character = substr($string_of_multibyte_chracters,0,127); - $id = EEM_Change_Log::instance()->insert( - array( - 'LOG_message' => $string_with_a_chopped_multibyte_character - ) - ); - $this->assertNotFalse($id); - } - public function test_models_defined_ok() - { - foreach (EE_Registry::instance()->non_abstract_db_models as $model) { - $model_instance = EE_Registry::instance()->load_model($model); - $this->assertInstanceOf('EEM_Base', $model_instance); - //checks their relations - foreach ($model_instance->relation_settings() as $relation_name => $relation_obj) { - //verify that each relation is named according to an existing model - $related_model_instance = EE_Registry::instance()->load_model($relation_name); - $this->assertInstanceOf('EE_Model_Relation_Base', $relation_obj); - } - foreach ($model_instance->field_settings(true) as $field_name => $field_obj) { - $this->assertInstanceOf('EE_Model_Field_Base', $field_obj); - } - } - } - - - - /** - * Verifies that for each model, the tables it claims to require have been installed - */ - public function test_model_tables_exist() - { - foreach (EE_Registry::instance()->non_abstract_db_models as $model) { - $model_instance = EE_Registry::instance()->load_model($model); - foreach ($model_instance->get_tables() as $table_alias => $table_obj) { - $this->assertTableExists($table_obj->get_table_name(), $model); - } - } - } -// public function test_models_can_insert(){ -// foreach(EE_Registry::instance()->non_abstract_db_models as $model){ -// $model_instance = EE_Registry::instance()->load_model($model); -// $id = $model_instance->insert(array()); -// $this->assertNotEmpty($id); -// } -// } - /** - * checks that EEM_Base::has_field works properly - */ - public function test_has_field() - { - $this->assertTrue(EEM_Question::instance()->has_field('QST_ID')); - $this->assertTrue(EEM_QUestion::instance()->has_field('QST_admin_only')); - $this->assertFalse(EEM_Question::instance()->has_field('monkey brains')); - } - - - - /** - * checks that adding a LIKE in teh WHERE clauses works ok - */ - public function test_where_like() - { - $attendees_before = EEM_Attendee::instance()->get_all(); - $this->assertEmpty($attendees_before); - $a = EE_Attendee::new_instance(array('ATT_email' => 'monkey123@hotmail.com')); - $a->save(); - $attendees_after_insert = EEM_Attendee::instance()->get_all(); - $this->assertEquals(1, count($attendees_after_insert)); - $attendee_found = EEM_Attendee::instance()->get_one(array(array('ATT_email' => array('LIKE', '%key12%')))); - $this->assertInstanceOf('EE_Attendee', $attendee_found); - $this->assertEquals($a->ID(), $attendee_found->ID()); - } - - - - public function test_delete() - { - $e1 = EE_Event::new_instance(); - $e1->save(); - $e2 = EE_Event::new_instance(); - $e2->save(); - $e3 = EE_Event::new_instance(); - $e3->save(); - //now assert things are as they should be: the items are in teh Db and the entity map - $this->assertEquals(EEM_Event::instance()->get_one_by_ID($e1->ID()), $e1); - $this->assertEquals(EEM_Event::instance()->get_one_by_ID($e2->ID()), $e2); - $this->assertEquals(EEM_Event::instance()->get_one_by_ID($e3->ID()), $e3); - $this->assertEquals(EEM_Event::instance()->get_from_entity_map($e1->ID()), $e1); - $this->assertEquals(EEM_Event::instance()->get_from_entity_map($e2->ID()), $e2); - $this->assertEquals(EEM_Event::instance()->get_from_entity_map($e3->ID()), $e3); - //now run a delete query that should have deleted $e1 and $e2 - EEM_Event::instance()->delete_permanently(array(array('EVT_ID' => array('<=', $e2->ID())))); - //check $e1 and $e2 don't exist in the DB anymore - $this->assertEmpty(EEM_Event::instance()->get_one_by_ID($e1->ID())); - $this->assertEmpty(EEM_Event::instance()->get_one_by_ID($e2->ID())); - $this->assertEquals(EEM_Event::instance()->get_one_by_ID($e3->ID()), $e3); - //and now chekc $e1 and $e2 don't exist in the entity map either - $this->assertEmpty(EEM_Event::instance()->get_from_entity_map($e1->ID())); - $this->assertEmpty(EEM_Event::instance()->get_from_entity_map($e2->ID())); - $this->assertEquals(EEM_Event::instance()->get_from_entity_map($e3->ID()), $e3); - } - - - /** - * Verifies deletes still work properly, even when deleting a model object whose data is shared between two tables - */ - public function test_delete__across_multiple_tables() - { - $event_to_delete = $this->new_model_obj_with_dependencies('Event'); - $event_shouldnt_be_harmed = $this->new_model_obj_with_dependencies('Event'); - global $wpdb; - $post_table_entries = $wpdb->get_var('SELECT COUNT(*) FROM ' . EEM_Event::instance()->table()); - $event_meta_table_entries = $wpdb->get_var('SELECT COUNT(*) FROM ' . EEM_Event::instance()->second_table()); - //make sure when we delete this event, both the record from the posts table and the event meta table get deleted - $success = $event_to_delete->delete_permanently(); - $this->assertEquals(2, $success); - $this->assertEquals( - $post_table_entries - 1, - $wpdb->get_var('SELECT COUNT(*) FROM ' . EEM_Event::instance()->table()) - ); - $this->assertEquals( - $event_meta_table_entries - 1, - $wpdb->get_var('SELECT COUNT(*) FROM ' . EEM_Event::instance()->second_table()) - ); - } - - - /** - * Verifies permanent deletes will also remove any extra meta that might be present in the database for items - * deleted. - */ - public function test_delete_with_extra_meta() - { - /** @var EE_Registration $registration_to_delete */ - $registration_to_delete = $this->factory->registration->create(); - //add extrameta - $registration_to_delete->update_extra_meta('test_registration_meta', 'value'); - - //get the extra meta so we have its ID for checking later. - $extra_meta = EEM_Extra_Meta::instance()->get_one(array( - array( - 'OBJ_ID' => $registration_to_delete->ID(), - 'EXM_type' => 'Registration', - 'EXM_key' => 'test_registration_meta' - ) - )); - $this->assertInstanceOf('EE_Extra_Meta', $extra_meta); - - //delete the registration - $success = $registration_to_delete->delete_permanently(); - $this->assertEquals(1, $success); - - //assert the meta no longer exists in the db. - $extra_meta = EEM_Extra_Meta::instance()->get_one_by_ID($extra_meta->ID()); - $this->assertNotInstanceOf('EE_Extra_Meta', $extra_meta); - } - - - - /** - * @throws EE_Error - */ - public function test_distanced_HABTM_join() - { - try { - EEM_Line_Item::instance()->get_all(array(array('Ticket.Datetime.EVT_ID' => 1, 'TXN_ID' => 1))); - $this->assertTrue(true); - } catch (EE_Error $e) { - throw $e; - } - } - - - - public function test_get_col() - { - $att1 = EEM_Attendee::instance()->insert(array('ATT_fname' => 'one')); - $att2 = EEM_Attendee::instance()->insert(array('ATT_fname' => 'two')); - $att3 = EEM_Attendee::instance()->insert(array('ATT_fname' => 'three')); - $att4 = EEM_Attendee::instance()->insert(array('ATT_fname' => 'four')); - $all = EEM_Attendee::instance()->get_col(); - $this->assertArrayContains((string)$att1, $all); - $this->assertArrayContains((string)$att2, $all); - $this->assertArrayContains((string)$att3, $all); - $this->assertArrayContains((string)$att4, $all); - $just_two_and_threes_names = EEM_Attendee::instance()->get_col(array( - array( - 'ATT_fname' => array( - 'IN', - array( - 'two', - 'three', - ), - ), - ), - ), 'ATT_fname'); - $this->assertArrayDoesNotContain('one', $just_two_and_threes_names); - $this->assertArrayContains('two', $just_two_and_threes_names); - $this->assertArrayContains('three', $just_two_and_threes_names); - $this->assertArrayDoesNotContain('four', $just_two_and_threes_names); - } - - - - /** - * - */ - public function test_update__keeps_model_objs_in_sync() - { - $att1 = EE_Attendee::new_instance(array('ATT_fname' => 'one')); - $att2 = EE_Attendee::new_instance(array('ATT_fname' => 'two')); - $att3 = EE_Attendee::new_instance(array('ATT_fname' => 'three')); - $att1->save(); - $att2->save(); - $att3->save(); - //test taht when do perform an update, the model objects are updated also - $attm = EE_Registry::instance()->load_model('EEM_Attendee'); - $attm->update(array('ATT_fname' => 'win'), array(array('ATT_fname' => 'two'))); - $this->assertEquals('one', $att1->fname()); - $this->assertEquals('win', $att2->fname()); - $this->assertEquals('three', $att3->fname()); - //now test doing an update that should be more efficient wehre we DON'T update - //model objects - $attm->update(array('ATT_fname' => 'win_again'), array(array('ATT_fname' => 'one')), false); - $this->assertEquals('one', $att1->fname()); - $this->assertEquals('win', $att2->fname()); - $this->assertEquals('three', $att3->fname()); - global $wpdb; - $name_in_db = $wpdb->get_var("select ATT_fname FROM " - . $wpdb->prefix - . "esp_attendee_meta WHERE ATT_ID = " - . $att1->ID()); - $this->assertEquals('win_again', $name_in_db); - //also test to make sure there are no errors when there was nothing to update in the entity map - $att4 = EEM_Attendee::instance()->insert(array('ATT_fname' => 'four')); - $wpdb->last_error = null; - EEM_Attendee::instance()->update(array('ATT_fname' => 'lose'), array(array('ATT_fname' => 'four'))); - $this->assertEmpty($wpdb->last_error); - //and that there are no errors when nothing at all is updated - EEM_Attendee::instance() - ->update(array('ATT_fname' => 'lose_again'), array(array('ATT_fname' => 'nonexistent'))); - $this->assertEmpty($wpdb->last_error); - } - - - - /** - * @group 6767 - */ - public function test_two_joins() - { - EEM_Attendee::instance()->get_all(array(array('Registration.Event.EVT_name' => 'bob'))); - $this->assertTrue(true, 'No exception thrown'); - } - - - - /** - * @group 7151 - */ - public function test_refresh_entity_map_from_db() - { - //get an object purposefully out-of-sync with the DB - //call this and make sure it's wiped clean and - $p = $this->new_model_obj_with_dependencies('Payment', array('PAY_amount' => 25)); - $p->save(); - $this->assertEquals($p, EEM_Payment::instance()->get_from_entity_map($p->ID())); - //now manually update it in teh DB, but not the model object - global $wpdb; - $affected = $wpdb->query($wpdb->prepare("update {$wpdb->prefix}esp_payment SET PAY_amount = 100, TXN_ID = 0 WHERE PAY_ID = %d", - $p->ID())); - $this->assertEquals(1, $affected); - //and when it's refreshed, its PAY_amount should be updated too and it should no longer have any transaction cached or evenfindable - EEM_Payment::instance()->refresh_entity_map_from_db($p->ID()); - $this->assertEquals(100, $p->get('PAY_amount')); - $this->assertEquals(0, $p->get('TXN_ID')); - $this->assertEquals(array(), $p->get_all_from_cache('Transaction')); - $this->assertEquals(null, $p->transaction()); - } - - - - /** - * @group 7151 - */ - public function test_refresh_entity_map_from_db__serialized_object() - { - //get an object purposefully out-of-sync with the DB - //call this and make sure it's wiped clean and - $p = $this->new_model_obj_with_dependencies('Payment', array('PAY_amount' => 25)); - $p->save(); - $this->assertEquals($p, EEM_Payment::instance()->get_from_entity_map($p->ID())); - //ok now remember that ID, serialize the payment, and otherwise remove the object - $p_id = $p->ID(); - $p_serialized = serialize($p); - unset($p); - EEM_Payment::reset(); - //now manually update it in teh DB, but not the model object - global $wpdb; - $affected = $wpdb->query($wpdb->prepare("update {$wpdb->prefix}esp_payment SET PAY_amount = 100, TXN_ID = 0 WHERE PAY_ID = %d", - $p_id)); - $this->assertEquals(1, $affected); - //now unserialize it and verify it's what we thought it was - $p_unserialized = unserialize($p_serialized); - $this->assertEquals($p_id, $p_unserialized->ID()); - $this->assertEquals(25, $p_unserialized->get('PAY_amount')); - //and when it's refreshed, its PAY_amount should be updated too and it should no longer have any transaction cached or even findable - $p_unserialized = EEM_Payment::instance()->refresh_entity_map_from_db($p_unserialized->ID()); - $this->assertEquals(100, $p_unserialized->get('PAY_amount')); - $this->assertEquals(0, $p_unserialized->get('TXN_ID')); - $this->assertEquals(array(), $p_unserialized->get_all_from_cache('Transaction')); - $this->assertEquals(null, $p_unserialized->transaction()); - } - - - - /** - * @group 7151 - */ - public function test_fresh_entity_map_with() - { - $p = $this->new_model_obj_with_dependencies('Payment', array('PAY_amount' => 25)); - $p->save(); - $this->assertEquals($p, EEM_Payment::instance()->get_from_entity_map($p->ID())); - //now purposefully make a naughty payment which isn't in the entity map - $p2 = clone $p; - $this->assertFalse($p2->in_entity_map()); - //make the two EE_Payments diverge - $p2->set('PAY_amount', 99); - $t = EE_Transaction::new_instance(); - $p2->cache('Transaction', $t); - $this->assertEquals(25, $p->get('PAY_amount')); - $this->assertEquals(99, $p2->get('PAY_amount')); - $this->assertNotEquals($p->get_all_from_cache('Transaction'), $p2->get_all_from_cache('Transaction')); - //now update the payment in the entity map with the other - EEM_Payment::instance()->refresh_entity_map_with($p->ID(), $p2); - $this->assertEquals(99, $p->get('PAY_amount')); - //make sure p hasn't changed into p2. that's not what we wanted to do... - $this->assertFalse($p2 === $p); - //We wanted to just UPDATE p with p2's values - $this->assertEquals($p, EEM_Payment::instance()->get_from_entity_map($p->ID())); - //and make sure p's cache was updated to be the same as p2's - $this->assertEquals($p2->get_all_from_cache('Transaction'), $p->get_all_from_cache('Transaction')); - } - - - - /** - * This tests the get_formats_for method with exception - * - * @since 4.6.x - */ - public function test_get_formats_for_with_exception() - { - EEM_Datetime::reset(); - //test expected exception for invalid field - $this->setExpectedException('EE_Error'); - EEM_Datetime::instance()->get_formats_for('Bogus_Field'); - } - - - - /** - * This tests the get_formats_for method with valid field - * - * @since 4.6.x - */ - public function test_get_formats_for_with_valid_field() - { - EEM_Datetime::reset(); - //first test default field setup - $formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start'); - $this->assertContains('F j, Y', $formats); - $this->assertContains('g:i a', $formats); - //test values on EE_Datetime_Field after EE_Datetime instantiation. - $this->factory->datetime->create(array('formats' => array('Y-m-d', 'H:i:s'))); - $test_formats = EEM_Datetime::instance()->get_formats_for('DTT_EVT_start'); - $this->assertContains('Y-m-d', $test_formats); - $this->assertContains('H:i:s', $test_formats); - } - - - - /** - * @since 4.6.x - */ - public function test_current_time_for_query() - { - EEM_Datetime::reset(); - //baseline DateTime object for testing - $now = new DateTime("now"); - $DateTimeZone = new DateTimeZone('America/Vancouver'); - $timezoneTest = new DateTime("now", $DateTimeZone); - //just in case some other test has messed up the default date format string in WordPress unit tests. - $expected_format = get_option('date_format') . ' ' . get_option('time_format'); - //test getting default formatted string and default formatted unix timestamp. - $formatted_string = EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'); - $this->assertEquals($now->format($expected_format), $formatted_string); - $timestamp_with_offset = EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start', true); - $this->assertEquals($now->format('U'), $timestamp_with_offset); - //test values when timezone and formats modified on EE_Datetime instantiation - $this->factory->datetime->create(array( - 'formats' => array('Y-m-d', 'H:i:s'), - 'timezone' => 'America/Vancouver', - )); - $formatted_string = EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start'); - $this->assertDateWithinOneMinute($timezoneTest->format('Y-m-d H:i:s'), $formatted_string, 'Y-m-d H:i:s'); - $unix_timestamp = EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start', true); - $this->assertDateWithinOneMinute($timezoneTest->format('U'), $unix_timestamp, 'U'); - } - - - - /** - * If the site time format doesn't include seconds (which it doesn't, by default) - * then EEM_Base::current_time_for_query() truncates them - * @group 10869 - */ - public function test_current_time_for_query__ignore_minutes(){ - $formats = EE_Registry::instance()->load_model('Datetime')->get_formats_for('DTT_EVT_start'); - $this->assertEquals( - Datetime::createFromFormat( - 'Y-m-d H:i', - gmdate( 'Y-m-d H:i' ) - ), - DateTime::createFromFormat( - implode(' ', $formats - ), - EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start') - ) - ); - } - - /** - * If the site time format doesn't include seconds (which it doesn't, by default) - * then EEM_Base::current_time_for_query() truncates them - * @group 10869 - */ - public function test_current_time_for_query__timestamp(){ - $formats = EE_Registry::instance()->load_model('Datetime')->get_formats_for('DTT_EVT_start'); - $datetime = new DateTime(); - $datetime->setTimestamp( - EEM_Datetime::instance()->current_time_for_query('DTT_EVT_start', true) - ); - $this->assertDateWithinOneMinute( - time(), - $datetime->format('U'), - 'U' - ); - } - - - - /** - * @group 341 - * @since 4.6.x - */ - public function test_convert_datetime_for_query() - { - EEM_Datetime::reset(); - //baselines for testing with - //baseline DateTime object for testing - $now = new DateTime("now"); - $timezoneTest = new DateTime("now", new DateTimeZone('America/Vancouver')); - $timezones_to_test = array( - 'Asia/Singapore', - 'America/Denver', - ); - $original_timezone = get_option('timezone_string'); - $original_offset = get_option('gmt_offset'); - foreach ($timezones_to_test as $timezone) { - //change the timezone set in wp options to something that has a positive offset - update_option('timezone_string', $timezone); - //initialize EEM_Datetime and EE_Datetime_Field settings for caches - $this->factory->datetime->create(array('formats' => array('F j, Y', 'g:i a'), 'timezone' => 'UTC')); - //test getting correctly formatted string for matching incoming format with defaults in WP - //options - $converted = EEM_Datetime::instance() - ->convert_datetime_for_query('DTT_EVT_start', $now->format('F j, Y g:i a'), - 'F j, Y g:i a', 'UTC'); - $this->assertDateWithinOneMinute( - $now->format('F j, Y g:i a'), - $converted->format('F j, Y g:i a'), - 'F j, Y g:i a', - sprintf('Dates not within one minute for timezone: %s', $timezone) - ); - //test getting correctly formatted string for different incoming format in same timezone. - $converted = EEM_Datetime::instance() - ->convert_datetime_for_query('DTT_EVT_start', $now->format('Y-m-d H:i:s'), - 'Y-m-d H:i:s', 'UTC'); - $this->assertDateWithinOneMinute( - $now->format('F j, Y g:i a'), - $converted->format('F j, Y g:i a'), - 'F j, Y g:i a', - sprintf('Dates not within one minute for timezone tested: %s', $timezone) - ); - //test getting correctly formatted string for different incoming format in different incoming timezone. - $converted = EEM_Datetime::instance() - ->convert_datetime_for_query('DTT_EVT_start', $timezoneTest->format('Y-m-d H:i:s'), - 'Y-m-d H:i:s', 'America/Vancouver'); - $this->assertDateWithinOneMinute( - $now->format('F j, Y g:i a'), - $converted->format('F j, Y g:i a'), - 'F j, Y g:i a', - sprintf('Dates not within one minute for timezone: %s', $timezone)); - //test getting correctly formatted string for unix_timestamp format. - $converted = EEM_Datetime::instance()->convert_datetime_for_query('DTT_EVT_start', time(), 'U'); - $this->assertDateWithinOneMinute( - $now->format('F j, Y g:i a'), - $converted->format('F j, Y g:i a'), - 'F j, Y g:i a', - sprintf('Timezone tested: %s', $timezone) - ); - //test getting correctly formatted string for current_time('mysql') format. - $converted = EEM_Datetime::instance() - ->convert_datetime_for_query('DTT_EVT_start', current_time('mysql'), - 'Y-m-d H:i:s'); - $this->assertDateWithinOneMinute( - $now->format('F j, Y g:i a'), - $converted->format('F j, Y g:i a'), - 'F j, Y g:i a', - sprintf('Dates not within one minute for timezone: %s', $timezone) - ); - //repeat above tests when internals on EE_Datetime_Field have been modified by new - //datetime creation. - $this->factory->datetime->create(array( - 'formats' => array('d/m/Y', 'h:i a'), - 'timezone' => 'America/Vancouver', - )); - //test getting correctly formatted string for matching incoming format with what is currently - //set - $converted = EEM_Datetime::instance() - ->convert_datetime_for_query('DTT_EVT_start', $timezoneTest->format('U'), 'U', - 'America/Vancouver'); - $this->assertDateWithinOneMinute( - $timezoneTest->format('d/m/Y h:i a'), - $converted->format('d/m/Y h:i a'), - 'd/m/Y h:i a', - sprintf('Dates not within one minute for timezone: %s', $timezone) - ); - //test getting correctly formatted string for different incoming format in same timezone. - $converted = EEM_Datetime::instance() - ->convert_datetime_for_query('DTT_EVT_start', $timezoneTest->format('Y-m-d H:i:s'), - 'Y-m-d H:i:s', 'America/Vancouver'); - $this->assertDateWithinOneMinute( - $timezoneTest->format('d/m/Y h:i a'), - $converted->format('d/m/Y h:i a'), - 'd/m/Y h:i a', - sprintf('Dates not within one minute for timezone tested: %s', $timezone) - ); - //test getting correctly formatted string for different incoming format in different incoming timezone. - $converted = EEM_Datetime::instance() - ->convert_datetime_for_query('DTT_EVT_start', $now->format('U'), 'U', 'UTC'); - $this->assertDateWithinOneMinute( - $timezoneTest->format('d/m/Y h:i a'), - $converted->format('d/m/Y h:i a'), - 'd/m/Y h:i a', - sprintf('Dates not within one minute for timezone tested: %s', $timezone) - ); - //test getting correctly formatted string for time() format. - $converted = EEM_Datetime::instance()->convert_datetime_for_query('DTT_EVT_start', time(), 'U'); - $this->assertDateWithinOneMinute( - $timezoneTest->format('d/m/Y h:i a'), - $converted->format('d/m/Y h:i a'), - 'd/m/Y h:i a', - sprintf('Dates not within one minute for timezone tested: %s', $timezone) - ); - //test getting correctly formatted string for current_time('mysql') format. - $converted = EEM_Datetime::instance() - ->convert_datetime_for_query('DTT_EVT_start', current_time('mysql'), - 'Y-m-d H:i:s'); - $this->assertDateWithinOneMinute( - $timezoneTest->format('d/m/Y h:i a'), - $converted->format('d/m/Y h:i a'), - 'd/m/Y h:i a', - sprintf('Dates not within one minute for timezone tested: %s', $timezone) - ); - } - update_option('timezone_string', $original_timezone); - update_option('gmt_offset', $original_offset); - } - - - - public function test_alter_query_params_to_only_include_mine__logged_in() - { - global $current_user; - //setup our user and set as current user. - $user = $this->factory->user->create_and_get(); - $this->assertInstanceOf('WP_User', $user); - $user->add_role('administrator'); - $current_user = $user; - $this->assertTrue(is_user_logged_in()); - $this->assertEquals( - array( - array( - 'QST_wp_user' => get_current_user_id(), - ), - ), - EEM_Question::instance()->alter_query_params_to_only_include_mine()); - } - - - - public function test_alter_query_params_to_only_include_mine__not_logged_in() - { - $this->assertFalse(is_user_logged_in()); - $this->assertEquals( - array( - array( - 'QST_wp_user' => get_current_user_id(), - ), - ), - EEM_Question::instance()->alter_query_params_to_only_include_mine()); - } - - - - public function test_alter_query_params_to_only_include_mine__across_model_chain_once() - { - $this->assertFalse(is_user_logged_in()); - $this->assertEquals( - array( - array( - 'Event.EVT_wp_user' => get_current_user_id(), - ), - ), - EEM_Registration::instance()->alter_query_params_to_only_include_mine()); - } - - - - public function test_alter_query_params_to_only_include_mine__across_model_chain_twice() - { - $this->assertFalse(is_user_logged_in()); - $this->assertEquals( - array( - array( - 'Registration.Event.EVT_wp_user' => get_current_user_id(), - ), - ), - EEM_Transaction::instance()->alter_query_params_to_only_include_mine()); - } - - - - /** - * @group 10083 - */ - public function test_alter_query_params_to_restrict_by_ID__simple_id() - { - $e = $this->new_model_obj_with_dependencies('Event'); - $query_params = EEM_Event::instance()->alter_query_params_to_restrict_by_ID($e->ID()); - $e_found = EEM_Event::instance()->get_one($query_params); - $this->assertEquals($e, $e_found); - } - - - - /** - * @group 10083 - */ - public function test_alter_query_params_to_restrict_by_ID__get_index_primary_key_string() - { - $e = $this->new_model_obj_with_dependencies('Event'); - $query_params = EEM_Event::instance()->alter_query_params_to_restrict_by_ID( - EEM_Event::instance()->get_index_primary_key_string( - $e->model_field_array() - ) - ); - $e_found = EEM_Event::instance()->get_one($query_params); - $this->assertEquals($e, $e_found); - } - - - - /** - * Checks that we can correctly apply backend read caps where there is only - * one cap controlling access to the model - * - * @group model_caps - */ - public function test_get_all__caps_admin_read__basic() - { - $this->assertEquals(0, EEM_Transaction::instance()->count()); - $this->new_typical_transaction(); - $current_user = $this->_ensure_current_user_set(); - //let's test first on transactions, which just have a single cap controlling access - //which the current user doesn't have so nothing should be found - $this->assertEquals(0, EEM_Transaction::instance()->count(array('caps' => EEM_Base::caps_read_admin))); - //now give the user permission to access transactions and make sure he can - $current_user->add_cap('ee_read_transactions'); - $this->assertEquals(EEM_Transaction::instance()->count(), - EEM_Transaction::instance()->count(array('caps' => EEM_Base::caps_read_admin))); - } - - - - /** - * Checks that we can correctly apply backend read caps where there are two - * caps controlling access to the model: the basic cap (eg 'ee_read_registrations') - * and the 'others' cap (eg 'ee_read_others_registrations' ) - * - * @group model_caps - */ - public function test_get_all__caps_admin_read__basic_and_others() - { - $current_user = $this->_ensure_current_user_set(); - $mtg_mine = $this->new_model_obj_with_dependencies('Message_Template_Group', - array('MTP_user_id' => $current_user->ID, 'MTP_is_global' => false)); - $mtg_others = $this->new_model_obj_with_dependencies('Message_Template_Group', - array('MTP_user_id' => $current_user->ID + 1, 'MTP_is_global' => false)); - //current user can't access messages - $this->assertEquals(0, - EEM_Message_Template_Group::instance()->count(array('caps' => EEM_Base::caps_read_admin))); - //ok now allow them to see their own messages - $current_user->add_cap('ee_read_messages'); - $mtgs_i_can_see_now = EEM_Message_Template_Group::instance() - ->get_all(array('caps' => EEM_Base::caps_read_admin)); - $this->assertEquals(1, count($mtgs_i_can_see_now)); - $first_mtg_i_can_see_now = reset($mtgs_i_can_see_now); - $this->assertEquals($mtg_mine, $first_mtg_i_can_see_now); - //ok now allowthem to see others non-global messages (tesing global-related-caps should happen on EEM_Message_template_Group_Test) - $current_user->add_cap('ee_read_others_messages'); - $mtgs_i_can_see_now = EEM_Message_Template_Group::instance()->get_all(array( - 'caps' => EEM_Base::caps_read_admin, - array('MTP_is_global' => false), - )); - $this->assertEquals(2, count($mtgs_i_can_see_now)); - $first_mtg_i_can_see_now = reset($mtgs_i_can_see_now); - $this->assertEquals($mtg_mine, $first_mtg_i_can_see_now); - $last_mtg_i_can_see_now = end($mtgs_i_can_see_now); - $this->assertEquals($mtg_others, $last_mtg_i_can_see_now); - } - - - - /** - * Checks that we can correctly apply backend read caps where there are three - * caps controlling access to the model: the basic cap (eg 'ee_read_events') - * and the 'others' cap (eg 'ee_read_others_events' ) and the - * 'private' cap (eg 'ee_read_private_events') - * - * @group model_caps - */ - public function test_get_all__caps_admin_read__basic_others_and_private() - { - $current_user = $this->_ensure_current_user_set(); - $my_e = $this->new_model_obj_with_dependencies('Event', - array('EVT_wp_user' => $current_user->ID, 'status' => 'publish')); - $others_public_e = $this->new_model_obj_with_dependencies('Event', - array('EVT_wp_user' => $current_user->ID + 1, 'status' => 'publish')); - $others_private_e = $this->new_model_obj_with_dependencies('Event', - array('EVT_wp_user' => $current_user->ID + 1, 'status' => 'private')); - //although there are 3 events, the current user shouldn't have permission to see any in the admin - $this->assertEquals(3, EEM_Event::instance()->count()); - $this->assertEquals(0, EEM_Event::instance()->count(array('caps' => EEM_Base::caps_read_admin))); - //ok give them the cap to view their own - $current_user->add_cap('ee_read_events'); - $events_i_can_see = EEM_Event::instance()->get_all(array('caps' => EEM_Base::caps_read_admin)); - $this->assertEquals(1, count($events_i_can_see)); - $first_event_i_can_see = reset($events_i_can_see); - $this->assertEquals($my_e, $first_event_i_can_see); - //ok now allowthem to see others, but not others private events - $current_user->add_cap('ee_read_others_events'); - $events_i_can_see = EEM_Event::instance()->get_all(array('caps' => EEM_Base::caps_read_admin)); - $this->assertEquals(2, count($events_i_can_see)); - $first_event_i_can_see = reset($events_i_can_see); - $this->assertEquals($my_e, $first_event_i_can_see); - $second_event_i_can_see = next($events_i_can_see); - $this->assertEquals($others_public_e, $second_event_i_can_see); - //ok now allowthem to see others private events - $current_user->add_cap('ee_read_private_events'); - $events_i_can_see = EEM_Event::instance()->get_all(array( - 'caps' => EEM_Base::caps_read_admin, - 'order_by' => array('EVT_ID' => 'ASC'), - )); - $this->assertEquals(3, count($events_i_can_see)); - $first_event_i_can_see = reset($events_i_can_see); - $this->assertEquals($my_e, $first_event_i_can_see); - $second_event_i_can_see = next($events_i_can_see); - $this->assertEquals($others_public_e, $second_event_i_can_see); - $second_event_i_can_see = next($events_i_can_see); - $this->assertEquals($others_private_e, $second_event_i_can_see); - } - - - - /** - * Checks that we can correctly apply FRONTEND read caps where there are three - * caps controlling access to the model: the basic cap (eg 'ee_read_events') - * and the 'others' cap (eg 'ee_read_others_events' ) and the - * 'private' cap (eg 'ee_read_private_events') - * - * @group model_caps - */ - public function test_get_all__caps_read_read__basic_others_and_private() - { - $others_public_e = $this->new_model_obj_with_dependencies('Event', - array('EVT_wp_user' => 45678, 'status' => 'publish')); - $others_private_e = $this->new_model_obj_with_dependencies('Event', - array('EVT_wp_user' => 3456, 'status' => 'private')); - $others_draft_e = $this->new_model_obj_with_dependencies('Event', - array('EVT_wp_user' => 1234, 'status' => 'draft')); - //although there are 3 events, the current user shouldn't have permission to see any in the admin - $this->assertEquals(3, EEM_Event::instance()->count()); - $events_i_can_see = EEM_Event::instance()->get_all(array('caps' => EEM_Base::caps_read)); - $this->assertEquals(1, count($events_i_can_see)); - $first_event_i_can_see = reset($events_i_can_see); - $this->assertEquals($others_public_e, $first_event_i_can_see); - //ok great. now let's authenticate and create some events for the authenticated user - $current_user = $this->_ensure_current_user_set(); - //ok give them the cap to view their own - $current_user->add_cap('ee_read_events'); - $my_e = $this->new_model_obj_with_dependencies('Event', - array('EVT_wp_user' => $current_user->ID, 'status' => 'publish')); - $my_private_e = $this->new_model_obj_with_dependencies('Event', - array('EVT_wp_user' => $current_user->ID, 'status' => 'private')); - $this->assertEquals(5, EEM_Event::instance()->count()); - $events_i_can_see = EEM_Event::instance()->get_all(array( - 'caps' => EEM_Base::caps_read, - 'order_by' => array('EVT_ID' => 'ASC'), - )); - $this->assertEquals(3, count($events_i_can_see)); - $first_event_i_can_see = reset($events_i_can_see); - $this->assertEquals($others_public_e, $first_event_i_can_see); - $second_event_i_can_see = next($events_i_can_see); - $this->assertEquals($my_e, $second_event_i_can_see); - $third_event_i_can_see = next($events_i_can_see); - $this->assertEquals($my_private_e, $third_event_i_can_see); - //ok great. give them the cap to view others - $current_user->add_cap('ee_read_others_events'); - $events_i_can_see = EEM_Event::instance()->get_all(array( - 'caps' => EEM_Base::caps_read, - 'order_by' => array('EVT_ID' => 'ASC'), - )); - $this->assertEquals(4, count($events_i_can_see)); - $first_event_i_can_see = reset($events_i_can_see); - $this->assertEquals($others_public_e, $first_event_i_can_see); - $second_event_i_can_see = next($events_i_can_see); - $this->assertEquals($others_draft_e, $second_event_i_can_see); - $third_event_i_can_see = next($events_i_can_see); - $this->assertEquals($my_e, $third_event_i_can_see); - $fourth_event_i_can_see = next($events_i_can_see); - $this->assertEquals($my_private_e, $fourth_event_i_can_see); - //ok now allowthem to see others, but not others private events - $current_user->add_cap('ee_read_others_events'); - $events_i_can_see = EEM_Event::instance()->get_all(array( - 'caps' => EEM_Base::caps_read, - 'order_by' => array('EVT_ID' => 'ASC'), - )); - $this->assertEquals(4, count($events_i_can_see)); - $first_event_i_can_see = reset($events_i_can_see); - $this->assertEquals($others_public_e, $first_event_i_can_see); - $second_event_i_can_see = next($events_i_can_see); - $this->assertEquals($others_draft_e, $second_event_i_can_see); - $third_event_i_can_see = next($events_i_can_see); - $this->assertEquals($my_e, $third_event_i_can_see); - $fourth_event_i_can_see = next($events_i_can_see); - $this->assertEquals($my_private_e, $fourth_event_i_can_see); - //ok now allowthem to see others private events - $current_user->add_cap('ee_read_private_events'); - $events_i_can_see = EEM_Event::instance()->get_all(array( - 'caps' => EEM_Base::caps_read, - 'order_by' => array('EVT_ID' => 'ASC'), - )); - $this->assertEquals(5, count($events_i_can_see)); - $first_event_i_can_see = reset($events_i_can_see); - $this->assertEquals($others_public_e, $first_event_i_can_see); - $second_event_i_can_see = next($events_i_can_see); - $this->assertEquals($others_private_e, $second_event_i_can_see); - $third_event_i_can_see = next($events_i_can_see); - $this->assertEquals($others_draft_e, $third_event_i_can_see); - $fourth_event_i_can_see = next($events_i_can_see); - $this->assertEquals($my_e, $fourth_event_i_can_see); - $fifth_event_i_can_see = next($events_i_can_see); - $this->assertEquals($my_private_e, $fifth_event_i_can_see); - } - - - - /** - * Makes sure the current user global is set and returns whoever that is - * - * @global WP_User $current_user - * @return WP_User - */ - protected function _ensure_current_user_set() - { - global $current_user; - if ( ! $current_user instanceof WP_User || ($current_user instanceof WP_User && $current_user->ID == 0)) { - $current_user = $this->factory->user->create_and_get(); - } - return $current_user; - } - - - - /** - * Tests that when we get rows from the database and a secondary table has no row, - * but the primary one does, that the fields for the secondary table are given - * DEFAULT values instead of NULLs - * - * @group 7634 - */ - public function test_if_no_meta_row_use_defaults_not_nulls() - { - $e = $this->new_model_obj_with_dependencies('Event'); - //now use wpdb to directly delete its meta row - global $wpdb; - $deletions = $wpdb->delete(EEM_Event::instance()->second_table(), array('EVT_ID' => $e->ID()), array('%d')); - $this->assertEquals(1, $deletions); - //now forget about the old event object we had, we want to see what happens when we fetch it again - EEM_Event::reset(); - $incomplete_e = EEM_Event::instance()->get_one_by_ID($e->ID()); - $actual_row = EEM_Event::instance()->get_all_wpdb_results(array(array('EVT_ID' => $e->ID()))); - $a_field_from_meta_table = EEM_Event::instance()->field_settings_for('EVT_display_ticket_selector'); - $another_field_from_meta_table = EEM_Event::instance()->field_settings_for('EVT_additional_limit'); - $this->assertEquals($a_field_from_meta_table->get_default_value(), - $incomplete_e->get('EVT_display_ticket_selector')); - $this->assertTrue(null !== $incomplete_e->get('EVT_display_ticket_selector')); - $this->assertEquals($another_field_from_meta_table->get_default_value(), - $incomplete_e->get('EVT_additional_limit')); - } - - - - /** - * Tests that if we are joining to a table that has no entries matching the query, - * but the primary table does that we don't create model objects for the non-existent - * row, but we do still create model objects for the row that did exist. - * - * @group 7634 - */ - public function test_get_all_if_related_model_blank_use_nulls() - { - $price_sans_price_type = EE_Price::new_instance(array( - 'PRC_name' => 'original', - 'PRT_ID' => EEM_Price_Type::instance()->count() + 1, - )); - $price_sans_price_type->save(); - $fetched_price = EEM_Price::reset()->get_one(array( - array('PRC_ID' => $price_sans_price_type->ID()), - 'force_join' => array('Price_Type'), - )); - $this->assertInstanceOf('EE_Price', $fetched_price); - $this->assertEquals(null, $fetched_price->type_obj()); - } - - - - /** - * Should reproduce issue 7791 - * - * @group 7791 - */ - public function test_create_question_options() - { - foreach (EE_Registry::instance()->non_abstract_db_models as $model_name => $model_classname) { - $model = EE_Registry::instance()->load_model($model_name); - $question_option = $this->new_model_obj_with_dependencies($model_name); - $this->assertInstanceOf('EE_' . $model_name, $question_option); - //make sure this model is queryable and when we fetch its items that there's no errors - $model->get_all(); - } - } - - - - /** - * @since 4.6.x - */ - public function test_next_x() - { - //create 5 events for testing with. - $events = $this->factory->event->create_many(5); - //grab the first event in the list as the reference - $event = reset($events); - $this->assertInstanceOf('EE_Event', $event); - //test method retrieving objects - $next_events = EEM_Event::instance()->next_x($event->ID(), 'EVT_ID', 4); - $this->assertEquals(4, count($next_events)); - $this->assertInstanceOf('EE_Event', reset($next_events)); - //test retrieving just ids - $next_events = EEM_Event::instance()->next_x($event->ID(), 'EVT_ID', 4, array(), 'EVT_ID'); - $this->assertEquals(4, count($next_events)); - $this->assertTrue(array_key_exists('EVT_ID', $next_events[0])); - } - - - - /** - * @since 4.6.x - */ - public function test_previous_x() - { - //create 5 events for testing with. - $events = $this->factory->event->create_many(5); - //grab the last event in the list as the reference - $event = end($events); - $this->assertInstanceOf('EE_Event', $event); - //test method retrieving objects - $previous_events = EEM_Event::instance()->previous_x($event->ID(), 'EVT_ID', 4); - $this->assertEquals(4, count($previous_events)); - $this->assertInstanceOf('EE_Event', reset($previous_events)); - //test retrieving just ids - $previous_events = EEM_Event::instance()->previous_x($event->ID(), 'EVT_ID', 4, array(), 'EVT_ID'); - $this->assertEquals(4, count($previous_events)); - $this->assertTrue(array_key_exists('EVT_ID', $previous_events[3])); - } - - - - /** - * @since 4.6.x - */ - public function test_next() - { - //create 5 events for testing with. - $events = $this->factory->event->create_many(5); - //grab the first event in the list as the reference - $event = reset($events); - $this->assertInstanceOf('EE_Event', $event); - //test method retrieving object - $next_event = EEM_Event::instance()->next($event->ID()); - $this->assertInstanceOf('EE_Event', $next_event); - $this->assertEquals($event->ID() + 1, $next_event->ID()); - //test retrieving just ids - $next_event = EEM_Event::instance()->next($event->ID(), 'EVT_ID', array(), 'EVT_ID'); - $this->assertTrue(array_key_exists('EVT_ID', $next_event)); - $this->assertEquals($event->ID() + 1, $next_event['EVT_ID']); - } - - - - /** - * @since 4.6.x - */ - public function test_previous() - { - //create 5 events for testing with. - $events = $this->factory->event->create_many(5); - //grab the last event in the list as the reference - $event = end($events); - $this->assertInstanceOf('EE_Event', $event); - //test method retrieving object - $previous_event = EEM_Event::instance()->previous($event->ID()); - $this->assertInstanceOf('EE_Event', $previous_event); - $this->assertEquals($event->ID() - 1, $previous_event->ID()); - //test retrieving just ids - $previous_event = EEM_Event::instance()->previous($event->ID(), 'EVT_ID', array(), 'EVT_ID'); - $this->assertTrue(array_key_exists('EVT_ID', $previous_event)); - $this->assertEquals($event->ID() - 1, $previous_event['EVT_ID']); - } - - - - /** - * checks that the BETWEEN operator works ok - * - * @group 8187 - */ - public function test_get_all__between() - { - EEM_Event::instance()->get_all(array( - array( - 'Datetime.DTT_EVT_start' => array('BETWEEN', array('2015-03-02 00:00:00', '2016-03-04 00:00:00')), - ), - )); - $this->assertTrue(true); - } - - - - /** - * @group 8241 - */ - public function test_get_IDs__empty_ID() - { - $e1 = $this->new_model_obj_with_dependencies('Event', array(), false); - $e2 = $this->new_model_obj_with_dependencies('Event', array(), false); - $this->assertEquals(array(), EEM_Event::instance()->get_IDs(array($e1, $e2), true)); - } - - - - /** - * @group 8241 - */ - public function test_get_IDS() - { - $e1 = $this->new_model_obj_with_dependencies('Event', array()); - $e2 = $this->new_model_obj_with_dependencies('Event', array()); - $this->assertEquals(array($e1->ID(), $e2->ID()), EEM_Event::instance()->get_IDs(array($e1, $e2), true)); - } - - - - /** - * @group 9389 - */ - public function test_get_all__automatic_group_by() - { - $this->assertEquals(2, EEM_Question_Group::instance()->count()); - $qsgs = EEM_Question_Group::instance()->get_all( - array( - 'force_join' => array('Question'), - 'limit' => array(2, 2),//grab 2 but offset by 2 - ) - ); - //so there are only 2 question groups, and we offset by 2. - //so we shouldn't see any right? - $this->assertEmpty($qsgs); - } - - - - /** - * Verifies that the EEM_Base::$_model_query_blog_id is not set until any model is instantiated and that if the - * blog id is explicitly changed after instantiation (via the setter), future models instantiated will still retain - * the blog id changed to. - * - * @group 9743 - */ - public function test_model_query_blog_id_set_on_instantiation() - { - //instantiate a model and verify that sets to current_blog_id(); - $attendee = EEM_Attendee::instance(); - $this->assertEquals(EEM_Base::get_model_query_blog_id(), get_current_blog_id()); - //verify blog_id changes - EEM_Base::set_model_query_blog_id(2); - $this->assertEquals(EEM_Base::get_model_query_blog_id(), 2); - //verify that any NEW models instantiated retain that change. - $question = EEM_Question::reset(); - $this->assertEquals(EEM_Base::get_model_query_blog_id(), 2); - //make sure we restore the models to blog 1 for future tests. - EEM_Base::set_model_query_blog_id(1); - } - - - - /** - * @group 9566 - */ - public function test_is_logic_query_param_key() - { - $this->assertTrue( EEM_Answer::instance()->is_logic_query_param_key( 'OR' ) ); - $this->assertTrue( EEM_Answer::instance()->is_logic_query_param_key( 'NOT*' ) ); - $this->assertTrue( EEM_Answer::instance()->is_logic_query_param_key( 'AND*other-condition' ) ); - $this->assertFalse( EEM_Answer::instance()->is_logic_query_param_key( 'ATT_fname' ) ); - $this->assertFalse( EEM_Answer::instance()->is_logic_query_param_key( 'Registration.REG_date' ) ); - $this->assertFalse( EEM_Answer::instance()->is_logic_query_param_key( 'ORG_name' ) ); - - } - - - /** - * @group customselects - * @throws EE_Error - * @throws InvalidArgumentException - * @throws ReflectionException - * @throws InvalidDataTypeException - * @throws InvalidInterfaceException - * @throws Exception - */ - public function testExtraSelects() - { - //setup some data in the db - $attendee = $this->factory->attendee->create(); - $this->factory->registration->create_many(3, array('ATT_ID' => $attendee->ID())); - EEM_Attendee::reset(); - EEM_Registration::reset(); - $attendees = EEM_Attendee::instance()->get_all( - array( - 'extra_selects' => array( - 'registration_count' => array('Registration.REG_ID', 'count', '%d') - ) - ) - ); - $this->assertCount(1, $attendees); - $attendee = reset($attendees); - $this->assertInstanceOf('EE_Attendee', $attendee); - $this->assertEquals(3, $attendee->getCustomSelect('registration_count')); - } - -} - -// End of file EEM_Base_Test.php -// Location: testcases/core/db_models/EEM_Base_Test.php diff --git a/tests/testcases/core/db_models/EEM_Base_Using_Mock_Model_Test.php b/tests/testcases/core/db_models/EEM_Base_Using_Mock_Model_Test.php deleted file mode 100644 index ab33963d4aa..00000000000 --- a/tests/testcases/core/db_models/EEM_Base_Using_Mock_Model_Test.php +++ /dev/null @@ -1,166 +0,0 @@ -_stop_pretending_addon_hook_time(); - $this->_pretend_addon_hook_time(); - $this->assertArrayDoesNotContain('EEM_Mock', EE_Registry::instance()->non_abstract_db_models); - $this->assertArrayDoesNotContain('EEM_Mock', EE_Registry::instance()->models); - //register it for realz - EE_Register_Model::register( - 'Mock', - array( - 'model_paths' => array(EE_MOCKS_DIR . 'core/db_models/'), - 'class_paths' => array(EE_MOCKS_DIR . 'core/db_classes/'), - ) - ); - //whitelist the table we're about to add - add_filter('FHEE__EEH_Activation__create_table__short_circuit', array($this, 'dont_short_circuit_mock_table'), 25, 3); - //add table from related DMS - EEH_Activation::create_table('esp_mock', ' - MCK_ID int(10) unsigned NOT NULL AUTO_INCREMENT, - MCK_value varchar(100), - MCK_datetime DATETIME NOT NULL DEFAULT "0000-00-00 00:00:00", - PRIMARY KEY (MCK_ID)' - ); - $this->assertTableExists('esp_mock'); - EE_System::instance()->load_core_configuration(); - $this->assertArrayContains('EEM_Mock', EE_Registry::instance()->non_abstract_db_models); - $this->assertArrayContains('EEM_Mock', EE_Registry::instance()->models); - } - - - - /** - * OK's the creation of the esp_new_addon table, because this hooks in AFTER EE_UNitTestCase's callback on this same hook - * - * @param bool $short_circuit - * @param string $table_name - * @param string $create_sql - * @return array - */ - public function dont_short_circuit_mock_table($short_circuit = false, $table_name = '', $create_sql = '') - { - $table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true); - if ($table_name == 'esp_mock' && ! $table_analysis->tableExists($table_name)) { - // echo "\r\n\r\nDONT short circuit $sql"; - //it's not altering. it's ok to allow this - return false; - } else { - // echo "3\r\n\r\n short circuit:$sql"; - return $short_circuit; - } - } - - - - /** - */ - public function test_get_all() - { - //there should be nothing in here - $this->assertFalse(EEM_Mock::instance()->exists(array())); - $mock_thing = EE_Mock::new_instance( - array( - 'MCK_value' => 'foobar', - ) - ); - $id = $mock_thing->save(); - $found_mock_thing = EEM_Mock::instance()->get_one(); - $this->assertEquals($mock_thing, $found_mock_thing); - } - - - - /** - */ - public function test_get_qualified_columns_for_all_fields__as_string() - { - $this->assertEquals( - 'Mock.MCK_ID, Mock.MCK_value, Mock.MCK_datetime', - EEM_Mock::instance()->get_qualified_columns_for_all_fields() - ); - } - - - - /** - */ - public function test_get_qualified_columns_for_all_fields__as_array() - { - $this->assertEquals( - array( - 'Mock.MCK_ID', - 'Mock.MCK_value', - 'Mock.MCK_datetime', - ), - EEM_Mock::instance()->get_qualified_columns_for_all_fields('', false) - ); - } - - - - /** - */ - public function test_get_qualified_columns_for_all_fields__with_prefix() - { - $this->assertEquals( - array( - 'Extra_Meta__Mock.MCK_ID', - 'Extra_Meta__Mock.MCK_value', - 'Extra_Meta__Mock.MCK_datetime', - ), - EEM_Mock::instance()->get_qualified_columns_for_all_fields('Extra_Meta', false) - ); - } - - - - /** - * Make up a really long model chain. It doesn't need to be actual model names (at least right now; if that - * ever becomes a requirement then we'll need to hae EEM_Mock actually related to some more mock models) - */ - public function test_get_qualified_columns_for_all_fields__with_big_prefix() - { - $this->assertEquals( - array( - 'Some__Model__Chain__Mock.MCK_ID', - 'Some__Model__Chain__Mock.MCK_value', - 'Some__Model__Chain__Mock.MCK_datetime', - ), - EEM_Mock::instance()->get_qualified_columns_for_all_fields('Some.Model.Chain', false) - ); - } - - - - public function tearDown() - { - EE_Register_Model::deregister('Mock'); - EE_System::instance()->load_core_configuration(); - $this->assertArrayDoesNotContain('EEM_Mock', EE_Registry::instance()->non_abstract_db_models); - $this->assertArrayDoesNotContain('EEM_Mock', EE_Registry::instance()->models); - $this->_stop_pretending_addon_hook_time(); - parent::tearDown(); - } - - -} -// End of file EEM_Base_Using_Mock_Model_Test.php -// Location: tests\testcases\core\db_models/EEM_Base_Using_Mock_Model_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/EEM_CPT_Base_Test.php b/tests/testcases/core/db_models/EEM_CPT_Base_Test.php deleted file mode 100644 index 3a21b033a86..00000000000 --- a/tests/testcases/core/db_models/EEM_CPT_Base_Test.php +++ /dev/null @@ -1,89 +0,0 @@ -assertEquals(0, EEM_Event::instance()->count(array('default_where_conditions' => 'none'))); - $e_normal = $this->new_model_obj_with_dependencies('Event', - array('status' => EEM_CPT_Base::post_status_publish)); - $e_trashed = $this->new_model_obj_with_dependencies('Event', - array('status' => EEM_CPT_Base::post_status_trashed)); - $normal_post = $this->factory->post->create_and_get(array('post_type' => 'monkey')); - //verify the regular post got added correctly - $this->assertNotEquals( 0, $normal_post->ID ); - //now verify we get what we wanted: the normal and trashed event, but not - //the normal post - $events_found = EEM_Event::instance()->get_all(array('default_where_conditions' => 'minimum')); - $this->assertArrayContains($e_normal, $events_found); - $this->assertArrayContains($e_trashed, $events_found); - $this->assertCount(2, $events_found); - //incidentally, lets show the problem of using the 'default_where_conditions' => 'none' - //it WOULD count the normal post. Which is obviously NOT an event! - $this->assertEquals(3, EEM_Event::instance()->count(array('default_where_conditions' => 'none'))); - } - - /** - * Test that when we set the minimum_others where conditions, we don't find trashed cpt items - * for the current model (because we use normal default where conditions for main model), but not for related - * trashed models (because they only use their minimum where conditions) - * -*@group 10260 - */ - public function test_get_minimum_others_where_conditions_during_query() - { - $this->assertEquals(0, EEM_Event::instance()->count(array('default_where_conditions' => 'none'))); - $e_normal = $this->new_model_obj_with_dependencies('Event', - array('status' => EEM_CPT_Base::post_status_publish)); - $e_normal_but_with_trashed_v = $this->new_model_obj_with_dependencies('Event', - array('status' => EEM_CPT_Base::post_status_publish)); - $e_trashed = $this->new_model_obj_with_dependencies('Event', - array('status' => EEM_CPT_Base::post_status_trashed)); - $v_normal = $this->new_model_obj_with_dependencies('Venue', - array('status' => EEM_CPT_Base::post_status_publish)); - $v_trashed = $this->new_model_obj_with_dependencies('Venue', - array('status' => EEM_CPT_Base::post_status_trashed)); - //associate them - $e_normal->_add_relation_to($v_normal, 'Venue'); - $e_normal_but_with_trashed_v->_add_relation_to($v_trashed, 'Venue'); - $e_trashed->_add_relation_to($v_normal, 'Venue'); - //now verify we get what we wanted... - $events_found = EEM_Event::instance()->get_all( - array( - 'force_join' => array( 'Venue' ), - 'default_where_conditions' => \EEM_Base::default_where_conditions_minimum_others - ) - ); - //we should find the normal one because it's not trashed, nor is its venue - $this->assertArrayContains($e_normal, $events_found); - //we should NOT find the trashed event - $this->assertArrayDoesNotContain($e_trashed, $events_found); - //we should find the event that's related to a trashed venue, because - //we should only be applying the MINIMUM where conditions for venues, which don't include their status - $this->assertArrayContains($e_normal_but_with_trashed_v, $events_found); - //and that's it - $this->assertCount(2, $events_found); - } -} diff --git a/tests/testcases/core/db_models/EEM_Change_Log_Test.php b/tests/testcases/core/db_models/EEM_Change_Log_Test.php deleted file mode 100644 index 57cf8b0d9f1..00000000000 --- a/tests/testcases/core/db_models/EEM_Change_Log_Test.php +++ /dev/null @@ -1,50 +0,0 @@ -new_model_obj_with_dependencies( - 'Change_Log', - array( - 'LOG_time' => new DateTime('-2 weeks'), - 'LOG_type' => EEM_Change_Log::type_gateway - ) - ); - $wrong_type = $this->new_model_obj_with_dependencies( - 'Change_Log', - array( - 'LOG_time' => new DateTime('-2 weeks'), - 'LOG_type' => EEM_Change_Log::type_create - ) - ); - $too_new = $this->new_model_obj_with_dependencies( - 'Change_Log', - array( - 'LOG_time' => new DateTime('-1 days'), - 'LOG_type' => EEM_Change_Log::type_gateway - ) - ); - - $result = EEM_Change_Log::instance()->delete_gateway_logs_older_than(new DateTime('-1 weeks')); - $this->assertTrue(EEM_Change_Log::instance()->exists_by_ID( $wrong_type->ID())); - $this->assertTrue(EEM_Change_Log::instance()->exists_by_ID($too_new->ID())); - $this->assertFalse(EEM_Change_Log::instance()->exists_by_ID($delete_me->ID())); - $this->assertEquals( '1', $result ); - - } - - -} -// End of file EEM_Change_Log_Test.php -// Location: ${NAMESPACE}/EEM_Change_Log_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/EEM_Country_Test.php b/tests/testcases/core/db_models/EEM_Country_Test.php deleted file mode 100644 index f02bb057778..00000000000 --- a/tests/testcases/core/db_models/EEM_Country_Test.php +++ /dev/null @@ -1,24 +0,0 @@ -assertFalse( EEM_Country::instance()->exists_by_ID( 'ZZZ' ) ); - $c = $this->new_model_obj_with_dependencies( 'Country' ); - $this->assertEquals( '', EEM_Country::instance()->get_country_name_by_ISO( 'ZZZ' ) ); - $this->assertEquals( $c->name(), EEM_Country::instance()->get_country_name_by_ISO( $c->ID() ) ); - } -} - -// End of file EEM_Country_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/EEM_Datetime_Test.php b/tests/testcases/core/db_models/EEM_Datetime_Test.php deleted file mode 100644 index cf0078cceb9..00000000000 --- a/tests/testcases/core/db_models/EEM_Datetime_Test.php +++ /dev/null @@ -1,441 +0,0 @@ -factory->event->create( array( 'EVT_timezone_string' => 'Australia/Sydney' ) ); - - //for test we want a datetime begining one hour before now and ending now (-1min), and a datetime starting now and ending one hour from now. - $dtt1_start = time() - 60*60*24; - $dtt1_end = time() - 60*60; - $dtt2_start = $dtt1_start + 60*60; - $dtt2_end = $dtt1_end + 60*60*24; - - - $dtt1 = $this->factory->datetime->create( array( 'DTT_EVT_start' => $dtt1_start, 'DTT_EVT_end' => $dtt1_end ) ); - $dtt2 = $this->factory->datetime->create( array( 'DTT_EVT_start' => $dtt2_start, 'DTT_EVT_end' => $dtt2_end ) ); - - //verify - $this->assertInstanceOf( 'EE_Event', $event ); - $this->assertInstanceOf( 'EE_Datetime', $dtt1 ); - $this->assertInstanceOf( 'EE_Datetime', $dtt2 ); - - //attach dtt to event and save - $event->_add_relation_to( $dtt1, 'Datetime' ); - $event->_add_relation_to( $dtt2, 'Datetime' ); - $event->save(); - - //now let's run the method we're checking. - //first NO expiry flag. - $datetimes_on_event = EEM_Datetime::instance()->get_datetimes_for_event_ordered_by_DTT_order( $event->ID() ); - - //we should have all the datetimes returned - $dtt_checked = reset( $datetimes_on_event ); - - $this->assertEquals( 2, count( $datetimes_on_event ) ); - $this->assertInstanceOf( 'EE_Datetime', $dtt_checked ); - $this->assertEquals( $dtt_checked->ID(), $dtt1->ID() ); - - //now let's run the method excluding expired dtts - $datetimes_on_event = EEM_Datetime::instance()->get_datetimes_for_event_ordered_by_DTT_order( $event->ID(), false ); - $second_dtt_chk = reset( $datetimes_on_event ); - - //only one datetime should be returned - $this->assertEquals( 1, count( $datetimes_on_event ) ); - - //we should have the SECOND datetime returned because its the non-expired one. - $this->assertInstanceOf( 'EE_Datetime', $second_dtt_chk ); - $this->assertEquals( $second_dtt_chk->ID(), $dtt2->ID() ); - } - - - - - /** - * Test for get_datetimes_for_event_ordered_by_start_time method - * - * @since 4.5.0 - * - */ - public function test_get_datetimes_for_event_ordered_by_start_time() { - //create an event we'll use - $event = $this->factory->event->create(); - - //let's create three datetimes ( one that started one hour ago and ended now(-1min), one that starts now and ends one hour from now, and one that starts one hour from now and ends two hours from now) - $dtt1start = time() - 60*60; - $dtt1end = time() - 60; - - $dtt2start = $dtt1start + 60*60; - $dtt2end = $dtt1end + 60*60; - $dtt3start = $dtt2start + 60*60; - $dtt3end = $dtt2end + 60*60; - - $dtt1 = $this->factory->datetime->create( array( 'DTT_EVT_start' => $dtt1start, 'DTT_EVT_end' => $dtt1end ) ); - $dtt2 = $this->factory->datetime->create( array( 'DTT_EVT_start' => $dtt2start, 'DTT_EVT_end' => $dtt2end ) ); - $dtt3 = $this->factory->datetime->create( array( 'DTT_EVT_start' => $dtt3start, 'DTT_EVT_end' => $dtt3end ) ); - - //verify - $this->assertInstanceOf( 'EE_Event', $event ); - $this->assertInstanceOf( 'EE_Datetime', $dtt1 ); - $this->assertInstanceOf( 'EE_Datetime', $dtt2 ); - $this->assertInstanceOf( 'EE_Datetime', $dtt3 ); - - //add dtts to event - $event->_add_relation_to( $dtt1, 'Datetime' ); - $event->_add_relation_to( $dtt2, 'Datetime' ); - $event->_add_relation_to( $dtt3, 'Datetime' ); - $event->save(); - - //run the method we are checking with NO expiry flag set (so means we are including expired dtts). - $datetimes_on_event = EEM_Datetime::instance()->get_datetimes_for_event_ordered_by_start_time( $event->ID() ); - - //now let's verify that there are two datetimes returned - $this->assertEquals( 3, count( $datetimes_on_event) ); - - //verify the first datetime = dtt1 (because orderby is supposed to be DTT_EVT_start => ASC ); - $first_dtt = reset( $datetimes_on_event ); - $this->assertInstanceOf( 'EE_Datetime', $first_dtt ); - $this->assertEquals( $first_dtt->ID(), $dtt1->ID() ); - - //k now let's do the same thing as above but this time we DONT' return expired dtts. - //run the method we are checking with NO expiry flag set (so means we are including expired dtts). - $datetimes_on_event = EEM_Datetime::instance()->get_datetimes_for_event_ordered_by_start_time( $event->ID(), false ); - - //now let's verify that there are two datetimes returned (because the dtts should NOT have expired!) - $this->assertEquals( 2, count( $datetimes_on_event) ); - - //verify the first datetime = dtt2 (because orderby is supposed to be DTT_EVT_start => ASC ) AND the datetimes have NOT expired.; - $first_dtt = reset( $datetimes_on_event ); - $this->assertInstanceOf( 'EE_Datetime', $first_dtt ); - $this->assertEquals( $first_dtt->ID(), $dtt2->ID() ); - } - - - - - - /** - * Test the get_datetimes_for_ticket_ordered_by_start_time() method - * @since 4.5.0 - */ - public function test_get_datetimes_for_ticket_ordered_by_start_time() { - //now create a TICKET we'll use. - $ticket = $this->factory->ticket->create(); - - //let's create three datetimes ( one that started one hour ago and ended now (-1min), one that starts now and ends one hour from now, and one that starts one hour from now and ends two hours from now) - $dtt1start = time() - 60*60; - $dtt1end = time() - 60; - - $dtt2start = $dtt1start + 60*60; - $dtt2end = $dtt1end + 60*60; - $dtt3start = $dtt2start + 60*60; - $dtt3end = $dtt2end + 60*60; - - $dtt1 = $this->factory->datetime->create( array( 'DTT_EVT_start' => $dtt1start, 'DTT_EVT_end' => $dtt1end ) ); - $dtt2 = $this->factory->datetime->create( array( 'DTT_EVT_start' => $dtt2start, 'DTT_EVT_end' => $dtt2end ) ); - $dtt3 = $this->factory->datetime->create( array( 'DTT_EVT_start' => $dtt3start, 'DTT_EVT_end' => $dtt3end ) ); - - //verify - $this->assertInstanceOf( 'EE_Datetime', $dtt1 ); - $this->assertInstanceOf( 'EE_Datetime', $dtt2 ); - $this->assertInstanceOf( 'EE_Datetime', $dtt3 ); - $this->assertInstanceOf( 'EE_Ticket', $ticket ); - - //add dtts to ticket - $ticket->_add_relation_to( $dtt1, 'Datetime' ); - $ticket->_add_relation_to( $dtt2, 'Datetime' ); - $ticket->_add_relation_to( $dtt3, 'Datetime' ); - $ticket->save(); - - - //run the method we are checking with NO expiry flag set (so means we are including expired dtts). - $datetimes_on_ticket = EEM_Datetime::instance()->get_datetimes_for_ticket_ordered_by_start_time( $ticket->ID() ); - - //now let's verify that there are three datetimes returned - $this->assertEquals( 3, count( $datetimes_on_ticket) ); - - //verify the first datetime = dtt1 (because orderby is supposed to be DTT_EVT_start => ASC ); - $first_dtt = reset( $datetimes_on_ticket ); - $this->assertInstanceOf( 'EE_Datetime', $first_dtt ); - $this->assertEquals( $first_dtt->ID(), $dtt1->ID() ); - - //k now let's do the same thing as above but this time we DONT' return expired dtts. - //run the method we are checking with NO expiry flag set (so means we are including expired dtts). - $datetimes_on_ticket = EEM_Datetime::instance()->get_datetimes_for_ticket_ordered_by_start_time( $ticket->ID(), false ); - - //now let's verify that there are two datetimes returned (because only 2 of the dtts should NOT have expired!) - $this->assertEquals( 2, count( $datetimes_on_ticket) ); - - //verify the first datetime = dtt2 (because orderby is supposed to be DTT_EVT_start => ASC ) AND the second datetime is the first one that has NOT expired.; - $first_dtt = reset( $datetimes_on_ticket ); - $this->assertInstanceOf( 'EE_Datetime', $first_dtt ); - $this->assertEquals( $first_dtt->ID(), $dtt2->ID() ); - } - - - - - /** - * Test the get_datetimes_for_ticket_ordered_by_DTT_order() method - * @since 4.5.0 - */ - public function test_get_datetimes_for_ticket_ordered_by_DTT_order() { - //create an event and datetime - $ticket = $this->factory->ticket->create(); - - //for test we want a datetime begining one hour before now and ending now (-1min), and a datetime starting now and ending one hour from now. - $dtt1_start = time() - 60*60; - $dtt1_end = time() - 60; - $dtt2_start = $dtt1_start + 60*60; - $dtt2_end = $dtt1_end + 60*60; - - - $dtt1 = $this->factory->datetime->create( array( 'DTT_EVT_start' => $dtt1_start, 'DTT_EVT_end' => $dtt1_end ) ); - $dtt2 = $this->factory->datetime->create( array( 'DTT_EVT_start' => $dtt2_start, 'DTT_EVT_end' => $dtt2_end ) ); - - //verify - $this->assertInstanceOf( 'EE_Ticket', $ticket ); - $this->assertInstanceOf( 'EE_Datetime', $dtt1 ); - $this->assertInstanceOf( 'EE_Datetime', $dtt2 ); - - //attach dtt to ticket and save - $ticket->_add_relation_to( $dtt1, 'Datetime' ); - $ticket->_add_relation_to( $dtt2, 'Datetime' ); - $ticket->save(); - - //now let's run the method we're checking. - //first NO expiry flag. - $datetimes_on_ticket = EEM_Datetime::instance()->get_datetimes_for_ticket_ordered_by_DTT_order( $ticket->ID() ); - - //we should have the datetime returned - $dtt_checked = reset( $datetimes_on_ticket ); - - //check count, it should be two datetimes because expiry ignored. - $this->assertEquals( 2, count( $datetimes_on_ticket ) ); - - //shoudl be first datetime because expiry ignored. - $this->assertInstanceOf( 'EE_Datetime', $dtt_checked ); - $this->assertEquals( $dtt_checked->ID(), $dtt1->ID() ); - - //now let's run the method excluding expired dtts - $datetimes_on_ticket = EEM_Datetime::instance()->get_datetimes_for_ticket_ordered_by_DTT_order( $ticket->ID(), false ); - $second_dtt_chk = reset( $datetimes_on_ticket ); - - //count should be one because expiry considered. - $this->assertEquals( 1, count( $datetimes_on_ticket ) ); - - //first datetime returned should be dtt2 because dtt1 is expired. - $this->assertInstanceOf( 'EE_Datetime', $second_dtt_chk ); - $this->assertEquals( $second_dtt_chk->ID(), $dtt2->ID() ); - } - - - - - /** - * @since 4.6.x - */ - public function test_create_new_blank_datetime() { - //if timezone is empty string then the setUp didn't work correctly. For the purpose of this test - //we want a high positive timezone, so let's force that if necessary - if ( get_option( 'timezone_string' ) != 'Australia/Sydney' ) { - update_option( 'timezone_string', 'Australia/Sydney' ); - EEM_Datetime::reset(); - EEM_Datetime::instance(); - } - - //make sure now is in the timezone we want to test with. - $now = new Datetime( '@' . ( time() + ( DAY_IN_SECONDS * 30 ) ) ); - $now->setTimeZone( new DateTimeZone( EEH_DTT_Helper::get_timezone() ) ); - $now->setTime( '8', '0', '0' ); - $now->setTimeZone( new DateTimeZone( 'America/Toronto' ) ); - - //get the default datetime - $default_date = EEM_Datetime::instance()->create_new_blank_datetime(); - $default_date = reset( $default_date ); - - //assert instance - $this->assertInstanceOf( 'EE_Datetime', $default_date ); - - //set its timezone to match our expected timezone - $default_date->set_timezone( 'America/Toronto' ); - $actual = $default_date->get_DateTime_object( 'DTT_EVT_start'); - - $this->assertInstanceOf( 'DateTime', $actual ); - - //assert timezones are the same - $this->assertEquals( $now->getTimezone(), $actual->getTimeZone() ); - - //assert that we have the correct values on the date... we'll do each part separately to verify. - $this->assertEquals( $now->format('Y'), $actual->format('Y' ) ); - $this->assertEquals( $now->format('m'), $actual->format( 'm' ) ); - $this->assertEquals( $now->format('d'), $actual->format( 'd' ) ); - $this->assertEquals( $now->format('H'), $actual->format( 'H' ) ); - $this->assertEquals( $now->format('i'), $actual->format('i' ) ); - } - - - - public function test_get_dtt_months_and_years() { - //setup some dates we'll use for testing with. - $timezone = new DateTimeZone( 'America/Toronto' ); - $upcoming_start_date = new DateTime( "now +2hours", $timezone ); - $past_start_date = new DateTime( "now -2days", $timezone ); - $current_end_date = new DateTime( "now +2days", $timezone ); - $current = new DateTime( "now", $timezone ); - $formats = array( 'Y-d-m', 'h:i a' ); - $full_format = implode( ' ', $formats ); - - //setup some datetimes to attach to events. - $datetimes = array( - 'expired_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $past_start_date->format( $full_format ), 'DTT_EVT_end' => $past_start_date->format( $full_format), 'timezone' => 'America/Toronto', 'formats' => $formats ) ), - 'upcoming_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $upcoming_start_date->format( $full_format ), 'DTT_EVT_end' => $upcoming_start_date->format( $full_format), 'timezone' => 'America/Toronto', 'formats' => $formats ) ), - 'active_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $current->sub( new DateInterval( "PT2H") )->format( $full_format ), 'DTT_EVT_end' => $current_end_date->add( new DateInterval( "PT2H" ) )->format( $full_format), 'timezone' => 'America/Toronto', 'formats' => $formats ) ), - 'sold_out_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $upcoming_start_date->format( $full_format ), 'DTT_EVT_end' => $upcoming_start_date->format( $full_format), 'DTT_reg_limit' => 10, 'DTT_sold' => 10, 'timezone' => 'America/Toronto', 'formats' => $formats ) ), - 'inactive_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $current->format( $full_format ), 'DTT_EVT_end' => $current_end_date->format( $full_format), 'timezone' => 'America/Toronto', 'formats' => $formats ) ) - ); - - - $events = $this->factory->event->create_many(5); - - //add datetimes to the events. - $events[0]->_add_relation_to( $datetimes['expired_datetime'], 'Datetime' ); - $events[0]->save(); - $events[1]->_add_relation_to( $datetimes['upcoming_datetime'], 'Datetime' ); - $events[1]->save(); - $events[2]->_add_relation_to( $datetimes['active_datetime'], 'Datetime' ); - $events[2]->save(); - $events[3]->_add_relation_to( $datetimes['sold_out_datetime'], 'Datetime' ); - $events[3]->save(); - $events[4]->_add_relation_to( $datetimes['inactive_datetime'], 'Datetime' ); - $events[4]->save(); - - foreach ( $events as $index => $event ) { - if ( $index !== 4 ) { - $event->set('status', 'publish' ); - $event->save(); - } - } - - //run tests for various scenarios. - foreach ( $datetimes as $type => $datetime ) { - switch ( $type ) { - case 'expired_datetime' : - $dtts = EEM_Datetime::instance()->get_dtt_months_and_years( array(), 'expired' ); - $dtt = reset( $dtts ); - $this->assertEquals( 1, count( $dtts ) ); - $this->assertEquals( $past_start_date->format('Y'), $dtt->dtt_year ); - $this->assertEquals( $past_start_date->format('F'), $dtt->dtt_month ); - break; - case 'upcoming_datetime' : - $dtts = EEM_Datetime::instance()->get_dtt_months_and_years( array(), 'upcoming' ); - $dtt = reset( $dtts ); - $this->assertEquals( 1, count( $dtts ) ); - $this->assertEquals( $upcoming_start_date->format('Y'), $dtt->dtt_year ); - $this->assertEquals( $upcoming_start_date->format('F'), $dtt->dtt_month ); - break; - case 'active_datetime' : - $dtts = EEM_Datetime::instance()->get_dtt_months_and_years( array(), 'active' ); - $dtt = reset( $dtts ); - $this->assertEquals( 1, count( $dtts ) ); - $this->assertEquals( $current->format('Y'), $dtt->dtt_year ); - $this->assertEquals( $current->format('F'), $dtt->dtt_month ); - break; - case 'sold_out_datetime' : - $dtts = EEM_Datetime::instance()->get_dtt_months_and_years( array(), 'upcoming' ); - $dtt = reset( $dtts ); - $this->assertEquals( 1, count( $dtts ) ); - $this->assertEquals( $upcoming_start_date->format('Y'), $dtt->dtt_year ); - $this->assertEquals( $upcoming_start_date->format('F'), $dtt->dtt_month ); - break; - case 'inactive_datetime' : - $dtts = EEM_Datetime::instance()->get_dtt_months_and_years( array(), 'inactive' ); - $dtt = reset( $dtts ); - $this->assertEquals( 1, count( $dtts ) ); - $this->assertEquals( $current->format('Y'), $dtt->dtt_year ); - $this->assertEquals( $current->format('F'), $dtt->dtt_month ); - break; - } - } - } - - - /** - * @since 4.8.27.rc.005 - */ - public function test_get_datetime_counts_by_status_and_get_datetime_count_for_status() { - //setup some datetimes for testing with - $upcoming_datetimes = $this->factory->datetime->create_many(5); - //set upcoming datetimes to actually be upcoming! - foreach( $upcoming_datetimes as $datetime ) { - $datetime->set('DTT_EVT_start', time() + 500 ); - $datetime->save(); - } - - //setup some expired datetimes - $expired_datetimes = $this->factory->datetime->create_many(2); - //set expired - foreach( $expired_datetimes as $datetime ) { - $datetime->set( 'DTT_EVT_end', time() - 500 ); - $datetime->set( 'DTT_EVT_start', time() - 1000 ); - $datetime->save(); - } - - //active datetimes - $active_datetime = $this->factory->datetime->create( array( 'DTT_EVT_start' => time() - 500, 'DTT_EVT_end' => time() + 500 ) ); - - //now get the results from the method being tested - $datetimes_count = EEM_Datetime::instance()->get_datetime_counts_by_status(); - - $this->assertTrue( is_array( $datetimes_count ) ); - $this->assertEquals( 1, $datetimes_count[ EE_Datetime::active ] ); - $this->assertEquals( 5, $datetimes_count[ EE_Datetime::upcoming ] ); - $this->assertEquals( 2, $datetimes_count[ EE_Datetime::expired ] ); - - //test just getting a specific status via get_datetime_count_for_status - $this->assertEquals( 5, EEM_Datetime::instance()->get_datetime_count_for_status( EE_Datetime::upcoming ) ); - $this->assertEquals( 1, EEM_Datetime::instance()->get_datetime_count_for_status() ); - $this->assertEquals( 2, EEM_Datetime::instance()->get_datetime_count_for_status( EE_Datetime::expired ) ); - } -} diff --git a/tests/testcases/core/db_models/EEM_Event_Test.php b/tests/testcases/core/db_models/EEM_Event_Test.php deleted file mode 100644 index 88db329d9fa..00000000000 --- a/tests/testcases/core/db_models/EEM_Event_Test.php +++ /dev/null @@ -1,156 +0,0 @@ - $this->factory->datetime->create( array( 'DTT_EVT_start' => $past_start_date->format( $full_format ), 'DTT_EVT_end' => $past_start_date->format( $full_format), 'timezone' => 'America/Toronto', 'formats' => $formats ) ), - 'upcoming_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $upcoming_start_date->format( $full_format ), 'DTT_EVT_end' => $upcoming_start_date->format( $full_format), 'timezone' => 'America/Toronto', 'formats' => $formats ) ), - 'active_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $current->sub( new DateInterval( "PT2H") )->format( $full_format ), 'DTT_EVT_end' => $current_end_date->add( new DateInterval( "PT2H" ) )->format( $full_format), 'timezone' => 'America/Toronto', 'formats' => $formats ) ), - 'sold_out_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $upcoming_start_date->format( $full_format ), 'DTT_EVT_end' => $upcoming_start_date->format( $full_format), 'DTT_reg_limit' => 10, 'DTT_sold' => 10, 'timezone' => 'America/Toronto', 'formats' => $formats ) ), - 'inactive_datetime' => $this->factory->datetime->create( array( 'DTT_EVT_start' => $current->sub( new DateInterval( "PT2H") )->format( $full_format ), 'DTT_EVT_end' => $current_end_date->add( new DateInterval( "PT2H" ) )->format( $full_format), 'timezone' => 'America/Toronto', 'formats' => $formats ) ) - ); - - //setup some events - /** @var EE_Event[] $events */ - $events = $this->factory->event->create_many( '4' ); - - //add datetimes to the events. - $events[0]->_add_relation_to( $datetimes['expired_datetime'], 'Datetime' ); - $events[0]->save(); - $events[1]->_add_relation_to( $datetimes['upcoming_datetime'], 'Datetime' ); - $events[1]->save(); - $events[2]->_add_relation_to( $datetimes['active_datetime'], 'Datetime' ); - $events[2]->save(); - $events[3]->_add_relation_to( $datetimes['sold_out_datetime'], 'Datetime' ); - $events[3]->save(); - - foreach( $events as $event ) { - $event->set('status', 'publish'); - $event->save(); - } - - //one more event that is just going to be inactive - /** @var EE_Event $final_event */ - $final_event = $this->factory->event->create(); - $final_event->_add_relation_to( $datetimes['inactive_datetime'], 'Datetime' ); - $final_event->save(); - - } - - - - /** - * This tests getting active events. - * @since 4.6.x - */ - public function test_get_active_events() { - $this->_setup_events(); - //now do our tests - $this->assertEquals( 1, EEM_Event::instance()->get_active_events( array(), true ) ); - } - - - public function test_get_upcoming_events() { - $this->_setup_events(); - //now do our tests - $this->assertEquals( 2, EEM_Event::instance()->get_upcoming_events( array(), true ) ); - } - - - public function test_get_expired_events() { - $this->_setup_events(); - //now do our tests - $this->assertEquals( 1, EEM_Event::instance()->get_expired_events( array(), true ) ); - } - - public function test_get_inactive_events() { - $this->_setup_events(); - //now do our tests - $this->assertEquals( 1, EEM_Event::instance()->get_inactive_events( array(), true ) ); - } - - public function test_get_active_and_upcoming_events() { - $this->_setup_events(); - //now do our tests - $this->assertEquals( 3, EEM_Event::instance()->get_active_and_upcoming_events( array(), true ) ); - } - - - /** - * @see https://events.codebasehq.com/projects/event-espresso/tickets/8799 - * @group 8799 - * @since 4.8.8.rc.019 - */ - public function test_default_reg_status() { - //first verify the default reg status on config is pending payment - $this->assertEquals( EEM_Registration::status_id_pending_payment, EE_Registry::instance()->CFG->registration->default_STS_ID ); - - //verify creating default event from the model has that default reg status - /** @type EE_Event $event */ - $event = EEM_Event::instance()->create_default_object(); - $this->assertEquals( EEM_Registration::status_id_pending_payment, $event->default_registration_status() ); - - //let's update config in the db to have default reg status of approved - EE_Registry::instance()->CFG->registration->default_STS_ID = EEM_Registration::status_id_approved; - EE_Registry::instance()->CFG->update_espresso_config(); - - //let's reset for new test - EEM_Event::reset(); - EE_Registry::reset(); - - //k NOW the default reg status in config should be approved - $this->assertEquals( EEM_Registration::status_id_approved, EE_Registry::instance()->CFG->registration->default_STS_ID ); - - //new default event should have approved as the default reg status - $event = EEM_Event::instance()->create_default_object(); - $this->assertEquals( EEM_Registration::status_id_approved, $event->default_registration_status() ); - } - -} -// Location: testcases/core/db_models/EEM_Event_Test.php diff --git a/tests/testcases/core/db_models/EEM_Extra_Join_Test.php b/tests/testcases/core/db_models/EEM_Extra_Join_Test.php deleted file mode 100644 index 992e7e6206d..00000000000 --- a/tests/testcases/core/db_models/EEM_Extra_Join_Test.php +++ /dev/null @@ -1,117 +0,0 @@ -new_model_obj_with_dependencies('Event'); - $pm = $this->new_model_obj_with_dependencies('Payment_Method', array('PMD_type' => 'Invoice')); - //add a few extra events and payment methods, just to make sure we are - //only relating the things we intended - $this->new_model_obj_with_dependencies('Event'); - $this->new_model_obj_with_dependencies('Payment_Method', array('PMD_type' => 'Invoice')); - $this->new_model_obj_with_dependencies( - 'Extra_Join', - array( - 'EXJ_first_model_ID' => $e->ID(), - 'EXJ_first_model_name' => 'Event', - 'EXJ_second_model_ID' => $pm->ID(), - 'EXJ_second_model_name' => 'Payment_Method', - ) - ); - $this->assertEquals(array($pm->ID() => $pm), $e->get_many_related('Payment_Method')); - $this->assertEquals(array($e->ID() => $e), $pm->get_many_related('Event')); - } - - - /** - * @group 9113 - */ - public function test_add() - { - $e = $this->new_model_obj_with_dependencies('Event'); - $pm = $this->new_model_obj_with_dependencies('Payment_Method', array('PMD_type' => 'Invoice')); - $e->_add_relation_to($pm, 'Payment_Method'); - $this->assertEquals(array($pm->ID() => $pm), $e->get_many_related('Payment_Method')); - } - - - - /** - * @group 9113 - */ - public function test_delete() - { - $e = $this->new_model_obj_with_dependencies('Event'); - $pm = $this->new_model_obj_with_dependencies('Payment_Method', array('PMD_type' => 'Invoice')); - $e->_add_relation_to($pm, 'Payment_Method'); - $this->assertEquals(array($pm->ID() => $pm), $e->get_many_related('Payment_Method')); - $e->_remove_relation_to($pm, 'Payment_Method'); - $this->assertEquals(array(), $e->get_many_related('Payment_Method')); - } - -} - -// Location: testcases/core/db_models/EEM_Extra_Join_Test.php diff --git a/tests/testcases/core/db_models/EEM_Line_Item_Test.php b/tests/testcases/core/db_models/EEM_Line_Item_Test.php deleted file mode 100644 index 33a24002780..00000000000 --- a/tests/testcases/core/db_models/EEM_Line_Item_Test.php +++ /dev/null @@ -1,76 +0,0 @@ -new_model_obj_with_dependencies('Transaction'); - $ticket = $this->new_model_obj_with_dependencies( 'Ticket' ); - $tax = $this->new_model_obj_with_dependencies( 'Price' ); - $line_item_for_ticket = $this->new_model_obj_with_dependencies( 'Line_Item', - array( - 'TXN_ID' => $txn->ID(), - 'LIN_type' => EEM_Line_Item::type_line_item, - 'OBJ_type' => 'Ticket', - 'OBJ_ID' => $ticket->ID() - ) ); - $line_item_for_tax = $this->new_model_obj_with_dependencies( 'Line_Item', - array( - 'TXN_ID' => $txn->ID(), - 'LIN_type' => EEM_Line_Item::type_tax, - 'OBJ_type' => 'Price', - 'OBJ_ID' => $tax->ID() - )); - $line_item_for_nothing = $this->new_model_obj_with_dependencies( 'Line_Item', - array( - 'TXN_ID' => $txn->ID(), - 'LIN_type' => EEM_Line_Item::type_line_item, - 'OBJ_type' => NULL, - 'OBJ_ID' => 0 - ) - ); - $line_item_for_venue = $this->new_model_obj_with_dependencies( 'Line_Item', - array( - 'TXN_ID' => $txn->ID(), - 'LIN_type' => EEM_Line_Item::type_line_item, - 'OBJ_type' => 'Venue', - 'OBJ_ID' => 0 - ) - ); - $non_ticket_line_items = EEM_Line_Item::instance()->get_all_non_ticket_line_items_for_transaction( $txn ); - $this->assertEquals( 2, count( $non_ticket_line_items ) ); - $this->assertTrue( in_array( $line_item_for_nothing, $non_ticket_line_items ) ); - $this->assertTrue( in_array( $line_item_for_venue, $non_ticket_line_items ) ); - } - - /** - * @group 7965 - */ - function test_delete_registrations_with_no_transaction(){ - $deletable_count = 5; - $safe_count = 8; - for( $i = 0; $i < $deletable_count; $i++ ) { - $this->new_model_obj_with_dependencies( 'Line_Item', array( 'TXN_ID' => 0, 'LIN_timestamp' => time() - WEEK_IN_SECONDS * 2 ) ); - } - for( $i=0;$i< $safe_count; $i++ ){ - $this->new_model_obj_with_dependencies( 'Line_Item' ); - } - $deleted = EEM_Line_Item::instance()->delete_line_items_with_no_transaction(); - $this->assertEquals( $deletable_count, $deleted ); - } -} - -// End of file EEM_Line_Item_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/EEM_Message_Template_Caps_Test.php b/tests/testcases/core/db_models/EEM_Message_Template_Caps_Test.php deleted file mode 100644 index d766c1c2c04..00000000000 --- a/tests/testcases/core/db_models/EEM_Message_Template_Caps_Test.php +++ /dev/null @@ -1,70 +0,0 @@ -delete( array(), false ); - $this->assertEquals( 0, EEM_Message_Template::instance()->count() ); - EEM_Message_Template_Group::instance()->delete_permanently( EEM_Message_Template_Group::instance()->alter_query_params_so_deleted_and_undeleted_items_included(), false ); - $this->assertEquals( 0, EEM_Message_Template_Group::instance()->count() ); - - global $current_user; - $user = $this->factory->user->create_and_get(); - $this->assertEquals( 0, EEM_Question::instance()->count( array( 'caps' => EEM_Base::caps_read_admin ) ) ); - - //now log in and see I can edit my own - $current_user = $user; - $user->add_cap( 'ee_read_messages'); - $mtg1 = $this->new_model_obj_with_dependencies( 'Message_Template_Group', array( 'MTP_is_global' => false, 'MTP_user_id' => $user->ID ) ); - $mt1 = $this->new_model_obj_with_dependencies( 'Message_Template', array( 'GRP_ID' => $mtg1->ID() ) ); - - $mtg2_others = $this->new_model_obj_with_dependencies( 'Message_Template_Group', array( 'MTP_is_global' => false, 'MTP_user_id' => 9999 ) ); - $mt2_others = $this->new_model_obj_with_dependencies( 'Message_Template', array( 'GRP_ID' => $mtg2_others->ID() ) ); - - $mtg3_global = $this->new_model_obj_with_dependencies( 'Message_Template_Group', array( 'MTP_is_global' => true, 'MTP_user_id' => 9999 ) ); - $mt3_global = $this->new_model_obj_with_dependencies( 'Message_Template', array( 'GRP_ID' => $mtg3_global->ID() ) ); - - $i_can_edit = EEM_Message_Template::instance()->get_all( array( 'caps' => EEM_Base::caps_read_admin ) ); - $this->assertEquals( $mt1, reset( $i_can_edit ) ); - $this->assertEquals( 1, count( $i_can_edit ) ); - - //now give them the ability to read others messages - $user->add_cap( 'ee_read_others_messages' ); - $i_can_edit = EEM_Message_Template::instance()->get_all( array( 'caps' => EEM_Base::caps_read_admin ) ); - $this->assertEquals( $mt1, reset( $i_can_edit ) ); - $this->assertEquals( $mt2_others, next( $i_can_edit ) ); - $this->assertEquals( 2, count( $i_can_edit ) ); - - //now let them read global message - $user->add_cap( 'ee_read_global_messages' ); - $i_can_edit = EEM_Message_Template::instance()->get_all( array( 'caps' => EEM_Base::caps_read_admin, 'order_by' => array( 'MTP_ID' => 'ASC' ) ) ); - $this->assertEquals( $mt1, reset( $i_can_edit ) ); - $this->assertEquals( $mt2_others, next( $i_can_edit ) ); - $this->assertEquals( $mt3_global, next( $i_can_edit ) ); - $this->assertEquals( 3, count( $i_can_edit ) ); - } -} - -// End of file EEM_Message_Template_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/EEM_Message_Test.php b/tests/testcases/core/db_models/EEM_Message_Test.php deleted file mode 100644 index a4af60a450d..00000000000 --- a/tests/testcases/core/db_models/EEM_Message_Test.php +++ /dev/null @@ -1,41 +0,0 @@ -fail( __METHOD__ . ' cannot be tested because the EE_DEBUG_MESSAGES constant has been set somewhere. Please ensure this constant isn\'t set for unit tests' ); - } - - //set constant and ensure it defaults to true. - define( 'EE_DEBUG_MESSAGES', true ); - $this->assertTrue( EEM_Message::debug() ); - - //ensure it continues to return true - $this->assertTrue( EEM_Message::debug() ); - - //set false and ensure it continues to return false - EEM_Message::debug( false ); - $this->assertFalse( EEM_Message::debug() ); - - //set true and ensure it continues to return true - EEM_Message::debug( true ); - $this->assertTrue( EEM_Message::debug() ); - - //filter so it always returns true. - add_filter( 'FHEE__EEM_Message__debug', '__return_true' ); - EEM_Message::debug( false ); - $this->assertTrue( EEM_Message::debug() ); - - //remove filter and restore to default. - remove_filter( 'FHEE__EEM_Message__debug', '__return_true' ); - EEM_Message::debug( false ); - } -} diff --git a/tests/testcases/core/db_models/EEM_Payment_Method_Test.php b/tests/testcases/core/db_models/EEM_Payment_Method_Test.php deleted file mode 100644 index 1245c15d075..00000000000 --- a/tests/testcases/core/db_models/EEM_Payment_Method_Test.php +++ /dev/null @@ -1,38 +0,0 @@ -new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Invoice' ) ); - $this->assertNotEmpty( $pm->ID() ); - $this->assertEquals( $pm, EEM_Payment_Method::instance()->ensure_is_obj( $pm ) ); - $this->assertEquals( $pm, EEM_Payment_Method::instance()->ensure_is_obj( $pm->ID() ) ); - $this->assertEquals( $pm, EEM_Payment_Method::instance()->ensure_is_obj( $pm->slug() ) ); - } - - /** - * @group 7201 - */ - function test_get_one_by_slug(){ - $pm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Invoice' ) ); - $this->assertNotEmpty( $pm->ID() ); - $this->assertEquals( $pm, EEM_Payment_Method::instance()->get_one_by_ID( $pm->ID() ) ); - $this->assertEquals( $pm, EEM_Payment_Method::instance()->get_one_by_slug( $pm->slug() ) ); - } -} - -// End of file EEM_Payment_Method_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/EEM_Payment_Test.php b/tests/testcases/core/db_models/EEM_Payment_Test.php deleted file mode 100644 index e67503cf884..00000000000 --- a/tests/testcases/core/db_models/EEM_Payment_Test.php +++ /dev/null @@ -1,147 +0,0 @@ -sub(new DateInterval('P2D')); - $one_hour_from_now = $one_hour_from_now->add(new DateInterval('PT1H')); - $two_hours_ago = $two_hours_ago->sub(new DateInterval('PT2H')); - $two_days_from_now = $two_days_from_now->add(new DateInterval('P2D')); - // grab format settings - $formats = array(\EE_Datetime_Field::mysql_date_format, \EE_Datetime_Field::mysql_time_format); - // let's setup the args for our payments in an array, - // then we can just loop through to grab them and set things up. - $payment_args = array( - array( - 'PAY_timestamp' => $two_days_ago->format(\EE_Datetime_Field::mysql_timestamp_format), - 'timezone' => 'America/Toronto', - 'formats' => $formats, - ), - array( - 'PAY_timestamp' => $one_hour_from_now->format(\EE_Datetime_Field::mysql_timestamp_format), - 'timezone' => 'America/Toronto', - 'formats' => $formats, - ), - array( - 'PAY_timestamp' => $two_hours_ago->format(\EE_Datetime_Field::mysql_timestamp_format), - 'timezone' => 'America/Toronto', - 'formats' => $formats, - ), - array( - 'PAY_timestamp' => $two_days_from_now->format(\EE_Datetime_Field::mysql_timestamp_format), - 'timezone' => 'America/Toronto', - 'formats' => $formats, - ), - array( - 'PAY_timestamp' => $two_days_ago->format(\EE_Datetime_Field::mysql_timestamp_format), - 'timezone' => 'America/Toronto', - 'formats' => $formats, - ), - ); - foreach ($payment_args as $payment_arg) { - $this->factory->payment->create($payment_arg); - } - $this->assertEquals(5, EEM_Payment::instance()->count()); - } - - - - /** - * @since 4.6.0 - */ - public function test_get_payments_between_dates() - { - $timezone = new DateTimeZone('America/Toronto'); - // set $test_time in the timezone being tested. - $test_time = new DateTime('now', $timezone); - $test_time->setTime(14, 00); - $this->_setup_payments($test_time, $timezone); - //test defaults - $payments = EEM_Payment::instance()->get_payments_made_between_dates(); - $this->assertCount(2, $payments); - //test including a date from past date for start date. - $payments = EEM_Payment::instance()->get_payments_made_between_dates( - $test_time->sub(new DateInterval('P2D'))->format('d/m/Y'), - '', - 'd/m/Y', - 'America/Toronto' - ); - $this->assertCount(4, $payments); - //test including a date from past date for end date. - $payments = EEM_Payment::instance()->get_payments_made_between_dates( - '', - $test_time->format('d/m/Y'), - 'd/m/Y', - 'America/Toronto' - ); - $this->assertCount(4, $payments); - //test including a date from upcoming date for start date - $payments = EEM_Payment::instance()->get_payments_made_between_dates( - $test_time->add(new DateInterval('P4D'))->format('d/m/Y'), - '', - 'd/m/Y', - 'America/Toronto' - ); - $this->assertCount(3, $payments); - //test including a date from upcoming date for end date - $payments = EEM_Payment::instance()->get_payments_made_between_dates( - '', - $test_time->format('d/m/Y'), - 'd/m/Y', - 'America/Toronto' - ); - $this->assertCount(3, $payments); - //test exception - $this->setExpectedException('EE_Error'); - EEM_Payment::instance()->get_payments_made_between_dates('trigger_exception'); - } - - -} -//end class EEM_Payment_Test -// Location: tests/testcases/core/db_models/EEM_Payment_Test.php diff --git a/tests/testcases/core/db_models/EEM_Price_Caps_Test.php b/tests/testcases/core/db_models/EEM_Price_Caps_Test.php deleted file mode 100644 index fb33b1aeb95..00000000000 --- a/tests/testcases/core/db_models/EEM_Price_Caps_Test.php +++ /dev/null @@ -1,201 +0,0 @@ -user - * @var EE_Price - */ - public $p_mine; - - /** - * Non-default ticket owned by another user - * @var EE_Price - */ - public $p_others; - - /** - * Event though tickets can't be "private", the event they are for can be - * @var EE_Price - */ - public $p_private; - - /** - * Default ticket owned by $this->user - * @var EE_Price - */ - public $p_mine_default; - - /** - * Default ticket owned by another user - * @var EE_Price - */ - public $p_others_default; - - /** - * Non-default ticket owned by the $this->user - * @var EE_Ticket - */ - public $t_mine; - - /** - * Non-default ticket owned by another user - * @var EE_Ticket - */ - public $t_others; - - /** - * Event though tickets can't be "private", the event they are for can be - * @var EE_Ticket - */ - public $t_private; - - /** - * My Event - * @var EE_Event - */ - public $e_mine; - - /** - * Another users event - * @var EE_Event - */ - public $e_others; - - /** - * Another users private event - * @var EE_Event - */ - public $e_private; - public function setUp(){ - parent::setUp(); - //let's make sure we start off with NO tickets in the DB - EEM_Price::instance()->delete_permanently( EEM_Price::instance()->alter_query_params_so_deleted_and_undeleted_items_included(), false ); - $this->assertEquals( 0, EEM_Price::instance()->count( EEM_Price::instance()->alter_query_params_so_deleted_and_undeleted_items_included() ) ); - - $this->user = $this->factory->user->create_and_get(); - $this->e_mine = $this->new_model_obj_with_dependencies( 'Event', array( 'EVT_wp_user' => $this->user->ID, 'status' => 'publish' ) ); - $this->e_others = $this->new_model_obj_with_dependencies( 'Event', array( 'EVT_wp_user' => 99999, 'status' => 'publish' ) ); - $this->e_private = $this->new_model_obj_with_dependencies( 'Event', array( 'EVT_wp_user' => 99999, 'status' => 'private' ) ); - $this->t_mine = $this->new_model_obj_with_dependencies('Ticket', array( 'TKT_is_default' => false, 'TKT_wp_user' => $this->user->ID ) ); - $this->t_others = $this->new_model_obj_with_dependencies('Ticket', array( 'TKT_is_default' => false, 'TKT_wp_user' => 9999 ) ); - $this->t_private = $this->new_model_obj_with_dependencies('Ticket', array( 'TKT_is_default' => false, 'TKT_wp_user' => 9999 ) ); - $dtt_to_mine = $this->new_model_obj_with_dependencies( 'Datetime', array( 'EVT_ID' => $this->e_mine->ID() ) ); - $dtt_to_mine->_add_relation_to( $this->t_mine, 'Ticket' ); - $dtt_to_others = $this->new_model_obj_with_dependencies( 'Datetime', array( 'EVT_ID' => $this->e_others->ID() ) ); - $dtt_to_others->_add_relation_to( $this->t_others, 'Ticket' ); - $dtt_to_private = $this->new_model_obj_with_dependencies( 'Datetime', array( 'EVT_ID' => $this->e_private->ID() ) ); - $dtt_to_private->_add_relation_to( $this->t_private, 'Ticket'); - - $this->p_mine = $this->new_model_obj_with_dependencies('Price', array( 'PRC_is_default' => false, 'PRC_wp_user' => $this->user->ID ) ); - $this->p_others = $this->new_model_obj_with_dependencies('Price', array( 'PRC_is_default' => false, 'PRC_wp_user' => 9999 ) ); - $this->p_private = $this->new_model_obj_with_dependencies('Price', array( 'PRC_is_default' => false, 'PRC_wp_user' => 9999 ) ); - $this->p_mine_default = $this->new_model_obj_with_dependencies('Price', array( 'PRC_is_default' => true, 'PRC_wp_user' => $this->user->ID ) ); - $this->p_others_default = $this->new_model_obj_with_dependencies('Price', array( 'PRC_is_default' => true, 'PRC_wp_user' =>999999 ) ); - $this->p_mine->_add_relation_to( $this->t_mine, 'Ticket' ); - $this->p_others->_add_relation_to( $this->t_others, 'Ticket' ); - $this->p_private->_add_relation_to( $this->t_private, 'Ticket' ); - } - - /** - * Make sure we are getting back the right things when we apply the read-context - * restrictions - */ - public function test_get_all__caps__read__not_logged_in() { - //when we have no caps we should find all the non-global ones - $results = EEM_Price::instance()->get_all( array( 'caps' => EEM_Base::caps_read, 'order_by' => array ('PRC_ID' => 'ASC' ) ) ); - - $first_result = reset( $results ); - $this->assertEEModelObjectsEquals($this->p_mine, $first_result ); - $next_result = next( $results ); - $this->assertEEModelObjectsEquals( $this->p_others, $next_result ); - $this->assertEquals( 2, count( $results ) ); - } - - public function test_get_all__caps__read__logged_in_with_read_default_prices_cap(){ - //now if we are a real user with read default tickets, we should also be able to see our own - global $current_user; - $current_user = $this->user; - $this->user->add_cap( 'ee_read_default_prices' ); - $results = EEM_Price::instance()->get_all( array( 'caps' => EEM_Base::caps_read, 'order_by' => array ('PRC_ID' => 'ASC' ) ) ); - $this->assertEEModelObjectsEquals($this->p_mine, reset( $results ) ); - $this->assertEEModelObjectsEquals( $this->p_others, next( $results ) ); - $this->assertEEModelObjectsEquals( $this->p_mine_default, next( $results ) ); - $this->assertEEModelObjectsEquals( $this->p_others_default, next( $results ) ); - $this->assertEquals( 4, count( $results ) ); - } - - - public function test_get_all__caps__read_admin__not_logged_in(){ - //when we have no caps we should none - $results = EEM_Price::instance()->get_all( array( 'caps' => EEM_Base::caps_read_admin, 'order_by' => array ('PRC_ID' => 'ASC' ) ) ); - $this->assertEquals( 0, count( $results ) ); - } - - /** - * If a user can read events, they should be able to read their own prices - */ - public function test_get_all__caps__read_admin__logged_in_with_read_events(){ - global $current_user; - $current_user = $this->user; - $current_user->add_cap( 'ee_read_events' ); - $results = EEM_Price::instance()->get_all( array( 'caps' => EEM_Base::caps_read_admin, 'order_by' => array ('PRC_ID' => 'ASC' ) ) ); - //I should be able to read prices for my own events - $this->assertEEModelObjectsEquals( $this->p_mine, reset( $results ) ); - $this->assertEquals( 1, count( $results ) ); - } - - /** - * If a user can read others' events, they should be able to read prices for others' events - */ - public function test_get_all__caps__read_admin__logged_in_with_read_others_events(){ - global $current_user; - $current_user = $this->user; - $current_user->add_cap( 'ee_read_events' ); - $current_user->add_cap( 'ee_read_others_events' ); - $results = EEM_Price::instance()->get_all( array( 'caps' => EEM_Base::caps_read_admin, 'order_by' => array ('PRC_ID' => 'ASC' ) ) ); - //I should be able to read tickets for my own events, and for others' that aren't private - $this->assertEEModelObjectsEquals( $this->p_mine, reset( $results ) ); - $this->assertEEModelObjectsEquals($this->p_others, next( $results ) ); - $this->assertEquals( 2, count( $results ) ); - } - - /** - * If a user can read private events, they should be able to read others private events' prices - */ - public function test_get_all__caps__read_admin__logged_in_with_read_private_events(){ - global $current_user; - $current_user = $this->user; - $current_user->add_cap( 'ee_read_events' ); - $current_user->add_cap( 'ee_read_others_events' ); - $current_user->add_cap( 'ee_read_private_events' ); - $results = EEM_Price::instance()->get_all( array( 'caps' => EEM_Base::caps_read_admin, 'order_by' => array ('PRC_ID' => 'ASC' ) ) ); - //I should be able to read prices for my own events, and for others' that aren't private - $this->assertEEModelObjectsEquals( $this->p_mine, reset( $results ) ); - $this->assertEEModelObjectsEquals($this->p_others, next( $results ) ); - $this->assertEEModelObjectsEquals($this->p_private, next( $results ) ); - $this->assertEquals( 3, count( $results ) ); - } -} - -// End of file EEM_Price_Caps_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/EEM_Question_Caps_Test.php b/tests/testcases/core/db_models/EEM_Question_Caps_Test.php deleted file mode 100644 index 0f554aaaadb..00000000000 --- a/tests/testcases/core/db_models/EEM_Question_Caps_Test.php +++ /dev/null @@ -1,64 +0,0 @@ -assertEquals( EEM_Question::instance()->count(), EEM_Question::instance()->count( array( 'caps' => EEM_Base::caps_read ) ) ); - } - /** - * test that questions aren't editable until you're logged in, - * then you can only edit your own non-system questions, - * and then you can edit others if you have that cap, - * and then you can edit others if you have that cap - */ - function test_get_all__caps__edit() { - //remove all questions currently existing - EEM_Question::instance()->delete_permanently( EEM_Question::instance()->alter_query_params_so_deleted_and_undeleted_items_included(), false ); - $this->assertEquals( 0, EEM_Question::instance()->count( EEM_Question::instance()->alter_query_params_so_deleted_and_undeleted_items_included() ) ); - global $current_user; - $user = $this->factory->user->create_and_get(); - $this->assertEquals( 0, EEM_Question::instance()->count( array( 'caps' => EEM_Base::caps_edit ) ) ); - - //now log in and see I can edit my own - $current_user = $user; - $user->add_cap( 'ee_edit_questions'); - $q1 = $this->new_model_obj_with_dependencies( 'Question', array( 'QST_system' => '', 'QST_wp_user' => $user->ID ) ); - $q2_system = $this->new_model_obj_with_dependencies( 'Question', array( 'QST_system' => 'something', 'QST_wp_user' => $user->ID ) ); - $q3_others = $this->new_model_obj_with_dependencies( 'Question', array( 'QST_system' => '', 'QST_wp_user' => 9999 ) ); - $q4_others_system = $this->new_model_obj_with_dependencies( 'Question', array( 'QST_system' => 'somethingelse', 'QST_wp_user' => 9999 ) ); - $i_can_edit = EEM_Question::instance()->get_all( array( 'caps' => EEM_Base::caps_edit ) ); - $this->assertEquals( $q1, reset( $i_can_edit ) ); - $this->assertEquals( $q3_others, next( $i_can_edit ) ); - $this->assertEquals( 2, count( $i_can_edit ) ); - - //now give them the ability to edit system questions - $user->add_cap( 'ee_edit_system_questions' ); - $i_can_edit = EEM_Question::instance()->get_all( array( 'caps' => EEM_Base::caps_edit ) ); - $this->assertEquals( $q1, reset( $i_can_edit ) ); - $this->assertEquals( $q2_system, next( $i_can_edit ) ); - $this->assertEquals( $q3_others, next( $i_can_edit ) ); - $this->assertEquals( $q4_others_system, next( $i_can_edit ) ); - $this->assertEquals( 4, count( $i_can_edit ) ); - } -} - -// End of file EEM_Question_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/EEM_Question_Group_Question_Caps_Test.php b/tests/testcases/core/db_models/EEM_Question_Group_Question_Caps_Test.php deleted file mode 100644 index e076b9c83f2..00000000000 --- a/tests/testcases/core/db_models/EEM_Question_Group_Question_Caps_Test.php +++ /dev/null @@ -1,70 +0,0 @@ -delete_permanently( EEM_Question_Group::instance()->alter_query_params_so_deleted_and_undeleted_items_included(), false ); - $this->assertEquals( 0, EEM_Question_Group::instance()->count( EEM_Question_Group::instance()->alter_query_params_so_deleted_and_undeleted_items_included() ) ); - EEM_Question_Group_Question::instance()->delete( array(), false ); - $this->assertEquals( 0, EEM_Question_Group_Question::instance()->count() ); - global $current_user; - $user = $this->factory->user->create_and_get(); - - - - $qg1 = $this->new_model_obj_with_dependencies( 'Question_Group', array( 'QSG_system' => 0, 'QSG_wp_user' => $user->ID ) ); - $qg2_system = $this->new_model_obj_with_dependencies( 'Question_Group', array( 'QSG_system' => 3, 'QSG_wp_user' => $user->ID ) ); - $qg3_others = $this->new_model_obj_with_dependencies( 'Question_Group', array( 'QSG_system' => 0, 'QSG_wp_user' => 9999 ) ); - $qg4_others_system = $this->new_model_obj_with_dependencies( 'Question_Group', array( 'QSG_system' => 4, 'QSG_wp_user' => 9999 ) ); - $q = $this->new_model_obj_with_dependencies( 'Question' ); - $qgq1 = $this->new_model_obj_with_dependencies( 'Question_Group_Question', array( 'QST_ID' => $q->ID(), 'QSG_ID' => $qg1->ID() ) ); - $qgq2 = $this->new_model_obj_with_dependencies( 'Question_Group_Question', array( 'QST_ID' => $q->ID(), 'QSG_ID' => $qg2_system->ID() ) ); - $qgq3 = $this->new_model_obj_with_dependencies( 'Question_Group_Question', array( 'QST_ID' => $q->ID(), 'QSG_ID' => $qg3_others->ID() ) ); - $qgq4 = $this->new_model_obj_with_dependencies( 'Question_Group_Question', array( 'QST_ID' => $q->ID(), 'QSG_ID' => $qg4_others_system->ID() ) ); - - //I am not yet logged in, so I shouldnt be able to edit any - $this->assertEquals( 0, EEM_Question_Group_Question::instance()->count( array( 'caps' => EEM_Base::caps_edit ) ) ); - - //now log in and see I can edit my own - $current_user = $user; - $user->add_cap( 'ee_edit_question_groups'); - $i_can_edit = EEM_Question_Group_Question::instance()->get_all( array( 'caps' => EEM_Base::caps_edit ) ); - $this->assertEquals( $qgq1, reset( $i_can_edit ) ); - $this->assertEquals( $qgq3, next( $i_can_edit ) ); - $this->assertEquals( 2, count( $i_can_edit ) ); - - //now give them the ability to edit system questions - $user->add_cap( 'ee_edit_system_question_groups' ); - $i_can_edit = EEM_Question_Group_Question::instance()->get_all( array( 'caps' => EEM_Base::caps_edit ) ); - $this->assertEquals( $qgq1, reset( $i_can_edit ) ); - $this->assertEquals( $qgq2, next( $i_can_edit ) ); - $this->assertEquals( $qgq3, next( $i_can_edit ) ); - $this->assertEquals( $qgq4, next( $i_can_edit ) ); - $this->assertEquals( 4, count( $i_can_edit ) ); - } -} - -// End of file EEM_Question_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/EEM_Registration_Test.php b/tests/testcases/core/db_models/EEM_Registration_Test.php deleted file mode 100644 index 185f8f6c82b..00000000000 --- a/tests/testcases/core/db_models/EEM_Registration_Test.php +++ /dev/null @@ -1,157 +0,0 @@ -factory->transaction->create(); - //them and set things up. - $registration_args = array( - array( - 'REG_date' => $past_start_date->format( $full_format ), - 'timezone' => 'America/Toronto', - 'formats' => $formats, - 'TXN_ID' => $transaction->ID(), - ), - array( - 'REG_date' => $future_end_date->format( $full_format ), - 'timezone' => 'America/Toronto', - 'formats' => $formats, - 'TXN_ID' => $transaction->ID(), - ), - array( - 'REG_date' => $current->sub( new DateInterval( "PT2H" ) )->format( $full_format ), - 'timezone' => 'America/Toronto', - 'formats' => $formats, - 'TXN_ID' => $transaction->ID(), - ), - array( - 'REG_date' => $current->add( new DateInterval( "P1M" ) )->format( $full_format ), - 'timezone' => 'America/Toronto', - 'formats' => $formats, - 'TXN_ID' => $transaction->ID(), - ), - array( - 'REG_date' => $past_start_date->format( $full_format ), - 'timezone' => 'America/Toronto', - 'formats' => $formats, - 'TXN_ID' => $transaction->ID(), - ), - ); - //need to create an event to add all these registrations to because of the capability checks - $events = $this->factory->event->create_many( 4, array( 'EVT_wp_user' => 0 ) ); - - foreach ( $events as $event ) { - foreach( $registration_args as $registration_arg ) { - /** @var EE_Registration $reg */ - $reg = $this->factory->registration->create( $registration_arg ); - //set registrations to pending so we can test - $reg->set_status( EEM_Registration::status_id_pending_payment ); - $reg->_add_relation_to( $event, 'Event' ); - $reg->save(); - } - } - - $this->assertEquals( 20, EEM_Registration::instance()->count() ); - } - - - - /** - * @since 4.6.0 - */ - public function test_get_registrations_per_day_report() { - $this->_setup_registrations(); - - $regs_per_day = EEM_Registration::instance()->get_registrations_per_day_report(); - - //first assert count of results - $this->assertEquals( 3, count( $regs_per_day ) ); - - //next there should be a total = 1 for each result - foreach ( $regs_per_day as $registration ) { - $this->assertEquals( 4, $registration->total ); - } - } - - - - - public function test_get_registrations_per_event_report() { - $this->_setup_registrations(); - $regs_per_event = EEM_Registration::instance()->get_registrations_per_event_report(); - - //first assert total count of results - $this->assertEquals( 4, count( $regs_per_event ) ); - - //next there should be a total = 1 for each result - foreach ( $regs_per_event as $registration ) { - $this->assertEquals( 3, $registration->total ); - } - } - - - - /** - * @group 7965 - */ - function test_delete_registrations_with_no_transaction(){ - $deletable_count = 5; - $safe_count = 8; - $this->factory->registration->create_many( $deletable_count, array( 'TXN_ID' => 0 ) ); - for( $i=0;$i< $safe_count; $i++ ){ - $this->new_model_obj_with_dependencies( 'Registration' ); - } - $deleted = EEM_Registration::instance()->delete_registrations_with_no_transaction(); - $this->assertEquals( $deletable_count, $deleted ); - } - - - -} -// End of file EEM_Registration_Test.php -// Location: testcases/core/db_models/EEM_Registration_Test.php diff --git a/tests/testcases/core/db_models/EEM_Soft_Delete_Base_Test.php b/tests/testcases/core/db_models/EEM_Soft_Delete_Base_Test.php deleted file mode 100644 index d108363d891..00000000000 --- a/tests/testcases/core/db_models/EEM_Soft_Delete_Base_Test.php +++ /dev/null @@ -1,127 +0,0 @@ - 'tim', 'ATT_lname' => 'bob', 'ATT_email' => 'few@ew.efds' ) ); - $a1->save(); - - - $a2 = EE_Attendee::new_instance( array( 'ATT_fname' => 'update-me', 'ATT_lname' => 'man', 'ATT_email' => 'few@ew.efds' ) ); - $a2->save(); - - //and isnert another attendee NOT using the models system - $new_attendee_id = wp_insert_post( array( 'post_name' => 'update-me-abnormal-man', 'post_content' => 'the man', 'post_status' => 'publish', 'post_type' => 'espresso_attendees' ), TRUE ); - $this->assertNotEmpty( $new_attendee_id ); - $this->assertFalse( is_array( $new_attendee_id ) ); - global $wpdb; - $wpdb->insert( $wpdb->prefix."esp_attendee_meta", array( - 'ATT_ID' => $new_attendee_id, - 'ATT_fname' => 'update-me-abnormal', - 'ATT_lname' => 'man', - 'ATT_email' => 'few@fewd.v4', - ), array( - '%d', //ATT_ID' - '%s', //ATT_fname - '%s', //ATT_lname - '%s', //ATT_email - ) - ); - $this->assertNotEmpty( $wpdb->insert_id ); - - - //soft delete 'update-me' and 'update-me-abnormal' - $att_model = EE_Registry::instance()->load_model( 'Attendee' ); - $att_model->delete( array( array( 'ATT_lname' => 'man' ) ) ); - $this->assertNotEquals( EEM_CPT_Base::post_status_trashed, $a1->status() ); - $this->assertEquals( EEM_CPT_Base::post_status_trashed, $a2->status() ); - - $abnormal_attendee = $att_model->get_one_by_ID( $new_attendee_id ); - $this->assertInstanceOf( 'EE_Attendee', $abnormal_attendee ); - $this->assertEquals( EEM_CPT_Base::post_status_trashed, $abnormal_attendee->status()); - } - - - - /** - * This tests a soft delete trash and restore of a cpt model item. - * Test prompted by https://events.codebasehq.com/projects/event-espresso/tickets/6625 - * - * @since 4.4.0 - * - * @return void - */ - public function test_soft_trash_restore_cpt_from_model_context() { - //create attendee model object and dependencies. - $attendee = $this->new_model_obj_with_dependencies( 'Attendee' ); - - //verify have an attendeee object - $this->assertInstanceOf( 'EE_Attendee', $attendee ); - - //use this attendee_id for every model request. - $att_id = $attendee->ID(); - - //reset model - EEM_Attendee::instance()->reset(); - - //verify not trashed. - $status = $attendee->status(); - $this->assertFalse( $status == 'trash' ); - - //k now let's trash it - EEM_Attendee::instance()->delete_by_ID( $att_id ); - - //verify - $trash_attendee = EEM_Attendee::instance()->get_one_by_ID( $att_id ); - $this->assertInstanceOf( 'EE_Attendee', $trash_attendee ); - $status = $trash_attendee->status(); - $this->assertTrue( $status == 'trash' ); - - //reset model again - EEM_Attendee::instance()->reset(); - - //now let's try to restore. - EEM_Attendee::instance()->restore_by_ID( $att_id ); - $restore_attendee = EEM_Attendee::instance()->get_one_by_ID( $att_id ); - $this->assertInstanceOf( 'EE_Attendee', $restore_attendee ); - $status = $restore_attendee->status(); - $this->assertFalse( $status == 'trash' ); - } - - /** - * @group 9179 - */ - public function test_get_minimum_where_conditions_during_query() { - $this->new_model_obj_with_dependencies( 'Registration', array( 'REG_deleted' => true ) ); - $this->new_model_obj_with_dependencies( 'Registration', array( 'REG_deleted' => false ) ); - //count using the default where conditions, which excludes the deleted one - $this->assertEquals( - 1, - EEM_Registration::instance()->count() - ); - //count using the MINIMUM where conditions, which INCLUDES the deleted one - $this->assertEquals( - 2, - EEM_Registration::instance()->count( - array( - 'default_where_conditions' => 'minimum' - )) - ); - } - - -} - -// End of file EEM_Soft_Delete_Base_Test.php diff --git a/tests/testcases/core/db_models/EEM_State_Test.php b/tests/testcases/core/db_models/EEM_State_Test.php deleted file mode 100644 index 8b7313d5016..00000000000 --- a/tests/testcases/core/db_models/EEM_State_Test.php +++ /dev/null @@ -1,25 +0,0 @@ -assertFalse( EEM_State::instance()->exists_by_ID( 99999 ) ); - $s = $this->new_model_obj_with_dependencies( 'State' ); - $this->assertEquals( '', EEM_State::instance()->get_state_name_by_ID( 99999 ) ); - $this->assertEquals( $s->name(), EEM_State::instance()->get_state_name_by_ID( $s->ID() ) ); - } -} - -// End of file EEM_State_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/EEM_Term_Caps_Test.php b/tests/testcases/core/db_models/EEM_Term_Caps_Test.php deleted file mode 100644 index b5be0b6d752..00000000000 --- a/tests/testcases/core/db_models/EEM_Term_Caps_Test.php +++ /dev/null @@ -1,185 +0,0 @@ -event_term = $this->new_model_obj_with_dependencies('Term' ); - $this->new_model_obj_with_dependencies( 'Term_Taxonomy', array( - 'term_id' => $this->event_term->ID(), - 'taxonomy' => 'espresso_event_categories' )); - $this->venue_term = $this->new_model_obj_with_dependencies( 'Term' ); - $this->new_model_obj_with_dependencies( 'Term_Taxonomy', array( - 'term_id' => $this->venue_term->ID(), - 'taxonomy' => 'espresso_venue_categories' )); - } - - /** - * anyone should be able to read term-taxonomies - */ - function test_get_all__caps__read__not_logged_in() { - $venue_and_event_cats = EEM_Term::instance()->get_all( array( - 'caps' => EEM_Base::caps_read, - 'order_by' => array( 'term_id' => 'ASC' ), - array( 'Term_Taxonomy.taxonomy' => array( 'IN', array( 'espresso_event_categories', 'espresso_venue_categories'))) - )); - $this->assertEEModelObjectsEquals( $this->event_term, reset( $venue_and_event_cats ) ); - $this->assertEEModelObjectsEquals($this->venue_term, next( $venue_and_event_cats ) ); - $this->assertEquals( 2, count( $venue_and_event_cats ) ); - } - - function test_get_all__caps__read_admin__not_logged_in() { - $venue_and_event_cats = EEM_Term::instance()->get_all( array( - 'caps' => EEM_Base::caps_read_admin, - 'order_by' => array( 'term_id' => 'ASC' ), - array( 'Term_Taxonomy.taxonomy' => array( 'IN', array( 'espresso_event_categories', 'espresso_venue_categories'))) - )); - $this->assertEquals( 0, count( $venue_and_event_cats ) ); - } - - function test_get_all__caps__read_admin__read_event_cats() { - global $current_user; - $current_user = $this->factory->user->create_and_get(); - $current_user->add_cap( 'ee_manage_event_categories'); - $venue_and_event_cats = EEM_Term::instance()->get_all( array( - 'caps' => EEM_Base::caps_read_admin, - 'order_by' => array( 'term_id' => 'ASC' ), - array( 'Term_Taxonomy.taxonomy' => array( 'IN', array( 'espresso_event_categories', 'espresso_venue_categories'))) - )); - $this->assertEEModelObjectsEquals( $this->event_term, reset( $venue_and_event_cats ) ); - $this->assertEquals( 1, count( $venue_and_event_cats ) ); - } - - function test_get_all__caps__read_admin__read_venue_cats() { - global $current_user; - $current_user = $this->factory->user->create_and_get(); - $current_user->add_cap( 'ee_manage_venue_categories'); - $venue_and_event_cats = EEM_Term::instance()->get_all( array( - 'caps' => EEM_Base::caps_read_admin, - 'order_by' => array( 'term_id' => 'ASC' ), - array( 'Term_Taxonomy.taxonomy' => array( 'IN', array( 'espresso_event_categories', 'espresso_venue_categories'))) - )); - $this->assertEEModelObjectsEquals( $this->venue_term, reset( $venue_and_event_cats ) ); - $this->assertEquals( 1, count( $venue_and_event_cats ) ); - } - - function test_get_all__caps__read_admin__read_event_and_venue_cats() { - global $current_user; - $current_user = $this->factory->user->create_and_get(); - $current_user->add_cap( 'ee_manage_event_categories'); - $current_user->add_cap( 'ee_manage_venue_categories'); - $venue_and_event_cats = EEM_Term::instance()->get_all( array( - 'caps' => EEM_Base::caps_read_admin, - 'order_by' => array( 'term_id' => 'ASC' ), - array( 'Term_Taxonomy.taxonomy' => array( 'IN', array( 'espresso_event_categories', 'espresso_venue_categories'))) - )); - $this->assertEEModelObjectsEquals( $this->event_term, reset( $venue_and_event_cats ) ); - $this->assertEEModelObjectsEquals($this->venue_term, next( $venue_and_event_cats ) ); - $this->assertEquals( 2, count( $venue_and_event_cats ) ); - } - - function test_get_all__caps__edit__no_caps() { - $venue_and_event_cats = EEM_Term::instance()->get_all( array( - 'caps' => EEM_Base::caps_edit, - 'order_by' => array( 'term_id' => 'ASC' ), - array( 'Term_Taxonomy.taxonomy' => array( 'IN', array( 'espresso_event_categories', 'espresso_venue_categories'))) - )); - $this->assertEquals( 0, count( $venue_and_event_cats ) ); - } - - function test_get_all__caps__edit__event_caps() { - global $current_user; - $current_user = $this->factory->user->create_and_get(); - $current_user->add_cap( 'ee_edit_event_category'); - $venue_and_event_cats = EEM_Term::instance()->get_all( array( - 'caps' => EEM_Base::caps_edit, - 'order_by' => array( 'term_id' => 'ASC' ), - array( 'Term_Taxonomy.taxonomy' => array( 'IN', array( 'espresso_event_categories', 'espresso_venue_categories'))) - )); - $this->assertEEModelObjectsEquals( $this->event_term, reset( $venue_and_event_cats ) ); - $this->assertEquals( 1, count( $venue_and_event_cats ) ); - } - - function test_get_all__caps__edit__venue__caps() { - global $current_user; - $current_user = $this->factory->user->create_and_get(); - $current_user->add_cap( 'ee_edit_venue_category'); - $venue_and_event_cats = EEM_Term::instance()->get_all( array( - 'caps' => EEM_Base::caps_edit, - 'order_by' => array( 'term_id' => 'ASC' ), - array( 'Term_Taxonomy.taxonomy' => array( 'IN', array( 'espresso_event_categories', 'espresso_venue_categories'))) - )); - $this->assertEEModelObjectsEquals( $this->venue_term, reset( $venue_and_event_cats ) ); - $this->assertEquals( 1, count( $venue_and_event_cats ) ); - } - - function test_get_all__caps__delete__no_caps() { - $venue_and_event_cats = EEM_Term::instance()->get_all( array( - 'caps' => EEM_Base::caps_delete, - 'order_by' => array( 'term_id' => 'ASC' ), - array( 'Term_Taxonomy.taxonomy' => array( 'IN', array( 'espresso_event_categories', 'espresso_venue_categories'))) - )); - $this->assertEquals( 0, count( $venue_and_event_cats ) ); - } - - function test_get_all__caps__delete__event_caps() { - global $current_user; - $current_user = $this->factory->user->create_and_get(); - $current_user->add_cap( 'ee_delete_event_category'); - $venue_and_event_cats = EEM_Term::instance()->get_all( array( - 'caps' => EEM_Base::caps_delete, - 'order_by' => array( 'term_id' => 'ASC' ), - array( 'Term_Taxonomy.taxonomy' => array( 'IN', array( 'espresso_event_categories', 'espresso_venue_categories'))) - )); - $this->assertEEModelObjectsEquals( $this->event_term, reset( $venue_and_event_cats ) ); - $this->assertEquals( 1, count( $venue_and_event_cats ) ); - } - - function test_get_all__caps__delete__venue_and_event_caps() { - global $current_user; - $current_user = $this->factory->user->create_and_get(); - $current_user->add_cap( 'ee_delete_venue_category'); - $current_user->add_cap( 'ee_delete_event_category'); - $venue_and_event_cats = EEM_Term::instance()->get_all( array( - 'caps' => EEM_Base::caps_delete, - 'order_by' => array( 'term_id' => 'ASC' ), - array( 'Term_Taxonomy.taxonomy' => array( 'IN', array( 'espresso_event_categories', 'espresso_venue_categories'))) - )); - $this->assertEEModelObjectsEquals( $this->event_term, reset( $venue_and_event_cats ) ); - $this->assertEEModelObjectsEquals( $this->venue_term, next( $venue_and_event_cats ) ); - $this->assertEquals( 2, count( $venue_and_event_cats ) ); - } - - - - -} - -// End of file EE_Term_Relationship_Caps_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/EEM_Term_Relationship_Caps_Test.php b/tests/testcases/core/db_models/EEM_Term_Relationship_Caps_Test.php deleted file mode 100644 index 4278e6076d8..00000000000 --- a/tests/testcases/core/db_models/EEM_Term_Relationship_Caps_Test.php +++ /dev/null @@ -1,238 +0,0 @@ -user = $this->factory->user->create_and_get(); - $this->my_event = $this->new_model_obj_with_dependencies( 'Event', array( 'EVT_wp_user' => $this->user->ID ) ); - $term_id_and_taxonomy_id = wp_insert_term('term_r_for_my_event', 'espresso_event_categories' ); - $result = wp_set_object_terms( $this->my_event->ID(), $term_id_and_taxonomy_id['term_id'], 'espresso_event_categories' ); - $this->term_r_for_my_event = EEM_Term_Relationship::instance()->get_one( - array( - array( - 'object_id' => $this->my_event->ID(), - 'term_taxonomy_id' => reset( $result ) - ) - ) - ); - - $this->others_event = $this->new_model_obj_with_dependencies( 'Event', array( 'EVT_wp_user' => $this->user->ID + 1 ) ); - $term_id_and_taxonomy_id = wp_insert_term('term_r_for_others_event', 'espresso_event_categories' ); - $result = wp_set_object_terms( $this->others_event->ID(), $term_id_and_taxonomy_id['term_id'], 'espresso_event_categories' ); - $this->term_r_for_others_event = EEM_Term_Relationship::instance()->get_one( - array( - array( - 'object_id' => $this->others_event->ID(), - 'term_taxonomy_id' => reset( $result ) - ) - ) - ); - - - } - - public function test_get_all__caps__read(){ - $term_rs = EEM_Term_Relationship::instance()->get_all( - array( - array( - 'object_id' => array( 'IN', array( $this->my_event->ID(), $this->others_event->ID() ) ) - ), - 'order_by' => array( 'object_id' => 'ASC' ), - ) - ); - $this->assertEEModelObjectsEquals( $this->term_r_for_my_event, reset( $term_rs ) ); - $this->assertEEModelObjectsEquals( $this->term_r_for_others_event, next( $term_rs ) ); - $this->assertEquals( 2, count( $term_rs ) ); - } - - /** - * if you're not logged in, you shouldn't be able to see any of this in the admin context - */ - public function test_get_all_read_admin__no_caps() { - $term_rs = EEM_Term_Relationship::instance()->get_all( - array( - array( - 'object_id' => array( 'IN', array( $this->my_event->ID(), $this->others_event->ID() ) ) - ), - 'order_by' => array( 'object_id' => 'ASC' ), - 'caps' => EEM_Base::caps_read_admin - ) - ); - $this->assertEquals( 0, count( $term_rs ) ); - } - - /** - * currently, you don't need "ee_assign_event_categories" to READ term relationships in the admin - */ - public function test_get_all__caps__read_admin__my_own(){ - //log the user in - global $current_user; - $current_user = $this->user; - $current_user->add_cap( 'ee_read_events' ); - - //now check they can only see the term relationship for their own event - $term_rs = EEM_Term_Relationship::instance()->get_all( - array( - array( - 'object_id' => array( 'IN', array( $this->my_event->ID(), $this->others_event->ID() ) ) - ), - 'order_by' => array( 'object_id' => 'ASC' ), - 'caps' => EEM_Base::caps_read_admin - ) - ); - $this->assertEEModelObjectsEquals( $this->term_r_for_my_event, reset( $term_rs ) ); - $this->assertEquals( 1, count( $term_rs ) ); - } - - public function test_get_all__caps__read_admin__others(){ - //log the user in - global $current_user; - $current_user = $this->user; - $current_user->add_cap( 'ee_read_events' ); - $current_user->add_cap( 'ee_read_others_events' ); - - //now check they can only see the term relationship for their own event - $term_rs = EEM_Term_Relationship::instance()->get_all( - array( - array( - 'object_id' => array( 'IN', array( $this->my_event->ID(), $this->others_event->ID() ) ) - ), - 'order_by' => array( 'object_id' => 'ASC' ), - 'caps' => EEM_Base::caps_read_admin - ) - ); - $this->assertEEModelObjectsEquals( $this->term_r_for_my_event, reset( $term_rs ) ); - $this->assertEEModelObjectsEquals( $this->term_r_for_others_event, next( $term_rs ) ); - $this->assertEquals( 2, count( $term_rs ) ); - } - - /** - * you need the "ee_assign_event_categories" too, in order to edit any event categories - */ - public function test_get_all__caps__edit__no_assign_event_category(){ - //log the user in - global $current_user; - $current_user = $this->user; - $current_user->add_cap( 'ee_edit_events' ); - - //now check they can only see the term relationship for their own event - $term_rs = EEM_Term_Relationship::instance()->get_all( - array( - array( - 'object_id' => array( 'IN', array( $this->my_event->ID(), $this->others_event->ID() ) ) - ), - 'order_by' => array( 'object_id' => 'ASC' ), - 'caps' => EEM_Base::caps_edit - ) - ); - $this->assertEquals( 0, count( $term_rs ) ); - } - - public function test_get_all__caps__edit__with_assign_event_category(){ - //log the user in - global $current_user; - $current_user = $this->user; - $current_user->add_cap( 'ee_edit_events' ); - $current_user->add_cap( 'ee_assign_event_category' ); - $term_rs = EEM_Term_Relationship::instance()->get_all( - array( - array( - 'object_id' => array( 'IN', array( $this->my_event->ID(), $this->others_event->ID() ) ) - ), - 'order_by' => array( 'object_id' => 'ASC' ), - 'caps' => EEM_Base::caps_edit - ) - ); - $this->assertEEModelObjectsEquals( $this->term_r_for_my_event, reset( $term_rs ) ); - $this->assertEquals( 1, count( $term_rs ) ); - } - - - - /** - * you need the "ee_assign_event_categories" too, in order to edit any event categories - */ - public function test_get_all__caps__delete__no_assign_event_category(){ - //log the user in - global $current_user; - $current_user = $this->user; - $current_user->add_cap( 'ee_edit_events' ); - - //now check they can only see the term relationship for their own event - $term_rs = EEM_Term_Relationship::instance()->get_all( - array( - array( - 'object_id' => array( 'IN', array( $this->my_event->ID(), $this->others_event->ID() ) ) - ), - 'order_by' => array( 'object_id' => 'ASC' ), - 'caps' => EEM_Base::caps_delete - ) - ); - $this->assertEquals( 0, count( $term_rs ) ); - } - - public function test_get_all__caps__delete__with_assign_event_category(){ - //log the user in - global $current_user; - $current_user = $this->user; - $current_user->add_cap( 'ee_edit_events' ); - $current_user->add_cap( 'ee_assign_event_category' ); - - //now check they can only see the term relationship for their own event - $term_rs = EEM_Term_Relationship::instance()->get_all( - array( - array( - 'object_id' => array( 'IN', array( $this->my_event->ID(), $this->others_event->ID() ) ) - ), - 'order_by' => array( 'object_id' => 'ASC' ), - 'caps' => EEM_Base::caps_delete - ) - ); - $this->assertEEModelObjectsEquals( $this->term_r_for_my_event, reset( $term_rs ) ); - $this->assertEquals( 1, count( $term_rs ) ); - } - - - - -} - -// End of file EEM_Term_Relationship_Caps_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/EEM_Term_Relationship_Test.php b/tests/testcases/core/db_models/EEM_Term_Relationship_Test.php deleted file mode 100644 index 554ae708a08..00000000000 --- a/tests/testcases/core/db_models/EEM_Term_Relationship_Test.php +++ /dev/null @@ -1,143 +0,0 @@ - 'monkey1', 'slug' => 'monkey1' ) ); - $term2 = EE_Term::new_instance( array( 'name' => 'monkey2', 'slug'=> 'monkey2' ) ); - $term1->save(); - $term2->save(); - $tt_1 = EE_Term_Taxonomy::new_instance( array( 'taxonomy' => 'whatever', 'term_id' => $term1->ID() ) ); - $tt_1->save(); - $tt_2 = EE_Term_Taxonomy::new_instance( array( 'taxonomy' => 'whatever', 'term_id' => $term2->ID() ) ); - $tt_2->save(); - $e = EE_Event::new_instance( array( 'EVT_name' => 'for_term_1' ) ); - $e->save(); - //ok done setup - //test INSERT - $this->assertEquals(0,$tt_1->count()); - $new_tr_id = EEM_Term_Relationship::instance()->insert( array( 'term_taxonomy_id'=>$tt_1->ID(), 'object_id' => $e->ID() ) ); - $this->assertNotNull( $new_tr_id ); - //refresh out term_taxonomy objects, as the database has changed - $tt_1 = EEM_Term_Taxonomy::reset()->get_one_by_ID( $tt_1->ID() ); - $tt_2 = EEM_Term_Taxonomy::instance()->get_one_by_ID($tt_2->ID() ); - $this->assertEquals( 1, $tt_1->count() ); - $this->assertEquals(0,$tt_2->count() ); - - //test UPDATE... except we can't update term_relationship because there's no Primary Key - //on it. This should be fixed at some point - //@todo: fix this test -// $updated = EEM_Term_Relationship::instance()->update_by_ID(array('term_taxonomy_id'=>$tt_2->ID() ), $new_tr_id ); -// //refresh out term_taxonomy objects, as the database has changed -// $tt_1 = EEM_Term_Taxonomy::reset()->get_one_by_ID( $tt_1->ID() ); -// $tt_2 = EEM_Term_Taxonomy::instance()->get_one_by_ID($tt_2->ID() ); -// $this->assertEquals( 0, $tt_1->count() ); -// $this->assertEquals(1,$tt_2->count() ); - - //test DELETE - //@todo: fix this test too. see above -// $count_deleted = EEM_Term_Relationship::instance()->delete_by_ID($new_tr_id); -// $this->assertNotEmpty( $count_deleted ); -// //refresh out term_taxonomy objects, as the database has changed -// $tt_1 = EEM_Term_Taxonomy::reset()->get_one_by_ID( $tt_1->ID() ); -// $tt_2 = EEM_Term_Taxonomy::instance()->get_one_by_ID($tt_2->ID() ); -// $this->assertEquals( 0, $tt_1->count() ); -// $this->assertEquals(0,$tt_2->count() ); - } - - - /** - * Verifies that when EEM_Term_Relationship::update_term_taxonomy_counts is called with no arguments, - * the counts are correct - */ - public function testUpdateTermTaxonomyCountsPassNull() - { - $terms = $this->setupTerms(); - //verify that when we update the counts, they aren't set to zero - EEM_Term_Relationship::instance()->update_term_taxonomy_counts(); - $this->assertTermCountsCorrect($terms); - } - - - /** - * Verifies that when EEM_Term_Relationship::update_term_taxonomy_counts is called with a term ID, that - * the term counts are afterwards correct still. - */ - public function testUpdateTermTaxonomyCountsPassInt() - { - $terms = $this->setupTerms(); - $term2 = $terms[1]; - //verify that when we update the counts, they aren't set to zero - EEM_Term_Relationship::instance()->update_term_taxonomy_counts($term2->term_id); - $this->assertTermCountsCorrect($terms); - } - - - /** - * Sets up 3 terms, and some related posts, and associates them so that the term counts are :1, 2, 1, respectively. - * Returns a numerically-indexed array of these WP_Term objects - * @return WP_Term[] - */ - protected function setupTerms() - { - //create a few term taxonomies - $term1 = $this->factory()->term->create_and_get(); - $term2 = $this->factory()->term->create_and_get(); - $term3 = $this->factory()->term->create_and_get(); - //add them to some posts - $post1 = $this->factory()->post->create_and_get(); - $post2 = $this->factory()->post->create_and_get(); - wp_set_post_terms($post1->ID, array($term1->term_id, $term2->term_id)); - wp_set_post_terms($post2->ID,array($term2->term_id, $term3->term_id)); - wp_cache_flush(); - $term1 = get_term($term1->term_id); - $term2 = get_term($term2->term_id); - $term3 = get_term($term3->term_id); - - $this->assertEquals(1, $term1->count); - $this->assertEquals(2, $term2->count); - $this->assertEquals(1, $term3->count); - return array( - $term1, - $term2, - $term3 - ); - } - - - /** - * Asserts that the terms received were from setupTerms() and have the correct counts - * @param WP_Term[] $terms - */ - protected function assertTermCountsCorrect(array $terms) - { - $term1 = $terms[0]; - $term2 = $terms[1]; - $term3 = $terms[2]; - wp_cache_flush(); - $term1 = get_term($term1->term_id); - $term2 = get_term($term2->term_id); - $term3 = get_term($term3->term_id); - $this->assertEquals(1, $term1->count); - $this->assertEquals(2, $term2->count); - $this->assertEquals(1, $term3->count); - } -} - -// End of file EEM_Term_Relationship_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/EEM_Ticket_Caps_Test.php b/tests/testcases/core/db_models/EEM_Ticket_Caps_Test.php deleted file mode 100644 index cf29bda41fa..00000000000 --- a/tests/testcases/core/db_models/EEM_Ticket_Caps_Test.php +++ /dev/null @@ -1,198 +0,0 @@ -user - * @var EE_Ticket - */ - public $t_mine; - - /** - * Non-default ticket owned by another user - * @var EE_Ticket - */ - public $t_others; - - /** - * Event though tickets can't be "private", the event they are for can be - * @var EE_Ticket - */ - public $t_private; - - /** - * Default ticket owned by $this->user - * @var EE_Ticket - */ - public $t_mine_default; - - /** - * Default ticket owned by another user - * @var EE_Ticket - */ - public $t_others_default; - - /** - * My Event - * @var EE_Event - */ - public $e_mine; - - /** - * Another users event - * @var EE_Event - */ - public $e_others; - - /** - * Another users private event - * @var EE_Event - */ - public $e_private; - public function setUp(){ - parent::setUp(); - //let's make sure we start off with NO tickets in the DB - EEM_Ticket::instance()->delete_permanently( EEM_Ticket::instance()->alter_query_params_so_deleted_and_undeleted_items_included(), false ); - $this->assertEquals( 0, EEM_Ticket::instance()->count( EEM_Ticket::instance()->alter_query_params_so_deleted_and_undeleted_items_included() ) ); - - $this->user = $this->factory->user->create_and_get(); - $this->e_mine = $this->new_model_obj_with_dependencies( 'Event', array( 'EVT_wp_user' => $this->user->ID, 'status' => 'publish' ) ); - $this->e_others = $this->new_model_obj_with_dependencies( 'Event', array( 'EVT_wp_user' => 99999, 'status' => 'publish' ) ); - $this->e_private = $this->new_model_obj_with_dependencies( 'Event', array( 'EVT_wp_user' => 99999, 'status' => 'private' ) ); - $this->t_mine = $this->new_model_obj_with_dependencies('Ticket', array( 'TKT_is_default' => false, 'TKT_wp_user' => $this->user->ID ) ); - $this->t_others = $this->new_model_obj_with_dependencies('Ticket', array( 'TKT_is_default' => false, 'TKT_wp_user' => 9999 ) ); - $this->t_private = $this->new_model_obj_with_dependencies('Ticket', array( 'TKT_is_default' => false, 'TKT_wp_user' => 9999 ) ); - $this->t_mine_default = $this->new_model_obj_with_dependencies('Ticket', array( 'TKT_is_default' => true, 'TKT_wp_user' => $this->user->ID ) ); - $this->t_others_default = $this->new_model_obj_with_dependencies('Ticket', array( 'TKT_is_default' => true, 'TKT_wp_user' => 9999 ) ); - $dtt_to_mine = $this->new_model_obj_with_dependencies( 'Datetime', array( 'EVT_ID' => $this->e_mine->ID() ) ); - $dtt_to_mine->_add_relation_to( $this->t_mine, 'Ticket' ); - $dtt_to_others = $this->new_model_obj_with_dependencies( 'Datetime', array( 'EVT_ID' => $this->e_others->ID() ) ); - $dtt_to_others->_add_relation_to( $this->t_others, 'Ticket' ); - $dtt_to_private = $this->new_model_obj_with_dependencies( 'Datetime', array( 'EVT_ID' => $this->e_private->ID() ) ); - $dtt_to_private->_add_relation_to( $this->t_private, 'Ticket'); - } - - /** - * Make sure we are getting back the right things when we apply the read-context - * restrictions - */ - public function test_get_all__caps__read__not_logged_in() { - //when we have no caps we should find all the non-global ones - $results = EEM_Ticket::instance()->get_all( array( 'caps' => EEM_Base::caps_read, 'order_by' => array( 'TKT_ID' => 'ASC' ) ) ); - - $first_result = reset( $results ); - $this->assertEEModelObjectsEquals($this->t_mine, $first_result ); - $next_result = next( $results ); - $this->assertEEModelObjectsEquals( $this->t_others, $next_result ); - $this->assertEquals( 2, count( $results ) ); - } - - public function test_get_all__caps__read__logged_in_with_read_default_tickets_cap(){ - //now if we are a real user with read default tickets, we should also be able to see our own - global $current_user; - $current_user = $this->user; - $this->user->add_cap( 'ee_read_default_tickets' ); - $results = EEM_Ticket::instance()->get_all( array( 'caps' => EEM_Base::caps_read, 'order_by' => array( 'TKT_ID' => 'ASC' ) ) ); - $first_result = reset( $results ); - $this->assertEEModelObjectsEquals($this->t_mine, $first_result ); - $next_result = next( $results ); - $this->assertEEModelObjectsEquals( $this->t_others, $next_result ); - $next_result = next( $results ); - $this->assertEEModelObjectsEquals( $this->t_mine_default, $next_result ); - $this->assertEquals( 3, count( $results ) ); - } - - public function test_get_all__caps__read__logged_in_with_read_others_default_tickets_cap(){//now if we are a real user with read default tickets, we should also be able to see our own - //and lastly, if we are a real user who can read others default tickets... - global $current_user; - $current_user = $this->user; - $this->user->add_cap( 'ee_read_default_tickets' ); - $this->user->add_cap( 'ee_read_others_default_tickets' ); - $results = EEM_Ticket::instance()->get_all( array( 'caps' => EEM_Base::caps_read, 'order_by' => array( 'TKT_ID' => 'ASC' ) ) ); - $first_result = reset( $results ); - $this->assertEEModelObjectsEquals($this->t_mine, $first_result ); - $next_result = next( $results ); - $this->assertEEModelObjectsEquals( $this->t_others, $next_result ); - $next_result = next( $results ); - $this->assertEEModelObjectsEquals( $this->t_mine_default, $next_result ); - $next_result = next( $results ); - $this->assertEEModelObjectsEquals( $this->t_others_default, $next_result ); - $this->assertEquals( 4, count( $results ) ); - } - - - public function test_get_all__caps__read_admin__not_logged_in(){ - //when we have no caps we should none - $results = EEM_Ticket::instance()->get_all( array( 'caps' => EEM_Base::caps_read_admin, 'order_by' => array( 'TKT_ID' => 'ASC' ) ) ); - $this->assertEquals( 0, count( $results ) ); - } - - /** - * If a user can read events, they should be able to read their own tickets - */ - public function test_get_all__caps__read_admin__logged_in_with_read_events(){ - global $current_user; - $current_user = $this->user; - $current_user->add_cap( 'ee_read_events' ); - $results = EEM_Ticket::instance()->get_all( array( 'caps' => EEM_Base::caps_read_admin, 'order_by' => array( 'TKT_ID' => 'ASC' ) ) ); - //I should be able to read tickets for my own events - $this->assertEEModelObjectsEquals( $this->t_mine, reset( $results ) ); - $this->assertEquals( 1, count( $results ) ); - } - - /** - * If a user can read others' events, they should be able to read tickets for others' events - */ - public function test_get_all__caps__read_admin__logged_in_with_read_others_events(){ - global $current_user; - $current_user = $this->user; - $current_user->add_cap( 'ee_read_events' ); - $current_user->add_cap( 'ee_read_others_events' ); - $results = EEM_Ticket::instance()->get_all( array( 'caps' => EEM_Base::caps_read_admin, 'order_by' => array( 'TKT_ID' => 'ASC' ) ) ); - //I should be able to read tickets for my own events, and for others' that aren't private - $this->assertEEModelObjectsEquals( $this->t_mine, reset( $results ) ); - $this->assertEEModelObjectsEquals($this->t_others, next( $results ) ); - $this->assertEquals( 2, count( $results ) ); - } - - /** - * If a user can read private events, they should be able to read others private events' tickets - */ - public function test_get_all__caps__read_admin__logged_in_with_read_private_events(){ - global $current_user; - $current_user = $this->user; - $current_user->add_cap( 'ee_read_events' ); - $current_user->add_cap( 'ee_read_others_events' ); - $current_user->add_cap( 'ee_read_private_events' ); - $results = EEM_Ticket::instance()->get_all( array( 'caps' => EEM_Base::caps_read_admin, 'order_by' => array( 'TKT_ID' => 'ASC' ) ) ); - //I should be able to read tickets for my own events, and for others' that aren't private - $this->assertEEModelObjectsEquals( $this->t_mine, reset( $results ) ); - $this->assertEEModelObjectsEquals($this->t_others, next( $results ) ); - $this->assertEEModelObjectsEquals($this->t_private, next( $results ) ); - $this->assertEquals( 3, count( $results ) ); - } - - -} - -// End of file EEM_Ticket_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/EEM_Ticket_Test.php b/tests/testcases/core/db_models/EEM_Ticket_Test.php deleted file mode 100644 index 4edfe5aa082..00000000000 --- a/tests/testcases/core/db_models/EEM_Ticket_Test.php +++ /dev/null @@ -1,38 +0,0 @@ -loadTestScenarios(); - $scenarios = $this->scenarios->get_scenarios_by_type( 'datetime' ); - foreach ( $scenarios as $scenario ) { - //echo "\n\nTesting" . $scenario->name; - if ( $scenario->get_expected( 'sum_tickets_currently_available_at_datetime' ) !== false ) { - //echo "\n scenario->get_scenario_object()->ID(): " . $scenario->get_scenario_object()->ID(); - $actual = EEM_Ticket::instance()->sum_tickets_currently_available_at_datetime( $scenario->get_scenario_object()->ID() ); - $this->assertEquals( $scenario->get_expected( 'sum_tickets_currently_available_at_datetime' ), $actual ); - } - } - } - -} -// Location: tests/testcases/core/db_models/EEM_Ticket_Test.php diff --git a/tests/testcases/core/db_models/EEM_Transaction_Test.php b/tests/testcases/core/db_models/EEM_Transaction_Test.php deleted file mode 100644 index 12cc535eca6..00000000000 --- a/tests/testcases/core/db_models/EEM_Transaction_Test.php +++ /dev/null @@ -1,68 +0,0 @@ -factory->transaction->create_many( - $pretend_bot_creations, - array('TXN_timestamp' => time() - WEEK_IN_SECONDS * 2, 'STS_ID' => EEM_Transaction::failed_status_code) - ); - $this->factory->transaction->create_many( - $pretend_real_recent_txns, - array( - 'TXN_timestamp' => time() - EE_Session_Mock::instance()->lifespan() + MINUTE_IN_SECONDS, - 'STS_ID' => EEM_Transaction::failed_status_code, - ) - ); - $this->factory->transaction->create_many( - $pretend_real_good_txns, - array('STS_ID' => EEM_Transaction::abandoned_status_code) - ); - $failed_transaction_with_real_payment = $this->factory->transaction->create( - array( - 'TXN_timestamp' => time() - WEEK_IN_SECONDS * 2, - 'STS_ID' => EEM_Transaction::failed_status_code - ) - ); - $transaction_count = EEM_Transaction::instance()->count(); - - $this->assertEquals( - $pretend_bot_creations + $pretend_real_recent_txns + $pretend_real_good_txns + 1, - $transaction_count - ); - $failed_transaction_count = EEM_Transaction::instance()->count( - array( - array('STS_ID' => EEM_Transaction::failed_status_code) - ) - ); - $this->assertEquals( - $pretend_bot_creations + $pretend_real_recent_txns + 1, - $failed_transaction_count - ); - $this->factory->payment->create(array('TXN_ID' => $failed_transaction_with_real_payment->ID())); - $num_deleted = EEM_Transaction::instance()->delete_junk_transactions(); - $this->assertEquals($pretend_bot_creations, $num_deleted); - } - - -} diff --git a/tests/testcases/core/db_models/EEM_WP_User_Caps_Test.php b/tests/testcases/core/db_models/EEM_WP_User_Caps_Test.php deleted file mode 100644 index 4f78e9cb577..00000000000 --- a/tests/testcases/core/db_models/EEM_WP_User_Caps_Test.php +++ /dev/null @@ -1,64 +0,0 @@ -delete( array(), false ); - $this->me = $this->factory->user->create_and_get(); - $this->somebody_else = $this->factory->user->create_and_get(); - } - - function test_get_all__caps__not_logged_in() { - $this->assertEquals( 0, EEM_WP_User::instance()->count( array( 'caps' => EEM_Base::caps_read ) ) ); - } - - function test_get_all__caps__logged_in(){ - global $current_user; - $current_user = $this->me; - $results = EEM_WP_User::instance()->get_all( array( 'caps' => EEM_Base::caps_read ) ); - $this->assertEEModelObjectsEquals( EEM_WP_User::instance()->get_one_by_ID( $this->me->ID ), reset( $results ) ); - $this->assertEquals( 1, count( $results ) ); - } - - function test_get_all__caps__list_users(){ - global $current_user; - $current_user = $this->me; - $current_user->add_cap( 'list_users' ); - $results = EEM_WP_User::instance()->get_all( array( 'caps' => EEM_Base::caps_read ) ); - $this->assertEEModelObjectsEquals( EEM_WP_User::instance()->get_one_by_ID( $this->me->ID ), reset( $results ) ); - $this->assertEEModelObjectsEquals( EEM_WP_User::instance()->get_one_by_ID( $this->somebody_else->ID ), next( $results ) ); - $this->assertEquals( 2, count( $results ) ); - } -} - -// End of file EEM_WP_User_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/EEM_WP_User_Test.php b/tests/testcases/core/db_models/EEM_WP_User_Test.php deleted file mode 100644 index f6d7f1645b9..00000000000 --- a/tests/testcases/core/db_models/EEM_WP_User_Test.php +++ /dev/null @@ -1,27 +0,0 @@ -assertEquals( 1, EEM_WP_User::instance()->count() ); - } -} - -// End of file EEM_WP_User_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_All_Caps_Text_Field_Test.php b/tests/testcases/core/db_models/fields/EE_All_Caps_Text_Field_Test.php deleted file mode 100644 index 07db3b74abb..00000000000 --- a/tests/testcases/core/db_models/fields/EE_All_Caps_Text_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Payment::instance()->field_settings_for('PAY_source'); - $this->assertInstanceOf('EE_All_Caps_Text_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('string', $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%s', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Any_Foreign_Model_Name_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Any_Foreign_Model_Name_Field_Test.php deleted file mode 100644 index 39179c71015..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Any_Foreign_Model_Name_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Extra_Meta::instance()->field_settings_for('EXM_type'); - $this->assertInstanceOf('EE_Any_Foreign_Model_Name_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('string', $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%s', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Boolean_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Boolean_Field_Test.php deleted file mode 100644 index ab8bfe80f3f..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Boolean_Field_Test.php +++ /dev/null @@ -1,55 +0,0 @@ -_field = EEM_Checkin::instance()->field_settings_for('CHK_in'); - $this->assertInstanceOf('EE_Boolean_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('boolean', $this->_field->getSchemaType()); - } - - - public function test_prepare_for_pretty_echoing() - { - $this->assertEquals(__('Yes', 'event_espresso'), $this->_field->prepare_for_pretty_echoing(true)); - $this->assertEquals(__('No', 'event_espresso'), $this->_field->prepare_for_pretty_echoing(false)); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%d', $this->_field->get_wpdb_data_type()); - } -} diff --git a/tests/testcases/core/db_models/fields/EE_DB_Only_Float_Field_Test.php b/tests/testcases/core/db_models/fields/EE_DB_Only_Float_Field_Test.php deleted file mode 100644 index ce0b55e9474..00000000000 --- a/tests/testcases/core/db_models/fields/EE_DB_Only_Float_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Event::instance()->field_settings_for('EVTM_ID'); - $this->assertInstanceOf('EE_DB_Only_Float_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('number', $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%f', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_DB_Only_Int_Field_Test.php b/tests/testcases/core/db_models/fields/EE_DB_Only_Int_Field_Test.php deleted file mode 100644 index 0f0abcc3317..00000000000 --- a/tests/testcases/core/db_models/fields/EE_DB_Only_Int_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Attendee::instance()->field_settings_for('ATT_parent'); - $this->assertInstanceOf('EE_DB_Only_Int_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('integer', $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%d', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_DB_Only_Text_Field_Test.php b/tests/testcases/core/db_models/fields/EE_DB_Only_Text_Field_Test.php deleted file mode 100644 index e84e612e9ed..00000000000 --- a/tests/testcases/core/db_models/fields/EE_DB_Only_Text_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = new EE_DB_Only_Text_Field('post_type', __("Post Type", 'event_espresso'), false, 'espresso_events'); - $this->assertInstanceOf('EE_DB_Only_Text_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('string', $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%s', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Datetime_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Datetime_Field_Test.php deleted file mode 100644 index 2de314434bc..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Datetime_Field_Test.php +++ /dev/null @@ -1,439 +0,0 @@ -loadModelFieldMocks(array('EE_Datetime_Field')); - } - - - /** - * Used to set the _datetime_field property for tests with the provided params and set with defaults - * if none provided. - * - * @see EE_Datetime_Field for docs on params - * @param string $table_column - * @param string $nice_name - * @param bool $nullable - * @param string $default_value - * @param null $timezone - * @param null $date_format - * @param null $time_format - * @param null $pretty_date_format - * @param null $pretty_time_format - */ - protected function _set_dtt_field_object( - $table_column = 'DTT_EVT_start', - $nice_name = 'Start Date', - $nullable = false, - $default_value = '', - $timezone = null, - $date_format = null, - $time_format = null, - $pretty_date_format = null, - $pretty_time_format = null - ) { - $this->_datetime_field = new EE_Datetime_Field_Mock( - $table_column, - $nice_name, - $nullable, - $default_value, - $timezone, - $date_format, - $time_format, - $pretty_date_format, - $pretty_time_format - ); - } - - - /** - * This returns a common set of time strings for testing indexed by format. - * - * @return array - */ - protected function _get_time_strings_for_testing() - { - //set our expected properties - //setup some baselines to get expected values (the date/time strings match what is returned from _get_time_strings_for_testing ); - $datetimeZoneVC = new DateTimeZone('America/Vancouver'); - $datetimeZoneUTC = new DateTimeZone('UTC'); - $this->_defaultDTT = new DateTime('2015-02-20 11:38', $datetimeZoneVC); - - //formats we want to test - $date_formats = $this->date_formats_to_test(); - - //set the timezone to be America/Vancouver (UTC-8h Daylight UTC-7h) - $this->_datetime_field->set_timezone('America/Vancouver'); - - //set the expected Unix timestamp - $expectedDTT = clone $this->_defaultDTT; - $expectedDTT->setTimezone($datetimeZoneUTC); - $this->_expected_unixtimestamp = $expectedDTT->format('U'); - $this->_expected_mysqltimestamp = $expectedDTT->format('Y-m-d H:i:s'); - return $date_formats; - } - - - /** - * This ensures that when constructed the datetime field object is setup correctly - * - * @since 4.6 - */ - public function test_construct() - { - //instantiate a _datetime_field object for tests. - $this->_set_dtt_field_object(); - - //verify date_format - $this->assertEquals($this->_datetime_field->get_property('_date_format'), 'F j, Y'); - $this->assertEquals($this->_datetime_field->get_property('_time_format'), 'g:i a'); - $this->assertEquals($this->_datetime_field->get_property('_pretty_date_format'), 'F j, Y'); - $this->assertEquals($this->_datetime_field->get_property('_pretty_time_format'), 'g:i a'); - - //verify timezone. By default wp has the gmt_offset set to 0. So this means we convert that to UTC. - $this->assertEquals($this->_datetime_field->get_timezone(), 'UTC'); - } - - - /** - * Test getting a DateTimeZone object that has the UTC timezone set. - * - * @since 4.6 - */ - public function test_get_UTC_DateTimeZone() - { - $this->_set_dtt_field_object(); - $utcTz = $this->_datetime_field->get_UTC_DateTimeZone(); - $this->assertInstanceOf('DateTimeZone', $utcTz); - //should be in utc! - $this->assertEquals('UTC', $utcTz->getName()); - } - - - /** - * Test prepare_for_set method. - * - * @since 4.6 - */ - public function test_prepare_for_set() - { - //instantiate a _datetime_field object. Set timezone - $this->_set_dtt_field_object(); - - //grab our time strings - $timestrings = $this->_get_time_strings_for_testing(); - - //loop through timestrings and run tests - foreach ($timestrings['date'] as $format) { - $datetime = $this->_defaultDTT->format($format); - $this->_datetime_field->set_date_format($format); - foreach ($timestrings['time'] as $time_format) { - $dtt = $datetime . ' ' . $this->_defaultDTT->format($time_format); - $this->_datetime_field->set_time_format($time_format); - $dateobject = $this->_datetime_field->prepare_for_set($dtt); - $this->assertInstanceOf('DateTime', $dateobject); - //test expected value - $this->assertEquals($this->_expected_unixtimestamp, $dateobject->format('U')); - } - } - } - - - /** - * This tests the prepare_for_set_with_new_time method in EE_Datetime_Field - * - * @since 4.6 - */ - public function test_prepare_for_set_with_new_time() - { - $this->_set_dtt_field_object(); - $timestrings = $this->_get_time_strings_for_testing(); - - //clone defaultDTT to setup what our expected time offset unixtimestamp will be. - $DTToffset = clone $this->_defaultDTT; - $DTToffset->add(new DateInterval('PT2H')); - $expected = $DTToffset->format('U'); - - //loop through timestrings and run tests - foreach ($timestrings['time'] as $format) { - $this->_datetime_field->set_time_format($format); - $new_time_string = $this->_datetime_field->prepare_for_set_with_new_time($DTToffset->format($format), - $this->_defaultDTT); - $this->assertEquals($expected, $new_time_string->format('U'), - sprintf('Time Format is %s. Date format is %s.', $format, $this->_datetime_field->get_date_format())); - } - - //loop again except this time just send in the DateTime object. - foreach ($timestrings['time'] as $format) { - $this->_datetime_field->set_time_format($format); - $new_time_string = $this->_datetime_field->prepare_for_set_with_new_time($DTToffset, $this->_defaultDTT); - $this->assertEquals($expected, $new_time_string->format('U'), - sprintf('Time Format is %s. Date format is %s.', $format, $this->_datetime_field->get_date_format())); - } - } - - - /** - * This tests the prepare_for_set_with_new_date method in EE_Datetime_Field - * - * @since 4.6 - */ - public function test_prepare_for_set_with_new_date() - { - $this->_set_dtt_field_object(); - $timestrings = $this->_get_time_strings_for_testing(); - - //clone defaultDTT to setup what our expected time offset unixtimestamp will be. - $DTToffset = clone $this->_defaultDTT; - $DTToffset->add(new DateInterval('P2D')); - $expected = $DTToffset->format('U'); - - - //loop through timestrings and run tests - foreach ($timestrings['date'] as $format) { - $this->_datetime_field->set_date_format($format); - $new_time_string = $this->_datetime_field->prepare_for_set_with_new_date($DTToffset->format($format), - $this->_defaultDTT); - $this->assertEquals($expected, $new_time_string->format('U'), sprintf('Format is %s', $format)); - } - - - //loop again except this time just send in the DateTime object. - foreach ($timestrings['date'] as $format) { - $this->_datetime_field->set_date_format($format); - $new_time_string = $this->_datetime_field->prepare_for_set_with_new_date($DTToffset, $this->_defaultDTT); - $this->assertEquals($expected, $new_time_string->format('U'), sprintf('Format is %s.', $format)); - } - } - - - /** - * This tests the prepare_for_get method in EE_Datetime_Field - * - * @since 4.6 - */ - public function test_prepare_for_get() - { - $this->_set_dtt_field_object(); - $timestrings = $this->_get_time_strings_for_testing(); - - foreach ($timestrings['date'] as $dateformat) { - $this->_datetime_field->set_date_format($dateformat); - foreach ($timestrings['time'] as $timeformat) { - $this->_datetime_field->set_time_format($timeformat); - - //test date_time_output as time. - $this->_datetime_field->set_date_time_output('time'); - $output = $this->_datetime_field->prepare_for_get($this->_defaultDTT); - $this->assertEquals($output, $this->_defaultDTT->format($timeformat), - sprintf('Date Format: %s Time Format: %s', $dateformat, $timeformat)); - - //test date_time_output as date. - $this->_datetime_field->set_date_time_output('date'); - $output = $this->_datetime_field->prepare_for_get($this->_defaultDTT); - $this->assertEquals($output, $this->_defaultDTT->format($dateformat), - sprintf('Date Format: %s Time Format: %s', $dateformat, $timeformat)); - - //test date_time_output as date and time. - $this->_datetime_field->set_date_time_output('all'); - $output = $this->_datetime_field->prepare_for_get($this->_defaultDTT); - $this->assertEquals($output, $this->_defaultDTT->format($dateformat . ' ' . $timeformat), - sprintf('Date Format: %s Time Format: %s', $dateformat, $timeformat)); - } - } - } - - - /** - * Tests EE_Datetime_Field prepare_for_display method when it receives a - * invalid DateTime object on a non-nullable field and WP_DEBUG is true. - * - * @since 4.7.0 - * @expectedException EE_Error - * @expectedExceptionMessage EE_Datetime_Field::_prepare_for_display requires a DateTime class to be the value - * for the $DateTime argument because the Start Date field is not nullable. - */ - public function test_prepare_for_display_with_exception() - { - $this->_set_dtt_field_object(); - if (defined('WP_DEBUG') && ! WP_DEBUG) { - $this->markTestSkipped('Unable to complete test because WP_DEBUG is already defined and is set to false'); - } else { - if (! defined('WP_DEBUG')) { - define('WP_DEBUG', true); - } - } - - $this->_datetime_field->prepare_for_display(null); - } - - - /** - * Tests EE_Datetime_Field prepare_for_display method when it receives an invalid DateTime object on a - * non-nullable field and WP_DEBUG is false. - * - * @since 4.7.0 - */ - public function test_prepare_for_display_with_EE_Error() - { - if (defined('WP_DEBUG') && WP_DEBUG) { - $this->markTestSkipped('Unable to complete test because WP_DEBUG is already defined and is set to true'); - } - $this->_set_dtt_field_object(); - $this->_datetime_field->prepare_for_display(null); - //have error notice? - $notice = EE_Error::get_notices(false); - $notice = $notice['errors']; - $expected = 'An error has occurred:
EE_Datetime_Field::_prepare_for_display requires a DateTime class to be the value for the $DateTime argument because the Start Date field is not nullable. When WP_DEBUG is false, the value is set to "now" instead of throwing an exception.'; - $this->assertEquals($expected, $notice); - EE_Error::reset_notices(); - } - - /** - * @since 4.7.0 - */ - public function test_prepare_for_display() - { - $this->_set_dtt_field_object(); - - //set nullable allowed (non nullable allowed are in other tests). - $this->_datetime_field->set_nullable(); - - //test null value. - $this->assertEmpty($this->_datetime_field->prepare_for_display(null)); - - //non null values are tested by prepare_for_get_test - } - - - /** - * This tests the prepare_for_use_in_db method on EE_Datetime_Field - * - * @since 4.6 - */ - public function test_prepare_for_use_in_db() - { - $this->_set_dtt_field_object(); - $this->_get_time_strings_for_testing(); - - //test if not nullable and datestring is empty, then we should get back current_time in utc in mysql timestamp. - $this->assertEquals(date('Y-m-d H:i:s'), $this->_datetime_field->prepare_for_use_in_db(null)); - - //test if nullable and datestring is empty, then we should get null. - $this->_datetime_field->set_nullable(); - $this->assertNull($this->_datetime_field->prepare_for_use_in_db('')); - - //test getting the correct value for the set UTC timestamp - $this->assertEquals($this->_expected_mysqltimestamp, - $this->_datetime_field->prepare_for_use_in_db($this->_defaultDTT)); - } - - - /** - * This tests the prepare_for_set_from_db method in EE_Datetime_Field - * - * @since 4.6 - */ - public function test_prepare_for_set_from_db() - { - $this->_set_dtt_field_object(); - $this->_get_time_strings_for_testing(); - - //test if not nullable and datestring is empty, then we should get back datetime object. - $this->assertInstanceOf('DateTime', $this->_datetime_field->prepare_for_set_from_db('')); - - //test if nullable and datestring is empty, then we should get null. - $this->_datetime_field->set_nullable(); - $this->assertNull($this->_datetime_field->prepare_for_set_from_db('')); - - //test getting the correct value for the set UTC mysql timestamp - $this->assertEquals( - $this->_expected_unixtimestamp, - $this->_datetime_field->prepare_for_set_from_db($this->_expected_mysqltimestamp)->format('U') - ); - } - - - public function test_datetime_field_serialization() - { - if (version_compare(PHP_VERSION, '5.5', '<')) { - $this->markTestSkipped(); - } - $this->_set_dtt_field_object('LIN_timestamp', 'LIN_timestamp', false, EE_Datetime_Field::now); - $this->_get_time_strings_for_testing(); - $datetime_field = $this->_datetime_field; - $datetime_field = serialize($datetime_field); - $datetime_field = unserialize($datetime_field); - /** @var DateTime $datetime */ - $datetime = $datetime_field->get_date_object(''); - $this->assertInstanceOf('EventEspresso\core\domain\entities\DbSafeDateTime', $datetime); - // now serialize and unserialize - $datetime = serialize($datetime); - // ensure that a DateTime object was not serialized - $this->assertFalse(strpos($datetime, 'O:8:"DateTime"')); - $datetime = unserialize($datetime); - $this->assertInstanceOf('EventEspresso\core\domain\entities\DbSafeDateTime', $datetime); - } - - - public function test_getSchemaType() - { - $this->_set_dtt_field_object('LIN_timestamp', 'LIN_timestamp', false, EE_Datetime_Field::now); - $this->assertEquals('string', $this->_datetime_field->getSchemaType()); - } - - - public function test_get_wpdb_data_type() - { - $this->_set_dtt_field_object('LIN_timestamp', 'LIN_timestamp', false, EE_Datetime_Field::now); - $this->assertEquals('%s', $this->_datetime_field->get_wpdb_data_type()); - } -} -// end class EE_Datetime_Field_Test -// Location: tests/testcases/core/db_models/fields/EE_Datetime_Field_Test.php diff --git a/tests/testcases/core/db_models/fields/EE_Email_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Email_Field_Test.php deleted file mode 100644 index 0f61cb67199..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Email_Field_Test.php +++ /dev/null @@ -1,106 +0,0 @@ -_field = EEM_Attendee::instance()->field_settings_for('ATT_email'); - $this->assertInstanceOf('EE_Email_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals(array('string','null'), $this->_field->getSchemaType()); - } - - public function test_prepare_for_set() - { - $email_validation_levels = array( - 'basic' => true, - 'wp_default' => false, - 'i18n' => true, - ); - //only add `i18n_dns` validation check if mailcatcher isn't detected. Mailcatcher hijacks that dns checks. - if (strpos(ini_get('sendmail_path'), 'catchmail') === false) { - $email_validation_levels['i18n_dns'] = true; - } - foreach ($email_validation_levels as $email_validation_level => $test_should_pass) { - EE_Registry::instance()->CFG->registration->email_validation_level = $email_validation_level; - $this->set_email_field_value($email_validation_level, $test_should_pass); - } - } - - - /** - * @param bool $test_should_pass - * @throws \EE_Error - */ - public function set_email_field_value($validation_being_tested, $test_should_pass = true) - { - $international_email_address = 'jägerjürgen@deutschland.com'; - /** @var \EE_Email_Field $email_field */ - $email_field = $this->_field; - $actual_email_address = $email_field->prepare_for_set($international_email_address); - if ($test_should_pass) { - $this->assertEquals( - $international_email_address, - $actual_email_address, - sprintf( - 'Was ist das? Die E-Mail-Adresse des Teilnehmers sollte "%1$s", nicht "%2$s" sein (Validation Level: %3$s)!', - $international_email_address, - $actual_email_address, - $validation_being_tested - ) - // translation: - // What is this? The attendee's email address should be "jägerjürgen@deutschland.com", not "{actual result}" - ); - } else { - $this->assertNotEquals( - $international_email_address, - $actual_email_address, - sprintf( - 'Was ist das? Die E-Mail-Adresse des Teilnehmers sollte "", nicht "%1$s" sein (Validation Level: %2$s!', - $actual_email_address, - $validation_being_tested - ) - // translation: - // What is this? The attendee's email address should be "", not "{actual result}" - ); - } - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%s', $this->_field->get_wpdb_data_type()); - } - -} -// End of file EE_Email_Field_Test.php -// Location: tests/testcases/core/db_models/fields/EE_Email_Field_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Enum_Integer_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Enum_Integer_Field_Test.php deleted file mode 100644 index c46ac521ef8..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Enum_Integer_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Message::instance()->field_settings_for('MSG_priority'); - $this->assertInstanceOf('EE_Enum_Integer_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('object', $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%d', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Enum_Text_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Enum_Text_Field_Test.php deleted file mode 100644 index 2089f80025e..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Enum_Text_Field_Test.php +++ /dev/null @@ -1,114 +0,0 @@ -_an_enum_field = new EE_Enum_Text_Field( - 'A_field', - 'some field', - true, - 'b', - array( - 'a' => 'A', - 'b' => 'B', - 'c' => 'C' - ) - ); - } - - /** - * ensures that when valid input is provided, its left as-is - */ - public function test_prepare_for_set__valid() - { - $this->assertEquals('a',$this->_an_enum_field->prepare_for_set('a')); - $this->assertEquals('b',$this->_an_enum_field->prepare_for_set('b')); - } - - /** - * verifies that when invalid input is provided, it's replaced with the default - */ - public function test_prepare_for_set__invalid() - { - $this->assertEquals('b', $this->_an_enum_field->prepare_for_set('invalid')); - $this->assertEquals('b', $this->_an_enum_field->prepare_for_set('borked')); - //verify an error was issued if WP_DEBUG is on - $this->assertTrue( WP_DEBUG && EE_Error::has_error()); - EE_Error::reset_notices(); - } - - - - /** - * Verify that when retrieving from the DB, we're accepting of invalid input. - * That's because data might have gotten into the db via models - * when the filter FHEE__EE_Enum_Text_Field___allowed_enum_options - * was used, but then the filter callback got removed. In that case, - * we don't really want to change that existing data - * in the DB, and we certainly don't want to have errors because of it. - */ - public function test_prepare_for_set_from_db() - { - $this->assertEquals( - 'invalid-data-from-db', - $this->_an_enum_field->prepare_for_set_from_db('invalid-data-from-db') - ); - } - - - - /** - * Verify that when something borked got into the model - * (eg from prepare_for_set_from_db()) then it should actually - * stay that way, even inserting it into the DB. - * This way, if someone retrieves something borked from the DB and - * it gets set on the model, if they switch some other field - * on that model object and re-save it, this enum's "invalid" - * data won't get overridden. - * So if we want to enforce switching data back into a valid form, - * we need to explicitly do that, it won't happen - * automatically. - */ - public function test_prepare_for_use_in_db() - { - $this->assertEquals( - 'invalid-data-on-model-object', - $this->_an_enum_field->prepare_for_use_in_db('invalid-data-on-model-object') - ); - } - - - public function test_getSchemaType() - { - $this->assertEquals(array('object','null'), $this->_an_enum_field->getSchemaType()); - } - - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%s', $this->_an_enum_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Float_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Float_Field_Test.php deleted file mode 100644 index 0ad0266eb71..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Float_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Line_Item::instance()->field_settings_for('LIN_percent'); - $this->assertInstanceOf('EE_Float_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('number', $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%f', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Foreign_Key_Int_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Foreign_Key_Int_Field_Test.php deleted file mode 100644 index 6c3421badbb..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Foreign_Key_Int_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Checkin::instance()->field_settings_for('REG_ID'); - $this->assertInstanceOf('EE_Foreign_Key_Int_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('integer', $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%d', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Foreign_Key_String_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Foreign_Key_String_Field_Test.php deleted file mode 100644 index cd3ecc70e8b..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Foreign_Key_String_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Attendee::instance()->field_settings_for('CNT_ISO'); - $this->assertInstanceOf('EE_Foreign_Key_String_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals(array('string','null'), $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%s', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Full_HTML_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Full_HTML_Field_Test.php deleted file mode 100644 index 7726dd48996..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Full_HTML_Field_Test.php +++ /dev/null @@ -1,48 +0,0 @@ -_field = EEM_Line_Item::instance()->field_settings_for('LIN_name'); - $this->assertInstanceOf('EE_Full_HTML_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('object', $this->_field->getSchemaType()); - } - - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%s', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Infinite_Integer_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Infinite_Integer_Field_Test.php deleted file mode 100644 index c2c072ccda2..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Infinite_Integer_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Ticket::instance()->field_settings_for('TKT_qty'); - $this->assertInstanceOf('EE_Infinite_Integer_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals(array('integer', 'null'), $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%d', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Integer_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Integer_Field_Test.php deleted file mode 100644 index 208df2055db..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Integer_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Datetime::instance()->field_settings_for('DTT_sold'); - $this->assertInstanceOf('EE_Integer_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals(array('integer','null'), $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%d', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Maybe_Serialized_Simple_HTML_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Maybe_Serialized_Simple_HTML_Field_Test.php deleted file mode 100644 index 045463cd056..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Maybe_Serialized_Simple_HTML_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Answer::instance()->field_settings_for('ANS_value'); - $this->assertInstanceOf('EE_Maybe_Serialized_Simple_HTML_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals(array('object','string'), $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%s', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Maybe_Serialized_Text_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Maybe_Serialized_Text_Field_Test.php deleted file mode 100644 index 62f77141ed4..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Maybe_Serialized_Text_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Message::instance()->field_settings_for('MSG_content'); - $this->assertInstanceOf('EE_Maybe_Serialized_Text_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals(array('object','string','null'), $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%s', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Money_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Money_Field_Test.php deleted file mode 100644 index 70c66685bb2..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Money_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Price::instance()->field_settings_for('PRC_amount'); - $this->assertInstanceOf('EE_Money_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('object', $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%f', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Plain_Text_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Plain_Text_Field_Test.php deleted file mode 100644 index cfa3a36a4af..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Plain_Text_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Message::instance()->field_settings_for('MSG_token'); - $this->assertInstanceOf('EE_Plain_Text_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('string', $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%s', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Post_Content_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Post_Content_Field_Test.php deleted file mode 100644 index 13d23b56fba..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Post_Content_Field_Test.php +++ /dev/null @@ -1,112 +0,0 @@ -_field = EEM_Event::instance()->field_settings_for('EVT_desc'); - $this->assertInstanceOf('EE_Post_Content_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('object', $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%s', $this->_field->get_wpdb_data_type()); - } - - - /** - * @group 8405 - */ - public function test_prepare_for_pretty_echoing() - { - //use a simple mock shortcode to verify it gets replaced - add_shortcode( - 'mock', - function () { - return 'replacement'; - } - ); - $this->assertTrue( - strpos( - $this->_field->prepare_for_pretty_echoing('This is the shortcode: [mock]'), - 'This is the shortcode: replacement' - ) !== false - ); - } - - /** - * @group 8405 - */ - public function test_prepare_for_get() - { - //use a simple mock shortcode to verify it DOESN'T get replaced - add_shortcode( - 'mock', - function () { - return 'replacement'; - } - ); - $this->assertTrue( - strpos( - $this->_field->prepare_for_get('This is the shortcode: [mock]'), - 'This is the shortcode: replacement' - ) === false - ); - } - - public function test_prepare_for_set_with_valid_html() - { - $valid_html = 'Hey! This should stay.'; - $this->assertEquals($valid_html, $this->_field->prepare_for_set($valid_html)); - } - - - public function test_prepare_for_set_with_invalid_partial_html_tag() - { - $invalid_html = 'Hey! assertEquals($expected_result, $this->_field->prepare_for_set($invalid_html)); - } - - - public function test_prepare_for_set_with_invalid_full_html_tag() - { - $invalid_html = 'Hey! '; - $expected_result = 'Hey! '; - $this->assertEquals($expected_result, $this->_field->prepare_for_set($invalid_html)); - } - -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Primary_Key_Int_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Primary_Key_Int_Field_Test.php deleted file mode 100644 index beed488f337..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Primary_Key_Int_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Message::instance()->field_settings_for('MSG_ID'); - $this->assertInstanceOf('EE_Primary_Key_Int_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('integer', $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%d', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Primary_Key_String_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Primary_Key_String_Field_Test.php deleted file mode 100644 index ef81716e072..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Primary_Key_String_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Country::instance()->field_settings_for('CNT_ISO'); - $this->assertInstanceOf('EE_Primary_Key_String_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('string', $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%s', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Serialized_Text_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Serialized_Text_Field_Test.php deleted file mode 100644 index 9f24ec1ba36..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Serialized_Text_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Transaction::instance()->field_settings_for('TXN_session_data'); - $this->assertInstanceOf('EE_Serialized_Text_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals(array('object','string','null'), $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%s', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Simple_HTML_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Simple_HTML_Field_Test.php deleted file mode 100644 index 92d0daebb8b..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Simple_HTML_Field_Test.php +++ /dev/null @@ -1,69 +0,0 @@ -_field = EEM_Event::instance()->field_settings_for('EVT_short_desc'); - $this->assertInstanceOf('EE_Simple_HTML_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('string', $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%s', $this->_field->get_wpdb_data_type()); - } - - public function test_prepare_for_set_with_valid_html() - { - $valid_html = 'Hey! This should stay.'; - $this->assertEquals($valid_html, $this->_field->prepare_for_set($valid_html)); - } - - - public function test_prepare_for_set_with_invalid_partial_html_tag() - { - $invalid_html = 'Hey! assertEquals($expected_result, $this->_field->prepare_for_set($invalid_html)); - } - - - public function test_prepare_for_set_with_invalid_full_html_tag() - { - $invalid_html = 'Hey! '; - $expected_result = 'Hey! '; - $this->assertEquals($expected_result, $this->_field->prepare_for_set($invalid_html)); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Slug_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Slug_Field_Test.php deleted file mode 100644 index c3bccbe5fa4..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Slug_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Event::instance()->field_settings_for('EVT_slug'); - $this->assertInstanceOf('EE_Slug_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('string', $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%s', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_Trashed_Flag_Field_Test.php b/tests/testcases/core/db_models/fields/EE_Trashed_Flag_Field_Test.php deleted file mode 100644 index c77f2ff18db..00000000000 --- a/tests/testcases/core/db_models/fields/EE_Trashed_Flag_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Registration::instance()->field_settings_for('REG_deleted'); - $this->assertInstanceOf('EE_Trashed_Flag_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('boolean', $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%d', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_WP_Post_Status_Field_Test.php b/tests/testcases/core/db_models/fields/EE_WP_Post_Status_Field_Test.php deleted file mode 100644 index d522b6f26f0..00000000000 --- a/tests/testcases/core/db_models/fields/EE_WP_Post_Status_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Event::instance()->field_settings_for('status'); - $this->assertInstanceOf('EE_WP_Post_Status_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('object', $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%s', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_WP_Post_Type_Field_Test.php b/tests/testcases/core/db_models/fields/EE_WP_Post_Type_Field_Test.php deleted file mode 100644 index 7d6bd751a8a..00000000000 --- a/tests/testcases/core/db_models/fields/EE_WP_Post_Type_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Event::instance()->field_settings_for('post_type'); - $this->assertInstanceOf('EE_WP_Post_Type_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('string', $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%s', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/fields/EE_WP_User_Field_Test.php b/tests/testcases/core/db_models/fields/EE_WP_User_Field_Test.php deleted file mode 100644 index abb49991cb9..00000000000 --- a/tests/testcases/core/db_models/fields/EE_WP_User_Field_Test.php +++ /dev/null @@ -1,47 +0,0 @@ -_field = EEM_Event::instance()->field_settings_for('EVT_wp_user'); - $this->assertInstanceOf('EE_WP_User_Field', $this->_field); - } - - - public function tearDown() - { - $this->_field = null; - parent::tearDown(); - } - - - public function test_getSchemaType() - { - $this->assertEquals('integer', $this->_field->getSchemaType()); - } - - public function test_get_wpdb_data_type() - { - $this->assertEquals('%d', $this->_field->get_wpdb_data_type()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/db_models/strategies/EE_Default_Where_Conditions_Test.php b/tests/testcases/core/db_models/strategies/EE_Default_Where_Conditions_Test.php deleted file mode 100644 index ed488767caf..00000000000 --- a/tests/testcases/core/db_models/strategies/EE_Default_Where_Conditions_Test.php +++ /dev/null @@ -1,58 +0,0 @@ -factory->user->create_and_get(); - $value1 = 12; - $value2 = 23; - $value3= array( 1,2,3); - $value4 = 'eee'; - $default_where_conditions = new EE_Default_Where_Conditions(); - $default_where_conditions->_finalize_construct( EEM_Event::instance() ); - $this->assertEquals( - array( 'OR*' => array( 'Event.EVT_ID' => $value1, 'Event.Datetime.DTT_ID' => $value2 ), 'AND' => array( 'Event.EVT_name' => array( 'IN', $value3 ), 'Event.Datetime.DTT_name' => $value4 ), 'Event.EVT_wp_user' => $current_user->ID ), - $default_where_conditions->prepare_where_conditions_for_querying( - array( 'OR*' => array( 'EVT_ID' => $value1, 'Datetime.DTT_ID' => $value2 ), 'AND' => array( 'EVT_name' => array( 'IN', $value3 ), 'Datetime.DTT_name' => $value4 ), EEM_Event::instance()->wp_user_field_name() => EE_Default_Where_Conditions::current_user_placeholder ), 'Event.' )); - } - function test_wp_user_field_name(){ - $this->assertEquals( 'EVT_wp_user', EEM_Event::instance()->wp_user_field_name() ); - $this->assertEquals( 'Registration.Event.EVT_wp_user', EEM_Transaction::instance()->wp_user_field_name() ); - $this->assertEquals( 'TKT_wp_user', EEM_Ticket::instance()->wp_user_field_name() ); - } - - /** - * tests teh odd case where we want to add a model relation chain that goes back on itself - */ -// function test_add_model_relation_chain_onto_where_conditions__reciprocal_relation(){ -// $value1 = 12; -// $default_where_conditions = new EE_Default_Where_Conditions( array( 'Event.EVT_wp_user' => $value1 ) ); -// $default_where_conditions->_finalize_construct( EEM_Registration::instance() ); -// //pretend we were querying events, and we joined to the registrations model, and so the -// //registration's model added a default where condition to only return registrations for events owned -// //by teh current user. eg EEM_Event::instance()->get_all( array( array( 'Registration.REG_ID' => 12 ) ); -// $this->assertEquals( -// array( -// 'EVT_wp_user' => $value1 -// //NOT Event.Event.EVT_wp_user -// ) -// , -// $default_where_conditions->add_model_relation_chain_onto_where_conditions( array( 'Event.EVT_wp_user' => $value1 ), 'Registration.' )); -// } -} - -// End of file EE_Default_Where_Conditions_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/strategies/EE_Restriciton_Generator_Protected_Test.php b/tests/testcases/core/db_models/strategies/EE_Restriciton_Generator_Protected_Test.php deleted file mode 100644 index b04705706fd..00000000000 --- a/tests/testcases/core/db_models/strategies/EE_Restriciton_Generator_Protected_Test.php +++ /dev/null @@ -1,80 +0,0 @@ -_construct_finalize( EEM_Transaction::instance(), EEM_Base::caps_read ); - $restrictions = $generator->generate_restrictions(); - foreach ( $restrictions as $default_where_conditions ) { - $default_where_conditions->_finalize_construct( EEM_Registration::instance() ); - } - $this->assertArrayHasKey( 'ee_read_transactions', $restrictions ); - $this->assertInstanceOf( 'EE_Return_None_Where_Conditions', $restrictions[ 'ee_read_transactions' ] ); - $this->assertEquals( 1, count( $restrictions ) ); - } - - function test_generate_restrictions__basic_and_others() { - global $current_user; - $current_user = $this->factory->user->create_and_get(); - //currently registrations have the 'ee_read_registrations' and 'ee_read_others_registrations' permissions - //if that changes, this will need to be updated - $generator = new EE_Restriction_Generator_Protected(); - $generator->_construct_finalize( EEM_Registration::instance(), EEM_Base::caps_read ); - $restrictions = $generator->generate_restrictions(); - foreach ( $restrictions as $default_where_conditions ) { - $default_where_conditions->_finalize_construct( EEM_Registration::instance() ); - } - $this->assertArrayHasKey( 'ee_read_registrations', $restrictions ); - $this->assertInstanceOf( 'EE_Return_None_Where_Conditions', $restrictions[ 'ee_read_registrations' ] ); - $this->assertArrayHasKey( 'ee_read_others_registrations', $restrictions ); - $this->assertInstanceOf( 'EE_Default_Where_Conditions', $restrictions[ 'ee_read_others_registrations' ] ); - $this->assertEquals( array( EEM_Registration::instance()->wp_user_field_name() => get_current_user_id() ), $restrictions[ 'ee_read_others_registrations' ]->get_default_where_conditions() ); - $this->assertEquals( 2, count( $restrictions ) ); - } - - function test_generate_restrictions__basic_and_others_and_private() { - //currently events have the 'ee_read_events', 'ee_read_others_events', and 'ee_read_others_private_events' caps - //if that changes, this will need to be updated - $generator = new EE_Restriction_Generator_Protected(); - $generator->_construct_finalize( EEM_Event::instance(), EEM_Base::caps_read ); - $restrictions = $generator->generate_restrictions(); - foreach ( $restrictions as $default_where_conditions ) { - $default_where_conditions->_finalize_construct( EEM_Event::instance() ); - } - $this->assertArrayHasKey( 'ee_read_events', $restrictions ); - $this->assertInstanceOf( 'EE_Return_None_Where_Conditions', $restrictions[ 'ee_read_events' ] ); - - $this->assertArrayHasKey( 'ee_read_others_events', $restrictions ); - $this->assertInstanceOf( 'EE_Default_Where_Conditions', $restrictions[ 'ee_read_others_events' ] ); - $this->assertEquals( - array( EEM_Event::instance()->wp_user_field_name() => get_current_user_id() ), $restrictions[ 'ee_read_others_events' ]->get_default_where_conditions() ); - - $this->assertArrayHasKey( 'ee_read_private_events', $restrictions ); - $this->assertInstanceOf( 'EE_Default_Where_Conditions', $restrictions[ 'ee_read_private_events' ] ); - $this->assertEquals( array( - 'OR*no_' . EE_Restriction_Generator_Base::get_cap_name( EEM_Event::instance(), 'read_private' ) => array( - EEM_Event::instance()->wp_user_field_name() => get_current_user_id(), - 'status' => array( '!=', 'private' ) ) ), $restrictions[ 'ee_read_private_events' ]->get_default_where_conditions() ); - $this->assertEquals( 3, count( $restrictions ) ); - } - -} - -// End of file EE_Restriciton_Generator_Protected_Test.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/strategies/EE_Restriction_Generator_Base_Test.php b/tests/testcases/core/db_models/strategies/EE_Restriction_Generator_Base_Test.php deleted file mode 100644 index 52de7a6a5fa..00000000000 --- a/tests/testcases/core/db_models/strategies/EE_Restriction_Generator_Base_Test.php +++ /dev/null @@ -1,29 +0,0 @@ -assertEquals( 'ee_edit_events', EE_Restriction_Generator_Base::get_cap_name(EEM_Event::instance(), 'edit' ) ); - $this->assertEquals( 'ee_read_private_venues', EE_Restriction_Generator_Base::get_cap_name( EEM_Venue::instance(), 'read_private' ) ); - } - - function test_is_cap(){ - $this->assertTrue( EE_Restriction_Generator_Base::is_cap( EEM_Event::instance(), 'edit' ) ); - $this->assertTrue( EE_Restriction_Generator_Base::is_cap( EEM_Event::instance(), 'edit_others' ) ); - $this->assertFalse( EE_Restriction_Generator_Base::is_cap( EEM_Event::instance(), 'rock' ) ); - } -} - -// End of file EE_Restriction_Generator_Base.php \ No newline at end of file diff --git a/tests/testcases/core/db_models/strategies/EE_Restriction_Generator_Meta_Test.php b/tests/testcases/core/db_models/strategies/EE_Restriction_Generator_Meta_Test.php deleted file mode 100644 index 612b768c134..00000000000 --- a/tests/testcases/core/db_models/strategies/EE_Restriction_Generator_Meta_Test.php +++ /dev/null @@ -1,67 +0,0 @@ -_construct_finalize( EEM_Post_Meta::instance(), EEM_Base::caps_read ); - $restrictions = $generator->generate_restrictions(); - $this->assertArrayHasKey( EE_Restriction_Generator_Base::get_default_restrictions_cap(), $restrictions ); - $this->assertArrayHasKey( 'apply-to-all-queries-using-caps', $restrictions ); - $this->assertInstanceOf( 'EE_Return_None_Where_Conditions', $restrictions[ EE_Restriction_Generator_Base::get_default_restrictions_cap() ] ); - $restrictions_for_all_cap_contexts = $restrictions[ 'apply-to-all-queries-using-caps' ]; - $this->assertInstanceOf( 'EE_Default_Where_Conditions', $restrictions_for_all_cap_contexts ); - $this->assertEquals( - array( - 'meta_key' => array( 'NOT_LIKE', "\\\\_%" ), - 'meta_value' => array( 'NOT_REGEXP', '^[aOs]:[\d]:.*$') - ), - $restrictions_for_all_cap_contexts->get_default_where_conditions() - ); - } - - public function test_no_caps__whitelisted_and_blacklisted() { - add_filter( 'FHEE__EE_Restriction_Generator_Meta___generate_restrictions__whitelisted_meta_keys', array( $this, '_whitelist_metas' ) ); - add_filter( 'FHEE__EE_Restriction_Generator_Meta___generate_restrictions__blacklisted_meta_keys', array( $this, '_blacklist_metas' ) ); - $generator = new EE_Restriction_Generator_Meta( 'meta_key', 'meta_value' ); - $generator->_construct_finalize( EEM_Post_Meta::instance(), EEM_Base::caps_read ); - $restrictions = $generator->generate_restrictions(); - $this->assertArrayHasKey( EE_Restriction_Generator_Base::get_default_restrictions_cap(), $restrictions ); - $this->assertArrayHasKey( 'apply-to-all-queries-using-caps', $restrictions ); - $this->assertInstanceOf( 'EE_Return_None_Where_Conditions', $restrictions[ EE_Restriction_Generator_Base::get_default_restrictions_cap() ] ); - $restrictions_for_all_cap_contexts = $restrictions[ 'apply-to-all-queries-using-caps' ]; - $this->assertInstanceOf( 'EE_Default_Where_Conditions', $restrictions_for_all_cap_contexts ); - $this->assertEquals( - array( - 'OR*whitelisted-or-normal' => array( - 'meta_key*whitelisted' => array( 'IN', array( 'white' ) ), - 'AND' => array( - 'meta_key' => array( 'NOT_LIKE', "\\\\_%" ), - 'meta_value' => array( 'NOT_REGEXP', '^[aOs]:[\d]:.*$'), - 'meta_key*blacklisted' => array( 'NOT_IN', array( 'black' ) ), - ), - ), - ), - $restrictions_for_all_cap_contexts->get_default_where_conditions() - ); - } - - public function _whitelist_metas( $whitelisted_metas ) { - return array( 'white' ); - } - - public function _blacklist_metas( $blacklisted_metas ) { - return array( 'black' ); - } -} diff --git a/tests/testcases/core/db_models/strategies/EE_Return_None_Where_Conditions_Test.php b/tests/testcases/core/db_models/strategies/EE_Return_None_Where_Conditions_Test.php deleted file mode 100644 index 6a6c2d1ca5b..00000000000 --- a/tests/testcases/core/db_models/strategies/EE_Return_None_Where_Conditions_Test.php +++ /dev/null @@ -1,30 +0,0 @@ -_finalize_construct( EEM_Registration::instance() ); - $this->assertEquals( - array( - 'Event.Registration.REG_ID' => array('<', 0 ) - ) - , - $default_where_conditions->get_default_where_conditions( 'Event.Registration' )); - } -} - -// End of file EE_Return_None_Where_Conditions_Test.php \ No newline at end of file diff --git a/tests/testcases/core/domain/DomainFactoryTest.php b/tests/testcases/core/domain/DomainFactoryTest.php deleted file mode 100644 index 9e07bfb353a..00000000000 --- a/tests/testcases/core/domain/DomainFactoryTest.php +++ /dev/null @@ -1,91 +0,0 @@ -assertInstanceOf('EventEspresso\tests\mocks\core\domain\DomainMock', $domain_mock); - $this->assertInstanceOf('EventEspresso\core\domain\DomainBase', $domain_mock); - $this->assertEquals($file_path, $domain_mock->pluginFile()); - $this->assertEquals(plugin_basename($file_path), $domain_mock->pluginBasename()); - $this->assertEquals(plugin_dir_path($file_path),$domain_mock->pluginPath()); - $this->assertEquals(plugin_dir_url($file_path),$domain_mock->pluginUrl()); - $this->assertEquals(plugin_dir_url($file_path),$domain_mock->pluginUrl()); - $this->assertEquals($version, $domain_mock->version()); - $this->assertEquals('Oh Yeah', $domain_mock->returnOhYeah()); - } - - - public function test_constructor_with_invalid_arguments() - { - $this->setExceptionExpected('InvalidArgumentException'); - DomainFactory::getShared( - new FullyQualifiedName( - 'EventEspresso\tests\mocks\core\domain\DomainMock' - ), - array() - ); - } - - - public function test_constructor_with_invalid_arguments_2() - { - $this->setExceptionExpected('InvalidArgumentException'); - DomainFactory::getShared( - new FullyQualifiedName( - 'EventEspresso\tests\mocks\core\domain\DomainMock' - ), - array(new FilePath(EE_TESTS_DIR . 'mocks/core/domain/DomainMock.php')) - ); - } - - - public function test_constructor_with_invalid_arguments_3() - { - $this->setExceptionExpected('DomainException'); - DomainFactory::getShared( - new FullyQualifiedName( - 'EventEspresso\core\domain\values\FilePath' - ), - array( - EE_TESTS_DIR . 'mocks/core/domain/DomainMock.php', - '1.2.3.p' - ) - ); - } - -} -// Location: DomainFactoryTest.php diff --git a/tests/testcases/core/domain/entities/DbSafeDateTimeTest.php b/tests/testcases/core/domain/entities/DbSafeDateTimeTest.php deleted file mode 100644 index a7b98b31498..00000000000 --- a/tests/testcases/core/domain/entities/DbSafeDateTimeTest.php +++ /dev/null @@ -1,79 +0,0 @@ -assertEquals( - $original_datetime->format('Y-m-d H:m:i'), - $test_datetime->format('Y-m-d H:m:i'), - sprintf('The timezone string: %s isn\'t working', $timezone_string) - ); - } - } - - - - public function test_serialization_and_unserialization_with_empty_datetime_string() - { - $utc = new DateTimeZone('UTC'); - $empty_datetime = new DateTime('0000-00-00 00:00:00.000000', $utc); - $db_safe_datetime = new DbSafeDateTime($empty_datetime->format('Y-m-d H:i:s.u'), $utc); - // serializing the above will write to the PHP error log, - // so we are going to set that path to something else, so that we can grab that error - $log_file = EVENT_ESPRESSO_UPLOAD_DIR . 'logs' . DS . 'espresso_unit_tests_errors.log'; - EEH_File::ensure_file_exists_and_is_writable($log_file); - $db_safe_datetime->setErrorLogDir($log_file); - // now perform the serialization - $serialized_datetime = serialize($db_safe_datetime); - // and grab the error log file - $errors = file_get_contents($log_file); - if ($errors) { - $this->assertNotFalse(strpos($errors, 'A valid DateTime could not be generated')); - } - unlink($log_file); - $db_safe_datetime = unserialize($serialized_datetime); - $this->assertInstanceOf('DateTime', $db_safe_datetime); - // still vot a valid date, but at least this won't cause additional errors - $this->assertEquals( - '-0001-11-30 00:00:00.000000', - $db_safe_datetime->format('Y-m-d H:i:s.u') - ); - // and just verify that nothing changed - $this->assertEquals( - $empty_datetime->format('Y-m-d H:i:s.u'), - $db_safe_datetime->format('Y-m-d H:i:s.u') - ); - } - - - -} -// end of file DbSafeDateTimeTest.php -// Location: /tests/testcases/core/domain/entities/DbSafeDateTimeTest.php \ No newline at end of file diff --git a/tests/testcases/core/domain/services/custom_post_types/RegisterCustomPostTypesTest.php b/tests/testcases/core/domain/services/custom_post_types/RegisterCustomPostTypesTest.php deleted file mode 100644 index e23d1f7cdaa..00000000000 --- a/tests/testcases/core/domain/services/custom_post_types/RegisterCustomPostTypesTest.php +++ /dev/null @@ -1,290 +0,0 @@ -custom_post_types = LoaderFactory::getLoader()->getShared( - 'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' - ); - EE_Dependency_Map::register_dependencies( - 'EventEspresso\tests\mocks\core\domain\services\custom_post_types\RegisterCustomPostTypesMock', - array( - 'EventEspresso\core\domain\entities\custom_post_types\CustomPostTypeDefinitions' => EE_Dependency_Map::load_from_cache, - ) - ); - $this->register_custom_post_types = LoaderFactory::getLoader()->getShared( - 'EventEspresso\tests\mocks\core\domain\services\custom_post_types\RegisterCustomPostTypesMock' - ); - } - - - /** - * @since 4.9.62.p - */ - public function testPrepareArguments() - { - $custom_post_types = $this->custom_post_types->getDefinitions(); - foreach ($custom_post_types as $custom_post_type => $CPT) { - $this->assertEquals( - $this->getExpected($custom_post_type), - $this->register_custom_post_types->prepareArguments( - $custom_post_type, - $CPT['singular_name'], - $CPT['plural_name'], - $CPT['singular_slug'], - $CPT['plural_slug'], - $CPT['args'] - ), - "The prepared arguments for {$custom_post_type} do not match what is expected." - ); - } - } - - - /** - * @since 4.9.62.p - * @param string $custom_post_type - * @return array|mixed - */ - public function getExpected($custom_post_type) - { - $custom_post_types = array( - 'espresso_events' => array( - 'labels' => array( - 'name' => 'Events', - 'singular_name' => 'Event', - 'singular_slug' => 'event', - 'plural_slug' => 'events', - 'add_new' => 'Add Event', - 'add_new_item' => 'Add New Event', - 'edit_item' => 'Edit Event', - 'new_item' => 'New Event', - 'all_items' => 'All Events', - 'view_item' => 'View Event', - 'search_items' => 'Search Events', - 'not_found' => 'No Events found', - 'not_found_in_trash' => 'No Events found in Trash', - 'parent_item_colon' => '', - 'menu_name' => 'Events', - ), - 'public' => true, - 'publicly_queryable' => true, - 'show_ui' => false, - 'show_ee_ui' => true, - 'show_in_menu' => false, - 'show_in_nav_menus' => true, - 'query_var' => true, - 'rewrite' => array( - 'slug' => 'events', - ), - 'capability_type' => 'event', - 'map_meta_cap' => true, - 'has_archive' => true, - 'hierarchical' => false, - 'menu_position' => - null, - 'supports' => array( - 0 => 'title', - 1 => 'editor', - 2 => 'author', - 3 => 'thumbnail', - 4 => 'excerpt', - 5 => 'custom-fields', - 6 => 'comments', - ), - 'capabilities' => array( - 'edit_post' => 'ee_edit_event', - 'read_post' => 'ee_read_event', - 'delete_post' => 'ee_delete_event', - 'edit_posts' => 'ee_edit_events', - 'edit_others_posts' => 'ee_edit_others_events', - 'publish_posts' => 'ee_publish_events', - 'read_private_posts' => 'ee_read_private_events', - 'delete_posts' => 'ee_delete_events', - 'delete_private_posts' => 'ee_delete_private_events', - 'delete_published_posts' => 'ee_delete_published_events', - 'delete_others_posts' => 'ee_delete_others_events', - 'edit_private_posts' => 'ee_edit_private_events', - 'edit_published_posts' => 'ee_edit_published_events', - ), - 'taxonomies' => array( - 0 => 'espresso_event_categories', - 1 => 'espresso_event_type', - 2 => 'post_tag', - ), - 'page_templates' => true, - ), - 'espresso_venues' => array( - 'labels' => array( - 'name' => 'Venues', - 'singular_name' => 'Venue', - 'singular_slug' => 'venue', - 'plural_slug' => 'venues', - 'add_new' => 'Add Venue', - 'add_new_item' => 'Add New Venue', - 'edit_item' => 'Edit Venue', - 'new_item' => 'New Venue', - 'all_items' => 'All Venues', - 'view_item' => 'View Venue', - 'search_items' => 'Search Venues', - 'not_found' => 'No Venues found', - 'not_found_in_trash' => 'No Venues found in Trash', - 'parent_item_colon' => '', - 'menu_name' => 'Venues', - ), - 'public' => true, - 'publicly_queryable' => true, - 'show_ui' => false, - 'show_ee_ui' => true, - 'show_in_menu' => false, - 'show_in_nav_menus' => true, - 'query_var' => true, - 'rewrite' => array( - 'slug' => 'venues', - ), - 'capability_type' => 'venue', - 'map_meta_cap' => true, - 'has_archive' => true, - 'hierarchical' => false, - 'menu_position' => - null, - 'supports' => array( - 0 => 'title', - 1 => 'editor', - 2 => 'author', - 3 => 'thumbnail', - 4 => 'excerpt', - 5 => 'custom-fields', - 6 => 'comments', - ), - 'capabilities' => array( - 'edit_post' => 'ee_edit_venue', - 'read_post' => 'ee_read_venue', - 'delete_post' => 'ee_delete_venue', - 'edit_posts' => 'ee_edit_venues', - 'edit_others_posts' => 'ee_edit_others_venues', - 'publish_posts' => 'ee_publish_venues', - 'read_private_posts' => 'ee_read_private_venues', - 'delete_posts' => 'ee_delete_venues', - 'delete_private_posts' => 'ee_delete_private_venues', - 'delete_published_posts' => 'ee_delete_published_venues', - 'delete_others_posts' => 'ee_edit_others_venues', - 'edit_private_posts' => 'ee_edit_private_venues', - 'edit_published_posts' => 'ee_edit_published_venues', - ), - 'taxonomies' => array( - 0 => 'espresso_venue_categories', - 1 => 'post_tag', - ), - 'page_templates' => true, - ), - 'espresso_attendees' => array( - 'labels' => array( - 'name' => 'Contacts', - 'singular_name' => 'Contact', - 'singular_slug' => 'contact', - 'plural_slug' => 'contacts', - 'add_new' => 'Add Contact', - 'add_new_item' => 'Add New Contact', - 'edit_item' => 'Edit Contact', - 'new_item' => 'New Contact', - 'all_items' => 'All Contacts', - 'view_item' => 'View Contact', - 'search_items' => 'Search Contacts', - 'not_found' => 'No Contacts found', - 'not_found_in_trash' => 'No Contacts found in Trash', - 'parent_item_colon' => '', - 'menu_name' => 'Contacts', - ), - 'public' => false, - 'publicly_queryable' => false, - 'show_ui' => false, - 'show_ee_ui' => true, - 'show_in_menu' => false, - 'show_in_nav_menus' => false, - 'query_var' => true, - 'rewrite' => array( - 'slug' => 'contacts', - ), - 'capability_type' => 'contact', - 'map_meta_cap' => true, - 'has_archive' => false, - 'hierarchical' => false, - 'menu_position' => - null, - 'supports' => array( - 0 => 'editor', - 1 => 'thumbnail', - 2 => 'excerpt', - 3 => 'custom-fields', - 4 => 'comments', - ), - 'taxonomies' => array( - 0 => 'post_tag', - ), - 'capabilities' => array( - 'edit_post' => 'ee_edit_contact', - 'read_post' => 'ee_read_contact', - 'delete_post' => 'ee_delete_contact', - 'edit_posts' => 'ee_edit_contacts', - 'edit_others_posts' => 'ee_edit_contacts', - 'publish_posts' => 'ee_edit_contacts', - 'read_private_posts' => 'ee_edit_contacts', - 'delete_posts' => 'ee_delete_contacts', - 'delete_private_posts' => 'ee_delete_contacts', - 'delete_published_posts' => 'ee_delete_contacts', - 'delete_others_posts' => 'ee_delete_contacts', - 'edit_private_posts' => 'ee_edit_contacts', - 'edit_published_posts' => 'ee_edit_contacts', - ), - ), - ); - return isset($custom_post_types[ $custom_post_type ]) ? $custom_post_types[ $custom_post_type ] : array(); - } -} -// location: tests/testcases/core/domain/services/custom_post_types/RegisterCustomPostTypesTest.php \ No newline at end of file diff --git a/tests/testcases/core/domain/services/custom_post_types/RegisterCustomTaxonomiesTest.php b/tests/testcases/core/domain/services/custom_post_types/RegisterCustomTaxonomiesTest.php deleted file mode 100644 index 658a72ddfaf..00000000000 --- a/tests/testcases/core/domain/services/custom_post_types/RegisterCustomTaxonomiesTest.php +++ /dev/null @@ -1,170 +0,0 @@ -custom_taxonomies = LoaderFactory::getLoader()->getShared( - 'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' - ); - EE_Dependency_Map::register_dependencies( - 'EventEspresso\tests\mocks\core\domain\services\custom_post_types\RegisterCustomTaxonomiesMock', - array( - 'EventEspresso\core\domain\entities\custom_post_types\CustomTaxonomyDefinitions' => EE_Dependency_Map::load_from_cache, - ) - ); - $this->register_custom_taxonomies = LoaderFactory::getLoader()->getShared( - 'EventEspresso\tests\mocks\core\domain\services\custom_post_types\RegisterCustomTaxonomiesMock' - ); - } - - - /** - * @since 4.9.62.p - */ - public function testPrepareArguments() - { - $custom_taxonomies = $this->custom_taxonomies->getCustomTaxonomyDefinitions(); - foreach ($custom_taxonomies as $taxonomy => $tax) { - $this->assertEquals( - $this->getExpected($taxonomy), - $this->register_custom_taxonomies->prepareArguments( - $tax['singular_name'], - $tax['plural_name'], - $tax['args'] - ) - ); - } - } - - - /** - * @since 4.9.62.p - * @param string $taxonomy - * @return array|mixed - */ - public function getExpected($taxonomy) - { - $custom_taxonomies = array( - 'espresso_event_categories' => array( - 'hierarchical' => true, - 'labels' => array( - 'name' => 'Event Categories', - 'singular_name' => 'Event Category', - ), - 'show_ui' => true, - 'show_ee_ui' => true, - 'show_admin_column' => true, - 'query_var' => true, - 'show_in_nav_menus' => true, - 'map_meta_cap' => true, - 'public' => true, - 'show_in_rest' => true, - 'capabilities' => array( - 'manage_terms' => 'ee_manage_event_categories', - 'edit_terms' => 'ee_edit_event_category', - 'delete_terms' => 'ee_delete_event_category', - 'assign_terms' => 'ee_assign_event_category', - ), - 'rewrite' => array( - 'slug' => 'event-category', - ), - ), - 'espresso_venue_categories' => array( - 'hierarchical' => true, - 'labels' => array( - 'name' => 'Venue Categories', - 'singular_name' => 'Venue Category', - ), - 'show_ui' => true, - 'show_ee_ui' => true, - 'show_admin_column' => true, - 'query_var' => true, - 'show_in_nav_menus' => true, - 'map_meta_cap' => true, - 'public' => true, - 'show_in_rest' => true, - 'capabilities' => array( - 'manage_terms' => 'ee_manage_venue_categories', - 'edit_terms' => 'ee_edit_venue_category', - 'delete_terms' => 'ee_delete_venue_category', - 'assign_terms' => 'ee_assign_venue_category', - ), - 'rewrite' => array( - 'slug' => 'venue-category', - ), - ), - 'espresso_event_type' => array( - 'hierarchical' => true, - 'labels' => array( - 'name' => 'Event Types', - 'singular_name' => 'Event Type', - ), - 'show_ui' => false, - 'show_ee_ui' => true, - 'show_admin_column' => true, - 'query_var' => true, - 'show_in_nav_menus' => false, - 'map_meta_cap' => true, - 'public' => true, - 'show_in_rest' => true, - 'capabilities' => array( - 'manage_terms' => 'ee_read_event_type', - 'edit_terms' => 'ee_edit_event_type', - 'delete_terms' => 'ee_delete_event_type', - 'assign_terms' => 'ee_assign_event_type', - ), - 'rewrite' => array( - 'slug' => 'event-type', - ), - ), - ); - return isset($custom_taxonomies[$taxonomy]) ? $custom_taxonomies[ $taxonomy ] : array(); - } -} -// location: tests/testcases/core/domain/services/custom_post_types/RegisterCustomTaxonomiesTest.php - - - diff --git a/tests/testcases/core/domain/values/FilePathTest.php b/tests/testcases/core/domain/values/FilePathTest.php deleted file mode 100644 index dd80ee09a1f..00000000000 --- a/tests/testcases/core/domain/values/FilePathTest.php +++ /dev/null @@ -1,58 +0,0 @@ -assertInstanceOf('EventEspresso\core\domain\values\FilePath', $filepath); - } - - - public function test_constructor_with_invalid_data_type() - { - $this->setExceptionExpected('EventEspresso\core\exceptions\InvalidDataTypeException'); - new FilePath(1234); - } - - - public function test_constructor_with_invalid_filepath() - { - $this->setExceptionExpected('EventEspresso\core\exceptions\InvalidFilePathException'); - new FilePath(__FILE__ . '.totallynotmalware'); - } - - - public function test_toString() - { - $filepath = new FilePath(__FILE__); - $this->assertEquals(__FILE__, (string) $filepath); - $this->assertEquals( - 'This is located at ' . EE_TESTS_DIR . 'testcases/core/domain/values/FilePathTest.php', - "This is located at {$filepath}" - ); - } - - -} -// Location: FilePathTest.php diff --git a/tests/testcases/core/domain/values/FullyQualifiedNameTest.php b/tests/testcases/core/domain/values/FullyQualifiedNameTest.php deleted file mode 100644 index 15218d542ec..00000000000 --- a/tests/testcases/core/domain/values/FullyQualifiedNameTest.php +++ /dev/null @@ -1,63 +0,0 @@ -assertInstanceOf('EventEspresso\core\domain\values\FullyQualifiedName', $fqcn); - } - - public function test_constructor_with_invalid_data_type() - { - $this->setExceptionExpected('EventEspresso\core\exceptions\InvalidDataTypeException'); - new FullyQualifiedName(1234); - } - - - public function test_constructor_with_invalid_class_name() - { - $this->setExceptionExpected('EventEspresso\core\exceptions\InvalidClassException'); - new FullyQualifiedName('EventExpresso\tests\testcases\core\domain\values\FullyQualifiedNameTest'); - } - - - public function test_constructor_with_invalid_interface() - { - $this->setExceptionExpected('EventEspresso\core\exceptions\InvalidInterfaceException'); - new FullyQualifiedName('EventEspresso\tests\testcases\core\domain\values\FullyQualifiedNameInterface'); - } - - - public function test_toString() - { - $fqcn = new FullyQualifiedName(__CLASS__); - $this->assertEquals(__CLASS__, (string) $fqcn); - $this->assertEquals( - 'This test is part of the EventEspresso\tests\testcases\core\domain\values\FullyQualifiedNameTest class', - "This test is part of the {$fqcn} class" - ); - } - -} -// Location: FullyQualifiedNameTest.php diff --git a/tests/testcases/core/domain/values/UrlTest.php b/tests/testcases/core/domain/values/UrlTest.php deleted file mode 100644 index da2bb0b0272..00000000000 --- a/tests/testcases/core/domain/values/UrlTest.php +++ /dev/null @@ -1,301 +0,0 @@ -setExceptionExpected('InvalidArgumentException'); - } - $url = new Url($url_string); - $this->assertInstanceOf('EventEspresso\core\domain\values\Url', $url); - } - - - /** - * @return array - */ - public function schemeProvider() - { - return array( - array( - 'http://local.wordpress.dev', - 'http://', - ), - array( - 'https://local.wordpress.dev/wp-admin/admin.php', - 'https://', - ), - array( - 'abc://username:password@example.com:123/path/data?key=value#fragid1', - 'abc://', - ), - ); - } - - - /** - * @dataProvider schemeProvider - * @param string $url_string - * @param string $scheme - * @throws Exception - */ - public function testScheme($url_string, $scheme) - { - $url = new Url($url_string); - $this->assertInstanceOf('EventEspresso\core\domain\values\Url', $url); - $this->assertEquals($scheme, $url->scheme()); - } - - - /** - * @return array - */ - public function hostProvider() - { - return array( - array( - 'http://local.wordpress.dev', - 'local.wordpress.dev', - ), - array( - 'https://www.eventespresso.com/', - 'www.eventespresso.com', - ), - array( - 'abc://username:password@example.com:123/path/data?key=value#fragid1', - 'example.com', - ), - ); - } - - - /** - * @dataProvider hostProvider - * @param string $url_string - * @param string $host - * @throws Exception - */ - public function testHost($url_string, $host) - { - $url = new Url($url_string); - $this->assertInstanceOf('EventEspresso\core\domain\values\Url', $url); - $this->assertEquals($host, $url->host()); - } - - - /** - * @return array - */ - public function pathProvider() - { - return array( - array( - 'http://local.wordpress.dev', - '', - ), - array( - 'https://local.wordpress.dev/wp-admin/admin.php', - '/wp-admin/admin.php', - ), - array( - 'abc://username:password@example.com:123/path/data?key=value#fragid1', - '/path/data', - ), - ); - } - - - /** - * @dataProvider pathProvider - * @param string $url_string - * @param string $path - * @throws Exception - */ - public function testPath($url_string, $path) - { - $url = new Url($url_string); - $this->assertInstanceOf('EventEspresso\core\domain\values\Url', $url); - $this->assertEquals($path, $url->path()); - } - - - /** - * @return array - */ - public function queryProvider() - { - return array( - array( - 'http://local.wordpress.dev', - '', - array(), - ), - array( - 'http://local.wordpress.dev/wp-admin/admin.php?page=espresso_events&action=edit&post=39', - '?page=espresso_events&action=edit&post=39', - array( - 'page' => 'espresso_events', - 'action' => 'edit', - 'post' => '39', - ), - ), - array( - 'abc://username:password@example.com:123/path/data?key=value#fragid1', - '?key=value', - array('key' => 'value'), - ), - ); - } - - - /** - * @dataProvider queryProvider - * @param string $url_string - * @param string $query_string - * @param array $query_params - * @throws Exception - */ - public function testQueryStringAndQueryParams($url_string, $query_string, array $query_params) - { - $url = new Url($url_string); - $this->assertInstanceOf('EventEspresso\core\domain\values\Url', $url); - $this->assertEquals($query_string, $url->queryString()); - $this->assertEquals($query_params, $url->queryParams()); - } - - - /** - * @return array - */ - public function fragmentProvider() - { - return array( - array( - 'http://local.wordpress.dev', - '', - ), - array( - 'http://local.wordpress.dev/registration-checkout/?uts=1513717329#checkout', - '#checkout', - ), - array( - 'abc://username:password@example.com:123/path/data?key=value#fragid1', - '#fragid1', - ), - ); - } - - - /** - * @dataProvider fragmentProvider - * @param string $url_string - * @param string $fragment - * @throws Exception - */ - public function testFragment($url_string, $fragment) - { - $url = new Url($url_string); - $this->assertInstanceOf('EventEspresso\core\domain\values\Url', $url); - $this->assertEquals($fragment, $url->fragment()); - } - - - /** - * @return array - */ - public function fullUrlProvider() - { - return array( - array( - 'http://local.wordpress.dev', - 'http://local.wordpress.dev', - ), - array( - 'http://local.wordpress.dev/registration-checkout/?uts=1513717329#checkout', - 'http://local.wordpress.dev/registration-checkout/?uts=1513717329#checkout', - ), - array( - 'abc://username:password@example.com:123/path/data?key=value#fragid1', - 'abc://example.com/path/data?key=value#fragid1', - ), - ); - } - - - /** - * @dataProvider fullUrlProvider - * @param string $url_string - * @param string $full_url - * @throws Exception - */ - public function testGetFullUrl($url_string, $full_url) - { - $url = new Url($url_string); - $this->assertInstanceOf('EventEspresso\core\domain\values\Url', $url); - $this->assertEquals($full_url, $url->getFullUrl()); - ob_start(); - echo $url; - $this->assertEquals($full_url, ob_get_clean()); - } -} diff --git a/tests/testcases/core/domain/values/VersionTest.php b/tests/testcases/core/domain/values/VersionTest.php deleted file mode 100644 index 5250d82d602..00000000000 --- a/tests/testcases/core/domain/values/VersionTest.php +++ /dev/null @@ -1,369 +0,0 @@ -assertInstanceOf('EventEspresso\core\domain\values\Version', $version); - } - - - - /** - * @return array - */ - public function invalidMajorMinorPatchProvider() - { - return array( - array(1.1, 2, 3, 'rc', 4), - array(1, 2.1, 3, 'rc', 4), - array(1, 2, 'three', 'rc', 4), - array(1, 2, 3, 3.5, 4, 'InvalidArgumentException'), - array(1, 2, 3, 'release', 4, 'InvalidArgumentException'), - array(1, 2, 3, 'decaff', 4, 'InvalidArgumentException'), - array(1, 2, 3, 'rc', 4.1), - array(1, 2, 3, 'rc', '001'), - ); - } - - - /** - * @dataProvider invalidMajorMinorPatchProvider - * @param $major - * @param $minor - * @param $patch - * @param string $release - * @param int $build - * @param string $exception - * @throws Exception - */ - public function testConstructorWithInvalidParameters( - $major, - $minor, - $patch, - $release = Version::RELEASE_TYPE_PROD, - $build = 0, - $exception = 'EventEspresso\core\exceptions\InvalidDataTypeException' - ) { - $this->setExceptionExpected($exception); - new Version($major, $minor, $patch, $release, $build); - } - - - - /** - * @return array - */ - public function validVersionStringProvider() - { - return array( - array(espresso_version(), espresso_version()), - array('1.2.3.rc.4', '1.2.3.rc.004'), - array('1.2.3.beta', '1.2.3.beta.000'), - array('1.2.3.decaf.123', '1.2.3.decaf'), - array('1.2.3.decaf', '1.2.3.decaf'), - array('1.2.3.p.123', '1.2.3.p'), - array('1.2.3.p', '1.2.3.p'), - array('1.2.3', '1.2.3.p'), - ); - } - - - - /** - * @dataProvider validVersionStringProvider - * @param string $version_string - * @param string $expected - * @throws Exception - * @throws InvalidArgumentException - */ - public function testFromString($version_string, $expected) - { - // using EE version method - $version = Version::fromString($version_string); - $this->assertInstanceOf('EventEspresso\core\domain\values\Version', $version); - $this->assertEquals($expected, "{$version}"); - } - - - - /** - * @return array - */ - public function invalidVersionStringProvider() - { - return array( - array('1.2.3.alpha.4'), - array('moar.betterer.version.for.$5000'), - array('Oh come on!!! This isn\'t even a version string!!!'), - ); - } - - - /** - * @dataProvider invalidVersionStringProvider - * @param string $version_string - * @throws Exception - * @throws InvalidArgumentException - */ - public function testFromStringWithInvalidData($version_string) - { - $this->setExceptionExpected('InvalidArgumentException'); - Version::fromString($version_string); - } - - - /** - * @return array - */ - public function majorMinorPatchReleaseAndBuildProvider() - { - return array( - array(1, 2, 3, 'rc', 4), - array(1, 2, 3, 'beta', 4), - array(1, 2, 3, 'decaf', 4), - array(1, 2, 3, 'p', 4), - array(1, 2, 3, 'p'), - array(1, 2, 3), - ); - } - - - /** - * @dataProvider validMajorMinorPatchProvider - * @param $major - * @param $minor - * @param $patch - * @param string $release - * @param int $build - * @throws Exception - */ - public function testMajorMinorPatchReleaseAndBuild( - $major, - $minor, - $patch, - $release = Version::RELEASE_TYPE_PROD, - $build = 0 - ) { - $version = new Version($major, $minor, $patch, $release, $build); - $this->assertEquals($major, $version->major()); - $this->assertEquals($minor, $version->minor()); - $this->assertEquals($patch, $version->patch()); - $this->assertEquals($release, $version->release()); - $this->assertEquals($build, $version->build()); - } - - - - /** - * @return array - */ - public function versionCompareProvider() - { - return array( - 'major version compare' => array( - 'version' => new Version(2, 2, 3, 'p', 0), - 'older version' => new Version(1, 2, 3, 'p', 0), - 'same version' => new Version(2, 2, 3, 'p', 0), - 'newer version' => new Version(3, 2, 3, 'p', 0), - ), - 'minor version compare' => array( - 'version' => new Version(1, 2, 3, 'p', 0), - 'older version' => new Version(1, 1, 3, 'p', 0), - 'same version' => new Version(1, 2, 3, 'p', 0), - 'newer version' => new Version(1, 3, 3, 'p', 0), - ), - 'patch version compare' => array( - 'version' => new Version(1, 2, 3, 'p', 0), - 'older version' => new Version(1, 2, 2, 'p', 0), - 'same version' => new Version(1, 2, 3, 'p', 0), - 'newer version' => new Version(1, 2, 4, 'p', 0), - ), - 'release version compare' => array( - 'version' => new Version(1, 2, 3, 'rc', 0), - 'older version' => new Version(1, 2, 3, 'beta', 0), - 'same version' => new Version(1, 2, 3, 'rc', 0), - 'newer version' => new Version(1, 2, 3, 'p', 0), - ), - 'build version compare' => array( - 'version' => new Version(1, 2, 3, 'rc', 2), - 'older version' => new Version(1, 2, 3, 'rc', 1), - 'same version' => new Version(1, 2, 3, 'rc', 2), - 'newer version' => new Version(1, 2, 3, 'rc', 3), - ), - ); - } - - - - /** - * @dataProvider versionCompareProvider - * @param Version $version - * @param Version $older_version - * @param Version $same_version - * @param Version $newer_version - */ - public function testCompare( - Version $version, - Version $older_version, - Version $same_version, - Version $newer_version - ) { - // current version is newer so result == 1 - $this->assertEquals(1, $version->compare($older_version)); - // current version is same so result == 0 - $this->assertEquals(0, $version->compare($same_version)); - // current version is older so result == -1 - $this->assertEquals(-1, $version->compare($newer_version)); - } - - - /** - * @dataProvider versionCompareProvider - * @param Version $version - * @param Version $older_version - * @param Version $same_version - * @param Version $newer_version - */ - public function testEquals( - Version $version, - Version $older_version, - Version $same_version, - Version $newer_version - ) { - $this->assertFalse($version->equals($older_version)); - $this->assertFalse( $version->equals($newer_version)); - $this->assertTrue($version->equals($same_version)); - } - - - /** - * @dataProvider versionCompareProvider - * @param Version $version - * @param Version $older_version - * @param Version $same_version - * @param Version $newer_version - */ - public function testNewerThan( - Version $version, - Version $older_version, - Version $same_version, - Version $newer_version - ) { - $this->assertFalse( $version->newerThan($same_version)); - $this->assertFalse($version->newerThan($newer_version)); - $this->assertTrue($version->newerThan($older_version)); - } - - - /** - * @dataProvider versionCompareProvider - * @param Version $version - * @param Version $older_version - * @param Version $same_version - * @param Version $newer_version - */ - public function testOlderThan( - Version $version, - Version $older_version, - Version $same_version, - Version $newer_version - ) { - $this->assertFalse( $version->olderThan($same_version)); - $this->assertFalse($version->olderThan($older_version)); - $this->assertTrue($version->olderThan($newer_version)); - } - - - /** - * @return array - */ - public function toStringProvider() - { - return array( - array('1.2.3.rc.004', 1, 2, 3, 'rc', 4), - array('1.2.3.beta.004', 1, 2, 3, 'beta', 4), - array('1.2.3.decaf', 1, 2, 3, 'decaf', 4), - array('1.2.3.decaf', 1, 2, 3, 'decaf'), - array('1.2.3.p', 1, 2, 3, 'p', 4), - array('1.2.3.p', 1, 2, 3, 'p'), - array('1.2.3.p', 1, 2, 3), - ); - } - - - /** - * @dataProvider toStringProvider - * @param string $expected - * @param int $major - * @param int $minor - * @param int $patch - * @param string $release - * @param int $build - * @throws Exception - */ - public function testToString ( - $expected, - $major, - $minor, - $patch, - $release = Version::RELEASE_TYPE_PROD, - $build = 0 - ) { - $version = new Version($major, $minor, $patch, $release, $build); - $this->assertInstanceOf('EventEspresso\core\domain\values\Version', $version); - $this->assertEquals($expected, (string) $version); - $this->assertEquals($expected, "{$version}"); - } - - -} -// Location: VersionTest.php diff --git a/tests/testcases/core/domain/values/model/CustomSelectsTests.php b/tests/testcases/core/domain/values/model/CustomSelectsTests.php deleted file mode 100644 index 53a09772780..00000000000 --- a/tests/testcases/core/domain/values/model/CustomSelectsTests.php +++ /dev/null @@ -1,131 +0,0 @@ - '%s', 'REG_ID' => '%s', 'TXN_ID' => '%s') - ), - array( - CustomSelects::TYPE_COMPLEX, - array( - 'attendee_id' => array('ATT_ID', '%s'), - 'registration_count' => array('count(REG_ID)', '%d'), - 'transaction_total' => array('sum(TXN_total)', '%f') - ), - 'ATT_ID AS attendee_id, count(REG_ID) AS registration_count, sum(TXN_total) AS transaction_total', - array('attendee_id', 'registration_count', 'transaction_total'), - array('attendee_id' => '%s', 'registration_count' => '%d', 'transaction_total' => '%f') - ), - array( - CustomSelects::TYPE_STRUCTURED, - array( - 'attendee_id' => array('ATT_ID', '', '%s'), - 'registration_count' => array('REG_ID', 'count', '%d'), - 'transaction_total' => array('TXN_total', 'sum', '%f') - ), - 'ATT_ID AS attendee_id, COUNT(REG_ID) AS registration_count, SUM(TXN_total) AS transaction_total', - array('attendee_id', 'registration_count', 'transaction_total'), - array('attendee_id' => '%s', 'registration_count' => '%d', 'transaction_total' => '%f') - ) - ); - } - - - /** - * @return array - */ - public function typeSelectFailsProvider() - { - return array( - array( - array('ATT_ID', 'REG_ID' => 2) - ), - array( - array('attendee_id' => 'something') - ), - array( - array('attendee_id' => array('count(REG_ID)', '%d', 'count')) - ) - ); - } - - - /** - * @dataProvider typesSelectProvider - * @param string $type - * @param array $incoming_select_array - * @param string $expected__columns_to_select - * @param array $expected_column_aliases - * @param array $expected_data_types_for_aliases - * @throws InvalidArgumentException - */ - public function testTypes( - $type, - array $incoming_select_array, - $expected__columns_to_select, - array $expected_column_aliases, - array $expected_data_types_for_aliases - ) { - $select = new CustomSelects($incoming_select_array); - $this->assertEquals($incoming_select_array, $select->originalSelects()); - $this->assertEquals( - $expected__columns_to_select, - $select->columnsToSelectExpression() - ); - $this->assertEquals( - $expected_column_aliases, - $select->columnAliases() - ); - $this->assertEquals( - $type, - $select->type() - ); - //data types - foreach ($expected_data_types_for_aliases as $alias => $data_type) { - $this->assertEquals($data_type, $select->getDataTypeForAlias($alias)); - } - $this->assertEquals( - '%s', - $select->getDataTypeForAlias('ATT_ID') - ); - } - - - /** - * @dataProvider typeSelectFailsProvider - * @param array $incoming_select_array - * @throws InvalidArgumentException - * @throws Exception - */ - public function testTypeFails(array $incoming_select_array) - { - $this->setExceptionExpected('InvalidArgumentException'); - $select = new CustomSelects($incoming_select_array); - } -} diff --git a/tests/testcases/core/helpers/EEH_Activation_Test.php b/tests/testcases/core/helpers/EEH_Activation_Test.php deleted file mode 100644 index 39938f17b16..00000000000 --- a/tests/testcases/core/helpers/EEH_Activation_Test.php +++ /dev/null @@ -1,264 +0,0 @@ -load_lib( 'Message_Resource_Manager' ); - // messengers that have been activated and verified installed - $active_messengers = $message_resource_manager->active_messengers(); - // ALL installed messengers regardless of whether they are active or not - $installed_messengers = $message_resource_manager->installed_messengers(); - $should_be_installed = array(); - foreach( $active_messengers as $msgr ) { - $this->assertInstanceOf( 'EE_messenger', $msgr ); - if ( $msgr->activate_on_install ) { - $should_be_installed[] = $msgr->name; - } - } - //loop through $should_be_installed and verify that those that should be active ARE active. - foreach ( $should_be_installed as $msgr_name ) { - $this->assertTrue( - isset( $installed_messengers[ $msgr_name ] ), - sprintf( 'The messenger %s should be active on fresh install, but it is not.', $msgr_name ) - ); - } - - //now verify that the code doesn't run new message template generation etc. - $this->assertFalse( EEH_Activation::generate_default_message_templates() ); - - - // now we simulate someone who's deactivated a messenger - // and we simulate a migration that triggers generating default message templates again. - // The html messenger should STICK and NOT be activated. - $message_resource_manager->deactivate_messenger( 'html' ); - - //do the same for message type - $message_resource_manager->deactivate_message_type_for_messenger( 'not_approved', 'email' ); - - //Reset messages to test stickiness - EE_Registry::reset(); - - $activated_response = EEH_Activation::generate_default_message_templates(); - - //verify we got a response (html should not have templates generated) - $this->assertFalse( $activated_response ); - - // double check we still don't have html in the active messengers array - $active_messengers = $message_resource_manager->get_active_messengers_option( true ); - $this->assertFalse( isset( $active_messengers['html'] ) ); - $this->assertFalse( $message_resource_manager->is_message_type_active_for_messenger( 'email', 'not_approved' ) ); - } - - - - - - /** - * This tests the generate_default_message_templates method with using the - * FHEE__EE_messenger__get_default_message_types__default_types filter to add a - * bogus message_type string. No errors should be triggered, and the invalid default mt - * should NOT be added to the active array for the messenger. - * - * @since 4.6 - * @group 7595 - */ - public function test_filtered_default_message_types_on_activation() { - /** @type EE_Message_Resource_Manager $message_resource_manager */ - $message_resource_manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' ); - //let's clear out all active messengers to get an accurate test of initial generation of message templates. - global $wpdb; - // delete message_template_group templates - $message_template_group_table = $wpdb->prefix . 'esp_message_template_group'; - $query = "DELETE FROM $message_template_group_table WHERE 'GRP_ID' > 0"; - $wpdb->query( $query ); - // delete message_template templates - $message_template_table = $wpdb->prefix . 'esp_message_template'; - $query = "DELETE FROM $message_template_table WHERE 'MTP_ID' > 0"; - $wpdb->query($query); - // delete event_message_template templates - $event_message_template_table = $wpdb->prefix . 'esp_event_message_template'; - $query = "DELETE FROM $event_message_template_table WHERE 'EMT_ID' > 0"; - $wpdb->query( $query ); - - $message_resource_manager->update_active_messengers_option( array() ); - //set a filter for the invalid message type - add_filter( - 'FHEE__EE_messenger__get_default_message_types__default_types', - function( $default_types ) { - $default_types[] = 'bogus_message_type'; - return $default_types; - }, 10, 2 - ); - - try { - //activate messages... if there's any problems then errors will trigger a fail. - EEH_Activation::generate_default_message_templates(); - } catch( EE_Error $e ){ - $this->assertInstanceOf( 'EE_Error', $e ); - } - - //all went well so let's make sure the activated system does NOT have our invalid message type string. - $active_messengers = $message_resource_manager->get_active_messengers_option( true ); - foreach( $active_messengers as $messenger => $settings ) { - $this->assertFalse( - isset( $settings[ 'settings' ][ $messenger . '-message_types' ][ 'bogus_message_type' ] ), - sprintf( 'The %s messenger should not have "bogus_message_type" active on it but it does.', $messenger ) - ); - } - } - - - - - /** - * Ensure getting default creator works as expected - * @since 4.6.0 - */ - public function test_get_default_creator_id() { - //clear out any previous users that may be lurking in teh system - foreach( get_users() as $wp_user ){ - wp_delete_user( $wp_user->ID ); - } - //set some users; and just make it interesting by having the first user NOT be an admin - $this->factory->user->create_many( 2 ); - $users = $this->factory->user->create_many( 2 ); - //make users administrators. - foreach ( $users as $user_id ) { - $user = $this->factory->user->get_object_by_id( $user_id ); - //verify - $this->assertInstanceOf( 'WP_User', $user ); - //add role - $user->add_role( 'administrator' ); - } - - //get all users so we know who is the first one that we should be expecting. - $expected_id = reset( $users ); - $this->assertEquals( EEH_Activation::get_default_creator_id(), $expected_id ); - - /** - * ok now let's verify EEH_Activation::reset() properly clears the cache - * on EEH_Activation. This is important for subsequent unit tests (because - * EEH_Activation::reset() is called between unit tests), but also when an admin - * resets their EE database, or when anyone wants to reset that cache) - * clear out any previous users that may be lurking in teh system - */ - EEH_Activation::reset(); - foreach( get_users() as $wp_user ){ - wp_delete_user( $wp_user->ID ); - } - //set some users; and just make it interesting by having the first user NOT be an admin - $this->factory->user->create_many( 2 ); - $users_created_after_reset = $this->factory->user->create_many( 2 ); - //make users administrators. - foreach ( $users_created_after_reset as $user_id ) { - $user = $this->factory->user->get_object_by_id( $user_id ); - //verify - $this->assertInstanceOf( 'WP_User', $user ); - //add role - $user->add_role( 'administrator' ); - } - - //get all users so we know who is the first one that we should be expecting. - $new_expected_id = reset( $users_created_after_reset ); - $this->assertEquals( EEH_Activation::get_default_creator_id(), $new_expected_id ); - - } - - function test_get_cron_tasks__old() { - add_filter( 'FHEE__EEH_Activation__get_cron_tasks', array( $this, 'change_cron_tasks' ) ); - $old_cron_tasks = EEH_Activation::get_cron_tasks( 'old' ); - $this->assertArrayHasKey( self::expired_cron_task_name, $old_cron_tasks ); - $this->assertArrayNotHasKey( self::current_cron_task_name, $old_cron_tasks ); - } - function test_get_cron_tasks__all() { - add_filter( 'FHEE__EEH_Activation__get_cron_tasks', array( $this, 'change_cron_tasks' ) ); - $old_cron_tasks = EEH_Activation::get_cron_tasks( 'all' ); - $this->assertArrayHasKey( self::expired_cron_task_name, $old_cron_tasks ); - $this->assertArrayHasKey( self::current_cron_task_name, $old_cron_tasks ); - } - - - /** - * @see https://events.codebasehq.com/projects/event-espresso/tickets/9501 - * @since 4.8.36 - */ - function test_remove_cron_tasks_with_empty_timestamp_values() { - //first cache existing cron array - $old_cron_option = _get_cron_array(); - //merge in a bunch of empty timestamps - $empty_timestamps = array( - time() + 30 => array(), - time() + 600 => array(), - time() - 400 => array() - ); - _set_cron_array( - array_merge( $empty_timestamps, $old_cron_option ) - ); - - //now let's run the EEH_Activation::remove_cron_tasks - EEH_Activation::remove_cron_tasks(); - - //and verify that there are no empty timestamps - $updated_cron_option = _get_cron_array(); - $this->assertEquals( count( $old_cron_option ), count( $updated_cron_option ) ); - - //now restore - _set_cron_array( $old_cron_option ); - } - - - /** - * Makes it so this function can be independent on what the current cron tasks actually are - * (because they'll likely change, whereas some of these functions just want to check that - * we are retrieving cron tasks correctly) - * - * @param array $old_cron_tasks - * @return array - */ - function change_cron_tasks( $old_cron_tasks ) { - return array( - self::current_cron_task_name => 'hourly', - self::expired_cron_task_name => EEH_Activation::cron_task_no_longer_in_use - ); - } - - function test_table_exists__success() { - $this->assertTrue( EEH_Activation::table_exists( 'posts' ) ); - $this->assertTrue( EEH_Activation::table_exists( 'esp_attendee_meta' ) ); - } - - function test_table_exists__false() { - $this->assertFalse( EEH_Activation::table_exists( 'monkeys' ) ); - } - - - -} //end class EEH_Activation_Test -// location: tests/testcases/core/helpers/EEH_Activation_Test.php diff --git a/tests/testcases/core/helpers/EEH_Array_Test.php b/tests/testcases/core/helpers/EEH_Array_Test.php deleted file mode 100644 index ffcff9f70fb..00000000000 --- a/tests/testcases/core/helpers/EEH_Array_Test.php +++ /dev/null @@ -1,214 +0,0 @@ - 'apple', - 'b' => 'banana', - ); - // add to start - $fruits = EEH_Array::insert_into_array( $fruits, array( 'c' => 'coconut' ) ); - $this->assertEquals( 'coconut', reset( $fruits ) ); - $this->assertEquals( 'apple', next( $fruits ) ); - $this->assertEquals( 'banana', next( $fruits ) ); - // add to end - $fruits = EEH_Array::insert_into_array( $fruits, array( 'd' => 'date' ), null, false ); - $this->assertEquals( 'coconut', reset( $fruits ) ); - $this->assertEquals( 'apple', next( $fruits ) ); - $this->assertEquals( 'banana', next( $fruits ) ); - $this->assertEquals( 'date', next( $fruits ) ); - // add to middle BEFORE 'banana' - $fruits = EEH_Array::insert_into_array( $fruits, array( 'e' => 'elderberry' ), 'b' ); - $this->assertEquals( 'coconut', reset( $fruits ) ); - $this->assertEquals( 'apple', next( $fruits ) ); - $this->assertEquals( 'elderberry', next( $fruits ) ); - $this->assertEquals( 'banana', next( $fruits ) ); - $this->assertEquals( 'date', next( $fruits ) ); - } - - - - /** - * test_insert_into_array_with_numeric_indexes - */ - function test_insert_into_array_with_numeric_indexes() { - // starting data - $fruits = array( - 1 => 'one', - 2 => 'two' - ); - // add to start - $fruits = EEH_Array::insert_into_array( $fruits, array( 3 => 'three' ) ); - //echo '$fruits: ', var_dump( $fruits ); - $this->assertEquals( 'three', reset( $fruits ) ); - $this->assertEquals( 'one', next( $fruits ) ); - $this->assertEquals( 'two', next( $fruits ) ); - // add to end - $fruits = EEH_Array::insert_into_array( $fruits, array( 4 => 'four' ), null, false ); - $this->assertEquals( 'three', reset( $fruits ) ); - $this->assertEquals( 'one', next( $fruits ) ); - $this->assertEquals( 'two', next( $fruits ) ); - $this->assertEquals( 'four', next( $fruits ) ); - // add to middle before 2 - $fruits = EEH_Array::insert_into_array( $fruits, array( 5 => 'five' ), 2 ); - $this->assertEquals( 'three', reset( $fruits ) ); - $this->assertEquals( 'one', next( $fruits ) ); - $this->assertEquals( 'five', next( $fruits ) ); - $this->assertEquals( 'two', next( $fruits ) ); - $this->assertEquals( 'four', next( $fruits ) ); - // try to bork keys and add onto the end while also specifying the last known key - $fruits = EEH_Array::insert_into_array( $fruits, array( 6 => 'six' ), 4, false ); - //echo '$fruits: ', var_dump( $fruits ); - $this->assertEquals( 'three', reset( $fruits ) ); - $this->assertEquals( 'one', next( $fruits ) ); - $this->assertEquals( 'five', next( $fruits ) ); - $this->assertEquals( 'two', next( $fruits ) ); - $this->assertEquals( 'four', next( $fruits ) ); - $this->assertEquals( 'six', next( $fruits ) ); - // add to end and reindex keys - $fruits = EEH_Array::insert_into_array( $fruits, array( 7 => 'seven' ), null, false, false ); - $this->assertEquals( 'three', reset( $fruits ) ); - $this->assertEquals( 'one', next( $fruits ) ); - $this->assertEquals( 'five', next( $fruits ) ); - $this->assertEquals( 'two', next( $fruits ) ); - $this->assertEquals( 'four', next( $fruits ) ); - $this->assertEquals( 'six', next( $fruits ) ); - $this->assertEquals( 'seven', next( $fruits ) ); - // now test keys - reset( $fruits ); - $this->assertEquals( 0, key( $fruits ) ); - next( $fruits ); - $this->assertEquals( 1, key( $fruits ) ); - next( $fruits ); - $this->assertEquals( 2, key( $fruits ) ); - next( $fruits ); - $this->assertEquals( 3, key( $fruits ) ); - next( $fruits ); - $this->assertEquals( 4, key( $fruits ) ); - next( $fruits ); - $this->assertEquals( 5, key( $fruits ) ); - next( $fruits ); - $this->assertEquals( 6, key( $fruits ) ); - } - - - - /** - * test_insert_into_array_with_mixed_indexes - */ - function test_insert_into_array_with_mixed_indexes() { - // starting data - $fruits = array( - 1 => 'one', - 'p' => 'potato' - ); - // add to start - $fruits = EEH_Array::insert_into_array( $fruits, array( 2 => 'two' ) ); - //echo '$fruits: ', var_dump( $fruits ); - $this->assertEquals( 'two', reset( $fruits ) ); - $this->assertEquals( 'one', next( $fruits ) ); - $this->assertEquals( 'potato', next( $fruits ) ); - // add to end - $fruits = EEH_Array::insert_into_array( $fruits, array( 't' => 'tomato' ), null, false ); - //echo '$fruits: ', var_dump( $fruits ); - $this->assertEquals( 'two', reset( $fruits ) ); - $this->assertEquals( 'one', next( $fruits ) ); - $this->assertEquals( 'potato', next( $fruits ) ); - $this->assertEquals( 'tomato', next( $fruits ) ); - // add to middle before potato - $fruits = EEH_Array::insert_into_array( $fruits, array( 3 => 'three' ), 'p' ); - //echo '$fruits: ', var_dump( $fruits ); - $this->assertEquals( 'two', reset( $fruits ) ); - $this->assertEquals( 'one', next( $fruits ) ); - $this->assertEquals( 'three', next( $fruits ) ); - $this->assertEquals( 'potato', next( $fruits ) ); - $this->assertEquals( 'tomato', next( $fruits ) ); - // try to bork keys and add onto the end while also specifying the last known key - $fruits = EEH_Array::insert_into_array( $fruits, array( 6 => 'tornado' ), 't', false ); - $this->assertEquals( 'two', reset( $fruits ) ); - $this->assertEquals( 'one', next( $fruits ) ); - $this->assertEquals( 'three', next( $fruits ) ); - $this->assertEquals( 'potato', next( $fruits ) ); - $this->assertEquals( 'tomato', next( $fruits ) ); - $this->assertEquals( 'tornado', next( $fruits ) ); - // add to end and reindex keys - $fruits = EEH_Array::insert_into_array( $fruits, array( 'g' => 'GO NATO' ), null, false, false ); - $this->assertEquals( 'two', reset( $fruits ) ); - $this->assertEquals( 'one', next( $fruits ) ); - $this->assertEquals( 'three', next( $fruits ) ); - $this->assertEquals( 'potato', next( $fruits ) ); - $this->assertEquals( 'tomato', next( $fruits ) ); - $this->assertEquals( 'tornado', next( $fruits ) ); - $this->assertEquals( 'GO NATO', next( $fruits ) ); - // now test keys - reset( $fruits ); - $this->assertEquals( 0, key( $fruits ) ); - next( $fruits ); - $this->assertEquals( 1, key( $fruits ) ); - next( $fruits ); - $this->assertEquals( 2, key( $fruits ) ); - next( $fruits ); - $this->assertEquals( 'p', key( $fruits ) ); - next( $fruits ); - $this->assertEquals( 't', key( $fruits ) ); - next( $fruits ); - $this->assertEquals( 3, key( $fruits ) ); - next( $fruits ); - $this->assertEquals( 4, key( $fruits ) ); - } - - /** - * @group 9784 - */ - public function test_convert_array_values_to_keys() { - $arr = array( 'top', 'middle', 'bottom' ); - $val = 'value'; - $this->assertEquals( - array( - 'top' => array( - 'middle' => array( - 'bottom' => 'value' - ) - ) - ), - EEH_Array::convert_array_values_to_keys( $arr, $val) - ); - } - -} - -// End of file EEH_Array_Test.php \ No newline at end of file diff --git a/tests/testcases/core/helpers/EEH_DTT_Helper_Test.php b/tests/testcases/core/helpers/EEH_DTT_Helper_Test.php deleted file mode 100644 index 50cae60e075..00000000000 --- a/tests/testcases/core/helpers/EEH_DTT_Helper_Test.php +++ /dev/null @@ -1,481 +0,0 @@ -loadModelFieldMocks(array('EE_Datetime_Field')); - $this->_datetime_field = new EE_Datetime_Field_Mock( - $table_column, - $nice_name, - $nullable, - $default_value, - $timezone, - $date_format, - $time_format, - $pretty_date_format, - $pretty_time_format - ); - } - - - /** - * test_get_valid_timezone_string - */ - public function test_get_valid_timezone_string() - { - - $original_timezone_string = get_option('timezone_string'); - // TEST 1: retrieval of WP timezone string - $expected_timezone_string = 'UTC'; - update_option('timezone_string', $expected_timezone_string); - $timezone_string = EEH_DTT_Helper::get_valid_timezone_string(); - $this->assertEquals($timezone_string, $expected_timezone_string); - // TEST 2: retrieval of specific timezone string - $expected_timezone_string = 'America/Vancouver'; - update_option('timezone_string', $expected_timezone_string); - $timezone_string = EEH_DTT_Helper::get_valid_timezone_string($expected_timezone_string); - $this->assertEquals($timezone_string, $expected_timezone_string); - // TEST 3: bogus timezone string - try { - $timezone_string = EEH_DTT_Helper::get_valid_timezone_string('me got funky pants and like to dance'); - $this->fail( - sprintf( - __( - 'The timezone string %1$s should have thrown an Exception, but did not!', - 'event_espresso' - ), - $timezone_string - ) - ); - } catch (EE_Error $e) { - $this->assertTrue(true); - } - // reset timezone_string - update_option('timezone_string', $original_timezone_string); - } - - - /** - * test_get_timezone_string_from_gmt_offset - */ - public function test_get_timezone_string_from_gmt_offset() - { - // TEST 4: gmt offsets - $orig_timezone_string = get_option('timezone_string'); - $orig_gmt_offset = get_option('gmt_offset'); - // set timezone string to empty string - update_option('timezone_string', ''); - $this->assertEmpty(get_option('timezone_string')); - $gmt_offsets = array( - -12, - -11.5, - -11, - -10.5, - -10, - -9.5, - -9, - -8.5, - -8, - -7.5, - -7, - -6.5, - -6, - -5.5, - -5, - -4.5, - -4, - -3.5, - -3, - -2.5, - -2, - -1.5, - -1, - -0.5, - 0, - 0.5, - 1, - 1.5, - 2, - 2.5, - 3, - 3.5, - 4, - 4.5, - 5, - 5.5, - 5.75, - 6, - 6.5, - 7, - 7.5, - 8, - 8.5, - 8.75, - 9, - 9.5, - 10, - 10.5, - 11, - 11.5, - 12, - 12.75, - 13, - 13.75, - 14, - ); - foreach ($gmt_offsets as $gmt_offset) { - update_option('gmt_offset', $gmt_offset); - try { - $timezone_string = EEH_DTT_Helper::get_valid_timezone_string(); - $this->assertNotEmpty( - $timezone_string, - sprintf( - __( - 'The WP GMT offset setting %1$s has resulted in an invalid timezone_string!', - 'event_espresso' - ), - $gmt_offset - ) - ); - } catch (EE_Error $e) { - $gmt_offset = $gmt_offset >= 0 ? '+' . (string)$gmt_offset : (string)$gmt_offset; - $gmt_offset = str_replace(array('.25', '.5', '.75'), array(':15', ':30', ':45'), $gmt_offset); - $gmt_offset = 'UTC' . $gmt_offset; - $this->fail( - sprintf( - __( - 'The WP GMT offset setting %1$s has thrown the following Exception, but should not have! %2$s %3$s', - 'event_espresso' - ), - $gmt_offset, - '
', - $e->getMessage() - ) - ); - unset($gmt_offset); - } - } - update_option('timezone_string', $orig_timezone_string); - update_option('gmt_offset', $orig_gmt_offset); - } - - - /** - * If the WordPress database has a timezone_string set in the database, then when this method is called with no - * arguments, it is EXPECTED that it will return the actual timezone_string set in the database unless gmt_offset is - * provided. - * - * @group 10626 - */ - public function test_get_timezone_string_from_gmt_offset_when_timezone_string_set() - { - $original_tz = get_option('timezone_string'); - update_option('timezone_string', 'America/New_York'); - $actual = EEH_DTT_Helper::get_timezone_string_from_gmt_offset(); - $this->assertEquals('America/New_York', $actual); - //let's provide 0 as offset - expect UTC back - $actual = EEH_DTT_Helper::get_timezone_string_from_gmt_offset(0); - $this->assertEquals('UTC', $actual); - // let's provide an offset THAT IS A KNOWN OFFSET WITH A MATCHING VALID TIMEZONE, - // whatever timezone string that gets - // returned should have a matching offset. - $actual = EEH_DTT_Helper::get_timezone_string_from_gmt_offset(-5); - $actual = new DateTimeZone($actual); - $now = new DateTime('now', $actual); - $actual = $actual->getOffset($now); - $this->assertEquals(-5 * HOUR_IN_SECONDS, $actual); - // let's provide an offset THAT IS A KNOWN OFFSET WITH NO MATCHING VALID TIMEZONE, - // whatever timezone string that - // gets returned should have a matching offset. - // first we need to get our expected offset based on the invalid offset we provide. - $expected = EEH_DTT_Helper::adjust_invalid_gmt_offsets(-11.5 * HOUR_IN_SECONDS); - $actual = EEH_DTT_Helper::get_timezone_string_from_gmt_offset(-11.5); - $actual = new DateTimeZone($actual); - $now = new DateTime('now', $actual); - $actual = $actual->getOffset($now); - $this->assertEquals($expected, $actual); - update_option('timezone_string', $original_tz); - } - - - /** - * setup_DateTime_object - * - * @param string $timezone_string - * @param int $time - * @return \DateTime - */ - public function setup_DateTime_object($timezone_string = 'Africa/Abidjan', $time = 0) - { - $timezone_string = empty($timezone_string) ? 'Africa/Abidjan' : $timezone_string; - $DateTime = new DateTime('now', new DateTimeZone($timezone_string)); - $time = absint($time); - if ($time) { - $DateTime->setTimestamp($time); - } - return $DateTime; - } - - - /** - * test_date_time_add - */ - public function test_date_time_add() - { - $this->_date_time_modifier_tests(); - } - - - /** - * test_date_time_subtract - */ - public function test_date_time_subtract() - { - $this->_date_time_modifier_tests(false); - } - - - /** - * _date_time_modifier_tests - * - * @param bool $increment_datetimes - * @throws EE_Error - */ - protected function _date_time_modifier_tests($increment_datetimes = true) - { - $orig_timezone_string = get_option('timezone_string'); - $orig_gmt_offset = get_option('gmt_offset'); - // setup data arrays for generating test conditions - $timezones_and_offsets = array( - 'UTC' => '', - 'America/Vancouver' => '', - null => -5 // EST with no DST - ); - $periods = array( - 'years' => 'P%Y', - 'months' => 'P%M', - 'weeks' => 'P%W', - 'days' => 'P%D', - 'hours' => 'PT%H', - 'minutes' => 'PT%M', - 'seconds' => 'PT%S', - ); - // I can not tell a Fib... the following sequence is for Sidney - $intervals = array(0, 1, 2, 3, 5, 8, 13, 21, 34); - // loop thru timezones and gmt_offsets and set up environment - foreach ($timezones_and_offsets as $timezone_string => $gmt_offset) { - $gmt_offset = $gmt_offset !== 'null' ? $gmt_offset : ''; - update_option('timezone_string', $timezone_string); - update_option('gmt_offset', $gmt_offset); - // loop thru remaining data arrays - foreach ($periods as $period => $designator) { - foreach ($intervals as $interval) { - // don't bother adding more than 5 years - if ($period === 'years' && $interval > 5) { - continue; - } - // TEST: add $interval $period ( ie: add 1 year... add 3 months... add 34 seconds ) - // setup some objects used for testing - $expected_datetime = $this->setup_DateTime_object(); - $actual_datetime = EE_Datetime::new_instance(array('DTT_EVT_start' => time())); - $expected_datetime->setTimezone(new DateTimeZone($actual_datetime->get_timezone())); - $period_interval = str_replace('%', $interval, $designator); - // apply conditions to both objects - if ($increment_datetimes) { - $expected_datetime->add(new DateInterval($period_interval)); - $actual_datetime = EEH_DTT_Helper::date_time_add( - $actual_datetime, - 'DTT_EVT_start', - $period, - $interval - ); - } else { - $expected_datetime->sub(new DateInterval($period_interval)); - $actual_datetime = EEH_DTT_Helper::date_time_subtract( - $actual_datetime, - 'DTT_EVT_start', - $period, - $interval - ); - } - $expected = $expected_datetime->format(EE_Datetime_Field::mysql_timestamp_format); - $actual = $actual_datetime->get_DateTime_object('DTT_EVT_start') - ->format(EE_Datetime_Field::mysql_timestamp_format); - $this->assertDateWithinOneMinute( - $expected, - $actual, - EE_Datetime_Field::mysql_timestamp_format, - sprintf( - __( - 'The %1$s method failed to produce correct results for the the period interval %2$s for timezone "%6$s" and UTC offset "%7$s" .%3$sExpected value: %4$s%3$sActual value: %5$s%3$s', - 'event_espresso' - ), - $increment_datetimes - ? 'EEH_DTT_Helper::date_time_add()' - : 'EEH_DTT_Helper::date_time_subtract()', - $period_interval, - "\n", - $expected, - $actual, - $timezone_string, - $gmt_offset - ) - ); - unset($expected_datetime, $actual_datetime); - } - } - } - update_option('timezone_string', $orig_timezone_string); - update_option('gmt_offset', $orig_gmt_offset); - } - - - /** - * @since 4.6.12+ - */ - public function test_get_timestamp_with_offset() - { - //now in timezone currently set. - $default_timezone = new DateTimeZone(EEH_DTT_Helper::get_timezone()); - $now = new DateTime('now', $default_timezone); - $expected_offset = (int)$now->format('U') + (int)timezone_offset_get($default_timezone, $now); - $this->assertEquals( - $expected_offset, - EEH_DTT_Helper::get_timestamp_with_offset($now->format('U')) - ); - //this might fail because of execution time. - $this->assertEquals(current_time('timestamp'), EEH_DTT_Helper::get_timestamp_with_offset()); - //now let's test with a different timezone for the incoming timestamp. - $now->setTimezone(new DateTimeZone('America/Toronto')); - $expected_timestamp = (int)$now->format('U') + (int)timezone_offset_get( - new DateTimeZone('America/Toronto'), - $now - ); - $this->assertEquals( - $expected_timestamp, - EEH_DTT_Helper::get_timestamp_with_offset($now->format('U'), 'America/Toronto') - ); - } - - - /** - * @since 4.7.0 - */ - public function test_dates_represent_one_24_hour_date() - { - $midnight_start = new DateTime('2015-01-25 00:00:00'); - $midnight_end = new DateTime('2015-01-26 00:00:00'); - $midday_start = new DateTime('2015-01-25 12:00:00'); - $midday_end = new DateTime('2015-01-26 12:00:00'); - $midnight_next_day = new DateTime('2015-01-27 00:00:00'); - //first test nulls - $this->assertFalse(EEH_DTT_Helper::dates_represent_one_24_hour_date(null, $midnight_end)); - $this->assertFalse(EEH_DTT_Helper::dates_represent_one_24_hour_date($midnight_start, null)); - //test non midnights - $this->assertFalse(EEH_DTT_Helper::dates_represent_one_24_hour_date($midnight_start, $midday_end)); - $this->assertFalse(EEH_DTT_Helper::dates_represent_one_24_hour_date($midday_start, $midnight_end)); - //test midnights but not 24 hours difference - $this->assertFalse(EEH_DTT_Helper::dates_represent_one_24_hour_date($midnight_start, $midnight_next_day)); - //test correct range - $this->assertTrue(EEH_DTT_Helper::dates_represent_one_24_hour_date($midnight_start, $midnight_end)); - } - - - /** - * @since 4.9.0.rc.025 - */ - public function test_get_timezone_string_for_display() - { - $offsets_to_test = array( - 0 => 'UTC+0:00', - 1 => 'UTC+1:00', - '-1.5' => 'UTC-1:30', - '1.25' => 'UTC+1:15', - ); - $original_timezone_string = get_option('timezone_string'); - $original_offset = get_option('gmt_offset'); - //first test when there is an actual timezone_string - update_option('timezone_string', 'America/New_York'); - $this->assertEquals('New York', EEH_DTT_Helper::get_timezone_string_for_display()); - //clear out timezone string and do offset tests - update_option('timezone_string', ''); - foreach ($offsets_to_test as $offset => $expected) { - update_option('gmt_offset', $offset); - $this->assertEquals($expected, EEH_DTT_Helper::get_timezone_string_for_display()); - } - //restore original timezone_string and offset - update_option('gmt_offset', $original_offset); - update_option('timezone_string', $original_timezone_string); - } - - - /** - * @since 4.9.27.rc - * @group 10417 - */ - public function test_tomorrow() - { - $original_offset = get_option('gmt_offset'); - $original_timezone_string = get_option('timezone_string'); - //set timezone offset to -5 and timezone_string to '' - update_option('gmt_offset', '-5'); - update_option('timezone_string', ''); - //the `5` is not a typo here. You may be thinking expected should be `-5` but the method we're testing converts - //offsets from negative to positive and from positive to negative so that the timestamp accurately represents - //midnight in that sites timezone as it exists in UTC+0 time. - $expected = strtotime('tomorrow') + (5 * 60 * 60); - $this->assertEquals($expected, EEH_DTT_Helper::tomorrow()); - //restore - update_option('gmt_offset', $original_offset); - update_option('timezone_string', $original_timezone_string); - } - - -} -// End of file EEH_DTT_Helper_Test.php -// Location: tests/testcases/core/helpers/EEH_DTT_Helper_Test.php diff --git a/tests/testcases/core/helpers/EEH_File_Test.php b/tests/testcases/core/helpers/EEH_File_Test.php deleted file mode 100644 index 12bf5e72b88..00000000000 --- a/tests/testcases/core/helpers/EEH_File_Test.php +++ /dev/null @@ -1,293 +0,0 @@ -init('/'); - } - - function tearDown() { - global $wp_filesystem; - remove_filter( 'filesystem_method_file', array( $this, 'filter_abstraction_file' ) ); - remove_filter( 'filesystem_method', array( $this, 'filter_fs_method' ) ); - unset( $wp_filesystem ); - - parent::tearDown(); - } - - function filter_fs_method( $method ) { - return 'MockEEFS'; - } - function filter_abstraction_file( $file ) { - return EE_TESTS_DIR . '/includes/mock-ee-fs.php'; - } - - /** - * Just makes sure we're really using the mock filesystem, not the real fileysstem - * @global type $wp_filesystem - */ - function test_is_MockFS_sane() { - global $wp_filesystem; - $this->assertTrue( is_a( $wp_filesystem, 'WP_Filesystem_MockEEFS' ) ); - - $wp_filesystem->init('/'); - - // Test creation/exists checks - $this->assertFalse( $wp_filesystem->is_dir( '/test/' ) ); - $wp_filesystem->mkdir( '/test' ); - $this->assertTrue( $wp_filesystem->exists( '/test' ) ); - $this->assertTrue( $wp_filesystem->is_dir( '/test/' ) ); - $this->assertFalse( $wp_filesystem->is_file( '/test' ) ); - } - - - /** - * - * @global type $wp_filesystem - */ - public function test_verify_filepath_and_permissions(){ - global $wp_filesystem; - - // Test creation/exists checks - $this->assertFalse( $wp_filesystem->is_dir( '/test/' ) ); - $wp_filesystem->mkdir( '/test', '755' ); - $this->assertTrue( $wp_filesystem->is_dir( '/test/' ) ); - $this->assertTrue( EEH_File::verify_filepath_and_permissions( '/test/' ) ); - $wp_filesystem->chmod( '/test/', '000' ); - try{ - EEH_File::verify_filepath_and_permissions( '/test/' ) ; - $this->fail(sprintf( __( 'An exception SHOULD have been thrown but wasn\'t', 'event_espresso' ))); - }catch( EE_Error $e ) { - $this->assertTrue( TRUE ); - } - - - } - - /** - * - * @global type $wp_filesystem - */ - public function test_ensure_folder_exists_and_is_writable__and__is_writable(){ - global $wp_filesystem; - $folder_path = '/test/'; - // Test creation/exists checks - $this->assertFalse( $wp_filesystem->is_dir( $folder_path ) ); - $this->assertTrue( EEH_File::ensure_folder_exists_and_is_writable( $folder_path ) ); - $this->assertTrue( EEH_File::verify_is_writable( $folder_path ) ); - $wp_filesystem->chmod( $folder_path, '000' ); - try{ - $this->assertFalse( EEH_File::ensure_folder_exists_and_is_writable( $folder_path ) ); - $this->fail(sprintf( __( 'An exception SHOULD have been thrown but wasn\'t', 'event_espresso' ))); - }catch( EE_Error $e ) { - $this->assertTrue( TRUE ); - } - try{ - $this->assertFalse( EEH_File::verify_is_writable( $folder_path ) ); - $this->fail(sprintf( __( 'An exception SHOULD have been thrown but wasn\'t', 'event_espresso' ))); - }catch( EE_Error $e ) { - $this->assertTrue( TRUE ); - } - - } - - /** - * @group 9059 - * @global type $wp_filesystem - */ - function test_ensure_folder_exists_and_is_writable__recursive_folders() { - global $wp_filesystem; - $folder_path = '/test/new/thing'; - // Test creation/exists checks - $this->assertFalse( $wp_filesystem->is_dir( $folder_path ) ); - $this->assertTrue( EEH_File::ensure_folder_exists_and_is_writable( $folder_path ) ); - $folders_in_new_folder = $wp_filesystem->dirlist( '/test/new/' ); - $this->assertTrue( isset( $folders_in_new_folder[ 'thing' ] ) ); - $folders_in_new_folder = $wp_filesystem->dirlist( '/test/new' ); - $this->assertTrue( isset( $folders_in_new_folder[ 'thing' ] ) ); - } - - /** - * @group 9059 - * @global type $wp_filesystem - */ - function test_ensure_file_exists_and_is_writable__recursive_folders() { - global $wp_filesystem; - $folder_path = '/test/new/thing.txt'; - // Test creation/exists checks - $this->assertFalse( $wp_filesystem->is_dir( $folder_path ) ); - $this->assertTrue( EEH_File::ensure_file_exists_and_is_writable( $folder_path ) ); - $folders_in_new_folder = $wp_filesystem->dirlist( '/test/new/' ); - $this->assertTrue( isset( $folders_in_new_folder[ 'thing.txt' ] ) ); - $folders_in_new_folder = $wp_filesystem->dirlist( '/test/new' ); - $this->assertTrue( isset( $folders_in_new_folder[ 'thing.txt' ] ) ); - } - - /** - * - * @global type $wp_filesystem - */ - public function test_ensure_file_exists_and_is_writable(){ - global $wp_filesystem; - $file_path = '/test.txt'; - // Test creation/exists checks - $this->assertFalse( $wp_filesystem->exists( $file_path ) ); - $this->assertTrue( EEH_File::ensure_file_exists_and_is_writable( $file_path ) ); - $this->assertTrue( EEH_File::verify_is_writable( $file_path ) ); - $wp_filesystem->chmod( $file_path, '000' ); - try{ - $this->assertFalse( EEH_File::ensure_file_exists_and_is_writable( $file_path ) ); - $this->fail(sprintf( __( 'An exception SHOULD have been thrown but wasn\'t', 'event_espresso' ))); - }catch( EE_Error $e ) { - $this->assertTrue( TRUE ); - } - try{ - $this->assertFalse( EEH_File::verify_is_writable( $file_path ) ); - $this->fail(sprintf( __( 'An exception SHOULD have been thrown but wasn\'t', 'event_espresso' ))); - }catch( EE_Error $e ) { - $this->assertTrue( TRUE ); - } - - } - - /** - * - * @global type $wp_filesystem - */ - public function test_get_file_contents(){ - global $wp_filesystem; - $file_path = '/test.txt'; - $content = 'hello'; - // Test creation/exists checks - $this->assertFalse( $wp_filesystem->exists( $file_path ) ); - $wp_filesystem->put_contents( $file_path, $content ); - $this->assertTrue( $wp_filesystem->exists( $file_path ) ); - $this->assertEquals( $content, EEH_File::get_file_contents( $file_path ) ); - } - - /** - * - * @global type $wp_filesystem - */ - public function test_write_to_file(){ - global $wp_filesystem; - $wp_filesystem->chmod( '/', '755' ); - $file_path = '/test.txt'; - $content1 = 'hello'; - $content2 = ''; - $this->assertFalse( $wp_filesystem->exists( $file_path ) ); - $wp_filesystem->put_contents( $file_path, $content1, '644' ); - $this->assertTrue( $wp_filesystem->exists( $file_path ) ); - $this->assertEquals( $content1, EEH_File::get_file_contents( $file_path ) ); - //now add to it - EEH_File::write_to_file( $file_path, $content2 ); - $this->assertEquals( $content2, EEH_File::get_file_contents( $file_path ) ); - } - - public function test_remove_filename_form_filepath(){ - $file_path = '/var/whatever/thing.txt'; - $this->assertEquals( '/var/whatever', EEH_File::remove_filename_from_filepath( $file_path ) ); - } - - public function test_get_filename_from_filepath(){ - $file_path = '/var/whatever/thing.txt'; - $this->assertEquals( 'thing.txt', EEH_File::get_filename_from_filepath( $file_path ) ); - } - - public function test_get_file_extension(){ - $file_path = '/var/whatever/thing.txt'; - $this->assertEquals( 'txt', EEH_File::get_file_extension( $file_path ) ); - } - - public function test_get_classname_from_filepath_with_standard_filename(){ - $file_path = '/we/fds/vdw/ew/EE_Thingy.junk.php'; - $this->assertEquals( 'EE_Thingy', EEH_File::get_classname_from_filepath_with_standard_filename($file_path) ); - } - public function test_standardise_diirectory_seperators_and_end_with_directory_separator(){ - $file_path = '/well\\this/isnt\\very/consistent'; - $this->assertEquals( '/well/this/isnt/very/consistent/', EEH_File::standardise_and_end_with_directory_separator($file_path)); - } - - /** - * @group 9059 - */ - public function test_is_in_uploads_folder__barely() { - $uploads = wp_upload_dir(); - $this->assertTrue( EEH_File::is_in_uploads_folder( $uploads[ 'basedir' ] ) ); - } - - /** - * @group 9059 - */ - public function test_is_in_uploads_folder__subfolder() { - $this->assertTrue( EEH_File::is_in_uploads_folder( EVENT_ESPRESSO_UPLOAD_DIR . 'mazurky' ) ); - } - - /** - * @group 9059 - */ - public function test_is_in_uploads_folder__elsewhere() { - $this->assertFalse( EEH_File::is_in_uploads_folder( '/var/somewhere/else/entirely' ) ); - } - - /** - * @group 9059 - */ - public function test_is_in_uploads_folder__elsewhere_but_tricky() { - $this->assertFalse( EEH_File::is_in_uploads_folder( '/not/uploads/dir/' . EVENT_ESPRESSO_UPLOAD_DIR ) ); - } - - /** - * @group 9059 - */ - public function test_get_parent_folder__file() { - $this->assertEquals( - '/var/something/', - EEH_File::get_parent_folder( '/var/something/thingy.txt' ) ); - } - /** - * @group 9059 - */ - public function test_get_parent_folder__file_with_one_character() { - $this->assertEquals( - '/var/something/', - EEH_File::get_parent_folder( '/var/something/a' ) ); - } - - /** - * @group 9059 - */ - public function test_get_parent_folder__folder() { - $this->assertEquals( - '/var/something/', - EEH_File::get_parent_folder( '/var/something/somewhere/' ) ); - } - - - - - - -} - -// End of file EEH_File_Test.php \ No newline at end of file diff --git a/tests/testcases/core/helpers/EEH_Inflector_Test.php b/tests/testcases/core/helpers/EEH_Inflector_Test.php deleted file mode 100644 index 199138aae3a..00000000000 --- a/tests/testcases/core/helpers/EEH_Inflector_Test.php +++ /dev/null @@ -1,60 +0,0 @@ -assertEquals( 'events', EEH_Inflector::pluralize_and_lower( 'Event' ) ); - } - /** - * at first EEH_Inflector had trouble with the word 'price' because it contains the word - * 'rice', which word pluralizes to 'rice', not 'rices'; so it made the mistake of thinking - * the plural of 'price' was 'price' (not 'priceS') - */ - public function test_pluralize_and_lower__price() { - $this->assertEquals( 'prices', EEH_Inflector::pluralize_and_lower( 'Price' ) ); - } - - public function test_pluralize_and_lower__two_words() { - $this->assertEquals( 'price_types', EEH_Inflector::pluralize_and_lower( 'Price_Type' ) ); - } - - public function test_pluralize_and_lower__three_words() { - $this->assertEquals( 'question_group_questions', EEH_Inflector::pluralize_and_lower( 'Question_Group_Question' ) ); - } - - public function test_pluralize_and_lower__funny_plural() { - $this->assertEquals( 'term_taxonomies', EEH_Inflector::pluralize_and_lower( 'Term_Taxonomy' ) ); - } - public function test_singuralize_and_upper__basic() { - $this->assertEquals( 'Attendee', EEH_Inflector::singularize_and_upper( 'attendees' ) ); - } - public function test_singuralize_and_upper__price() { - $this->assertEquals( 'Price', EEH_Inflector::singularize_and_upper( 'prices' ) ); - } - public function test_singuralize_and_upper__two_words() { - $this->assertEquals( 'Datetime_Ticket', EEH_Inflector::singularize_and_upper( 'datetime_tickets' ) ); - } - public function test_singuralize_and_upper__three_words() { - $this->assertEquals( 'Question_Group_Question', EEH_Inflector::singularize_and_upper( 'question_group_questions' ) ); - } - public function test_singuralize_and_upper__funny_plural() { - $this->assertEquals( 'Term_Taxonomy', EEH_Inflector::singularize_and_upper( 'term_taxonomies' ) ); - } -} - -// End of file EEH_Inflector_Test.php \ No newline at end of file diff --git a/tests/testcases/core/helpers/EEH_Line_Item_Test.php b/tests/testcases/core/helpers/EEH_Line_Item_Test.php deleted file mode 100644 index 86576cc441e..00000000000 --- a/tests/testcases/core/helpers/EEH_Line_Item_Test.php +++ /dev/null @@ -1,930 +0,0 @@ -new_typical_transaction(); - $items_subtotals = EEM_Line_Item::instance()->get_all_of_type_for_transaction( EEM_Line_Item::type_sub_total, $transaction ); - $items_subtotal = array_shift( $items_subtotals ); - $eeh_found_items_subtotal = EEH_Line_Item::get_pre_tax_subtotal( $transaction->total_line_item() ); - $this->assertEquals( $items_subtotal, $eeh_found_items_subtotal ); - } - - public function test_create_default_total_line_item(){ - $total_line_item = EEH_Line_Item::create_total_line_item(); - $this->assertEquals( EEM_Line_Item::type_total, $total_line_item->type() ); - $pre_tax_subtotal = EEH_Line_Item::get_pre_tax_subtotal( $total_line_item ); - $this->assertEquals( EEM_Line_Item::type_sub_total, $pre_tax_subtotal->type() ); - $taxes_subtotal = EEH_Line_Item::get_taxes_subtotal( $total_line_item ); - $this->assertEquals( EEM_Line_Item::type_tax_sub_total, $taxes_subtotal->type() ); - $taxes = $taxes_subtotal->children(); - //by default there should be 1 tax at 15% - $this->assertEquals( 1, count( $taxes ) ); - $tax = array_shift( $taxes ); - $this->assertEquals(EEM_Line_Item::type_tax, $tax->type() ); - $this->assertEquals( 15, $tax->percent() ); - } - - /** - * test_add_ticket_purchase - */ - public function test_add_ticket_purchase(){ - // create grand total - $total_line_item = EEH_Line_Item::create_total_line_item(); - $this->assertEquals( 0, $total_line_item->total() ); - // create a ticket - $ticket = $this->new_ticket( array( - 'dollar_surcharge' => 5, - 'percent_surcharge' => 10, - 'datetimes' => 2 - ) ); - // need to save ticket for other tests to work - $ticket->save(); - // two tickets plz - $ticket_line_item = EEH_Line_Item::add_ticket_purchase( $total_line_item, $ticket, 2 ); - // confirm tickets - $this->assertEquals( 2, $ticket_line_item->quantity() ); - $this->assertEquals( 33, $ticket_line_item->total() ); - // confirm subtotal - $pre_tax_subtotal = EEH_Line_Item::get_pre_tax_subtotal( $total_line_item ); - $this->assertEquals( 33, $pre_tax_subtotal->total() ); - // confirm taxes - $taxes_subtotal = EEH_Line_Item::get_taxes_subtotal( $total_line_item ); - $this->assertEquals( 4.95, $taxes_subtotal->total() ); - // confirm totals - $this->assertEquals( 37.95, $total_line_item->total() ); - // one moar ticket plz - $ticket_line_item = EEH_Line_Item::add_ticket_purchase( $total_line_item, $ticket ); - // confirm tickets - $this->assertEquals( 3, $ticket_line_item->quantity() ); - $this->assertEquals( 49.5, $ticket_line_item->total() ); - // confirm subtotal - $this->assertEquals( 49.5, $pre_tax_subtotal->total() ); - // confirm taxes - $this->assertEquals( 7.43, $taxes_subtotal->total() ); - // confirm totals - $this->assertEquals( 56.93, $total_line_item->total() ); - // total ticket line items count? should just be one ticket line item - $this->assertEquals( 1, count( EEH_Line_Item::get_ticket_line_items( $total_line_item ) ) ); - // now add a different ticket - $new_ticket = $this->new_ticket( array( - 'TKT_price' => 10, - 'TKT_taxable' => false, - 'datetimes' => 1 - ) ); - $new_ticket->save(); - // add one - $new_ticket_line_item = EEH_Line_Item::add_ticket_purchase( $total_line_item, $new_ticket ); - $this->assertEquals( 1, $new_ticket_line_item->quantity() ); - // add one moar - $new_ticket_line_item = EEH_Line_Item::add_ticket_purchase( $total_line_item, $new_ticket ); - $this->assertEquals( 2, $new_ticket_line_item->quantity() ); - // confirm totals - $this->assertEquals( 20, $new_ticket_line_item->total() ); - $this->assertEquals( 69.5, $pre_tax_subtotal->total() ); - // should be same taxes as before - $this->assertEquals( 7.43, $taxes_subtotal->total() ); - $this->assertEquals( 76.93, $total_line_item->total() ); - // total ticket ticket line items? - $this->assertEquals( 2, count( EEH_Line_Item::get_ticket_line_items( $total_line_item ) ) ); - - } - - - - /** - * test_set_tax - */ - function test_set_tax(){ - //first create a line item - $txn = $this->new_typical_transaction(); - $line_item = $txn->total_line_item(); - $old_tax_subtotal = EEH_Line_Item::get_nearest_descendant_of_type( $line_item, EEM_Line_Item::type_tax_sub_total ); - $this->assertInstanceOf( 'EE_Line_Item', $old_tax_subtotal ); - EEH_Line_Item::get_nearest_descendant_of_type( $old_tax_subtotal, EEM_Line_Item::type_tax ); - - $new_tax = EEH_Line_Item::set_total_tax_to( $line_item, 1.5, 'Monkey Tax', 'Only monkey must pay' ); - $this->assertEquals( 1.5, $new_tax->total()); - $this->assertEquals( $new_tax->total(), $old_tax_subtotal->total() ); - $child_of_tax_subtotal = EEH_Line_Item::get_nearest_descendant_of_type( $old_tax_subtotal, EEM_Line_Item::type_tax ); - $this->assertEquals( $new_tax, $child_of_tax_subtotal ); - - $tax_total_before_recalculation = $old_tax_subtotal->total(); - $tax_before_recalculations = $new_tax->total(); - $line_item->recalculate_taxes_and_tax_total(); - - $this->assertEquals( $tax_before_recalculations, $new_tax->total() ); - $this->assertEquals( $tax_total_before_recalculation, $old_tax_subtotal->total() ); - } - /** - * @group 8193 - */ - public function test_calculate_reg_final_prices_per_line_item__1_nontaxable_ticket() { - $transaction = $this->new_typical_transaction( - array( - 'taxable_tickets' => 0 - )); - $totals = EEH_Line_Item::calculate_reg_final_prices_per_line_item( $transaction->total_line_item() ); - $this->assertEquals( $transaction->total(), $totals[ 'total' ] ); - $ticket_line_items = EEM_Line_Item::instance()->get_all( - array( - array( - 'TXN_ID' => $transaction->ID(), - 'LIN_type' => EEM_Line_Item::type_line_item - ) - )); - $this->assertEquals( 1, count( $ticket_line_items ) ); - $ticket_line_item = reset( $ticket_line_items ); - $this->assertEquals( 1, $ticket_line_item->quantity() ); - $this->assertEquals( $ticket_line_item->total(), $totals[ $ticket_line_item->ID() ] ); - } - - /** - * @group 8193 - */ - public function test_calculate_reg_final_prices_per_line_item__1_taxable_ticket() { - $transaction = $this->new_typical_transaction(); - $totals = EEH_Line_Item::calculate_reg_final_prices_per_line_item( $transaction->total_line_item() ); - $this->assertEquals( $transaction->total(), $totals[ 'total' ] ); - $ticket_line_items = EEM_Line_Item::instance()->get_all( - array( - array( - 'TXN_ID' => $transaction->ID(), - 'LIN_type' => EEM_Line_Item::type_line_item - ) - )); - $this->assertEquals( 1, count( $ticket_line_items ) ); - $ticket_line_item = reset( $ticket_line_items ); - $this->assertEquals( 1, $ticket_line_item->quantity() ); - /** @var EE_Ticket $ticket */ - $ticket = $ticket_line_item->ticket(); - $this->assertEquals( $ticket->get_ticket_total_with_taxes(), $totals[ $ticket_line_item->ID() ] ); - } - - /** - * @group 8193 - */ - public function test_calculate_reg_final_prices_per_line_item__1_taxable_ticket_with_quantity_of_2() { - $transaction = $this->new_typical_transaction(); - $ticket_line_items = EEM_Line_Item::instance()->get_all( - array( - array( - 'TXN_ID' => $transaction->ID(), - 'LIN_type' => EEM_Line_Item::type_line_item - ) - )); - $this->assertEquals( 1, count( $ticket_line_items ) ); - $ticket_line_item = reset( $ticket_line_items ); - $ticket_line_item->set_quantity( 2 ); - $transaction->total_line_item()->recalculate_total_including_taxes(); - $this->assertEquals( 2, $ticket_line_item->quantity() ); - /** @var EE_Ticket $ticket */ - $ticket = $ticket_line_item->ticket(); - - $totals = EEH_Line_Item::calculate_reg_final_prices_per_line_item( $transaction->total_line_item() ); - $this->assertEquals( $transaction->total(), $totals[ 'total' ] ); - $this->assertEquals( $ticket->get_ticket_total_with_taxes(), $totals[ $ticket_line_item->ID() ] ); - } - - /** - * @group 8193 - */ - public function test_calculate_reg_final_prices_per_line_item__1_taxable_ticket_with_a_discount() { - $transaction = $this->new_typical_transaction(); - EEH_Line_Item::add_unrelated_item( $transaction->total_line_item(), 'Some Discount', -5 ); - - $totals = EEH_Line_Item::calculate_reg_final_prices_per_line_item( $transaction->total_line_item() ); - $this->assertEquals( $transaction->total(), $totals[ 'total' ] ); - $ticket_line_items = EEM_Line_Item::instance()->get_all( - array( - array( - 'TXN_ID' => $transaction->ID(), - 'LIN_type' => EEM_Line_Item::type_line_item, - 'OBJ_type' => 'Ticket' - ) - )); - $this->assertEquals( 1, count( $ticket_line_items ) ); - $ticket_line_item = reset( $ticket_line_items ); - $this->assertEquals( 6.50, $totals[ $ticket_line_item->ID() ] ); - -// honestly the easiest way to confirm the total was right is to visualize the tree -// EEH_Line_Item::visualize( $transaction->total_line_item() ); - } - - /** - * @group 8193 - */ - public function test_calculate_reg_final_prices_per_line_item__3_taxable_tickets_with_a_discount() { - $transaction = $this->new_typical_transaction( - array( - 'ticket_types' => 2 - )); - //add another ticket purchase for one of the same events - $event1 = EEM_Event::instance()->get_one( - array( - array( - 'Registration.TXN_ID' => $transaction->ID() - ) - )); - $dtt = $event1->get_first_related( 'Datetime' ); - $new_tkt = $this->new_model_obj_with_dependencies( 'Ticket', array( 'TKT_price' => 6 ) ); - $new_tkt->_add_relation_to( $dtt, 'Datetime' ); - $quantity_of_new_tks_purchased = 2; - EEH_Line_Item::add_ticket_purchase( $transaction->total_line_item(), $new_tkt, $quantity_of_new_tks_purchased ); - for( $i = 0; $i < 2; $i++ ) { - $this->new_model_obj_with_dependencies( 'Registration', - array( - 'TXN_ID' => $transaction->ID(), - 'EVT_ID' => $dtt->get( 'EVT_ID' ), - 'TKT_ID' => $new_tkt->ID(), - )); - } - //and add an unrelated purchase - EEH_Line_Item::add_unrelated_item( $transaction->total_line_item(), 'Transaction-Wide Discount', -5 ); - - $totals = EEH_Line_Item::calculate_reg_final_prices_per_line_item( $transaction->total_line_item() ); - - // honestly the easiest way to confirm the total was right is to visualize the tree -// var_dump( $totals ); -// EEH_Line_Item::visualize( $transaction->total_line_item() ); - - //verify that if we added the REG_final_prices onto the regs as derived from $totals, - //that it would equal the grand total - $sum_of_regs_final_prices = 0; - foreach( $transaction->registrations() as $reg ) { - $ticket_line_item = EEM_Line_Item::instance()->get_line_item_for_registration( $reg ); - $sum_of_regs_final_prices += $totals[ $ticket_line_item->ID() ]; - } - $this->assertEquals( $totals[ 'total' ], $sum_of_regs_final_prices ); - - //ok now let's verify the 'REG_final_price' for each ticket's line item is what we expect it to be - //so there should be 3 ticket line items right? - $ticket_line_items = EEM_Line_Item::instance()->get_all( - array( - array( - 'TXN_ID' => $transaction->ID(), - 'OBJ_type' => 'Ticket' - ) - )); - $this->assertCount(3, $ticket_line_items); - //one ticket should be 10 pre-tax - $ten_dollar_ticket = EEM_Line_Item::instance()->get_one( array( - array( - 'TXN_ID' => $transaction->ID(), - 'LIN_unit_price' => 10, - 'LIN_type' => EEM_Line_Item::type_line_item, - ) - )); - $this->assertEquals( 10.31, round( $totals[ $ten_dollar_ticket->ID() ], 2 ) ); - //one ticket should be 20 pre-tax - $twenty_dollar_ticket = EEM_Line_Item::instance()->get_one( array( - array( - 'TXN_ID' => $transaction->ID(), - 'LIN_unit_price' => 20, - 'LIN_type' => EEM_Line_Item::type_line_item, - ) - )); - $this->assertEquals( 20.62, round( $totals[ $twenty_dollar_ticket->ID() ], 2 ) ); - //one ticket should be for 6 pre-tax (although its non-taxable anyway) - $six_dollar_ticket = EEM_Line_Item::instance()->get_one( array( - array( - 'TXN_ID' => $transaction->ID(), - 'LIN_unit_price' => 6, - 'LIN_type' => EEM_Line_Item::type_line_item, - ) - )); - $this->assertEquals( 5.29, round( $totals[ $six_dollar_ticket->ID() ], 2 ) ); - } - - /** - * @group 8193 - */ - public function test_calculate_reg_final_prices_per_line_item__3_taxable_tickets_with_an_event_wide_discount() { - $number_of_tickets = 2; - $transaction = $this->new_typical_transaction( array( 'ticket_types' => $number_of_tickets )); - //add another ticket purchase for one of the same events - $event1 = EEM_Event::instance()->get_one( - array( - array( - 'Registration.TXN_ID' => $transaction->ID() - ) - )); - /** @var EE_Line_Item $event_line_item */ - $event_line_item = EEM_Line_Item::instance()->get_one( - array( - array( - 'TXN_ID' => $transaction->ID(), - 'OBJ_type' => 'Event', - 'OBJ_ID' => $event1->ID() ))); - $this->new_model_obj_with_dependencies( 'Line_Item', - array( - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_name' => 'event discount', - 'LIN_total' => -8, - 'LIN_unit_price' => -8, - 'LIN_quantity' => 1, - 'LIN_parent' => $event_line_item->ID(), - 'LIN_percent' => null, - 'LIN_order' => count( $event_line_item->children() ) - )); - $transaction->total_line_item()->recalculate_pre_tax_total(); - //and add an unrelated purchase - EEH_Line_Item::add_unrelated_item( $transaction->total_line_item(), 'Transaction-Wide Discount', -5 ); - - $totals = EEH_Line_Item::calculate_reg_final_prices_per_line_item( $transaction->total_line_item() ); - - // honestly the easiest way to confirm the total was right is to visualize the tree -// var_dump( $totals ); -// EEH_Line_Item::visualize( $transaction->total_line_item() ); - - //verify that if we added the REG_final_prices onto the regs as derived from $totals, - //that it would equal the grand total - $sum_of_regs_final_prices = 0; - foreach( $transaction->registrations() as $reg ) { - $ticket_line_item = EEM_Line_Item::instance()->get_line_item_for_registration( $reg ); - $sum_of_regs_final_prices += $totals[ $ticket_line_item->ID() ]; - } - $this->assertEquals( $totals[ 'total' ], $sum_of_regs_final_prices ); - - //ok now let's verify the 'REG_final_price' for each ticket's line item is what we expect it to be - //so there should be 3 ticket line items right? - $ticket_line_items = EEM_Line_Item::instance()->get_all( - array( - array( - 'TXN_ID' => $transaction->ID(), - 'OBJ_type' => 'Ticket' - ) - )); - $this->assertCount( $number_of_tickets, $ticket_line_items ); - //one ticket should be 10 pre-tax - $ten_dollar_ticket = EEM_Line_Item::instance()->get_one( array( - array( - 'TXN_ID' => $transaction->ID(), - 'LIN_unit_price' => 10, - 'LIN_type' => EEM_Line_Item::type_line_item, - ) - )); - $this->assertEquals( 3.05, round( $totals[ $ten_dollar_ticket->ID() ], 2 ) ); - //one ticket should be 20 pre-tax - $twenty_dollar_ticket = EEM_Line_Item::instance()->get_one( array( - array( - 'TXN_ID' => $transaction->ID(), - 'LIN_unit_price' => 20, - 'LIN_type' => EEM_Line_Item::type_line_item, - ) - )); - $this->assertEquals( 18.45, round( $totals[ $twenty_dollar_ticket->ID() ], 2 ) ); - } - - /** - * This tests the case where we buy 1 taxable $10 ticket and a nontaxable $10 ticket, - * and apply a 50% taxable discount (ie, taxes factor it in), and there is a 10% tax. - * After teh discount, each should cost $5, and the taxable one should add 10% onto it. - * So we shoudl end up with one costing $5.50 and one $5. - * @group 8193 - */ - function test_calculate_reg_final_prices_per_line_item__percent_discount_partially_taxable() { - $grand_total = $this->new_model_obj_with_dependencies( 'Line_Item', - array( - 'LIN_name' => 'total', - 'LIN_type' => EEM_Line_Item::type_total, - 'LIN_total' => 0 - )); - $subtotal = $this->new_model_obj_with_dependencies( 'Line_Item', - array( - 'LIN_name' => 'subtotal', - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'LIN_total' => 0, - 'LIN_unit_price' => 0, - 'LIN_quantity' => 0, - 'LIN_parent' => $grand_total->ID(), - 'LIN_order' => 0, - )); - $taxable = $this->new_model_obj_with_dependencies( 'Line_Item', - array( - 'LIN_name' => 'taxable', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_is_taxable' => true, - 'LIN_total' => 10, - 'LIN_unit_price' => 10, - 'LIN_quantity' => 1, - 'LIN_parent' => $subtotal->ID(), - 'LIN_order' => 1, - 'OBJ_type' => 'Ticket', - )); - $nontaxable = $this->new_model_obj_with_dependencies( 'Line_Item', - array( - 'LIN_name' => 'taxable', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_is_taxable' => false, - 'LIN_total' => 10, - 'LIN_unit_price' => 10, - 'LIN_quantity' => 1, - 'LIN_parent' => $subtotal->ID(), - 'LIN_order' => 2, - 'OBJ_type' => 'Ticket', - )); - $this->new_model_obj_with_dependencies( 'Line_Item', - array( - 'LIN_name' => 'discount', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_is_taxable' => true, - 'LIN_total' => -10, - 'LIN_unit_price' => 0, - 'LIN_percent' => -50, - 'LIN_quantity' => 1, - 'LIN_parent' => $subtotal->ID(), - 'LIN_order' => 3, - )); - $this->new_model_obj_with_dependencies( 'Line_Item', - array( - 'LIN_name' => 'taxes', - 'LIN_type' => EEM_Line_Item::type_tax_sub_total, - 'LIN_percent' => 10, - 'LIN_parent' => $grand_total->ID(), - 'LIN_order' => 1, - )); - - $totals = EEH_Line_Item::calculate_reg_final_prices_per_line_item( $grand_total ); - $this->assertEquals( 5.5, $totals[ $taxable->ID() ] ); - $this->assertEquals( 5, $totals[ $nontaxable->ID() ] ); -// var_dump($totals); -// EEH_Line_Item::visualize( $subtotal ); - } - - /** - * Verifies discounts only apply to the their sibling ticket line item's REG_final_prices - * @group 8541 - */ - function test_calculate_reg_final_prices_per_line_item__discount_only_for_one_event_subtotal() { - $grand_total = $this->new_model_obj_with_dependencies( 'Line_Item', - array( - 'LIN_name' => 'total', - 'LIN_type' => EEM_Line_Item::type_total, - 'LIN_total' => 0 - )); - $subtotal_a = $this->new_model_obj_with_dependencies( 'Line_Item', - array( - 'LIN_name' => 'subtotal_a', - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'LIN_total' => 0, - 'LIN_unit_price' => 0, - 'LIN_quantity' => 0, - 'LIN_parent' => $grand_total->ID(), - 'LIN_order' => 0, - )); - $subtotal_b = $this->new_model_obj_with_dependencies( 'Line_Item', - array( - 'LIN_name' => 'subtotal_b', - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'LIN_total' => 0, - 'LIN_unit_price' => 0, - 'LIN_quantity' => 0, - 'LIN_parent' => $grand_total->ID(), - 'LIN_order' => 1, - )); - $ticket_line_item_a = $this->new_model_obj_with_dependencies( 'Line_Item', - array( - 'LIN_name' => 'ticket_line_item_a', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_is_taxable' => false, - 'LIN_total' => 10, - 'LIN_unit_price' => 10, - 'LIN_quantity' => 1, - 'LIN_parent' => $subtotal_a->ID(), - 'LIN_order' => 1, - 'OBJ_type' => 'Ticket', - )); - $ticket_line_item_b = $this->new_model_obj_with_dependencies( 'Line_Item', - array( - 'LIN_name' => 'ticket_line_item_b', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_is_taxable' => false, - 'LIN_total' => 10, - 'LIN_unit_price' => 10, - 'LIN_quantity' => 1, - 'LIN_parent' => $subtotal_b->ID(), - 'LIN_order' => 1, - 'OBJ_type' => 'Ticket', - )); - $this->new_model_obj_with_dependencies( 'Line_Item', - array( - 'LIN_name' => 'discount_for_b', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_is_taxable' => false, - 'LIN_total' => -5, - 'LIN_unit_price' => 0, - 'LIN_percent' => -50, - 'LIN_quantity' => 1, - 'LIN_parent' => $subtotal_b->ID(), - 'LIN_order' => 100, - )); - $this->new_model_obj_with_dependencies( 'Line_Item', - array( - 'LIN_name' => 'taxes', - 'LIN_type' => EEM_Line_Item::type_tax_sub_total, - 'LIN_percent' => 0, - 'LIN_parent' => $grand_total->ID(), - 'LIN_order' => 1, - )); - - $totals = EEH_Line_Item::calculate_reg_final_prices_per_line_item( $grand_total ); -// var_dump($totals); -// EEH_Line_Item::visualize( $grand_total ); - //now verify the discount only applied to event B's ticket, not event A's - $this->assertEquals( 10, $totals[ $ticket_line_item_a->ID() ] ); - $this->assertEquals( 5, $totals[ $ticket_line_item_b->ID() ] ); - } - - - /** - * Create a line item tree which was originally for 6 tickets and a discount, - * but 2 got cancelled and so shouldn't count towards the grand total, - * and so the ticket line item's quantity should be 4 - * @group 5580 - */ - function test_cancel_ticket_line_item__with_sub_items_already(){ - $grand_total = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'total', - 'LIN_name' => __( 'Grand Total', 'event_espresso' ), - 'LIN_type' => EEM_Line_Item::type_total, - 'OBJ_type' => 'Transaction' - ) - ); - $grand_total->save(); - $event_subtotal = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'event1', - 'LIN_name' => 'EventA', - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'OBJ_type' => 'Event', - 'LIN_total' => 0, - 'LIN_parent' => $grand_total->ID(), - )); - $event_subtotal->save(); - $normal_line_item = EE_Line_Item::new_instance( - array( - 'LIN_code' => '12354', - 'LIN_name' => 'ticketA', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'OBJ_type' => 'Ticket', - 'LIN_unit_price' => 10, - 'LIN_quantity' => 6, - 'LIN_order' => 1, - 'LIN_parent' => $event_subtotal->ID() - )); - $normal_line_item->save(); - $subitem_base_price = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'baseprice', - 'LIN_name' => 'basepriceA', - 'LIN_type' => EEM_Line_Item::type_sub_line_item, - 'OBJ_type' => 'Price', - 'LIN_unit_price' => 20, - 'LIN_quantity' => 6, - 'LIN_order' => 1, - 'LIN_parent' => $normal_line_item->ID() - )); - $subitem_base_price->save(); - $subitem_percent_price = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'percentdiscount', - 'LIN_name' => 'percentprice', - 'LIN_type' => EEM_Line_Item::type_sub_line_item, - 'OBJ_type' => 'Price', - 'LIN_unit_price' => 0, - 'LIN_percent' => -50, - 'LIN_quantity' => 1, - 'LIN_order' => 2, - 'LIN_parent' => $normal_line_item->ID() - )); - $subitem_percent_price->save(); - - $cancellation_subitem = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'cancellationoruny', - 'LIN_name' => 'cancellationOfA', - 'LIN_type' => EEM_Line_Item::type_cancellation, - 'OBJ_type' => '',//? - 'LIN_unit_price' => 10, - 'LIN_quantity' => 1, - 'LIN_total' => 10, - 'LIN_order' => 3, - 'LIN_parent' => $normal_line_item->ID() - )); - $cancellation_subitem->save(); - $percent_line_item = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'dscntfry', - 'LIN_name' => 'Discounto', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'OBJ_type' => '', - 'LIN_unit_price' => null, - 'LIN_quantity' => null, - 'LIN_percent' => -25, - 'LIN_order' => 1000, - 'LIN_parent' => $event_subtotal->ID() - )); - $percent_line_item->save(); - $event_subtotal->recalculate_total_including_taxes(); - // EEH_Line_Item::visualize( $event_subtotal ); - $this->assertEquals( 60, $normal_line_item->total() ); - $this->assertEquals( 45, $event_subtotal->total() ); - $this->assertEquals( -15, $percent_line_item->total() ); - - //ok now cancel a few and make sure the totals add up correctly - EEH_Line_Item::cancel_ticket_line_item( $normal_line_item ); - EEH_Line_Item::cancel_ticket_line_item( $normal_line_item ); - $event_subtotal->recalculate_total_including_taxes(); - // EEH_Line_Item::visualize( $event_subtotal ); - $this->assertEquals( 40, $normal_line_item->total() ); - $this->assertEquals( 30, $event_subtotal->total() ); - $this->assertEquals( -10, $percent_line_item->total() ); - $cancellation_line_items = EEH_Line_Item::get_descendants_of_type( $event_subtotal, EEM_Line_Item::type_cancellation ); - $the_only_cancellation_item = reset( $cancellation_line_items ); - $this->assertEquals( 3, $the_only_cancellation_item->quantity() ); - $this->assertEquals( 10, $the_only_cancellation_item->total() ); - } - - /** - * Checks we correctly add a cancellation line item - * @group 5580 - */ - function test_cancel_ticket_line_item__with_no_previous_cancellations(){ - $grand_total = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'total', - 'LIN_name' => __( 'Grand Total', 'event_espresso' ), - 'LIN_type' => EEM_Line_Item::type_total, - 'OBJ_type' => 'Transaction' - ) - ); - $grand_total->save(); - $event_subtotal = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'event1', - 'LIN_name' => 'EventA', - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'OBJ_type' => 'Event', - 'LIN_total' => 0, - 'LIN_parent' => $grand_total->ID(), - )); - $event_subtotal->save(); - $normal_line_item = EE_Line_Item::new_instance( - array( - 'LIN_code' => '12354', - 'LIN_name' => 'ticketA', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'OBJ_type' => 'Ticket', - 'LIN_unit_price' => 10, - 'LIN_quantity' => 6, - 'LIN_order' => 1, - 'LIN_parent' => $event_subtotal->ID() - )); - $normal_line_item->save(); - $subitem_base_price = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'baseprice', - 'LIN_name' => 'basepriceA', - 'LIN_type' => EEM_Line_Item::type_sub_line_item, - 'OBJ_type' => 'Price', - 'LIN_unit_price' => 20, - 'LIN_quantity' => 6, - 'LIN_order' => 1, - 'LIN_parent' => $normal_line_item->ID() - )); - $subitem_base_price->save(); - $subitem_percent_price = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'percentdiscount', - 'LIN_name' => 'percentprice', - 'LIN_type' => EEM_Line_Item::type_sub_line_item, - 'OBJ_type' => 'Price', - 'LIN_unit_price' => 0, - 'LIN_percent' => -50, - 'LIN_quantity' => 1, - 'LIN_order' => 2, - 'LIN_parent' => $normal_line_item->ID() - )); - $subitem_percent_price->save(); - $percent_line_item = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'dscntfry', - 'LIN_name' => 'Discounto', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'OBJ_type' => '', - 'LIN_unit_price' => null, - 'LIN_quantity' => null, - 'LIN_percent' => -25, - 'LIN_order' => 1000, - 'LIN_parent' => $event_subtotal->ID() - )); - $percent_line_item->save(); - $grand_total->recalculate_total_including_taxes(); - // EEH_Line_Item::visualize( $grand_total ); - $this->assertEquals( 60, $normal_line_item->total() ); - $this->assertEquals( 45, $event_subtotal->total() ); - $this->assertEquals( -15, $percent_line_item->total() ); - - //ok now cancel a few and make sure the totals add up correctly - EEH_Line_Item::cancel_ticket_line_item( $normal_line_item, 2 ); - $grand_total->recalculate_total_including_taxes(); - // EEH_Line_Item::visualize( $grand_total ); - $this->assertEquals( 40, $normal_line_item->total() ); - $this->assertEquals( 30, $event_subtotal->total() ); - $this->assertEquals( -10, $percent_line_item->total() ); - $cancellation_line_items = EEH_Line_Item::get_descendants_of_type( $event_subtotal, EEM_Line_Item::type_cancellation ); - $the_only_cancellation_item = reset( $cancellation_line_items ); - $this->assertEquals( 2, $the_only_cancellation_item->quantity() ); - $this->assertEquals( 0, $the_only_cancellation_item->total() ); - } - - /** - * Create a line item tree which was originally for 6 tickets and a discount, - * but 2 got cancelled and so shouldn't count towards the grand total. When - * we reinstate a ticket, the ticket's quantity should change from 4 to 5, and - * then when both are reinstated it should increase to 6 and the cancellation - * line item should be removed - * @group 5580 - */ - function test_reinstate_canceled_ticket_line_item(){ - $grand_total = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'total', - 'LIN_name' => __( 'Grand Total', 'event_espresso' ), - 'LIN_type' => EEM_Line_Item::type_total, - 'OBJ_type' => 'Transaction' - ) - ); - $grand_total->save(); - $event_subtotal = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'event1', - 'LIN_name' => 'EventA', - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'OBJ_type' => 'Event', - 'LIN_total' => 1, - 'LIN_parent' => $grand_total->ID(), - )); - $event_subtotal->save(); - $normal_line_item = EE_Line_Item::new_instance( - array( - 'LIN_code' => '12354', - 'LIN_name' => 'ticketA', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'OBJ_type' => 'Ticket', - 'LIN_unit_price' => 10, - 'LIN_quantity' => 4, - 'LIN_order' => 1, - 'LIN_parent' => $event_subtotal->ID() - )); - $normal_line_item->save(); - $subitem_base_price = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'baseprice', - 'LIN_name' => 'basepriceA', - 'LIN_type' => EEM_Line_Item::type_sub_line_item, - 'OBJ_type' => 'Price', - 'LIN_unit_price' => 10, - 'LIN_quantity' => 4, - 'LIN_order' => 1, - 'LIN_parent' => $normal_line_item->ID() - )); - $subitem_base_price->save(); - $cancellation_subitem = EE_Line_Item::new_instance( - array( - 'LIN_code' => 'cancellationoruny', - 'LIN_name' => 'cancellationOfA', - 'LIN_type' => EEM_Line_Item::type_cancellation, - 'OBJ_type' => '',//? - 'LIN_unit_price' => 10, - 'LIN_quantity' => 2, - 'LIN_order' => 2, - 'LIN_parent' => $normal_line_item->ID() - )); - $cancellation_subitem->save(); - $grand_total->recalculate_total_including_taxes(); - // EEH_Line_Item::visualize( $grand_total ); - $this->assertEquals( 40, $normal_line_item->total() ); - //remove the last cancellation - EEH_Line_Item::reinstate_canceled_ticket_line_item( $normal_line_item ); - $grand_total->recalculate_total_including_taxes(); - // EEH_Line_Item::visualize( $grand_total ); - $this->assertEquals( 5, $normal_line_item->quantity() ); - $this->assertEquals( 50, $normal_line_item->total() ); - $this->assertEquals( 1, $cancellation_subitem->quantity() ); - //remove another cancellation - EEH_Line_Item::reinstate_canceled_ticket_line_item( $normal_line_item ); - $grand_total->recalculate_total_including_taxes(); - // EEH_Line_Item::visualize( $grand_total ); - $this->assertEquals( 6, $normal_line_item->quantity() ); - $this->assertEquals( 60, $normal_line_item->total() ); - $this->assertEquals( 0, $cancellation_subitem->quantity() ); - // and then cancel one of the tickets again - EEH_Line_Item::cancel_ticket_line_item( $normal_line_item ); - $grand_total->recalculate_total_including_taxes(); - // EEH_Line_Item::visualize( $grand_total ); - } - - - - /** - * @group 4710 - */ - function test_set_line_items_taxable() { - $t = $this->new_typical_transaction( array( 'taxable_tickets' => 0 ) ); - EEH_Line_Item::add_unrelated_item( $t->total_line_item(), 'Exempt Line Item', 1, 'Description', 1, false, 'exempt_me'); - $reg_line_items = EEH_Line_Item::get_descendants_of_type( $t->total_line_item(), EEM_Line_Item::type_line_item ); - foreach( $reg_line_items as $line_item ) { - $this->assertFalse( $line_item->is_taxable(), print_r( $line_item->model_field_array(), true ) ); - } - EEH_Line_Item::set_line_items_taxable( $t->total_line_item(), true, 'exempt_me' ); - foreach( $reg_line_items as $line_item ) { - if( $line_item->code() == 'exempt_me' ) { - $this->assertFalse( $line_item->is_taxable(), print_r( $line_item->model_field_array(), true ) ); - } else { - $this->assertTrue( $line_item->is_taxable(), print_r( $line_item->model_field_array(), true ) ); - } - } - } - - - - function test_recalculate_total_including_taxes_after_ticket_cancellation() { - // create txn with one $10 ticket that is taxable at default 15% rate - $transaction = $this->new_typical_transaction( array( 'taxable_tickets' => 1 ) ); - $registrations = $transaction->registrations(); - $registration = reset( $registrations ); - $this->assertInstanceOf( 'EE_Registration', $registration ); - $ticket1 = $registration->ticket(); - $this->assertEquals( 10, $ticket1->price() ); - $total_line_item = $transaction->total_line_item(); - $this->assertInstanceOf( 'EE_Line_Item', $total_line_item ); - $this->assertEquals( 11.5, $total_line_item->total() ); - // EEH_Line_Item::visualize( $total_line_item ); - // now cancel the registration - $registration->set_status( \EEM_Registration::status_id_cancelled ); - $registration->save(); - // EEH_Line_Item::cancel_ticket_line_item( $ticket_line_item ); - // now retrieve the line item for the ticket - $ticket_line_items = EEH_Line_Item::get_ticket_line_items( $total_line_item ); - $this->assertCount( 1, $ticket_line_items ); - $ticket_line_item = reset( $ticket_line_items ); - $this->assertInstanceOf( 'EE_Line_Item', $ticket_line_item ); - // and check its quantity - $this->assertEquals( 0, $ticket_line_item->quantity() ); - // EEH_Line_Item::visualize( $total_line_item ); - $ticket_line_items = array(); - $ticket_line_item = null; - // echo "\n\n now add a new $15 ticket: \n"; - // now add a new ticket - $ticket2 = $this->new_ticket( array( 'TKT_price' => 15, 'TKT_taxable' => false ) ); - $this->assertEquals( 15, $ticket2->price() ); - EEH_Line_Item::add_ticket_purchase( $total_line_item, $ticket2 ); - // EEH_Line_Item::visualize( $total_line_item ); - $ticket_line_items = EEH_Line_Item::get_ticket_line_items( $total_line_item ); - $this->assertCount( 2, $ticket_line_items ); - // find ticket 2 - foreach ( $ticket_line_items as $ticket_line_item ) { - if ( $ticket_line_item->OBJ_type() === 'Ticket' && $ticket_line_item->OBJ_ID() === $ticket2->ID() ) { - $this->assertEquals( $ticket2->price(), $ticket_line_item->total() ); - } - } - $this->assertEquals( 15, $total_line_item->total() ); - } - - - - public function test_event_subtotal_line_items() { - $transaction = $this->new_typical_transaction( array( 'ticket_types' => 2 ) ); - /** @var EE_Line_Item $total_line_item */ - $total_line_item = $transaction->total_line_item(); - $total_line_item->recalculate_total_including_taxes(); - // EEH_Line_Item::visualize( $total_line_item ); - foreach ( EEH_Line_Item::get_event_subtotals( $total_line_item ) as $event_line_item ) { - $this->assertNotEquals( 0.0, $event_line_item->unit_price() ); - $this->assertEquals( $event_line_item->unit_price(), ( $event_line_item->total() / $event_line_item->quantity() ) ); - } - } - -} - -// End of file EEH_Line_Item_Test.php -// Location: /tests/testcases/core/helpers/EEH_Line_Item_Test.php \ No newline at end of file diff --git a/tests/testcases/core/helpers/EEH_MSG_Template_Test.php b/tests/testcases/core/helpers/EEH_MSG_Template_Test.php deleted file mode 100644 index deb81d8fba1..00000000000 --- a/tests/testcases/core/helpers/EEH_MSG_Template_Test.php +++ /dev/null @@ -1,109 +0,0 @@ -_message_resource_manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' ); - $this->assertInstanceOf( 'EE_Message_Resource_Manager', $this->_message_resource_manager ); - } - - - public function tearDown() { - parent::tearDown(); - $this->_message_resource_manager = null; - } - - - /** - * test messenger that should be active - * - * @since 4.4.1 - */ - public function test_get_active_messenger() { - EEH_Activation::generate_default_message_templates(); - $Message_Resource_Manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' ); - $this->assertInstanceOf( - 'EE_messenger', - $Message_Resource_Manager->get_active_messenger( 'email' ) - ); - $this->assertNotInstanceOf( - 'EE_messenger', - $Message_Resource_Manager->get_active_messenger( 'some_random_messenger' ) - ); - } - - - /** - * @since 4.9.0 - */ - public function test_create_new_templates() { - //let's first delete known global templates for the purpose of the test - $MessageTemplateGroup = EEM_Message_Template_Group::instance()->get_one( - array( - array( - 'MTP_messenger' => 'html', - 'MTP_message_type' => 'invoice', - 'MTP_is_global' => true - ) - ) - ); - - $this->assertInstanceOf( 'EE_Message_Template_Group', $MessageTemplateGroup ); - $MessageTemplateGroup->delete_related_permanently( 'Message_Template' ); - $MessageTemplateGroup->delete_permanently(); - - //try to retrieve again just to verify its been deleted. - $MessageTemplateGroup = EEM_Message_Template_Group::instance()->get_one( - array( - array( - 'MTP_messenger' => 'html', - 'MTP_message_type' => 'invoice', - 'MTP_is_global' => true - ) - ) - ); - $this->assertNull( $MessageTemplateGroup ); - - //okay now we can do our create templates test. - EE_Registry::instance()->load_helper( 'MSG_Template' ); - $templates = EEH_MSG_Template::create_new_templates( - 'html', - 'invoice', - 0, - true - ); - $this->assertTrue( is_array( $templates ) ); - $this->assertEquals( 2, count( $templates ) ); - $this->assertTrue( isset( $templates['GRP_ID'] ) ); - $this->assertTrue( isset( $templates['MTP_context'] ) ); - $this->assertTrue( $templates['GRP_ID'] > 0 ); - } - - -} //end EEH_MSG_Template_Test -// Location: tests/testcases/core/helpers/EEH_MSG_Template_Test.php diff --git a/tests/testcases/core/helpers/EEH_Parse_Shortcodes_Test.php b/tests/testcases/core/helpers/EEH_Parse_Shortcodes_Test.php deleted file mode 100644 index b9a27bcb2cd..00000000000 --- a/tests/testcases/core/helpers/EEH_Parse_Shortcodes_Test.php +++ /dev/null @@ -1,413 +0,0 @@ -factory->price_chained->create_object(array( - 'PRC_name' => 'Not Free Price', - 'PRC_amount' => '125.00', - )); - $this->_ticket = $this->factory->ticket_chained->create_object(array('PRC_ID' => $price->ID())); - //update ticket price - $this->_ticket->set('TKT_price', '125.00'); - $this->_ticket->set('TKT_name', 'Podracing Entry'); - $this->_ticket->set('TKT_description', 'One entry in the event.'); - $this->_datetime = $this->_ticket->first_datetime(); - $this->_event = $this->_datetime->event(); - - //set the author of the event - $this->_event->set('EVT_wp_user', 1); - require_once EE_TESTS_DIR . 'mocks/core/helpers/EEH_Parse_Shortcodes_Mock.php'; - $this->_parse_shortcodes_helper_mock = new EEH_Parse_Shortcodes_Mock; - } - - - /** - * This grabs an EE_Messages_Addressee object for the Preview data handler. - * - * @param string $context - * @return \EE_Messages_Addressee - */ - protected function _get_addressee($context = 'primary_attendee') - { - $aee = array(); - $data = new EE_Messages_Preview_incoming_data(array('event_ids' => array($this->_event->ID()))); - /** - * @see EE_message_type::_set_defautl_addressee_data() - */ - $addressee_data = array( - 'billing' => $data->billing, - 'taxes' => $data->taxes, - 'tax_line_items' => $data->tax_line_items, - 'additional_line_items' => $data->additional_line_items, - 'grand_total_line_item' => $data->grand_total_line_item, - 'txn' => $data->txn, - 'payments' => $data->payments, - 'payment' => isset($data->payment) ? $data->payment : null, - 'reg_objs' => $data->reg_objs, - 'registrations' => $data->registrations, - 'datetimes' => $data->datetimes, - 'tickets' => $data->tickets, - 'line_items_with_children' => $data->line_items_with_children, - 'questions' => $data->questions, - 'answers' => $data->answers, - 'txn_status' => $data->txn_status, - 'total_ticket_count' => $data->total_ticket_count, - ); - - if (is_array($data->primary_attendee_data)) { - $addressee_data = array_merge($addressee_data, $data->primary_attendee_data); - $addressee_data['primary_att_obj'] = $data->primary_attendee_data['att_obj']; - $addressee_data['primary_reg_obj'] = $data->primary_attendee_data['reg_obj']; - } - - /** - * @see EE_message_type::_process_data() - */ - switch ($context) { - case 'primary_attendee' : - case 'purchaser' : - $aee = $addressee_data; - $aee['events'] = $data->events; - $aee['attendees'] = $data->attendees; - break; - case 'attendee' : - //for the purpose of testing we're just going to do ONE attendee - $attendee = reset($data->attendees); - foreach ($attendee as $item => $value) { - $aee[$item] = $value; - if ($item == 'line_ref') { - foreach ($value as $event_id) { - $aee['events'][$event_id] = $data->events[$event_id]; - } - } - } - $aee['reg_obj'] = array_shift($attendee['reg_objs']); - $aee['attendees'] = $data->attendees; - break; - case 'admin' : - //for the purpose of testing we're only setting up for the event we have active for testing. - $aee['user_id'] = $this->_event->get('EVT_wp_user'); - $aee['events'] = $data->events; - $aee['attendees'] = $data->attendees; - } - return new EE_Messages_Addressee($aee); - } - - - /** - * This helper returns parsed content from the parser to be used for tests using the given params. - * - * @param string $messenger The slug for the messenger being tested. - * @param string $message_type The slug for the message type being tested. - * @param string $field The field being tested. - * @param string $context The context being tested. - * @param array|string $append Append content to a default template for testing with. If - * you want to append to multiple fields, then include an - * array indexed by field. Otherwise the string will be - * appended to the field sent in with the $field param. - * @param EE_Messages_Addressee $addressee Optionally include a - * messages addressee object if you do not wish - * to use the default one generated. This is - * useful for simulating exceptions and failures. - * @return string The parsed content. - */ - protected function _get_parsed_content($messenger, $message_type, $field, $context, $append = '', $addressee = null) - { - //grab the correct template @see EE_message_type::_get_templates() - /** @type EE_Message_Template_Group $mtpg */ - $mtpg = EEM_Message_Template_Group::instance()->get_one(array( - array( - 'MTP_messenger' => $messenger, - 'MTP_message_type' => $message_type, - 'MTP_is_global' => true, - ), - )); - $all_templates = $mtpg instanceof EE_Message_Template_Group ? $mtpg->context_templates() : array(); - $templates = array(); - foreach ($all_templates as $t_context => $template_fields) { - foreach ($template_fields as $template_field => $template_obj) { - $templates[$template_field][$t_context] = $template_obj->get('MTP_content'); - } - } - - //instantiate messenger and message type objects - $msg_class = 'EE_' . str_replace(' ', '_', ucwords(str_replace('_', ' ', $messenger))) . '_messenger'; - $mt_class = 'EE_' . str_replace(' ', '_', ucwords(str_replace('_', ' ', $message_type))) . '_message_type'; - /** @type EE_messenger $messenger */ - $messenger = new $msg_class(); - /** @type EE_message_type $message_type */ - $message_type = new $mt_class(); - - //grab valid shortcodes and setup for parser. - $m_shortcodes = $messenger->get_valid_shortcodes(); - $mt_shortcodes = $message_type->get_valid_shortcodes(); - - //just sending in the content field and primary_attendee context/data for testing. - $template = isset($templates[$field][$context]) ? $templates[$field][$context] : array(); - - /** - * if empty template then its possible that the requested field is inside the "content" - * field array. - */ - if (empty($template)) { - $template = isset($templates['content'][$context]) ? $templates['content'][$context] : array(); - //verify the requested field is present - if (! empty($template) && is_array($template) && ! isset($template[$field])) { - return ''; - } - } - - //if $template is still empty then return an empty string - if (empty($template)) { - return ''; - } - - // any appends? - if (! empty($append)) { - if (is_array($template)) { - //we've already done a check for the presence of field above. - if (is_array($append)) { - foreach ($append as $a_field => $string) { - if (isset($template[$a_field])) { - $template[$a_field] = $template[$a_field] . $string; - } - } - } else { - $template[$field] = $template[$field] . $append; - } - } else { - //only append if $append is not an array because the $template is not an array. - if (! is_array($append)) { - $template .= $append; - } - - } - } - - - $valid_shortcodes = isset($m_shortcodes[$field]) ? $m_shortcodes[$field] : $mt_shortcodes[$context]; - $data = $addressee instanceof EE_Messages_Addressee ? $addressee : $this->_get_addressee(); - - //parser needs EE_Message object - $message = EE_Message_Factory::create( - array( - 'MSG_messenger' => $messenger->name, - 'MSG_message_type' => $message_type->name, - 'MSG_context' => $context, - 'GRP_ID' => $mtpg->ID(), - ) - ); - $parser = new EEH_Parse_Shortcodes(); - return $parser->parse_message_template($template, $data, $valid_shortcodes, $message_type, $messenger, - $message); - } - - - /** - * Tests parsing the message template for email messenger, payment received message - * type. - * - * @group 7585 - * @since 4.6 - */ - public function test_parsing_email_payment_received() - { - $parsed = $this->_get_parsed_content('email', 'payment', 'content', 'primary_attendee'); - - //now that we have parsed let's test the results, note for the purpose of this test we are verifying transaction shortcodes and ticket shortcodes. - - //testing [PRIMARY_REGISTRANT_FNAME], [PRIMARY_REGISTRANT_LNAME] - $this->assertContains('Luke Skywalker', $parsed); - - //testing [PAYMENT_STATUS] - $this->assertContains('Incomplete', $parsed); - - //testing [TXN_ID] - $this->assertContains('999999', $parsed); - - //testing [TOTAL_COST] and [AMOUNT_DUE] (should be $125*3 + 20 shipping charge + taxes) - $total_cost = EEH_Template::format_currency('398.00'); - $this->assertContains($total_cost, $parsed); - //but we should also have a count of TWO for this string - $this->assertEquals(2, substr_count($parsed, $total_cost)); - - //testing [AMOUNT_PAID] - $amount_paid = EEH_Template::format_currency('0'); - $this->assertContains($amount_paid, $parsed); - - - //testing [TICKET_NAME] - $this->assertContains('Podracing Entry', $parsed); - - //testing [TICKET_DESCRIPTION] - $this->assertContains('One entry in the event.', $parsed); - - //testing [TICKET_PRICE] - $this->assertContains(EEH_Template::format_currency('125.00'), $parsed); - - - //testing [TKT_QTY_PURCHASED] - $expected = 'Quantity Purchased: 3'; - $this->assertContains($expected, $parsed, - '[TKT_QTY_PURCHASED] shortcode was not parsed correctly to the expected value which is 3'); - - } - - - /** - * Test parsing the html receipt message templates. - * - * @since 4.6 - * @group 7623 - */ - public function test_parsing_html_receipt() - { - //see https://events.codebasehq.com/projects/event-espresso/tickets/9337, I think when running all tests, html - //messenger is getting stuck deactivated and thus the generated message template for this test will be missing some - //info. - EE_Registry::instance()->load_lib('Message_Resource_Manager')->ensure_messenger_is_active('html'); - //currently with @group 7623 just testing if there are any error notices. - $parsed = $this->_get_parsed_content('html', 'receipt', 'content', 'purchaser'); - - //testing [PAYMENT_GATEWAY] - $this->assertContains('Invoice', $parsed); - } - - - /** - * Test parsing the email registration message templates (registration approved). - * - * @since 4.6 - * @group 7613 - */ - public function test_parsing_email_registration() - { - //add in shortcodes for testing [ANSWER_*] as a part of the [ATTENDEE_LIST] parsing from the [EVENT_LIST] context. - $test_answer_attendee_list_event_list_append = array( - 'event_list' => '[ATTENDEE_LIST]', - 'attendee_list' => 'Custom Answer: [ANSWER_* What is your favorite planet?]', - 'ticket_list' => '[ATTENDEE_LIST]', - 'main' => '[ATTENDEE_LIST]', - ); - - $parsed = $this->_get_parsed_content('email', 'registration', 'attendee_list', 'attendee', - $test_answer_attendee_list_event_list_append); - - //testing [ATTENDEE_LIST] and [ANSWER_*] which should appear three times (because [ATTENDEE_LIST] was added to three fields), - $this->assertEquals(3, substr_count($parsed, 'Custom Answer: Tattoine')); - } - - - /** - * This test is for testing an exception is thrown when invalid attendee - * object in the data sent to the parsers. - * - * @group 7659 - */ - public function test_invalid_attendee_obj_EE_Attendee_Shortcodes() - { - $addressee = $this->_get_addressee(); - - //manipulate to remove data - $addressee->registrations = array(); - - try { - $parsed_content = $this->_get_parsed_content('email', 'registration', 'content', 'admin', '', $addressee); - } catch (EE_Error $e) { - return; - } - $this->fail('Expected an exception for invalid EE_Attendee Object'); - } - - - /** - * @group 10561 - */ - public function test_is_conditional_shortcode() - { - //test is conditional shortcode - $this->assertTrue($this->_parse_shortcodes_helper_mock->is_conditional_shortcode('[IF_something_* id=10]')); - - $non_conditional_expectations = array( - '[SOMETHING]', - '[WHEN_IF_NESTED]', - '[if_lowercase]', - '[/IF_CLOSING_TAG]' - ); - - foreach ($non_conditional_expectations as $non_conditional_expectation) { - //should not be conditional shortcode - $this->assertFalse( - $this->_parse_shortcodes_helper_mock->is_conditional_shortcode( - $non_conditional_expectation - ), - sprintf( - 'This shortcode pattern should not test as matching a conditional shortcode but it did: %s', - $non_conditional_expectation - ) - ); - } - } - -} //end class EEH_Parse_Shortcodes_Test diff --git a/tests/testcases/core/helpers/EEH_TemplateTest.php b/tests/testcases/core/helpers/EEH_TemplateTest.php deleted file mode 100644 index 2b3b01c9ab4..00000000000 --- a/tests/testcases/core/helpers/EEH_TemplateTest.php +++ /dev/null @@ -1,30 +0,0 @@ -datetime_offset_fix_mock = new DatetimeOffsetFixMock(); - } - - /** - * @group offset_fix_test - * @throws EE_Error - */ - public function testProcessModel() - { - $original_date_and_time = new DateTime('now'); - $expected_positive_offset_datetime = clone $original_date_and_time; - $test_offsets = array( - '2' => $expected_positive_offset_datetime->add(new DateInterval('PT2H')), - //note we have the expectation set here back to the original date and time because offset test _should_ just - //restore the original time. - '-2' => $original_date_and_time - ); - /** @var EE_Datetime $datetime */ - $datetime = $this->factory->datetime->create( - array( - 'DTT_EVT_start' => $original_date_and_time->format('U'), - 'DTT_EVT_end' => $original_date_and_time->format('U') - ) - ); - //k run our tests - foreach ($test_offsets as $offset_to_test => $expected_datetime_object) { - DatetimeOffsetFixMock::updateOffset((float) $offset_to_test); - $this->datetime_offset_fix_mock->processModel('EEM_Datetime'); - //need to clear any entities cached in the model - EEM_Datetime::instance()->clear_entity_map(); - $actual_datetime = EEM_Datetime::instance()->get_one_by_ID($datetime->ID()); - $this->assertEquals( - $expected_datetime_object->format('U'), - $actual_datetime->get_DateTime_object('DTT_EVT_start')->format('U'), - sprintf('Offset being tested is %s', $offset_to_test) - ); - } - } -} diff --git a/tests/testcases/core/libraries/form_sections/base/EE_Form_Section_Base__find_section_from_path_Test.php b/tests/testcases/core/libraries/form_sections/base/EE_Form_Section_Base__find_section_from_path_Test.php deleted file mode 100644 index f2c68e0b01b..00000000000 --- a/tests/testcases/core/libraries/form_sections/base/EE_Form_Section_Base__find_section_from_path_Test.php +++ /dev/null @@ -1,100 +0,0 @@ -_child_section = new EE_Text_Input(); - $this->_sibling_section = new EE_Text_Input(); - $this->_parent_section = new EE_Form_Section_Proper( - array( - 'subsections' => array( - 'child' => $this->_child_section, - 'sibling' => $this->_sibling_section - ) - ) - ); - $this->_cousin_section = new EE_Text_Input(); - $this->_aunt_section = new EE_Form_Section_Proper( - array( - 'subsections' => array( - 'cousin' => $this->_cousin_section - ) - ) - ); - $this->_granparent_section = new EE_Form_Section_Proper( - array( - 'name' => 'grandparent', - 'subsections' => array( - 'parent' => $this->_parent_section, - 'aunt' => $this->_aunt_section - ) - ) - ); - } - //put your code here - public function test_sibling() { - $this->assertEquals( $this->_sibling_section, $this->_child_section->find_section_from_path( '../sibling' ) ); - } - public function test_parent() { - $this->assertEquals( $this->_parent_section, $this->_child_section->find_section_from_path( '../' ) ); - $this->assertEquals( $this->_parent_section, $this->_child_section->find_section_from_path( '../../parent' ) ); - } - public function test_aunt() { - $this->assertEquals( $this->_aunt_section, $this->_child_section->find_section_from_path( '../../aunt' ) ); - } - public function test_cousin() { - $this->assertEquals( $this->_cousin_section, $this->_child_section->find_section_from_path( '../../aunt/cousin' ) ); - } - public function test_nephew() { - $this->assertEquals( $this->_cousin_section, $this->_parent_section->find_section_from_path( '../aunt/cousin' ) ); - } - public function test_child() { - $this->assertEquals( $this->_child_section, $this->_parent_section->find_section_from_path( 'child' ) ); - } - - - public function test_grandparent(){ - $this->assertEquals( $this->_granparent_section, $this->_child_section->find_section_from_path( '../../' ) ); - } - public function test_self() { - $this->assertEquals( $this->_child_section, $this->_child_section->find_section_from_path( '' ) ); - $this->assertEquals( $this->_child_section, $this->_child_section->find_section_from_path( '../child' ) ); - } - public function test_invalid_strings() { - $invalid_strings = array( - 'child-of-child', - '../child/child-of-child', - '../brother-i-never-had' - ); - foreach( $invalid_strings as $invalid_string ) { - $this->assertNull( $this->_child_section->find_section_from_path( $invalid_string ), 'The string ' . $invalid_string . ' shouldnt be considered valid' ); - } - - } -} diff --git a/tests/testcases/core/libraries/form_sections/base/EE_Form_Section_Proper_Test.php b/tests/testcases/core/libraries/form_sections/base/EE_Form_Section_Proper_Test.php deleted file mode 100644 index 3a9ade92c71..00000000000 --- a/tests/testcases/core/libraries/form_sections/base/EE_Form_Section_Proper_Test.php +++ /dev/null @@ -1,472 +0,0 @@ -array( - 'first_name' => new EE_Text_Input(), - 'last_name' => new EE_Text_Input(), - ) - - )); - $data = array('first_name'=>'brent','last_name'=>'possum'); - $form->receive_form_submission( $data ); - $this->assertEquals( $data, $form->input_values() ); - } - public function test_add_subsection__before(){ - $input1 = new EE_Text_Input(); - $input2 = new EE_Text_Input(); - $input3 = new EE_Text_Input(); - $input4 = new EE_Text_Input(); - $input5 = new EE_Text_Input(); - $parent_form = new EE_Form_Section_Proper( array( - 'name' => 'form', - 'subsections' => array( - 'input1' => $input1, - 'input2' => $input2, - ) - )); - $inputs = $parent_form->inputs(); - $this->assertEquals( $input1, reset($inputs) ); - $this->assertEquals( $input2, next( $inputs ) ); - - //ok now add a subsection before the first one - $parent_form->add_subsections( array( 'input3' => $input3 ), 'input1' ); - $inputs = $parent_form->inputs(); - $this->assertEquals( $input3, reset($inputs) ); - $this->assertEquals( $input1, next( $inputs ) ); - $this->assertEquals( $input2, next( $inputs ) ); - - //now add a subsection in the middle - $parent_form->add_subsections( array( 'input4' => $input4 ), 'input1' ); - $inputs = $parent_form->inputs(); - $this->assertEquals( $input3, reset($inputs) ); - $this->assertEquals( $input4, next($inputs) ); - $this->assertEquals( $input1, next( $inputs ) ); - $this->assertEquals( $input2, next( $inputs ) ); - - //lastly add a subsection onto the very end - $parent_form->add_subsections( array( 'input5' => $input5 ), null, false ); - $inputs = $parent_form->inputs(); - $this->assertEquals( $input3, reset($inputs) ); - $this->assertEquals( $input4, next($inputs) ); - $this->assertEquals( $input1, next( $inputs ) ); - $this->assertEquals( $input2, next( $inputs ) ); - $this->assertEquals( $input5, next( $inputs ) ); - } - public function test_add_subsection__after(){ - $input1 = new EE_Text_Input(); - $input2 = new EE_Text_Input(); - $input3 = new EE_Text_Input(); - $input4 = new EE_Text_Input(); - $input5 = new EE_Text_Input(); - $parent_form = new EE_Form_Section_Proper( array( - 'name' => 'form', - 'subsections' => array( - 'input1' => $input1, - 'input2' => $input2, - ) - )); - $inputs = $parent_form->inputs(); - $this->assertEquals( $input1, reset($inputs) ); - $this->assertEquals( $input2, next( $inputs ) ); - - //ok now add a subsection after the last one - $parent_form->add_subsections( array( 'input3' => $input3 ), 'input2', false ); - $inputs = $parent_form->inputs(); - $this->assertEquals( $input1, reset($inputs) ); - $this->assertEquals( $input2, next( $inputs ) ); - $this->assertEquals( $input3, next( $inputs ) ); - - //now add a subsection in the middle - $parent_form->add_subsections( array( 'input4' => $input4 ), 'input2', false ); - $inputs = $parent_form->inputs(); - $this->assertEquals( $input1, reset($inputs) ); - $this->assertEquals( $input2, next($inputs) ); - $this->assertEquals( $input4, next( $inputs ) ); - $this->assertEquals( $input3, next( $inputs ) ); - - //lastly add a subsection onto the very beginning - $parent_form->add_subsections( array( 'input5' => $input5 ) ); - $inputs = $parent_form->inputs(); - $this->assertEquals( $input5, reset($inputs) ); - $this->assertEquals( $input1, next($inputs) ); - $this->assertEquals( $input2, next($inputs) ); - $this->assertEquals( $input4, next( $inputs ) ); - $this->assertEquals( $input3, next( $inputs ) ); - } - public function test_add_subsection__weird_subsection_names(){ - $grandparent_form = new EE_Form_Section_Proper(array( - 'name'=>'grandparent', - 'subsections'=>array( - '123-reg-money'=> new EE_Form_Section_Proper(array( - 'subsections'=>array( - '!0!a77y-bad`string' => new EE_Text_Input() - ) - )) - ) - )); - $grandparent_form->add_subsections(array('new_one'=>new EE_Text_Input())); - $added_input = $grandparent_form->get_input('new_one'); - $this->assertInstanceOf('EE_Text_Input', $added_input); - $this->assertEquals( 'new_one', $added_input->name() ); - $this->assertEquals( 'grandparent[new_one]', $added_input->html_name() ); - - $grandparent_form->add_subsections(array(12=>new EE_Text_Input())); - $other_added_input = $grandparent_form->get_input( 12 ); - $this->assertInstanceOf('EE_Text_Input', $other_added_input); - - } - public function test_form_data_present_in__normal(){ - $granparent_form = new EE_Form_Section_Proper(array( - 'name'=>'grandparent', - 'subsections'=>array( - 'parent' => new EE_Form_Section_Proper( array( - 'subsections' => array( - 'form' => new EE_Form_Section_Proper( array( - 'subsections' => array( - 'input' => new EE_Text_Input(), - 'input2' => new EE_Text_Input() - ) - ) - )) - ) - )) - ) - ); - - $req_data_good = array('grandparent'=>array('parent' => array( 'form' =>array( 'input' => 'value', 'input2' => 'value2')))); - $req_data_bad = array('foo'=>array('bar'=>array('monkey' => 'poop' ) ), - 'fluff' => array( 'baz' => array( 'lizard' => 'tail' ))); - $this->assertTrue( $granparent_form->form_data_present_in( $req_data_good) ); - $this->assertFalse( $granparent_form->form_data_present_in( $req_data_bad ) ); - } - public function test_form_data_present_in__custom_html_name(){ - $granparent_form = new EE_Form_Section_Proper(array( - 'name'=>'grandparent', - 'subsections'=>array( - 'parent' => new EE_Form_Section_Proper( array( - 'subsections' => array( - 'form' => new EE_Form_Section_Proper( array( - 'subsections' => array( - 'input' => new EE_Text_Input(array( - 'html_name' => 'foo[bar][monkey]', - )), - 'input2' => new EE_Text_Input(array( - 'html_name' => 'fluff[baz][lizard]' - )) - ) - ) - )) - ) - )) - ) - ); - - $req_data_bad = array('grandparent'=>array('parent' => array( 'form' =>array( 'input' => 'value', 'input2' => 'value2')))); - $req_data_good = array('foo'=>array('bar'=>array('monkey' => 'poop' ) ), - 'fluff' => array( 'baz' => array( 'lizard' => 'tail' ))); - $this->assertTrue( $granparent_form->form_data_present_in( $req_data_good) ); - $this->assertFalse( $granparent_form->form_data_present_in( $req_data_bad ) ); - - $parent_form = $granparent_form->get_subsection( 'parent' ); - $this->assertTrue( $parent_form->form_data_present_in( $req_data_good) ); - $this->assertFalse( $parent_form->form_data_present_in( $req_data_bad ) ); - - $form = $parent_form->get_subsection( 'form' ); - $this->assertTrue( $form->form_data_present_in( $req_data_good) ); - $this->assertFalse( $form->form_data_present_in( $req_data_bad ) ); - - } - - public function test_is_valid(){ - $form = new EE_Form_Section_Proper( array( - 'name'=>'form', - 'subsections' => array( - 'subform1' => new EE_Form_Section_Proper( array( - 'subsections' => array( - 'input1' => new EE_Text_Input() - ) - )) - ) - )); - $req_data_bad = array(); - $req_data_good = array('form' => array( 'subform1' => array( 'input1' => 'value' ) ) ); - $this->assertTrue( $form->was_submitted( $req_data_good ) ); - $form->receive_form_submission( $req_data_good ); - $this->assertTrue( $form->is_valid() ); - - } - - /** - * @group ticket_6505 - */ - public function test_numeric_named_inputs(){ - $form = new EE_Form_Section_Proper( - array( - 'html_id' => 'ee-available-payment-method-inputs', - 'subsections' => array( - 0 => new EE_Radio_Button_Input( - array( 'one' => 'One','two' => 'Two', 'three' => 'Three' ), - array( - 'html_name' => 'selected_method_of_payment', - 'html_class' => 'spco-payment-method', - 'default' => 'three' - ) - ) - ) - ) - ); - $this->assertEquals(1, count( $form->inputs() ) ); - } - - /** - * @group 6781 - */ - public function test_get_validation_errors_accumulated(){ - $form = new EE_Form_Section_Proper( - array( - 'name' => 'Form', - 'subsections' => array( - 'radio1' => new EE_Radio_Button_Input( - array( 'one' => 'One','two' => 'Two', 'three' => 'Three' ), - array( - 'html_class' => 'spco-payment-method', - 'default' => 'three' - ) - ), - 'input2' => new EE_Text_Input( array( - 'required' => TRUE - )), - 'subsubsection' => new EE_Form_Section_Proper( array( - 'subsections' => array( - 'input3' => new EE_Float_Input(), - 'input4' => new EE_Text_Input() - ) - )) - ) - ) - ); - $post_data = array( - 'Form' => array( - 'radio1' => 'four-invalid', - 'input2' => '', - 'subsubsection' => array( - 'input3' => 'non-number', - 'input4' => 'whatever-ok' - )) - ); - $form->receive_form_submission( $post_data ); - //submit twice, which should be fine; it shoudl jsut reset before - //2nd submission - $form->receive_form_submission( $post_data ); - $this->assertFalse( $form->is_valid() ); - $all_errors = $form->get_validation_errors_accumulated(); - $this->assertEquals( 3, count( $all_errors ) ); - $error1 = array_shift( $all_errors ); - $error2 = array_shift( $all_errors ); - $error3 = array_shift( $all_errors ); - - - $this->assertInstanceOf( 'EE_Validation_Error', $error1 ); - $this->assertInstanceOf( 'EE_Radio_Button_Input', $error1->get_form_section() ); - $this->assertEquals( 'radio1', $error1->get_form_section()->name() ); - - - $this->assertInstanceOf( 'EE_Validation_Error', $error2 ); - $this->assertInstanceOf( 'EE_Text_Input', $error2->get_form_section() ); - $this->assertEquals( 'input2', $error2->get_form_section()->name() ); - $this->assertInstanceOf( 'EE_Validation_Error', $error3 ); - $this->assertInstanceOf( 'EE_Float_Input', $error3->get_form_section() ); - $this->assertEquals( 'input3', $error3->get_form_section()->name() ); - } - - /** - * Tests the form was submitted functionality. - * - * @group 7431 - */ - public function test_form_was_submitted() { - $form = new EE_Form_Section_Proper( array( - 'name' => 'test_form', - 'html_id' => 'test_form', - 'subsections' => array( - 'yes_no' => new EE_Yes_No_Input( - array( - 'html_label_text' => 'testing', - 'default' => false - ) - ) - ) - ) - ); - $post_data = array( - 'test_form' => array( - 'yes_no' => '0' - ) - ); - $this->assertTrue( $form->was_submitted( $post_data ) ); - } - /** - * @group 9784 - * Verify EE_FOrm_SEction_proper::submitted_values() generates an array - * exactly like the submitted data - */ - public function test_submitted_values() { - $form = new EE_Form_Section_Proper( - array( - 'name' => 'top', - 'subsections' => array( - 'middle' => new EE_Form_Section_Proper( - array( - 'subsections' => array( - 'bottom_input1' => new EE_Phone_Input(), - 'bottom_checkbox' => new EE_Checkbox_Multi_Input( - array( - 'op1' => 'option1', - 'op2' => 'option2', - 'op3' => 'option3' - ) - ) - ) - ) - ), - 'middle_checkbox' => new EE_Checkbox_Multi_Input( - array( - 'op1' => 'option1', - 'op2' => 'option2', - 'op3' => 'option3' - ) - ), - 'middle_radio' => new EE_Radio_Button_Input( - array( - 'op1' => 'option1', - 'op2' => 'option2' - ) - ) - ) - ) - ); - $form->_construct_finalize(null, null ); - $submitted_data = array( - 'top' => array( - 'middle' => array( - 'bottom_input1' => 'not-a-phone-number', - 'bottom_checkbox' => array( - 'op2', - 'not-existent-op' - ) - ), - 'middle_checkbox' => array( - 'op2', - 'not-existent-op' - ), - 'middle_radio' => 'op1' - ) - ); - $form->receive_form_submission( - $submitted_data - ); - $this->assertEquals( - $submitted_data, - $form->submitted_values( true ) - ); - } - - /** - * @group 9784 - * Verify EE_FOrm_section_Proper::submitted_values generates the post-like submission - * array when there are custom names on inputs - */ - public function test_submitted_values__custom_html_name_on_input(){ - $form = new EE_Form_Section_Proper( - array( - 'name' => 'top', - 'subsections' => array( - 'middle' => new EE_Form_Section_Proper( - array( - 'subsections' => array( - 'bottom' => new EE_Text_Input( - array( - 'html_name' => 'custom_html_name' - ) - ) - ) - ) - ) - ) - ) - ); - $form->_construct_finalize(null, null); - $submitted_data = array( - 'custom_html_name' => 'value' - ); - $form->receive_form_submission( $submitted_data ); - $this->assertEquals( - $submitted_data, - $form->submitted_values( true ) - ); - } - - - - /** - * validate the form (which caches the result) then re-submit it and verify the cache got cleared - * @group 11381 - */ - public function testIsValidCached() - { - $f = new EE_Form_Section_Proper( - array( - 'name' => 'form', - 'subsections'=> array( - 'int' => new EE_Integer_Input( - array( - 'required' => true - ) - ) - ) - ) - ); - $f->receive_form_submission( - array( - 'form' => array( - 'int' => '4' - ) - ) - ); - $this->assertTrue($f->is_valid()); - //and double-check calling it again works fine too - $this->assertTrue($f->is_valid()); - //now change the form's input - $f->receive_form_submission( - array( - 'form' => array( - 'int' => 'saskquatch' - ) - ) - ); - $this->assertFalse($f->is_valid()); - - } -} - -// End of file EE_Form_Section_Proper_Test.php diff --git a/tests/testcases/core/libraries/form_sections/inputs/EE_Form_Input_Base_Test.php b/tests/testcases/core/libraries/form_sections/inputs/EE_Form_Input_Base_Test.php deleted file mode 100644 index 1ed3715693f..00000000000 --- a/tests/testcases/core/libraries/form_sections/inputs/EE_Form_Input_Base_Test.php +++ /dev/null @@ -1,247 +0,0 @@ -'grandparent', - 'subsections'=>array( - 'parent' => new EE_Form_Section_Proper( array( - 'subsections' => array( - 'form' => new EE_Form_Section_Proper( array( - 'subsections' => array( - 'input' => new EE_Text_Input() - ) - ) - )) - ) - )) - ) - ); - - $input = $granparent_form->get_subsection( 'parent' )->get_subsection( 'form' )->get_subsection( 'input' ); - $this->assertInstanceOf('EE_Form_Input_Base', $input); - $this->assertEquals('grandparent[parent][form][input]', $input->html_name()); - } - - public function test_find_form_data_for_this_section__custom_html_name(){ - $granparent_form = new EE_Form_Section_Proper(array( - 'name'=>'grandparent', - 'subsections'=>array( - 'parent' => new EE_Form_Section_Proper( array( - 'subsections' => array( - 'form' => new EE_Form_Section_Proper( array( - 'subsections' => array( - 'input' => new EE_Text_Input(array( - 'html_name' => 'foo[bar][monkey]' - )) - ) - ) - )) - ) - )) - ) - ); - $input = $granparent_form->get_subsection( 'parent' )->get_subsection( 'form' )->get_subsection( 'input' ); - $req_data_bad = array('grandparent'=>array('parent' => array( 'form' =>array( 'input' => 'value')))); - $req_data_good = array('foo'=>array('bar'=>array('monkey' => 'value'))); - $this->assertNull($input->find_form_data_for_this_section( $req_data_bad ) ); - $this->assertEquals( 'value', $input->find_form_data_for_this_section( $req_data_good ) ); - } - - public function test_find_form_data_for_this_section__normal(){ - $granparent_form = new EE_Form_Section_Proper(array( - 'name'=>'grandparent', - 'subsections'=>array( - 'parent' => new EE_Form_Section_Proper( array( - 'subsections' => array( - 'form' => new EE_Form_Section_Proper( array( - 'subsections' => array( - 'input' => new EE_Text_Input() - ) - ) - )) - ) - )) - ) - ); - $input = $granparent_form->get_subsection( 'parent' )->get_subsection( 'form' )->get_subsection( 'input' ); - $req_data_good = array('grandparent'=>array('parent' => array( 'form' =>array( 'input' => 'value')))); - $req_data_bad = array('foo'=>array('bar'=>array('monkey' => 'value'))); - $this->assertNull($input->find_form_data_for_this_section( $req_data_bad ) ); - $this->assertEquals( 'value', $input->find_form_data_for_this_section( $req_data_good ) ); - } - - public function test_form_data_present_in__normal(){ - $granparent_form = new EE_Form_Section_Proper(array( - 'name'=>'grandparent', - 'subsections'=>array( - 'parent' => new EE_Form_Section_Proper( array( - 'subsections' => array( - 'form' => new EE_Form_Section_Proper( array( - 'subsections' => array( - 'input' => new EE_Text_Input(), - 'input2' => new EE_Text_Input() - ) - ) - )) - ) - )) - ) - ); - - $req_data_good = array('grandparent'=>array('parent' => array( 'form' =>array( 'input' => 'value', 'input2' => 'value2')))); - $req_data_bad = array('foo'=>array('bar'=>array('monkey' => 'poop' ) ), - 'fluff' => array( 'baz' => array( 'lizard' => 'tail' ))); - $input = $granparent_form->get_subsection( 'parent' )->get_subsection( 'form' )->get_subsection( 'input' ); - $this->assertTrue( $input->form_data_present_in( $req_data_good) ); - $this->assertFalse( $input->form_data_present_in( $req_data_bad ) ); - } - public function test_form_data_present_in__custom_html_name(){ - $granparent_form = new EE_Form_Section_Proper(array( - 'name'=>'grandparent', - 'subsections'=>array( - 'parent' => new EE_Form_Section_Proper( array( - 'subsections' => array( - 'form' => new EE_Form_Section_Proper( array( - 'subsections' => array( - 'input' => new EE_Text_Input(array( - 'html_name' => 'foo[bar][monkey]', - )), - 'input2' => new EE_Text_Input(array( - 'html_name' => 'fluff[baz][lizard]' - )) - ) - ) - )) - ) - )) - ) - ); - - $req_data_bad = array('grandparent'=>array('parent' => array( 'form' =>array( 'input' => 'value', 'input2' => 'value2')))); - $req_data_good = array('foo'=>array('bar'=>array('monkey' => 'poop' ) ), - 'fluff' => array( 'baz' => array( 'lizard' => 'tail' ))); - $input = $granparent_form->get_subsection( 'parent' )->get_subsection( 'form' )->get_subsection( 'input' ); - $this->assertTrue( $input->form_data_present_in( $req_data_good) ); - $this->assertFalse( $input->form_data_present_in( $req_data_bad ) ); - - - } - - /** - * Verifies that the inputs default HTML names reflect the actual form structure. - * @group 10110 - */ - public function test_input_names_should_be_consistent_regardless_of_when_input_was_added() { - $input1 = new EE_Text_Input(); - $form = new EE_Form_Section_Proper( - array( - 'subsections' => array( - 'input1' => $input1, - ) - ) - ); - $form->_construct_finalize( null, null ); - //ok so subform is complete right? Well let's now make it a subform. - //what could possibly go wrong when you do that? - $top_form = new EE_Form_Section_Proper( - array( - 'subsections' => array( - 'subform' => $form - ) - ) - ); - $top_form->_construct_finalize(null, 'topform' ); - //ok great. Now let's add something to the form. It shouldn't - //matter if the input was added when the form was constructed, - //or after it was all done being constructed. It should still work. - $input2 = new EE_Text_Input(); - $form->add_subsections( - array( - 'input2' => $input2 - ) - ); - //both inputs, regardless of when they were added, should have pretty well the - //same html name. - $this->assertEquals( 'topform[subform][input1]', $input1->html_name() ); - $this->assertEquals( 'topform[subform][input2]', $input2->html_name() ); - } - - - - /** - * Tests that if `ignore_input` is provided, we get the null normalization and no validation strategies - * @group 11380 - * @group current - */ - public function testIgnoreInput() { - $f = new EE_Form_Section_Proper( - array( - 'name' => 'form', - 'subsections' => array( - 'text' => new EE_Text_Input( - array( - 'ignore_input' => true - ) - ), - 'email' => new EE_Email_Input( - array( - 'ignore_input' => true - ) - ), - 'checkbox' => new EE_Checkbox_Multi_Input( - array('a','b'), - array( - 'ignore_input' => true - ) - ), - 'radio' => new EE_Radio_Button_Input( - array('a','b'), - array( - 'ignore_input' => true - ) - ), - 'ok' => new EE_Text_Input() - ) - ) - ); - $f->receive_form_submission( - array( - 'form' => array( - 'text' => 'hackerz', - 'email' => 'virus!', - 'checkbox' => array( 2, 3), - 'radio' => 3, - 'ok' => 'yep' - ) - ) - ); - $this->assertNull($f->get_input_value('text')); - $this->assertNull($f->get_input_value('email')); - $this->assertNull($f->get_input_value('checkbox')); - $this->assertNull($f->get_input_value('radio')); - //verify we still get normal inputs - $this->assertEquals('yep', $f->get_input_value('ok')); - //verify the form is still valid, even though the inputs had null normalization - $this->assertTrue($f->is_valid()); - } -} - -// End of file EE_Form_Input_Base_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/form_sections/inputs/EE_Form_Input_With_Options_Test.php b/tests/testcases/core/libraries/form_sections/inputs/EE_Form_Input_With_Options_Test.php deleted file mode 100644 index 6938682e263..00000000000 --- a/tests/testcases/core/libraries/form_sections/inputs/EE_Form_Input_With_Options_Test.php +++ /dev/null @@ -1,85 +0,0 @@ - 'test1', - 'subsections' => array( - 'radio1' => new EE_Radio_Button_Input(array( - 'option1' => 'Option 1', - 'option2' => 'Option 2' ) - )) - )); - $radio_button = $form->get_input( 'radio1' ); - //that radio button's normalization strategy is correct - $this->assertInstanceOf( 'EE_Radio_Button_Input', $radio_button ); - $this->assertInstanceOf( 'EE_Text_Normalization', $radio_button->get_normalization_strategy() ); - //and that when it receives input, it sets it correctly - $form->receive_form_submission( array( 'radio1' => 'option1' ) ); - $this->assertTrue($form->is_valid() ); - $form->receive_form_submission( array( 'radio1' => 'option_nonexistent' ) ); - $this->assertFalse( $form->is_valid() ); - } - - /** - * Verifies we don't change these options into booleans - * @group 8006 - */ - function test_double_valued_with_blank(){ - EEM_Country::reset(); - EEM_Country::instance()->update( array( 'CNT_active' => false ), array() ); - EEM_Country::instance()->update( array( 'CNT_active' => true), array( 'limit' => 1 ) ); - $active_countries = EEM_Country::instance()->get_all( array( array( 'CNT_active' => true ) ) ); - $this->assertEquals( 1, count( $active_countries ) ); - $active_country = reset( $active_countries ); - $country_input = new EE_Country_Select_Input(); - $this->assertEquals( - array( - '' => '', - $active_country->ID() => $active_country->name() - ), - $country_input->options() ); - $this->assertInstanceOf( 'EE_Text_Normalization', $country_input->get_normalization_strategy() ); - } - - function test_many_valued(){ - //create a form with radio button in it. - $form = new EE_Form_Section_Proper(array( - 'name' => 'test1', - 'subsections' => array( - 'checkbox1' => new EE_Checkbox_Multi_Input(array( - 'option1' => 'Option 1', - 'option2' => 'Option 2' ) - )) - )); - $checkbox = $form->get_input( 'checkbox1' ); - //that radio button's normalization strategy is correct - $this->assertInstanceOf( 'EE_Checkbox_Multi_Input', $checkbox ); - $this->assertInstanceOf( 'EE_Many_Valued_Normalization', $checkbox->get_normalization_strategy() ); - //and that when it receives input, it sets it correctly - $form->receive_form_submission( array( 'checkbox1' => array( 'option1' ) ) ); - $this->assertTrue($form->is_valid() ); - $form->receive_form_submission( array( 'checkbox1' => array( 'option_nonexistent' ) ) ); - $this->assertFalse( $form->is_valid() ); - $form->receive_form_submission( array( 'checkbox1' => 'option1' ) ); - $this->assertTrue( $form->is_valid() ); - $form->receive_form_submission( array( 'checkbox1' => 'option_nonexistent' ) ); - $this->assertFalse( $form->is_valid() ); - } - -} - -// End of file EE_Radio_Button_Input_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/form_sections/inputs/EE_Radio_Button_Input_Test.php b/tests/testcases/core/libraries/form_sections/inputs/EE_Radio_Button_Input_Test.php deleted file mode 100644 index c5f9a1d3e6e..00000000000 --- a/tests/testcases/core/libraries/form_sections/inputs/EE_Radio_Button_Input_Test.php +++ /dev/null @@ -1,57 +0,0 @@ - 'test', - 'subsections' => array( - 'use_captcha' => new EE_Radio_Button_Input( - array( - 1 => __( 'Yes', 'event_espresso' ), - 0 => __( 'No', 'event_espresso' ) - ), - array( - 'html_label_text' => __( 'Use reCAPTCHA', 'event_espresso' ), - 'default' => isset( EE_Registry::instance()->CFG->registration->use_captcha ) ? EE_Registry::instance()->CFG->registration->use_captcha : FALSE, - 'normalization_strategy' => new EE_Int_Normalization() - ) - ) - ) - )); - $form->receive_form_submission( array( - 'test' => array( - 'use_captcha' => '1' - ) - )); - $this->assertTrue( $form->is_valid() ); - $this->assertTrue( 1 === $form->get_input( 'use_captcha' )->normalized_value() ); - $this->assertTrue( '1' === $form->get_input( 'use_captcha' )->raw_value() ); - - $form->receive_form_submission( array( - 'test' => array( - 'use_captcha' => '0' - ) - )); - $this->assertTrue( $form->is_valid() ); - $this->assertTrue( 0 === $form->get_input( 'use_captcha' )->normalized_value() ); - $this->assertTrue( '0' === $form->get_input( 'use_captcha' )->raw_value() ); - } -} - -// End of file EE_Radio_Button_Input_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/form_sections/inputs/EE_State_Select_Input_Test.php b/tests/testcases/core/libraries/form_sections/inputs/EE_State_Select_Input_Test.php deleted file mode 100644 index 5d945e089f3..00000000000 --- a/tests/testcases/core/libraries/form_sections/inputs/EE_State_Select_Input_Test.php +++ /dev/null @@ -1,105 +0,0 @@ - 'where-you-live', - 'subsections' => array( - 'state' => new EE_State_Select_Input(null) - ) - ) - ); - $submitted_data = array('where-you-live' => array()); - $form->receive_form_submission($submitted_data); - $this->assertTrue($form->is_valid()); - $this->assertEmpty($form->submission_error_message()); - $this->assertEquals( - null, - $form->get_input('state')->normalized_value() - ); - $this->assertEquals( - '', - $form->get_input('state')->raw_value() - ); - $this->assertEquals( - array('where-you-live' => array('state' => '')), - $form->submitted_values(true) - ); - } - - - /** - * @group 10643 - * @throws EE_Error - */ - public function test_required_EE_State_Input_with_no_input() - { - $form = new EE_Form_Section_Proper( - array( - 'name' => 'where-you-live', - 'subsections' => array( - 'state' => new EE_State_Select_Input(null, array('required' => true)) - ) - ) - ); - $submitted_data = array('where-you-live' => array()); - $form->receive_form_submission($submitted_data); - $this->assertFalse($form->is_valid()); - $this->assertNotEmpty($form->submission_error_message()); - } - - - - /** - * @group 10643 - * @throws EE_Error - */ - public function test_EE_State_Input_with_input() - { - $form = new EE_Form_Section_Proper( - array( - 'name' => 'where-you-live', - 'subsections' => array( - 'state' => new EE_State_Select_Input(null) - ) - ) - ); - $submitted_data = array('where-you-live' => array('state' => 61)); - $form->receive_form_submission($submitted_data); - $this->assertTrue($form->is_valid()); - $this->assertEquals( - 61, - $form->get_input('state')->normalized_value() - ); - $this->assertEquals( - '61', - $form->get_input('state')->raw_value() - ); - $this->assertEquals( - $submitted_data, - $form->submitted_values(true) - ); - } - - -} - -// End of file EE_Radio_Button_Input_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/form_sections/strategies/display/EE_Button_Input_Display_Strategy_Test.php b/tests/testcases/core/libraries/form_sections/strategies/display/EE_Button_Input_Display_Strategy_Test.php deleted file mode 100644 index 4c69432410c..00000000000 --- a/tests/testcases/core/libraries/form_sections/strategies/display/EE_Button_Input_Display_Strategy_Test.php +++ /dev/null @@ -1,38 +0,0 @@ -Brent On skateboard'; - $input = new EE_Button_Input( - array( - 'button_content' => $button_content, - 'default' => 'brent-skateboard' - ) - ); - $input->_construct_finalize(null, 'brent-on-skateboard'); - $output = $input->get_display_strategy()->display(); - $expected = ''; - $this->assertHTMLEquals($expected,$output); - } -} - -// End of file EE_Button_Input_Display_Strategy_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/form_sections/strategies/display/EE_Checkbox_Display_Strategy_Test.php b/tests/testcases/core/libraries/form_sections/strategies/display/EE_Checkbox_Display_Strategy_Test.php deleted file mode 100644 index cb227d99480..00000000000 --- a/tests/testcases/core/libraries/form_sections/strategies/display/EE_Checkbox_Display_Strategy_Test.php +++ /dev/null @@ -1,58 +0,0 @@ - 'form', - 'subsections' => array( - 'input1' => new EE_Checkbox_Multi_Input(array('foo' => 'Foo', 'bar' => 'Bar', "baz'em" => 'Baz')), - ), - )); - $input = $form->get_input('input1'); - // data-question_label="ee_reg_qstn-6-11-lbl" - $expected_output = ' - - -'; - $this->assertHTMLEquals($expected_output, $input->get_html_for_input()); - //now if we set the default, does it get selected? - $form->populate_defaults(array( - 'input1' => array("baz'em", 'bar'), - )); - $this->assertEquals(array("baz'em", 'bar'), $input->normalized_value()); - $this->assertEquals(array("baz'em", 'bar'), $input->raw_value()); - $expected_output2 = ' - - -'; - $this->assertHTMLEquals($expected_output2, $input->get_html_for_input()); - } -} - -// End of file tests/testcases/core/libraries/form_sections/strategies/display/EE_Checkbox_Display_Strategy_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/form_sections/strategies/display/EE_Number_Input_Display_Strategy_Test.php b/tests/testcases/core/libraries/form_sections/strategies/display/EE_Number_Input_Display_Strategy_Test.php deleted file mode 100644 index 186911bf70a..00000000000 --- a/tests/testcases/core/libraries/form_sections/strategies/display/EE_Number_Input_Display_Strategy_Test.php +++ /dev/null @@ -1,84 +0,0 @@ -_construct_finalize(null, 'age'); - $output = $input->get_display_strategy()->display(); - $expected = ''; - $this->assertHTMLEquals($expected,$output); - } - - /** - * @group 10586 - */ - public function test_display__with_min_max_required() - { - $input = new EE_Integer_Input( - array( - 'min_value' => 2, - 'max_value' => 5, - 'html_class' => 'funky', - 'required' => true - )); - $input->_construct_finalize(null, 'age'); - $output = $input->get_display_strategy()->display(); - $expected = ''; - $this->assertHTMLEquals($expected,$output); - } - - /** - * @group 10586 - */ - public function test_display__for_float() - { - $input = new EE_Float_Input( - array( - 'html_class' => 'funky', - 'required' => true, - 'step_value' => 'any', - 'min_value' => -2 - ) - ); - $input->_construct_finalize(null, 'age'); - $output = $input->get_display_strategy()->display(); - $expected = ''; - $this->assertHTMLEquals($expected,$output); - } - - /** - * @group 10586 - */ - public function test_display__with_value() - { - $input = new EE_Integer_Input( - array( - 'default' => 123 - ) - ); - $input->_construct_finalize(null, 'age'); - $output = $input->get_display_strategy()->display(); - $expected = ''; - $this->assertHTMLEquals($expected,$output); - } -} - -// End of file EE_Checkbox_Display_Strategy_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/form_sections/strategies/display/EE_Radio_Button_Display_Strategy_Test.php b/tests/testcases/core/libraries/form_sections/strategies/display/EE_Radio_Button_Display_Strategy_Test.php deleted file mode 100644 index 3290592831b..00000000000 --- a/tests/testcases/core/libraries/form_sections/strategies/display/EE_Radio_Button_Display_Strategy_Test.php +++ /dev/null @@ -1,114 +0,0 @@ - 'test', - 'subsections' => array( - 'use_captcha' => new EE_Radio_Button_Input( - array( - 1 => __('Yes', 'event_espresso'), - 0 => __('No', 'event_espresso'), - ), - array( - 'html_label_text' => __('Use reCAPTCHA', 'event_espresso'), - 'default' => 1, - 'normalization_strategy' => new EE_Int_Normalization(), - ) - ), - ), - )); - $this->assertEquals(1, $form->get_input('use_captcha')->normalized_value()); - $this->assertEquals('1', $form->get_input('use_captcha')->raw_value()); - $this->assertHTMLEquals(' - - -
-
', $form->get_input('use_captcha')->get_html_for_input()); - - $form->populate_defaults(array('use_captcha' => 0)); - //the first option should be selected now - $this->assertEquals(0, $form->get_input('use_captcha')->normalized_value()); - $this->assertEquals('0', $form->get_input('use_captcha')->raw_value()); - $this->assertHTMLEquals(' - - -
-
', $form->get_input('use_captcha')->get_html_for_input()); - } - - - /** - * @group 7121 - * @group html - * @throws EE_Error - */ - public function test_display__normalizing_as_string() - { - $form = new EE_Form_Section_Proper(array( - 'name' => 'test', - 'subsections' => array( - 'use_captcha' => new EE_Radio_Button_Input( - array( - "yes ma'am" => __('Yes', 'event_espresso'), - "no ma'am" => __('No', 'event_espresso'), - ), - array( - 'html_label_text' => __('Use reCAPTCHA', 'event_espresso'), - 'default' => "yes ma'am", - ) - ), - ), - )); - $this->assertEquals("yes ma'am", $form->get_input('use_captcha')->normalized_value()); - $this->assertEquals("yes ma'am", $form->get_input('use_captcha')->raw_value()); - $this->assertHTMLEquals(' - - -
-
', $form->get_input('use_captcha')->get_html_for_input()); - - $form->populate_defaults(array('use_captcha' => "no ma'am")); - //the first option should be selected now - $this->assertEquals("no ma'am", $form->get_input('use_captcha')->normalized_value()); - $this->assertEquals("no ma'am", $form->get_input('use_captcha')->raw_value()); - $this->assertHTMLEquals(' - - -
-
', $form->get_input('use_captcha')->get_html_for_input()); - } -} - -// End of file tests/testcases/core/libraries/form_sections/strategies/display/EE_Radio_Button_Display_Strategy_Test.php diff --git a/tests/testcases/core/libraries/form_sections/strategies/display/EE_Select_Display_Strategy_Test.php b/tests/testcases/core/libraries/form_sections/strategies/display/EE_Select_Display_Strategy_Test.php deleted file mode 100644 index f11678f89ee..00000000000 --- a/tests/testcases/core/libraries/form_sections/strategies/display/EE_Select_Display_Strategy_Test.php +++ /dev/null @@ -1,85 +0,0 @@ - 'form', - 'subsections' => array( - 'input1' => new EE_Select_Input( array( 'foo' => 'Foo', 'bar' => 'Bar', "baz'em" => 'Baz' ) ) - ) - )); - $input = $form->get_input( 'input1' ); - $expected_output = ' -'; - $this->assertHTMLEquals( $expected_output, $input->get_html_for_input() ); - //now if we set the default, does it get selected? - $form->populate_defaults( array( - 'input1' => "baz'em" - )); - $this->assertEquals( "baz'em", $input->normalized_value() ); - $this->assertEquals( "baz'em", $input->raw_value() ); - $expected_output2 = ' -'; - $this->assertHTMLEquals( $expected_output2, $input->get_html_for_input() ); - - } - - /** - * @group html - */ - public function test_display_flat_multidimensional_array(){ - $input = new EE_Select_Input( array( - 'code_var_names' => array( - 'foo' => 'Foo', - 'bar' => 'Bar', - 'baz' => 'Baz' ), - 'primates' => array( - 'chimp' => 'Chimp', - 'orangutan' => 'Orangutan', - 'baboon' => 'Baboon' - ))); - $expected_output = ' -'; - $this->assertHTMLEquals( $expected_output, $input->get_html_for_input() ); - - - } -} - -// End of file EE_Select_Display_Strategy_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/form_sections/strategies/display/EE_Select_Multiple_Display_Strategy_Test.php b/tests/testcases/core/libraries/form_sections/strategies/display/EE_Select_Multiple_Display_Strategy_Test.php deleted file mode 100644 index 6ef18ca97d8..00000000000 --- a/tests/testcases/core/libraries/form_sections/strategies/display/EE_Select_Multiple_Display_Strategy_Test.php +++ /dev/null @@ -1,53 +0,0 @@ - 'form', - 'subsections' => array( - 'input1' => new EE_Select_Multiple_Input( array( 'foo' => 'Foo', 'bar' => 'Bar', "baz'em" => 'Baz' ) ) - ) - )); - $input = $form->get_input( 'input1' ); - $expected_output = ' -'; - $this->assertHTMLEquals( $expected_output, $input->get_html_for_input() ); - //now if we set the default, does it get selected? - $form->populate_defaults( array( - 'input1' => array( "baz'em", 'bar' ) - )); - $this->assertEquals( array( "baz'em", 'bar' ), $input->normalized_value() ); - $this->assertEquals( array( "baz'em", 'bar' ), $input->raw_value() ); - $expected_output2 = ' -'; - $this->assertHTMLEquals( $expected_output2, $input->get_html_for_input() ); - - } -} - -// End of file EE_Select_Display_Strategy_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/form_sections/strategies/display/EE_Submit_Input_Display_Strategy_Test.php b/tests/testcases/core/libraries/form_sections/strategies/display/EE_Submit_Input_Display_Strategy_Test.php deleted file mode 100644 index 9a7ca6f7711..00000000000 --- a/tests/testcases/core/libraries/form_sections/strategies/display/EE_Submit_Input_Display_Strategy_Test.php +++ /dev/null @@ -1,72 +0,0 @@ -_construct_finalize(null, 'search'); - $output = $input->get_display_strategy()->display(); - $expected = ''; - $this->assertHTMLEquals($expected,$output); - } - - /** - * Verifies that even if the form is submitted WITHOUT pressing the submit button, - * when we show the form we will still show the submit input with the same value - * @group 11107 - */ - public function test_display__dont_change_value() - { - $submit_input = new EE_Submit_Input( - array( - 'default' => 'Apply', - ) - ); - $form = new EE_Form_Section_Proper(array( - 'name' => 'myform', - 'subsections' => array( - 'discount_code' => new EE_Text_Input(), - 'apply' => $submit_input - ) - )); - $form->receive_form_submission( - array( - 'myform' => array( - 'discount_code' => '', - //missing 'apply' on purrpose - ) - ) - ); - $this->assertEquals( - '', - $submit_input->raw_value() - ); - $this->assertEquals( - '', - $submit_input->normalized_value() - ); - $output = $submit_input->get_display_strategy()->display(); - $expected = ''; - $this->assertHTMLEquals($expected,$output); - } -} - -// End of file EE_Checkbox_Display_Strategy_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/form_sections/strategies/filter/VsprintfFilterTest.php b/tests/testcases/core/libraries/form_sections/strategies/filter/VsprintfFilterTest.php deleted file mode 100644 index 7b449c57669..00000000000 --- a/tests/testcases/core/libraries/form_sections/strategies/filter/VsprintfFilterTest.php +++ /dev/null @@ -1,96 +0,0 @@ - new VsprintfFilter( - '^^-1%1$s--2%2$s---3%3$s----4%4$s-1%1$s^^', - array( - 'argument1', - 'argument2', - ) - ), - 'subsections' => array( - 'some_input' => new EE_Text_Input() - ) - ) - ); - - //get the html for the form - $actual_output = $form->get_html(); - //our expectations are the following output: - //^^-1argument1--2argument2---3 - // - // - // - // - // - // - // - // - //
- // - // - // - //
- // - // - // - // ----4 - // - // - // - // - // - // - // - // - //-1argument1^^ - - //there should be two instances of the following, one at the beginning and one at the end - $expected_string_end = '-1argument1^^'; - $this->assertEquals(2, substr_count($actual_output, '-1argument1')); - $this->assertEquals(0, strpos($actual_output, '^^-1argument1')); - $this->assertEquals( - strlen($actual_output)-strlen($expected_string_end), - strrpos($actual_output, $expected_string_end) - ); - - //there should be one instance of the following - $this->assertEquals(1, substr_count($actual_output, '--2argument2')); - $this->assertEquals(0, strpos($actual_output, '^^-1argument1--2argument2')); - - //entire form should be in here - $this->assertEquals( - 1, - substr_count($actual_output, '') - ); - - //text input should appear twice - $this->assertEquals( - 2, - substr_count($actual_output, '_strategy = new EE_Float_Normalization(); - $input = new EE_Text_Input(); - $this->_strategy->_construct_finalize( $input ); - } - - - /** - * Data Provider for OK float inputs - * @return array{ - * array{ - * $0 the expected float - * $1 the input value - * } - * } - */ - public function ok_float_inputs(){ - return array( - array(null,''), - array(null,' '), - array(10, '10'), - array(10, '10'), - array(1000,'1,000'), - array(1000,' 1 000'), - array(10,'$10'), - array(1,'1.00'), - array(1000,' 1, 000.00'), - array(-1,'-1'), - array(-1,'- 1'), - array(20,'20 guineas'), - array(10,10.00), - array(56, '5 quid 6 pence'), - array(null, 'one hundred'), - ); - } - - - - /** - * @group 10586 - * @dataProvider ok_float_inputs - * @param $expected - * @param $input - * @throws EE_Validation_Error - */ - public function test_normalize_ok($expected, $input){ - $this->assertEquals($expected, $this->_strategy->normalize($input)); - } - - - /** - * Data Provider for bad float inputs - * @return array of arrays with the invalid inputs - */ - public function bad_float_inputs(){ - return array( - array(array()), - array(new stdClass()), - ); - } - - - - /** - * @group 10586 - * @dataProvider bad_float_inputs - * @expectedException EE_Validation_Error - * @param $input - * @throws EE_Validation_Error - */ - public function test_bad_float_inputs($input){ - $this->_strategy->normalize( $input ); - } -} - -// End of file EE_Float_Normalization_Test.php -// Location: tests/testcases/core/libraries/form_sections/strategies/normalization/EE_Float_Normalization_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/form_sections/strategies/normalization/EE_Int_Normalization_Test.php b/tests/testcases/core/libraries/form_sections/strategies/normalization/EE_Int_Normalization_Test.php deleted file mode 100644 index 4c2145159da..00000000000 --- a/tests/testcases/core/libraries/form_sections/strategies/normalization/EE_Int_Normalization_Test.php +++ /dev/null @@ -1,104 +0,0 @@ -_strategy = new EE_Int_Normalization(); - $input = new EE_Text_Input(); - $this->_strategy->_construct_finalize( $input ); - } - - - /** - * Data Provider for OK float inputs - * @return array{ - * array{ - * $0 the expected integer - * $1 the input value - * } - * } - */ - public function ok_int_inputs(){ - return array( - array(null,''), - array(null,' '), - array(10, '10'), - array(10, '10'), - array(1000,'1,000'), - array(1000,' 1 000'), - array(-1,'-1'), - array(-1,'- 1'), - array(10,10), - array(20,'20 guineas'), - array(10,'10.00'), - array(10,'10.0'), - array(10,'10.00000'), - array(10,'$10'), - array(56, '5 quid 6 pence'), - array(null, 'one hundred'), - ); - } - - - - /** - * @group 10586 - * @dataProvider ok_int_inputs - * @param $expected - * @param $input - * @throws EE_Validation_Error - */ - public function test_normalize_ok($expected, $input){ - $this->assertEquals($expected, $this->_strategy->normalize($input)); - } - - - /** - * Data Provider for bad float inputs - * @return array of arrays with the invalid inputs - */ - public function bad_int_inputs(){ - return array( - array(array()), - array(new stdClass()), - array('10.01'), - array('10.') - ); - } - - - - /** - * @group 10586 - * @dataProvider bad_int_inputs - * @expectedException EE_Validation_Error - * @param $input - * @throws EE_Validation_Error - */ - public function test_bad_float_inputs($input){ - $this->_strategy->normalize( $input ); - } -} - -// End of file EE_Int_Normalization_Test.php -// Location: tests/testcases/core/libraries/form_sections/strategies/normalization/EE_Int_Normalization_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/form_sections/strategies/validation/EE_Email_Validation_Strategy_Test.php b/tests/testcases/core/libraries/form_sections/strategies/validation/EE_Email_Validation_Strategy_Test.php deleted file mode 100644 index 39d638c28a9..00000000000 --- a/tests/testcases/core/libraries/form_sections/strategies/validation/EE_Email_Validation_Strategy_Test.php +++ /dev/null @@ -1,322 +0,0 @@ -_validator = new EE_Email_Validation_Strategy(); - //finalize its construction, but we don't actually need the input anyways - $this->_validator->_construct_finalize( new EE_Email_Input() ); - } - - - - /** - * @param $counter - * @param $email_address - * @param bool $assert_success - */ - public function validate_email_address( $counter, $email_address, $assert_success = true ) { - - if ( $assert_success ) { - $success = true; - $fail = false; - } else { - $success = false; - $fail = true; - } - try { - $this->_validator->validate( $email_address ); - $this->assertTrue( - $success, - sprintf( - 'Email addy #%1$s "%2$s" passed validation when it should have failed.', - $counter, - $email_address - ) - ); - } catch ( EE_Validation_Error $e ) { - $this->assertTrue( - $fail, - sprintf( - 'Email addy #%1$s "%2$s" failed validation when it should have passed.', - $counter, - $email_address - ) - ); - } - // i'm using = and NOT ==, so that I can bypass the following tests, - // these were only added for dev purposes, but fail too often to be useful - /*if ( $test_PHP_and_WP_validators = false ) { - if ( $assert_success ) { - $this->assertEquals( - $email_address, - filter_var( $email_address, FILTER_VALIDATE_EMAIL ), - sprintf( - 'PHP says email addy #%1$s "%2$s" failed validation when it should have passed.', - $counter, - $email_address - ) - ); - $this->assertEquals( - $email_address, - is_email( $email_address ), - sprintf( - 'WordPress says email addy #%1$s "%2$s" failed validation when it should have passed.', - $counter, - $email_address - ) - ); - } else { - $this->assertFalse( - filter_var( $email_address, FILTER_VALIDATE_EMAIL ), - sprintf( - 'PHP says email addy #%1$s "%2$s" passed validation when it should have failed.', - $counter, - $email_address - ) - ); - $this->assertFalse( - is_email( $email_address ), - sprintf( - 'WordPress says email addy #%1$s "%2$s" passed validation when it should have failed.', - $counter, - $email_address - ) - ); - } - }*/ - - } - - - - public function test_validate__pass_basic() { - EE_Registry::instance()->CFG->registration->email_validation_level = 'basic'; - // these should pass ALL validations - $good_addys = array( - 'bogus@eventespresso.com', - 'developers@eventespresso.museum', - 'üñîçøðé@example.com', // (Unicode characters in local part) - 'äöüÄÖÜß@eventespresso.com', // lötsä umläüts - '用户@例子.广告', // ( Chinese, Unicode ) - 'उपयोगकर्ता@उदाहरण.कॉम', // ( Hindi, Unicode ) - 'юзер@екзампл.ком', // ( Ukrainian, Unicode ) - 'θσερ@εχαμπλε.ψομ', // ( Greek, Unicode ) - 'Dörte@Sörensen.example.com', // ( German, Unicode ) - // short domain - 'developers@e.com', - 'developers@eventespresso.c', - // from https://en.wikipedia.org/wiki/Email_address#Examples - 'niceandsimple@example.com', - 'very.common@example.com', - 'a.little.lengthy.but.fine@dept.example.com', - 'disposable.style.email.with+symbol@example.com', - "!#$%&'*+-/=?^_`{}|~@example.org", - // the following, despite being valid, do NOT pass our validation - //'user@[IPv6:2001:db8:1ff::a0b:dbd0]', - '"much.more unusual"@example.com', - '"very.unusual.@.unusual.com"@example.com', - '"very.(),:;<>[]\".VERY.\"very@\ \"very\".unusual"@strange.example.com', - 'postbox@com', - 'admin@mailserver1', // local domain name with no TLD - '"()<>[]:,;@\\"!#$%&\'*+-/=?^_`{}| ~.a"@example.org', - '" "@example.org', // (space between the quotes) - // the following, despite being INVALID, pass validation when they should NOT - // haxxor - '@eventespresso.com', - ); - // turn off DNS checks - foreach ( $good_addys as $count => $good_addy ) { - $this->validate_email_address( $count, $good_addy ); - } - } - - - - public function test_validate__fail_basic(){ - EE_Registry::instance()->CFG->registration->email_validation_level = 'basic'; - $bad_addys = array( - // double dots - 'develop..ers@eventespresso.com', - 'developers@event..espresso.com', - // no local - '@eventespresso.com', - // no domain - 'developers@', - ); - foreach ( $bad_addys as $count => $bad_addy ) { - $this->validate_email_address( $count, $bad_addy, false ); - } - } - - - - public function test_validate__pass_wp_default() { - EE_Registry::instance()->CFG->registration->email_validation_level = 'wp_default'; - // these should pass ALL validations - $good_addys = array( - 'bogus@eventespresso.com', - 'developers@eventespresso.museum', - // short domain - 'developers@e.com', - 'developers@eventespresso.c', - // from https://en.wikipedia.org/wiki/Email_address#Examples - 'niceandsimple@example.com', - 'very.common@example.com', - 'a.little.lengthy.but.fine@dept.example.com', - 'disposable.style.email.with+symbol@example.com', - "!#$%&'*+-/=?^_`{}|~@example.org", - // the following, despite being valid, do NOT pass WordPress is_email() validation - //'üñîçøðé@example.com', // (Unicode characters in local part) - //'äöüÄÖÜß@eventespresso.com', // lötsä umläüts - //'用户@例子.广告', // ( Chinese, Unicode ) - //'उपयोगकर्ता@उदाहरण.कॉम', // ( Hindi, Unicode ) - //'юзер@екзампл.ком', // ( Ukrainian, Unicode ) - //'θσερ@εχαμπλε.ψομ', // ( Greek, Unicode ) - //'Dörte@Sörensen.example.com', // ( German, Unicode ) - //'user@[IPv6:2001:db8:1ff::a0b:dbd0]', - //'"much.more unusual"@example.com', - //'"very.unusual.@.unusual.com"@example.com', - //'"very.(),:;<>[]\".VERY.\"very@\ \"very\".unusual"@strange.example.com', - //'postbox@com', - //'admin@mailserver1', // local domain name with no TLD - //'"()<>[]:,;@\\"!#$%&\'*+-/=?^_`{}| ~.a"@example.org', - //'" "@example.org', // (space between the quotes) - ); - // turn off DNS checks - foreach ( $good_addys as $count => $good_addy ) { - $this->validate_email_address( $count, $good_addy ); - } - } - - - - public function test_validate__fail_wp_default() { - EE_Registry::instance()->CFG->registration->email_validation_level = 'wp_default'; - $bad_addys = array( - // double dots - 'develop..ers@eventespresso.com', - 'developers@event..espresso.com', - // haxxor - '@eventespresso.com', - // no local - '@eventespresso.com', - // no domain - 'developers@', - // valid but international - 'üñîçøðé@example.com', // (Unicode characters in local part) - 'äöüÄÖÜß@eventespresso.com', // lötsä umläüts - '用户@例子.广告', // ( Chinese, Unicode ) - 'उपयोगकर्ता@उदाहरण.कॉम', // ( Hindi, Unicode ) - 'юзер@екзампл.ком', // ( Ukrainian, Unicode ) - 'θσερ@εχαμπλε.ψομ', // ( Greek, Unicode ) - 'Dörte@Sörensen.example.com', // ( German, Unicode ) - ); - foreach ( $bad_addys as $count => $bad_addy ) { - $this->validate_email_address( $count, $bad_addy, false ); - } - } - - - - public function test_validate__pass_i18n() { - EE_Registry::instance()->CFG->registration->email_validation_level = 'i18n'; - // these should pass ALL validations - $good_addys = array( - 'bogus@eventespresso.com', - 'developers@eventespresso.museum', - 'üñîçøðé@example.com', // (Unicode characters in local part) - 'äöüÄÖÜß@eventespresso.com', // lötsä umläüts - '用户@例子.广告', // ( Chinese, Unicode ) - 'उपयोगकर्ता@उदाहरण.कॉम', // ( Hindi, Unicode ) - 'юзер@екзампл.ком', // ( Ukrainian, Unicode ) - 'θσερ@εχαμπλε.ψομ', // ( Greek, Unicode ) - 'Dörte@Sörensen.example.com', // ( German, Unicode ) - // short domain - 'developers@e.com', - // from https://en.wikipedia.org/wiki/Email_address#Examples - 'niceandsimple@example.com', - 'very.common@example.com', - 'a.little.lengthy.but.fine@dept.example.com', - 'disposable.style.email.with+symbol@example.com', - "!#$%&'*+-/=?^_`{}|~@example.org", - // the following, despite being valid, do NOT pass our validation - //'user@[IPv6:2001:db8:1ff::a0b:dbd0]', - //'"much.more unusual"@example.com', - //'"very.unusual.@.unusual.com"@example.com', - //'"very.(),:;<>[]\".VERY.\"very@\ \"very\".unusual"@strange.example.com', - //'postbox@com', - //'admin@mailserver1', // local domain name with no TLD - //'"()<>[]:,;@\\"!#$%&\'*+-/=?^_`{}| ~.a"@example.org', - //'" "@example.org', // (space between the quotes) - ); - // turn off DNS checks - foreach ( $good_addys as $count => $good_addy ) { - $this->validate_email_address( $count, $good_addy ); - } - } - - - - public function test_validate__fail_i18n() { - EE_Registry::instance()->CFG->registration->email_validation_level = 'i18n'; - $bad_addys = array( - // double dots - 'develop..ers@eventespresso.com', - 'developers@event..espresso.com', - // haxxor - '@eventespresso.com', - // domain too short - 'developers@eventespresso.c', - // no local - '@eventespresso.com', - // no domain - 'developers@', - ); - foreach ( $bad_addys as $count => $bad_addy ) { - $this->validate_email_address( $count, $bad_addy, false ); - } - } - - - - public function test_DNS_and_MX_record_check_fail(){ - EE_Registry::instance()->CFG->registration->email_validation_level = 'i18n_dns'; - $bad_addys = array( - // no MX records (bogus addresses) - 'valid-but-not-real@siiiiiiiiiiiiiiite.com', - 'developers@eventespresso.museum', - '用户@例子.广告', // ( Chinese, Unicode ) - 'उपयोगकर्ता@उदाहरण.कॉम', // ( Hindi, Unicode ) - 'юзер@екзампл.ком', // ( Ukrainian, Unicode ) - 'θσερ@εχαμπλε.ψομ', // ( Greek, Unicode ) - 'Dörte@Sörensen.staaaaaaaandooooooooort.com', // ( German, Unicode ) - ); - foreach ( $bad_addys as $count => $bad_addy ) { - $this->validate_email_address( $count, $bad_addy, false ); - } - } - - -} -// End of file tests/testcases/core/libraries/form_sections/strategies/validation/EE_Email_Validation_Strategy_Test.php diff --git a/tests/testcases/core/libraries/form_sections/strategies/validation/EE_Max_Length_Validation_Strategy_Test.php b/tests/testcases/core/libraries/form_sections/strategies/validation/EE_Max_Length_Validation_Strategy_Test.php deleted file mode 100644 index eb1995d7261..00000000000 --- a/tests/testcases/core/libraries/form_sections/strategies/validation/EE_Max_Length_Validation_Strategy_Test.php +++ /dev/null @@ -1,81 +0,0 @@ -_validator = new EE_Max_Length_Validation_Strategy( 'oups', 5 ); - $input = new EE_Text_Input(); - //finalize its construction, but we don't actually need the input anyways - $this->_validator->_construct_finalize( $input ); - } - /** - * tests that it can be left blank and pass validation (because the required validation - * strategy is what should fail here, if it's added as a validation strategy) - */ - public function test_validate__blank_but_not_required() { - try{ - $this->_validator->validate( '' ); - $this->assertTrue(true); - }catch(EE_Validation_Error $e ){ - $this->assertFalse( true, 'The empty string is shorter than 5 so it should be ok' ); - } - } - - /** - * tests that validation passes with LESS than the maximum characters - */ - public function test_validate__pass() { - try{ - $this->_validator->validate( '1234' ); - $this->assertTrue(true); - }catch(EE_Validation_Error $e ){ - $this->assertFalse( true, '1234 has less than 5 characters and so should be ok' ); - } - } - - /** - * tests validation passes with the maximum number of characters - */ - public function test_validate__pass_but_barely() { - try{ - $this->_validator->validate( '12345' ); - $this->assertTrue(true); - }catch(EE_Validation_Error $e ){ - $this->assertFalse( true, '12345 has 5 characters and so should be ok' ); - } - } - - /** - * tests that validation fails when there are FEWER than the maximum number of characters - */ - public function test_validate__fail() { - try{ - $this->_validator->validate( '123456' ); - $this->assertFalse( true, '123456 has too MANY character' ); - }catch(EE_Validation_Error $e ){ - $this->assertTrue( true ); - } - } - - - -} - -// End of file EE_Max_Length_Validation_Strategy_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/form_sections/strategies/validation/EE_Min_Length_Validation_Strategy_Test.php b/tests/testcases/core/libraries/form_sections/strategies/validation/EE_Min_Length_Validation_Strategy_Test.php deleted file mode 100644 index 1f50a732699..00000000000 --- a/tests/testcases/core/libraries/form_sections/strategies/validation/EE_Min_Length_Validation_Strategy_Test.php +++ /dev/null @@ -1,81 +0,0 @@ -_validator = new EE_Min_Length_Validation_Strategy( 'oups', 5 ); - $input = new EE_Text_Input(); - //finalize its construction, but we don't actually need the input anyways - $this->_validator->_construct_finalize( $input ); - } - /** - * tests that it can be left blank and pass validation (because the required validation - * strategy is what should fail here, if it's added as a validation strategy) - */ - public function test_validate__blank_but_not_required() { - try{ - $this->_validator->validate( '' ); - $this->assertTrue(true); - }catch(EE_Validation_Error $e ){ - $this->assertFalse( true, 'Even though the empty string is shorter than the min length, that indicates no response was given. And that should be checked by the REQUIRED validation' ); - } - } - - /** - * tests that validation passes with MORE than th eminimum characters - */ - public function test_validate__pass() { - try{ - $this->_validator->validate( '123456' ); - $this->assertTrue(true); - }catch(EE_Validation_Error $e ){ - $this->assertFalse( true, '123456 has more than 5 characters and so should be ok' ); - } - } - - /** - * tests validation passes with the minimum number of characters - */ - public function test_validate__pass_but_barely() { - try{ - $this->_validator->validate( '12345' ); - $this->assertTrue(true); - }catch(EE_Validation_Error $e ){ - $this->assertFalse( true, '12345 has 5 characters and so should be ok' ); - } - } - - /** - * tests that validation fails when there are FEWER than the minimum number of characters - */ - public function test_validate__fail() { - try{ - $this->_validator->validate( '123' ); - $this->assertFalse( true, '123 has too FEW character' ); - }catch(EE_Validation_Error $e ){ - $this->assertTrue( true ); - } - } - - - -} - -// End of file EE_Min_Length_Validation_Strategy_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/form_sections/strategies/validation/EE_Model_Matching_Query_Validation_Strategy_Test.php b/tests/testcases/core/libraries/form_sections/strategies/validation/EE_Model_Matching_Query_Validation_Strategy_Test.php deleted file mode 100644 index a1cee2e3de7..00000000000 --- a/tests/testcases/core/libraries/form_sections/strategies/validation/EE_Model_Matching_Query_Validation_Strategy_Test.php +++ /dev/null @@ -1,51 +0,0 @@ - array( 'LIKE', '%bar' ) - ) - ) - ); - $ev = $this->new_model_obj_with_dependencies( 'Event', array( 'EVT_name' => 'bobit' ) ); - try{ - $validator->validate( $ev->ID() + 1 ); - $this->fail( 'this one doesn\'t match because there is no event with this ID'); - }catch( EE_Validation_Error $e ) {} - try{ - $this->assertfalse( $validator->validate( $ev->ID() ) ); - $this->fail("this one doesn't match because the validator only looks for events with EVT_name like '%bar'" ); - }catch( EE_Validation_Error $e ) {} - - $ev->set( 'EVT_name', 'foobar' ); - $ev->save(); - //this one is valid because the name matches the validator's criteria and - //and the id exists - $validator->validate( $ev->ID() ); - } - - public function test_valid__treating_input_as_other_field() { - $validator = new EE_Model_Matching_Query_Validation_Strategy( - '', - 'Event', - array(), - 'EVT_name' - ); - $ev = $this->new_model_obj_with_dependencies( 'Event', array( 'EVT_name' => 'bobit' ) ); - try{ - $validator->validate( 'non-existent-event-name' ); - $this->fail( 'There is no event with this name so it shouldnt pass validation'); - } catch ( EE_Validation_Error $ex) {} - $validator->validate('bobit'); - } -} \ No newline at end of file diff --git a/tests/testcases/core/libraries/form_sections/strategies/validation/EE_Plaintext_Validation_Strategy_Test.php b/tests/testcases/core/libraries/form_sections/strategies/validation/EE_Plaintext_Validation_Strategy_Test.php deleted file mode 100644 index 2eb7dedfdbd..00000000000 --- a/tests/testcases/core/libraries/form_sections/strategies/validation/EE_Plaintext_Validation_Strategy_Test.php +++ /dev/null @@ -1,43 +0,0 @@ -_validator = new EE_Plaintext_Validation_Strategy(); - $input = new EE_Text_Input(); - //finalize its construction, but we don't actually need the input anyways - $this->_validator->_construct_finalize( $input ); - } - function test_validate__fail(){ - try{ - $this->_validator->validate( ' ' ); - $this->assertTrue( false ); - }catch( EE_Validation_Error $e ) { - $this->assertTrue( true ); - } - } - - function test_validate__pass(){ - $this->_validator->validate( 'just some text; no html anywhere' ); - } -} - -// End of file EE_Plaintext_Validation_Strategy_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/form_sections/strategies/validation/EE_Text_Length_Validation_Strategy_Test.php b/tests/testcases/core/libraries/form_sections/strategies/validation/EE_Text_Length_Validation_Strategy_Test.php deleted file mode 100644 index 9b8b255a44c..00000000000 --- a/tests/testcases/core/libraries/form_sections/strategies/validation/EE_Text_Length_Validation_Strategy_Test.php +++ /dev/null @@ -1,73 +0,0 @@ -_validator = new EE_Text_Validation_Strategy( 'oups', '~Darth ([\w]*)~' ); - $input = new EE_Text_Input(); - //finalize its construction, but we don't actually need the input anyways - $this->_validator->_construct_finalize( $input ); - } - /** - * tests that it can be left blank and pass validation (because the required validation - * strategy is what should fail here, if it's added as a validation strategy) - */ - public function test_validate__blank_but_not_required() { - try{ - $this->_validator->validate( '' ); - $this->assertTrue(true); - }catch(EE_Validation_Error $e ){ - $this->assertFalse( true, 'This isnt the requried validation. Blank string is ok' ); - } - } - - /** - * tests that validation passes with LESS than the maximum characters - */ - public function test_validate__pass() { - try{ - $this->_validator->validate( 'Darth Vader' ); - $this->assertTrue(true); - }catch(EE_Validation_Error $e ){ - $this->assertFalse( true, 'This should have matched the regex' ); - } - } - - - /** - * tests that validation fails when there are FEWER than the maximum number of characters - */ - public function test_validate__fail() { - try{ - $this->_validator->validate( 'Han Solo' ); - $this->assertFalse( true, '"Han Solo" should not mathc regex' ); - }catch(EE_Validation_Error $e ){ - $this->assertTrue( true ); - } - } - - public function test_regex_js(){ - $this->assertEquals( 'Darth ([\w]*)', $this->_validator->regex_js() ); - } - - -} - -// End of file EE_Text_Validation_Strategy_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/line_item_filters/EE_Line_Item_Filter_Processor_Test.php b/tests/testcases/core/libraries/line_item_filters/EE_Line_Item_Filter_Processor_Test.php deleted file mode 100644 index 11a95fe2d86..00000000000 --- a/tests/testcases/core/libraries/line_item_filters/EE_Line_Item_Filter_Processor_Test.php +++ /dev/null @@ -1,44 +0,0 @@ -new_typical_transaction( array( 'ticket_types' => 2 ) ); - $original_total = $txn->total(); - //in order for us to do a good test, let's verify - $this->assertNotEquals( 0, $original_total ); - $this->assertEquals( 2, count( $txn->registrations() ) ); - //ok now use the processor with some kind of filter - $collection = new EE_Line_Item_Filter_Collection(); - $collection->add( new EE_Single_Registration_Line_Item_Filter( $txn->primary_registration() ) ); - $processor = new EE_Line_Item_Filter_Processor( $collection, $txn->total_line_item() ); - $filtered_line_item_tree = $processor->process(); - //doesn't matter which filter so long as it just changes the grand total line item's total is all - $this->assertNotEquals( $txn->total_line_item()->total(), $filtered_line_item_tree->total() ); - //and now verify the transaction wasn't changed in this process - $this->assertEquals( $original_total, $txn->total() ); - - } -} - -// End of file EE_Line_Item_Filter_Processor_Test.php -// Location: /tests/testcases/core/libraries/line_item_filters/EE_Line_Item_Filter_Processor_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/line_item_filters/EE_Non_Zero_Line_Item_Filter_Test.php b/tests/testcases/core/libraries/line_item_filters/EE_Non_Zero_Line_Item_Filter_Test.php deleted file mode 100644 index 539f6d10801..00000000000 --- a/tests/testcases/core/libraries/line_item_filters/EE_Non_Zero_Line_Item_Filter_Test.php +++ /dev/null @@ -1,151 +0,0 @@ - 'subtotal', - 'LIN_code' => 'subtotal', - 'LIN_type' => EEM_Line_Item::type_sub_total, - )); - //and four children: - //a ticket with a quantity of 1 - $tktli1 = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'tktli1', - 'LIN_code' => 'tktli1', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_unit_price' => 10, - 'LIN_quantity' => 1, - 'OBJ_type' => 'Ticket' - )); - $subtotal->add_child_line_item( $tktli1 ); - //a ticket with a quantity of 0 - $tktli2 = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'tktli2', - 'LIN_code' => 'tktli2', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_unit_price' => 10, - 'LIN_quantity' => 0, - 'OBJ_type' => 'Ticket' - )); - $subtotal->add_child_line_item( $tktli2 ); - //a non-ticket with a quantity of 1 - $non_tkt_li = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'non_tkt', - 'LIN_code' => 'non_tkt', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_unit_price' => 10, - 'LIN_quantity' => 1, - 'OBJ_type' => null - )); - $subtotal->add_child_line_item( $non_tkt_li ); - //and a discount which erroneously has a quantity of 0 - $discount = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'discount', - 'LIN_code' => 'discount', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_unit_price' => 0, - 'LIN_percent' => 25, - 'LIN_quantity' => 0, - 'OBJ_type' => null - )); - $subtotal->add_child_line_item( $discount ); - //when filtered, only the ticket with a quantity of 1 should be removed - $filter = new EE_Non_Zero_Line_Item_Filter(); - $filter->process( $subtotal ); - $filtered_children = $subtotal->children(); - $this->assertContains( $tktli1, $filtered_children ); - $this->assertNotContains( $tktli2, $filtered_children ); - $this->assertContains( $non_tkt_li, $filtered_children ); - $this->assertContains( $discount, $filtered_children ); - } - /** - */ - function test_filter__removed_subtotals_with_no_ticket_children() { - //verify that normal subtotals stay, but subtotals with no ticket children get removed - //so create a total - $total = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'total', - 'LIN_code' => 'total', - 'LIN_type' => EEM_Line_Item::type_total - )); - //and a subttoal WITH a ticket (but the subtotal itself was erroneously labelled as quantity 0) - $subtotal_with_tkt = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'subtotal-with-tkt', - 'LIN_code' => 'subttoal-with-tkt', - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'LIN_quantity' => 0, //we should be setting it to 1 from now on, but earlier code set it to 0 - )); - $total->add_child_line_item( $subtotal_with_tkt ); - $tkt1 = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'tkt1', - 'LIN_code' => 'tkt1', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'OBJ_type' => 'Ticket', - 'LIN_quantity' => 1 - )); - $subtotal_with_tkt->add_child_line_item( $tkt1 ); - - //and another subtotal with a ticket but quantity 0, and another non-ticket line item with quantity 1 - $subtotal_without_tkt = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'subtotal-without-tkt', - 'LIN_code' => 'subttoal-without-tkt', - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'LIN_quantity' => 0, //we should be setting it to 1 from now on, but earlier code set it to 0 - )); - $total->add_child_line_item( $subtotal_without_tkt ); - $tkt2 = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'tkt2', - 'LIN_code' => 'tkt2', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'OBJ_type' => 'Ticket', - 'LIN_quantity' => 0,//IMPORTANT! - )); - $subtotal_without_tkt->add_child_line_item( $tkt2 ); - $non_tkt_li = EE_Line_Item::new_instance( - array( - 'LIN_name' => 'non_tkt_li', - 'LIN_code' => 'non_tkt_li', - 'LIN_type' => EEM_Line_Item::type_line_item, - 'OBJ_type' => null, - 'LIN_quantity' => 1, - )); - $subtotal_without_tkt->add_child_line_item( $non_tkt_li ); - - //only the subtotal without a ticket should get filtered out - $filter = new EE_Non_Zero_Line_Item_Filter(); - $filter->process( $total ); - $totals_children = $total->children(); - $this->assertContains( $subtotal_with_tkt, $totals_children ); - $this->assertNotContains( $subtotal_without_tkt, $totals_children ); - } -} - -// End of file EE_Non_Zero_Line_Item_Filter_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/line_item_filters/EE_Specific_Registrations_Line_Item_Filter_Test.php b/tests/testcases/core/libraries/line_item_filters/EE_Specific_Registrations_Line_Item_Filter_Test.php deleted file mode 100644 index 6dfaa90ed44..00000000000 --- a/tests/testcases/core/libraries/line_item_filters/EE_Specific_Registrations_Line_Item_Filter_Test.php +++ /dev/null @@ -1,446 +0,0 @@ - EEM_Line_Item::type_total, - 'LIN_name' => 'Total', - )); - $pretax_total = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'LIN_code' => 'pretax', - 'LIN_name' => 'pretax', - 'LIN_order' => 1, - )); - $grand_total->add_child_line_item( $pretax_total ); - - $tax_total = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_tax_sub_total, - 'LIN_code' => 'tax-total', - 'LIN_name' => 'tax-total', - 'LIN_order' => 1000 - )); - $grand_total->add_child_line_item( $tax_total ); - $event_subtotal = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'LIN_code' => 'event1', - 'LIN_name' => 'event1', - ) ); - $pretax_total->add_child_line_item( $event_subtotal ); - - $ticket_quantities = array( - 1 => array( - 'included' => 2, - 'not' => 3 - ) - ); - $ticket_li = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_code' => 'ticket1', - 'LIN_name' => 'ticket1', - 'OBJ_ID' => 1, - 'OBJ_type' => 'Ticket', - 'LIN_unit_price' => 10, - 'LIN_quantity' => 5 - )); - $event_subtotal->add_child_line_item( $ticket_li ); - $regs_to_include = $this->_create_regs( $ticket_quantities, $grand_total); - //ok now let's use the filter - $filter = new EE_Specific_Registrations_Line_Item_Filter( $regs_to_include ); - $filtered_total = $filter->process( $grand_total ); - //the filter doesn't recalculate totals, and it edits the inputted tree; - //hat's ok, the processor does both of those. But we need to manually do it here - $this->assertEquals( $grand_total, $filtered_total ); - $grand_total->recalculate_total_including_taxes(); - $this->assertEquals( 2, $ticket_li->quantity() ); - $this->assertEquals( 10, $ticket_li->unit_price() ); - $this->assertEquals( 20, $ticket_li->total() ); - } - - function test_process__1_taxless_ticket_and_percent_discount() { - $grand_total = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_total, - 'LIN_name' => 'Total', - )); - $pretax_total = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'LIN_code' => 'pretax', - 'LIN_name' => 'pretax', - 'LIN_order' => 1, - )); - $grand_total->add_child_line_item( $pretax_total ); - - $tax_total = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_tax_sub_total, - 'LIN_code' => 'tax-total', - 'LIN_name' => 'tax-total', - 'LIN_order' => 1000 - )); - $grand_total->add_child_line_item( $tax_total ); - $event_subtotal = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'LIN_code' => 'event1', - 'LIN_name' => 'event1', - ) ); - $pretax_total->add_child_line_item( $event_subtotal ); - - $ticket_quantities = array( - 1 => array( - 'included' => 4, - 'not' => 6 - ) - ); - $ticket_li = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_code' => 'ticket1', - 'LIN_name' => 'ticket1', - 'OBJ_ID' => 1, - 'OBJ_type' => 'Ticket', - 'LIN_unit_price' => 10, - 'LIN_quantity' => 10, - 'LIN_total' => 100, - )); - $event_subtotal->add_child_line_item( $ticket_li ); - - $percent_discount_li = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_code' => 'discount1', - 'LIN_name' => 'discount1', - 'LIN_unit_price' => 0, - 'LIN_percent' => -25, - 'LIN_total' => -25, - 'LIN_quantity' => 1 - )); - $event_subtotal->add_child_line_item( $percent_discount_li ); - //also need to make registrations - $regs_to_include = $this->_create_regs( $ticket_quantities, $grand_total ); - //ok now let's use the filter - $filter = new EE_Specific_Registrations_Line_Item_Filter( $regs_to_include ); - $filtered_total = $filter->process( $grand_total ); - //the filter doesn't recalculate totals, and it edits the inputted tree; - //hat's ok, the processor does both of those. But we need to manually do it here - $this->assertEquals( $grand_total, $filtered_total ); - $grand_total->recalculate_total_including_taxes(); - $this->assertEquals( 4, $ticket_li->quantity() ); - $this->assertEquals( 10, $ticket_li->unit_price() ); - $this->assertEquals( 40, $ticket_li->total() ); - //and verify the percent line item's total has changed, but not its percent - $this->assertEquals( -25, $percent_discount_li->percent() ); - $this->assertEquals( -10, $percent_discount_li->total() ); - } - - - function test_process__1_taxless_ticket_with_modifier_and_fixed_discount() { - $grand_total = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_total, - 'LIN_name' => 'Total', - )); - $pretax_total = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'LIN_code' => 'pretax', - 'LIN_name' => 'pretax', - 'LIN_order' => 1, - )); - $grand_total->add_child_line_item( $pretax_total ); - - $tax_total = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_tax_sub_total, - 'LIN_code' => 'tax-total', - 'LIN_name' => 'tax-total', - 'LIN_order' => 1000 - )); - $grand_total->add_child_line_item( $tax_total ); - $event_subtotal = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'LIN_code' => 'event1', - 'LIN_name' => 'event1', - ) ); - $pretax_total->add_child_line_item( $event_subtotal ); - - $ticket_quantities = array( - 1 => array( - 'included' => 5, - 'not' => 5 - ) - ); - $ticket_li = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_code' => 'ticket1', - 'LIN_name' => 'ticket1', - 'OBJ_ID' => 1, - 'OBJ_type' => 'Ticket', - 'LIN_unit_price' => 10, - 'LIN_quantity' => 10, - 'LIN_total' => 100, - )); - $event_subtotal->add_child_line_item( $ticket_li ); - - $base_price_li = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_sub_line_item, - 'LIN_code' => 'price1', - 'LIN_name' => 'price1', - 'OBJ_ID' => 1, - 'OBJ_type' => 'Price', - 'LIN_unit_price' => 9, - 'LIN_quantity' => 10, - 'LIN_total' => 90, - )); - $ticket_li->add_child_line_item( $base_price_li ); - - $modifier_li = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_sub_line_item, - 'LIN_code' => 'price2', - 'LIN_name' => 'price2', - 'OBJ_ID' => 2, - 'OBJ_type' => 'Price', - 'LIN_unit_price' => 1, - 'LIN_quantity' => 10, - 'LIN_total' => 10, - )); - $ticket_li->add_child_line_item( $modifier_li ); - - $percent_discount_li = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_code' => 'discount1', - 'LIN_name' => 'discount1', - 'LIN_unit_price' => -50, - 'LIN_percent' => 0, - 'LIN_total' => -50, - 'LIN_quantity' => 1 - )); - $event_subtotal->add_child_line_item( $percent_discount_li ); - //also need to make registrations - $regs_to_include = $this->_create_regs( $ticket_quantities, $grand_total ); - //ok now let's use the filter - $filter = new EE_Specific_Registrations_Line_Item_Filter( $regs_to_include ); - $filtered_total = $filter->process( $grand_total ); - //the filter doesn't recalculate totals, and it edits the inputted tree; - //hat's ok, the processor does both of those. But we need to manually do it here - $this->assertEquals( $grand_total, $filtered_total ); - $grand_total->recalculate_total_including_taxes(); - $this->assertEquals( 5, $ticket_li->quantity() ); - $this->assertEquals( 10, $ticket_li->unit_price() ); - $this->assertEquals( 50, $ticket_li->total() ); - //and verify the percent line item's total has changed, but not its percent - $this->assertEquals( -25, $percent_discount_li->unit_price() ); - $this->assertEquals( -25, $percent_discount_li->total() ); - } - - -/** - * - */ -function test_process__2_events_some_taxed_with_discounts() { - $grand_total = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_total, - 'LIN_name' => 'Total', - )); - $pretax_total = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'LIN_code' => 'pretax', - 'LIN_name' => 'pretax', - 'LIN_order' => 1, - )); - $grand_total->add_child_line_item( $pretax_total ); - - $tax_total = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_tax_sub_total, - 'LIN_code' => 'tax-total', - 'LIN_name' => 'tax-total', - 'LIN_order' => 1000 - )); - $grand_total->add_child_line_item( $tax_total ); - - $a_tax = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_tax, - 'LIN_code' => 'tax', - 'LIN_name' => 'tax', - 'LIN_percent' => 10, - 'LIN_order' => 1000 - )); - $tax_total->add_child_line_item( $a_tax ); - - $event_A_subtotal = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'LIN_code' => 'eventA', - 'LIN_name' => 'eventA', - 'LIN_order' => 1, - ) ); - $pretax_total->add_child_line_item( $event_A_subtotal ); - - $event_B_subtotal = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_sub_total, - 'LIN_code' => 'eventB', - 'LIN_name' => 'eventB', - 'LIN_order' => 2, - ) ); - $pretax_total->add_child_line_item( $event_B_subtotal ); - $ticket_quantities = array( - 1 => array( - 'included' => 4, - 'not' => 6 - ), - 2 => array( - 'included' => 0, - 'not' => 2, - ), - 3 => array( - 'included' => 1, - 'not' => 0 - ) - ); - $ticket_1_li = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_code' => 'ticket1', - 'LIN_name' => 'ticket1', - 'OBJ_ID' => 1, - 'OBJ_type' => 'Ticket', - 'LIN_unit_price' => 10, - 'LIN_quantity' => $ticket_quantities[1]['included'] + $ticket_quantities[1]['not'], - 'LIN_total' => 100, - 'LIN_is_taxable' => false, - 'LIN_order' => 1, - )); - $event_A_subtotal->add_child_line_item( $ticket_1_li ); - - $ticket_2_li = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_code' => 'ticket2', - 'LIN_name' => 'ticket2', - 'OBJ_ID' => 2, - 'OBJ_type' => 'Ticket', - 'LIN_unit_price' => 50, - 'LIN_quantity' => $ticket_quantities[2]['included'] + $ticket_quantities[2]['not'], - 'LIN_total' => 50, - 'LIN_is_taxable' => true, - 'LIN_order' => 2, - )); - $event_A_subtotal->add_child_line_item( $ticket_2_li ); - - $percent_discount_li = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_code' => 'discount-percent', - 'LIN_name' => 'discount-percent', - 'LIN_unit_price' => 0, - 'LIN_percent' => -25, - 'LIN_total' => -50, - 'LIN_quantity' => 1, - 'LIN_order' => 3, - )); - $event_A_subtotal->add_child_line_item( $percent_discount_li ); - - $flat_discount_li = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_code' => 'discount-flat', - 'LIN_name' => 'discount-flat', - 'LIN_unit_price' => 0, - 'LIN_percent' => 0, - 'LIN_unit_price' => -10, - 'LIN_total' => -10, - 'LIN_quantity' => 1, - 'LIN_order' => 4, - )); - $event_A_subtotal->add_child_line_item( $flat_discount_li ); - - //and add something to event B - $ticket_3_li = EE_Line_Item::new_instance( array( - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_code' => 'ticket3', - 'LIN_name' => 'ticket3', - 'OBJ_ID' => 3, - 'OBJ_type' => 'Ticket', - 'LIN_unit_price' => 35, - 'LIN_quantity' => $ticket_quantities[3]['included'] + $ticket_quantities[3]['not'], - 'LIN_total' => 35, - 'LIN_is_taxable' => true, - )); - $event_B_subtotal->add_child_line_item( $ticket_3_li ); - - //also need to make registrations - $regs_to_include = $this->_create_regs( $ticket_quantities, $grand_total ); - - //ok now let's use the filter - $filter = new EE_Specific_Registrations_Line_Item_Filter( - $regs_to_include ); - $filtered_total = $filter->process( $grand_total ); -// echo "AFTER tree:"; -// EEH_Line_Item::visualize( $grand_total ); - //the filter doesn't recalculate totals, and it edits the inputted tree; - //hat's ok, the processor does both of those. But we need to manually do it here - $this->assertEquals( $grand_total, $filtered_total ); - $grand_total->recalculate_total_including_taxes(); - //check ticket 1 - $this->assertEquals( 4, $ticket_1_li->quantity() ); - $this->assertEquals( 10, $ticket_1_li->unit_price() ); - $this->assertEquals( 40, $ticket_1_li->total() ); - //check ticket 2 - $this->assertEquals( 0, $ticket_2_li->quantity() ); - $this->assertEquals( 50, $ticket_2_li->unit_price() ); - $this->assertEquals( 0, $ticket_2_li->total() ); - //and verify the percent line item's total has changed, but not its percent - $this->assertEquals( -25, $percent_discount_li->percent() ); - $this->assertEquals( -10, $percent_discount_li->total() ); - //flat discount is tricky. we only show the PART of the flat discount - //that applied to the tickets shown. To determine that, we see what - //percent of the original discount was of the original total, and then multiply - //the new total by that percent. - //the original total = ticket1's-total + ticket2's-total + percent-discount - // = 100 + 100 - 50 = 150 - //flat discount's original percent of total = flat-discount / original total - // = -10 / 150 = 0.0666666 - //new total = ticket1's-filtered-total + ticket2's-filtered-total + percent-discount-for-filtered-total - // = 40 + 0 - 10 = 30 - //new flat total = flat discount's original percent of total x new total - // = 0.0666666 x 30 = 1.9999999 - $this->assertEquals( 1, $flat_discount_li->quantity() ); - $this->assertEquals( -2, $flat_discount_li->unit_price() ); - $this->assertEquals( -2, $flat_discount_li->total() ); - //other event's ticket purchase - $this->assertEquals( 1, $ticket_3_li->quantity() ); - $this->assertEquals( 35, $ticket_3_li->unit_price() ); - $this->assertEquals( 35, $ticket_3_li->total() ); - } - - /** - * Creates a bunch of registrations and returns an array of all the "approved" ones - * @param array $ticket_quantities top-level-keys are ticket IDs, - * next-level keys are either 'included' or 'not'. - * @param EE_Line_Item $grand_total - * @return a flat array of all the registrations that were for 'included' - */ - protected function _create_regs( $ticket_quantities, $grand_total ) { - $txn = $this->new_model_obj_with_dependencies( 'Transaction' ); - $regs_to_include = array(); - foreach( $ticket_quantities as $ticket_id => $approved_or_not_counts ) { - foreach( $approved_or_not_counts as $key => $count ) { - for( $i = 0; $i < $count; $i++ ) { - $r = $this->new_model_obj_with_dependencies( 'Registration', array( 'TXN_ID' => $txn->ID(), 'TKT_ID' => $ticket_id ) ); - if( $key == 'included' ) { - $regs_to_include[] = $r; - } - } - } - } - $grand_total->save_this_and_descendants_to_txn( $txn->ID() ); - return $regs_to_include; - } - -} - -// End of file EE_Specific_Registrations_Line_Item_Filter_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/messages/EE_Message_Repository_Test.php b/tests/testcases/core/libraries/messages/EE_Message_Repository_Test.php deleted file mode 100644 index fb892cb7726..00000000000 --- a/tests/testcases/core/libraries/messages/EE_Message_Repository_Test.php +++ /dev/null @@ -1,191 +0,0 @@ -factory->message->create( array( 'nosave' => 1 ) ); - $test_repo = new EE_Message_Repository(); - $this->assertInstanceOf( 'EE_Message_Repository', $test_repo ); - - $test_repo->add( $message ); - - //verify the message was added - $this->assertEquals( 1, $test_repo->count() ); - $test_repo->rewind(); - $this->assertInstanceOf( 'EE_Message', $test_repo->current() ); - return $test_repo; - } - - - - /** - * @depends test_add - * @param EE_Message_Repository $test_repo - */ - function test_remove( EE_Message_Repository $test_repo ) { - //get the object to remove. - $message = $test_repo->current(); - - //let's persist this object for persist tests - $message->save(); - $msgid = $message->ID(); - //verify in db - $this->assertInstanceOf( 'EE_Message', EEM_Message::instance()->get_one_by_ID( $msgid ) ); - - //remove from repo only and verify removed and verify still in db. - $test_repo->remove( $message ); - $this->assertEquals( 0, $test_repo->count() ); - $this->assertInstanceOf( 'EE_Message', EEM_Message::instance()->get_one_by_ID( $msgid ) ); - - //add back to repo and then try persist remove - $test_repo->add( $message ); - $test_repo->delete(); - $this->assertEmpty( EEM_Message::instance()->get_one_by_ID( $msgid ) ); - } - - - /** - * @return EE_Message_Repository - */ - function test_saveAll() { - //create a bunch of message objects and add to repo. - $test_repo = new EE_Message_Repository(); - $generation_data = array( 'MSG_generation_data' => array( - 'REG_ID' => 12 - ), - 'preview' => true - ); - $messages = array(); - for( $i=0;$i<5;$i++) { - $message = $this->factory->message->create( array( 'nosave' => 1 ) ); - //verify not saved - $this->assertEquals( 0, $message->ID() ); - $messages[] = $message; - $test_repo->add( $message, $generation_data ); - } - - $saved = $test_repo->saveAll(); - $this->assertEquals( 5, $saved['updated'] ); - return $test_repo; - } - - - - - /** - * @depends test_saveAll - * @param EE_Message_Repository $test_repo - * @return EE_Message_Repository - */ - function test_getMessageByToken( EE_Message_Repository $test_repo ) { - //pop a message out of the repo to test with - $test_repo->rewind(); - $message = $test_repo->current(); - $this->assertEquals( $message, $test_repo->getMessageByToken( $message->MSG_token() ) ); - return $test_repo; - } - - - /** - * @depends test_getMessageByToken - * @param EE_Message_Repository $test_repo - * @return EE_Message_Repository - */ - function test_get_generation_data( EE_Message_Repository $test_repo ) { - $test_repo->rewind(); - $actual_generation_data = $test_repo->get_generation_data(); - $this->assertTrue( isset( $actual_generation_data['REG_ID'] ) ); - $this->assertEquals( 12, $actual_generation_data['REG_ID'] ); - return $test_repo; - } - - - /** - * @depends test_get_generation_data - * @param EE_Message_Repository $test_repo - */ - function test_is_preview( EE_Message_Repository $test_repo ) { - $test_repo->rewind(); - $this->assertTrue( $test_repo->is_preview() ); - } - - - - - function test__maybe_persist_generation_data() { - $test_repo = new EE_Message_Repository(); - $message = $this->factory->message->create(); - $actual_generation_data = array( 'MSG_generation_data' => array( - 'REG_ID' => 14 - ) ); - $test_repo->add( $message, $actual_generation_data ); - $test_repo->saveAll(); - $test_repo->rewind(); - $message = $test_repo->current(); - $actual_generation_data = $message->get_generation_data(); - $this->assertTrue( isset( $actual_generation_data['REG_ID'] ) ); - $this->assertEquals( 14, $actual_generation_data['REG_ID'] ); - } - - - - - - function test_count_by_priority_and_status() { - $test_repo = new EE_Message_Repository(); - //let's setup some message objects with a variety of priorities and statuses. - //high priority, idle (invoice is high priority hence it is used as a message type). - $messages_a = $this->factory->message->create_many( 3, array( 'STS_ID' => EEM_Message::status_idle, 'MSG_message_type' => 'invoice' ) ); - //medium priority, sent (the default message type has a priority of medium) - $messages_b = $this->factory->message->create_many( 2, array( 'STS_ID' => EEM_Message::status_sent ) ); - //medium priority, resend (the default message type has a priority of medium) - $messages_c = $this->factory->message->create_many( 2, array( 'STS_ID' => EEM_Message::status_resend ) ); - //low priority, resend - $messages_d = $this->factory->message->create_many( 4, array( 'STS_ID' => EEM_Message::status_resend ) ); - //need to manually force this priority because there are no message types currently that set low priority - foreach ( $messages_d as $message ) { - $message->set_priority( EEM_Message::priority_low ); - } - - $all_messages = array_merge( $messages_a, $messages_b, $messages_c, $messages_d ); - - //add to queue - foreach( $all_messages as $message ) { - $test_repo->add( $message ); - } - - //test high priority results - $this->assertEquals( 3, $test_repo->count_by_priority_and_status( EEM_Message::priority_high ) ); - $this->assertEquals( 0, $test_repo->count_by_priority_and_status( EEM_Message::priority_high, EEM_Message::status_incomplete ) ); - $this->assertEquals( 3, $test_repo->count_by_priority_and_status( EEM_Message::priority_high, array( EEM_Message::status_incomplete, EEM_Message::status_idle ) ) ); - - //test medium priority results - $this->assertEquals( 4, $test_repo->count_by_priority_and_status( EEM_Message::priority_medium ) ); - $this->assertEquals( 2, $test_repo->count_by_priority_and_status( EEM_Message::priority_medium, EEM_Message::status_resend ) ); - $this->assertEquals( 4, $test_repo->count_by_priority_and_status( EEM_Message::priority_medium, array( EEM_Message::status_incomplete, EEM_Message::status_resend, EEM_Message::status_sent ) ) ); - - //test low priority results - $this->assertEquals( 4, $test_repo->count_by_priority_and_status( EEM_Message::priority_low, EEM_Message::status_resend ) ); - } - - -} //end EE_Message_Repository_Test \ No newline at end of file diff --git a/tests/testcases/core/libraries/messages/EE_Message_Resource_Manager_Test.php b/tests/testcases/core/libraries/messages/EE_Message_Resource_Manager_Test.php deleted file mode 100644 index b090161549c..00000000000 --- a/tests/testcases/core/libraries/messages/EE_Message_Resource_Manager_Test.php +++ /dev/null @@ -1,423 +0,0 @@ -_message_resource_manager = EE_Registry::instance()->load_lib( 'Message_Resource_Manager' ); - $this->assertInstanceOf( 'EE_Message_Resource_Manager', $this->_message_resource_manager ); - //make sure message type and messenger that might be persisting inactive between tests are fixed. - $this->_message_resource_manager->ensure_message_type_is_active( 'invoice', 'html' ); - } - - - public function tearDown() { - $this->_message_resource_manager = null; - parent::tearDown(); - } - - - public function test_messenger_collection() { - $messenger_collection = $this->_message_resource_manager->messenger_collection(); - $this->assertInstanceOf( 'EE_Messenger_Collection', $messenger_collection ); - } - - - - public function test_active_messengers() { - $active_messengers = $this->_message_resource_manager->active_messengers(); - - //email messenger should be active by default so using that for the test. - $this->assertTrue( isset( $active_messengers['email'] ) ); - $this->assertInstanceOf( 'EE_Email_messenger', $active_messengers['email'] ); - } - - - - public function test_get_messenger() { - $messenger = $this->_message_resource_manager->get_messenger( 'email' ); - $this->assertInstanceOf( 'EE_Email_messenger', $messenger ); - } - - - - public function test_get_active_messenger() { - $messenger_that_is_active = $this->_message_resource_manager->get_active_messenger( 'email' ); - $inactive_messenger = $this->_message_resource_manager->get_active_messenger( 'dummy' ); - $this->assertInstanceOf( 'EE_Email_messenger', $messenger_that_is_active ); - $this->assertNotInstanceOf( 'EE_Email_messenger', $inactive_messenger ); - } - - - - public function test_installed_messengers() { - $installed_messengers = $this->_message_resource_manager->installed_messengers(); - $this->assertTrue( isset( $installed_messengers['email'] ) ); - $this->assertInstanceOf( 'EE_Email_messenger', $installed_messengers['email'] ); - } - - - - - public function test_valid_messenger() { - //test valid first. - $messenger = $this->_message_resource_manager->valid_messenger( 'email' ); - $this->assertInstanceOf( 'EE_Email_messenger', $messenger ); - - //test invalid - $this->setExpectedException( 'EE_Error' ); - $this->_message_resource_manager->valid_messenger( 'dummy' ); - } - - - - - public function test_message_type_collection() { - $message_type_collection = $this->_message_resource_manager->message_type_collection(); - $this->assertInstanceOf( 'EE_Message_Type_Collection', $message_type_collection ); - } - - - - - public function test_active_message_types() { - $active_message_types = $this->_message_resource_manager->active_message_types(); - $this->assertTrue( isset( $active_message_types['email']['settings']['email-message_types']['registration'] ) ); - } - - - - public function test_get_message_type() { - $message_type = $this->_message_resource_manager->get_message_type( 'invoice' ); - $this->assertInstanceOf( 'EE_Invoice_message_type', $message_type ); - } - - - - public function test_get_active_message_type_for_messenger() { - $active_message_type = $this->_message_resource_manager->get_active_message_type_for_messenger( 'email', 'registration' ); - $invalid_message_type = $this->_message_resource_manager->get_active_message_type_for_messenger( 'email', 'invoice' ); - $this->assertInstanceOf( 'EE_Registration_message_type', $active_message_type ); - $this->assertNull( $invalid_message_type ); - } - - - - - public function test_is_message_type_active_for_messenger() { - $active_message_type = $this->_message_resource_manager->is_message_type_active_for_messenger( 'email', 'registration' ); - $invalid_message_type = $this->_message_resource_manager->is_message_type_active_for_messenger( 'email', 'invoice' ); - $this->assertTrue( $active_message_type ); - $this->assertFalse( $invalid_message_type ); - } - - - - public function test_is_messenger_active() { - $this->assertTrue( $this->_message_resource_manager->is_messenger_active( 'email' ) ); - $this->assertFalse( $this->_message_resource_manager->is_messenger_active( 'dummy' ) ); - } - - - - public function test_get_message_type_settings_for_messenger() { - $message_type_settings = $this->_message_resource_manager->get_message_type_settings_for_messenger( 'email', 'registration' ); - //currently this will always be an empty array because no message type has settings, so this should always return an array. - $this->assertTrue( is_array( $message_type_settings ) ); - } - - - - - public function test_messenger_has_active_message_types() { - $this->assertTrue( $this->_message_resource_manager->messenger_has_active_message_types( 'email' ) ); - $this->assertFalse( $this->_message_resource_manager->messenger_has_active_message_types( 'pdf' ) ); - } - - - - - public function test_get_active_message_types_for_messenger() { - $active_message_types = $this->_message_resource_manager->get_active_message_types_for_messenger( 'email' ); - $this->assertTrue( isset( $active_message_types['registration'] ) ); - $this->assertInstanceOf( 'EE_Registration_message_type', $active_message_types['registration'] ); - } - - - - public function test_list_of_active_message_types() { - $active_message_type_list = $this->_message_resource_manager->list_of_active_message_types(); - $this->assertArrayContains( 'invoice', $active_message_type_list ); - } - - - - public function test_get_active_message_type_objects() { - $active_message_type_objects = $this->_message_resource_manager->get_active_message_type_objects(); - $this->assertTrue( isset( $active_message_type_objects['invoice'] ) ); - $this->assertInstanceOf( 'EE_Invoice_message_type', $active_message_type_objects['invoice'] ); - } - - - - - public function test_installed_message_types() { - $installed_message_types = $this->_message_resource_manager->installed_message_types(); - $this->assertTrue( isset( $installed_message_types['invoice'] ) ); - $this->assertInstanceOf( 'EE_Invoice_message_type', $installed_message_types['invoice'] ); - } - - - - public function test_valid_message_type() { - //test valid - $this->assertInstanceOf( 'EE_Registration_message_type', $this->_message_resource_manager->valid_message_type( 'registration' ) ); - - //test invalid throwing exception - $this->setExpectedException( 'EE_Error' ); - $this->_message_resource_manager->valid_message_type( 'dummy' ); - } - - - - public function test_valid_message_type_for_messenger() { - //test valid - $html_messenger = $this->_message_resource_manager->get_messenger( 'html' ); - $this->assertTrue( $this->_message_resource_manager->valid_message_type_for_messenger( $html_messenger, 'invoice' ) ); - - //test invalid throwing exception - $email_messenger = $this->_message_resource_manager->get_messenger( 'email' ); - $this->setExpectedException( 'EE_Error' ); - $this->_message_resource_manager->valid_message_type_for_messenger( $email_messenger, 'invoice' ); - } - - - - public function test_get_active_messengers_option() { - $active_messengers_option = $this->_message_resource_manager->get_active_messengers_option( true ); - - //this should be the same as what gets returned for the active_message_types property. - $this->assertEquals( - $active_messengers_option, - $this->_message_resource_manager->active_message_types() - ); - } - - - - public function test_update_active_messengers_option() { - $this->markTestIncomplete( - 'This test is incomplete because for now it is tested indirectly via other tests in this class.' - ); - } - - - - - public function test_get_has_activated_messengers_option() { - $has_activated = $this->_message_resource_manager->get_has_activated_messengers_option(true); - $this->assertTrue( isset( $has_activated['email'] ) ); - $this->assertArrayContains( 'registration', $has_activated['email'] ); - } - - - - public function test_update_has_activated_messengers_option() { - $has_activated = $this->_message_resource_manager->get_has_activated_messengers_option(); - $has_activated['email'][] = 'test_message_type'; - $this->assertTrue( $this->_message_resource_manager->update_has_activated_messengers_option( $has_activated ) ); - - $has_activated_persistent_check = $this->_message_resource_manager->get_has_activated_messengers_option( true ); - $this->assertTrue( isset( $has_activated_persistent_check['email'] ) ); - $this->assertArrayContains( 'test_message_type', $has_activated_persistent_check['email'] ); - } - - - - public function test_reset_active_messengers_and_message_types() { - $this->markTestIncomplete( - 'Not sure how to usefully perform this test just yet so this is just a marker.' - ); - } - - - /** - * tests to make sure forcing a messenger to be active works. - * - * Note this also indirectly tests the following methods in the MRM: - * - active_messengers - * - deactivate_messenger - * - update_active_messengers_option - * - is_messenger_active - * - * @since 4.9.0 - */ - public function test_ensure_messenger_is_active() { - //make sure html messenger is setup (should be by default) - $current_active_messengers = $this->_message_resource_manager->active_messengers(); - $this->assertTrue( isset( $current_active_messengers['html'] ), sprintf( 'The messenger %s should be active on fresh install, but it is not.', 'html' ) ); - - //let's deactivate the html messenger from active messengers and update the db - $this->_message_resource_manager->deactivate_messenger( 'html' ); - $this->_message_resource_manager->update_active_messengers_option(); - //verify active_messengers prop in MRM doesn't have html in it - $current_active_messengers = $this->_message_resource_manager->active_messengers(); - $this->assertFalse( isset( $current_active_messengers['html'] ) ); - - //verify its not active - $this->assertFalse( $this->_message_resource_manager->is_messenger_active( 'html' ) ); - - //now let's FORCE reactivation. - $response = $this->_message_resource_manager->ensure_messenger_is_active( 'html' ); - $this->assertTrue( $response ); - - //verify html messenger IS actually active now. - $current_active_messengers = $this->_message_resource_manager->active_messengers(); - $this->assertTrue( isset( $current_active_messengers['html'] ), 'The html messenger should have been forced to be active again but it is not.' ); - } - - - - public function test_ensure_messengers_are_active() { - $this->markTestIncomplete( - 'For now, this test is mostly covered by test_ensure_messenger_is_active.' - ); - } - - - /** - * This test also indirectly tests the following methods: - * - get_active_message_type_objects - * - deactivate_message_type - * - update_active_messengers_option - * - * - * @since 4.9.0 - */ - public function test_ensure_message_type_is_active() { - //get all active message types. - $current_active_message_types = $this->_message_resource_manager->get_active_message_type_objects(); - $this->assertTrue( isset( $current_active_message_types['invoice'] ) ); - - //deactivate the invoice message type and persist - $this->_message_resource_manager->deactivate_message_type( 'invoice' ); - $this->_message_resource_manager->update_active_messengers_option(); - - //verify message type isn't active anywhere internally on the class. - $list_of_active_message_types = $this->_message_resource_manager->list_of_active_message_types(); - $this->assertArrayDoesNotContain( 'invoice', $list_of_active_message_types ); - - //now let's force reactivation (for html messenger) - $response = $this->_message_resource_manager->ensure_message_type_is_active( 'invoice', 'html' ); - $this->assertTrue( $response ); - - //very invoice message type IS actually active now. - $current_active_message_types = $this->_message_resource_manager->get_active_message_type_objects(); - $this->assertTrue( isset( $current_active_message_types['invoice'] ) ); - } - - - - public function test_ensure_message_types_are_active() { - $this->markTestIncomplete( - 'This test is mostly covered via test_ensure_message_type_is_active' - ); - } - - - - public function test_activate_messenger() { - $this->markTestIncomplete( - 'This method is indirectly covered in the test_ensure_messenger_is_active' - ); - } - - - - public function test_add_settings_for_message_type() { - $this->markTestIncomplete( - 'There are currently no message types that have settings so not tested yet.' - ); - } - - - - public function test_add_settings_for_messenger() { - $this->markTestIncomplete( - 'There are currently no messengers that have settings so not tested yet.' - ); - } - - - - public function test_deactivate_messenger() { - $this->assertTrue( $this->_message_resource_manager->is_messenger_active( 'html' ) ); - $this->_message_resource_manager->deactivate_messenger( 'html' ); - $this->assertFalse( $this->_message_resource_manager->is_messenger_active( 'html' ) ); - } - - - - public function test_deactivate_message_type() { - $this->assertTrue( $this->_message_resource_manager->is_message_type_active_for_messenger( 'html', 'invoice' ) ); - $this->_message_resource_manager->deactivate_message_type( 'invoice' ); - $this->assertFalse( $this->_message_resource_manager->is_message_type_active_for_messenger( 'html', 'invoice' ) ); - } - - - - public function test_deactivate_message_type_for_messenger() { - $this->assertTrue( $this->_message_resource_manager->is_message_type_active_for_messenger( 'html', 'invoice' ) ); - $this->_message_resource_manager->deactivate_message_type_for_messenger( 'invoice', 'html' ); - $this->assertFalse( $this->_message_resource_manager->is_message_type_active_for_messenger( 'html', 'invoice' ) ); - } - - - - - public function test_is_generating_messenger_and_active() { - //get email messenger - $email_messenger = $this->_message_resource_manager->get_messenger( 'email' ); - //get registration message type - $registration_message_type = $this->_message_resource_manager->get_message_type( 'registration' ); - //get invoice message type - $invoice_message_type = $this->_message_resource_manager->get_message_type( 'invoice' ); - - $this->assertTrue( $this->_message_resource_manager->is_generating_messenger_and_active( $email_messenger, $registration_message_type ) ); - $this->assertFalse( $this->_message_resource_manager->is_generating_messenger_and_active( $email_messenger, $invoice_message_type ) ); - } - - - - function test_get_all_contexts() { - $contexts = $this->_message_resource_manager->get_all_contexts(); - - //expected four contexts. - $this->assertEquals( 4, count( $contexts ) ); - - //expecting an array with 'admin', 'attendee', and 'primary_attendee', and 'purchaser' in it. - $this->arrayHasKey( 'admin', $contexts ); - $this->arrayHasKey( 'attendee', $contexts ); - $this->arrayHasKey( 'primary_attendee', $contexts ); - $this->arrayHasKey( 'purchaser', $contexts ); - } - - -} //end EE_messages_Test class -// Location: tests/testcases/core/libraries/messages/EE_Message_Resource_Manager_Test.php diff --git a/tests/testcases/core/libraries/messages/EE_Message_Template_Group_Collection_Test.php b/tests/testcases/core/libraries/messages/EE_Message_Template_Group_Collection_Test.php deleted file mode 100644 index a092b20bdb8..00000000000 --- a/tests/testcases/core/libraries/messages/EE_Message_Template_Group_Collection_Test.php +++ /dev/null @@ -1,75 +0,0 @@ -get_one( - array( - array( - 'MTP_messenger' => 'email', - 'MTP_message_type' => 'registration', - ), - ) - ); - $this->assertInstanceOf('EE_Message_Template_Group', $message_template_group); - - $test_repo = new EE_Message_Template_Group_Collection(); - - $this->assertInstanceOf('EE_Message_Template_Group_Collection', $test_repo); - - //add mtpg to repo with dummy evtID used for later tests. - $test_repo->add($message_template_group, 22); - - //verify the message was added - $this->assertEquals(1, $test_repo->count()); - $test_repo->rewind(); - $this->assertInstanceOf('EE_Message_Template_Group', $test_repo->current()); - return $test_repo; - } - - - /** - * @depends test_add - * @param EE_Message_Template_Group_Collection $test_repo - * @return EE_Message_Template_Group_Collection - */ - public function test_get_by_ID(EE_Message_Template_Group_Collection $test_repo) - { - //get the object to remove. - $mtpg = $test_repo->current(); - - //verify that retrieving the object by ID works - $this->assertEquals($mtpg, $test_repo->get_by_ID($mtpg->ID())); - - return $test_repo; - } - - - /** - * @depends test_get_by_ID - * @param EE_Message_Template_Group_Collection $test_repo - */ - public function test_get_by_key(EE_Message_Template_Group_Collection $test_repo) - { - $key_should_exist = $test_repo->getKey('email', 'registration', array(22)); - $key_should_not_exist = $test_repo->getKey('email', 'registration', array(15)); - $this->assertNotInstanceOf('EE_Message_Template_Group', $test_repo->get_by_key($key_should_not_exist)); - $this->assertInstanceOf('EE_Message_Template_Group', $test_repo->get_by_key($key_should_exist)); - } - - -} diff --git a/tests/testcases/core/libraries/messages/EE_Message_To_Generate_Test.php b/tests/testcases/core/libraries/messages/EE_Message_To_Generate_Test.php deleted file mode 100644 index 5836a5c6a07..00000000000 --- a/tests/testcases/core/libraries/messages/EE_Message_To_Generate_Test.php +++ /dev/null @@ -1,56 +0,0 @@ -assertInstanceOf( 'EE_Registration_message_type', $mtg->message_type() ); - $this->assertInstanceOf( 'EE_Email_messenger', $mtg->messenger() ); - $this->assertEquals( array(), $mtg->data() ); - $this->assertEquals( 'admin', $mtg->context() ); - $this->assertTrue( $mtg->preview() ); - return $mtg; - } - - - - - /** - * @depends test_construct - * @param EE_Message_To_Generate $mtg - */ - function test_get_EE_Message( EE_Message_To_Generate $mtg ) { - /** @type EE_Message $msg */ - $msg = $mtg->get_EE_Message(); - $this->assertInstanceOf( 'EE_Message', $msg ); - $this->assertEquals( 'email', $msg->messenger() ); - $this->assertEquals( 'registration', $msg->message_type() ); - $this->assertEquals( 'admin', $msg->context() ); - $this->assertEquals( EEM_Message::status_incomplete, $msg->STS_ID() ); - - //this is also implicitly testing the _get_priority_for_message_type method because Registration message type - //and email messenger should result in EEM_Message::priority_medium. - $this->assertEquals( EEM_Message::priority_medium, $msg->priority() ); - } - -} //end EE_Message_To_Generate_Test class \ No newline at end of file diff --git a/tests/testcases/core/libraries/messages/EE_Messages_Data_Handler_Collection_Test.php b/tests/testcases/core/libraries/messages/EE_Messages_Data_Handler_Collection_Test.php deleted file mode 100644 index 94eb8d86c21..00000000000 --- a/tests/testcases/core/libraries/messages/EE_Messages_Data_Handler_Collection_Test.php +++ /dev/null @@ -1,84 +0,0 @@ -loadTestScenarios(); - //need to add some events for previewer to use... we'll just use the event scenarios - $this->scenarios->get_scenarios_by_type( 'event' ); - - $data_handler = new EE_Messages_Preview_incoming_data(); - $test_repo = new EE_Messages_Data_Handler_Collection(); - - $this->assertInstanceOf( 'EE_Messages_Data_Handler_Collection', $test_repo ); - - $test_repo->add( $data_handler, array() ); - - //verify the message was added - $this->assertEquals( 1, $test_repo->count() ); - $test_repo->rewind(); - $this->assertInstanceOf( 'EE_Messages_Preview_incoming_data', $test_repo->current() ); - return $test_repo; - } - - - - /** - * @depends test_add - * -*@param EE_Messages_Data_Handler_Collection $test_repo - * -*@return EE_Messages_Data_Handler_Collection - */ - function test_remove( EE_Messages_Data_Handler_Collection $test_repo ) { - //get the object to remove. - $data_handler = $test_repo->current(); - - //verify in db - $this->assertInstanceOf( 'EE_Transaction', $data_handler->txn ); - - //remove and verify removed. - $test_repo->remove( $data_handler ); - $this->assertEquals( 0, $test_repo->count() ); - - //add back to repo for next test. - $test_repo->add( $data_handler, array() ); - return $test_repo; - } - - - - - /** - * @depends test_remove - * -*@param EE_Messages_Data_Handler_Collection $test_repo - */ - function test_get_by_key( EE_Messages_Data_Handler_Collection $test_repo ) { - $key_should_exist = $test_repo->get_key( 'EE_Messages_Preview_incoming_data', array() ); - $key_should_not_exist = $test_repo->get_key( 'Some_Bogus_Class', array() ); - $this->assertNotInstanceOf( 'EE_Messages_Preview_incoming_data', $test_repo->get_by_key( $key_should_not_exist ) ); - $this->assertInstanceOf( 'EE_Messages_Preview_incoming_data', $test_repo->get_by_key( $key_should_exist ) ); - } - - -} //end EE_Messages_Data_Handler_Collection_Test diff --git a/tests/testcases/core/libraries/messages/EE_Messages_Generator_Test.php b/tests/testcases/core/libraries/messages/EE_Messages_Generator_Test.php deleted file mode 100644 index ee76a26a5a4..00000000000 --- a/tests/testcases/core/libraries/messages/EE_Messages_Generator_Test.php +++ /dev/null @@ -1,77 +0,0 @@ -assertInstanceOf('EE_Messages_Generator', $generator); - return $generator; - } - - - /** - * This test verifies that the generation queue only generates messages with the status of incomplete. - * - * @see https://events.codebasehq.com/projects/event-espresso/tickets/9787 - * @group 9787 - */ - function test_generate_only_incomplete_messages() - { - $message_processor = EE_Registry::instance()->load_lib('Messages_Processor'); - //make sure there is nothing in the queue - $this->assertFalse($message_processor->batch_generate_from_queue(array(), true)); - - //get an event (with relations via creating the ticket) in the db for the message preview - $this->factory->ticket_chained->create(); - - //get some ready to generate - $this->factory->message->create_many(5); - - /** @var EE_Messages_Queue $new_queue */ - $new_queue = $message_processor->batch_generate_from_queue(); - $this->assertInstanceOf('EE_Messages_Queue', $new_queue); - - //now let's grab the generated messages from this queue and send it in to the batch_generate_from_queue - $messages = array(); - $new_queue->get_message_repository()->rewind(); - while ($new_queue->get_message_repository()->valid()) { - $messages[] = $new_queue->get_message_repository()->current(); - $new_queue->get_message_repository()->next(); - } - - /** @var EE_Messages_Queue $newer_queue */ - $newer_queue = $message_processor->batch_generate_from_queue($messages); - $this->assertInstanceOf('EE_Messages_Queue', $newer_queue); - //there should be NO fails in the queue. - $this->assertEquals(0, $newer_queue->count_STS_in_queue(array(EEM_Message::status_failed))); - } - - -} //end EE_Messages_Generator_Test class -// Location: tests/testcases/core/libraries/messages/EE_Messages_Generator_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/messages/EE_Messages_Processor_Test.php b/tests/testcases/core/libraries/messages/EE_Messages_Processor_Test.php deleted file mode 100644 index 5303dbf37b2..00000000000 --- a/tests/testcases/core/libraries/messages/EE_Messages_Processor_Test.php +++ /dev/null @@ -1,388 +0,0 @@ -loadTestScenarios(); - //setup events etc for previewer to use - $this->scenarios->get_scenarios_by_type('event'); - } - - - /** - * This returns an array of components used in testing. - * An array with the following: - * - EE_messages object - * - EE_Messages_Processor object (clean) - * - EE_Message_To_Generate object. - * - * @return array - */ - protected function _test_components() - { - return array( - 'proc' => EE_Registry::instance()->load_lib('Messages_Processor'), - 'mtg' => new EE_Message_To_Generate( - 'email', - 'registration', - array(), - 'admin', - true - ), - ); - } - - - /** - * Tests constructing the processor object and retrieving a EE_Messages_Queue after construct. - * Passes along EE_Messages_Processor for other test. - * - * @return EE_Messages_Processor - */ - function test_construct_and_get_queue() - { - $message_proc = null; - try { - /** @type EE_Messages_Processor $message_proc */ - $message_proc = EE_Registry::instance()->load_lib('Messages_Processor'); - } catch (Exception $e) { - $this->fail(sprintf('Loading EE_Messages_Processor failed: %s', $e->getMessage())); - } - - //verify things loaded okay via the queue. - $this->assertInstanceOf('EE_Messages_Queue', $message_proc->get_queue()); - return $message_proc; - } - - - /** - * @depends test_construct_and_get_queue - * @param EE_Messages_Processor $message_proc - */ - function test_batch_generate_from_queue(EE_Messages_Processor $message_proc) - { - //first we know there is nothing in the db, so let's verify that returns false. (this also verifies the clear param) - $this->assertFalse($message_proc->batch_generate_from_queue(array(), true)); - - //now let's test getting some batch ready to generate. - $this->factory->message->create_many(5); - - $new_queue = $message_proc->batch_generate_from_queue(); - - $this->assertInstanceOf('EE_Messages_Queue', $new_queue); - //this will be 5 because there the messages the factory create set the preview data handler for the data used. - $this->assertEquals(5, $new_queue->get_message_repository()->count()); - } - - - /** - * Same as above test except only doing batch generation on specific messages - * - * @depends test_construct_and_get_queue - * @param EE_Messages_Processor $message_proc - */ - function test_batch_generate_from_queue_with_messages(EE_Messages_Processor $message_proc) - { - //make sure clear works - $this->assertFalse($message_proc->batch_generate_from_queue(array(), true)); - - //setup some messages for generation. - $messages_to_test = $this->factory->message->create_many(5); - - //now let's create 3 more that will NOT be used. - $this->factory->message->create_many(3); - - $new_queue = $message_proc->batch_generate_from_queue($messages_to_test); - - $this->assertInstanceOf('EE_Messages_Queue', $new_queue); - - //verify 5 got generated - $this->assertEquals(5, $new_queue->get_message_repository()->count()); - - //verify the original MIC Messages do not exist in the db anymore. - $messages_no_exist = EEM_Message::instance()->count(array( - array( - 'MSG_ID' => array('IN', array_keys($messages_to_test)), - ), - )); - - $this->assertEquals(0, $messages_no_exist); - } - - - /** - * @depends test_construct_and_get_queue - * @param EE_Messages_Processor $message_proc - */ - function test_batch_send_from_queue(EE_Messages_Processor $message_proc) - { - - //create messages ready to send. - $this->factory->message->create_many(5, array('STS_ID' => EEM_Message::status_idle)); - - $sent_queue = $message_proc->batch_send_from_queue(array(), true); - - $this->assertInstanceOf('EE_Messages_Queue', $sent_queue); - $this->assertEquals(5, $sent_queue->get_message_repository()->count()); - - //verify no errors - $this->assertEquals(0, - $sent_queue->count_STS_in_queue(EEM_Message::instance()->stati_indicating_failed_sending())); - - $this->assertEquals(5, $sent_queue->count_STS_in_queue(EEM_Message::status_sent)); - } - - - /** - * Same as previous test except tests with sending in messages. - * - * @depends test_construct_and_get_queue - * @param EE_Messages_Processor $messages_proc - */ - function test_batch_send_from_queue_with_messages(EE_Messages_Processor $messages_proc) - { - //create messages we're going to use for sending - $messages_to_send = $this->factory->message->create_many(5, array('STS_ID' => EEM_Message::status_idle)); - - //create messages that are not ready for sending as a foil. - $this->factory->message->create_many(3); - - $sent_queue = $messages_proc->batch_send_from_queue($messages_to_send, true); - - $this->assertInstanceOf('EE_Messages_Queue', $sent_queue); - $this->assertEquals(5, $sent_queue->get_message_repository()->count()); - - //verify no errors - $this->assertEquals(0, - $sent_queue->count_STS_in_queue(EEM_Message::instance()->stati_indicating_failed_sending())); - $this->assertEquals(5, $sent_queue->count_STS_in_queue(EEM_Message::status_sent)); - } - - - /** - * This simulates the behaviour of EE_Messages_Processor::init_queue_and_generator for resetting the - * Messages_Generator on the processor. - */ - function test__init_queue_and_generator() - { - //load processor - $message_proc = EE_Registry::instance()->load_lib('Messages_Processor'); - - //grab generation queue. - $orig_generator_queue = $message_proc->get_queue(); - - //load generator via EE_Registry::factory() (which simulates what happens when executing EE_Messages_Processor::_init_queue_and_generator - $generator = EE_Registry::factory('EE_Messages_Generator'); - $new_generator_queue = $generator->generation_queue(); - - //these two queues should NOT be the same objects. - $this->assertNotEquals(spl_object_hash($orig_generator_queue), spl_object_hash($new_generator_queue)); - } - - - /** - * This implicitly tests the following methods as well: - * - queue_for_generation - * - queue_for_generation_loop - */ - function test_generate_and_return() - { - $test_components = $this->_test_components(); - /** @type EE_Messages_Processor $proc */ - $proc = $test_components['proc']; - $mtg = $test_components['mtg']; - - $generated_queue = $proc->generate_and_return($mtg); - - $this->assertInstanceOf('EE_Messages_Queue', $generated_queue); - - /** - * Expect 1 generated messages from the one MTG because there is a specific context provided (admin) that - * should only result in one message. - */ - $this->assertEquals(1, $generated_queue->count_STS_in_queue(EEM_Message::status_idle)); - - //messages in queue should be saved - this is because the cc field for email messages is extra meta and when - //that's added it saves the object to get an ID for the extra meta relation. - $generated_queue->get_message_repository()->rewind(); - $msg = $generated_queue->get_message_repository()->current(); - $this->assertGreaterThan(0, $msg->ID()); - } - - - function test_batch_queue_for_generation_and_persist() - { - $this->_common_test_with_specific_expected_status('batch_queue_for_generation_and_persist', null, false, 0); - } - - - function test_batch_queue_for_generation_no_persist() - { - $this->_common_test_with_specific_expected_status('batch_queue_for_generation_no_persist', null, false, 0); - } - - - function test_generate_and_queue_for_sending() - { - $this->_common_test_with_specific_expected_status('generate_and_queue_for_sending', EEM_Message::status_idle, - false, 0); - //now there should be Messages in the database all queued up for sending. Let's check - $messages = EEM_Message::instance()->get_all(array( - array( - 'STS_ID' => EEM_Message::status_idle, - ), - )); - - //expecting only one message because the specific context was provided. - $this->assertEquals(1, count($messages)); - } - - - function test_generate_for_preview() - { - $test_components = $this->_test_components(); - /** @type EE_Messages_Processor $proc */ - $proc = $test_components['proc']; - /** @type EE_Message_To_Generate $mtg */ - $mtg = $test_components['mtg']; - - $this->assertTrue($mtg->preview()); - $generated_queue = null; - - try { - /** @type EE_Messages_Queue $generated_queue */ - $generated_queue = $proc->generate_for_preview($mtg); - } catch (Exception $e) { - $this->fail(sprintf('Something went wrong with the test: %s', $e->getMessage())); - } - - //if made it here then we should have some content to verify. We're not matching entire string, just key - //components of what should be generated for the email messenger and registration message type using - //default dummy preview data. - $this->assertInstanceOf('EE_Messages_Queue', $generated_queue); - $generated_queue->get_message_repository()->rewind(); - /** @type EE_Message $msg */ - $msg = $generated_queue->get_message_repository()->current(); - $this->assertInstanceOf('EE_Message', $msg); - $this->assertContains('Registration Notification', $msg->content()); - $this->assertContains('Luke Skywalker', $msg->content()); - $this->assertContains('Test Scenario EVT A', $msg->content()); - - //messages in queue should be saved - this is because the cc field for email messages is extra meta and when - //that's added it saves the object to get an ID for the extra meta relation. - $this->assertGreaterThan(0, $msg->ID()); - - //verify sent! - $this->assertEquals(EEM_Message::status_sent, $msg->STS_ID()); - } - - - function test_setup_messages_from_ids_and_send() - { - //setup processor to work with - /** @type EE_Messages_Processor $proc */ - $proc = EE_Registry::instance()->load_lib('Messages_Processor'); - - //setup up messages we'll use for sending that have the right status - $messages_with_right_status = $this->factory->message->create_many(5, - array('STS_ID' => EEM_Message::status_sent)); - //include some EEM_Message::status_retry messages in the "right_status" group - $i = 0; - foreach ($messages_with_right_status as $message) { - $message->set_STS_ID(EEM_Message::status_retry); - $i++; - if ($i === 2) { - break; - } - } - $messages_with_wrong_status = $this->factory->message->create_many(5); - - $messages_with_right_status = array_map( - function ($message) { - return $message instanceof EE_Message ? $message->ID() : 0; - }, - $messages_with_right_status - ); - $messages_with_wrong_status = array_map( - function ($message) { - return $message instanceof EE_Message ? $message->ID() : 0; - }, - $messages_with_wrong_status - ); - - //first test correct messages - $proc->setup_messages_from_ids_and_send($messages_with_right_status); - $this->assertEquals(5, $proc->get_queue()->count_STS_in_queue(EEM_Message::status_resend)); - - //next test incorrect messages - //note calling this method SHOULD reset the internal queue. - $proc->setup_messages_from_ids_and_send($messages_with_wrong_status); - $this->assertEquals(0, $proc->get_queue()->count_STS_in_queue(EEM_Message::status_resend)); - } - - - /** - * Has common assertions for multiple EE_Messages_Processor method tests. - * - * @param string $method_to_test EE_Messages_Processor method being tested - * @param string $expected_status Expected EEM_Message::STS_ID() for the status test. - * @param bool $in_database Whether the test for persistence in db should be checked. - * @param int $expected_message_objects How many message objects are expected in the queue. - */ - protected function _common_test_with_specific_expected_status( - $method_to_test, - $expected_status, - $in_database = true, - $expected_message_objects = 1 - ) { - $test_components = $this->_test_components(); - /** @type EE_Messages_Processor $proc */ - $proc = $test_components['proc']; - /** @type EE_Message_To_Generate $mtg */ - $mtg = $test_components['mtg']; - - $queue = $proc->get_queue(); - - $proc->$method_to_test(array($mtg)); - - //queue should have $expected_message_objects EE_Message_object(s) and it/they should not be in the db and it/they - //should have status for the sent in status. - $this->assertEquals($expected_message_objects, $queue->get_message_repository()->count(), - sprintf('Failed test for the %s method', $method_to_test)); - if ($expected_message_objects > 0) { - $queue->get_message_repository()->rewind(); - $msg = $queue->get_message_repository()->current(); - $this->assertInstanceOf('EE_Message', $msg, sprintf('Failed test for the %s method', $method_to_test)); - if ($in_database) { - $this->assertInstanceOf('EE_Message', EEM_Message::instance()->get_one_by_ID($msg->ID()), - sprintf('Failed test for the %s method', $method_to_test)); - } else { - $this->assertEquals(0, $msg->ID(), sprintf('Failed test for the %s method', $method_to_test)); - } - $this->assertEquals($expected_status, $msg->STS_ID(), - sprintf('Failed test for the %s method', $method_to_test)); - } - } - - -} //end EE_Messages_Processor_Test -// Location: tests/testcases/core/libraries/messages/EE_Messages_Processor_Test.php diff --git a/tests/testcases/core/libraries/messages/EE_Messages_Queue_Test.php b/tests/testcases/core/libraries/messages/EE_Messages_Queue_Test.php deleted file mode 100644 index 2f8b53047ca..00000000000 --- a/tests/testcases/core/libraries/messages/EE_Messages_Queue_Test.php +++ /dev/null @@ -1,233 +0,0 @@ -load_lib( 'Messages_Queue' ); - } - - - - - - /** - * Testing adding to the queue - * @return EE_Messages_Queue - */ - function test_add_and_get_queue() { - $queue = $this->_get_queue(); - $message = $this->factory->message->create(array('nosave'=> 1)); - - - //add message - $added = $queue->add( $message ); - - //verify bool returns that it was added - $this->assertTrue( $added ); - - //get_message_repository to verify EE_Message is in it. - $test_queue = $queue->get_message_repository(); - $this->assertInstanceOf( 'EE_Message_Repository', $test_queue ); - - //verify the queue contains the message object - $test_queue->rewind(); - $this->assertTrue( $test_queue->valid() ); - $this->assertInstanceOf( 'EE_Message', $test_queue->current() ); - return $queue; - } - - - - - - /** - * @param EE_Messages_Queue $queue - * @depends test_add_and_get_queue - * @return EE_Messages_Queue - */ - function test_remove( EE_Messages_Queue $queue ) { - $test_queue = $queue->get_message_repository(); - - $test_queue->rewind(); - $this->assertTrue( $test_queue->valid() ); - $message = $test_queue->current(); - $test_queue->remove( $message ); - - //validate that the queue is empty - $test_queue->rewind(); - $this->assertFalse( $test_queue->valid() ); - - //add the message back to the queue for the next test - $test_queue->add( $message ); - return $queue; - } - - - - - - /** - * @param EE_Messages_Queue $queue - * @depends test_remove - * @return EE_Messages_Queue - */ - function test_save( EE_Messages_Queue $queue ) { - //first verify that the current EE_Message object in the queue does - //not have an ID() (it shouldn't) - $test_queue = $queue->get_message_repository(); - $test_queue->rewind(); - $this->assertEmpty( $test_queue->current()->ID() ); - - //save! - $queue->save(); - $test_queue->rewind(); - //verify we have an ID and can retrieve from db. - $message = EEM_Message::instance()->get_one_by_ID( $test_queue->current()->ID() ); - $this->assertInstanceOf( 'EE_Message', $message ); - return $queue; - } - - - - - - /** - * @param EE_Messages_Queue $queue - * @depends test_save - * @return EE_Messages_Queue - */ - function test_remove_with_persist( EE_Messages_Queue $queue ) { - $test_queue = $queue->get_message_repository(); - $test_queue->rewind(); - //verify we have a message object before removing - $message = $test_queue->current(); - $this->assertInstanceOf( 'EE_Message', $message ); - - //now do a remove of this message object but with the persist flag set. - $queue->remove( $message, true ); - - //did it get removed? - $test_queue->rewind(); - $this->assertFalse( $test_queue->valid() ); - //ensure message gets removed from entity map - EEM_Message::instance()->clear_entity_map( $message->ID() ); - //should not be in db either - $this->assertEmpty( EEM_Message::instance()->get_one_by_ID( $message->ID() ) ); - } - - - - - - /** - * This is also testing the lock functionality - * @return EE_Messages_Queue - */ - function test_get_batch_to_generate() { - //grab a bunch of message objects and add to queue. - $queue = $this->_get_queue(); - for ( $i=0;$i<5;$i++ ) { - $queue->add( $this->factory->message->create() ); - } - - //now get a new queue - $queue = $this->_get_queue(); - - //test getting batch and that there is the right count in the batch. - $this->assertTrue( $queue->get_batch_to_generate() ); - $this->assertEquals( 5, $queue->get_message_repository()->count() ); - - //test lock is set. - $lock_test_queue = $this->_get_queue(); - $this->assertTrue( $lock_test_queue->is_locked() ); - $this->assertFalse( $lock_test_queue->get_batch_to_generate() ); - - //test unlocking - $lock_test_queue->unlock_queue( 'generation' ); - $this->assertFalse( $lock_test_queue->is_locked() ); - $this->assertTrue( $lock_test_queue->get_batch_to_generate() ); - } - - - - - function test_get_to_send_batch_and_send() { - //grab a bunch of message objects and add to queue. - $queue = $this->_get_queue(); - for ( $i=0;$i<5;$i++ ) { - $queue->add( $this->factory->message->create() ); - } - //persist - $queue->save(); - - //next verify that nothing gets processed when there are no messages TO send (i.e. current EE_Message objects - //in db should be all incomplete. - $test_queue = $this->_get_queue(); - $this->assertFalse( $test_queue->get_to_send_batch_and_send() ); - - //okay let's now set all messages to be ready for sending. - foreach( $queue->get_message_repository() as $message ) { - $message->set_STS_ID( EEM_Message::status_idle ); - } - - //save queue - $queue->save(); - - //run test - $test_queue = $this->_get_queue(); - $this->assertTrue( $test_queue->get_to_send_batch_and_send() ); - - //verify no messages have failed status. - $this->assertEquals( 0, $test_queue->count_STS_in_queue( EEM_Message::instance()->stati_indicating_failed_sending() ) ); - //verify all have been marked as sent. - $this->assertEquals( 5, $test_queue->count_STS_in_queue(EEM_Message::status_sent ) ); - } - - - /** - * This is used to test the execute method when there are messages in the queue that are NOT with a status representing - * to send. They should NOT get sent if that's the case. - * @group 9787 - */ - public function test_send_only_ready_to_send_messages() { - //get some messages ready for the test and add to queue - $queue = $this->_get_queue(); - for ( $i = 0; $i < 5; $i++ ) { - $queue->add( $this->factory->message->create() ); - } - - //should be 5 items in the queue with MIC status - $this->assertEquals( 5, $queue->count_STS_in_queue( array( EEM_Message::status_incomplete ) ) ); - - //now if we execute now, NOTHING should get sent and we should still see all messages in the queue as MIC. - //anything else and we know the test has failed. - $queue->execute(); - - $this->assertEquals( 5, $queue->count_STS_in_queue( array( EEM_Message::status_incomplete ) ) ); - - } - - -} //end EE_Messages_Queue_Test \ No newline at end of file diff --git a/tests/testcases/core/libraries/messages/EE_Messages_Scheduler_Test.php b/tests/testcases/core/libraries/messages/EE_Messages_Scheduler_Test.php deleted file mode 100644 index ebfd50070e9..00000000000 --- a/tests/testcases/core/libraries/messages/EE_Messages_Scheduler_Test.php +++ /dev/null @@ -1,67 +0,0 @@ -addSomeMessagesForTesting(); - EE_Registry::instance()->CFG->messages->delete_threshold = 0; - EE_Messages_Scheduler::cleanup(); - //there should still be the old message in there. - $this->assertEquals(3, EEM_Message::instance()->count()); - } - - - /** - * Tests the cleanup method for messages when config is set to remove. - * @group 10417 - */ - public function test_cleanup_turned_on() - { - //create some messages - $this->addSomeMessagesForTesting(); - EE_Registry::instance()->CFG->messages->delete_threshold = 3; - EE_Messages_Scheduler::cleanup(); - $this->assertEquals(1, EEM_Message::instance()->count()); - } - - - protected function addSomeMessagesForTesting() - { - $messages_to_create = array( - array( - 'STS_ID' => EEM_Message::status_idle, - 'MSG_modified' => time() - (4*MONTH_IN_SECONDS) - ), - array( - 'STS_ID' => EEM_Message::status_debug_only, - 'MSG_modified' => time() - (4*MONTH_IN_SECONDS) - ), - array( - 'STS_ID' => EEM_Message::status_sent, - 'MSG_modified' => time() - (4*MONTH_IN_SECONDS) - ) - ); - foreach ($messages_to_create as $message_to_create) { - $this->factory->message->create($message_to_create); - } - } - -} \ No newline at end of file diff --git a/tests/testcases/core/libraries/messages/EE_Messages_Validator_Test.php b/tests/testcases/core/libraries/messages/EE_Messages_Validator_Test.php deleted file mode 100644 index 07a1ca9e54b..00000000000 --- a/tests/testcases/core/libraries/messages/EE_Messages_Validator_Test.php +++ /dev/null @@ -1,66 +0,0 @@ -loadMessagesMocks(); - $this->_messagesValidatorMock = new EE_Messages_Validator_Mock(); - } - - - - /** - * This tests validating dynamic messages shortcodes against the _invalid_shortcodes - * method in the EE_Messages_Validator class. - * - * @since @4.6.0 - * @group 7534 - */ - public function test_validating_dynamic_shortcodes() { - - $valid_shortcodes_array = array( - '[LINE_ITEM_TAXABLE_*]', - '[CO_TAX_NUMBER_*]', - '[PAYMENT_LIST_*]', - '[RECIPIENT_ANSWER_*]', - '[TKT_USES_*]', - '[INVOICE_PAYEE_TAX_NUMBER_*]', - '[OWING_STATUS_MESSAGE_*]', - '[ANSWER_*]' - ); - $valid_shortcodes_array = array_flip( $valid_shortcodes_array ); - - $string_with_valid_shortcodes = '[LINE_ITEM_TAXABLE_* some_param="this" or this ?] with [CO_TAX_NUMBER_* some_param="this" or this ?] and [PAYMENT_LIST_* some_param="this" or this ?]. But don\'t forget [RECIPIENT_ANSWER_* some_param="this" or this ?] or [TKT_USES_* some_param="this" or this ?] because [INVOICE_PAYEE_TAX_NUMBER_* some_param="this" or this ?] has [OWING_STATUS_MESSAGE_* some_param="this" or this ?] and finally, [ANSWER_* some_param="this" or this ?]'; - - $string_with_invalid_shortcodes = '[JUST_AN_INVALID*_] and another that is [SOMEWHAT_INVALID missing a bracket of course. But then there is [THIS_ONE_* (that does have a bracket)], and finally [JUST_A_PLAIN_INVALID_SHORTCODE]'; - - //test valid shortcodes - $this->assertFalse( $this->_messagesValidatorMock->invalid_shortcodes( $string_with_valid_shortcodes, $valid_shortcodes_array ) ); - - //test invalid shortcodes - $this->assertContains( '[JUST_AN_INVALID*_]', $this->_messagesValidatorMock->invalid_shortcodes( $string_with_invalid_shortcodes, $valid_shortcodes_array ) ); - $this->assertContains( '[THIS_ONE_* (that does have a bracket)]', $this->_messagesValidatorMock->invalid_shortcodes( $string_with_invalid_shortcodes, $valid_shortcodes_array ) ); - $this->assertContains( '[JUST_A_PLAIN_INVALID_SHORTCODE]', $this->_messagesValidatorMock->invalid_shortcodes( $string_with_invalid_shortcodes, $valid_shortcodes_array ) ); - $this->assertContains( '[SOMEWHAT_INVALID', $this->_messagesValidatorMock->invalid_shortcodes( $string_with_invalid_shortcodes, $valid_shortcodes_array ) ); - } -} diff --git a/tests/testcases/core/libraries/plugin_api/EE_Register_Addon_Test.php b/tests/testcases/core/libraries/plugin_api/EE_Register_Addon_Test.php deleted file mode 100644 index 221c60c82ae..00000000000 --- a/tests/testcases/core/libraries/plugin_api/EE_Register_Addon_Test.php +++ /dev/null @@ -1,508 +0,0 @@ -_mock_addon_path = EE_MOCKS_DIR . 'addons/eea-new-addon/'; - $this->_reg_args = array( - 'version' => '1.0.0', - 'min_core_version' => '4.0.0', - 'main_file_path' => $this->_mock_addon_path . 'eea-new-addon.php', - 'dms_paths' => $this->_mock_addon_path . 'core/data_migration_scripts', - 'model_paths' => $this->_mock_addon_path . 'core/db_models', - 'class_paths' => $this->_mock_addon_path . 'core/db_classes', - 'class_extension_paths' => $this->_mock_addon_path . 'core/db_class_extensions', - 'model_extension_paths' => $this->_mock_addon_path . 'core/db_model_extensions', - ); - $this->_addon_name = 'New_Addon'; - parent::__construct($name, $data, $dataName); - } - - - - public function setUp() - { - parent::setUp(); - add_filter( - 'FHEE__EEH_Activation__create_table__short_circuit', - array($this, 'dont_short_circuit_new_addon_table'), - 20, - 3 - ); - } - - - - /** - * OK's the creation of the esp_new_addon table, because this hooks in AFTER EE_UNitTestCase's callback on this same hook - * - * @param bool $short_circuit - * @param string $table_name - * @param string $create_sql - * @return boolean - */ - public function dont_short_circuit_new_addon_table($short_circuit = false, $table_name = '', $create_sql = '') - { - $table_analysis = EE_Registry::instance()->create('TableAnalysis', array(), true); - if ( - in_array($table_name, array('esp_new_addon_thing', 'esp_new_addon_attendee_meta'), true) - && ! $table_analysis->tableExists($table_name) - ) { - // echo "\r\n\r\nDONT short circuit $sql"; - // it's not altering. it's ok to allow this - return false; - } - // echo "3\r\n\r\n short circuit:$sql"; - return $short_circuit; - } - - - - //test registering a bare minimum addon, and then de-registering it - public function test_register_mock_addon_fail() - { - // echo "\n\n " . __LINE__ . ") " . __METHOD__ . "()"; - //we're registering the addon WAAAY after EE_System has set thing up, so - //registering this first time should throw an E_USER_NOTICE - try { - EE_Register_Addon::register($this->_addon_name, $this->_reg_args); - $this->fail('We should have had a warning saying that we are setting up the ee addon at the wrong time'); - } catch (PHPUnit_Framework_Error_Notice $e) { - $this->assertTrue(true); - } - //check that we didn't actually register the addon - $this->assertArrayNotHasKey('EE_New_Addon', EE_Registry::instance()->addons); - //check DMSs weren't setup either - $DMSs_available = EE_Data_Migration_Manager::reset()->get_all_data_migration_scripts_available(); - $this->assertArrayNotHasKey('EE_DMS_New_Addon_1_0_0', $DMSs_available); - //check that we didn't register the addon's deactivation hook either - $this->assertFalse(has_action('deactivate_' . plugin_basename($this->_reg_args['main_file_path']))); - } - - - - public function test_register_mock_addon_fail__bad_parameters() - { - //we're registering the addon with the wrong parameters - $this->_pretend_addon_hook_time(); - if (did_action('activate_plugin')) { - $this->assertTrue(false); - } - try { - EE_Register_Addon::register( - $this->_addon_name, - array( - 'version' => '1.0.0', - 'min_core_version' => '4.0.0', - 'dms_paths' => $this->_mock_addon_path . 'core/data_migration_scripts', - ) - ); - $this->fail( - 'We should have received a warning that the "main_file_path" is a required argument when registering an addon' - ); - } catch (EE_Error $e) { - $this->assertTrue(true); - } - //check that we didn't actually register the addon - $this->assertArrayNotHasKey('EE_New_Addon', EE_Registry::instance()->addons); - //check DMSs weren't setup either - $DMSs_available = EE_Data_Migration_Manager::reset()->get_all_data_migration_scripts_available(); - $this->assertArrayNotHasKey('EE_DMS_New_Addon_1_0_0', $DMSs_available); - //check that we didn't register the addon's de-activaiton hook either - $this->assertFalse(has_action('deactivate_' . plugin_basename($this->_reg_args['main_file_path']))); - } - - - - public function test_register_mock_addon_success() - { - //ensure model and class extensions weren't setup beforehand - $this->assertFalse($this->_class_has_been_extended()); - $this->assertFalse($this->_model_has_been_extended()); - $this->_pretend_addon_hook_time(); - if (did_action('activate_plugin')) { - $this->assertTrue(false); - } - $this->assertArrayNotHasKey('EE_New_Addon', EE_Registry::instance()->addons); - //just to make this test truly test the "eea-new-addon", use its own addon params - //this way we're more likely to keep the EE_New_Addon up-to-date - require_once(EE_TESTS_DIR . 'mocks/addons/eea-new-addon/eea-new-addon.php'); - require_once(EE_TESTS_DIR . 'mocks/addons/eea-new-addon/EE_New_Addon.class.php'); - EE_New_Addon::register_addon(); - $this->assertArrayHasKey( - 'EE_New_Addon', - EE_Registry::instance()->addons - ); - $this->assertInstanceOf( - 'EE_New_Addon', - EE_Registry::instance()->addons->EE_New_Addon - ); - //check DMSs were setup properly too - $DMSs_available = EE_Data_Migration_Manager::reset()->get_all_data_migration_scripts_available(); - $this->assertArrayHasKey('EE_DMS_New_Addon_1_0_0', $DMSs_available); - //and check the deactivation hook was setup properly - $this->assertTrue( - has_action('deactivate_' . EE_Registry::instance()->addons->EE_New_Addon->get_main_plugin_file_basename()) - ); - //check that the model was registered properly - EE_System::instance()->load_core_configuration(); - $this->assertArrayContains('EEM_New_Addon_Thing', EE_Registry::instance()->non_abstract_db_models); - $this->assertArrayContains('EEM_New_Addon_Thing', EE_Registry::instance()->models); - $dms = EE_Registry::instance()->load_dms('New_Addon_1_0_0'); - $this->assertInstanceOf('EE_Data_Migration_Script_Base', $dms); - $dms->set_migrating(false); - $dms->schema_changes_before_migration(); - $dms->schema_changes_after_migration(); - $this->assertTableExists('esp_new_addon_thing', 'New_Addon_Thing'); - //check that the model extension was registered properly - $this->assertTrue($this->_class_has_been_extended(true)); - $this->assertTrue($this->_model_has_been_extended(true)); - //check that the caps maps were registered properly too - $this->_pretend_capabilities_registered(); - $current_user = $this->factory->user->create_and_get(); - $other_user = $this->factory->user->create_and_get(); - //give user administrator role for test! - $current_user->add_role('administrator'); - $a_thing = $this->new_model_obj_with_dependencies('New_Addon_Thing', array('NEW_wp_user' => $current_user->ID)); - $others_thing = $this->new_model_obj_with_dependencies( - 'New_Addon_Thing', - array('NEW_wp_user' => $other_user->ID) - ); - $this->assertTrue( - EE_Capabilities::instance()->user_can($current_user, 'edit_thing', 'testing_edit', $a_thing->ID()) - ); - $this->assertTrue( - EE_Capabilities::instance()->user_can($current_user, 'edit_thing', 'testing_edit', $others_thing->ID()) - ); - } - - - - /** - * Utility function to just setup valid capabilities for tests in this suite. - * - * @since 1.0.0 - * @return void - */ - private function _pretend_capabilities_registered() - { - EE_Registry::instance()->load_core('Capabilities'); - EE_Capabilities::instance()->init_caps(true); - //validate caps were registered and init saved. - $admin_caps_init = EE_Capabilities::instance()->get_ee_capabilities('administrator'); - $this->assertArrayContains('edit_thing', $admin_caps_init); - //verify new caps are in the role - $role = get_role('administrator'); - $this->assertContains( - array('edit_thing', 'edit_things', 'edit_others_things', 'edit_private_things'), - $role->capabilities - ); - } - - /** - * uses the connection settings on EE_New_Addon::register() instead - * of our copy of them - */ - // function test_register_mock_addon_success_using_its_callback(){ - // //ensure model and class extensions weren't setup beforehand - // $this->assertFalse( $this->_class_has_been_extended() ); - // $this->assertFalse( $this->_model_has_been_extended() ); - // - // $this->_pretend_addon_hook_time(); - // if( did_action( 'activate_plugin' ) ){ - // $this->assertTrue( FALSE ); - // } - // $this->assertFalse(property_exists(EE_Registry::instance()->addons, 'EE_New_Addon')); - // - // - // //use the function in mocks/addons/new_addon/eea-new-addon.php - // load_espresso_new_addon(); - // - // $this->assertAttributeNotEmpty('EE_New_Addon',EE_Registry::instance()->addons); - // //check DMSs were setup properly too - // $DMSs_available = EE_Data_Migration_Manager::reset()->get_all_data_migration_scripts_available(); - // $this->assertArrayHasKey('EE_DMS_New_Addon_1_0_0',$DMSs_available); - // - // //and check the deactivation hook was setup properly - // $this->assertTrue( has_action( 'deactivate_' . EE_Registry::instance()->addons->EE_New_Addon->get_main_plugin_file_basename() ) ); - // - // //check that the model was registered properly - // EE_System::instance()->load_core_configuration(); - // $this->assertArrayContains('EEM_New_Addon_Thing', EE_Registry::instance()->non_abstract_db_models); - // $this->assertArrayContains('EEM_New_Addon_Thing', EE_Registry::instance()->models); - // - // $dms = EE_Registry::instance()->load_dms('New_Addon_1_0_0'); - // $this->assertInstanceOf( 'EE_Data_Migration_Script_Base', $dms ); - // $dms->schema_changes_before_migration(); - // $dms->schema_changes_after_migration(); - // $this->assertTableExists( 'esp_new_addon_thing', 'New_Addon_Thing' ); - // //check that the model extension was registered properly - // $this->assertTrue( $this->_class_has_been_extended( TRUE ) ); - // $this->assertTrue( $this->_model_has_been_extended( TRUE ) ); - // } - /** - * check that when we register an addon and then another after the 'activate_plugin' - * action fired, that there are no errors and the 2nd addon's activation indicator - * was set properly - * - * @throws \EE_Error - */ - public function test_register_mock_addon__activation() - { - $this->_pretend_after_plugin_activation(); - EE_Register_Addon::register($this->_addon_name, $this->_reg_args); - $this->assertArrayHasKey( - 'EE_New_Addon', - EE_Registry::instance()->addons - ); - $this->assertInstanceOf( - 'EE_New_Addon', - EE_Registry::instance()->addons->EE_New_Addon - ); - $this->assertWPOptionExists( - EE_Registry::instance()->addons->EE_New_Addon->get_activation_indicator_option_name() - ); - } - - - - /** - * registers an addon as usual, but then calls 'activate_plugin', as if a different - * addon had been activated. Because the register method is called twice, this has the potential - * for problems - * - * @throws \EE_Error - */ - public function test_register_addon_called_twice_on_activation() - { - EE_System::reset(); - $this->_pretend_addon_hook_time(); - if (did_action('activate_plugin')) { - $this->assertTrue(false); - } - $this->assertFalse(property_exists(EE_Registry::instance()->addons, 'EE_New_Addon')); - EE_Register_Addon::register($this->_addon_name, $this->_reg_args); - $this->assertArrayHasKey( - 'EE_New_Addon', - EE_Registry::instance()->addons - ); - $this->assertInstanceOf( - 'EE_New_Addon', - EE_Registry::instance()->addons->EE_New_Addon - ); - global $wp_actions; - $times_load_addons_fired = $wp_actions['AHEE__EE_System__load_espresso_addons']; - do_action('activate_plugin'); - $this->assertGreaterThan($times_load_addons_fired, $wp_actions['AHEE__EE_System__load_espresso_addons']); - } - - - - public function tearDown() - { - if (isset($this->_addon_name, EE_Registry::instance()->addons->EE_New_Addon)) { - $main_file_path_before_deregistration = EE_Registry::instance() - ->addons - ->EE_New_Addon - ->get_main_plugin_file_basename(); - EE_Register_Addon::deregister($this->_addon_name); - $this->assertArrayNotHasKey('EE_New_Addon', EE_Registry::instance()->addons); - //verify the de-activation hook was removed - $this->assertFalse(has_action('deactivate_' . $main_file_path_before_deregistration)); - //verify the models were deregistered - EE_System::instance()->load_core_configuration(); - $this->assertArrayDoesNotContain('EEM_New_Addon_Thing', EE_Registry::instance()->non_abstract_db_models); - $this->assertArrayDoesNotContain('EEM_New_Addon_Thing', EE_Registry::instance()->models); - EE_Registry::instance()->reset_model('Attendee'); - //verify that the model and class extensions have been removed - $this->assertFalse($this->_class_has_been_extended()); - $this->assertFalse($this->_model_has_been_extended()); - } - //verify DMSs deregistered - $DMSs_available = EE_Data_Migration_Manager::reset()->get_all_data_migration_scripts_available(); - $this->assertArrayNotHasKey('EE_DMS_New_Addon_1_0_0', $DMSs_available); - $this->_stop_pretending_addon_hook_time(); - $this->_stop_pretending_after_plugin_activation(); - remove_all_filters('AHEE__EE_System__load_espresso_addons'); - parent::tearDown(); - } - - /** - * double checks that we the example addon is registering correctly. - * - * @todo: to make sure our example addon is really working, we should try using it - * on its own - */ - // public function test_regular_new_addon_activation(){ - // $this->_pretend_addon_hook_time(); - // require_once( EE_TESTS_DIR . 'mocks/addons/eea-new-addon/eea-new-addon.php' ); - // EE_New_Addon::register_addon(); - // $this->assertAttributeNotEmpty('EE_New_Addon',EE_Registry::instance()->addons); - // - // //and then it should be torn down by tearDown() - // } - protected function _stop_pretending_after_plugin_activation() - { - global $wp_actions; - unset($wp_actions['activate_plugin']); - } - - - - protected function _pretend_after_plugin_activation() - { - do_action('activate_plugin'); - } - - - - protected function _pretend_addon_hook_time() - { - global $wp_actions; - unset( - $wp_actions['AHEE__EEM_Attendee__construct__end'], - $wp_actions['AHEE__EE_System__load_core_configuration__begin'], - $wp_actions['AHEE__EE_System__register_shortcodes_modules_and_widgets'], - $wp_actions['AHEE__EE_System__core_loaded_and_ready'] - ); - parent::_pretend_addon_hook_time(); - } - - - - /** - * Determines if the attendee class has been extended by teh mock extension - * - * @param bool $throw_error - * @return bool - * @throws \EE_Error - */ - private function _class_has_been_extended($throw_error = false) - { - try { - $a = EE_Attendee::new_instance(); - $a->foobar(); - return true; - } catch (EE_Error $e) { - if ($throw_error) { - throw $e; - } - return false; - } - } - - - - /** - * Determines if the Attendee model has been extended by the mock extension - * - * @param bool $throw_error - * @return bool - * @throws \EE_Error - */ - private function _model_has_been_extended($throw_error = false) - { - try { - /** @var EEM_Attendee $att */ - $att = EE_Registry::instance()->reset_model('Attendee'); - if (! $att->has_field('ATT_foobar')) { - if ($throw_error) { - throw new EE_Error( - sprintf( - __( - 'The field ATT_foobar is not on EEM_Attendee, but the extension should have added it. fields are: %s', - 'event_espresso' - ), implode(",", array_keys(EEM_Attendee::instance()->field_settings())) - ) - ); - } - return false; - } - if (! $att->has_relation('New_Addon_Thing')) { - if ($throw_error) { - throw new EE_Error( - sprintf( - __( - 'The relation of type New_Addon_Thing on EEM_Attendee, but the extension should have added it. fields are: %s', - 'event_espresso' - ), implode(",", array_keys(EEM_Attendee::instance()->field_settings())) - ) - ); - } - return false; - } - $att->get_all_new_things(); - return true; - } catch (EE_Error $e) { - if ($throw_error) { - throw $e; - } - return false; - } - } - - - - public function test_effective_version() - { - //use reflection to test this protected method - $method = new ReflectionMethod('EE_Register_Addon', '_effective_version'); - $method->setAccessible(true); - $this->assertEquals('4.3.0.dev.000', $method->invoke(null, '4.3.0')); - $this->assertEquals('4.3.0.p.000', $method->invoke(null, '4.3.0.p')); - $this->assertEquals('4.3.0.rc.123', $method->invoke(null, '4.3.0.rc.123')); - } - - - - public function test_meets_min_core_version_requirement() - { - //use reflection to test this protected method - $method = new ReflectionMethod('EE_Register_Addon', '_meets_min_core_version_requirement'); - $method->setAccessible(true); - $this->assertTrue($method->invoke(null, '4.3.0', '4.3.0.p')); - $this->assertTrue($method->invoke(null, '4.3.0', '4.3.0.rc.032')); - $this->assertTrue($method->invoke(null, '4.3.0.p', '4.3.0.p')); - $this->assertTrue($method->invoke(null, '4.3.0.p', '4.4.0.p')); - $this->assertTrue($method->invoke(null, '4.3.0.rc.000', '4.3.0.p')); - $this->assertFalse($method->invoke(null, '4.4.0', '4.3.0.p')); - $this->assertFalse($method->invoke(null, '4.4.0.p', '4.3.0.p')); - $this->assertFalse($method->invoke(null, '4.3.0.rc.123', '4.3.0.rc.001')); - } - -} - -// End of file EE_Register_Addon_Test.php -// Location: testcases/core/libraries/plugin_api/EE_Register_Addon_Test.php diff --git a/tests/testcases/core/libraries/plugin_api/EE_Register_Capabilities_Test.php b/tests/testcases/core/libraries/plugin_api/EE_Register_Capabilities_Test.php deleted file mode 100644 index 1064663f240..00000000000 --- a/tests/testcases/core/libraries/plugin_api/EE_Register_Capabilities_Test.php +++ /dev/null @@ -1,403 +0,0 @@ - array( - 'test_reads', - 'test_writes', - 'test_others_read', - 'test_others_write', - 'test_private_read', - 'test_private_write', - ), - ); - $non_numeric_cap_maps_array = array( - 'EE_Meta_Capability_Map_Read' => array( - 'test_read', - array('Event', 'test_published_read', 'test_others_read', 'test_private_read'), - ), - 'EE_Meta_Capability_Map_Edit' => array( - 'test_write', - array('Event', 'test_published_write', 'test_others_write', 'test_private_write'), - ), - ); - $numeric_cap_maps_array = array( - 0 => array( - 'EE_Meta_Capability_Map_Read' => array( - 'test_read', - array('Event', 'test_published_read', 'test_others_read', 'test_private_read'), - ), - ), - 1 => array( - 'EE_Meta_Capability_Map_Edit' => array( - 'test_write', - array('Event', 'test_published_write', 'test_others_write', 'test_private_write'), - ), - ), - ); - $this->_valid_capabilities = array( - 'capabilities' => $capabilities_array, - 'capability_maps' => $non_numeric_cap_maps_array, - ); - $this->_valid_capabilities_numeric_caps_map = array( - 'capabilities' => $capabilities_array, - 'capability_maps' => $numeric_cap_maps_array, - ); - } - - - /** - * Utility function to just ensure and admin user is setup for tests in this suite - * - * @since 4.5.0 - * @return void - */ - private function setupUser() - { - //create a user for checking caps on. - $user_id = $this->factory->user->create(); - $this->_user = $this->factory->user->get_object_by_id($user_id); - //give user administrator role for test! - $this->_user->add_role('administrator'); - - //verify administrator role set - $this->assertTrue(user_can($this->_user, 'administrator')); - } - - - /** - * Utility function to just setup valid capabilities for tests in this suite. - * - * @since 1.0.0 - * @return void - */ - private function _pretend_capabilities_registered($non_numeric = true) - { - //pretend correct hookpoint set. - global $wp_actions; - unset($wp_actions['AHEE__EE_System___detect_if_activation_or_upgrade__begin']); - //register capabilities - $capabilities_to_register = $non_numeric ? $this->_valid_capabilities : $this->_valid_capabilities_numeric_caps_map; - EE_Register_Capabilities::register('Test_Capabilities', $capabilities_to_register); - - $this->_add_test_helper_filters(); - - EE_Registry::instance()->load_core('Capabilities'); - EE_Capabilities::instance()->init_caps(true); - - //remove filters that were added to prevent pollution in other tests - $this->_remove_test_helper_filters(); - //validate caps were registered and init saved. - $admin_caps_init = EE_Capabilities::instance()->get_ee_capabilities('administrator'); - $this->assertArrayContains('test_reads', $admin_caps_init); - - //verify new caps are in the role - $role = get_role('administrator'); - $this->assertContains($this->_valid_capabilities['capabilities']['administrator'], $role->capabilities); - - //make sure we didn't erase the existing capabilities (@see https://events.codebasehq.com/projects/event-espresso/tickets/6700) - $this->assertContains(array('ee_read_ee', 'ee_read_events'), $role->capabilities, - 'Looks like registering capabilities is overwriting default capabilites, that will cause problems'); - - //setup user - $this->setupUser(); - } - - - /** - * Adds filter to help with tests that in turn verify things that should be setup are. - */ - private function _add_test_helper_filters() - { - //use filters to access some of the data normally private to EE_Capabilities because we want to verify it - add_filter('FHEE__EE_Capabilities__init_caps_map__caps', array($this, '_remember_what_caps_were_beforehand'), - 1); - add_filter('FHEE__EE_Capabilities__init_caps_map__caps', array($this, '_verify_new_cap_map_ok'), 100); - - //verify the cap_map_maps - add_filter('FHEE__EE_Capabilities___set_meta_caps__meta_caps', array($this, '_verify_new_meta_caps_ok'), 200); - } - - - /** - * Removes the helper filters that were added initially for helping verify setup. - */ - private function _remove_test_helper_filters() - { - remove_filter('FHEE__EE_Capabilities__init_caps_map__caps', array($this, '_remember_what_caps_were_beforehand'), - 1); - remove_filter('FHEE__EE_Capabilities__init_caps_map__caps', array($this, '_verify_new_cap_map_ok'), 100); - remove_filter('FHEE__EE_Capabilities___set_meta_caps__meta_caps', array($this, '_verify_new_meta_caps_ok'), - 200); - } - - - /** - * Verify that the $incoming_cap_map looks normal after EE_Register_Capabilities has played with it - * - * @param array $incoming_cap_map - * @return array - */ - public function _verify_new_cap_map_ok($incoming_cap_map) - { - foreach ($this->_caps_before_registering_new_ones as $role => $caps) { - $this->assertArrayHasKey($role, $incoming_cap_map); - foreach ($caps as $cap) { - $this->assertArrayContains($cap, $incoming_cap_map[$role]); - } - } - return $incoming_cap_map; - } - - - /** - * Verify that the $incoming_meta_caps (via _set_meta_caps ) looks normal after EE_Register_Capabilities has played - * with it - * - * @param array $incoming_meta_caps - * @return array - */ - public function _verify_new_meta_caps_ok($incoming_meta_caps) - { - foreach ($this->_valid_capabilities['capability_maps'] as $meta_ref => $meta_cap_info) { - $has_meta_cap = false; - $meta_cap_to_check = $meta_cap_info[0]; - //loop through and make sure that this meta cap is set on an instantiated map - foreach ($incoming_meta_caps as $meta_cap_class) { - if ($meta_cap_class->meta_cap == $meta_cap_to_check) { - $has_meta_cap = true; - break; - } - } - - if (! $has_meta_cap) { - $this->fail(sprintf('Expecting the %s meta cap to be registered but it is not.', $meta_cap_to_check)); - } - } - return $incoming_meta_caps; - } - - - /** - * Verify that the $incoming_cap_map looks normal after EE_Register_Capabilities has deregistered existing - * registered caps - * - * @param array $incoming_cap_map - * @return array - */ - public function _verify_new_cap_map_ok_after_deregister($incoming_cap_map) - { - $this->assertNotContains($this->_valid_capabilities['capabilities']['administrator'], - $incoming_cap_map['administrator']); - return $incoming_cap_map; - } - - - /** - * Verify that the $incoming_meta_caps looks normal after EE_Register_Capabilities has deregistered existing - * registered caps. - * - * @param array $incoming_meta_caps - * @return array - */ - public function _verify_new_meta_cap_ok_after_deregister($incoming_meta_caps) - { - foreach ($this->_valid_capabilities['capability_maps'] as $meta_ref => $meta_cap_info) { - $has_meta_cap = false; - $meta_cap_to_check = $meta_cap_info[0]; - //loop through and make sure that this meta cap is set on an instantiated map - foreach ($incoming_meta_caps as $meta_cap_class) { - if ($meta_cap_class->meta_cap == $meta_cap_to_check) { - $has_meta_cap = true; - break; - } - } - - if ($has_meta_cap) { - $this->fail(sprintf('Expecting the %s meta cap to not be registered but it is.', $meta_cap_to_check)); - } - } - return $incoming_meta_caps; - } - - - /** - * Gets all the caps BEFORE the registered caps get added to make sure none get - * removed. - * - * @param type $incoming_cap_map - * @return array - */ - public function _remember_what_caps_were_beforehand($incoming_cap_map) - { - $this->_caps_before_registering_new_ones = $incoming_cap_map; - return $incoming_cap_map; - } - - - /** - * Gets all the cap maps BEFORE the registered caps get added to make sure none get - * removed. - * - * @param type $incoming_cap_map - * @return array - */ - public function _remember_what_meta_caps_were_beforehand($incoming_cap_map) - { - $this->_meta_caps_before_registering_new_ones = $incoming_cap_map; - return $incoming_cap_map; - } - - - public function test_registering_capabilities_too_early() - { - - //test activating in the wrong spot. - try { - EE_Register_Capabilities::register('Test_Capabilities', $this->_valid_capabilities); - $this->fail('We should have had a warning saying that we are registering capabilities at the wrong time'); - } catch (PHPUnit_Framework_Error_Notice $e) { - $this->assertTrue(true); - } - } - - - public function test_registering_capabilities_and_they_are_assigned() - { - $this->_pretend_capabilities_registered(); - - //now capabilities *SHOULD* be set on the user. Let's verify. - $this->assertTrue(user_can($this->_user, 'test_reads')); - $this->assertTrue(user_can($this->_user, 'test_writes')); - $this->assertTrue(user_can($this->_user, 'test_others_read')); - $this->assertTrue(user_can($this->_user, 'test_others_write')); - $this->assertTrue(user_can($this->_user, 'test_private_read')); - $this->assertTrue(user_can($this->_user, 'test_private_write')); - } - - - public function test_capability_maps_registered_non_numeric() - { - $this->_pretend_capabilities_registered(); - //the best way to test this is to ensure the registered maps work. So let's author an event by the user. - - //main users event. - $event = $this->factory->event->create(array('EVT_wp_user' => $this->_user->ID)); - - //other users event (checking others event caps). - $user_id = $this->factory->user->create(); - $other_user = $this->factory->user->get_object_by_id($user_id); - $other_event = $this->factory->event->create(array('EVT_wp_user' => $other_user->ID)); - - //make sure we have an event - $this->assertInstanceOf('EE_Event', $event); - $this->assertInstanceOf('EE_Event', $other_event); - - //check map items for event. - $this->assertTrue(EE_Capabilities::instance()->user_can($this->_user, 'test_read', 'testing_read', - $event->ID())); - $this->assertTrue(EE_Capabilities::instance()->user_can($this->_user, 'test_write', 'testing_edit', - $event->ID())); - $this->assertTrue(EE_Capabilities::instance()->user_can($this->_user, 'test_read', 'testing_read', - $other_event->ID())); - $this->assertTrue(EE_Capabilities::instance()->user_can($this->_user, 'test_write', 'testing_edit', - $other_event->ID())); - } - - - public function test_capability_maps_registered_numeric() - { - $this->_pretend_capabilities_registered(false); - //the best way to test this is to ensure the registered maps work. So let's author an event by the user. - - //main users event. - $event = $this->factory->event->create(array('EVT_wp_user' => $this->_user->ID)); - - //other users event (checking others event caps). - $user_id = $this->factory->user->create(); - $other_user = $this->factory->user->get_object_by_id($user_id); - $other_event = $this->factory->event->create(array('EVT_wp_user' => $other_user->ID)); - - //make sure we have an event - $this->assertInstanceOf('EE_Event', $event); - $this->assertInstanceOf('EE_Event', $other_event); - - //check map items for event. - $this->assertTrue(EE_Capabilities::instance()->user_can($this->_user, 'test_read', 'testing_read', - $event->ID())); - $this->assertTrue(EE_Capabilities::instance()->user_can($this->_user, 'test_write', 'testing_edit', - $event->ID())); - $this->assertTrue(EE_Capabilities::instance()->user_can($this->_user, 'test_read', 'testing_read', - $other_event->ID())); - $this->assertTrue(EE_Capabilities::instance()->user_can($this->_user, 'test_write', 'testing_edit', - $other_event->ID())); - } - - - public function test_capability_maps_deregistered() - {//setup registered caps first - $this->_pretend_capabilities_registered(); - - //now let's add filter verify that new cap map doesn't have the mapped items after de-registering. The callback - //on these filters should get called when EE_Register_Capabilities::deregister calls the EE_Capability::init_caps() method - //so at that point they'll verify that the items that should be removed were actually removed. - add_filter('FHEE__EE_Capabilities__init_caps_map__caps', - array($this, '_verify_new_cap_map_ok_after_deregister'), 100); - add_filter('FHEE__EE_Capabilities___set_meta_caps__meta_caps', - array($this, '_verify_new_meta_cap_ok_after_deregister'), 200); - - //now deregister - EE_Register_Capabilities::deregister('Test_Capabilities'); - - //remove filters - remove_filter('FHEE__EE_Capabilities__init_caps_map__caps', - array($this, '_verify_new_cap_map_ok_after_deregister'), 100); - remove_filter('FHEE__EE_Capabilities___set_meta_caps__meta_caps', - array($this, '_verify_new_meta_cap_ok_after_deregister'), 200); - } - - public function tearDown() - { - EE_Register_Capabilities::deregister('Test_Capabilities'); - parent::tearDown(); - } -} diff --git a/tests/testcases/core/libraries/plugin_api/EE_Register_Data_Migration_Scripts_Test.php b/tests/testcases/core/libraries/plugin_api/EE_Register_Data_Migration_Scripts_Test.php deleted file mode 100644 index 787ba453b62..00000000000 --- a/tests/testcases/core/libraries/plugin_api/EE_Register_Data_Migration_Scripts_Test.php +++ /dev/null @@ -1,55 +0,0 @@ -_stop_pretending_addon_hook_time(); - remove_all_filters('FHEE__EE_Data_Migration_Manager__get_data_migration_script_folders'); - $pretend_addon_name = 'More_Core'; - $args = array( - 'dms_paths'=>array(EE_TESTS_DIR.'mocks/core/data_migration_scripts') - ); - //try registering at wrong time - try{ - EE_Register_Data_Migration_Scripts::register($pretend_addon_name, $args); - $this->fail('We should have had a warning saying that we are setting up the ee addon at the wrong time'); - }catch(PHPUnit_Framework_Error_Notice $e){ - $this->assertTrue(True); - } - //and check we didn't actually register the DMSs (because we attempted to do so at teh wrong time) - $DMSs_available = EE_Data_Migration_Manager::reset()->get_all_data_migration_scripts_available(); - $this->assertArrayNotHasKey('EE_DMS_Core_1_0_0',$DMSs_available); - - //ok now pretend we're registering the DMS at the right time - $this->_pretend_addon_hook_time(); - EE_Register_Data_Migration_Scripts::register($pretend_addon_name, $args); - $DMSs_available = EE_Data_Migration_Manager::reset()->get_all_data_migration_scripts_available(); - $this->assertArrayHasKey('EE_DMS_Core_1_0_0',$DMSs_available); - - //now deregister it - EE_Register_Data_Migration_Scripts::deregister($pretend_addon_name); - $DMSs_available = EE_Data_Migration_Manager::reset()->get_all_data_migration_scripts_available(); - $this->assertArrayNotHasKey('EE_DMS_Core_1_0_0',$DMSs_available); - - $this->_stop_pretending_addon_hook_time(); - } -} - -// End of file EE_Register_Data_Migration_Scripts_test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/plugin_api/EE_Register_Model_Extensions_Test.php b/tests/testcases/core/libraries/plugin_api/EE_Register_Model_Extensions_Test.php deleted file mode 100644 index 23b196868fb..00000000000 --- a/tests/testcases/core/libraries/plugin_api/EE_Register_Model_Extensions_Test.php +++ /dev/null @@ -1,196 +0,0 @@ -_reg_args = array( - 'model_extension_paths' => array( EE_MOCKS_DIR . 'core/db_model_extensions/' ), - 'class_extension_paths' => array( EE_MOCKS_DIR . 'core/db_class_extensions/' ) - ); - $this->_model_group = 'Mock'; - parent::__construct($name, $data, $dataName); - } - /** - * Determines if the attendee class has been extended by teh mock extension - * @return boolean - */ - private function _class_has_been_extended( $throw_error = FALSE){ - try{ - $a = EE_Attendee::new_instance(); - $a->foobar(); - return TRUE; - }catch(EE_Error $e){ - if( $throw_error ){ - throw $e; - } - return FALSE; - } - } - - - - /** - * Determines if the Attendee model has been extended by the mock extension - * - * @param bool $throw_error - * @return bool - * @throws \EE_Error - */ - private function _model_has_been_extended( $throw_error = FALSE){ - try{ - $att = EE_Registry::instance()->load_model('Attendee'); - $att->reset()->foobar(); - if( ! $att->has_field('ATT_foobar')){ - if( $throw_error ){ - throw new EE_Error(sprintf( __( 'The field ATT_foobar is not on EEM_Attendee, but the extension should have added it. fields are: %s', 'event_espresso' ), implode(",",array_keys(EEM_Attendee::instance()->field_settings())))); - } - return FALSE; - } - if( ! $att->has_relation('Transaction')){ - if( $throw_error ){ - throw new EE_Error(sprintf( __( 'The relation of type Transaction on EEM_Attendee, but the extension should have added it. fields are: %s', 'event_espresso' ), implode(",",array_keys(EEM_Attendee::instance()->field_settings())))); - } - return FALSE; - } - return TRUE; - }catch(EE_Error $e){ - if( $throw_error ){ - throw $e; - } - return FALSE; - } - } - - //test registering a bare minimum addon, and then deregistering it - function test_register_mock_model_fail(){ - //we're registering the addon WAAAY after EE_System has set thing up, so - //registering this first time should throw an E_USER_NOTICE - $this->assertFalse( $this->_class_has_been_extended() ); - $this->assertFalse( $this->_model_has_been_extended() ); - try{ - EE_Register_Model_Extensions::register($this->_model_group, $this->_reg_args); - $this->fail('We should have had a warning saying that we are setting up the ee addon at the wrong time'); - }catch(EE_Error $e){ - $this->assertTrue(True); - } - //verify they still haven't been extended - $this->assertFalse( $this->_class_has_been_extended() ); - $this->assertFalse( $this->_model_has_been_extended() ); - } - - function test_register_mock_model_extension_fail__bad_parameters(){ - //we're registering the addon with the wrong parameters - $this->_pretend_addon_hook_time(); - $this->assertFalse( $this->_class_has_been_extended() ); - $this->assertFalse( $this->_model_has_been_extended() ); - try{ - EE_Register_Model_Extensions::register($this->_model_group, array('foo' => 'bar')); - $this->fail('We should have had a warning saying that we are setting up the ee addon at the wrong time'); - }catch(EE_Error $e){ - $this->assertTrue(True); - } - //verify they still haven't been extended - $this->assertFalse( $this->_class_has_been_extended() ); - $this->assertFalse( $this->_model_has_been_extended() ); - } - - protected function _pretend_addon_hook_time() { - global $wp_actions; - unset( $wp_actions['AHEE__EEM_Attendee__construct__end'] ); - parent::_pretend_addon_hook_time(); - } - - function test_register_mock_addon_success(){ - - $this->assertFalse( $this->_class_has_been_extended() ); - $this->assertFalse( $this->_model_has_been_extended() ); - $this->_pretend_addon_hook_time(); - - EE_Register_Model_Extensions::register($this->_model_group, $this->_reg_args); - EEM_Attendee::instance()->reset(); - //verify they still haven't been extended - $this->assertTrue( $this->_class_has_been_extended( TRUE ) ); - $this->assertTrue( $this->_model_has_been_extended( TRUE ) ); - //and that we can still use EEM_Attendee - EE_Attendee::new_instance(); - EEM_Attendee::instance()->get_all(); - EE_Registry::instance()->load_model('Attendee')->get_all(); - - //now deregister it - EE_Register_Model_Extensions::deregister($this->_model_group); - $this->assertFalse( $this->_class_has_been_extended() ); - $this->assertFalse( $this->_model_has_been_extended() ); - EEM_Attendee::instance()->reset(); - //and EEM_Attendee still works right? both ways of instantiating it? - EE_Attendee::new_instance(); - EEM_Attendee::instance()->get_all(); - EE_Registry::instance()->load_model('Attendee')->get_all(); - - } - public function setUp(){ - parent::setUp(); - //whitelist the table we're about to add - add_filter( 'FHEE__EEH_Activation__create_table__short_circuit', array($this, 'dont_short_circuit_mock_table' ), 25, 3 ); - //add table from related DMS - EEH_Activation::create_table('esp_mock_attendee_meta', ' - MATTM_ID int(10) unsigned NOT NULL AUTO_INCREMENT, - ATT_ID int(10) unsigned NOT NULL, - ATT_foobar int(10) unsigned NOT NULL, - PRIMARY KEY (MATTM_ID)' - ); - $this->assertTableExists( 'esp_mock_attendee_meta' ); - - EE_Register_Model_Extensions::deregister( $this->_model_group ); - } - - - - /** - * OK's the creation of the esp_new_addon table, because this hooks in AFTER EE_UNitTestCase's callback on this same hook - * - * @param bool $short_circuit - * @param string $table_name - * @param string $create_sql - * @return array - */ - public function dont_short_circuit_mock_table( $short_circuit = false, $table_name = '', $create_sql = '' ){ - $table_analysis = EE_Registry::instance()->create( 'TableAnalysis', array(), true ); - if( $table_name == 'esp_mock_attendee_meta' && ! $table_analysis->tableExists( $table_name) ){ -// echo "\r\n\r\nDONT short circuit $sql"; - //it's not altering. it's ok to allow this - return false; - }else{ -// echo "3\r\n\r\n short circuit:$sql"; - return $short_circuit; - } - } - public function tearDown(){ - //ensure the models aren't stil registered. they should have either been - //deregistered during the test, or not been registered at all - $this->_stop_pretending_addon_hook_time(); - parent::tearDown(); - } -} - -// End of file EE_Register_Model_Test.php -// Location: \tests\testcases\core\libraries\plugin_api\EE_Register_Model_Extensions_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/plugin_api/EE_Register_Model_Test.php b/tests/testcases/core/libraries/plugin_api/EE_Register_Model_Test.php deleted file mode 100644 index c5dd93ff8d1..00000000000 --- a/tests/testcases/core/libraries/plugin_api/EE_Register_Model_Test.php +++ /dev/null @@ -1,123 +0,0 @@ -_reg_args = array( - 'model_paths' => array(EE_MOCKS_DIR . 'core/db_models/'), - 'class_paths' => array(EE_MOCKS_DIR . 'core/db_classes/'), - ); - $this->_model_group = 'Mock'; - parent::__construct($name, $data, $dataName); - } - - - - public function setUp() - { - parent::setUp(); - $this->_stop_pretending_addon_hook_time(); - // EE_System::instance()->load_core_configuration(); - } - - - - //test registering a bare minimum addon, and then deregistering it - function test_register_mock_model_fail() - { - //we're registering the addon WAAAY after EE_System has set thing up, so - //registering this first time should throw an E_USER_NOTICE - $this->assertArrayDoesNotContain('EEM_Mock', EE_Registry::instance()->non_abstract_db_models); - $this->assertArrayDoesNotContain('EEM_Mock', EE_Registry::instance()->models); - try { - EE_Register_Model::register($this->_model_group, $this->_reg_args); - $this->fail('We should have had a warning saying that we are setting up the ee addon at the wrong time'); - } catch (PHPUnit_Framework_Error_Notice $e) { - $this->assertTrue(true); - } - EE_System::instance()->load_core_configuration(); - $this->assertArrayDoesNotContain('EEM_Mock', EE_Registry::instance()->non_abstract_db_models); - $this->assertArrayDoesNotContain('EEM_Mock', EE_Registry::instance()->models); - } - - - - function test_register_mock_addon_fail__bad_parameters() - { - //we're registering the addon with the wrong parameters - $this->_pretend_addon_hook_time(); - $this->assertArrayDoesNotContain('EEM_Mock', EE_Registry::instance()->non_abstract_db_models); - $this->assertArrayDoesNotContain('EEM_Mock', EE_Registry::instance()->models); - try { - EE_Register_Model::register($this->_model_group, array( - 'foobar' => '1.0.0', - 'model_paths' => EE_MOCKS_DIR . 'core/db_models', - 'class_paths' => EE_MOCKS_DIR . 'core/db_classes', - )); - $this->fail('We should have received a warning that the \'plugin_main_file\' is a required argument when registerign an addon'); - } catch (EE_Error $e) { - $this->assertTrue(true); - } - EE_System::instance()->load_core_configuration(); - //check that we didn't actually register the addon - $this->assertArrayDoesNotContain('EEM_Mock', EE_Registry::instance()->non_abstract_db_models); - $this->assertArrayDoesNotContain('EEM_Mock', EE_Registry::instance()->models); - } - - - - function test_register_mock_addon_success() - { - $this->_pretend_addon_hook_time(); - $this->assertArrayDoesNotContain('EEM_Mock', EE_Registry::instance()->non_abstract_db_models); - $this->assertArrayDoesNotContain('EEM_Mock', EE_Registry::instance()->models); - //register it for realz - EE_Register_Model::register($this->_model_group, $this->_reg_args); - EE_System::instance()->load_core_configuration(); - $this->assertArrayContains('EEM_Mock', EE_Registry::instance()->non_abstract_db_models); - $this->assertArrayContains('EEM_Mock', EE_Registry::instance()->models); - //now deregister it - EE_Register_Model::deregister($this->_model_group); - EE_System::instance()->load_core_configuration(); - $this->assertArrayDoesNotContain('EEM_Mock', EE_Registry::instance()->non_abstract_db_models); - $this->assertArrayDoesNotContain('EEM_Mock', EE_Registry::instance()->models); - } - - - - public function tearDown() - { - //ensure the models aren't stil registered. they should have either been - //deregistered during the test, or not been registered at all - $this->assertArrayDoesNotContain('EEM_Mock', EE_Registry::instance()->non_abstract_db_models); - $this->assertArrayDoesNotContain('EEM_Mock', EE_Registry::instance()->models); - $this->_stop_pretending_addon_hook_time(); - parent::tearDown(); - } -} - -// End of file EE_Register_Model_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/plugin_api/EE_Register_Payment_Method_Test.php b/tests/testcases/core/libraries/plugin_api/EE_Register_Payment_Method_Test.php deleted file mode 100644 index 8cb892e8416..00000000000 --- a/tests/testcases/core/libraries/plugin_api/EE_Register_Payment_Method_Test.php +++ /dev/null @@ -1,79 +0,0 @@ -_pmt_args = array( - 'payment_method_paths' => - array( - EE_TESTS_DIR . 'mocks' . DS . 'payment_methods' . DS . 'Mock_Onsite', - ), - ); - $this->_pmt_name = 'Mock_Onsite'; - $this->payment_method_manager = LoaderFactory::getLoader()->getShared('EE_Payment_Method_Manager'); - } - - - public function tearDown() - { - parent::tearDown(); - $this->_pmt_args = null; - $this->_pmt_name = null; - $this->payment_method_manager = null; - } - - public function test_register__fail() - { - $this->_stop_pretending_addon_hook_time(); - remove_all_filters('FHEE__EE_Payment_Method_Manager__register_payment_methods__payment_methods_to_register'); - - //first verify it doesn't already exists - $pmt_exists = $this->payment_method_manager->payment_method_type_exists($this->_pmt_name); - $this->assertFalse($pmt_exists); - - //try registering at wrong time - try { - EE_Register_Payment_Method::register($this->_pmt_name, $this->_pmt_args); - $this->fail('We should have had a warning saying that we are setting up the payment methods at the wrong time'); - } catch (PHPUnit_Framework_Error_Notice $e) { - $this->assertTrue(true); - } - } - - public function test_register__success() - { - $this->_pretend_addon_hook_time(); - //double-check no one else is filtering payment method types - remove_all_filters('FHEE__EE_Payment_Method_Manager__register_payment_methods__payment_methods_to_register'); - - //first verify it doesn't already exists - $pmt_exists = $this->payment_method_manager->payment_method_type_exists($this->_pmt_name); - $this->assertFalse($pmt_exists); - - - EE_Register_Payment_Method::register($this->_pmt_name, $this->_pmt_args); - //now check it does exist - $pmt_exists = EE_Payment_Method_Manager::instance()->payment_method_type_exists($this->_pmt_name, true); - $this->assertTrue($pmt_exists); - } -} diff --git a/tests/testcases/core/libraries/rest_api/Capabilities_Test.php b/tests/testcases/core/libraries/rest_api/Capabilities_Test.php deleted file mode 100644 index 97314f3ac88..00000000000 --- a/tests/testcases/core/libraries/rest_api/Capabilities_Test.php +++ /dev/null @@ -1,81 +0,0 @@ -markTestSkipped( - 'Test being run on a version of WP that does not have the REST framework installed' - ); - } - } - - - - /** - * Ensures we can correctly detect when users have partial access - */ - function test_current_user_has_partial_access_to() { - //yes - they can access some generally - //the user has free access to prices - $this->assertTrue( Capabilities::currentUserHasPartialAccessTo( \EE_Registry::instance()->load_model( 'Price' ) ) ); - //although there are some restrictions, the current user can access SOME events - $this->assertTrue( Capabilities::currentUserHasPartialAccessTo( \EE_Registry::instance()->load_model( 'Event' ) ) ); - //yes - they can access this field specifically sometimes - $this->assertTrue( Capabilities::currentUserHasPartialAccessTo( \EE_Registry::instance()->load_model( 'Event' ), \EEM_Base::caps_read, 'EVT_wp_user' ) ); - //no - no they can never access it - } - - /** - * Makes sure that we are able to filter out inaccessible items in the entity correctly - * (and that related items taht are included are left as-is) - * @group now - */ - function test_filter_out_inaccessible_entity_fields() { - $e = $this->new_model_obj_with_dependencies( 'Event' ); - $entity = $e->model_field_array(); - $entity[ 'datetimes' ] = array( array( 'DTT_ID' => 12 ) ); - $filtered_entity = Capabilities::filterOutInaccessibleEntityFields( - $entity, - \EE_Registry::instance()->load_model( 'Event' ), - \EEM_Base::caps_read, - new ModelVersionInfo( '4.8.29' ) - ); - //the filtered entity shouldn't have had EVT_desc raw - $this->assertFalse( - isset( $filtered_entity['EVT_desc'] ) - && is_array( $filtered_entity['EVT_desc'] ) - && isset( $filtered_entity['EVT_desc']['raw'] ) - ); - //the filtered entity should have had EVT_desc rendered - $this->assertFalse( - isset( $filtered_entity['EVT_desc'] ) - && is_array( $filtered_entity['EVT_desc'] ) - &&isset( $filtered_entity['EVT_desc']['rendered'] ) - ); - } - - /** - * placeholder because other tests have been at least temporarily removed - */ - function test_nothing(){ - $this->assertTrue(true); - } -} - -// End of file EE_REST_API_Capabilities_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/rest_api/ModelDataTranslatorTest.php b/tests/testcases/core/libraries/rest_api/ModelDataTranslatorTest.php deleted file mode 100644 index 96ffc209e9f..00000000000 --- a/tests/testcases/core/libraries/rest_api/ModelDataTranslatorTest.php +++ /dev/null @@ -1,889 +0,0 @@ -assertEquals( - $expected_unixtimestamp, - ModelDataTranslator::prepareFieldValueFromJson( - new EE_Datetime_Field( - 'post_date', - esc_html__('Date/Time Event Created', 'event_espresso'), - false, - EE_Datetime_Field::now - ), - $timestamp, - '4.8.36', - $timezone_string - ) - ); - } - - - /** - * @dataProvider invalidTimestampDataProvider - * @expectedException EventEspresso\core\libraries\rest_api\RestException - * @expectedExceptionCode 400 - * @throws DomainException - * @throws EE_Error - * @throws InvalidArgumentException - * @throws RestException - * @throws Exception - * @group 11368 - */ - public function testIncomingInvalidTimestamp($timestamp, $timezone) - { - ModelDataTranslator::prepareFieldValueFromJson( - new EE_Datetime_Field( - 'post_date', - esc_html__('Date/Time Event Created', 'event_espresso'), - false, - EE_Datetime_Field::now - ), - $timestamp, - $timezone - ); - } - - - public function testPrepareQueryParamsForRestApi() - { - $mysql_date = '2015-01-01 00:00:00'; - $statuses_in_query = array( - EEM_Registration::status_id_cancelled, - EEM_Registration::status_id_declined, - ); - $model_query = array( - array( - 'STS_ID' => array( - 'IN', - $statuses_in_query, - ), - 'REG_date' => strtotime($mysql_date), - 'REG_deleted' => false, - ), - 'limit' => 10, - ); - $rest_query = ModelDataTranslator::prepareQueryParamsForRestApi($model_query, EEM_Registration::instance()); - //assert the reg date matches and is in the right format - $this->assertArrayHasKey('where', $rest_query); - $this->assertArrayHasKey('REG_date', $rest_query['where']); - $this->assertEquals(strtotime($mysql_date), rest_parse_date($rest_query['where']['REG_date'])); - //assert statuses got translated - $this->assertArrayHasKey('STS_ID', $rest_query['where']); - $this->assertEquals($statuses_in_query, $rest_query['where']['STS_ID'][1]); - //assert limit got translated - $this->assertArrayHasKey('limit', $rest_query); - $this->assertEquals(10, (int)$rest_query['limit']); - //assert booleans correctly translated - $this->assertArrayHasKey('REG_deleted', $rest_query['where']); - $this->assertEquals(false, $rest_query['where']['REG_deleted']); - } - - - - /** - * Verifies prepare_conditions_query_params_for_models works properly, - * especially with datetimes which can be in UTC or local time - */ - public function testPrepareConditionsQueryParamsForModels__gmtDatetimes() - { - $data_translator = new ModelDataTranslator(); - $gmt_offsets = array(-12, -10.5, -9, -7.5, -6, -4.5, -3, -1.5, 0, 1.5, 3, 4.5, 6, 7.5, 9, 10.5, 12); - foreach ($gmt_offsets as $gmt_offset) { - //set the offset - update_option('gmt_offset', $gmt_offset); - //set the current time from our timezone helper to more closely mimic how dates and times pass through our - //model. We can't use WP's `current_time` because wp ALWAYS uses offset directly if its present whereas EE - //tries to coerce a closest matching timezone string for "invalid" offsets (PHP version < 5.6). - $datetime = new DateTime('now', new DateTimeZone( - EEH_DTT_Helper::get_timezone_string_from_gmt_offset($gmt_offset) - )); - $now_local_time = $datetime->format(EE_Datetime_Field::mysql_timestamp_format); - $now_utc_time = current_time('mysql', true); - //should always be not equal except when offset is 0 - if ($gmt_offset !== 0) { - $this->assertNotEquals($now_local_time, $now_utc_time, sprintf('For gmt offset %d', $gmt_offset)); - } else { - $this->assertEquals($now_local_time, $now_utc_time); - } - $model_data = $data_translator::prepareConditionsQueryParamsForModels( - array( - 'EVT_created' => mysql_to_rfc3339($now_local_time), - 'EVT_modified_gmt' => mysql_to_rfc3339($now_utc_time), - ), - \EEM_Event::instance(), - '4.8.36' - ); - //verify the model data being inputted is in UTC - $this->assertDateWithinOneMinute($now_utc_time, date('Y-m-d H:i:s', $model_data['EVT_created']), 'Y-m-d H:i:s'); - //NOT in local time - $this->assertNotEquals( - $now_local_time, - $model_data['EVT_created'], - sprintf('For gmt offset %d', $gmt_offset) - ); - //notice that there's no "_gmt" on EVT_modified. That's (currently at least) - //not a real model field. It just indicates to treat the time already being in UTC - $this->assertEquals($now_utc_time, date('Y-m-d H:i:s', $model_data['EVT_modified'])); - } - } - - - - public function testIsGmtDateFieldName__success() - { - $this->assertTrue(ModelDataTranslator::isGmtDateFieldName('Event.EVT_created_gmt')); - } - - - - public function testIsGmtDateFieldName__fail() - { - $this->assertFalse(ModelDataTranslator::isGmtDateFieldName('Event.EVT_created')); - } - - - - public function testIsGmtDateFieldName__failTinyInput() - { - $this->assertFalse(ModelDataTranslator::isGmtDateFieldName('foo')); - } - - - - public function testRemoveGmtFromFieldName() - { - $this->assertEquals( - 'Event.EVT_created', - ModelDataTranslator::removeGmtFromFieldName('Event.EVT_created_gmt')); - } - - - - public function testRemoveGmtFromFieldName__noGmtAnyways() - { - $this->assertEquals( - 'Event.EVT_created', - ModelDataTranslator::removeGmtFromFieldName('Event.EVT_created')); - } - - - - /** - * @return array first item is the expected value, 2nd is the input, 3rd is the field object to use - */ - public function dataProviderForTestPrepareFieldValueFromJsonOk() - { - $serialized_field = new EE_Maybe_Serialized_Simple_HTML_Field('whatever', 'Whatever', true); - return array( - array('1', '1', $serialized_field), - array('stringy', 'stringy', $serialized_field), - array(array('foo' => 'bar'), array('foo' => 'bar'), $serialized_field), - ); - } - - - - /** - * @dataProvider dataProviderForTestPrepareFieldValueFromJsonOk - * @param mixed $expected_result - * @param mixed $inputted_json_value - * @param EE_Model_Field_Base $field_obj - * @group 9222 - */ - public function testPrepareFieldValueFromJsonOk( - $expected_result, - $inputted_json_value, - EE_Model_Field_Base $field_obj - ) { - $this->assertEquals( - $expected_result, - ModelDataTranslator::prepareFieldValueFromJson( - $field_obj, - $inputted_json_value, - '4.8.36' - ) - ); - } - - - - /** - * @return array where the first item is value that would be retrieved from the request which should throw an - * exception. The 2nd item is an EE_Model_Field_Base child - */ - public function dataProviderForTestPrepareFieldValueFromJsonBad() - { - $serializable_field = new EE_Maybe_Serialized_Simple_HTML_Field('whatever', 'Whatever', true); - $serializable_field->_construct_finalize('Foobar', 'test_serialized_field','Foobar'); - $text_field = new EE_Plain_Text_Field('whatever', 'whatever', true); - $text_field->_construct_finalize('Foobar', 'test_text_field','Foobar'); - return array( - array('s:6:"foobar";', $serializable_field),//that's a serialized string alright! - array('O:4:"Evil":0:{}', $serializable_field),//that's a string with a serialized object of class "Evil" - array(array('s:6:"foobar";'), $serializable_field),//that's an array with a serialized string in it - array(array('s:6:"foobar";' => 1), $serializable_field),//that's an array with a serialized string as a key - array('O:4:"Evil":0:{}', $text_field),//double-check we don't even accept serialized text even on normal - // text fields. Theoretically these won't get unserialized, but I don't see much need for anyone to ever - // submit this kind of malicious junk, and having them sit around in our DB is dangerous - array( - array( - 'error_code' => 'php_object_not_return', - 'error_message' => esc_html__( - 'The value of this field in the database is a PHP object, which can\'t be represented in JSON.', - 'event_espresso' - ) - ), - $serializable_field - ) - ); - } - - - - /** - * @dataProvider dataProviderForTestPrepareFieldValueFromJsonBad - * @expectedException EventEspresso\core\libraries\rest_api\RestException - * @param mixed $expected_result - * @param mixed $inputted_json_value - * @param EE_Model_Field_Base $field_obj - * @group 9222 - */ - public function testPrepareFieldValueFromJsonBad($inputted_json_value, EE_Model_Field_Base $field_obj) - { - //ok duck and cover! It's gonna blow! - ModelDataTranslator::prepareFieldValueFromJson($field_obj, $inputted_json_value, '4.8.36'); - } - - - - /** - * @return array 1st item is the expected value, 2nd is the input, 3rd is the field object to use - */ - public function dataProviderForTestPrepareFieldValuesForJson() - { - //if we don't have the WP API infrastructure, return a dummy array - //it doesn't have to work because all the tests will be skipped too - if ( ! class_exists( 'WP_Rest_Request' ) ) { - return array( - array() - ); - } - $field = new EE_Maybe_Serialized_Simple_HTML_Field('whatever', 'whatever', true); - $datetime_field = new EE_Datetime_Field('whatever2', 'whatever2', true, EE_Datetime_Field::now); - $error_response = array( - 'error_code' => 'php_object_not_return', - 'error_message' => esc_html__( - 'The value of this field in the database is a PHP object, which can\'t be represented in JSON.', - 'event_espresso' - ) - ); - $datetime_field_obj = EE_Registry::instance()->load_model('Datetime')->field_settings_for('DTT_EVT_start'); - return array( - array( - array('foo' => 'bar'), - array('foo' => 'bar'), - $field) - , - array( - 1, - 1, - $field - ), - array( - 'stringy', - 'stringy', - $field - ), - array( - '2016-01-03T00:00:00', - new \EventEspresso\core\domain\entities\DbSafeDateTime( - '2016-01-03 00:00:00', - new DateTimeZone('UTC') - ), - $datetime_field, - ), - array( - $error_response, - new stdClass(), - $field - ), - array( - array('obj' => $error_response), - array('obj' => new stdClass()), - $field - ), - array( - $error_response, - @unserialize('O:6:"Foobar":0:{}'), - $field - ), - 'datetime_object_in_default_timezone' => array( - mysql_to_rfc3339(current_time('mysql')), - new DateTime('now'), - $datetime_field_obj, - ), - 'unix_timestamp_in_default_timezone' => array( - mysql_to_rfc3339(date(EE_Datetime_Field::mysql_timestamp_format, 946782245)), - 946782245, - $datetime_field_obj, - ), - 'unix_timestamp_STRING_in_default_timezone' => array( - mysql_to_rfc3339(date(EE_Datetime_Field::mysql_timestamp_format, 946782245)), - '946782245', - $datetime_field_obj, - ), - 'unix_timestamp_FLOAT_in_default_timezone' => array( - mysql_to_rfc3339(date(EE_Datetime_Field::mysql_timestamp_format, 946782245)), - (float)946782245, - $datetime_field_obj, - ), - 'null_datetime' => array( - '', - null, - $datetime_field_obj, - ), - 'mysql_in_default_timezone' => array( - mysql_to_rfc3339('2000-01-02 03:04:05'), - '2000-01-02 03:04:05', - $datetime_field_obj, - ), - 'datetime_object_in_different_timezone' => array( - mysql_to_rfc3339('2000-01-02 03:04:05'), - new DateTime('2000-01-02 03:04:05', new DateTimeZone('America/Vancouver')), - $datetime_field_obj, - 'America/Vancouver', - ), - //the input is a unix timestamp (in GMT) - //the result should be a RFC3339 string also in GMT - 'unix_timestamp_in_different_timezone' => array( - mysql_to_rfc3339('2000-01-02 03:04:05'), - 946782245, - $datetime_field_obj, - 'America/Vancouver', - ), - //so the input is for 3am Vancouver time, and the output should be too - 'mysql_datetime_in_different_timezone' => array( - mysql_to_rfc3339('2000-01-02 03:04:05'), - '2000-01-02 3:04:05', - $datetime_field_obj, - 'America/Vancouver', - ), - ); - } - - - - /** - * @group 9222 - * @dataProvider dataProviderForTestPrepareFieldValuesForJson - * @param $expected - * @param $input - * @param EE_Model_Field_Base $field_obj - */ - public function testPrepareFieldValuesForJson($expected, $input, $field_obj) - { - if ($field_obj instanceof EE_DateTime_Field && ! empty($expected)) { - $this->assertDateWithinOneMinute( - $expected, - ModelDataTranslator::prepareFieldValuesForJson($field_obj, $input, '4.8.36'), - 'Y-m-d\TH:i:s' - ); - } else { - $this->assertEquals( - $expected, - ModelDataTranslator::prepareFieldValuesForJson($field_obj, $input, '4.8.36') - ); - } - } - - - - /** - * @return array { - * @type array $0 input - * @type string $1 the model's name - * @type boolean $2 whether to consider this data as if it's being used for writing, or not - */ - public function dataProviderForTestPrepareConditionsQueryParamsForModelsBad() - { - return array( - //case 0: array isn't numerically indexed - array( - array( - 'EVT_ID' => array( - 'what_is_this_key_doing_here' => 'its_borked' - ) - ), - 'Event', - false - ), - //case 1: invalid key while reading - array( - array( - 'invalid_key' => 'whatever' - ), - 'Event', - false - ), - //case 2: invalid key while writing - array( - array( - 'invalid_key' => 'whatever' - ), - 'Registration', - true - ), - //case 3: logic parameter while writing - array( - array( - 'OR' => array( - 'EVT_name' => 'party' - ) - ), - 'Event', - true - ), - //case 4: nested invalid key while reading - array( - array( - 'or*allyourbase' => array( - 'EVT_ID' => 123, - 'invalid_nested_key' => 'foobar' - ) - ), - 'Event', - false - ), - //case 5: too few arguments for in operator - array( - array( - 'EVT_ID' => array('IN') - ), - 'Event', - false - ), - //case 6: too many arguments for in operator - array( - array( - 'EVT_ID' => array('IN', array('thingy'),'what_is_this_doing_here') - ), - 'Event', - false - ), - //case 7: too few arguments for between operator - array( - array( - 'EVT_created' => array( - 'BETWEEN', - '2017-01-01T00:00:00' - ) - ), - 'Event', - false - ), - //case 8: too many arguments for between operator - array( - array( - 'EVT_created' => array( - 'between', - '2017-01-01T00:00:00', - '2018-01-01T00:00:00', - 'extra_junk' - ) - ), - 'Event', - false - ), - //case 9: too few arguments for like operator - array( - array( - 'EVT_name' => array( - 'LIKE' - ) - ), - 'Event', - false - ), - //case 10: too many arguments for like operator - array( - array( - 'EVT_name' => array( - 'LIKE', - 'foobar', - 'something_extra' - ) - ), - 'Event', - false - ), - //case 11: too few arguments for normal operator - array( - array( - 'EVT_ID' => array( - '>' - ) - ), - 'Event', - false - ), - //case 12: too many arguments for normal operator - array( - array( - 'EVT_ID' => array( - '<', - 123, - 23452343 - ) - ), - 'Event', - false - ), - //case 13: too many arguments for null operator - array( - array( - 'EVT_ID' => array( - 'IS_NULL', - 'what_is_this_extra_arg' - ) - ), - 'Event', - false - ) - ); - } - - - - /** - * @param array $input array of data sent to REST API - * @param string $model_name eg 'Event' - * @param boolean $writing - * @group 9222 - * @dataProvider dataProviderForTestPrepareConditionsQueryParamsForModelsBad - * @expectedException EventEspresso\core\libraries\rest_api\RestException - */ - public function testPrepareConditionsQueryParamsForModelsBad($input, $model_name, $writing) - { - $model = EE_Registry::instance()->load_model($model_name); - //run for cover! it's going to error! - ModelDataTranslator::prepareConditionsQueryParamsForModels( - $input, - $model, - '4.8.36', - $writing - ); - } - - - - /** - * @return array { - * @type array $0 expected output - * @type array $1 input - * @type string $2 model name, eg 'Event' - * @type boolean $3 whether it's data for writing, or just conditions - */ - public function dataProviderForTestPrepareConditionsQueryParamsForModelsGood() - { - if( ! function_exists('rest_parse_date')){ - return array(); - } - return array( - //reading-style tests - //case 0: empty - array( - array(), - array(), - 'Event', - false - ), - //case 1: simple - array( - array('EVT_name' => 'foobar'), - array('EVT_name' => 'foobar'), - 'Event', - false - ), - //case 2: with nested logic - array( - array( - 'or' => array( - 'EVT_desc' => 'foobar', - 'EVT_short_desc' => 'foobar' - ), - 'NOT*' => array( - 'EVT_name' => 'foobar' - ) - ), - array( - 'or' => array( - 'EVT_desc' => 'foobar', - 'EVT_short_desc' => 'foobar' - ), - 'NOT*' => array( - 'EVT_name' => 'foobar' - ) - ), - 'Event', - false - ), - //case 3: with a between operator - array( - array( - 'EVT_created' => array( - 'between', - rest_parse_date('2015-01-01 00:00:00'), - rest_parse_date('2016-01-01 00:00:00') - ) - ), - array( - 'EVT_created' => array( - 'between', - '2015-01-01T00:00:00', - '2016-01-01T00:00:00' - ) - ), - 'Event', - false - ), - //case 4: with an "in" operator - array( - array( - 'TKT_uses' => array( - 'IN', - array( - 12, - 13, - EE_INF - ) - ) - ), - array( - 'TKT_uses' => array( - 'IN', - array( - '12', - '13', - '' - ) - ) - ), - 'Ticket', - false - ), - //case 5: with a "like" operator - array( - array( - 'PAY_details' => array( - 'LIKE', - '%foobar%' - ) - ), - array( - 'PAY_details' => array( - 'LIKE', - '%foobar%' - ) - ), - 'Payment', - false - ), - //case 6: with a "null" operator - array( - array( - 'EVT_name' => array('IS_NULL') - ), - array( - 'EVT_name' => array('IS_NULL') - ), - 'Event', - false - ), - //case 7: with various other operators - array( - array( - 'RPY_amount' => array( - '<', - 19 - ), - 'REG_ID' => array( - '!=', - 12 - ), - ), - array( - 'RPY_amount' => array( - '<', - '19' - ), - 'REG_ID' => array( - '!=', - '12' - ), - ), - 'Registration_Payment', - false - ), - //case 8: using related fields - array( - array( - 'Ticket.Datetime.DTT_reg_limit' => 12 - ), - array( - 'Ticket.Datetime.DTT_reg_limit' => '12' - ), - 'Registration', - false - ), - //writing-style tests - //case 8: with valid fields - array( - array( - 'TKT_uses' => EE_INF - ), - array( - 'TKT_uses' => '' - ), - 'Ticket', - true - ) - ); - } - - /** - * @param array $expected_output - * @param array $input array of data sent to REST API - * @param string $model_name eg 'Event' - * @param boolean $writing - * @group 9222 - * @dataProvider dataProviderForTestPrepareConditionsQueryParamsForModelsGood - */ - public function testPrepareConditionsQueryParamsForModelsGood( - $expected_output, - $input, - $model_name, - $writing - ) { - $model = EE_Registry::instance()->load_model($model_name); - $this->assertEquals( - $expected_output, - ModelDataTranslator::prepareConditionsQueryParamsForModels( - $input, - $model, - '4.8.36', - $writing - ) - ); - } - - /** - * Reproduced issue https://events.codebasehq.com/projects/event-espresso/tickets/10869 - * and https://events.codebasehq.com/projects/event-espresso/tickets/10858 by changing - * the site date format to 'd/m/Y' - */ - public function testPrepareFieldValueForJsonUnusualDateFormat(){ - $field_obj = EE_Registry::instance()->load_model('Datetime')->field_settings_for('DTT_EVT_start'); - if($field_obj instanceof EE_Datetime_Field){ - //change the date format because it used to make this not work - $field_obj->set_date_format('d/m/Y'); - //the default time format excludes seconds, - $field_obj->set_time_format('g:i a s'); - } - $current_time_mysql = current_time('mysql'); - $datetime = new DateTime( $current_time_mysql ); - $formats = EE_Registry::instance()->load_model('Datetime')->get_formats_for('DTT_EVT_start'); - $date_in_site_format = $datetime->format(implode(' ', $formats)); - $this->assertEquals( - mysql_to_rfc3339($current_time_mysql), - ModelDataTranslator::prepareFieldValueForJson( - $field_obj, - $date_in_site_format, - '4.8.36' - ) - ); - } - - - - /** - * If you pass in an empty string, it's the same as using the current time in the field's timezone - * @group 10869 - */ - public function testPrepareFieldValueForJsonPassingInEmptyString(){ - $field_obj = EE_Registry::instance()->load_model('Datetime')->field_settings_for('DTT_EVT_start'); - $field_obj->set_timezone('America/Vancouver'); - update_option('timezone_string', 'America/Vancouver'); - $this->assertDateWithinOneMinute( - mysql_to_rfc3339(current_time('mysql'), false), - ModelDataTranslator::prepareFieldValueForJson( - $field_obj, - '', - '4.8.36' - ), - 'Y-m-d\TH:i:s' - ); - } - -} - -// Location: tests/testcases/core/libraries/rest_api/ModelDataTranslator_Test.php diff --git a/tests/testcases/core/libraries/rest_api/Model_Version_Info_Test.php b/tests/testcases/core/libraries/rest_api/Model_Version_Info_Test.php deleted file mode 100644 index d8e0571fd9a..00000000000 --- a/tests/testcases/core/libraries/rest_api/Model_Version_Info_Test.php +++ /dev/null @@ -1,91 +0,0 @@ -markTestSkipped( - 'Test being run on a version of WP that does not have the REST framework installed' - ); - } - } - - /** - * pretend currently we're on 4.9, but they send in a request for 4.8. So this - * shoudl return all the changes from 4.9 - */ - function test_get_all_model_changes_between_requested_version_and_current__req_46_cur_49() { - $this->_pretend_current_version_49(); - $model_info = new ModelVersionInfo( '4.8.29' ); - $changes = $model_info->modelChangesBetweenRequestedVersionAndCurrent(); - $this->assertArrayNotHasKey( '4.8.29', $changes ); - } - - /** - * @group ignore - * needs to be updated once there is a new field added - */ - function test_fields_on_model_in_this_version__no_reg_paid_in_46() { - $this->_pretend_added_field_onto_registration_model(); - $this->_pretend_current_version_49(); - $model_info = new ModelVersionInfo( '4.6' ); - $fields_on_reg = $model_info->fieldsOnModelInThisVersion( \EEM_Registration::instance() ); - $this->assertArrayNotHasKey( 'REG_paid', $fields_on_reg ); - } - - /** - * @group ignore - * needs to be updated once there is a new field added - */ - function test_fields_on_model_in_this_version__has_reg_paid_in_47() { - $this->_pretend_added_field_onto_registration_model(); - $this->_pretend_current_version_49(); - $model_info = new ModelVersionInfo( '4.7' ); - $fields_on_reg = $model_info->fieldsOnModelInThisVersion( \EEM_Registration::instance() ); - $this->assertArrayHasKey( 'REG_paid', $fields_on_reg ); - } - - protected function _pretend_current_version_49(){ - add_filter( 'FHEE__EED_Core_REST_API__core_version', array( $this, '_tell_EED_Core_REST_API_current_version_is_49' ) ); - } - - /** - * Used on a filter to make the API think core's version is 4.8 - * @param type $current_version - * @return string - */ - public function _tell_EED_Core_REST_API_current_version_is_49( $current_version ) { - return '4.9.2'; - } - - protected function _pretend_added_field_onto_registration_model(){ - add_filter( 'FHEE__EEM_Registration__construct__fields', array( $this, '_add_reg_paid_field' ) ); - \EEM_Registration::reset(); - } - - public function _add_reg_paid_field( $reg_fields ) { - if( ! isset( $reg_fields[ 'Registration'][ 'REG_paid' ] ) ) { - $reg_fields[ 'Registration'][ 'REG_paid' ] = new \EE_Money_Field( 'REG_paid', __( 'Amount paid for registration', 'event_espresso' ), true ); - } - return $reg_fields; - } -} - -// End of file EE_REST_API_Model_Version_Info_Test.php \ No newline at end of file diff --git a/tests/testcases/core/libraries/rest_api/controllers/Checkin_Test.php b/tests/testcases/core/libraries/rest_api/controllers/Checkin_Test.php deleted file mode 100644 index 508a15cd7e0..00000000000 --- a/tests/testcases/core/libraries/rest_api/controllers/Checkin_Test.php +++ /dev/null @@ -1,194 +0,0 @@ -markTestSkipped( - 'Test being run on a version of WP that does not have the REST framework installed' - ); - } - } - - - - - /* - * we're doing stuff that we know will add error notices, so we don't care - * if there are errors (that's part of these tests) - */ - public function tearDown() - { - \EE_Error::reset_notices(); - parent::tearDown(); - } - - - - - /** - * @param int $reg_id - * @param int $dtt_id - * @return \WP_REST_Request - */ - protected function _create_checkin_request($reg_id, $dtt_id) - { - $req = new \WP_REST_Request( - 'POST', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.33/registrations/' . $reg_id . '/toggle_checkin_for_datetime/' . $dtt_id - ); - $req->set_url_params( - array( - 'REG_ID' => $reg_id, - 'DTT_ID' => $dtt_id, - ) - ); - $req->set_body_params( - array( - 'force' => "false", - ) - ); - return $req; - } - - - - - public function test_handle_checkin__success() - { - $checkins_before = \EEM_Checkin::instance()->count(); - global $current_user; - $current_user = $this->wp_admin_with_ee_caps(); - $reg = $this->new_model_obj_with_dependencies('Registration', array('STS_ID' => \EEM_Registration::status_id_approved)); - $dtt = $this->new_model_obj_with_dependencies('Datetime'); - $dtt->_add_relation_to($reg->get('TKT_ID'), 'Ticket'); - $response = rest_do_request($this->_create_checkin_request($reg->ID(), $dtt->ID())); - $data = $response->get_data(); - - - $this->assertEquals($checkins_before + 1, \EEM_Checkin::instance()->count()); - - $this->assertTrue(isset($data['CHK_ID'])); - $checkin_obj = \EEM_Checkin::instance()->get_one_by_ID($data['CHK_ID']); - $this->assertEquals($reg->ID(), $checkin_obj->get('REG_ID')); - $this->assertEquals($dtt->ID(), $checkin_obj->get('DTT_ID')); - $this->assertEquals(true, $data['CHK_in']); - $this->assertDateWithinOneMinute( - mysql_to_rfc3339(date('c')), - $data['CHK_timestamp'], - 'Y-m-d\TH:m:i+' - ); - } - - - - - public function test_handle_checkin__fail_not_approved() - { - $checkins_before = \EEM_Checkin::instance()->count(); - global $current_user; - $current_user = $this->wp_admin_with_ee_caps(); - $reg = $this->new_model_obj_with_dependencies('Registration', array('STS_ID' => \EEM_Registration::status_id_incomplete)); - $dtt = $this->new_model_obj_with_dependencies('Datetime'); - $dtt->_add_relation_to($reg->get('TKT_ID'), 'Ticket'); - $response = rest_do_request($this->_create_checkin_request($reg->ID(), $dtt->ID())); - $this->assertEquals($checkins_before, \EEM_Checkin::instance()->count()); - $data = $response->get_data(); - $this->assertTrue(isset($data['code'])); - $this->assertEquals('rest_toggle_checkin_failed', $data['code']); - $this->assertTrue(isset($data['additional_errors'])); - $this->assertFalse(empty($data['additional_errors'][0]['message'])); - } - - - - - //doesnt have permission - public function test_handle_checkin__fail_no_permitted() - { - //notice that we have NOT logged in! - $checkins_before = \EEM_Checkin::instance()->count(); - $reg = $this->new_model_obj_with_dependencies('Registration', array('STS_ID' => \EEM_Registration::status_id_incomplete)); - $dtt = $this->new_model_obj_with_dependencies('Datetime'); - $dtt->_add_relation_to($reg->get('TKT_ID'), 'Ticket'); - $response = rest_do_request($this->_create_checkin_request($reg->ID(), $dtt->ID())); - $this->assertEquals($checkins_before, \EEM_Checkin::instance()->count()); - $data = $response->get_data(); - $this->assertTrue(isset($data['code'])); - $this->assertEquals('rest_user_cannot_toggle_checkin', $data['code']); - } - - - - - //regsitered too many times - public function test_handle_checkin__fail_checked_in_too_many_times() - { - global $current_user; - $current_user = $this->wp_admin_with_ee_caps(); - $tkt = $this->new_model_obj_with_dependencies('Ticket', array('TKT_uses' => 1)); - $reg = $this->new_model_obj_with_dependencies( - 'Registration', - array( - 'STS_ID' => \EEM_Registration::status_id_approved, - 'TKT_ID' => $tkt->ID(), - ) - ); - $dtt = $this->new_model_obj_with_dependencies('Datetime'); - $dtt->_add_relation_to($reg->get('TKT_ID'), 'Ticket'); - $dtt2 = $this->new_model_obj_with_dependencies('Datetime'); - $dtt2->_add_relation_to($reg->get('TKT_ID'), 'Ticket'); - //create a previous checkin entry, so the reg shouldn't be allowed to checkin more - $old_checkin = $this->new_model_obj_with_dependencies( - 'Checkin', - array( - 'REG_ID' => $reg->ID(), - 'DTT_ID' => $dtt->ID(), - 'CHK_in' => true, - ) - ); - $checkins_before = \EEM_Checkin::instance()->count(); - $response = rest_do_request($this->_create_checkin_request($reg->ID(), $dtt2->ID())); - $this->assertEquals($checkins_before, \EEM_Checkin::instance()->count()); - $data = $response->get_data(); - $this->assertTrue(isset($data['code'])); - $this->assertEquals('rest_toggle_checkin_failed_not_forceable', $data['code']); - $this->assertTrue(isset($data['additional_errors'])); - $this->assertFalse(empty($data['additional_errors'][0]['message'])); - } - - - - - //registered too many times but force it - public function test_handle_checkin__success_only_because_forced() - { - global $current_user; - $current_user = $this->wp_admin_with_ee_caps(); - $reg = $this->new_model_obj_with_dependencies( - 'Registration', - array( - 'STS_ID' => \EEM_Registration::status_id_cancelled, - ) - ); - $dtt = $this->new_model_obj_with_dependencies('Datetime'); - $dtt->_add_relation_to($reg->get('TKT_ID'), 'Ticket'); - $checkins_before = \EEM_Checkin::instance()->count(); - $req = $this->_create_checkin_request($reg->ID(), $dtt->ID()); - $req->set_body_params(array('force' => "true")); - $response = rest_do_request($req); - $this->assertEquals($checkins_before + 1, \EEM_Checkin::instance()->count()); - } -} - diff --git a/tests/testcases/core/libraries/rest_api/controllers/Config_Test.php b/tests/testcases/core/libraries/rest_api/controllers/Config_Test.php deleted file mode 100644 index 880f7ee54b1..00000000000 --- a/tests/testcases/core/libraries/rest_api/controllers/Config_Test.php +++ /dev/null @@ -1,34 +0,0 @@ -admin->affiliate_id = 'star_wars'; - - global $current_user; - $current_user = $this->wp_admin_with_ee_caps(); - - $req = new WP_REST_Request( 'GET', '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/config'); - - $response = rest_do_request($req); - - $data = json_decode(wp_json_encode($response->get_data()),true); - $this->assertEquals(EE_Config::instance()->admin->affiliate_id, $data['admin']['affiliate_id'] ); - } - -} - diff --git a/tests/testcases/core/libraries/rest_api/controllers/Read_Test.php b/tests/testcases/core/libraries/rest_api/controllers/Read_Test.php deleted file mode 100644 index ccd52d873c6..00000000000 --- a/tests/testcases/core/libraries/rest_api/controllers/Read_Test.php +++ /dev/null @@ -1,1124 +0,0 @@ -setRequestedVersion('4.8.29'); - $this->assertEquals(array( - 'EVT_ID', - 'EVT_name', - ), $controller->explodeAndGetItemsPrefixedWith('EVT_ID,EVT_name', '')); - } - - - - public function test_explode_and_get_items_prefixed_with__extra_whitespace() - { - $controller = new Read(); - $controller->setRequestedVersion('4.8.29'); - $this->assertEquals(array( - 'EVT_ID', - 'EVT_name', - 'EVT_desc', - ), $controller->explodeAndGetItemsPrefixedWith('EVT_ID , EVT_name , EVT_desc', '')); - } - - - - public function test_explode_and_get_items_prefixed_with__related_model() - { - $controller = new Read(); - $controller->setRequestedVersion('4.8.29'); - $this->assertEquals(array(), $controller->explodeAndGetItemsPrefixedWith('Registration.*', '')); - } - - - - public function test_explode_and_get_items_prefixed_with__related_model_all() - { - $controller = new Read(); - $controller->setRequestedVersion('4.8.29'); - $this->assertEquals( - array( - '*', - ), - $controller->explodeAndGetItemsPrefixedWith('Registration.*', 'Registration') - ); - } - - - - public function test_explode_and_get_items_prefixed_with__related_models_but_searching_for_this_one() - { - $controller = new Read(); - $controller->setRequestedVersion('4.8.29'); - $this->assertEquals( - array(), - $controller->explodeAndGetItemsPrefixedWith('Registration.REG_ID, Registration.Attendee.ATT_ID', '') - ); - } - - - - public function test_explode_and_get_items_prefixed_with__related_models_but_searching_for_other() - { - $controller = new Read(); - $controller->setRequestedVersion('4.8.29'); - $this->assertEquals( - array( - 'REG_ID', - 'Attendee.ATT_ID', - ), - $controller->explodeAndGetItemsPrefixedWith('Registration.REG_ID, Registration.Attendee.ATT_ID', - 'Registration') - ); - } - - - - /** - * @group 10526 - */ - public function test_handle_request_get_one__event_includes() - { - $event = $this->new_model_obj_with_dependencies('Event', array('status' => 'publish')); - $req = new \WP_REST_Request('GET', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/events/' . $event->ID()); - $req->set_url_params( - array( - 'id' => $event->ID(), - ) - ); - $req->set_query_params( - array( - 'include' => 'EVT_ID,EVT_name', - ) - ); - $response = rest_do_request($req); - $result = $response->get_data(); - $this->assertEquals( - array( - 'EVT_ID' => $event->ID(), - 'EVT_name' => $event->name(), - ), - $result - ); - } - - - - /** - * Verifies 'featured_image_url' isn't added to all 4.8.29 requests. We had a bug introduced in 4.8.36 - * where requests to 4.8.29 added 'featured_image_url' all the time - * - * @group 10526 - */ - public function test_handle_request_get_one_4_8_29__event_includes() - { - $event = $this->new_model_obj_with_dependencies('Event', array('status' => 'publish')); - $req = new \WP_REST_Request('GET', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.29/events/' . $event->ID()); - $req->set_url_params( - array( - 'id' => $event->ID(), - ) - ); - $req->set_query_params( - array( - 'include' => 'EVT_ID,EVT_name', - ) - ); - $response = rest_do_request($req); - $result = $response->get_data(); - $this->assertEquals( - array( - 'EVT_ID' => $event->ID(), - 'EVT_name' => $event->name(), - ), - $result - ); - } - - - - public function test_handle_request_get_one__event_includes_two_related_models() - { - $event = $this->new_model_obj_with_dependencies('Event', array('status' => 'publish')); - $req = new \WP_REST_Request('GET', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/events/' . $event->ID()); - $req->set_url_params( - array( - 'id' => $event->ID(), - ) - ); - $req->set_query_params( - array( - 'include' => 'Venue,Datetime', - ) - ); - $response = rest_do_request($req); - $result = $response->get_data(); - //make sure we still included all the normal event fields - $this->assertArrayHasKey( - 'EVT_name', - $result - ); - $this->assertArrayHasKey( - 'datetimes', - $result - ); - $this->assertArrayHasKey( - 'venues', - $result - ); - } - - - - /** - * @group 10526 - */ - public function test_handle_request_get_one__event_include_non_model_field() - { - $this->authenticate_as_admin(); - $event = $this->new_model_obj_with_dependencies('Event'); - $req = new \WP_REST_Request('GET', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/events/' . $event->ID()); - $req->set_url_params( - array( - 'id' => $event->ID(), - ) - ); - $req->set_query_params( - array( - 'include' => 'EVT_desc', - ) - ); - $response = rest_do_request($req); - $result = $response->get_data(); - $this->assertEquals( - array( - 'EVT_ID' => $event->ID(), - 'EVT_desc' => array( - 'rendered' => $event->get_pretty('EVT_desc'), - 'raw' => $event->get('EVT_desc'), - ), - ), - $result - ); - } - - - - public function test_explode_and_get_items_prefixed_with__null() - { - $controller = new Read(); - $controller->setRequestedVersion('4.8.29'); - $this->assertEquals(array('*'), $controller->explodeAndGetItemsPrefixedWith('*', '')); - } - - - - /** - * @group 9406 - * @group 10976 - */ - public function test_handle_request_get_one__event_calculate_stuff() - { - $this->authenticate_as_admin(); - $limit_on_datetime = 100; - $limit_on_ticket = 50; - /** @var \EE_Event $event */ - $event = $this->new_model_obj_with_dependencies('Event'); - /** @var \EE_Datetime $dtt */ - $dtt = $this->new_model_obj_with_dependencies( - 'Datetime', - array( - 'DTT_reg_limit' => $limit_on_datetime, - 'EVT_ID' => $event->ID(), - 'DTT_sold' => 0, - 'DTT_reserved' => 0, - ) - ); - /** @var \EE_Ticket $tkt */ - $tkt = $this->new_model_obj_with_dependencies( - 'Ticket', - array( - 'TKT_qty' => $limit_on_ticket, - 'TKT_sold' => 0, - 'TKT_reserved' => 0, - ) - ); - $tkt->_add_relation_to($dtt, 'Datetime'); - /** @var \EE_Registration $registration */ - $registration = $this->new_model_obj_with_dependencies( - 'Registration', - array( - 'EVT_ID' => $event->ID(), - 'TKT_ID' => $tkt->ID(), - 'STS_ID' => \EEM_Registration::status_id_incomplete, - ) - ); - // NOW set status to approved which will increment the corresponding ticket and datetime sold values - $registration->set_status(\EEM_Registration::status_id_approved); - $registration->save(); - $this->assertEquals( - \EEM_Registration::status_id_approved, - $registration->status_ID() - ); - // also confirm relation to event - $this->assertEquals( - $event->ID(), - $registration->event_ID() - ); - $calculator = new EventSpacesCalculator($event); - $this->assertEquals( - $limit_on_ticket, - $calculator->totalSpacesAvailable(), - 'Testing REST API event for "Total Spaces Available"' - ); - $this->assertEquals( - $limit_on_ticket - 1, - $calculator->spacesRemaining(), - 'Testing REST API event for "Spaces Remaining"' - ); - $req = new \WP_REST_Request('GET', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/events/' . $event->ID()); - $req->set_url_params( - array( - 'id' => $event->ID(), - ) - ); - $req->set_query_params( - array( - 'include' => 'Datetime', - 'calculate' => 'optimum_sales_at_start,spots_taken,spaces_remaining,Datetime.registrations_checked_in_count', - ) - ); - $response = rest_do_request($req); - $result = $response->get_data(); - $this->assertTrue(isset($result['EVT_ID'])); - //check that the requested calculated fields were added. - //Seeing how these calculated fields just wrap other EE methods (which should already be tested) - //the emphasis here is just on whether or not they get included properly, not exhaustively - //testing the calculations themselves - $this->assertTrue(isset($result['_calculated_fields'])); - $this->assertEquals( - (object)array( - 'optimum_sales_at_start' => $limit_on_ticket, - 'spots_taken' => 1, - 'spaces_remaining' => $limit_on_ticket - 1, - ), - $result['_calculated_fields'] - ); - $this->assertTrue(isset($result['datetimes'])); - $this->assertTrue(isset($result['datetimes'][0])); - $this->assertTrue(isset($result['datetimes'][0]['_calculated_fields'])); - $this->assertEquals( - (object)array( - 'registrations_checked_in_count' => 0, - ), - $result['datetimes'][0]['_calculated_fields'] - ); - } - - - - /** - * Verifies the format of the response hasn't changed (unless of course we actually - * DO change it, in which case this unit test will need to be updated to - * include the known modifications). - * This helps prevent accidental changes - */ - public function test_handle_request_get_one__event() - { - $original_gmt_offset = get_option('gmt_offset'); - \EED_Core_Rest_Api::set_hooks_for_changes(); - //set a weird timezone - update_option('gmt_offset', -4.5); - $this->authenticate_as_admin(); - $current_time_mysql_gmt = current_time('Y-m-d\TH:i:s', true); - $current_time_mysql = current_time('Y-m-d\TH:i:s'); - - //these model objects were instantiated when the tests started, so their - //default time is actually quite old now (at least a few seconds, possibly a minute or two) - //so make sure we're creating the event with the CURRENT current time - $event = $this->new_model_obj_with_dependencies('Event' - // , - // array( - // 'EVT_created' => $current_time_mysql_gmt, - // 'EVT_modified' => $current_time_mysql_gmt, - // 'EVT_visible_on' => $current_time_mysql_gmt, - // ) - ); - $req = new \WP_REST_Request('GET', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.29/events/' . $event->ID()); - $req->set_url_params( - array( - 'id' => $event->ID(), - ) - ); - $response = rest_do_request($req); - $result = $response->get_data(); - $this->assertTrue(is_array($result)); - //compare all the times, realizing that _gmt times should be in UTC, others in the site's timezone - $this->assertDateWithinOneMinute($current_time_mysql, $result['EVT_created'], 'Y-m-d\TH:i:s'); - $this->assertDateWithinOneMinute($current_time_mysql, $result['EVT_modified'], 'Y-m-d\TH:i:s'); - $this->assertDateWithinOneMinute($current_time_mysql, $result['EVT_visible_on'], 'Y-m-d\TH:i:s'); - $this->assertDateWithinOneMinute($current_time_mysql_gmt, $result['EVT_created_gmt'], 'Y-m-d\TH:i:s'); - $this->assertDateWithinOneMinute($current_time_mysql_gmt, $result['EVT_modified_gmt'],'Y-m-d\TH:i:s'); - $this->assertDateWithinOneMinute($current_time_mysql_gmt, $result['EVT_visible_on_gmt'], 'Y-m-d\TH:i:s'); - //and let's just double-check the site's timezone isn't UTC, which would make it impossible to know if timezone offsets - //are being applied properly or not - $this->assertNotEquals( - $result['EVT_created'], - $result['EVT_created_gmt'], - 'There is no timezone offset, so its impossible to know if the timezone offset is being applied properly' - ); - $properties_we_cant_compare_exactly = array( - 'EVT_created', - 'EVT_modified', - 'EVT_visible_on', - 'EVT_created_gmt', - 'EVT_modified_gmt', - 'EVT_visible_on_gmt', - ); - foreach ($properties_we_cant_compare_exactly as $property_name) { - unset($result[$property_name]); - } - $event_id = $event->ID(); - $this->assertEquals( - array( - 'EVT_ID' => $event->get('EVT_ID'), - 'EVT_name' => $event->get('EVT_name'), - 'EVT_desc' => array( - 'raw' => $event->get('EVT_desc'), - 'rendered' => $event->get_pretty('EVT_desc'), - ), - 'EVT_slug' => $event->get('EVT_slug'), - 'EVT_short_desc' => $event->get('EVT_short_desc'), - 'parent' => $event->get('parent'), - 'EVT_order' => $event->get('EVT_order'), - 'status' => array( - 'raw' => $event->get('status'), - 'pretty' => $event->get_pretty('status'), - ), - 'comment_status' => $event->get('comment_status'), - 'ping_status' => $event->get('ping_status'), - 'EVT_display_desc' => $event->get('EVT_display_desc'), - 'EVT_display_ticket_selector' => $event->get('EVT_display_ticket_selector'), - 'EVT_additional_limit' => $event->get('EVT_additional_limit'), - 'EVT_default_registration_status' => array( - 'raw' => $event->get('EVT_default_registration_status'), - 'pretty' => $event->get_pretty('EVT_default_registration_status'), - ), - 'EVT_member_only' => $event->get('EVT_member_only'), - 'EVT_phone' => $event->get('EVT_phone'), - 'EVT_allow_overflow' => $event->get('EVT_allow_overflow'), - 'EVT_external_URL' => $event->get('EVT_external_URL'), - 'EVT_donations' => $event->get('EVT_donations'), - 'featured_image_url' => null, - 'EVT_timezone_string' => '', - 'link' => get_permalink($event->ID()), - '_links' => array( - 'self' => - array( - 0 => - array( - 'href' => rest_url('/ee/v4.8.29/events/' . $event_id), - ), - ), - 'collection' => - array( - 0 => - array( - 'href' => rest_url('/ee/v4.8.29/events'), - ), - ), - 'https://api.eventespresso.com/registrations' => - array( - 0 => - array( - 'href' => rest_url( - '/ee/v4.8.29/events/' - . $event_id - . '/registrations' - ), - 'single' => false, - ), - ), - 'https://api.eventespresso.com/datetimes' => - array( - 0 => - array( - 'href' => rest_url( - '/ee/v4.8.29/events/' - . $event_id - . '/datetimes' - ), - 'single' => false, - ), - ), - 'https://api.eventespresso.com/question_groups' => - array( - 0 => - array( - 'href' => rest_url( - '/ee/v4.8.29/events/' - . $event_id - . '/question_groups' - ), - 'single' => false, - ), - ), - 'https://api.eventespresso.com/venues' => - array( - 0 => - array( - 'href' => rest_url( '/ee/v4.8.29/events/' . $event_id . '/venues'), - 'single' => false, - ), - ), - 'https://api.eventespresso.com/term_taxonomies' => - array( - 0 => - array( - 'href' => rest_url( - '/ee/v4.8.29/events/' - . $event_id - . '/term_taxonomies' - ), - 'single' => false, - ), - ), - 'https://api.eventespresso.com/message_template_groups' => - array( - 0 => - array( - 'href' => rest_url( - '/ee/v4.8.29/events/' - . $event_id - . '/message_template_groups' - ), - 'single' => false, - ), - ), - 'https://api.eventespresso.com/attendees' => - array( - 0 => - array( - 'href' => rest_url( - '/ee/v4.8.29/events/' - . $event_id - . '/attendees' - ), - 'single' => false, - ), - ), - 'https://api.eventespresso.com/wp_user' => - array( - 0 => - array( - 'href' => rest_url( '/ee/v4.8.29/events/' . $event_id . '/wp_user'), - 'single' => true, - ), - ), - 'https://api.eventespresso.com/post_metas' => - array( - 0 => - array( - 'href' => rest_url( - '/ee/v4.8.29/events/' - . $event_id - . '/post_metas' - ), - 'single' => false, - ), - ), - 'https://api.eventespresso.com/extra_metas' => - array( - 0 => - array( - 'href' => rest_url( - '/ee/v4.8.29/events/' - . $event_id - . '/extra_metas' - ), - 'single' => false, - ), - ), - 'https://api.eventespresso.com/change_logs' => - array( - 0 => - array( - 'href' =>rest_url( - '/ee/v4.8.29/events/' - . $event_id - . '/change_logs' - ), - 'single' => false, - ), - ), - 'https://api.eventespresso.com/term_relationships' => - array( - 0 => - array( - 'href' => rest_url( - '/ee/v4.8.29/events/' - . $event_id - . '/term_relationships' - ), - 'single' => false, - ), - ), - ), - ), - $result - ); - // reset timezone - update_option('gmt_offset', $original_gmt_offset); - } - - - - public function test_handle_request_get_one__registration_include_attendee() - { - $this->authenticate_as_admin(); - $r = $this->new_model_obj_with_dependencies('Registration'); - $req = new \WP_REST_Request( - 'GET', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.29/registrations/' . $r->ID() - ); - $req->set_query_params( - array( - 'include' => 'Attendee.*', - ) - ); - $req->set_url_params( - array( - 'id' => $r->ID(), - ) - ); - $response = rest_do_request($req); - $entity = $response->get_data(); - $this->assertArrayHasKey('attendee', $entity); - } - - - - public function test_handle_request_get_one__registration_include_answers_and_questions_use_star() - { - $this->authenticate_as_admin(); - $r = $this->new_model_obj_with_dependencies('Registration'); - $this->new_model_obj_with_dependencies('Answer', array('REG_ID' => $r->ID())); - $req = new \WP_REST_Request('GET', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.29/registrations/' . $r->ID()); - $req->set_query_params( - array( - 'include' => 'Answer.Question.*', - ) - ); - $req->set_url_params( - array( - 'id' => $r->ID(), - ) - ); - $response = rest_do_request($req); - $entity = $response->get_data(); - $this->assertArrayHasKey('REG_date', $entity); - $this->assertArrayHasKey('answers', $entity); - $answers = $entity['answers']; - foreach ($answers as $answer) { - $this->assertArrayHasKey('question', $answer); - } - } - - - - public function test_handle_request_get_one__registration_include_answers_and_questions() - { - $this->authenticate_as_admin(); - $r = $this->new_model_obj_with_dependencies('Registration'); - $this->new_model_obj_with_dependencies('Answer', array('REG_ID' => $r->ID())); - $req = new \WP_REST_Request('GET', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.29/registrations/' . $r->ID()); - $req->set_query_params( - array( - 'include' => 'Answer.Question', - ) - ); - $req->set_url_params( - array( - 'id' => $r->ID(), - ) - ); - $response = rest_do_request($req); - $entity = $response->get_data(); - $this->assertArrayHasKey('REG_date', $entity); - $this->assertArrayHasKey('answers', $entity); - $answers = $entity['answers']; - foreach ($answers as $answer) { - $this->assertArrayHasKey('question', $answer); - } - } - - - - public function test_handle_request_get_one__registration_include_answers_and_question_bare_min_from_each() - { - $this->authenticate_as_admin(); - $r = $this->new_model_obj_with_dependencies('Registration'); - $this->new_model_obj_with_dependencies('Answer', array('REG_ID' => $r->ID())); - $req = new \WP_REST_Request('GET', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.29/registrations/' . $r->ID()); - $req->set_query_params( - array( - 'include' => 'Answer.ATT_ID, Answer.Question.QST_ID', - ) - ); - $req->set_url_params( - array( - 'id' => $r->ID(), - ) - ); - $response = rest_do_request($req); - $entity = $response->get_data(); - $this->assertArrayHasKey('answers', $entity); - $answers = $entity['answers']; - foreach ($answers as $answer) { - $this->assertArrayHasKey('question', $answer); - } - } - - - - public function test_handle_request_get_one__doesnt_exist() - { - $e = $this->new_model_obj_with_dependencies('Event'); - $non_existent_id = $e->ID() + 100; - $req = new \WP_REST_Request('GET', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.29/events/' . $non_existent_id); - $req->set_url_params( - array( - 'id' => $non_existent_id, - ) - ); - $response = rest_do_request($req); - $this->assertInstanceOf('WP_REST_Response', $response); - $this->assertEquals(404, $response->get_status()); - } - - - - public function test_handle_request_get_one__cannot_access() - { - $e = $this->new_model_obj_with_dependencies('Event', array('status' => 'draft')); - $req = new \WP_REST_Request('GET', '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.29/events/' . $e->ID()); - $req->set_url_params( - array( - 'id' => $e->ID(), - ) - ); - $response = rest_do_request($req); - $this->assertInstanceOf('WP_REST_Response', $response); - $this->assertEquals(403, $response->get_status()); - } - - - - public function test_handle_request_get_all__not_logged_in() - { - $this->new_model_obj_with_dependencies('Registration'); - $response = rest_do_request( - new \WP_REST_Request('GET', '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.29/registrations') - ); - $this->assertInstanceOf('WP_REST_Response', $response); - $this->assertEquals(403, $response->get_status()); - } - - - - /** - * @group 9406 - * @group 10526 - */ - public function test_handle_request_get_all__set_headers() - { - $datetimes_created = 65; - $event = $this->new_model_obj_with_dependencies('Event', array('status' => \EEM_CPT_Base::post_status_publish)); - for ($i = 0; $i < $datetimes_created; $i++) { - $this->new_model_obj_with_dependencies('Datetime', array('EVT_ID' => $event->ID())); - } - $this->assertEquals($datetimes_created, - \EEM_Datetime::instance()->count(array('caps' => \EEM_Base::caps_read))); - //request all datetimes from 4.8.36 (where the headers got added) - $response = rest_do_request( - new \WP_REST_Request('GET', '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/datetimes') - ); - $this->assertInstanceOf('WP_REST_Response', $response); - $headers = $response->get_headers(); - $this->assertArrayHasKey(Controller_Base::header_prefix_for_wp . 'Total', $headers); - $this->assertArrayHasKey(Controller_Base::header_prefix_for_wp . 'TotalPages', $headers); - $this->assertEquals($datetimes_created, $headers[Controller_Base::header_prefix_for_wp . 'Total']); - $this->assertEquals(ceil($datetimes_created / 50), - $headers[Controller_Base::header_prefix_for_wp . 'TotalPages']); - } - - - - /** - * @param string $role - * @return \WP_User - */ - public function get_wp_user_mock($role = 'administrator') - { - /** @type \WP_User $user */ - $user = $this->factory->user->create_and_get(); - $user->add_role($role); - return $user; - } - - - - /** - * @group 24 - */ - public function test_prepare_rest_query_params_key_for_models() - { - $controller = new Read(); - $this->assertEquals(array( - 'EVT_desc' => 'foobar', - 'OR' => array( - 'EVT_desc*gotcha' => array('LIKE', '%foobar%'), - 'EVT_name' => 'yep', - 'EVT_desc*gotchaagain' => array('IN', array('1', '2')), - ), - ), - $controller->prepareRestQueryParamsKeyForModels( - \EEM_Event::instance(), - array( - 'EVT_desc' => 'foobar', - 'OR' => array( - 'EVT_desc*gotcha' => array('LIKE', '%foobar%'), - 'EVT_name' => 'yep', - 'EVT_desc*gotchaagain' => array('IN', array('1', '2')), - ), - ))); - } - - - - /** - * @group 24 - * @group 9406 - */ - public function test_create_model_query_params__4_8_36() - { - $controller = new Read(); - $controller->setRequestedVersion('4.8.36'); - $this->assertEquals(array( - 0 => array( - 'EVT_desc*foobar' => array('LIKE', '%frogs%'), - 'OR*otherfunanimals' => array( - 'EVT_name' => array('IN', array('chickens', 'cows')), - 'EVT_slug' => 'cowbunga', - 'Datetime.DTT_reg_limit' => EE_INF, - 'Datetime.DTT_reg_limit*1' => EE_INF, - 'Datetime.DTT_EVT_start' => array('<', strtotime('2016-01-01 00:00:00')), - ), - ), - 'order_by' => array( - 'EVT_desc' => 'ASC', - ), - 'group_by' => array( - 'EVT_desc', - ), - 'having' => array( - 'EVT_desc' => 'monkey', - ), - 'limit' => 50, - 'caps' => \EEM_Base::caps_read_admin, - ), - $controller->createModelQueryParams( - \EEM_Event::instance(), - array( - 'where' => array( - 'EVT_desc*foobar' => array('LIKE', '%frogs%'), - 'OR*otherfunanimals' => array( - 'EVT_name' => array('IN', array('chickens', 'cows')), - 'EVT_slug' => 'cowbunga', - 'Datetime.DTT_reg_limit' => null, - 'Datetime.DTT_reg_limit*1' => '', - 'Datetime.DTT_EVT_start' => array('<', '2016-01-01T00:00:00'), - ), - ), - 'order_by' => array( - 'EVT_desc' => 'ASC', - ), - 'group_by' => array( - 'EVT_desc', - ), - 'having' => array( - 'EVT_desc' => 'monkey', - ), - 'caps' => \EEM_Base::caps_read_admin, - ))); - } - - - - /** - * @group 9389 - * @group 9222 - */ - public function test_handle_request_get_all__automatic_group_by() - { - $request = new \WP_REST_Request('GET', '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/question_groups'); - $request->set_query_params( - array( - 'where' => array( - 'Question.QST_ID' => array('IS_NOT_NULL'), - ), - 'limit' => '2,2', - ) - ); - $response = rest_do_request($request); - $this->assertEmpty($response->get_data()); - } - - - - /** - * Test that when we set the minimum_others where conditions, we don't find trashed cpt items - * for the current model (because we use normal default where conditions for main model), but not for related - * trashed models (because they only use their minimum where conditions) - * - * @group 10260 - */ - public function test_handle_request_get_all__use_minimum_others_where_conditions() - { - $this->assertEquals(0, \EEM_Event::instance()->count(array('default_where_conditions' => 'none'))); - $e_normal = $this->new_model_obj_with_dependencies('Event', - array('status' => \EEM_CPT_Base::post_status_publish)); - $e_normal_but_with_trashed_v = $this->new_model_obj_with_dependencies('Event', - array('status' => \EEM_CPT_Base::post_status_publish)); - $e_trashed = $this->new_model_obj_with_dependencies('Event', - array('status' => \EEM_CPT_Base::post_status_trashed)); - $v_normal = $this->new_model_obj_with_dependencies('Venue', - array('status' => \EEM_CPT_Base::post_status_publish)); - $v_trashed = $this->new_model_obj_with_dependencies('Venue', - array('status' => \EEM_CPT_Base::post_status_trashed)); - //associate them - $e_normal->_add_relation_to($v_normal, 'Venue'); - $e_normal_but_with_trashed_v->_add_relation_to($v_trashed, 'Venue'); - $e_trashed->_add_relation_to($v_normal, 'Venue'); - //now verify we get what we wanted... - $request = new \WP_REST_Request('GET', '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/events'); - $request->set_query_params( - array( - 'order_by' => array('Venue.VNU_ID' => 'ASC'), - 'default_where_conditions' => 'full_this_minimum_others', - ) - ); - $response = rest_do_request($request); - //we should find the normal event, and the event for the trashed venue - $this->assertCount(2, $response->data); - } - - - - /** - * This tests getting schema object returned for an options request on a valid collection endpoint. - * - * @group rest_schema_request - */ - public function test_handle_schema_request() - { - $request = new \WP_REST_Request('OPTIONS', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/events'); - $response = rest_do_request($request); - $data = $response->get_data(); - //verify there is a schema array - $this->assertArrayHasKey('schema', $data); - //verify schema has a `$schema` key - $this->assertArrayHasKey('$schema', $data['schema']); - //verify there is a title and it is "Event" - $this->assertArrayHasKey('title', $data['schema']); - $this->assertEquals('Event', $data['schema']['title']); - //verify there is a properties array in the schema and a few of the common fields are there (including that the - //EVT_ID field has `primary_key` flag set to true. - $this->assertArrayHasKey('properties', $data['schema']); - $this->assertArrayHasKey('EVT_ID', $data['schema']['properties']); - $this->assertArrayHasKey('primary_key', $data['schema']['properties']['EVT_ID']); - $this->assertTrue($data['schema']['properties']['EVT_ID']['primary_key']); - $this->assertArrayHasKey('EVT_desc', $data['schema']['properties']); - //finally let's verify that a relation that should be in the events schema (datetimes!) is present and that its - //relation items are correct. - $this->assertArrayHasKey('datetimes', $data['schema']['properties']); - $datetimes_array = $data['schema']['properties']['datetimes']; - $this->assertArrayHasKey('description', $datetimes_array); - $this->assertArrayHasKey('type', $datetimes_array); - $this->assertEquals('array', $datetimes_array['type']); - $this->assertArrayHasKey('relation', $datetimes_array); - $this->assertTrue($datetimes_array['relation']); - $this->assertArrayHasKey('relation_type', $datetimes_array); - $this->assertEquals('EE_Has_Many_Relation', $datetimes_array['relation_type']); - $this->assertArrayHasKey('readonly', $datetimes_array); - $this->assertTrue($datetimes_array['readonly']); - } - - - - /** - * @group rest_schema_request - */ - public function test_handle_schema_request_returning_defaults() - { - $request = new \WP_REST_Request('OPTIONS', '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/prices'); - $response = rest_do_request($request); - $data = $response->get_data(); - //verify that defaults are in the schema and in the correct format. - $PRC_amount_defaults = $data['schema']['properties']['PRC_amount']['default']; - $this->assertTrue(is_array($PRC_amount_defaults)); - $this->assertArrayHasKey('raw', $PRC_amount_defaults); - $this->assertArrayHasKey('pretty', $PRC_amount_defaults); - $this->assertEquals((float)0, $PRC_amount_defaults['raw']); - $this->assertEquals('$0.00 (USD)', $PRC_amount_defaults['pretty']); - } - - - - /** - * If someone specifies the same model field in a query parameter, which do we use? WP core uses the non-gmt field - * for now, so we'll do that too. See https://core.trac.wordpress.org/ticket/39954 - * - * @group 9222 - */ - public function test_handle_request_get_all__duplicate_query_fields_specified() - { - $this->authenticate_as_admin(); - //we aren't testing whether the timezone offset is being applied, we are just testing - //to see whether the gmt or non-gmt time is being used - $e = $this->new_model_obj_with_dependencies('Event',array('status' => 'publish')); - $d1 = $this->new_model_obj_with_dependencies( - 'Datetime', - array( - 'EVT_ID' => $e->ID(), - 'DTT_EVT_start' => \EEM_Datetime::instance()->convert_datetime_for_query( - 'DTT_EVT_start', - '2017-01-02 00:00:00', - \EE_Datetime_Field::mysql_timestamp_format, - \EEM_Datetime::instance()->get_timezone() - ) - ) - ); - $d2 = $this->new_model_obj_with_dependencies( - 'Datetime', - array( - 'EVT_ID' => $e->ID(), - 'DTT_EVT_start' => \EEM_Datetime::instance()->convert_datetime_for_query( - 'DTT_EVT_start', - '2017-01-03 00:00:00', - \EE_Datetime_Field::mysql_timestamp_format, - \EEM_Datetime::instance()->get_timezone() - ) - ) - ); - $request = new \WP_REST_Request('GET', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/datetimes'); - $request->set_query_params( - array( - 'where' => array( - 'DTT_EVT_start_gmt' => '2017-01-02T00:00:00', - 'DTT_EVT_start' => '2017-01-03T00:00:00' - ) - ) - ); - $response = rest_do_request($request); - $response_data = $response->get_data(); - $this->assertFalse(empty($response_data)); - $this->assertTrue(empty($response_data['code'])); - $first_result = array_shift( $response_data); - //we should have found the datetime which matches the DTT_EVT_start query parameter - //and DTT_EVT_start_gmt should have been ignored - $this->assertEquals('2017-01-03T00:00:00', $first_result['DTT_EVT_start']); - } - - - - /** - * This is to test a bug where getting extra metas were having a parsing error - */ - public function testHandleRequestGetRelatedExtraMeta(){ - $this->authenticate_as_admin(); - $e1 = $this->new_model_obj_with_dependencies('Event'); - $request = new \WP_REST_Request( - 'GET', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/events/' . $e1->ID() . '/extra_metas' - ); - $response = rest_do_request($request); - $response_data = $response->get_data(); - $this->assertTrue(empty($response_data['code'])); - } - /** - * Creates two events: one with registrations, the other without. - * Verify that if we loop over them and render their pretty content (which renders shortcodes) - * we don't accidentally cache the shortcode from one event to the other - * @group 10851 - */ - public function testShortcodesNotCachedForDifferentEvents() - { - $this->loadShortcodesManagerAndShortcodes(); - $transaction = $this->new_typical_transaction(); - $event_with_registrations = $transaction->primary_registration()->event(); - $event_with_registrations->set_description('[ESPRESSO_EVENT_ATTENDEES]'); - $event_with_registrations->set('status','publish'); - $event_with_registrations->save(); - - $other_event = $this->new_model_obj_with_dependencies( - 'Event', - array( - 'EVT_desc' => '[ESPRESSO_EVENT_ATTENDEES]', - 'status' => 'publish' - ) - ); - $dtt = $this->new_model_obj_with_dependencies('Datetime'); - $other_event->_add_relation_to( $dtt, 'Datetime' ); - $dtt->_add_relation_to( - $this->new_model_obj_with_dependencies('Ticket'), - 'Ticket' - ); - - $request = new \WP_REST_Request( 'GET', '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/events'); - $response = rest_do_request($request); - $data = $response->get_data(); - $this->assertEquals( 2, count($data)); - $this->assertNotEquals( - $data[0]['EVT_desc']['rendered'], - $data[1]['EVT_desc']['rendered'] - ); - } -} -// End of file Read_Test.php -// Location: testcases/core/libraries/rest_api/controllers/Read_Test.php diff --git a/tests/testcases/core/libraries/rest_api/controllers/WriteTest.php b/tests/testcases/core/libraries/rest_api/controllers/WriteTest.php deleted file mode 100644 index 4cee35308aa..00000000000 --- a/tests/testcases/core/libraries/rest_api/controllers/WriteTest.php +++ /dev/null @@ -1,472 +0,0 @@ -set_body_params( - array( - 'EVT_name' => 'Haha I didnt log in and I inserted an event', - ) - ); - $response = rest_do_request($request); - $data = $response->get_data(); - $this->assertEquals('rest_cannot_create_events', $data['code']); - } - - - - /** - * Verifies that even if the current user can edit events, they shouldn't be able - * to insert until we've sorted that code out - */ - public function testNoInsertLimitedUser() - { - $user = $this->factory->user->create_and_get(array('role' => 'subscriber')); - $user->add_cap('ee_edit_events'); - $user->add_cap('ee_read_events'); - wp_set_current_user($user->ID); - //ok now try to insert an event - $request = new \WP_REST_Request('POST', '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/events'); - $request->set_body_params( - array( - 'EVT_name' => 'Haha I didnt log in and I inserted an event', - ) - ); - $response = rest_do_request($request); - $data = $response->get_data(); - $this->assertEquals('rest_cannot_create_events', $data['code']); - } - - - - /** - * @group 9222 - */ - public function testInsertUtcAndRelativeTimes() - { - //let's set a different WP timezone. - update_option('gmt_offset', '-1'); - $this->authenticateAnAdmin(); - $req = new \WP_REST_Request( - 'POST', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/datetimes' - ); - $req->set_body_params( - array( - 'DTT_EVT_start_gmt' => '2016-01-02T00:00:00', - 'DTT_EVT_end' => '2016-01-03T00:00:00', - ) - ); - $response = rest_do_request($req); - $response_data = $response->get_data(); - if (! isset($response_data['code'])) { - $response_data['code'] = null; - } - $this->assertEmpty( - $response_data['code'], - '$response_data[\'code\'] was not empty and actually contained: ' . $response_data['code'] - . "\n" . ' The full response was: ' . var_export($response_data, true) - ); - $this->assertEquals('2016-01-02T00:00:00', $response_data['DTT_EVT_start_gmt']); - $this->assertEquals('2016-01-01T23:00:00', $response_data['DTT_EVT_start']); - $this->assertEquals('2016-01-03T01:00:00', $response_data['DTT_EVT_end_gmt']); - $this->assertEquals('2016-01-03T00:00:00', $response_data['DTT_EVT_end']); - } - - - - /** - * - * Verify that we follow WP's current behaviour when both a gmt and non-gmt date are provided: - * ignore the gmt datetime. See https://core.trac.wordpress.org/ticket/39954 - * @group 9222 - */ - public function testInsertUtcAndRelativeDuplicate() - { - //let's set a different WP timezone. - update_option('gmt_offset', '-1'); - $this->authenticateAnAdmin(); - $req = new \WP_REST_Request( - 'POST', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/datetimes' - ); - $req->set_body_params( - array( - 'DTT_EVT_start' => '2016-01-03T00:00:00', - 'DTT_EVT_start_gmt' => '2016-01-02T00:00:00', - ) - ); - $response = rest_do_request($req); - $response_data = $response->get_data(); - if (! isset($response_data['code'])) { - $response_data['code'] = null; - } - $this->assertEmpty( - $response_data['code'], - '$response_data[\'code\'] was not empty and actually contained: ' . $response_data['code'] - . "\n" . ' The full response was: ' . var_export($response_data, true) - ); - $this->assertEquals('2016-01-03T00:00:00', $response_data['DTT_EVT_start']); - } - - /** - * Originally I wanted to allow providing selection parameters on write requests, and this - * test verified we could do that. However, Darren had some issues with that, and so - * rather than discuss it further it was removed. So this test now verifies we DON'T - * use selection parameters on write requests. - * @group 9222 - */ - public function testInsertThenUseQuerystring() - { - $this->authenticateAnAdmin(); - $event = $this->new_model_obj_with_dependencies('Event'); - $req = new \WP_REST_Request( - 'POST', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/datetimes' - ); - $req->set_body_params( - array( - 'EVT_ID' => $event->ID(), - 'DTT_EVT_start_gmt' => '2016-01-02T00:00:00', - ) - ); - //it's a free country, so you can provide a query string - //with parameters for reading in it; but we will ignore it. - $req->set_query_params( - array( - 'include' => 'Event.EVT_ID' - ) - ); - $response = rest_do_request($req); - $response_data = $response->get_data(); - $this->assertTrue(empty($response_data['code'])); - $this->assertTrue(isset($response_data['DTT_ID'])); - //we should NOT include the datetime's related event, because we said we weren't going - //to use READ parameters on WRITE queries like this - $this->assertTrue(empty($response_data['event']['EVT_ID'])); - } - - - - /** - * @group 9222 - */ - public function testUpdateOnlySomeFields() - { - $this->authenticateAnAdmin(); - $original_reg_limit = 25; - $original_sold = 100; - $datetime = $this->new_model_obj_with_dependencies( - 'Datetime', - array( - 'DTT_reg_limit' => $original_reg_limit, - 'DTT_sold' => $original_sold, - ) - ); - $req = new \WP_REST_Request( - 'PUT', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/datetimes/' . $datetime->ID() - ); - //just update the reg limit, not the number sold - $req->set_body_params( - array( - 'DTT_reg_limit' => $original_reg_limit * 2, - ) - ); - $response = rest_do_request($req); - $response_data = $response->get_data(); - //verify there was no error code - $this->assertTrue(empty($response_data['code'])); - //assert the reg limit was updated properly - $this->assertEquals($original_reg_limit * 2, (int)$response_data['DTT_reg_limit']); - //but that teh sold count wasn't changed - $this->assertEquals($original_sold, (int)$response_data['DTT_sold']); - } - - - - /** - * Verifies that if we pass an invalid ID for a PUT, there is a proper REST API error - * (not just a model or PHP error) - * @group 9222 - */ - public function testUpdateInvalidID() - { - $this->authenticateAnAdmin(); - $req = new \WP_REST_Request( - 'PUT', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/datetimes/9999999' - ); - //just update the reg limit, not the number sold - $req->set_body_params( - array( - 'DTT_reg_limit' => 2, - ) - ); - $response = rest_do_request($req); - $response_data = $response->get_data(); - //verify there was no error code - $this->assertEquals('rest_datetime_invalid_id', $response_data['code']); - } - - - - /** - * Verifies that if we pass an invalid ID for a DELETE, there is a proper REST API error - * (not just a model or PHP error) - * @group 9222 - */ - public function testDeleteInvalidID() - { - $this->authenticateAnAdmin(); - $req = new \WP_REST_Request( - 'DELETE', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/datetimes/9999999' - ); - $response = rest_do_request($req); - $response_data = $response->get_data(); - //verify there was no error code - $this->assertEquals('rest_datetime_invalid_id', $response_data['code']); - } - - - - /** - * @group 9222 - */ - public function testNoDeleteIfNoCaps() - { - $datetime = $this->new_model_obj_with_dependencies( - 'Datetime', - array( - 'DTT_deleted' => false, - ) - ); - //double-check the datetime isn't trashed - $this->assertFalse($datetime->get('DTT_deleted')); - $request = new \WP_REST_Request('DELETE', '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/datetimes/' . $datetime->ID()); - $response = rest_do_request($request); - $data = $response->get_data(); - $this->assertEquals('rest_cannot_delete_datetimes', $data['code']); - } - - - - /** - * @group 9222 - */ - public function testDeleteTrashed() - { - $this->authenticateAnAdmin(); - $datetime = $this->new_model_obj_with_dependencies( - 'Datetime', - array( - 'DTT_deleted' => false, - ) - ); - //double-check the datetime isn't trashed - $this->assertFalse($datetime->get('DTT_deleted')); - $req = new \WP_REST_Request( - 'DELETE', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/datetimes/' . $datetime->ID() - ); - $response = rest_do_request($req); - $response_data = $response->get_data(); - //verify there was no error code - $this->assertTrue(empty($response_data['code'])); - $this->assertTrue($response_data['DTT_deleted']); - } - - - - /** - * @group 9222 - */ - public function testDeletePermanent() - { - $this->authenticateAnAdmin(); - $datetime_count_before_insertion = \EEM_Datetime::instance()->count_deleted_and_undeleted(); - $datetime = $this->new_model_obj_with_dependencies('Datetime'); - $req = new \WP_REST_Request( - 'DELETE', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/datetimes/' . $datetime->ID() - ); - $req->set_query_params( - array( - 'force' => true, - ) - ); - $response = rest_do_request($req); - $response_data = $response->get_data(); - //verify there was no error code - $this->assertTrue(empty($response_data['code'])); - $this->assertTrue(isset($response_data['deleted'], $response_data['previous'])); - $this->assertEquals($datetime->ID(), $response_data['previous']['DTT_ID']); - $this->assertEquals($datetime_count_before_insertion, \EEM_Datetime::instance()->count_deleted_and_undeleted()); - } - - /** - * @group 9222 - */ - public function testDeleteCPTPermanent() - { - $this->authenticateAnAdmin(); - $event_count_before_insertion = \EEM_Event::instance()->count_deleted_and_undeleted(); - $event = $this->new_model_obj_with_dependencies('Event'); - $req = new \WP_REST_Request( - 'DELETE', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/events/' . $event->ID() - ); - $req->set_query_params( - array( - 'force' => true, - ) - ); - $response = rest_do_request($req); - $response_data = $response->get_data(); - //verify there was no error code - $this->assertTrue(empty($response_data['code'])); - $this->assertTrue(isset($response_data['deleted'], $response_data['previous'])); - $this->assertEquals($event->ID(), $response_data['previous']['EVT_ID']); - $this->assertEquals($event_count_before_insertion, \EEM_Event::instance()->count_deleted_and_undeleted()); - } - - - - /** - * Tests that when we delete a non-soft-deletable model object, it has an error - * - * @group 9222 - */ - public function testDeleteNotAllowedOnNonSoftDeleteModel() - { - $this->authenticateAnAdmin(); - $payment = $this->new_model_obj_with_dependencies('Payment'); - $payment_count_before_deletion = \EEM_Payment::instance()->count(); - $req = new \WP_REST_Request( - 'DELETE', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/payments/' . $payment->ID() - ); - $response = rest_do_request($req); - $response_data = $response->get_data(); - $this->assertEquals('rest_trash_not_supported', $response_data['code']); - } - - - - /** - * Tests that when we delete a non-soft-deletable model object permanently, it works as normal - * - * @group 9222 - */ - public function testDeleteNonSoftDeleteModel() - { - $this->authenticateAnAdmin(); - $payment = $this->new_model_obj_with_dependencies('Payment'); - $payment_count_before_deletion = \EEM_Payment::instance()->count(); - $req = new \WP_REST_Request( - 'DELETE', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/payments/' . $payment->ID() - ); - $req->set_query_params( - array( - 'force' => 'true', - ) - ); - $response = rest_do_request($req); - $response_data = $response->get_data(); - //verify there was no error code - $this->assertTrue(empty($response_data['code'])); - $this->assertTrue(isset($response_data['deleted'], $response_data['previous'])); - $this->assertEquals($payment->ID(), $response_data['previous']['PAY_ID']); - $this->assertEquals($payment_count_before_deletion - 1, \EEM_Payment::instance()->count()); - } - - - - /** - * Test that we tell API clients when they are using a bad parameter - * @group 9222 - */ - public function testInsertInvalidParamProvided() - { - $this->authenticateAnAdmin(); - $req = new \WP_REST_Request( - 'POST', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/questions' - ); - $req->set_body_params( - array( - 'non-existent-field-name' => 'restorama', - ) - ); - $response = rest_do_request($req); - $response_data = $response->get_data(); - //verify there was no error code - $this->assertTrue(isset($response_data['code'])); - $this->assertEquals('invalid_field', $response_data['code']); - } - - /** - * Test that we tell API clients when they are using a bad parameter - * @group 9222 - */ - public function testInsertPostType() - { - $this->authenticateAnAdmin(); - $req = new \WP_REST_Request( - 'POST', - '/' . \EED_Core_Rest_Api::ee_api_namespace . '4.8.36/events' - ); - $req->set_body_params( - array( - 'post_type' => 'not-event', - 'EVT_name' => 'foobar' - ) - ); - $response = rest_do_request($req); - $response_data = $response->get_data(); - //verify there was an error code; we're not allowed to pass in post_type - $this->assertTrue(isset($response_data['code'])); - $this->assertEquals('invalid_field', $response_data['code']); - } - - - /** - * Authenticates an admin with capabilities to use the API - * - * @param array $caps - * @return \WP_User - */ - protected function authenticateAnAdmin() - { - global $current_user; - //setup our user and set as current user. - $current_user = $this->factory->user->create_and_get(); - $this->assertInstanceOf('WP_User', $current_user); - $current_user->add_role('administrator'); - return $current_user; - } - - - -} -// End of file Write_Test.php -// Location: tests\testcases\core\libraries\rest_api\controllers/Write_Test.php diff --git a/tests/testcases/core/libraries/shortcodes/EE_Shortcodes_Test.php b/tests/testcases/core/libraries/shortcodes/EE_Shortcodes_Test.php deleted file mode 100644 index b36ad1ff4a3..00000000000 --- a/tests/testcases/core/libraries/shortcodes/EE_Shortcodes_Test.php +++ /dev/null @@ -1,104 +0,0 @@ -shortcode_mock = new EE_Shortcodes_Mock; - } - - - /** - * @group 10561 - */ - public function test_mutate_conditional_block_in_template() - { - $data = array( - 'template' => 'This is a template with some conditional tags.' - . ' [IF_MOCK_TEST_ONE_* id=10]Mock Test One Content A[/IF_MOCK_TEST_ONE_*]' - . ' [IF_MOCK_TEST_ONE_* id=14]Mock Test One Content B[/IF_MOCK_TEST_ONE_*]' - . ' [IF_MOCK_TEST_ONE_* id=10]Mock Test One Content C[/IF_MOCK_TEST_ONE_*]' - . ' [IF_MOCK_TEST_TWO_* something=30]Mock Test Two Content[/IF_MOCK_TEST_TWO_*]' - ); - - //not expecting this return a value because the mock doesn't have conditional shortcodes registered. - $this->assertEmpty($this->shortcode_mock->parser('', $data)); - - //test the method we're testing. - //key is shortcode to test, value is expectation on return value. - $assertions_for_hide = array( - '[IF_MOCK_TEST_ONE_* id=10]' => 'This is a template with some conditional tags.' - . ' [IF_MOCK_TEST_ONE_* id=14]Mock Test One Content B[/IF_MOCK_TEST_ONE_*]' - . ' [IF_MOCK_TEST_TWO_* something=30]Mock Test Two Content[/IF_MOCK_TEST_TWO_*]', - '[IF_MOCK_TEST_ONE_* id=14]' => 'This is a template with some conditional tags.' - . ' [IF_MOCK_TEST_ONE_* id=10]Mock Test One Content A[/IF_MOCK_TEST_ONE_*]' - . ' [IF_MOCK_TEST_ONE_* id=10]Mock Test One Content C[/IF_MOCK_TEST_ONE_*]' - . ' [IF_MOCK_TEST_TWO_* something=30]Mock Test Two Content[/IF_MOCK_TEST_TWO_*]', - '[IF_MOCK_TEST_TWO_* something=30]' => 'This is a template with some conditional tags.' - . ' [IF_MOCK_TEST_ONE_* id=10]Mock Test One Content A[/IF_MOCK_TEST_ONE_*]' - . ' [IF_MOCK_TEST_ONE_* id=14]Mock Test One Content B[/IF_MOCK_TEST_ONE_*]' - . ' [IF_MOCK_TEST_ONE_* id=10]Mock Test One Content C[/IF_MOCK_TEST_ONE_*] ' - ); - - $assertions_for_show = array( - '[IF_MOCK_TEST_ONE_* id=10]' => 'This is a template with some conditional tags.' - . ' Mock Test One Content A' - . ' [IF_MOCK_TEST_ONE_* id=14]Mock Test One Content B[/IF_MOCK_TEST_ONE_*]' - . ' Mock Test One Content C' - . ' [IF_MOCK_TEST_TWO_* something=30]Mock Test Two Content[/IF_MOCK_TEST_TWO_*]', - '[IF_MOCK_TEST_ONE_* id=14]' => 'This is a template with some conditional tags.' - . ' [IF_MOCK_TEST_ONE_* id=10]Mock Test One Content A[/IF_MOCK_TEST_ONE_*]' - . ' Mock Test One Content B' - . ' [IF_MOCK_TEST_ONE_* id=10]Mock Test One Content C[/IF_MOCK_TEST_ONE_*]' - . ' [IF_MOCK_TEST_TWO_* something=30]Mock Test Two Content[/IF_MOCK_TEST_TWO_*]', - '[IF_MOCK_TEST_TWO_* something=30]' => 'This is a template with some conditional tags.' - . ' [IF_MOCK_TEST_ONE_* id=10]Mock Test One Content A[/IF_MOCK_TEST_ONE_*]' - . ' [IF_MOCK_TEST_ONE_* id=14]Mock Test One Content B[/IF_MOCK_TEST_ONE_*]' - . ' [IF_MOCK_TEST_ONE_* id=10]Mock Test One Content C[/IF_MOCK_TEST_ONE_*]' - . ' Mock Test Two Content' - ); - - //first lets test the expectations for when a condition results in hiding the contained content. - foreach ($assertions_for_hide as $shortcode => $expectation) { - $this->shortcode_mock->parser('', $data); - $this->assertEquals( - $expectation, - $this->shortcode_mock->mutate_conditional_block_in_template( - $shortcode, - false - ), - sprintf('Testing %s shortcode in the assertions for hide tests.', $shortcode) - ); - } - - //next test the expectations for when a condition results in showing - foreach ($assertions_for_show as $shortcode => $expectation) { - //reset template to original - $this->shortcode_mock->parser('', $data); - $this->assertEquals( - $expectation, - $this->shortcode_mock->mutate_conditional_block_in_template( - $shortcode - ), - sprintf('Testing %s shortcode in the assertions for show tests.', $shortcode) - ); - } - } -} \ No newline at end of file diff --git a/tests/testcases/core/libraries/shortcodes/VenueShortcodesTest.php b/tests/testcases/core/libraries/shortcodes/VenueShortcodesTest.php deleted file mode 100644 index 2eb773d1efb..00000000000 --- a/tests/testcases/core/libraries/shortcodes/VenueShortcodesTest.php +++ /dev/null @@ -1,126 +0,0 @@ -parser = new EE_Venue_Shortcodes(); - } - - public function tearDown() - { - parent::tearDown(); - $this->parser = null; - } - - - /** - * - * @return array - */ - protected function getVenueTestValues() - { - return array( - 'VNU_name' => 'Macadassy Hall', - 'VNU_address' => '10th St. & Constitution Ave. NW', - 'VNU_city' => 'Washington', - 'STA_ID' => 10, //District of Columnbia - 'CNT_ISO' => 'US', //United States - 'VNU_zip' => '20560', - 'VNU_desc' => 'test_description', - 'VNU_url' => 'http://testvenue.com', - 'VNU_phone' => '123-123-1234', - 'VNU_address2' => '', - ); - } - - - /** - * Data provider for tests. - * @return array - */ - public function venueShortcodeValuesProvider() - { - $testData = $this->getVenueTestValues(); - $google_map_url = htmlentities2( - 'http://maps.google.com/maps?q=' . urlencode( - $testData['VNU_address'] - . ',' . $testData['VNU_city'] - . ',' . 'District of Columbia' - . ',' . $testData['VNU_zip'] - . ',' . 'United States' - ) - ); - return array( - array('[VENUE_TITLE]', $testData['VNU_name']), - array('[VENUE_DESCRIPTION]', $testData['VNU_desc']), - array('[VENUE_URL]', $testData['VNU_url']), - array('[VENUE_PHONE]', $testData['VNU_phone']), - array('[VENUE_ADDRESS]', $testData['VNU_address']), - array('[VENUE_ADDRESS2]', $testData['VNU_address2']), - array('[VENUE_CITY]', $testData['VNU_city']), - array('[VENUE_COUNTRY]', 'United States'), - array('[VENUE_STATE]', 'District of Columbia'), - array('[VENUE_ZIP]', $testData['VNU_zip']), - array( - '[VENUE_FORMATTED_ADDRESS]', - '
10th St. & Constitution Ave. NW
Washington
District of Columbia
20560
United States
' - ), - array('[GOOGLE_MAP_URL]', $google_map_url), - array( - '[GOOGLE_MAP_LINK]', - '' - . $google_map_url - . '' - ) - ); - } - - - /** - * Returns an Event object for use by the Venue Shortcodes library tests. - * return EE_Event - */ - protected function getDataForShortcodes() - { - //setup a venue for the event for our tests. - $venue = $this->factory->venue->create($this->getVenueTestValues()); - /** @var EE_Event $event */ - $event = $this->factory->event->create(); - $event->_add_relation_to($venue, 'Venue'); - $event->save(); - return $event; - } - - - /** - * @dataProvider venueShortcodeValuesProvider - * @param string $shortcode_tested - * @param string $expected - */ - public function testShortcodes($shortcode_tested, $expected) - { - $this->assertEquals($expected, $this->parser->parser($shortcode_tested, $this->getDataForShortcodes())); - } - -} \ No newline at end of file diff --git a/tests/testcases/core/request_stack/RequestTest.php b/tests/testcases/core/request_stack/RequestTest.php deleted file mode 100644 index 323e77eff6e..00000000000 --- a/tests/testcases/core/request_stack/RequestTest.php +++ /dev/null @@ -1,484 +0,0 @@ - 'edit', - 'id' => 123, - 'event-name-123' => 'Event 123', - ); - } - - public function postParams(array $params = array()) - { - return $params + array( - 'input-a' => 'A', - 'input-b' => 'B', - 'sub' => array( - 'sub-a' => 'AA', - 'sub-b' => 'BB', - 'sub-sub' => array( - 'sub-sub-a' => 'AAA', - 'sub-sub-b' => 'BBB', - ) - ), - ); - } - - public function cookieParams(array $params = array()) - { - return $params + array( - 'PHPSESSID' => 'abcdefghijklmnopqrstuvwxyz', - 'cookie_test' => 'a1b2c3d4e5f6g7h8i9j0.12345678', - ); - } - - - /** - * @param array $get - * @param array $post - * @param array $cookie - * @param array $server - * @return EE_Request - */ - private function getLegacyRequest(array $get, array $post, array $cookie, array $server) - { - $request = new Request($get, $post, $cookie, $server); - $legacy_request = new EE_Request(array(), array(), array()); - $legacy_request->setRequest($request); - return $legacy_request; - } - - - public function testGetParams() - { - $request = $this->getLegacyRequest( - $this->getParams(), - array(), - array(), - array() - ); - $this->assertEquals( - $this->getParams(), - $request->get_params() - ); - } - - public function testPostParams() - { - $request = $this->getLegacyRequest( - array(), - $this->postParams(), - array(), - array() - ); - $this->assertEquals( - $this->postParams(), - $request->post_params() - ); - } - - public function testCookieParams() - { - $request = $this->getLegacyRequest( - array(), - array(), - $this->cookieParams(), - array() - ); - $this->assertEquals( - $this->cookieParams(), - $request->cookie_params() - ); - } - - public function testParams() - { - $request = $this->getLegacyRequest( - $this->getParams(), - $this->postParams(), - array(), - array() - ); - $this->assertEquals( - array_merge($this->getParams(), $this->postParams()), - $request->params() - ); - } - - public function testSet() - { - $request = $this->getLegacyRequest( - $this->getParams(), - array(), - array(), - array() - ); - $key = 'new-key'; - $value = 'ima noob'; - $request->set($key, $value); - $params = $request->params(); - $this->assertArrayHasKey($key, $params); - $this->assertEquals($value, $params[$key]); - } - - public function testSetEE() - { - $request = $this->getLegacyRequest( - $this->getParams(), - array(), - array(), - array() - ); - $request->set('ee', 'module-route'); - $params = $request->params(); - $this->assertArrayHasKey('ee', $params); - $this->assertEquals('module-route', $params['ee']); - } - - public function testAlreadySetEE() - { - $request = $this->getLegacyRequest( - $this->getParams(array('ee' => 'existing-route')), - array(), - array(), - array() - ); - $request->set('ee', 'module-route'); - $params = $request->params(); - $this->assertArrayHasKey('ee', $params); - $this->assertNotEquals('module-route', $params['ee']); - $this->assertEquals('existing-route', $params['ee']); - } - - public function testOverrideAlreadySetEE() - { - $request = $this->getLegacyRequest( - $this->getParams(array('ee' => 'existing-route')), - array(), - array(), - array() - ); - $request->set('ee', 'module-route', true); - $params = $request->params(); - $this->assertArrayHasKey('ee', $params); - $this->assertEquals('module-route', $params['ee']); - } - - - - public function testGet() - { - $request = $this->getLegacyRequest( - $this->getParams(), - array(), - array(), - array() - ); - // key exists - $this->assertEquals('edit', $request->get('action')); - // key does NOT exist and no default value set - $this->assertNotEquals('edit', $request->get('me-no-key')); - $this->assertNull($request->get('me-no-key')); - // key does NOT exist but default value set - $this->assertNotEquals( - 'edit', - $request->get('me-no-key', 'me-default') - ); - $this->assertEquals( - 'me-default', - $request->get('me-no-key', 'me-default') - ); - } - - - - public function testGetWithDrillDown() - { - $request = $this->getLegacyRequest( - array(), - $this->postParams(), - array(), - array() - ); - // our post data looks like this: - // array( - // 'input-a' => 'A', - // 'input-b' => 'B', - // 'sub' => array( - // 'sub-a' => 'AA', - // 'sub-b' => 'BB', - // 'sub-sub' => array( - // 'sub-sub-a' => 'AAA', - // 'sub-sub-b' => 'BBB', - // ) - // ) - // ); - // top-level value - $this->assertEquals('A', $request->get('input-a')); - $this->assertEquals('B', $request->get('input-b')); - // second level - $this->assertEquals('AA', $request->get('sub[sub-a]')); - $this->assertEquals('BB', $request->get('sub[sub-b]')); - // third level - $this->assertEquals('AAA', $request->get('sub[sub-sub][sub-sub-a]')); - $this->assertEquals('BBB', $request->get('sub[sub-sub][sub-sub-b]')); - // does not exist - $this->assertNull($request->get('input-c')); - $this->assertNull($request->get('sub[sub-c]')); - $this->assertNull($request->get('sub[sub-sub][sub-sub-c]')); - } - - - - public function testIsSet() - { - $request = $this->getLegacyRequest( - $this->getParams(), - array(), - array(), - array() - ); - $this->assertTrue($request->is_set('action')); - $this->assertFalse($request->is_set('me-no-key')); - } - - - - public function testIsSetWithDrillDown() - { - $request = $this->getLegacyRequest( - array(), - $this->postParams(), - array(), - array() - ); - // our post data looks like this: - // array( - // 'input-a' => 'A', - // 'input-b' => 'B', - // 'sub' => array( - // 'sub-a' => 'AA', - // 'sub-b' => 'BB', - // 'sub-sub' => array( - // 'sub-sub-a' => 'AAA', - // 'sub-sub-b' => 'BBB', - // ) - // ) - // ); - // top-level value - $this->assertTrue($request->is_set('input-a')); - $this->assertTrue($request->is_set('input-b')); - // second level - $this->assertTrue($request->is_set('sub[sub-a]')); - $this->assertTrue($request->is_set('sub[sub-b]')); - // third level - $this->assertTrue($request->is_set('sub[sub-sub][sub-sub-a]')); - $this->assertTrue($request->is_set('sub[sub-sub][sub-sub-b]')); - // not set - $this->assertFalse($request->is_set('input-c')); - $this->assertFalse($request->is_set('sub[sub-c]')); - $this->assertFalse($request->is_set('sub[sub-sub][sub-sub-c]')); - } - - - - public function testUnSet() - { - // do the chevy shuffle with the $_REQUEST global - // in case it's needed by other tests - $EXISTING_REQUEST = $_REQUEST; - $_REQUEST = $this->getParams(); - $request = $this->getLegacyRequest( - $_REQUEST, - array(), - array(), - array() - ); - $this->assertTrue($request->is_set('action')); - $request->un_set('action'); - $this->assertFalse($request->is_set('action')); - $this->assertTrue(isset($_REQUEST['action'])); - // unset 'id' param but from GLOBAL too - $this->assertTrue($request->is_set('id')); - $request->un_set('id', true); - $this->assertFalse($request->is_set('id')); - $this->assertFalse(isset($_REQUEST['id'])); - // reinstate $_REQUEST global - $_REQUEST = $EXISTING_REQUEST; - } - - - - public function testIpAddress() - { - // do the chevy shuffle with the $_SERVER global - // in case it's needed by other tests - $EXISTING_SERVER = $_SERVER; - $server_keys = array( - 'HTTP_CLIENT_IP', - 'HTTP_X_FORWARDED_FOR', - 'HTTP_X_FORWARDED', - 'HTTP_X_CLUSTER_CLIENT_IP', - 'HTTP_FORWARDED_FOR', - 'HTTP_FORWARDED', - 'REMOTE_ADDR', - ); - $x = 0; - // let's test 100 random IP addresses - while ($x < 100) { - // first clear out entries from previous test - foreach ($server_keys as $server_key) { - unset($_SERVER[$server_key]); - } - // randomly generate IP address. plz see: https://stackoverflow.com/a/39846883 - $ip_address = long2ip(mt_rand() + mt_rand() + mt_rand(0, 1)); - // then randomly populate one of the $_SERVER keys used to determine the IP - $_SERVER[$server_keys[mt_rand(0, 6)]] = $ip_address; - $request = $this->getLegacyRequest(array(), array(), array(), $_SERVER); - $this->assertEquals($ip_address, $request->ip_address()); - unset($request); - $x++; - } - // reinstate $_SERVER global - $_SERVER = $EXISTING_SERVER; - } - - - public function testMatches() - { - $request = $this->getLegacyRequest( - $this->getParams(), - array(), - array(), - array() - ); - $this->assertTrue($request->matches('event-*')); - $this->assertTrue($request->matches('*-name-*')); - $this->assertTrue($request->matches('event-name-*')); - $this->assertTrue($request->matches('event*name*')); - $this->assertTrue($request->matches('event?name*')); - $this->assertTrue($request->matches('event-name-123')); - $this->assertFalse($request->matches('event-name-?')); - } - - - public function testMatchesWithDrillDown() - { - $request = $this->getLegacyRequest( - array(), - $this->postParams(), - array(), - array() - ); - // our post data looks like this: - // array( - // 'input-a' => 'A', - // 'input-b' => 'B', - // 'sub' => array( - // 'sub-a' => 'AA', - // 'sub-b' => 'BB', - // 'sub-sub' => array( - // 'sub-sub-a' => 'AAA', - // 'sub-sub-b' => 'BBB', - // ) - // ) - // ); - // top-level value - $this->assertTrue($request->matches('input-?')); - $this->assertTrue($request->matches('input-*')); - // second level - $this->assertTrue($request->matches('sub[sub-?]')); - $this->assertTrue($request->matches('sub[sub-*]')); - // third level - $this->assertTrue($request->matches('sub[sub-sub][sub-sub-?]')); - $this->assertTrue($request->matches('sub[sub-sub][sub-sub-*]')); - // not set - $this->assertFalse($request->matches('input-c-*')); - $this->assertFalse($request->matches('sub[sub-c-*]')); - $this->assertFalse($request->matches('sub[sub-sub-*][sub-sub-c]')); - } - - public function testGetMatch() - { - $request = $this->getLegacyRequest( - $this->getParams(), - array(), - array(), - array() - ); - $this->assertEquals('Event 123', $request->getMatch('event-*')); - $this->assertEquals('Event 123', $request->getMatch('*-name-*')); - $this->assertEquals('Event 123', $request->getMatch('event-name-*')); - $this->assertEquals('Event 123', $request->getMatch('event*name*')); - $this->assertEquals('Event 123', $request->getMatch('event?name*')); - $this->assertEquals('Event 123', $request->getMatch('event-name-123')); - $this->assertNull($request->getMatch('event-name-?')); - // with default - $this->assertEquals('default', $request->getMatch('event-name-?', 'default')); - } - - - public function testGetMatchWithDrillDown() - { - $request = $this->getLegacyRequest( - array(), - $this->postParams(), - array(), - array() - ); - // our post data looks like this: - // array( - // 'input-a' => 'A', - // 'input-b' => 'B', - // 'sub' => array( - // 'sub-a' => 'AA', - // 'sub-b' => 'BB', - // 'sub-sub' => array( - // 'sub-sub-a' => 'AAA', - // 'sub-sub-b' => 'BBB', - // ) - // ) - // ); - // top-level value - $this->assertEquals('A', $request->getMatch('input-?')); - $this->assertEquals('A', $request->getMatch('input-*')); - // with default - $this->assertEquals('default', $request->getMatch('not-an-input-?', 'default')); - // second level - $this->assertEquals('AA', $request->getMatch('sub[sub-?]')); - $this->assertEquals('AA', $request->getMatch('sub[sub-*]')); - // with default - $this->assertEquals('default', $request->getMatch('sub[not-an-input-?]', 'default')); - // third level - $this->assertEquals('AAA', $request->getMatch('sub[sub-sub][sub-sub-?]')); - $this->assertEquals('AAA', $request->getMatch('sub[sub-sub][sub-sub-*]')); - // with default - $this->assertEquals('default', $request->getMatch('sub[sub-sub][not-an-input-?]', 'default')); - // not set - $this->assertNull($request->getMatch('input-c-*')); - $this->assertNull($request->getMatch('sub[sub-c-*]')); - $this->assertNull($request->getMatch('sub[sub-sub-*][sub-sub-c]')); - } -} -// Location: tests/testcases/core/request_stack/RequestTest.php diff --git a/tests/testcases/core/services/assets/RegistryTest.php b/tests/testcases/core/services/assets/RegistryTest.php deleted file mode 100644 index c5e5159b37d..00000000000 --- a/tests/testcases/core/services/assets/RegistryTest.php +++ /dev/null @@ -1,126 +0,0 @@ -registry = new Registry( - new AssetCollection(), - new i18nRegistry(array(), $domain) - ); - parent::setUp(); - } - - - public function tearDown() - { - parent::tearDown(); - $this->registry = null; - } - - - /** - * @throws InvalidArgumentException - */ - public function test_addData_no_previous_scalar() - { - $this->registry->addData('test', 'has_data'); - $actual = $this->registry->getData('test'); - $this->assertEquals('has_data', $actual); - } - - - /** - * @throws InvalidArgumentException - */ - public function test_addData_no_previous_array() - { - $this->registry->addData('test', array('has_data')); - $actual = $this->registry->getData('test'); - $this->assertEquals('has_data', $actual[0]); - } - - - /** - * @expectedException InvalidArgumentException - */ - public function test_addData_no_overwrite_array() - { - $this->registry->addData('test', array('initial_value')); - $this->registry->addData('test', array('another_value')); - } - - - /** - * @expectedException InvalidArgumentException - */ - public function test_addData_no_overwrite_scalar() - { - $this->registry->addData('test', 'initial_value'); - $this->registry->addData('test', 'cause_exception'); - } - - /** - * @expectedException InvalidArgumentException - * @group 10304 - */ - public function test_addTemplate_no_overwrite() - { - $this->registry->addTemplate('test', 'some_test_content'); - $this->registry->addTemplate('test', 'cause exception'); - } - - - /** - * @group 10304 - * @throws InvalidArgumentException - */ - public function test_getTemplate() - { - $this->registry->addTemplate('test', 'some test content'); - $this->assertEquals('some test content', $this->registry->getTemplate('test')); - } -} -// location: tests/testcases/core/services/assets/RegistryTest.php diff --git a/tests/testcases/core/services/cache/PostRelatedCacheManagerTest.php b/tests/testcases/core/services/cache/PostRelatedCacheManagerTest.php deleted file mode 100644 index 2e6339170a9..00000000000 --- a/tests/testcases/core/services/cache/PostRelatedCacheManagerTest.php +++ /dev/null @@ -1,147 +0,0 @@ -cache_manager = new PostRelatedCacheManagerMock( - new CacheStorageMock() - ); - } - - - private function getPostRelatedCache() - { - return (array)get_option(PostRelatedCacheManager::POST_CACHE_OPTIONS_KEY, array()); - } - - - private function updatePostRelatedCache(array $mock_cache = array()) - { - update_option(PostRelatedCacheManager::POST_CACHE_OPTIONS_KEY, $mock_cache); - } - - - public function testCachePrefix() - { - $this->assertEquals('ee_cache_post_', $this->cache_manager->cachePrefix()); - } - - - public function testGetPostRelatedCache() - { - $this->updatePostRelatedCache(array(123 => array('MOCK_CACHE'))); - $mock_cache = $this->cache_manager->getPostRelatedCache(); - $this->assertCount(1, $mock_cache); - $this->assertArrayHasKey(123, $mock_cache); - $this->assertCount(1, $mock_cache[123]); - $this->assertArrayContains('MOCK_CACHE', $mock_cache[123]); - // now test what happens if the cache is corrupted (need to update option directly) - update_option(PostRelatedCacheManager::POST_CACHE_OPTIONS_KEY, 'i am not serialized data'); - $this->assertEmpty($this->cache_manager->getPostRelatedCache()); - } - - - public function testUpdatePostRelatedCache() - { - // first save nothing to the cache - $this->updatePostRelatedCache(); - $this->assertEmpty($this->getPostRelatedCache()); - // then add our mock cache and verify - $this->cache_manager->updatePostRelatedCache(array(123 => array('MOCK_CACHE'))); - $mock_cache = $this->getPostRelatedCache(); - $this->assertCount(1, $mock_cache); - $this->assertArrayHasKey(123, $mock_cache); - $this->assertCount(1, $mock_cache[123]); - $this->assertArrayContains('MOCK_CACHE', $mock_cache[123]); - } - - - public function testClearPostRelatedCacheOnUpdate() - { - $this->updatePostRelatedCache(); - $this->assertEmpty($this->getPostRelatedCache()); - $this->cache_manager->clearPostRelatedCacheOnUpdate(123, 'MOCK_CACHE'); - $mock_cache = $this->getPostRelatedCache(); - $this->assertCount(1, $mock_cache); - $this->assertArrayHasKey(123, $mock_cache); - $this->assertCount(1, $mock_cache[123]); - $this->assertArrayContains('MOCK_CACHE', $mock_cache[123]); - // now try adding a duplicate, which should not happen - $this->cache_manager->clearPostRelatedCacheOnUpdate(123, 'MOCK_CACHE'); - $mock_cache = $this->getPostRelatedCache(); - $this->assertCount(1, $mock_cache); - $this->assertArrayHasKey(123, $mock_cache); - $this->assertCount(1, $mock_cache[123]); - $this->assertArrayContains('MOCK_CACHE', $mock_cache[123]); - } - - - public function testClearPostRelatedCache() - { - $this->updatePostRelatedCache(array(123 => array('MOCK_CACHE'))); - // first assert that the above exists as expected - $mock_cache = $this->getPostRelatedCache(); - $this->assertCount(1, $mock_cache); - $this->assertArrayHasKey(123, $mock_cache); - $this->assertCount(1, $mock_cache[123]); - $this->assertArrayContains('MOCK_CACHE', $mock_cache[123]); - // now clear it - $this->cache_manager->clearPostRelatedCache(123); - $this->assertEmpty($this->getPostRelatedCache()); - // now add a bunch of duplicated garbage - $this->updatePostRelatedCache( - array( - 123 => array( - 0 => 'MOCK_CACHE', - 1 => 'MOCK_CACHE', - 2 => 'MOCK_CACHE', - 3 => 'MOCK_CACHE', - 4 => 'MOCK_CACHE', - 5 => 'MOCK_CACHE', - ) - ) - ); - // and assert that the above exists as expected - $mock_cache = $this->getPostRelatedCache(); - $this->assertCount(1, $mock_cache); - $this->assertArrayHasKey(123, $mock_cache); - $this->assertCount(6, $mock_cache[123]); - $this->assertArrayContains('MOCK_CACHE', $mock_cache[123]); - // now attempt to clear another post ID that doesn't exist, which should clear duplicates - $this->cache_manager->clearPostRelatedCache(456); - $mock_cache = $this->getPostRelatedCache(); - $this->assertCount(1, $mock_cache); - $this->assertArrayHasKey(123, $mock_cache); - $this->assertCount(1, $mock_cache[123]); - $this->assertArrayContains('MOCK_CACHE', $mock_cache[123]); - } - -} -// Location: tests/testcases/core/services/cache/PostRelatedCacheManagerTest.php diff --git a/tests/testcases/core/services/cache/TransientCacheStorageTest.php b/tests/testcases/core/services/cache/TransientCacheStorageTest.php deleted file mode 100644 index b6ec5e9a2ae..00000000000 --- a/tests/testcases/core/services/cache/TransientCacheStorageTest.php +++ /dev/null @@ -1,219 +0,0 @@ -cache_storage = new \EventEspresso\core\services\cache\TransientCacheStorage(); - parent::setUp(); - } - - - - public function tearDown() - { - parent::tearDown(); - $this->cache_storage = null; - } - - - - /** - * @see http://stackoverflow.com/a/4356295 - * @param int $length - * @return string - */ - private function generateRandomString($length = 100) - { - $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - $charactersLength = strlen($characters); - $randomString = ''; - for ($i = 0; $i < $length; $i++) { - $randomString .= $characters[mt_rand(0, $charactersLength - 1)]; - } - return $randomString; - } - - - /** - * @group CacheStorageInterface - * @group slow_test - */ - public function test_add() - { - // echo "\n\n** " . __LINE__ . ") " . __METHOD__ . '() **'; - $key = __FUNCTION__; - $data = $this->generateRandomString(); - $added = $this->cache_storage->add($key, $data); - $this->assertTrue($added, __LINE__ . ") Transient {$key} was not added"); - $transient = get_transient($key); - $this->assertEquals($data, $transient); - // now test expiration - $key = __FUNCTION__ . '_expires_in_1_second'; - $added = $this->cache_storage->add($key, $data, 1); - $this->assertTrue($added, __LINE__ . ") Transient {$key} was not added"); - // wait 2 seconds - sleep(2); - $transient = get_transient($key); - $this->assertFalse($transient, __LINE__ . ") Transient {$key} returned data when it should not have"); - } - - - - /** - * @group CacheStorageInterface - * @group slow_test - */ - public function test_get() - { - // echo "\n\n** " . __LINE__ . ") " . __METHOD__ . '() **'; - $key = __FUNCTION__; - $data = $this->generateRandomString(); - $added = $this->cache_storage->add($key, $data); - $this->assertTrue($added, __LINE__ . ") Transient {$key} was not added"); - $transient = $this->cache_storage->get($key); - $this->assertEquals($data, $transient); - // now test expiration - $key = __FUNCTION__ . '_expires_in_1_second'; - $added = $this->cache_storage->add($key, $data, 1); - $this->assertTrue($added, __LINE__ . ") Transient {$key} was not added"); - // wait 2 seconds - sleep(2); - $transient = $this->cache_storage->get($key); - $this->assertNull($transient, __LINE__ . ") Transient {$key} returned data when it should not have"); - // now test standard cache early expiration - $key = __FUNCTION__ . '_expires_in_60_seconds'; - $added = $this->cache_storage->add($key, $data, 60); - $this->assertTrue($added, __LINE__ . ") Transient {$key} was not added"); - // wait 2 seconds - sleep(2); - $transient = $this->cache_storage->get($key); - // should be null because this request should trigger cache regeneration - // BEFORE the cache actually expires in roughly 58 seconds - $this->assertNull($transient, __LINE__ . ") Transient {$key} returned data when it should not have"); - // now attempt to retrieve the cache again, - $transient = $this->cache_storage->get($key); - // however, this second request should receive the cached content - // that still exists from before, therefore avoiding a cache stampede, - // (assuming the previous get() can regenerate the content in time) - $this->assertEquals($data, $transient, __LINE__ . ") Transient {$key} returned incorrect data"); - // now test with standard cache early expiration turned off - $key = __FUNCTION__ . '_not_standard_cache'; - $added = $this->cache_storage->add($key, $data, 60); - $this->assertTrue($added, __LINE__ . ") Transient {$key} was not added"); - // wait 2 seconds - sleep(2); - $transient = $this->cache_storage->get($key, false); - // cached content should be returned despite expiration being less than 60 seconds - // therefore avoiding a cache stampede, - // (assuming the previous get() can regenerate the content in time) - $this->assertEquals($data, $transient, __LINE__ . ") Transient {$key} returned incorrect data"); - } - - - /** - * @group CacheStorageInterface - */ - public function test_delete() - { - // echo "\n\n** " . __LINE__ . ") " . __METHOD__ . '() **'; - $key = __FUNCTION__; - $data = $this->generateRandomString(); - $added = $this->cache_storage->add($key, $data, 300); - $this->assertTrue($added, __LINE__ . ") Transient {$key} was not added"); - $transient = get_transient($key); - $this->assertEquals($data, $transient, __LINE__ . ") Transient {$key} returned incorrect data"); - $this->cache_storage->delete($key); - $transient = get_transient($key); - $this->assertFalse($transient, __LINE__ . ") Transient {$key} returned data when it should not have"); - } - - - - /** - * @group CacheStorageInterface - */ - public function test_deleteMany() - { - // echo "\n\n** " . __LINE__ . ") " . __METHOD__ . '() **'; - $data = $this->generateRandomString(); - $tests = array( - '_no_expiration_' => 0, - '_expires_in_5_minutes_' => 5 * MINUTE_IN_SECONDS, - '_expires_in_1_hour_' => HOUR_IN_SECONDS, - ); - foreach ($tests as $test => $expiration) { - // add transient with nearly identical name to confirm - // that deletion does not target transients it shouldn't - $added = set_transient($test, 'plz do not delete me', HOUR_IN_SECONDS); - $this->assertTrue($added, __LINE__ . ") Transient {$test} was not added"); - for ($x = 0; $x < 4; $x++) { - $key = __FUNCTION__ . $test . $x; - $added = $this->cache_storage->add($key, $data, $expiration); - $this->assertTrue($added, __LINE__ . ") Transient {$key} was not added"); - // assert that all transients exist - $transient = $this->cache_storage->get($key); - $this->assertEquals($data, $transient, __LINE__ . ") Transient {$key} returned incorrect data"); - } - } - // delete transients that expire in 5 minutes - $this->cache_storage->deleteMany(array(__FUNCTION__ . '_expires_in_5_minutes_')); - $results = array( - '_no_expiration_' => $data, - '_expires_in_5_minutes_' => false, - '_expires_in_1_hour_' => $data, - ); - foreach ($results as $test => $result) { - for ($x = 0; $x < 4; $x++) { - $key = __FUNCTION__ . $test . $x; - $message = $result - ? "Transient {$key} does not exist when it should" - : "Transient {$key} exists when it should not"; - $this->assertEquals($result, get_transient($key), $message); - } - // now confirm our similarly named transients still exist - $this->assertEquals( - 'plz do not delete me', - get_transient($test), - "Transient {$test} does not exist when it should" - ); - } - } - - - -} -// End of file CacheStorageTest.php -// Location:/tests/testcases/core/services/cache/TransientCacheStorageTest.php \ No newline at end of file diff --git a/tests/testcases/core/services/collections/iterators/CollectionFilterCallbackIteratorTest.php b/tests/testcases/core/services/collections/iterators/CollectionFilterCallbackIteratorTest.php deleted file mode 100644 index f83d1d40b70..00000000000 --- a/tests/testcases/core/services/collections/iterators/CollectionFilterCallbackIteratorTest.php +++ /dev/null @@ -1,62 +0,0 @@ -loose_collection = new LooseCollection(''); - parent::setUp(); - } - - - - public function tearDown() - { - parent::tearDown(); - $this->loose_collection = null; - } - - - public function testGetFiltered(){ - $ints = array(1,2,6,10,5,4,7,9,3,8); - foreach ($ints as $int) { - $this->loose_collection->add(new BasicIntVoMock($int)); - } - $filter_only_even_values = new CollectionFilterCallbackIterator( - $this->loose_collection, - function (BasicIntVoMock $int_vo) { - return $int_vo->intValue() % 2 === 0; - } - ); - $this->assertCount(5, $filter_only_even_values->getFiltered()); - //filter a specific number - $filter_num_six = new CollectionFilterCallbackIterator( - $this->loose_collection, - function (BasicIntVoMock $int_vo) { - return $int_vo->intValue() === 6; - } - ); - $filtered = $filter_num_six->getFiltered(); - $this->assertEquals(6, reset($filtered)->intValue()); - } -} \ No newline at end of file diff --git a/tests/testcases/core/services/commands/CommandBusTest.php b/tests/testcases/core/services/commands/CommandBusTest.php deleted file mode 100644 index 90f013a4f1a..00000000000 --- a/tests/testcases/core/services/commands/CommandBusTest.php +++ /dev/null @@ -1,181 +0,0 @@ - EE_Dependency_Map::load_from_cache,) - ); - // need to override the existing alias for the CommandHandlerManagerInterface - // or else the REAL class will still get used - EE_Dependency_Map::instance()->add_alias( - 'EventEspresso\core\services\commands\CommandHandlerManagerInterface', - 'EventEspresso\tests\mocks\core\services\commands\CommandHandlerManagerMock' - ); - parent::setUp(); - } - - - /** - * @param array $middleware - * @throws \PHPUnit\Framework\Exception - */ - protected function setupCommandBus(array $middleware = array()) - { - // setup a Bus that uses our Mocked CommandHandlerManager - $this->command_bus = new EventEspresso\core\services\commands\CommandBus( - new EventEspresso\tests\mocks\core\services\commands\CommandHandlerManagerMock(), - $middleware - ); - $this->assertInstanceOf( - 'EventEspresso\core\services\commands\CommandBus', - $this->command_bus - ); - } - - - /** - * @throws \PHPUnit\Framework\Exception - */ - public function testGetCommandHandlerManager() - { - $this->setupCommandBus(); - $this->assertInstanceOf( - 'EventEspresso\tests\mocks\core\services\commands\CommandHandlerManagerMock', - $this->command_bus->getCommandHandlerManager() - ); - } - - - /** - * @throws InvalidArgumentException - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException - * @throws \EventEspresso\core\services\commands\InvalidCommandHandlerException - * @throws \EventEspresso\core\services\commands\middleware\InvalidCommandBusMiddlewareException - * @throws \PHPUnit\Framework\Exception - */ - public function testExecute() - { - $this->setupCommandBus(); - // final results we want to see from CommandHandler - $you_did_it = 'you done gone an did it now'; - // create CommandHandler and set the results - $command_handler = new MockCommandHandler(); - $command_handler->results = $you_did_it; - // the Command we want to use - $command_fqcn = 'EventEspresso\tests\mocks\core\services\commands\MockCommand'; - $command_handler_manager = $this->command_bus->getCommandHandlerManager(); - // associate CommandHandler with the above Command - $command_handler_manager->addCommandHandler( - $command_handler, - $command_fqcn - ); - // execute Command and get results - $results = $this->command_bus->execute(new MockCommand()); - $this->assertEquals($you_did_it, $results); - } - - - /** - * @throws InvalidArgumentException - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException - * @throws \EventEspresso\core\services\commands\InvalidCommandHandlerException - * @throws \EventEspresso\core\services\commands\middleware\InvalidCommandBusMiddlewareException - * @throws \PHPUnit\Framework\Exception - */ - public function testExecuteWithPassingCapCheck() - { - // add CapChecker middleware that uses Mock that always returns true - $this->setupCommandBus( - array(new CapChecker(new CapabilitiesCheckerMock())) - ); - // final results we want to see from CommandHandler - $passed = 'this command passed its cap check'; - // create CommandHandler and set the results - $command_handler = new MockCommandHandler(); - $command_handler->results = $passed; - // the Command we want to use - $command_fqcn = 'EventEspresso\tests\mocks\core\services\commands\RequiresCapCheckMockCommand'; - $command_handler_manager = $this->command_bus->getCommandHandlerManager(); - // associate CommandHandler with the above Command (note that class names don't match, but that's ok) - $command_handler_manager->addCommandHandler( - $command_handler, - $command_fqcn - ); - $results = $this->command_bus->execute(new RequiresCapCheckMockCommand()); - $this->assertEquals($passed, $results); - } - - - /** - * @throws InvalidArgumentException - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException - * @throws \EventEspresso\core\services\commands\InvalidCommandHandlerException - * @throws \EventEspresso\core\services\commands\middleware\InvalidCommandBusMiddlewareException - * @throws \PHPUnit\Framework\AssertionFailedError - * @throws \PHPUnit\Framework\Exception - */ - public function testExecuteWithFailingCapCheck() - { - $capabilities_checker = new CapabilitiesCheckerMock(); - // now change the CapabilitiesChecker so that ALL cap checks fail - $capabilities_checker->cap_check_passes = false; - // add CapChecker middleware that uses Mock that always returns true - $this->setupCommandBus( - array(new CapChecker($capabilities_checker)) - ); - // final results we want to see from CommandHandler - $passed = 'this command should NOT pass its cap check'; - // create CommandHandler and set the results - $command_handler = new MockCommandHandler(); - $command_handler->results = $passed; - // the Command we want to use - $command_fqcn = 'EventEspresso\tests\mocks\core\services\commands\RequiresCapCheckMockCommand'; - $command_handler_manager = $this->command_bus->getCommandHandlerManager(); - // associate CommandHandler with the above Command - // note that the class names don't match, but that's ok, - // because this Mock doesn't really resolve classnames and instantiate objects, - // it just - $command_handler_manager->addCommandHandler( - $command_handler, - $command_fqcn - ); - $this->setExpectedException('EventEspresso\core\exceptions\InsufficientPermissionsException'); - $this->command_bus->execute(new RequiresCapCheckMockCommand()); - $this->fail('InsufficientPermissionsException should have been thrown'); - } - - - -} -// End of file CommandBusTest.php -// Location: testcases/core/services/commands/CommandBusTest.php diff --git a/tests/testcases/core/services/commands/CommandHandlerManagerTest.php b/tests/testcases/core/services/commands/CommandHandlerManagerTest.php deleted file mode 100644 index 4477805ec53..00000000000 --- a/tests/testcases/core/services/commands/CommandHandlerManagerTest.php +++ /dev/null @@ -1,98 +0,0 @@ - EE_Dependency_Map::load_from_cache,) - ); - parent::setUp(); - $this->command_handler_manager = EE_Registry::instance()->create( - 'EventEspresso\tests\testcases\core\services\commands\ExtendedCommandHandlerManager' - ); - } - - - - public function testAddCommandHandler() - { - $command_fqcn = 'EventEspresso\tests\mocks\core\services\commands\MockCommand'; - $this->command_handler_manager->addCommandHandler( - new MockCommandHandler(), - $command_fqcn - ); - $command_handlers = $this->command_handler_manager->getCommandHandlers(); - $this->assertArrayHasKey($command_fqcn, $command_handlers); - $this->assertInstanceOf( - 'EventEspresso\tests\mocks\core\services\commands\MockCommandHandler', - $command_handlers[$command_fqcn] - ); - } - - - - public function testGetCommandHandler() - { - // test regular CommandHandler - $command_handler = $this->command_handler_manager->getCommandHandler(new MockCommand()); - $this->assertInstanceOf( - 'EventEspresso\tests\mocks\core\services\commands\MockCommandHandler', - $command_handler - ); - } - - - - public function testGetCommandHandlerWithCompositeCommandHandler() - { - $this->command_handler_manager->addCommandHandler( - new MockCompositeCommandHandler( - new CommandBusMock(), - EE_Registry::instance()->create('EventEspresso\core\services\commands\CommandFactory') - ), - 'EventEspresso\tests\mocks\core\services\commands\MockCompositeCommand' - ); - $composite_command_handler = $this->command_handler_manager->getCommandHandler( - new MockCompositeCommand() - ); - $this->assertInstanceOf( - 'EventEspresso\tests\mocks\core\services\commands\MockCompositeCommandHandler', - $composite_command_handler - ); - $this->assertInstanceOf( - 'EventEspresso\tests\mocks\core\services\commands\CommandBusMock', - $composite_command_handler->commandBus() - ); - } - -} -// End of file CommandHandlerManagerTest.php -// Location: testcases/core/services/commands/CommandHandlerManagerTest.php \ No newline at end of file diff --git a/tests/testcases/core/services/commands/ExtendedCommandHandlerManager.php b/tests/testcases/core/services/commands/ExtendedCommandHandlerManager.php deleted file mode 100644 index 53114e524db..00000000000 --- a/tests/testcases/core/services/commands/ExtendedCommandHandlerManager.php +++ /dev/null @@ -1,35 +0,0 @@ -command_handlers; - } - - - -} -// End of file ExtendedCommandHandlerManager.php -// Location: EventEspresso\core\services\commands/ExtendedCommandHandlerManager.php \ No newline at end of file diff --git a/tests/testcases/core/services/container/CoffeeShopTest.php b/tests/testcases/core/services/container/CoffeeShopTest.php deleted file mode 100644 index 01fd1accca7..00000000000 --- a/tests/testcases/core/services/container/CoffeeShopTest.php +++ /dev/null @@ -1,612 +0,0 @@ -markTestSkipped('CoffeeShop DI not implemented yet.'); - // instantiate the container - $this->CoffeeShop = new CoffeeShop(); - // create a dependency injector class for resolving class constructor arguments - $this->DependencyInjector = new DependencyInjector( - $this->CoffeeShop, - new \EEH_Array() - ); - // and some coffeemakers, one for creating new instances - $this->CoffeeShop->addCoffeeMaker( - new NewCoffeeMaker($this->CoffeeShop, $this->DependencyInjector), - CoffeeMaker::BREW_NEW - ); - // and one for shared services - $this->CoffeeShop->addCoffeeMaker( - new SharedCoffeeMaker($this->CoffeeShop, $this->DependencyInjector), - CoffeeMaker::BREW_SHARED - ); - } - - - - public function addDefaultRecipes() - { - $this->CoffeeShop->addRecipe(new Recipe(Recipe::DEFAULT_ID)); - } - - - - public function addRecipeForRequest() - { - $this->CoffeeShop->addRecipe( - new Recipe( - 'EE_Request', - 'EE_Request', - array(), - array( - 'get'=> array(), - 'post' => array(), - 'cookie' => array(), - 'server' => array() - ), - CoffeeMaker::BREW_SHARED, - array(EE_CORE . 'request_stack/EE_Request.core.php') - ) - ); - // add recipe for Request, since we're going to need it - $this->CoffeeShop->brew( - 'EventEspresso\core\services\request\Request', - array($_GET, $_POST, $_COOKIE, $_SERVER), - CoffeeMaker::BREW_SHARED - ); - $this->CoffeeShop->addAliases( - 'EventEspresso\core\services\request\Request', - array('Request', 'EventEspresso\core\services\request\RequestInterface') - ); - /** @var EventEspresso\core\services\request\Request $request */ - $request = $this->CoffeeShop->brew('Request'); - /** @var \EE_Request $legacy_request */ - $legacy_request = $this->CoffeeShop->brew('EE_Request'); - $legacy_request->setRequest($request); - } - - - - public function test_addCoffeeMaker() - { - try { - // and CoffeeMaker for classes that do not require instantiation - $added = $this->CoffeeShop->addCoffeeMaker( - new LoadOnlyCoffeeMaker($this->CoffeeShop, $this->DependencyInjector), - CoffeeMaker::BREW_LOAD_ONLY - ); - $this->assertTrue($added); - } catch (Exception $e) { - $this->fail( - sprintf( - 'CoffeeShop::addCoffeeMaker() should Not have thrown the following Exception: %1$s' - ) - ); - } - } - - - - public function test_addClosure() - { - try { - $closure = function () { - return 'I AM CLOSURE'; - }; - $added = $this->CoffeeShop->addClosure('i-am-closure', $closure); - $this->assertInstanceOf('Closure', $added); - } catch (Exception $e) { - $this->fail( - sprintf( - 'CoffeeShop::addClosure() should Not have thrown the following Exception: %1$s', - $e->getMessage() - ) - ); - } - } - - - - public function test_addService() - { - try { - $added = $this->CoffeeShop->addService('i-am-stdClass', new stdClass()); - $this->assertTrue($added); - } catch (Exception $e) { - $this->fail( - sprintf( - 'CoffeeShop::addService() should Not have thrown the following Exception: %1$s', - $e->getMessage() - ) - ); - } - } - - - - public function test_addRecipe() - { - try { - // add default recipe, which should handle loading for most PSR-4 compatible classes - // as long as they are not type hinting for interfaces - $this->assertTrue( - $this->CoffeeShop->addRecipe(new Recipe(Recipe::DEFAULT_ID)) - ); - } catch (Exception $e) { - $this->fail( - sprintf( - 'CoffeeShop::addCoffeeMaker() should Not have thrown the following Exception: %1$s', - $e->getMessage() - ) - ); - } - } - - - - public function test_getRecipe() - { - $this->addDefaultRecipes(); - try { - $recipe = $this->CoffeeShop->getRecipe(Recipe::DEFAULT_ID); - $this->assertInstanceOf('EventEspresso\core\services\container\RecipeInterface', $recipe); - $this->assertEquals(Recipe::DEFAULT_ID, $recipe->identifier()); - $this->assertEquals(CoffeeMaker::BREW_NEW, $recipe->type()); - } catch (Exception $e) { - $this->fail( - sprintf( - 'CoffeeShop::getRecipe() should Not have thrown the following Exception: %1$s', - $e->getMessage() - ) - ); - } - } - - - - public function test_addAliases() - { - try { - $this->CoffeeShop->addAliases('EE_Class_For_Testing_Loading', array('Testing_Loading')); - } catch (Exception $e) { - $this->fail( - sprintf( - 'CoffeeShop::addAliases() should Not have thrown the following Exception: %1$s', - $e->getMessage() - ) - ); - } - } - - - - public function test_has() - { - $this->assertFalse($this->CoffeeShop->has('EE_Class_For_Testing_Loading')); - } - - - - public function test_get() - { - $this->addDefaultRecipes(); - try { - // attempt to get class that should NOT have a valid Recipe yet - $this->CoffeeShop->get('EE_Class_For_Testing_Loading'); - $this->fail('CoffeeShop::get() should have thrown an Exception'); - } catch (Exception $e) { - $this->assertInstanceOf('Exception', $e); - } - } - - - - public function test_brew_new() - { - $this->addDefaultRecipes(); - try { - // attempt to get class that should NOT have a valid Recipe yet - $this->CoffeeShop->get('EE_Class_For_Testing_Loading'); - $this->fail('CoffeeShop::get() should have thrown an Exception'); - } catch (Exception $e) { - $this->assertInstanceOf('Exception', $e); - } - // add recipe for our mock class - $added = $this->CoffeeShop->addRecipe( - new Recipe( - 'EE_Class_For_Testing_Loading', - 'EE_Class_For_Testing_Loading', - array(), - array(), - CoffeeMaker::BREW_NEW, - array( - EE_TESTS_DIR . 'mocks/core/EE_Class_For_Testing_Loading.core.php', - ) - ) - ); - $this->assertTrue($added); - // attempt to brew class - $mock1 = $this->CoffeeShop->brew('EE_Class_For_Testing_Loading'); - $this->assertInstanceOf('EE_Class_For_Testing_Loading', $mock1); - // and another one which should be a NEW instance - $mock2 = $this->CoffeeShop->brew('EE_Class_For_Testing_Loading'); - $this->assertInstanceOf('EE_Class_For_Testing_Loading', $mock2); - $this->assertFalse($mock1 === $mock2); - } - - - - public function test_brew_shared() - { - $this->addDefaultRecipes(); - try { - // attempt to get class that should NOT have a valid Recipe yet - $this->CoffeeShop->get('EE_Class_For_Testing_Loading'); - $this->fail('CoffeeShop::get() should have thrown an Exception'); - } catch (Exception $e) { - $this->assertInstanceOf('Exception', $e); - } - // add recipe for our mock class - $added = $this->CoffeeShop->addRecipe( - new Recipe( - 'EE_Class_For_Testing_Loading', - 'EE_Class_For_Testing_Loading', - array(), - array(), - CoffeeMaker::BREW_SHARED, - array( - EE_TESTS_DIR . 'mocks/core/EE_Class_For_Testing_Loading.core.php', - ) - ) - ); - $this->assertTrue($added); - // attempt to brew class - $mock1 = $this->CoffeeShop->brew('EE_Class_For_Testing_Loading'); - $this->assertInstanceOf('EE_Class_For_Testing_Loading', $mock1); - // and another one which should be the SAME instance - $mock2 = $this->CoffeeShop->brew('EE_Class_For_Testing_Loading'); - $this->assertInstanceOf('EE_Class_For_Testing_Loading', $mock2); - $this->assertTrue($mock1 === $mock2); - } - - - - public function test_brew_new_with_wildcard_recipe() - { - $this->addDefaultRecipes(); - try { - // attempt to get class that should NOT have a valid Recipe yet - $this->CoffeeShop->get('EE_Taxes'); - $this->fail('CoffeeShop::get() should have thrown an Exception'); - } catch (Exception $e) { - $this->assertInstanceOf('Exception', $e); - } - // now add recipe for loading our entities as shared services (singletons) - $added = $this->CoffeeShop->addRecipe( - new Recipe( - 'EE_*', - '', - array(), - array(), - CoffeeMaker::BREW_NEW, - array(EE_CLASSES . '*.class.php') - ) - ); - $this->assertTrue($added); - // attempt to brew EE_Taxes class since it is not coupled to EE_Base_Class - $object_1 = $this->CoffeeShop->brew('EE_Taxes', array()); - $this->assertInstanceOf('EE_Taxes', $object_1); - // and another one which should be the SAME instance - $object_2 = $this->CoffeeShop->brew('EE_Taxes', array()); - $this->assertInstanceOf('EE_Taxes', $object_2); - $this->assertFalse($object_1 === $object_2); - } - - - - public function test_brew_shared_with_wildcard_recipe() - { - $this->addDefaultRecipes(); - try { - // attempt to get class that should NOT have a valid Recipe yet - $this->CoffeeShop->get('EE_Taxes'); - $this->fail('CoffeeShop::get() should have thrown an Exception'); - } catch (Exception $e) { - $this->assertInstanceOf('Exception', $e); - } - // now add recipe for loading our entities as shared services (singletons) - $added = $this->CoffeeShop->addRecipe( - new Recipe( - 'EE_*', - '', - array(), - array(), - CoffeeMaker::BREW_SHARED, - array(EE_CLASSES . '*.class.php') - ) - ); - $this->assertTrue($added); - // attempt to brew EE_Taxes class since it is not coupled to EE_Base_Class - $object_1 = $this->CoffeeShop->brew('EE_Taxes', array()); - $this->assertInstanceOf('EE_Taxes', $object_1); - // and another one which should be the SAME instance - $object_2 = $this->CoffeeShop->brew('EE_Taxes', array()); - $this->assertInstanceOf('EE_Taxes', $object_2); - $this->assertTrue($object_1 === $object_2); - } - - - - /** - * @group CoffeeShopTestRequest - * @throws OutOfBoundsException - * @throws \EventEspresso\core\exceptions\InvalidClassException - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException - * @throws \EventEspresso\core\exceptions\InvalidIdentifierException - * @throws \EventEspresso\core\services\container\exceptions\InstantiationException - * @throws \EventEspresso\core\services\container\exceptions\ServiceExistsException - * @throws \EventEspresso\core\services\container\exceptions\ServiceNotFoundException - * @throws \PHPUnit\Framework\Exception - */ - public function test_brew_with_injected_dependency() - { - $this->addDefaultRecipes(); - $this->addRecipeForRequest(); - try { - // attempt to get class that should NOT have a valid Recipe yet - $this->CoffeeShop->get('EE_Session_Mock'); - $this->fail('CoffeeShop::get() should have thrown an Exception'); - } catch (Exception $e) { - $this->assertInstanceOf('Exception', $e); - } - // add default recipe for our mock classes - $added = $this->CoffeeShop->addRecipe( - new Recipe( - 'EE_*', - '', - array(), - array(), - CoffeeMaker::BREW_SHARED, - array( - EE_TESTS_DIR . 'mocks/core/*.core.php', - ) - ) - ); - $this->assertTrue($added); - // attempt to brew EE_Session_Mock class which type hints for EE_Encryption - // but first add alias for interface - $this->CoffeeShop->addAliases( - 'EventEspresso\core\services\cache\TransientCacheStorage', - 'EventEspresso\core\services\cache\CacheStorageInterface' - ); - $session = $this->CoffeeShop->brew('EE_Session_Mock'); - $this->assertInstanceOf('EE_Session_Mock', $session); - $this->assertInstanceOf('EE_Encryption', $session->encryption()); - } - - - - public function test_ingredients_and_dependency_substitution() - { - $this->addDefaultRecipes(); - // Add Recipe for using HonduranBean in place of BeanInterface - $this->CoffeeShop->addRecipe( - new Recipe( - 'HonduranBean', - 'EventEspresso\tests\mocks\core\services\container\HonduranBean', - array('EventEspresso\tests\mocks\core\services\container\BeanInterface'), - array(), - CoffeeMaker::BREW_SHARED - ) - ); - // Add Recipe for HonduranCoffee - $this->CoffeeShop->addRecipe( - new Recipe( - 'HonduranCoffee', - 'EventEspresso\tests\mocks\core\services\container\Coffee' - ) - ); - /** @var Coffee $HonduranCoffee */ - $HonduranCoffee = $this->CoffeeShop->brew('HonduranCoffee'); - // test it - $this->assertInstanceOf( - 'EventEspresso\tests\mocks\core\services\container\Coffee', - $HonduranCoffee, - "brew HonduranCoffee directly (should be instance of Coffee): " - ); - // test that bean type is an instance of HonduranBean - $this->assertInstanceOf( - 'EventEspresso\tests\mocks\core\services\container\HonduranBean', - $HonduranCoffee->getBeans(), - "bean type should be instance of HonduranBean" - ); - // Add another Recipe for KenyanCoffee - $this->CoffeeShop->addRecipe( - new Recipe( - 'KenyanCoffee', - 'EventEspresso\tests\mocks\core\services\container\Coffee' - ) - ); - /** @var Coffee $HonduranCoffee */ - $KenyanCoffee = $this->CoffeeShop->brew('KenyanCoffee'); - // test it - $this->assertInstanceOf( - 'EventEspresso\tests\mocks\core\services\container\Coffee', - $KenyanCoffee, - "brew KenyanCoffee directly (should be instance of Coffee): " - ); - // test that bean type is an instance of HonduranBean - $this->assertInstanceOf( - 'EventEspresso\tests\mocks\core\services\container\HonduranBean', - $KenyanCoffee->getBeans(), - "bean type should be instance of HonduranBean" - ); - // BUT... It can't be KenyanCoffee if it's using HonduranBean - // Remove Recipe for KenyanCoffee"; - $this->CoffeeShop->removeRecipe('KenyanCoffee'); - // and the Closure used for generating instances of KenyanCoffee - $this->CoffeeShop->removeClosure('KenyanCoffee'); - // Now Add NEW Recipe for KenyanCoffee that specifies KenyanBean - $this->CoffeeShop->addRecipe( - new Recipe( - 'KenyanCoffee', - 'EventEspresso\tests\mocks\core\services\container\Coffee', - array(), - array('EventEspresso\tests\mocks\core\services\container\BeanInterface' => 'EventEspresso\tests\mocks\core\services\container\KenyanBean'), - CoffeeMaker::BREW_NEW - ) - ); - // brew another KenyanCoffee directly - $KenyanCoffee = $this->CoffeeShop->brew('KenyanCoffee'); - $this->assertInstanceOf( - 'EventEspresso\tests\mocks\core\services\container\Coffee', - $KenyanCoffee, - "brew KenyanCoffee directly (should be instance of Coffee): " - ); - // and test that bean type is NOW an instance of KenyanBean - $this->assertInstanceOf( - 'EventEspresso\tests\mocks\core\services\container\KenyanBean', - $KenyanCoffee->getBeans(), - "bean type should be instance of KenyanBean" - ); - } - - - private function addClosureForCoffeeFactory() - { - $this->addDefaultRecipes(); - $this->addRecipeForRequest(); - // can't pass properties directly to a Closure - $coffee_shop = $this->CoffeeShop; - // create a Closure called "CoffeeFromRequest" - $this->CoffeeShop->addClosure( - 'CoffeeFactory', - function () use ($coffee_shop) - { - /** @var EventEspresso\core\services\request\Request $request */ - $request = $coffee_shop->brew('Request'); - $bean_type = $request->getRequestParam('bean_type', 'Honduran'); - $bean_type = in_array($bean_type, array('Honduran', 'Kenyan'), true) - ? "{$bean_type}Bean" - : 'HonduranBean'; - return $coffee_shop->brew( - 'EventEspresso\tests\mocks\core\services\container\Coffee', - array( - $coffee_shop->brew( - 'EventEspresso\tests\mocks\core\services\container\\' . $bean_type - ) - ) - ); - } - ); - } - - - - /** - * @group CoffeeShopAddClosure - * @throws OutOfBoundsException - * @throws \EventEspresso\core\exceptions\InvalidClassException - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException - * @throws \EventEspresso\core\exceptions\InvalidIdentifierException - * @throws \EventEspresso\core\services\container\exceptions\InstantiationException - * @throws \EventEspresso\core\services\container\exceptions\ServiceExistsException - * @throws \EventEspresso\core\services\container\exceptions\ServiceNotFoundException - * @throws \PHPUnit\Framework\Exception - */ - public function test_object_factories_using_addClosure() - { - $this->addClosureForCoffeeFactory(); - // brew a Coffee using the CoffeeFactory, - // which should use the default bean type since we haven't specified one - $default_coffee = $this->CoffeeShop->brew('CoffeeFactory'); - $this->assertInstanceOf( - 'EventEspresso\tests\mocks\core\services\container\Coffee', - $default_coffee, - 'should be instance of Coffee' - ); - // and test that default bean type is an instance of HonduranBean - $this->assertInstanceOf( - 'EventEspresso\tests\mocks\core\services\container\HonduranBean', - $default_coffee->getBeans(), - 'bean type should be instance of HonduranBean' - ); - } - - - /** - * @group CoffeeShopAddClosure - * @throws OutOfBoundsException - * @throws \EventEspresso\core\exceptions\InvalidClassException - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException - * @throws \EventEspresso\core\exceptions\InvalidIdentifierException - * @throws \EventEspresso\core\services\container\exceptions\InstantiationException - * @throws \EventEspresso\core\services\container\exceptions\ServiceExistsException - * @throws \EventEspresso\core\services\container\exceptions\ServiceNotFoundException - * @throws \PHPUnit\Framework\Exception - */ - public function test_object_factories_using_addClosure_and_get_param() - { - // first, add a $_GET param specifying the bean type as Kenyan - $_GET['bean_type'] = 'Kenyan'; - $this->addClosureForCoffeeFactory(); - // brew another Coffee using the CoffeeFactory - $new_coffee = $this->CoffeeShop->brew('CoffeeFactory'); - $this->assertInstanceOf( - 'EventEspresso\tests\mocks\core\services\container\Coffee', - $new_coffee, - 'should be instance of Coffee' - ); - // and test that bean type is NOW an instance of KenyanBean - $this->assertInstanceOf( - 'EventEspresso\tests\mocks\core\services\container\KenyanBean', - $new_coffee->getBeans(), - 'bean type should be instance of KenyanBean' - ); - } - - -} -// End of file CoffeeShopTest.php -// Location: testcases/core/services/container/CoffeeShopTest.php diff --git a/tests/testcases/core/services/context/ContextCheckerTest.php b/tests/testcases/core/services/context/ContextCheckerTest.php deleted file mode 100644 index 001b93d8027..00000000000 --- a/tests/testcases/core/services/context/ContextCheckerTest.php +++ /dev/null @@ -1,159 +0,0 @@ -context_checker = new ContextCheckerMock( - 'This-is-a-Test', - $this->acceptable_values - ); - } - - - public function testGetters() - { - $this->assertEquals('this-is-a-test', $this->context_checker->getIdentifier()); - $this->assertEquals($this->acceptable_values, $this->context_checker->getAcceptableValues()); - $this->assertInstanceOf('Closure', $this->context_checker->getEvaluationCallback()); - $context_checker = new ContextCheckerMock( - 'This-is-a-Test', - $this->acceptable_values, - function() { return true; } - ); - $this->assertInstanceOf('Closure', $context_checker->getEvaluationCallback()); - } - - - - public function testIsAllowed() - { - $this->assertTrue( - $this->context_checker->isAllowed( - new Context('context-one', 'for testing if context-one is valid') - ) - ); - $this->assertTrue( - $this->context_checker->isAllowed( - new Context('context-two', 'for testing if context-two is valid') - ) - ); - $this->assertFalse( - $this->context_checker->isAllowed( - new Context('context-three', 'for testing if context-three is valid') - ) - ); - } - - - public function testIsAllowedWithCustomCallback() - { - $context_three = new Context('context-three', 'for testing if context-three is valid'); - $context_checker_looking_for_three = new ContextCheckerMock( - 'looking-for-three', - $this->acceptable_values, - function (ContextInterface $context) - { - return strpos($context->slug(), 'three' ) !== false; - } - ); - $this->assertTrue($context_checker_looking_for_three->isAllowed($context_three)); - $context_checker_looking_for_four = new ContextCheckerMock( - 'looking-for-four', - $this->acceptable_values, - function (ContextInterface $context) - { - return strpos($context->slug(), 'four' ) !== false; - } - ); - $this->assertFalse($context_checker_looking_for_four->isAllowed($context_three)); - } - - - public function testIsAllowedWithFilter() - { - $context_five = new Context('context-five', 'for testing if context-five is valid'); - // hook into existing ContextChecker using default built-in evaluation callback, - // and add custom detection for the word "five" - add_filter( - 'FHEE__EventEspresso_core_domain_entities_context_ContextChecker__this-is-a-test__isAllowed', - function ($is_allowed, ContextInterface $context) - { - // if context slug contains the word "five" return true, else return previously evaluated result - return strpos($context->slug(), 'five') !== false - ? true - : $is_allowed; - }, - 10, - 2 - ); - $this->assertTrue($this->context_checker->isAllowed($context_five)); - remove_all_filters('FHEE__EventEspresso_core_domain_entities_context_ContextChecker__this-is-a-test__isAllowed'); - // now do it again, but looking for a value that will not be within the context slug - add_filter( - 'FHEE__EventEspresso_core_domain_entities_context_ContextChecker__this-is-a-test__isAllowed', - function ($is_allowed, ContextInterface $context) - { - // if context slug contains the word "six" return true, else return previously evaluated result - return strpos($context->slug(), 'six') !== false - ? true - : $is_allowed; - }, - 10, - 2 - ); - $this->assertFalse($this->context_checker->isAllowed($context_five)); - } - - - public function testIsAllowedWithFilteredAcceptableValues() - { - // and 'context-six' to list of acceptable values - add_filter( - 'FHEE__EventEspresso_core_domain_entities_context_ContextChecker__this-is-a-test__acceptableValues', - function ($acceptable_values) - { - $acceptable_values[] = 'context-six'; - return $acceptable_values; - } - ); - $this->assertTrue( - $this->context_checker->isAllowed( - new Context('context-six', 'for testing if context-six is valid') - ) - ); - } - - -} -// Location: /testcases/core/services/context/ContextCheckerTest.php diff --git a/tests/testcases/core/services/formatters/AsciiOnlyTest.php b/tests/testcases/core/services/formatters/AsciiOnlyTest.php deleted file mode 100644 index ec364ee6513..00000000000 --- a/tests/testcases/core/services/formatters/AsciiOnlyTest.php +++ /dev/null @@ -1,51 +0,0 @@ -formatter = new AsciiOnly(); - parent::__construct(); - } - - - - /** - */ - public function test_format(){ - //array keys are the strings, values are arrays containign each emoji in that string - $emoji_strings = array( - 'I feel 😁 today' => array('😁'), - 'I would like a taco 🌮, and some ramen 🍜 too' => array('🌮','🍜'), - 'Party 🈵 time' => array('🈵'), - ); - foreach($emoji_strings as $emoji_string => $emojis){ - $this->assertEquals( - str_replace($emojis,'',$emoji_string), - $this->formatter->format($emoji_string) - ); - } - } - - - - -} -// End of file EmojiRemovalTest.php -// Location: tests\testcases\core\services\formatters/EmojiRemovalTest.php \ No newline at end of file diff --git a/tests/testcases/core/services/loaders/CachingLoaderTest.php b/tests/testcases/core/services/loaders/CachingLoaderTest.php deleted file mode 100644 index 8f3c1f029df..00000000000 --- a/tests/testcases/core/services/loaders/CachingLoaderTest.php +++ /dev/null @@ -1,141 +0,0 @@ -load($this->getFqcnForTest()); - $this->assertInstanceOf( - $this->getFqcnForTest(), - $object, - sprintf( - '%1$s is not an instance of %2$s', - is_object($object) ? get_class($object) : print_r($object, true), - $this->getFqcnForTest() - ) - ); - $obj1ID = spl_object_hash($object); - // none of these objects are getting cached because it is turned off for unit testing - $object2 = self::$loader->load($this->getFqcnForTest()); - $obj2ID = spl_object_hash($object2); - $this->assertNotEquals($obj1ID, $obj2ID); - - //this time let's load the object with caching turned on so it gets in the cache and we'll send that objects - //hash along for the persistence test. - add_filter('FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache', '__return_false', 10); - return spl_object_hash(self::$loader->load($this->getFqcnForTest())); - } - - - - /** - * This tests persistence with caching on. - */ - public function testLoadCachingOn() - { - //turn caching on. - remove_all_filters('FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache'); - $this->assertEquals( - spl_object_hash(self::$loader->load($this->getFqcnForTest())), - spl_object_hash(self::$loader->load($this->getFqcnForTest())) - ); - } - - - /** - * This tests the resetting of cache - * - * @throws Exception - */ - public function testResetCache() - { - // turn caching on again - add_filter('FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache', '__return_false', 10); - // add a few different objects this time, but confirm that they are getting cached - $fqcn7 = '\EventEspresso\core\services\address\formatters\AddressFormatter'; - $object7 = self::$loader->load($fqcn7); - $this->assertInstanceOf($fqcn7, $object7); - $this->assertEquals(spl_object_hash($object7), spl_object_hash(self::$loader->load($fqcn7))); - $fqcn8 = '\EventEspresso\core\services\address\formatters\InlineAddressFormatter'; - $object8 = self::$loader->load($fqcn8); - $this->assertInstanceOf($fqcn8, $object8); - $this->assertEquals(spl_object_hash($object8), spl_object_hash(self::$loader->load($fqcn8))); - $fqcn9 = '\EventEspresso\core\services\address\formatters\MultiLineAddressFormatter'; - $object9 = self::$loader->load($fqcn9); - $this->assertInstanceOf($fqcn9, $object9); - $this->assertEquals(spl_object_hash($object9), spl_object_hash(self::$loader->load($fqcn9))); - $this->assertCount(3, self::$loader->getCache()); - // now reset the cache using the do_action() - do_action('AHEE__EventEspresso_core_services_loaders_CachingLoader__resetCache'); - $this->assertCount(0, self::$loader->getCache()); - // confirm that reloading the same FCQNs as above results in new objects - $this->assertNotEquals(spl_object_hash($object7), spl_object_hash(self::$loader->load($fqcn7))); - $this->assertNotEquals(spl_object_hash($object8), spl_object_hash(self::$loader->load($fqcn8))); - $this->assertNotEquals(spl_object_hash($object9), spl_object_hash(self::$loader->load($fqcn9))); - } - - - -} -// Location: testcases/core/services/loaders/CachingLoaderTest.php diff --git a/tests/testcases/core/services/loaders/CoreLoaderTest.php b/tests/testcases/core/services/loaders/CoreLoaderTest.php deleted file mode 100644 index a63274897d2..00000000000 --- a/tests/testcases/core/services/loaders/CoreLoaderTest.php +++ /dev/null @@ -1,72 +0,0 @@ -loader = new CoreLoader(EE_Registry::instance()); - } - - - - /** - * testBadConstruct - */ - public function testBadConstruct() - { - try { - $this->loader = new CoreLoader(new stdClass()); - $this->fail('EventEspresso\core\services\loaders\CoreLoader should have thrown an InvalidArgumentException'); - } catch (Exception $e) { - $this->assertTrue(true); - } - } - - - - /** - * testLoad - */ - public function testLoad() - { - $fqcn = '\EventEspresso\core\services\address\formatters\AddressFormatter'; - $formatter = $this->loader->load($fqcn); - $this->assertInstanceOf( - $fqcn, - $formatter, - sprintf( - '%1$s is not an instance of $fqcn', - is_object($formatter) ? get_class($formatter) : print_r($formatter, true), - $fqcn - ) - ); - } - -} - - -// End of file CoreLoaderTest.php -// Location: tests/testcases/core/services/loaders/CoreLoaderTest.php \ No newline at end of file diff --git a/tests/testcases/core/services/loaders/LoaderTest.php b/tests/testcases/core/services/loaders/LoaderTest.php deleted file mode 100644 index 198130a890f..00000000000 --- a/tests/testcases/core/services/loaders/LoaderTest.php +++ /dev/null @@ -1,132 +0,0 @@ -load($fqcn, array(), false); - $this->assertInstanceOf( - $fqcn, - $object, - sprintf( - '%1$s is not an instance of $fqcn', - is_object($object) ? get_class($object) : print_r($object, true), - $fqcn - ) - ); - // none of these objects are getting cached because it is turned off for unit testing - $object2 = self::$loader->load($fqcn, array(), false); - $this->assertFalse($object->sameInstance($object2)); - } - - - /** - * testSharedLoader - * - * @throws \PHPUnit\Framework\AssertionFailedError - * @throws \PHPUnit\Framework\Exception - */ - public function testSharedLoader() - { - // first turn caching on - add_filter('FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache', '__return_false'); - $fqcn = 'EventEspresso\tests\mocks\core\services\loaders\SharedClassToLoad'; - /** @var EventEspresso\tests\mocks\core\services\loaders\SharedClassToLoad $object */ - $object = self::$loader->load($fqcn); - $this->assertInstanceOf( - $fqcn, - $object, - sprintf( - '%1$s is not an instance of $fqcn', - is_object($object) ? get_class($object) : print_r($object, true), - $fqcn - ) - ); - // caching is on and we want a shared instance, so we should get the same object again - $object2 = self::$loader->load($fqcn); - $this->assertTrue($object->sameInstance($object2)); - } - - - /** - * testSharedLoader - * - * @group loaderArgs - * @throws \PHPUnit\Framework\AssertionFailedError - * @throws \PHPUnit\Framework\Exception - */ - public function testSharedLoaderWithArgs() - { - // first turn caching on - add_filter('FHEE__EventEspresso_core_services_loaders_CachingLoader__load__bypass_cache', '__return_false'); - $fqcn = 'EventEspresso\tests\mocks\core\services\loaders\SharedClassToLoad'; - $original_args = array(1, 2, 3); - /** @var EventEspresso\tests\mocks\core\services\loaders\SharedClassToLoad $object */ - $object = self::$loader->load($fqcn, array($original_args)); - $this->assertInstanceOf( - $fqcn, - $object, - sprintf( - '%1$s is not an instance of $fqcn', - is_object($object) ? get_class($object) : print_r($object, true), - $fqcn - ) - ); - $this->assertEquals($original_args, $object->args()); - // caching is on and we want a shared instance, - // but we are passing new args, so we should get a new object - $object2 = self::$loader->load($fqcn, array(array(4, 5, 6))); - $this->assertFalse($object->sameInstance($object2)); - $this->assertNotEquals($original_args, $object2->args()); - // now let's request another instance but with no args, which *should* return the first instance - $object3 = self::$loader->load($fqcn); - $this->assertTrue($object->sameInstance($object3)); - $this->assertEquals($original_args, $object3->args()); - } -} -// End of file LoaderTest.php -// Location: testcases/core/services/loaders/LoaderTest.php diff --git a/tests/testcases/core/services/loaders/ObjectIdentifierTest.php b/tests/testcases/core/services/loaders/ObjectIdentifierTest.php deleted file mode 100644 index 2bba0ed1dfb..00000000000 --- a/tests/testcases/core/services/loaders/ObjectIdentifierTest.php +++ /dev/null @@ -1,164 +0,0 @@ -object_identifier = LoaderFactory::getLoader()->getShared( - 'EventEspresso\core\services\loaders\ObjectIdentifier' - ); - } - - - /** - * dataProvider for testGetIdentifier() - * @return array[] - */ - public function getIdentifierProvider() - { - $object1 = new stdClass(); - $object1->prop1 = 1234; - $object1->prop2 = 'mom\'s spaghetti'; - $object1hash = spl_object_hash($object1); - return array( - // $fqcn, $arguments, $expected - 0 => array( - 'fully/qualified/class/name/DoesNotNeedToBeReal', - array(), - 'fully/qualified/class/name/DoesNotNeedToBeReal', - ), - 1 => array( - 'fully/qualified/class/name/DoesNotNeedToBeReal', - array(1, 2, 3, 4), - 'fully/qualified/class/name/DoesNotNeedToBeReal' . ObjectIdentifier::DELIMITER . md5('1234'), - ), - 2 => array( - 'fully/qualified/class/name/DoesNotNeedToBeReal', - array($object1), - 'fully/qualified/class/name/DoesNotNeedToBeReal' . ObjectIdentifier::DELIMITER . md5($object1hash), - ), - 3 => array( - 'fully/qualified/class/name/DoesNotNeedToBeReal', - array(1, 2, 3, 4, $object1), - 'fully/qualified/class/name/DoesNotNeedToBeReal' - . ObjectIdentifier::DELIMITER . md5('1234' . $object1hash), - ), - // test class that implements EventEspresso\core\interfaces\ReservedInstanceInterface - 4 => array( - 'EventEspresso\core\services\request\Request', - array(array(1, 2, 3, 4), array(), array(), array()), - 'EventEspresso\core\services\request\Request', - ), - ); - } - - - /** - * @dataProvider getIdentifierProvider - * @param string $fqcn - * @param array $arguments - * @param string $expected - */ - public function testGetIdentifier($fqcn, array $arguments, $expected) - { - $this->assertEquals( - $expected, - $this->object_identifier->getIdentifier($fqcn,$arguments) - ); - } - - - /** - * dataProvider for testHasArguments() - * - * @return array[] - */ - public function hasArgumentsProvider() - { - return array( - array('fully/qualified/class/Name', false), - array('fully/qualified/class/Name' . ObjectIdentifier::DELIMITER . md5('1234'), true), - ); - } - - - /** - * @dataProvider hasArgumentsProvider - * @param string $object_identifier - * @param bool $has_arguments - */ - public function testHasArguments($object_identifier, $has_arguments) - { - $this->assertEquals( - $has_arguments, - $this->object_identifier->hasArguments($object_identifier) - ); - } - - /** - * dataProvider for testFqcnMatchesObjectIdentifier() - * - * @return array[] - */ - public function fqcnMatchesObjectIdentifierProvider() - { - return array( - array('fully/qualified/class/Name', 'fully/qualified/class/Name', true), - array('fully/qualified/class/Name', 'fully/qualified/class/Name' . ObjectIdentifier::DELIMITER . md5('1234'), true), - array('fully/qualified/class/Name', 'fully/qualified/class/OtherName', false), - array('fully/qualified/class/Name', 'fully/qualified/class/OtherName' . ObjectIdentifier::DELIMITER . md5('1234'), false), - ); - } - - - /** - * @dataProvider fqcnMatchesObjectIdentifierProvider - * @param string $fqcn - * @param string $object_identifier - * @param bool $matches - */ - public function testFqcnMatchesObjectIdentifier($fqcn, $object_identifier, $matches) - { - $this->assertEquals( - $matches, - $this->object_identifier->fqcnMatchesObjectIdentifier( - $fqcn, - $object_identifier - ) - ); - } -} -// location: tests/testcases/core/services/loaders/ObjectIdentifierTest.php \ No newline at end of file diff --git a/tests/testcases/core/services/notices/AdminNoticeTest.php b/tests/testcases/core/services/notices/AdminNoticeTest.php deleted file mode 100644 index 13e2713d836..00000000000 --- a/tests/testcases/core/services/notices/AdminNoticeTest.php +++ /dev/null @@ -1,147 +0,0 @@ -extraErrorDetails(); - return new Notice( - $type, - $notice, - $dismissible, - $error_details->file, - $error_details->func, - $error_details->line - ); - } - - - public function noticeDetails() - { - return array( - (object)array( - 'type' => Notice::ERROR, - 'class' => 'error', - 'message' => 'this is an error message', - 'dismissible' => false, - ), - (object)array( - 'type' => Notice::ERROR, - 'class' => 'error', - 'message' => 'this is a dismissible error message', - 'dismissible' => true, - ), - (object)array( - 'type' => Notice::SUCCESS, - 'class' => 'success', - 'message' => 'this is a success message', - 'dismissible' => false, - ), - (object)array( - 'type' => Notice::SUCCESS, - 'class' => 'success', - 'message' => 'this is a dismissible success message', - 'dismissible' => true, - ), - (object)array( - 'type' => Notice::ATTENTION, - 'class' => 'warning', - 'message' => 'this is an attention message', - 'dismissible' => false, - ), - (object)array( - 'type' => Notice::ATTENTION, - 'class' => 'warning', - 'message' => 'this is a dismissible attention message', - 'dismissible' => true, - ), - (object)array( - 'type' => Notice::INFORMATION, - 'class' => 'info', - 'message' => 'this is an information message', - 'dismissible' => false, - ), - (object)array( - 'type' => Notice::INFORMATION, - 'class' => 'info', - 'message' => 'this is a dismissible information message', - 'dismissible' => true, - ), - ); - } - - - public function extraErrorDetails() - { - return (object)array( - 'file' => 'path/to/file.php', - 'func' => 'function', - 'line' => 123, - ); - } - - - public function testGetNotice() - { - $all_notice_details = $this->noticeDetails(); - foreach ($all_notice_details as $notice_details) { - $admin_notice = new \EventEspresso\core\services\notices\AdminNotice( - $this->createNotice( - $notice_details->type, - $notice_details->message, - $notice_details->dismissible - ) - ); - $this->assertEquals( - $this->noticeHtml( - $notice_details->type, - $notice_details->message, - $notice_details->dismissible, - $notice_details->class - ), - $admin_notice->getNotice() - ); - } - } - - - private function noticeHtml($type, $message, $dismissible, $class) - { - $notice = '

'; - $notice .= $message; - if ($type === Notice::ERROR) { - $notice .= '
file - function - 123'; - } - $notice .= '

'; - $notice .= '
'; - return $notice; - } - - -} -// Location: tests/testcases/core/services/notices/AdminNoticeTest.php diff --git a/tests/testcases/core/services/notices/NoticeTest.php b/tests/testcases/core/services/notices/NoticeTest.php deleted file mode 100644 index 33bae671b6a..00000000000 --- a/tests/testcases/core/services/notices/NoticeTest.php +++ /dev/null @@ -1,195 +0,0 @@ - true, - Notice::SUCCESS => true, - Notice::ATTENTION => true, - Notice::INFORMATION => true, - 'INVALID' => false, - ); - foreach ($types as $type => $valid) { - if (! $valid) { - $this->setExceptionExpected('EventEspresso\core\exceptions\InvalidDataTypeException'); - } - $notice = $this->createNotice($type); - $this->assertEquals($type, $notice->type()); - } - } - - - public function testValidMessage() - { - $notice = $this->createNotice(Notice::SUCCESS, 'valid message'); - $this->assertEquals('valid message', $notice->message()); - } - - - public function testMessageWithArray() - { - $this->setExceptionExpected('EventEspresso\core\exceptions\InvalidDataTypeException'); - $this->createNotice(Notice::SUCCESS, array('invalid message')); - } - - - public function testMessageWithObject() - { - $this->setExceptionExpected('EventEspresso\core\exceptions\InvalidDataTypeException'); - $this->createNotice(Notice::SUCCESS, new stdClass()); - } - - - public function testMessageWithInteger() - { - $this->setExceptionExpected('EventEspresso\core\exceptions\InvalidDataTypeException'); - $this->createNotice(Notice::SUCCESS, 12345); - } - - - public function testDismissible() - { - $dismissible_values = array( - true, - false, - 1, - 0, - 'true', - 'false', - 'yes', - 'no', - array(), - new stdClass(), - 12345, - 'nope', - ); - foreach ($dismissible_values as $dismissible) { - $notice = $this->createNotice(Notice::SUCCESS, 'valid message', $dismissible); - $this->assertEquals( - filter_var($dismissible, FILTER_VALIDATE_BOOLEAN), - $notice->isDismissible() - ); - } - } - - - public function testFile() - { - $files = array( - 0 => Notice::SUCCESS, - 1 => Notice::ATTENTION, - '' => Notice::INFORMATION, - 'valid_file.php' => Notice::ERROR, - 4 => Notice::ERROR, - ); - foreach ($files as $file => $type) { - // file is only required for Notice::ERROR types - if ($file === 4) { - $this->setExceptionExpected('EventEspresso\core\exceptions\InvalidDataTypeException'); - } - $notice = new Notice( - $type, - 'valid message', - true, - $file, - __FUNCTION__, - __LINE__ - ); - $this->assertEquals($type, $notice->type()); - } - } - - - public function testFunc() - { - $functions = array( - 0 => Notice::SUCCESS, - 1 => Notice::ATTENTION, - '' => Notice::INFORMATION, - __FUNCTION__ => Notice::ERROR, - 4 => Notice::ERROR, - ); - foreach ($functions as $function => $type) { - // file is only required for Notice::ERROR types - if ($function === 4) { - $this->setExceptionExpected('EventEspresso\core\exceptions\InvalidDataTypeException'); - } - $notice = new Notice( - $type, - 'valid message', - true, - __FILE__, - $function, - __LINE__ - ); - $this->assertEquals($type, $notice->type()); - } - } - - - public function testLine() - { - $lines = array( - '0' => Notice::SUCCESS, - '1' => Notice::ATTENTION, - '' => Notice::INFORMATION, - __LINE__ => Notice::ERROR, - 'number' => Notice::ERROR, - ); - foreach ($lines as $line => $type) { - // file is only required for Notice::ERROR types - if ($line === 'number') { - $this->setExceptionExpected('EventEspresso\core\exceptions\InvalidDataTypeException'); - } - $notice = new Notice( - $type, - 'valid message', - true, - __FILE__, - __FUNCTION__, - $line - ); - $this->assertEquals($type, $notice->type()); - } - } - - -} -// Location: tests/testcases/core/services/notices/NoticeTest.php diff --git a/tests/testcases/core/services/notices/NoticesContainerTest.php b/tests/testcases/core/services/notices/NoticesContainerTest.php deleted file mode 100644 index 08fc3edad7d..00000000000 --- a/tests/testcases/core/services/notices/NoticesContainerTest.php +++ /dev/null @@ -1,118 +0,0 @@ -notices_container = new NoticesContainer(); - } - - - /** - * @see https://stackoverflow.com/a/4356295 - * @return string - */ - public function generateRandomString() - { - $length = mt_rand(10, 50); - $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; - $charactersLength = strlen($characters); - $randomString = ''; - for ($i = 0; $i < $length; $i++) { - $randomString .= $characters[mt_rand(0, $charactersLength - 1)]; - } - return $randomString; - } - - - /** - * @return stdClass - */ - public function extraErrorDetails() - { - return (object)array( - 'file' => 'path/to/file.php', - 'func' => 'function', - 'line' => 123, - ); - } - - - public function containerMethods($type) - { - $add = "add{$type}"; - $count = "count{$type}"; - $get = "get{$type}"; - $has = "has{$type}"; - $error = $this->extraErrorDetails(); - $this->assertEquals(0, $this->notices_container->$count()); - for ($x = 1; $x <= 10; $x++) { - $message = $this->generateRandomString(); - if ($type === 'Error') { - $this->notices_container->$add( - $message, - $x % 2, - $error->file, - $error->func, - $error->line - ); - } else { - $this->notices_container->$add($message, $x % 2); - } - $this->assertTrue($this->notices_container->$has()); - $this->assertEquals($x, $this->notices_container->$count()); - } - $notices = $this->notices_container->$get(); - foreach ($notices as $notice) { - $this->assertInstanceOf('EventEspresso\core\services\notices\Notice', $notice); - } - } - - - public function testInformationMethods() - { - $this->containerMethods('Information'); - } - - - public function testAttentionMethods() - { - $this->containerMethods('Attention'); - } - - - public function testSuccessMethods() - { - $this->containerMethods('Success'); - } - - - public function testErrorMethods() - { - $this->containerMethods('Error'); - } -} -// Location: tests/testcases/core/services/notices/NoticesContainerTest.php diff --git a/tests/testcases/core/services/requests/RequestStackBuilderTest.php b/tests/testcases/core/services/requests/RequestStackBuilderTest.php deleted file mode 100644 index 0c2947363f0..00000000000 --- a/tests/testcases/core/services/requests/RequestStackBuilderTest.php +++ /dev/null @@ -1,259 +0,0 @@ -loader = LoaderFactory::getLoader(); - $this->request_stack_builder = $this->loader->getShared( - 'EventEspresso\tests\mocks\core\services\request\RequestStackBuilderMock', - array($this->loader) - ); - } - - - /** - * @return RequestStackCoreAppMock - */ - public function getCoreApp() - { - return $this->loader->getShared( - 'EventEspresso\tests\mocks\core\services\request\RequestStackCoreAppMock' - ); - } - - - /** - * @return Request - */ - public function getRequest() - { - return $this->loader->getShared( - 'EventEspresso\core\services\request\Request' - ); - } - - - /** - * @return Response - */ - public function getResponse() - { - return $this->loader->getShared( - 'EventEspresso\core\services\request\Response' - ); - } - - - /** - * @return array - */ - public function getNotices() - { - $notices = EE_Error::get_vanilla_notices(); - if(isset($notices['errors']['RequestStackCoreAppMock - handleRequest - 34'])) { - $notices['errors'][] = str_replace( - '
RequestStackCoreAppMock - handleRequest - 34', - '', - $notices['errors']['RequestStackCoreAppMock - handleRequest - 34'] - ); - unset($notices['errors']['RequestStackCoreAppMock - handleRequest - 34']); - } - return $notices; - } - - - /** - * @return void - */ - public function setMiddlewareFQCNs() - { - $this->obi_wan_kenobi = 'EventEspresso\tests\mocks\core\services\request\ObiWanKenobiWare'; - $this->general_grievous = 'EventEspresso\tests\mocks\core\services\request\GeneralGrievousWare'; - } - - - /** - * @param bool $legacy - * @return void - */ - public function addMiddleware($legacy = false) - { - $this->setMiddlewareFQCNs(); - if($legacy){ - $this->request_stack_builder->push(array(0, $this->general_grievous)); - $this->request_stack_builder->push(array(1, $this->obi_wan_kenobi)); - } else { - $this->request_stack_builder->push(array($this->general_grievous, array())); - $this->request_stack_builder->push(array($this->obi_wan_kenobi, array())); - } - } - - - /** - * @return void - */ - public function testRequestStackBuilderAsSplDoublyLinkedList() - { - $this->addMiddleware(); - // list should be FILO, so first in is at bottom of the stack - $first = $this->request_stack_builder->bottom(); - $first_fqcn = reset($first); - $this->assertEquals($this->general_grievous, $first_fqcn); - $last = $this->request_stack_builder->top(); - $last_fqcn = reset($last); - $this->assertEquals($this->obi_wan_kenobi, $last_fqcn); - } - - - /** - * returns following parameters: - * $middleware_app middleware app class details (FQCN, args array) - * $recurse true may call validateMiddlewareAppDetails() twice - * $expected expected middleware app class - * - * @return array - */ - public function middlewareAppProvider() - { - $this->setMiddlewareFQCNs(); - return array( - // empty array - array(array(), false, null), - // arguments in wrong order - array(array(array(), $this->obi_wan_kenobi), true, $this->obi_wan_kenobi), - // arguments in wrong order, no recurse - array(array(array(), $this->obi_wan_kenobi), false, null), - // legacy middleware - array(array(0, $this->obi_wan_kenobi), true, $this->obi_wan_kenobi), - // legacy middleware, no recurse - array(array(0, $this->obi_wan_kenobi), false, null), - // invalid FQCN - array(array('invalid/FQCN', array()), false, null), - // all good - array(array($this->obi_wan_kenobi, array()), true, $this->obi_wan_kenobi), - array(array($this->general_grievous, array()), true, $this->general_grievous), - ); - } - - - /** - * @dataProvider middlewareAppProvider - * @param array $middleware_app - * @param bool $recurse - * @param string $expected - * @throws \EventEspresso\core\services\request\InvalidRequestStackMiddlewareException - */ - public function testValidateMiddlewareAppDetails(array $middleware_app, $recurse, $expected) - { - if($recurse === false) { - $this->setExpectedException('EventEspresso\core\services\request\InvalidRequestStackMiddlewareException'); - $middleware_app_class = $this->request_stack_builder->validateMiddlewareAppDetails( - $middleware_app - ); - $this->assertEquals( - null, - $middleware_app_class, - 'An InvalidRequestStackMiddlewareException was expected but not thrown!' - ); - return; - } - $middleware_app = $this->request_stack_builder->validateMiddlewareAppDetails( - $middleware_app, - true - ); - $middleware_app_class = array_shift($middleware_app); - $this->assertEquals($expected, $middleware_app_class); - } - - - /** - * @return void - * @throws \Exception - */ - public function testRequestStackBuilderResolve() - { - $this->addMiddleware(); - $this->TheBattleOfUtapau(); - } - - /** - * @return void - * @throws \Exception - */ - public function testRequestStackBuilderResolveWithLegacyMiddleware() - { - $this->addMiddleware(true); - $this->TheBattleOfUtapau(); - } - - - /** - * @return void - * @throws \Exception - */ - public function TheBattleOfUtapau() - { - $request_stack = $this->request_stack_builder->resolve($this->getCoreApp()); - $this->assertInstanceOf( - 'EventEspresso\core\services\request\RequestStack', - $request_stack - ); - $this->assertEquals(0, EE_Error::has_notices()); - $request_stack->handleRequest($this->getRequest(), $this->getResponse()); - $notices = $this->getNotices(); - $this->assertCount(1, $notices['success']); - $this->assertEquals('Hello There!', $notices['success'][0]); - $this->assertCount(1, $notices['attention']); - $this->assertEquals('General Kenobi!', $notices['attention'][0]); - $this->assertCount(1, $notices['errors']); - $this->assertEquals('Back away! I will deal with this Jedi slime myself!', $notices['errors'][0]); - $request_stack->handleResponse(); - $notices = $this->getNotices(); - $this->assertCount(2, $notices['success']); - $this->assertEquals('Now, let\'s get a move on. We\'ve got a battle to win here.', $notices['success'][1]); - // now clear all notices - EE_Error::reset_notices(); - } -} -// location: tests/testcases/core/services/requests/RequestStackBuilderTest.php diff --git a/tests/testcases/espresso_Tests.php b/tests/testcases/espresso_Tests.php deleted file mode 100644 index adcaad8d5a3..00000000000 --- a/tests/testcases/espresso_Tests.php +++ /dev/null @@ -1,96 +0,0 @@ -assertTrue( defined('EVENT_ESPRESSO_VERSION') ); - $this->assertTrue( defined('EE_MIN_WP_VER_REQUIRED') ); - $this->assertTrue( defined('EE_MIN_WP_VER_RECOMMENDED') ); - $this->assertTrue( defined('EE_MIN_PHP_VER_RECOMMENDED') ); - $this->assertTrue( defined('EVENT_ESPRESSO_MAIN_FILE') ); - $this->assertTrue( defined('DS') ); - $this->assertTrue( defined('PS') ); - $this->assertTrue( defined('SP') ); - $this->assertTrue( defined('EE_SUPPORT_EMAIL') ); - $this->assertTrue( defined('EE_PLUGIN_BASENAME') ); - $this->assertTrue( defined('EE_PLUGIN_DIR_PATH') ); - $this->assertTrue( defined('EE_PLUGIN_DIR_URL') ); - $this->assertTrue( defined('EE_ADMIN_PAGES') ); - $this->assertTrue( defined('EE_CORE') ); - $this->assertTrue( defined('EE_MODULES') ); - $this->assertTrue( defined('EE_SHORTCODES') ); - $this->assertTrue( defined('EE_TEMPLATES') ); - $this->assertTrue( defined('EE_WIDGETS') ); - $this->assertTrue( defined('EE_CAFF_PATH') ); - $this->assertTrue( defined('EE_ADMIN') ); - $this->assertTrue( defined('EE_CPTS') ); - $this->assertTrue( defined('EE_CLASSES') ); - $this->assertTrue( defined('EE_MODELS') ); - $this->assertTrue( defined('EE_HELPERS') ); - $this->assertTrue( defined('EE_LIBRARIES') ); - $this->assertTrue( defined('EE_THIRD_PARTY') ); - $this->assertTrue( defined('EE_GLOBAL_ASSETS') ); - $this->assertTrue( defined('EE_GATEWAYS') ); - $this->assertTrue( defined('EE_GATEWAYS_URL') ); - $this->assertTrue( defined('EE_TEMPLATES_URL') ); - $this->assertTrue( defined('EE_GLOBAL_ASSETS_URL') ); - $this->assertTrue( defined('EE_IMAGES_URL') ); - $this->assertTrue( defined('EE_THIRD_PARTY_URL') ); - $this->assertTrue( defined('EE_HELPERS_ASSETS') ); - $this->assertTrue( defined('EVENT_ESPRESSO_UPLOAD_DIR') ); - $this->assertTrue( defined('EVENT_ESPRESSO_UPLOAD_URL') ); - $this->assertTrue( defined('EVENT_ESPRESSO_TEMPLATE_DIR') ); - $this->assertTrue( defined('EVENT_ESPRESSO_TEMPLATE_URL') ); - $this->assertTrue( defined('EVENT_ESPRESSO_GATEWAY_DIR') ); - $this->assertTrue( defined('EVENT_ESPRESSO_GATEWAY_URL') ); - $this->assertTrue( defined('EE_LANGUAGES_SAFE_LOC') ); - $this->assertTrue( defined('EE_LANGUAGES_SAFE_DIR') ); - $this->assertTrue( defined('EE_FRONT_AJAX') ); - $this->assertTrue( defined('EE_ADMIN_AJAX') ); - $this->assertTrue( defined('EE_INF_IN_DB') ); - } - - - /** - * espresso_load_required is run automatically when the plugin is loaded. - * - * That means we should have the following files already loaded: - * - EE_System - * - EE_Debug_Tools - * - EE_Error - * - * @since 4.3.0 - */ - function test_espresso_load_required() { - $this->assertTrue( class_exists( 'EE_System') ); - - //depends on WP_DEBUG - if( defined('WP_DEBUG') && WP_DEBUG ) - $this->assertTrue( class_exists( 'EEH_Debug_Tools') ); - else - $this->assertFalse( class_exists( 'EEH_Debug_Tools') ); - - $this->assertTrue( class_exists( 'EE_Error' ) ); - } -} diff --git a/tests/testcases/integration/EE_Line_Item__EE_Single_Registration_Line_Item_Filter__Integration_Test.php b/tests/testcases/integration/EE_Line_Item__EE_Single_Registration_Line_Item_Filter__Integration_Test.php deleted file mode 100644 index 6f80dd95428..00000000000 --- a/tests/testcases/integration/EE_Line_Item__EE_Single_Registration_Line_Item_Filter__Integration_Test.php +++ /dev/null @@ -1,153 +0,0 @@ -new_typical_transaction( array( 'ticket_types' => 2 ) ); - //add another ticket purchase for one of the same events - $event1 = EEM_Event::instance()->get_one( - array( array( 'Registration.TXN_ID' => $transaction->ID() ) ) - ); - $event_line_item = EEM_Line_Item::instance()->get_one( - array( - array( - 'TXN_ID' => $transaction->ID(), - 'OBJ_type' => 'Event', - 'OBJ_ID' => $event1->ID(), - ), - ) - ); - $this->new_model_obj_with_dependencies( - 'Line_Item', - array( - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_name' => 'event discount', - 'LIN_total' => -8, - 'LIN_unit_price' => -8, - 'LIN_quantity' => 1, - 'LIN_parent' => $event_line_item->ID(), - 'LIN_percent' => null, - 'LIN_order' => count( $event_line_item->children() ) - ) - ); - $total_line_item = $transaction->total_line_item(); - $total_line_item->recalculate_total_including_taxes(); - //and add an unrelated purchase - EEH_Line_Item::add_unrelated_item( $total_line_item, 'Transaction-Wide Discount', -5 ); - $totals = EEH_Line_Item::calculate_reg_final_prices_per_line_item( $total_line_item ); - // honestly the easiest way to confirm the total was right is to visualize the tree - // echo "\n\n " . __LINE__ . ') : visualize( $total_line_item )'; - // EEH_Line_Item::visualize( $total_line_item ); - // echo "\n\n " . __LINE__ . ') : $totals' . "\n"; - // var_dump( $totals ); - - //for each registration on the transaction, verify the REG_final_price - //indicated by EEH_Line_Item::calculate_reg_final_prices_per_line_item matches - //what the line item filters would have returned - EEH_Autoloader::register_line_item_filter_autoloaders(); - foreach( $transaction->registrations() as $registration ) { - $ticket_line_item = EEM_Line_Item::instance()->get_line_item_for_registration( $registration ); - $reg_final_price_from_line_item_helper = $totals[ $ticket_line_item->ID() ]; - //now get the line item filter's final price - $filters = new EE_Line_Item_Filter_Collection(); - $filters->add( new EE_Single_Registration_Line_Item_Filter( $registration ) ); - $line_item_filter_processor = new EE_Line_Item_Filter_Processor( $filters, $total_line_item ); - $filtered_line_item_tree = $line_item_filter_processor->process(); - // echo "\n\n " . __LINE__ . ') : visualize( $filtered_line_item_tree )'; - // EEH_Line_Item::visualize( $filtered_line_item_tree ); - $reg_final_price_from_line_item_filter = $filtered_line_item_tree->total(); - $this->assertLessThan( 0.2, abs( $reg_final_price_from_line_item_filter - $reg_final_price_from_line_item_helper ) ); - } - } - - /** - * like test_REG_final_price_matches_total_of_filtering_line_item_tree, - * but makes sure the tickets have sub-prices, because that has shown to have some - * bugs with calculations so far - */ - function test_REG_final_price_matches_total_of_filtering_line_item_tree__with_sub_line_items() { - $transaction = $this->new_typical_transaction( - array( - 'ticket_types' => 2, - 'fixed_ticket_price_modifiers' => 2, - ) - ); - //add another ticket purchase for one of the same events - $event1 = EEM_Event::instance()->get_one( - array( array( 'Registration.TXN_ID' => $transaction->ID() ) ) - ); - $event_line_item = EEM_Line_Item::instance()->get_one( - array( - array( - 'TXN_ID' => $transaction->ID(), - 'OBJ_type' => 'Event', - 'OBJ_ID' => $event1->ID() - ) - ) - ); - $this->new_model_obj_with_dependencies( - 'Line_Item', - array( - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_name' => 'event discount', - 'LIN_total' => -8, - 'LIN_unit_price' => -8, - 'LIN_quantity' => 1, - 'LIN_parent' => $event_line_item->ID(), - 'LIN_percent' => null, - 'LIN_order' => count( $event_line_item->children() ) - ) - ); - $total_line_item = $transaction->total_line_item(); - $total_line_item->recalculate_total_including_taxes(); - //and add an unrelated purchase - EEH_Line_Item::add_unrelated_item( $total_line_item, 'Transaction-Wide Discount', -5 ); - - $totals = EEH_Line_Item::calculate_reg_final_prices_per_line_item( $total_line_item ); - - // honestly the easiest way to confirm the total was right is to visualize the tree -// var_dump( $totals ); -// EEH_Line_Item::visualize( $total_line_item ); - - //for each registration on the transaction, verify the REG_final_price - //indicated by EEH_Line_Item::calculate_reg_final_prices_per_line_item matches - //what the line item filters would have returned - EEH_Autoloader::register_line_item_filter_autoloaders(); - foreach( $transaction->registrations() as $registration ) { - $ticket_line_item = EEM_Line_Item::instance()->get_line_item_for_registration( $registration ); - $reg_final_price_from_line_item_helper = $totals[ $ticket_line_item->ID() ]; - - //now get the line item filter's final price - $filters = new EE_Line_Item_Filter_Collection(); - $filters->add( new EE_Single_Registration_Line_Item_Filter( $registration ) ); - $line_item_filter_processor = new EE_Line_Item_Filter_Processor( $filters, $total_line_item ); - $filtered_line_item_tree = $line_item_filter_processor->process(); - $reg_final_price_from_line_item_filter = $filtered_line_item_tree->total(); - - $this->assertLessThan( 0.2, abs( $reg_final_price_from_line_item_filter - $reg_final_price_from_line_item_helper ) ); - } - } - - - -} - -// End of file EE_Line_Item__EE_Single_Registration_Line_Item_Filter__Integration_Test.php -// Location: testcases/integration/EE_Line_Item__EE_Single_Registration_Line_Item_Filter__Integration_Test.php \ No newline at end of file diff --git a/tests/testcases/misc/EE_Tests_Miscellaneous.php b/tests/testcases/misc/EE_Tests_Miscellaneous.php deleted file mode 100644 index 01d44644e4d..00000000000 --- a/tests/testcases/misc/EE_Tests_Miscellaneous.php +++ /dev/null @@ -1,27 +0,0 @@ -assertTrue( $EE_SYS instanceof EE_System ); - } -} diff --git a/tests/testcases/misc/EE_UnitTestCase_Test.php b/tests/testcases/misc/EE_UnitTestCase_Test.php deleted file mode 100644 index 9dc179c8470..00000000000 --- a/tests/testcases/misc/EE_UnitTestCase_Test.php +++ /dev/null @@ -1,128 +0,0 @@ -get_all_prices_that_are_taxes(); - $this->assertEquals(1, count( $taxes ) ); - $taxes_at_top_priority = array_shift( $taxes );//array shift twice because 2d array - $tax = array_shift( $taxes_at_top_priority ); - - //make transaction - $txn = $this->new_typical_transaction(); - - $this->assertEquals( 1.5, $taxable = $txn->tax_total() ); - //verify everything - $regs = $txn->registrations(); - $this->assertEquals(1, count( $regs ) ); - $reg = array_shift( $regs ); - $this->assertEquals( $txn->total(), $reg->final_price() ); - - $tkt = $reg->ticket(); - $this->assertEquals( $tkt->price() * ( 100 + $tax->amount()) / 100, $reg->final_price() ); - $this->assertTrue( $tkt->taxable() ); - - $total_line_item = $txn->total_line_item(); - $this->assertEquals( $txn->total(), $total_line_item->total() ); - - $this->_ensure_txn_on_line_item_and_children( $txn, $total_line_item ); - $this->assertNotEmpty( $txn->tax_total() ); - $this->assertEquals( $txn->ID(), $total_line_item->TXN_ID() ); - } - /** - * repeats the test because it originally failed when the test was repeated - * (because when we reset EE_Cart, it fetches the same one from the session, - * ie there was a bug in EE_Cart::reset) - */ - public function test_new_typical_transaction_again(){ - //there should be a tax in the system by default - $taxes = EEM_Price::instance()->get_all_prices_that_are_taxes(); - $this->assertEquals(1, count( $taxes ) ); - $taxes_at_top_priority = array_shift( $taxes );//array shift twice because 2d array - $tax = array_shift( $taxes_at_top_priority ); - - //make transaction - $txn = $this->new_typical_transaction(); - - //verify everything - $regs = $txn->registrations(); - $this->assertEquals(1, count( $regs ) ); - $reg = array_shift( $regs ); - $this->assertEquals( $txn->total(), $reg->final_price() ); - - $tkt = $reg->ticket(); - $this->assertEquals( $tkt->price() * ( 100 + $tax->amount()) / 100, $reg->final_price() ); - $this->assertTrue( $tkt->taxable() ); - - $total_line_item = $txn->total_line_item(); - $this->assertEquals( $txn->total(), $total_line_item->total() ); - - $this->_ensure_txn_on_line_item_and_children( $txn, $total_line_item ); - $this->assertNotEmpty( $txn->tax_total() ); - $this->assertEquals( $txn->ID(), $total_line_item->TXN_ID() ); - } - - public function test_new_typical_transaction__ticket_types_3(){ - $different_tickets_purchased = 3; - //there should be a tax in the system by default - $taxes = EEM_Price::instance()->get_all_prices_that_are_taxes(); - $this->assertEquals(1, count( $taxes ) ); - $taxes_at_top_priority = array_shift( $taxes );//array shift twice because 2d array - $tax = array_shift( $taxes_at_top_priority ); - - //make transaction - $txn = $this->new_typical_transaction( array('ticket_types'=>$different_tickets_purchased)); - - //verify everything - $regs = $txn->registrations(); - $this->assertEquals($different_tickets_purchased, count( $regs ) ); - - $sum_of_regs = 0; - foreach( $regs as $reg){ - $sum_of_regs += $reg->final_price(); - $reg = array_shift( $regs ); - $tkt = $reg->ticket(); - $this->assertEquals( $tkt->price() * ( 100 + $tax->amount()) / 100, $reg->final_price() ); - $this->assertTrue( $tkt->taxable() ); - } - $this->assertEquals( $txn->total(), $sum_of_regs ); - - - - $total_line_item = $txn->total_line_item(); - $this->assertEquals( $txn->total(), $total_line_item->total() ); - - $this->_ensure_txn_on_line_item_and_children( $txn, $total_line_item ); - $this->assertNotEmpty( $txn->tax_total() ); - $this->assertEquals( $txn->ID(), $total_line_item->TXN_ID() ); - } - - /** - * Checks line item and children list $txn as their transaction. - * Used by E_UnitTestCase_Test::test_new_typical_transaction() - * @param EE_Transaction $txn - * @param EE_Line_Item $line_item - */ - private function _ensure_txn_on_line_item_and_children( $txn, $line_item ){ - $this->assertEquals($txn->ID(), $line_item->TXN_ID() ); - foreach($line_item->children() as $child_line_item ){ - $this->_ensure_txn_on_line_item_and_children( $txn, $child_line_item ); - } - } -} -// End of file EE_UnitTestCase_Test.php \ No newline at end of file diff --git a/tests/testcases/misc/WP_Filesystem_permissions_UnitTestCases.php b/tests/testcases/misc/WP_Filesystem_permissions_UnitTestCases.php deleted file mode 100644 index 9bbce1c0140..00000000000 --- a/tests/testcases/misc/WP_Filesystem_permissions_UnitTestCases.php +++ /dev/null @@ -1,175 +0,0 @@ -assertTrue(is_a($wp_filesystem, 'WP_Filesystem_MockEEFS')); - $wp_filesystem->init('/'); - // Test creation/exists checks - $this->assertFalse($wp_filesystem->is_dir('/test/')); - $wp_filesystem->mkdir('/test'); - $this->assertTrue($wp_filesystem->exists('/test')); - $this->assertTrue($wp_filesystem->is_dir('/test/')); - $this->assertFalse($wp_filesystem->is_file('/test')); - //$this->assertFalse( true ); - } - - - - function test_mkdir() - { - global $wp_filesystem; - $wp_filesystem->init('/'); - $folder_path = '/test/'; - $wp_filesystem->mkdir($folder_path); - $this->assertTrue($wp_filesystem->exists($folder_path)); - $this->assertEquals(WP_Filesystem_MockFS_default_perms, $wp_filesystem->getchmod($folder_path)); - $this->assertEquals(WP_Filesystem_MockFS_default_owner, $wp_filesystem->owner($folder_path)); - $this->assertEquals(WP_Filesystem_MockFS_default_group, $wp_filesystem->group($folder_path)); - } - - - - function test_chmod() - { - global $wp_filesystem; - $wp_filesystem->init('/'); - $folder_path = '/test/'; - $wp_filesystem->mkdir($folder_path); - $this->assertEquals(WP_Filesystem_MockFS_default_perms, $wp_filesystem->getchmod($folder_path)); - $wp_filesystem->chmod($folder_path, 664); - $this->assertEquals(664, $wp_filesystem->getchmod($folder_path)); - } - - - - function test_chown() - { - global $wp_filesystem; - $wp_filesystem->init('/'); - $folder_path = '/test/'; - $wp_filesystem->mkdir($folder_path); - $this->assertEquals(WP_Filesystem_MockFS_default_owner, $wp_filesystem->owner($folder_path)); - $wp_filesystem->chown($folder_path, 'stranger'); - $this->assertEquals('stranger', $wp_filesystem->owner($folder_path)); - } - - - - function test_chgroup() - { - global $wp_filesystem; - $wp_filesystem->init('/'); - $folder_path = '/test/'; - $wp_filesystem->mkdir($folder_path); - $this->assertEquals(WP_Filesystem_MockFS_default_group, $wp_filesystem->group($folder_path)); - $success = $wp_filesystem->chgrp($folder_path, 'globe-trotters'); - $this->assertEquals('globe-trotters', $wp_filesystem->group($folder_path)); - } - - - - function test_is_readable() - { - global $wp_filesystem; - $wp_filesystem->init('/'); - $folder_path = '/test/'; - $wp_filesystem->mkdir($folder_path); - $this->assertEquals(WP_Filesystem_MockFS_default_perms, $wp_filesystem->getchmod($folder_path)); - $this->assertTrue($wp_filesystem->is_readable($folder_path)); - //switch to another user, although they should be able to read it too - $other_user_same_group = $wp_filesystem->add_system_user('other_user_same_group', WP_Filesystem_MockFS_default_group); - $other_user_other_group = $wp_filesystem->add_system_user('other_user_other_group', 'other_group'); - $wp_filesystem->change_current_system_user($other_user_other_group->username); - $this->assertTrue($wp_filesystem->is_readable($folder_path)); - $wp_filesystem->change_current_system_user(WP_Filesystem_MockFS_default_owner); - //change the permissions soo only someone in the same group can read - $wp_filesystem->chmod($folder_path, '770'); - $this->assertEquals('770', $wp_filesystem->getchmod($folder_path)); - $this->assertTrue($wp_filesystem->is_readable($folder_path)); - //and now check the user in the same group can still read... - $wp_filesystem->change_current_system_user($other_user_same_group->username); - $this->assertTrue($wp_filesystem->is_readable($folder_path)); - //..bu tthe user in a differeng group can't - $wp_filesystem->change_current_system_user($other_user_other_group->username); - $this->assertFalse($wp_filesystem->is_readable($folder_path)); - } - - - - function test_is_writable() - { - global $wp_filesystem; - $wp_filesystem->init('/'); - $folder_path = '/test/'; - $wp_filesystem->mkdir($folder_path); - $this->assertEquals(WP_Filesystem_MockFS_default_perms, $wp_filesystem->getchmod($folder_path)); - $this->assertTrue($wp_filesystem->is_writable($folder_path)); - //switch to another user, although they should be able to write it too - $other_user_same_group = $wp_filesystem->add_system_user('other_user_same_group', WP_Filesystem_MockFS_default_group); - $other_user_other_group = $wp_filesystem->add_system_user('other_user_other_group', 'other_group'); - $wp_filesystem->change_current_system_user($other_user_other_group->username); - $this->assertTrue($wp_filesystem->is_writable($folder_path)); - $wp_filesystem->change_current_system_user(WP_Filesystem_MockFS_default_owner); - //change the permissions soo only someone in the same group can read - $wp_filesystem->chmod($folder_path, '770'); - $this->assertEquals('770', $wp_filesystem->getchmod($folder_path)); - $this->assertTrue($wp_filesystem->is_writable($folder_path)); - //and now check the user in the same group can still write... - $wp_filesystem->change_current_system_user($other_user_same_group->username); - $this->assertTrue($wp_filesystem->is_writable($folder_path)); - //..bu tthe user in a differeng group can't - $wp_filesystem->change_current_system_user($other_user_other_group->username); - $this->assertFalse($wp_filesystem->is_writable($folder_path)); - } - -} - - diff --git a/tests/testcases/modules/EEDCoreRestApiTest.php b/tests/testcases/modules/EEDCoreRestApiTest.php deleted file mode 100644 index 5e3359e9a83..00000000000 --- a/tests/testcases/modules/EEDCoreRestApiTest.php +++ /dev/null @@ -1,536 +0,0 @@ - $ee_routes) { - foreach (EED_Core_Rest_Api::model_names_with_plural_routes('4.8.36') as $model_name => $model_classname) { - $model = EE_Registry::instance()->load_model($model_name); - $plural_model_route = EED_Core_Rest_Api::get_collection_route($model); - $singular_model_route = EED_Core_Rest_Api::get_entity_route($model, '(?P[^\/]+)'); - //currently, we expose models even for wp core routes to reading (we have plans to change this though) - //on https://events.codebasehq.com/projects/event-espresso/tickets/9583 - $this->assertArrayHasKey( - 0, - $ee_routes[$plural_model_route], - $plural_model_route - ); - //now let's double-check the singular routes too - $this->assertArrayHasKey( - 0, - $ee_routes[$singular_model_route], - $singular_model_route - ); - //wp core models should NOT have write endpoints - if ($model->is_wp_core_model()) { - //make sure there is no insert endpoint - $this->AssertArrayNotHasKey( - 1, - $ee_routes[$plural_model_route] - ); - //make sure there is no update or delete endpoints - $this->AssertArrayNotHasKey( - 1, - $ee_routes[$singular_model_route] - ); - $this->AssertArrayNotHasKey( - 2, - $ee_routes[$singular_model_route] - ); - } else { - //make sure there is an insert endpoint - $this->AssertArrayHasKey( - 1, - $ee_routes[$plural_model_route] - ); - //make sure there is update and delete endpoints - $this->assertArrayHasKey( - 1, - $ee_routes[$singular_model_route] - ); - $this->assertArrayHasKey( - 2, - $ee_routes[$singular_model_route] - ); - } - } - } - } - - - - /** - * @return array{ - * @type EEM_Base $model - * } - */ - public function dataProviderForTestGetAllCollectionRoutes() - { - $unit_test_data = array(); - foreach (array_keys(EED_Core_Rest_Api::model_names_with_plural_routes('4.8.36')) as $model_name) { - $model = EE_Registry::instance()->load_model($model_name); - //lets only verify requests for models with primary keys - if ($model->has_primary_key_field()) { - $unit_test_data[$model_name] = array($model); - } - } - return $unit_test_data; - } - - - - /** - * Verifies that, for each model from the data provider, we can query its GET routes - * - * @dataProvider dataProviderForTestGetAllCollectionRoutes - * @param EEM_Base $model - * @group big_rest_tests - */ - public function testGetAllCollectionRoutes(EEM_Base $model) - { - $this->authenticate_as_admin(); - //make sure there's an entry for this model. We will use it in an assertion later - $model_obj = $this->getAModelObjOfType($model); - $route = EED_Core_Rest_Api::get_versioned_route_to( - EED_Core_Rest_Api::get_collection_route($model), - '4.8.36' - ); - $response = rest_do_request( - new WP_REST_Request( - 'GET', - $route - ) - ); - $response_data = $response->get_data(); - $this->assertNotFalse($response_data); - $this->assertArrayNotHasKey( - 'code', - $response_data, - sprintf( - 'Got error response "%1$s" while querying route "%2$s"', - wp_json_encode($response_data), - $route - ) - ); - //verify we find the item we identified using the models - $contains_item = false; - foreach ($response_data as $datum) { - if ($datum[$model->primary_key_name()] == $model_obj->ID()) { - $contains_item = true; - break; - } - } - $this->assertTrue($contains_item); - } - - - - /** - * Verifies that all our models' singular GET routes work - * - * @dataProvider dataProviderForTestGetAllCollectionRoutes - * @param EEM_Base $model - * @group big_rest_tests - */ - public function testGetAllEntityRoutes(EEM_Base $model) - { - $this->authenticate_as_admin(); - //make sure there's an entry for this model. We will use it in an assertion later - $model_obj = $this->getAModelObjOfType($model); - $route = EED_Core_Rest_Api::get_versioned_route_to( - EED_Core_Rest_Api::get_entity_route($model, $model_obj->ID()), - '4.8.36' - ); - $response = rest_do_request( - new WP_REST_Request( - 'GET', - $route - ) - ); - $response_data = $response->get_data(); - $this->assertNotFalse($response_data); - $this->assertArrayNotHasKey( - 'code', - $response_data, - sprintf( - 'Got error response "%1$s" while querying route "%2$s"', - wp_json_encode($response_data), - $route - ) - ); - //verify we find the item we identified using the models - $this->assertEquals($model_obj->ID(), $response_data[$model->primary_key_name()]); - } - - - - /** - * @return array{ - * @type EEM_Base $model - * @type EE_Model_Relation_Base $relation_obj - * } - */ - public function dataProviderForTestGetAllRelatedRoutes() - { - $unit_test_data = array(); - $models_with_plural_routes = array_keys(EED_Core_Rest_Api::model_names_with_plural_routes('4.8.36')); - foreach ($models_with_plural_routes as $model_name) { - $model = EE_Registry::instance()->load_model($model_name); - foreach ($model->relation_settings() as $relation_name => $relation_obj) { - //lets only verify requests for models with primary keys - if ($model->has_primary_key_field()) { - $unit_test_data[$model_name] = array($model, $relation_obj); - } - } - } - return $unit_test_data; - } - - - - /** - * Verifies that all the existing related routes are queryable - * - * @dataProvider dataProviderForTestGetAllRelatedRoutes - * @param EEM_Base $model - * @param EE_Model_Relation_Base $relation_obj - * @group big_rest_tests - */ - public function testGetAllRelatedRoutes(EEM_Base $model, EE_Model_Relation_Base $relation_obj) - { - $related_model = $relation_obj->get_other_model(); - $this->authenticate_as_admin(); - $model_obj = $this->getAModelObjOfType($model); - $related_model_obj = $this->getAModelObjOfType($related_model); - $model_obj->_add_relation_to($related_model_obj, $related_model->get_this_model_name()); - - $route = EED_Core_Rest_Api::get_versioned_route_to( - EED_Core_Rest_Api::get_relation_route_via( - $model, - $model_obj->ID(), - $relation_obj - ), - '4.8.36' - ); - $response = rest_do_request( - new WP_REST_Request( - 'GET', - $route - ) - ); - $response_data = $response->get_data(); - $this->assertNotFalse($response_data); - $this->assertNotEmpty($response_data); - $this->assertNotNull($response_data); - $this->assertArrayNotHasKey( - 'code', - $response_data, - sprintf( - 'Got error response "%1$s" while querying route "%2$s"', - wp_json_encode($response_data), - $route - ) - ); - if ($relation_obj instanceof EE_Belongs_To_Relation){ - //only expect one result - $this->assertEquals($related_model_obj->ID(), $response_data[$related_model->primary_key_name()]); - } else { - //verify we find the item we identified using the models - $contains_item = false; - foreach ($response_data as $datum) { - if ($datum[$related_model->primary_key_name()] == $related_model_obj->ID()) { - $contains_item = true; - break; - } - } - $this->assertTrue($contains_item); - } - } - - - - /** - * Returns an array of model names which an object of type $model - * needs in order for queries for that model to return anything. - * (Because there are default model conditions that always join to that model - * when capabilities are being applied). - * - * @param string $model_name - * @return array - */ - protected function requiredRelationsInOrderToQuery($model_name) - { - $requirements = array( - 'Ticket_Template' => array('Ticket'), - ); - if (isset($requirements[$model_name])) { - return $requirements[$model_name]; - } else { - return array(); - } - } - - - - /** - * Fetches a model object of the specified type, or if none exists creates one. - * Also, verifies that model object has any related model objects which are - * needed in order to find that method object when applying caps - * (because capability conditions might join to that table) - * - * @param EEM_Base $model - * @param boolean $reuse_existing_objs whether to use existing model objects of this type, - * or always create a new one - * @return EE_Base_Class - */ - protected function getAModelObjOfType(EEM_Base $model, $reuse_existing_objs = true) - { - $model_obj = null; - if ($reuse_existing_objs) { - $model_obj = $model->get_one( - array( - 'caps' => EEM_Base::caps_read, - ) - ); - } - if (! $model_obj instanceof EE_Base_Class) { - $model_obj = $this->new_model_obj_with_dependencies($model->get_this_model_name()); - } - //add any data they might require in order to be queried - $required_relations = $this->requiredRelationsInOrderToQuery($model->get_this_model_name()); - foreach ($required_relations as $required_dependent_model_name) { - $related_model_obj = $this->new_model_obj_with_dependencies($required_dependent_model_name); - $model_obj->_add_relation_to($related_model_obj, $required_dependent_model_name); - } - return $model_obj; - } - - - - /** - * @return array{ - * @type EEM_Base $model - * } - */ - public function dataProviderForTestInsertsRoutes() - { - $unit_test_data = array(); - foreach (array_keys(EED_Core_Rest_Api::model_names_with_plural_routes('4.8.36')) as $model_name) { - $model = EE_Registry::instance()->load_model($model_name); - if (EED_Core_Rest_Api::should_have_write_endpoints($model)) { - //lets only verify requests for models with primary keys - if ($model->has_primary_key_field()) { - $unit_test_data[$model_name] = array($model); - } - } - } - return $unit_test_data; - } - - - - /** - * Verifies that, for each model from the data provider, we can use its INSERT routes - * - * @dataProvider dataProviderForTestInsertsRoutes - * @param EEM_Base $model - * @group big_rest_tests - */ - public function testInsertsRoutes(EEM_Base $model) - { - $this->authenticate_as_admin(); - $unsaved_model_obj = $this->new_model_obj_with_dependencies( - $model->get_this_model_name(), - array(), - false - ); - - $route = EED_Core_Rest_Api::get_versioned_route_to( - EED_Core_Rest_Api::get_collection_route($model), - '4.8.36' - ); - $insert_values = array(); - foreach ($unsaved_model_obj->get_model()->field_settings() as $field_name => $field_obj) { - $value_to_use = $field_obj instanceof EE_Datetime_Field - ? $unsaved_model_obj->get_DateTime_object($field_name) - : $unsaved_model_obj->get_raw($field_name); - $insert_values[$field_name] = ModelDataTranslator::prepareFieldValuesForJson( - $field_obj, - $value_to_use, - '4.8.36' - ); - } - $request = new WP_REST_Request( - 'POST', - $route - ); - $request->set_body_params($insert_values); - $response = rest_do_request( - $request - ); - $response_data = $response->get_data(); - $this->assertNotFalse($response_data); - $this->assertArrayNotHasKey( - 'code', - $response_data, - sprintf( - 'Got error response "%1$s" while POSTing to route "%2$s"', - wp_json_encode($response_data), - $route - ) - ); - } - - - - /** - * Verifies that, for each model from the data provider, we can use its DELETE routes - * - * @dataProvider dataProviderForTestInsertsRoutes - * @param EEM_Base $model - * @group big_rest_tests - */ - public function testDeleteRoutes(EEM_Base $model) - { - $this->authenticate_as_admin(); - $model_obj = $this->getAModelObjOfType($model, false); - $route = EED_Core_Rest_Api::get_versioned_route_to( - EED_Core_Rest_Api::get_entity_route($model, $model_obj->ID()), - '4.8.36' - ); - - $request = new WP_REST_Request( - 'DELETE', - $route - ); - $request->set_body_params( - array( - 'force' => true, - 'allow_blocking' => false - ) - ); - - $response = rest_do_request( - $request - ); - $response_data = $response->get_data(); - $this->assertNotFalse($response_data); - $this->assertArrayNotHasKey( - 'code', - $response_data, - sprintf( - 'Got error response "%1$s" while DELETEing on route "%2$s"', - wp_json_encode($response_data), - $route - ) - ); - $this->assertEquals(true, $response_data['deleted']); - $this->assertEquals($model_obj->ID(), $response_data['previous'][$model->primary_key_name()]); - } - - - /** - * Verifies that, for each model from the data provider, we can use its DELETE routes - * - * @dataProvider dataProviderForTestInsertsRoutes - * @param EEM_Base $model - * @group big_rest_tests - */ - public function testUpdateRoutes(EEM_Base $model) - { - $this->authenticate_as_admin(); - $model_obj = $this->getAModelObjOfType($model, false); - $route = EED_Core_Rest_Api::get_versioned_route_to( - EED_Core_Rest_Api::get_entity_route($model, $model_obj->ID()), - '4.8.36' - ); - - $request = new WP_REST_Request( - 'PUT', - $route - ); - $field_to_update = null; - foreach ($model->field_settings() as $field_obj) { - if (! $field_obj instanceof EE_Primary_Key_Field_Base) { - $field_to_update = $field_obj; - break; - } - } - if ($field_to_update instanceof EE_Boolean_Field) { - $set_value = ! $model_obj->get($field_to_update->get_name()); - } elseif ($field_to_update instanceof EE_Integer_Field - || $field_to_update instanceof EE_Float_Field - || $field_to_update instanceof EE_Foreign_Key_Int_Field) { - $set_value = $model_obj->get($field_to_update->get_name()) + 1; - } elseif ($field_to_update instanceof EE_Datetime_Field) { - $set_value = $model_obj->get_DateTime_object($field_to_update->get_name())->modify('+1 day'); - } elseif ($field_to_update instanceof EE_All_Caps_Text_Field - || $field_to_update instanceof EE_Foreign_Key_String_Field) { - $set_value = 'NEW'; - } else { - $set_value = 'new'; - } - //double check the new value won't be the same as the old one - $this->assertNotEquals( - $set_value, - $model_obj->get($field_to_update->get_name()), - $field_to_update->get_name() - ); - $request->set_body_params( - array( - $field_to_update->get_name() => ModelDataTranslator::prepareFieldValuesForJson( - $field_to_update, - $set_value, - '4.8.36' - ) - ) - ); - $response = rest_do_request( - $request - ); - $response_data = $response->get_data(); - $this->assertNotFalse($response_data); - $this->assertArrayNotHasKey( - 'code', - $response_data, - sprintf( - 'Got error response "%1$s" while PUTing on route "%2$s"', - wp_json_encode($response_data), - $route - ) - ); - if ($field_to_update instanceof EE_Datetime_Field) { - $current_value = $model_obj->get_DateTime_object($field_to_update->get_name()); - } else { - $current_value = $model_obj->get($field_to_update->get_name()); - } - $this->assertEquals($set_value, $current_value); - $this->assertEquals($model_obj->ID(), $response_data[$model->primary_key_name()]); - } -} -// End of file EEDCoreRestApiTest.php -// Location: /EEDCoreRestApiTest.php diff --git a/tests/testcases/modules/EED_Single_Page_Checkout_Test.php b/tests/testcases/modules/EED_Single_Page_Checkout_Test.php deleted file mode 100644 index fd4c0bfcdae..00000000000 --- a/tests/testcases/modules/EED_Single_Page_Checkout_Test.php +++ /dev/null @@ -1,112 +0,0 @@ -loadModuleMocks( array( 'EED_Single_Page_Checkout' ) ); - $this->spco_mock = EED_Single_Page_Checkout_Mock::instance(); - //add filter on permalink to add some noise - add_filter( 'page_link', array( $this, 'add_dummy_query_args' ) ); - // for some reason, whatever the reg_page_id is set on EE_Config is not an actual page in the db. - // so we first setup a page and set it as the reg page for the purpose of this test - $this->new_page_id = $this->factory->post->create( array( 'post_type' => 'page' ) ); - // then swap out existing reg page id with the new one - $this->original_reg_page_id = EE_Config::instance()->core->reg_page_id; - EE_Config::instance()->core->reg_page_id = $this->new_page_id; - } - - - - public function tearDown() { - EE_Config::instance()->core->reg_page_id = $this->original_reg_page_id; - // remove filter on permalink - remove_filter( 'page_link', array( $this, 'add_dummy_query_args' ) ); - parent::tearDown(); - } - - - - public function add_dummy_query_args( $link ) { - return add_query_arg( array( 'some_dummy_arg' => 'crazy' ), $link ); - } - - - - /** - * because older versions of WP don't have \WP_UnitTestCase::set_permalink_structure() - * - * @param string $structure - */ - public function set_permalink_structure( $structure = '' ) { - global $wp_rewrite; - $wp_rewrite->init(); - $wp_rewrite->set_permalink_structure( $structure ); - $wp_rewrite->flush_rules(); - } - - - - /** - * @group 10220 - * @group spco - */ - public function test_is_reg_page() { - $permalink_structures = array( - // plain /?p=123 - 'plain' => '', - // Day and name 2016/11/07/sample-post/ - 'day_name' => '/%year%/%monthnum%/%day%/%postname%/', - // Month and name http://local.wordpress.dev/2016/11/sample-post/ - 'month_name' => '/%year%/%monthnum%/%postname%/', - // Numeric http://local.wordpress.dev/archives/123 - 'numeric' => '/archives/%post_id%', - // Post name http://local.wordpress.dev/sample-post/ - 'post_name' => '/%postname%/', - ); - foreach ( $permalink_structures as $permalink_structure ) { - $this->set_permalink_structure( $permalink_structure ); - // example reg_page_permalink where a plugin or theme adds query params - // to links clicked by users for additional functionality that is NOT - // generated via filtering get_permalink. - $this->go_to( - add_query_arg( - array( - 'utm' => '5677', - 'campaign' => 'analytics_campaign', - ), - get_permalink( EE_Config::instance()->core->reg_page_id ) - ) - ); - //so we SHOULD be on the reg page - $this->assertTrue( $this->spco_mock->is_reg_checkout() ); - } - } - - -} -// End of file EED_Single_Page_Checkout_Test.php -// Location: tests/testcases/modules/EED_Single_Page_Checkout_Test.php \ No newline at end of file diff --git a/tests/testcases/modules/EED_Ticket_Sales_Monitor_Test.php b/tests/testcases/modules/EED_Ticket_Sales_Monitor_Test.php deleted file mode 100644 index 317be5a86f6..00000000000 --- a/tests/testcases/modules/EED_Ticket_Sales_Monitor_Test.php +++ /dev/null @@ -1,254 +0,0 @@ -set('TXN_ID', 0); - $this->assertEquals(0, $total_line_item->total()); - $ticket = $this->new_ticket(); - $ticket_line_item = EEH_Line_Item::add_ticket_purchase($total_line_item, $ticket, $ticket_count); - $this->assertInstanceOf('EE_Line_Item', $ticket_line_item); - $this->assertEquals($ticket_count, $ticket_line_item->quantity()); - $timestamp = time(); - if ($expired) { - $timestamp -= DAY_IN_SECONDS; - $this->fake_expired_cart($total_line_item, $timestamp); - } - $saved = $total_line_item->save_this_and_descendants_to_txn(); - // total, pretax, tax total, tax, event, ticket, price - $this->assertEquals(7, $saved); - $this->assertDateWithinOneMinute( - date('Y-m-d h:i a', $timestamp), - date('Y-m-d h:i a', $total_line_item->timestamp(true)), - 'Y-m-d h:i a' - ); - return $ticket_line_item; - } - - - /** - * sets timestamp for line item and descendants to past date - * - * @param EE_Line_Item $line_item - * @param int $timestamp - * @return void - * @throws EE_Error - * @throws InvalidArgumentException - * @throws ReflectionException - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException - */ - protected function fake_expired_cart(EE_Line_Item $line_item, $timestamp = 0) - { - $line_item->set('LIN_timestamp', $timestamp); - $children = $line_item->children(); - foreach ($children as $child_line_item) { - if ($child_line_item instanceof EE_Line_Item) { - $this->fake_expired_cart($child_line_item, $timestamp); - } - } - } - - - /** - * @param int $ticket_count - * @param int $line_item_count - * @return void - * @throws EE_Error - * @throws InvalidArgumentException - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException - * @throws \PHPUnit\Framework\Exception - */ - protected function confirm_ticket_line_item_counts($ticket_count = 1, $line_item_count = 1) - { - $ticket_line_items = EEM_Line_Item::instance()->get_all(array(array('OBJ_type' => 'Ticket'))); - $this->assertCount( - $line_item_count, - $ticket_line_items, - sprintf( - 'Line item count was %1$d when it should have been %2$d', - count($ticket_line_items), - $line_item_count - ) - ); - $qty = 0; - foreach ($ticket_line_items as $ticket_line_item) { - /** @var EE_Line_Item $ticket_line_item */ - $this->assertInstanceOf('EE_Line_Item', $ticket_line_item); - $qty += $ticket_line_item->quantity(); - } - $this->assertEquals( - $ticket_count, - $qty, - sprintf( - 'Ticket count was %1$d when it should have been %2$d', - $qty, - $ticket_count - ) - ); - } - - - /** - * generates all objects for each test and verifies all initial counts are correct - * - * @param array $cart_details - * @return array - * @throws EE_Error - * @throws InvalidArgumentException - * @throws ReflectionException - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException - * @throws \EventEspresso\core\exceptions\UnexpectedEntityException - * @throws \PHPUnit\Framework\Exception - */ - protected function setup_and_validate_tickets_for_carts(array $cart_details) - { - $cart_count = 0; - $total_ticket_count = 0; - foreach ($cart_details as $cart => $details) { - $cart_count++; - $total_ticket_count += $details['ticket_count']; - // simulate a couple of tickets that were added to the cart in the past - $ticket_line_item = $this->setup_cart_and_get_ticket_line_item( - $details['ticket_count'], - $details['expired'] - ); - // get ticket from line item - $ticket = $ticket_line_item->ticket(); - $this->assertInstanceOf('EE_Ticket', $ticket); - // confirm number of line items && tickets - $this->confirm_ticket_line_item_counts($total_ticket_count, $cart_count); - // this will increment ticket reserved count - EED_Ticket_Sales_Monitor::validate_ticket_sale($details['ticket_count'], $ticket); - $this->assertEquals( - $details['ticket_count'], - $ticket->reserved(), - sprintf( - 'The reserved ticket count for the %1$s ticket was %2$d when it should have been %3$d', - $cart, - $ticket->reserved(), - $details['ticket_count'] - ) - ); - // if cart is expired, the reserved count should get releases and end up as zero - $cart_details[$cart]['final_reserved_count'] = ! $details['expired'] ? $details['ticket_count'] : 0; - $cart_details[$cart]['ticket'] = $ticket; - } - return $cart_details; - } - - - /** - * Confirms that each ticket's reserved count matches what is expected - * - * @param array $cart_details - * @throws EE_Error - */ - protected function process_cart_results(array $cart_details) - { - foreach ($cart_details as $cart => $details) { - if ($details['ticket'] instanceof EE_Ticket) { - $this->assertEquals( - $details['final_reserved_count'], - $details['ticket']->reserved(), - sprintf( - 'The final reserved ticket count for the %1$s ticket after expired tickets were released, was %2$d when it should have been %3$d.', - $cart, - $details['ticket']->reserved(), - $details['final_reserved_count'] - ) - ); - } - } - } - - - /** - * @throws DomainException - * @throws EE_Error - * @throws InvalidArgumentException - * @throws ReflectionException - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException - * @throws \EventEspresso\core\exceptions\UnexpectedEntityException - * @throws \PHPUnit\Framework\Exception - */ - public function test_release_tickets_with_expired_carts() - { - $cart_results = $this->setup_and_validate_tickets_for_carts( - array( - 'expired cart' => array( - 'ticket_count' => 2, - 'expired' => true, - ), - 'valid cart' => array( - 'ticket_count' => 2, - 'expired' => false, - ), - ) - ); - EED_Ticket_Sales_Monitor::release_tickets_for_expired_carts(); - $this->process_cart_results($cart_results); - } - - - /** - * @throws DomainException - * @throws EE_Error - * @throws InvalidArgumentException - * @throws ReflectionException - * @throws \EventEspresso\core\exceptions\InvalidDataTypeException - * @throws \EventEspresso\core\exceptions\InvalidInterfaceException - * @throws \EventEspresso\core\exceptions\UnexpectedEntityException - * @throws \PHPUnit\Framework\Exception - */ - public function test_release_tickets_for_multiple_valid_carts() - { - $cart_results = $this->setup_and_validate_tickets_for_carts( - array( - 'first cart' => array( - 'ticket_count' => 4, - 'expired' => false, - ), - 'second cart' => array( - 'ticket_count' => 2, - 'expired' => false, - ), - ) - ); - EED_Ticket_Sales_Monitor::release_tickets_for_expired_carts(); - $this->process_cart_results($cart_results); - } - - -} -// End of file EED_Ticket_Sales_Monitor_Test.php -// Location: /tests/testcases/modules/EED_Ticket_Sales_Monitor_Test.php diff --git a/tests/testcases/modules/EE_CheckoutTest.php b/tests/testcases/modules/EE_CheckoutTest.php deleted file mode 100644 index 93e9ee80d0d..00000000000 --- a/tests/testcases/modules/EE_CheckoutTest.php +++ /dev/null @@ -1,35 +0,0 @@ -_test_settings = array( - 'login_id' => '534NmsVS', - 'transaction_key' => '9u64QUm4VzZ9x66d', - 'test_transactions' => FALSE, - 'debug_mode' => TRUE - ); - $this->_test_billing_info = array( - 'first_name' => 'auto', - 'last_name' => 'tester', - 'email' => 'few@ew.few', - 'address' => '2090 Nowhere Rd', - 'address2' => '', - 'city' => 'Whoville', - 'state' => 'Arkansas', - 'country' => 'US', - 'zip' => '84604', - 'credit_card' => '4007000000027', - 'cvv' => '123', - 'exp_month' => '05', - 'exp_year' => '2024', - 'company' => 'Event Espresso', - 'fax' => '1231231231', - 'phone' => '1231231231', - ); - } - public function setUp(){ - parent::setUp(); - EE_Payment_Method_Manager::reset(); - } - public function test_do_direct_payment__success(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Aim' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( $this->_test_settings ); - $t = $this->new_typical_transaction(); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() ) ); - $this->assertNotEquals( EEM_Payment::status_id_approved, $p->status() ); - - $p_processed = $ppg->do_direct_payment( $p, $this->_test_billing_info ); - $this->assertEquals( $p, $p_processed ); - $this->assertEquals( EEM_Payment::status_id_approved, $p_processed->status(), 'If this fails, verify the accounts transaction key hasntbeen updated. Here is the raw response from aim: ' . var_export( $p_processed->details(), true ) ); - $this->assertEquals( $t->total(), $p_processed->amount() ); - } - public function test_do_direct_payment__fail(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Aim' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( $this->_test_settings ); - $t = $this->new_typical_transaction(); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() ) ); - $this->assertNotEquals( EEM_Payment::status_id_declined, $p->status() ); - - $fail_billing_info = $this->_test_billing_info; - $fail_billing_info[ 'credit_card' ] = '4222222222222'; - $fail_billing_info[ 'zip' ] = '46282'; - - $p_processed = $ppg->do_direct_payment( $p, $fail_billing_info ); - $this->assertEquals( $p, $p_processed ); - $this->assertEquals( EEM_Payment::status_id_declined, $p_processed->status() ); - $this->assertEquals( $t->total(), $p_processed->amount() ); - } - public function test_do_direct_payment__partial_payment(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Aim' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( $this->_test_settings ); - $paid_so_far = 1.00; - $t = $this->new_typical_transaction(); - $t->set_paid( $paid_so_far ); - $previous_payment = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $paid_so_far ) ); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() - $paid_so_far ) ); - $this->assertNotEquals( EEM_Payment::status_id_approved, $p->status() ); - - $p_processed = $ppg->do_direct_payment( $p, $this->_test_billing_info ); - $this->assertEquals( EEM_Payment::status_id_approved, $p_processed->status() ); - $this->assertEquals( $t->total() - $paid_so_far, $p_processed->amount() ); - } - /** - * tests that even if the line items are too complicated for the gateway to handle, - * it can at least send the total payable - */ - public function test_do_direct_payment__total_mismatch(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Aim' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( $this->_test_settings ); - $t = $this->new_typical_transaction(); - $t->set_total( $t->total() / 2 ); - $t->total_line_item()->set_total ( $t->total() ); - $t->save(); - $t->total_line_item()->save(); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() ) ); - $this->assertNotEquals( EEM_Payment::status_id_approved, $p->status() ); - - $p_processed = $ppg->do_direct_payment( $p, $this->_test_billing_info ); - $this->assertEquals( EEM_Payment::status_id_approved, $p_processed->status() ); - $this->assertEquals( $t->total(), $p_processed->amount() ); - } -} - -// End of file EE_PMT_Aim_Test.php \ No newline at end of file diff --git a/tests/testcases/payment_methods/EE_PMT_Mijireh_Live_Test.php b/tests/testcases/payment_methods/EE_PMT_Mijireh_Live_Test.php deleted file mode 100644 index fb1393ae5bc..00000000000 --- a/tests/testcases/payment_methods/EE_PMT_Mijireh_Live_Test.php +++ /dev/null @@ -1,118 +0,0 @@ -_test_settings = array( - 'access_key' => '789a0b32d3d20d20514791a4', - ); - } - public function setUp(){ - parent::setUp(); - //make sure caf payment methods are registered - EE_Payment_Method_Manager::reset(); - } - public function test_set_redirect_info__success(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Mijireh' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( $this->_test_settings ); - $t = $this->new_typical_transaction(); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() ) ); - $this->assertEmpty( $p->redirect_url() ); - - - $p = $ppg->set_redirection_info( $p, NULL, self::return_url, self::notify_url, self::cancel_url ); - - $this->assertNotEmpty( $p->redirect_url() ); - $this->assertEquals( 0, strpos( $p->redirect_url(),self::mijireh_checkout_url_start) ); - $rargs = json_decode( $p->details() ); - $mijireh_items = $rargs->items; - $first_mijireh_item = array_shift( $mijireh_items ); - $this->assertEquals( - $t->primary_registration()->ticket()->name() . ' for ' . $t->primary_registration()->event_name(), - $first_mijireh_item->name - ); - $this->assertEquals( $t->primary_registration()->ticket()->price(), $first_mijireh_item->price ); - $this->assertEquals( 1, $first_mijireh_item->quantity ); - $this->assertEquals( $t->tax_total(), $rargs->tax ); - $this->assertEquals( self::return_url, $rargs->return_url ); - - } - public function test_set_redirect_info__fail(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Mijireh' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( array( 'access_key' => 'bogus_one') ); - $t = $this->new_typical_transaction(); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() ) ); - $this->assertEmpty( $p->redirect_url() ); - - $p = $ppg->set_redirection_info( $p, NULL, self::return_url, self::notify_url, self::cancel_url ); - //that should have thrown an error because the access key is bogus - $this->assertEmpty( $p->redirect_url() ); - - } - public function test_set_redirect_info__partial_payment(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Mijireh' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( $this->_test_settings ); - $paid_so_far = 1.00; - $t = $this->new_typical_transaction(); - $t->set_paid( $paid_so_far ); - $previous_payment = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $paid_so_far ) ); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() - $paid_so_far ) ); - $this->assertNotEquals( EEM_Payment::status_id_approved, $p->status() ); - - $p = $ppg->set_redirection_info( $p, NULL, self::return_url, self::notify_url, self::cancel_url ); - - $this->assertNotEmpty( $p->redirect_url() ); - $this->assertEquals( 0, strpos( $p->redirect_url(),self::mijireh_checkout_url_start) ); - } -// /** -// * tests that even if the line items are too complicated for the gateway to handle, -// * it can at least send the total payable -// */ - public function test_do_direct_payment__total_mismatch(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Mijireh' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( $this->_test_settings ); - $t = $this->new_typical_transaction(); - $t->set_total( $t->total() / 2 ); - $t->total_line_item()->set_total ( $t->total() ); - $t->save(); - $t->total_line_item()->save(); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() ) ); - $this->assertNotEquals( EEM_Payment::status_id_approved, $p->status() ); - - $p = $ppg->set_redirection_info( $p, NULL, self::return_url, self::notify_url, self::cancel_url ); - - $this->assertNotEmpty( $p->redirect_url() ); - $this->assertEquals( 0, strpos( $p->redirect_url(),self::mijireh_checkout_url_start) ); - } -} - -// End of file EE_PMT_Mijireh_Test.php \ No newline at end of file diff --git a/tests/testcases/payment_methods/EE_PMT_Mijireh_Test.php b/tests/testcases/payment_methods/EE_PMT_Mijireh_Test.php deleted file mode 100644 index f08aa98244f..00000000000 --- a/tests/testcases/payment_methods/EE_PMT_Mijireh_Test.php +++ /dev/null @@ -1,383 +0,0 @@ -_test_settings = array( - 'access_key' => self::access_key, - ); - add_filter( 'pre_http_request', array( $this, 'pre_http_request' ), 10, 3 ); - } - - public function setUp(){ - parent::setUp(); - //make sure caf payment methods are registered - new EE_Brewing_Regular( - EE_Registry::instance()->create( 'TableAnalysis', array(), true ) - ); - EE_Payment_Method_Manager::reset(); - } - - /** - * Verifies our fake responses actually match mijireh's live ones - * @group live - */ - public function test_pre_http_request(){ - - $not_found_result = wp_remote_post( 'https://secure.mijireh.com/non-existent-url', array() ); - $no_auth_result = wp_remote_post('https://secure.mijireh.com/api/1/orders',array()); - remove_filter( 'pre_http_request', array( $this, 'pre_http_request' ) ); - - $not_found_live_result = wp_remote_post( 'https://secure.mijireh.com/non-existent-url', array() ); - $no_auth_live_result = wp_remote_post('https://secure.mijireh.com/api/1/orders',array()); - - $this->assertHttpResponsesBasicallyEqual( $not_found_live_result, $not_found_result ); - $this->assertHttpResponsesBasicallyEqual( $no_auth_live_result, $no_auth_result ); - } - - protected function assertHttpResponsesBasicallyEqual( $live_response, $fake_response ) { - $this->assertEquals( gettype( $live_response ), gettype( $fake_response ) ); - if( is_array( $live_response ) && is_array( $fake_response ) ) { - //compare their bodies - if( isset( $live_response[ 'body' ] ) ) { - $live_body_sans_whitespace = preg_replace('/\s+/', '', $live_response[ 'body' ]); - $fake_body_sans_whitespace = preg_replace('/\s+/', '', $fake_response[ 'body' ]); - $this->assertEquals( $live_body_sans_whitespace, $fake_body_sans_whitespace ); - } - $this->assertEquals( $live_response[ 'response' ][ 'code' ], $fake_response[ 'response' ][ 'code' ] ); - $this->assertEquals( $live_response[ 'response' ][ 'message' ], $fake_response[ 'response' ][ 'message' ] ); - } - } - /** - * Prevents EEG_MIjireh from sending a real request to mijireh's server, and - * instead returns our own response - * @param boolean $response indicates we have overridden the normal wp_remote_request - * @param array $request_args exactly like wp_remote_request's 2nd arg - * @param string $url exactly like wp_remote_request's 1st arg - * @return array|WP_Error Array containing 'headers', 'body', 'response', 'cookies', 'filename'. - * A WP_Error instance upon error. - */ - public function pre_http_request( $response = FALSE, $request_args = array(), $url = '' ){ - if( strpos( $url, 'https://secure.mijireh.com/api/' ) !== FALSE && - $this->_authenticated( $request_args ) !== TRUE ){ - return $this->_authenticated( $request_args ); - } - switch( $url ){ - case 'https://secure.mijireh.com/api/1/orders': - return $this->_pre_http_request_orders( $request_args ); - default: - return array ( - 'headers' => - array ( - 'server' => 'nginx/1.6.2', - 'date' => 'Mon, 13 Oct 2014 20:28:11 GMT', - 'content-type' => 'text/html; charset=utf-8', - 'content-length' => '1140', - 'connection' => 'close', - 'status' => '404 Not Found', - 'x-request-id' => '37fdfb21e61db056b3a2fe8a123fb6ed', - 'x-runtime' => '0.002438', - 'x-rack-cache' => 'invalidate, pass', - ), - 'body' => ' - - - The page you were looking for doesn\'t exist (404) - - - - - - - - 404 Logo - - - ', - 'response' => - array ( - 'code' => 404, - 'message' => 'Not Found', - ), - 'cookies' => array (), - 'filename' => NULL, - ); - } - } - - protected function _authenticated( $request_args ){ - if( isset( $request_args[ 'headers' ][ 'Authorization' ] ) && - $request_args[ 'headers' ][ 'Authorization' ] == 'Basic ' . base64_encode( self::access_key . ':' )){ - return TRUE; - }else{ - return array ( - 'headers' => - array ( - 'server' => 'nginx/1.6.2', - 'date' => 'Mon, 13 Oct 2014 20:30:25 GMT', - 'content-type' => 'text/plain', - 'content-length' => '0', - 'connection' => 'close', - 'status' => '401 Unauthorized', - 'www-authenticate' => 'Basic realm="API Authorization"', - 'x-ua-compatible' => 'IE=Edge,chrome=1', - 'cache-control' => 'no-cache', - 'x-request-id' => '5a4b32e35e548381243d478c344b9894', - 'x-runtime' => '0.001448', - 'x-rack-cache' => 'invalidate, pass', - ), - 'body' => '', - 'response' => - array ( - 'code' => 401, - 'message' => 'Unauthorized', - ), - 'cookies' => array(), - 'filename' => NULL, - ); - } - } - /** - * Validste the /orders request. If valid return TRUE, if invalid return an entire - * response like wp_remote_request() - * @param array $req_args like 2nd arg to wp_remote_request() - * @return boolean or array - */ - protected function _valid_orders_request( $req_args ) { - $req_body = (array) json_decode( $req_args[ 'body' ], TRUE ); - //required parameters: - $required_keys = array( - 'total','return_url','items','email','first_name','last_name','tax','partner_id', - ); - $address_fields = array( - 'first_name', - 'last_name', - 'street', - 'city', - 'state_province', - 'zip_code', - 'country' - ); - $missing_keys = array(); - foreach( $required_keys as $key ){ - if( ! isset( $req_body[ $key ] ) ){ - $missing_keys[ $key ] = array( 'This field is required' ); - } - } - if( isset($req_args['billing_address'] ) ){ - foreach( $address_fields as $field){ - if( ! isset( $req_body[ 'billing_address' ][ $field ] ) ){ - $missing_keys[ $key ] = array( 'This field is required' ); - } - } - } - if( isset($req_body['shipping_address'] ) ){ - foreach( $address_fields as $field){ - if( ! isset( $req_body[ 'shipping_address' ][ $field ] ) ){ - $missing_keys[ $key ] = array( 'This field is required' ); - } - } - } - if( empty( $missing_keys ) ){ - return TRUE; - }else{ - return array( 'headers' => array ( - 'server' => 'nginx/1.6.2', - 'date' => 'Tue, 14 Oct 2014 22:19:37 GMT', - 'content-type' => 'application/json', - 'content-length' => '54', - 'connection' => 'close', - 'status' => '400 Bad Request', - 'x-ua-compatible' => 'IE=Edge,chrome=1', - 'cache-control' => 'no-cache', - 'x-request-id' => '1b777de9a7ff95091a3833574815ddae', - 'x-runtime' => '0.008036', - 'x-rack-cache' => 'invalidate, pass', - ), - 'body' => wp_json_encode( $missing_keys ), - 'response' => array ( - 'code' => 400, - 'message' => 'Bad Request', - ), - 'cookies' => array (), - 'filename' => NULL -); - } - } - - /** - * Handles a request to the /orders endpoint - * @param array $request_args exactly like 2nda rg of wp_remote_request - */ - protected function _pre_http_request_orders( $request_args = array() ){ - $valid_request_response = $this->_valid_orders_request( $request_args ); - if( $valid_request_response !== TRUE ){ - return $valid_request_response; - } - $req_body = (array) json_decode( $request_args[ 'body' ] ); - //directly take: email, first name, lastname, total, tax, discount (optional), shipping(optional) - //return_url, items, meta_data(optional),shipping_address,billing_address, - - $response_body = array( - 'order_number' => '1C107D792D2BACDE25F0FB77', - 'mode' => 'test', - 'status' => 'pending', - 'subtotal' => $req_body[ 'total' ], //- tax - discount - 'order_date' => current_time('Y-m-dTh:i:sP'), - 'ip_address' => NULL, - 'checkout_url' => 'https://secure.mijireh.com/checkout/1C107D792D2BACDE25F0FB77', - 'authorization' => NULL, - 'reference' => NULL, - 'discount' => "0.0", - 'shipping' => "0.0", - 'meta_data' => array(), - ); - $response_body = array_merge( $response_body, $req_body ); - $response_body_encoded = wp_json_encode( $response_body ); - return array ( - 'headers' => array ( - 'server' => 'nginx/1.6.2', - 'date' => 'Tue, 14 Oct 2014 18:32:49 GMT', - 'content-type' => 'application/json', - 'content-length' => '1062', - 'connection' => 'close', - 'status' => '201 Created', - 'x-ua-compatible' => 'IE=Edge,chrome=1', - 'etag' => '"d873a8aed59ee0f209eabab8a091a99b"', - 'cache-control' => 'max-age=0, private, must-revalidate', - 'x-request-id' => '44d6e48973e2e3a9fb69487b4db3505d', - 'x-runtime' => '0.009811', - 'x-rack-cache' => 'invalidate, pass', - ), - 'body' => $response_body_encoded,//'{"order_number":"1C107D792D2BACDE25F0FB77","email":"","first_name":"8_ATT_fname","last_name":"8_ATT_lname","mode":"test","status":"pending","subtotal":"10.0","tax":"1.5","shipping":"0.0","discount":"0.0","total":"11.5","return_url":"http://mysite.com/return","meta_data":{},"order_date":"2014-10-14T11:32:49-07:00","ip_address":null,"items":[{"name":"5_TKT_name","quantity":1,"price":"10.0","total":"10.0","sku":"640cbbe01b571fd036d3a7e4d5abcb07"}],"checkout_url":"https://secure.mijireh.com/checkout/1C107D792D2BACDE25F0FB77","authorization":null,"reference":null,"shipping_address":{"first_name":"8_ATT_fname","last_name":"8_ATT_lname","street":"8_ATT_address","apt_suite":"8_ATT_address2","city":"8_ATT_city","state_province":"7_STA_name","zip_code":"8_ATT_zip","country":"United States","phone":"8_ATT_phone"},"billing_address":{"first_name":"8_ATT_fname","last_name":"8_ATT_lname","street":"8_ATT_address","apt_suite":"8_ATT_address2","city":"8_ATT_city","state_province":"7_STA_name","zip_code":"8_ATT_zip","country":"United States","phone":"8_ATT_phone"}}', - 'response' => array ( - 'code' => 201, - 'message' => 'Created', - ), - 'cookies' => array (), - 'filename' => NULL, - ); - - - } - public function test_set_redirect_info__success(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Mijireh' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( $this->_test_settings ); - $t = $this->new_typical_transaction(); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() ) ); - $this->assertEmpty( $p->redirect_url() ); - - - $p = $ppg->set_redirection_info( $p, NULL, self::return_url, self::notify_url, self::cancel_url ); - - $this->assertNotEmpty( $p->redirect_url() ); - $this->assertEquals( 0, strpos( $p->redirect_url(),self::mijireh_checkout_url_start) ); - $rargs = json_decode( $p->details() ); - $mijireh_items = $rargs->items; - $first_mijireh_item = array_shift( $mijireh_items ); - $this->assertEquals( - $t->primary_registration()->ticket()->name() . ' for ' . $t->primary_registration()->event_name(), - $first_mijireh_item->name - ); - $this->assertEquals( $t->primary_registration()->ticket()->price(), $first_mijireh_item->price ); - $this->assertEquals( 1, $first_mijireh_item->quantity ); - $this->assertEquals( $t->tax_total(), $rargs->tax ); - $this->assertEquals( self::return_url, $rargs->return_url ); - - } - public function test_set_redirect_info__fail(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Mijireh' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( array( 'access_key' => 'bogus_one') ); - $t = $this->new_typical_transaction(); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() ) ); - $this->assertEmpty( $p->redirect_url() ); - - $p = $ppg->set_redirection_info( $p, NULL, self::return_url, self::notify_url, self::cancel_url ); - $this->assertEmpty( $p->redirect_url() ); - $this->assertEquals(EEM_Payment::status_id_failed, $p->get( 'STS_ID' ) ); - } - public function test_set_redirect_info__partial_payment(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Mijireh' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( $this->_test_settings ); - $paid_so_far = 1.00; - $t = $this->new_typical_transaction(); - $t->set_paid( $paid_so_far ); - $previous_payment = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $paid_so_far ) ); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() - $paid_so_far ) ); - $this->assertNotEquals( EEM_Payment::status_id_approved, $p->status() ); - - $p = $ppg->set_redirection_info( $p, NULL, self::return_url, self::notify_url, self::cancel_url ); - - $this->assertNotEmpty( $p->redirect_url() ); - $this->assertEquals( 0, strpos( $p->redirect_url(),self::mijireh_checkout_url_start) ); - } -//// /** -//// * tests that even if the line items are too complicated for the gateway to handle, -//// * it can at least send the total payable -//// */ - public function test_do_direct_payment__total_mismatch(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Mijireh' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( $this->_test_settings ); - $t = $this->new_typical_transaction(); - $t->set_total( $t->total() / 2 ); - $t->total_line_item()->set_total ( $t->total() ); - $t->save(); - $t->total_line_item()->save(); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() ) ); - $this->assertNotEquals( EEM_Payment::status_id_approved, $p->status() ); - - $p = $ppg->set_redirection_info( $p, NULL, self::return_url, self::notify_url, self::cancel_url ); - - $this->assertNotEmpty( $p->redirect_url() ); - $this->assertEquals( 0, strpos( $p->redirect_url(),self::mijireh_checkout_url_start) ); - } -} - -// End of file EE_PMT_Mijireh_Test.php \ No newline at end of file diff --git a/tests/testcases/payment_methods/EE_PMT_Paypal_Pro_Test.php b/tests/testcases/payment_methods/EE_PMT_Paypal_Pro_Test.php deleted file mode 100644 index baae4670de8..00000000000 --- a/tests/testcases/payment_methods/EE_PMT_Paypal_Pro_Test.php +++ /dev/null @@ -1,184 +0,0 @@ -_test_settings = array( - 'username' => 'sell_1359059457_biz_api1.eventespresso.com', - 'password' => '1359059477', - 'signature' => 'At4QgLNCqDfsw218JPKQWyb74X3HAicxDti5ZoS2qp01O8izJtunMnkZ', - 'debug_mode' => TRUE - ); - $this->_test_billing_info = array( - 'first_name' => 'auto', - 'last_name' => 'tester', - 'email' => 'few@ew.few', - 'address' => '2090 Nowhere Rd', - 'address2' => '', - 'city' => 'Whoville', - 'state' => 'Arkansas', - 'country' => 'US', - 'zip' => '84604', - 'phone' => '123-123-1234', - 'credit_card_type' => 'Visa', - 'credit_card' => '4127143344648082', - 'cvv' => '115', - 'exp_month' => '01', - 'exp_year' => '2018' - ); - } - - /** - * setUp - */ - public function setUp(){ - parent::setUp(); - //EEG_Paypal_Pro uses $_SERVER at some point, so we need to pretend this is a regular request - $this->go_to( 'http://localhost/' ); - //just set a random address - $_SERVER[ 'REMOTE_ADDR' ] = '192.0.0.1'; - add_filter('FHEE__EEG_Paypal_Pro__CurlRequest__CURLOPT_VERBOSE', '__return_false' ); - //make sure caf payment methods are registered - EE_Payment_Method_Manager::reset(); - } - - /** - * test_do_direct_payment__success - */ - public function test_do_direct_payment__success(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Paypal_Pro' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( $this->_test_settings ); - $t = $this->new_typical_transaction(); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() ) ); - $this->assertNotEquals( EEM_Payment::status_id_approved, $p->status() ); - - $p_processed = $ppg->do_direct_payment( $p, $this->_test_billing_info ); - $this->assertEquals( $p, $p_processed ); - $this->assertEquals( EEM_Payment::status_id_approved, $p_processed->status(), 'If this test fails, verify the paypal sandbox account HAS ENOUGH FUNDS and that we are still using the correct test credit card. Here is the payments details: ' . var_export( $p_processed->details(), true ) ); - $this->assertEquals( $t->total(), $p_processed->amount() ); - } - - /** - * test_do_direct_payment__fail - */ - public function test_do_direct_payment__fail(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Paypal_Pro' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( array( - 'username' => 'seller_with_fail_api1.eventespresso.com', - 'password' => '1405373725', - 'signature' => 'AySrU3tYAnUcGB87EC84g-FvwSiGA7pL1gPqq1ZS-ITCs1Sea8oAG2.e', - 'debug_mode' => TRUE - ) ); - $t = $this->new_typical_transaction( array('ticket_types' => 8 ) ); - ///set the payment amount to a specific error code (yes it's a partial payment that will be failing). See - //https://developer.paypal.com/docs/classic/lifecycle/sb_error-conditions/ for details - $amount_to_pay = 107.55; - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $amount_to_pay ) ); - $this->assertNotEquals( EEM_Payment::status_id_declined, $p->status() ); - - $billing_info = $this->_test_billing_info; - $billing_info['credit_card'] = '6011779094237966'; - $billing_info['credit_card_type'] = 'Discover'; - $billing_info['exp_month'] = '07'; - $billing_info['exp_year'] = '2019'; - $p_processed = $ppg->do_direct_payment( $p, $billing_info ); - - $this->assertEquals( $p, $p_processed ); - $this->assertEquals( EEM_Payment::status_id_declined, $p_processed->status(), 'transaction was for ' . $t->total() . ' and payment details were: ' . var_export( $p->details(), true ) ); - $this->assertEquals( $amount_to_pay, $p_processed->amount() ); - } - - /** - * test_do_direct_payment__partial_payment - */ - public function test_do_direct_payment__partial_payment(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Paypal_Pro' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( $this->_test_settings ); - $paid_so_far = 1.00; - $t = $this->new_typical_transaction(); - $t->set_paid( $paid_so_far ); - $previous_payment = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $paid_so_far ) ); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() - $paid_so_far ) ); - $this->assertNotEquals( EEM_Payment::status_id_approved, $p->status() ); - - $p_processed = $ppg->do_direct_payment( $p, $this->_test_billing_info ); - $this->assertEquals( EEM_Payment::status_id_approved, $p_processed->status() ); - $this->assertEquals( $t->total() - $paid_so_far, $p_processed->amount() ); - } - - /** - * test_do_direct_payment__total_mismatch - * - * tests that even if the line items are too complicated for the gateway to handle, - * it can at least send the total payable - */ - public function test_do_direct_payment__total_mismatch(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Paypal_Pro' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( $this->_test_settings ); - $t = $this->new_typical_transaction(); - $t->set_total( $t->total() / 2 ); - $t->total_line_item()->set_total ( $t->total() ); - $t->save(); - $t->total_line_item()->save(); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() ) ); - $this->assertNotEquals( EEM_Payment::status_id_approved, $p->status() ); - - $p_processed = $ppg->do_direct_payment( $p, $this->_test_billing_info ); - $this->assertEquals( EEM_Payment::status_id_approved, $p_processed->status() ); - $this->assertEquals( $t->total(), $p_processed->amount() ); - } - - /** - * test_generate_new_billing_form - */ - public function test_generate_new_billing_form(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Paypal_Pro', 'PMD_debug_mode' => TRUE ) ); - $t = $this->new_typical_transaction(); - $ppm->type_obj()->generate_new_billing_form( $t ); - } -} - -// End of file EE_PMT_Paypal_Pro_Test.php \ No newline at end of file diff --git a/tests/testcases/payment_methods/EE_PMT_Paypal_Standard_Test.php b/tests/testcases/payment_methods/EE_PMT_Paypal_Standard_Test.php deleted file mode 100644 index 8ccee9f916a..00000000000 --- a/tests/testcases/payment_methods/EE_PMT_Paypal_Standard_Test.php +++ /dev/null @@ -1,642 +0,0 @@ -_paypal_id = 'sell_1359059457_biz@eventespresso.com'; - $this->_test_settings = array( - 'paypal_id' => $this->_paypal_id, - 'shipping_details' => 1,//none - 'paypal_shipping'=> FALSE, - 'paypal_taxes'=> FALSE, - ); - } - public function test_set_redirection_info__success(){ - //make sure paypal gateway is included - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Paypal_Standard' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( $this->_test_settings ); - $t = $this->new_typical_transaction( array( 'ticket_types' => 2) ); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() ) ); - $this->assertEmpty( $p->redirect_url() ); - - - $p = $ppg->set_redirection_info( $p, NULL, self::return_url, self::notify_url, self::cancel_url ); - $this->assertNotEmpty( $p->redirect_url() ); - $this->assertEquals( self::paypal_url, $p->redirect_url() ); - $this->assertNotEmpty( $p->redirect_args() ); - $rargs = $p->redirect_args(); - $items_purchased = $t->items_purchased(); - $first_item = array_shift( $items_purchased ); - $second_item = array_shift( $items_purchased ); - $this->assertEquals( sprintf( '%s for %s', $first_item->ticket()->name(), $first_item->ticket_event_name() ), $rargs[ 'item_name_1' ] ); - $this->assertEquals( $first_item->ticket()->price(), $rargs[ 'amount_1' ] ); - $this->assertEquals( sprintf( '%s for %s', $second_item->ticket()->name(), $second_item->ticket_event_name() ), $rargs[ 'item_name_2' ] ); - $this->assertEquals( $second_item->ticket()->price(), $rargs[ 'amount_2' ] ); - $this->assertEquals( 1, $rargs[ 'quantity_1' ] ); - $this->assertEquals( $t->tax_total(), $rargs[ 'tax_cart' ] ); - $this->assertEquals( $this->_paypal_id, $rargs[ 'business' ] ); - $this->assertEquals( self::return_url, $rargs[ 'return' ] ); - $this->assertEquals( self::cancel_url, $rargs[ 'cancel_return' ] ); - $this->assertEquals( self::notify_url, $rargs[ 'notify_url' ] ); - $this->assertEquals( '_cart', $rargs[ 'cmd' ] ); - $this->assertEquals( 1, $rargs[ 'upload' ] ); - $this->assertEquals( 'USD', $rargs[ 'currency_code' ] ); - $this->assertEquals( 2, $rargs[ 'rm' ] );//makes the user return with method=POST - $this->assertEquals( 1, $rargs[ 'no_shipping'] ); - } - - /** - */ - public function test_set_redirection_info__with_paypal_taxes_and_shipping(){ - //make sure paypal gateway is included - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Paypal_Standard' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings(array( - 'paypal_id' => $this->_paypal_id, - 'paypal_taxes' => TRUE, - 'paypal_shipping' => TRUE - )); - $t = $this->new_typical_transaction( - array( - 'ticket_types' => 2, - 'taxable_tickets' => 1) ); - $original_txn_total = $t->total(); - //pretend we previous used paypal to make a payment. - EEH_Line_Item::add_unrelated_item( - $t->total_line_item(), - 'Shipping', - 8, - 'some shipping', - 1, - false, - 'paypal_shipping_' . $t->ID() ); - EEH_Line_Item::set_total_tax_to( $t->total_line_item(), 4, 'paypal taxes', 'paypal did thi', 'paypal_tax', false ); - $t->total_line_item()->save_this_and_descendants_to_txn( $t->ID() ); - $registration_processor = EE_Registry::instance()->load_class( 'Registration_Processor' ); - $registration_processor->update_registration_final_prices( $t ); - - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() ) ); - $this->assertEmpty( $p->redirect_url() ); - //set redirection info; we should ignore previously-added paypal tax and shipping - //(so paypal can add calculate them again when we send them) - $p = $ppg->set_redirection_info( $p, NULL, self::return_url, self::notify_url, self::cancel_url ); - $this->assertNotEmpty( $p->redirect_url() ); - $this->assertEquals( self::paypal_url, $p->redirect_url() ); - $this->assertNotEmpty( $p->redirect_args() ); - $rargs = $p->redirect_args(); - $items_purchased = $t->items_purchased(); - $first_item = array_shift( $items_purchased ); - $second_item = array_shift( $items_purchased ); - $this->assertEquals( sprintf( '%s for %s', $first_item->ticket()->name(), $first_item->ticket_event_name() ), $rargs[ 'item_name_1' ] ); - $this->assertEquals( $first_item->ticket()->price(), $rargs[ 'amount_1' ] ); - $this->assertEquals( sprintf( '%s for %s', $second_item->ticket()->name(), $second_item->ticket_event_name() ), $rargs[ 'item_name_2' ] ); - $this->assertEquals( $second_item->ticket()->price(), $rargs[ 'amount_2' ] ); - $this->assertEquals( 1, $rargs[ 'quantity_1' ] ); - //we shouldn't have told paypal how much tax to add. Let paypal decide. - $this->assertFalse( isset( $rargs[ 'tax_cart' ] ) ); - //there should be no 3rd item for shipping - $this->assertFalse( isset( $rargs[ 'amount_3' ] ) ); - } - //@todo test ipn with different tax and shipping - public function test_handle_payment_update(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Paypal_Standard' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings(array( - 'paypal_id' => $this->_paypal_id - )); - $t = $this->new_typical_transaction(); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() ) ); - $p_in_map = EE_Registry::instance()->load_model('Payment')->get_from_entity_map( $p->ID() ); - $this->assertInstanceOf( 'EE_Payment', $p_in_map ); - //skip IPN validation with paypal - add_filter( 'FHEE__EEG_Paypal_Standard__validate_ipn__skip', '__return_true' ); - - $ppg->handle_payment_update( array ( - 'e_reg_url_link' => '1-bfcffeb307c5f5e275643de154fe7192', - 'mc_gross' => $t->total(), - 'protection_eligibility' => 'Eligible', - 'address_status' => 'confirmed', - 'item_number1' => '', - 'item_number2' => '', - 'payer_id' => 'XN873NKAXAAE2', - 'tax' => '0.00', - 'address_street' => '1 Main St', - 'payment_date' => '10:55:09 Jul 03, 2014 PDT', - 'payment_status' => 'Completed', - 'option_selection1_2' => 'http://localhost/wp-develop/src/transactions/?e_reg_url_link=1-bfcffeb307c5f5e275643de154fe7192&ee_payment_method=paypal_standard', - 'charset' => 'windows-1252', - 'address_zip' => '95131', - 'mc_shipping' => '0.00', - 'mc_handling' => '0.00', - 'first_name' => 'Event', - 'mc_fee' => '2.04', - 'address_country_code' => 'US', - 'address_name' => 'Event Espresso', - 'notify_version' => '3.8', - 'custom' => '', - 'payer_status' => 'verified', - 'business' => 'sell_1359059457_biz@eventespresso.com', - 'address_country' => 'United States', - 'num_cart_items' => '2', - 'mc_handling1' => '0.00', - 'mc_handling2' => '0.00', - 'address_city' => 'San Jose', - 'payer_email' => 'buyer_1359059233_per@eventespresso.com', - 'verify_sign' => 'An5ns1Kso7MWUdW4ErQKJJJ4qi4-A7ueXcNiuE.6nTwMSoqIZ1cXOQTF', - 'mc_shipping1' => '0.00', - 'mc_shipping2' => '0.00', - 'tax1' => '0.00', - 'tax2' => '0.00', - 'option_name1_2' => 'NOTIFY URL', - 'txn_id' => '2UT88371J0075792R', - 'payment_type' => 'instant', - 'last_name' => 'Espresso', - 'item_name1' => 'Free Ticket', - 'address_state' => 'CA', - 'receiver_email' => 'sell_1359059457_biz@eventespresso.com', - 'item_name2' => 'DEBUG INFO (this item only added in sandbox mode', - 'payment_fee' => '2.04', - 'quantity1' => '1', - 'quantity2' => '1', - 'receiver_id' => 'M33RRGRH82CUN', - 'txn_type' => 'cart', - 'mc_gross_1' => $t->primary_registration()->ticket()->price(), - 'mc_currency' => 'USD', - 'mc_gross_2' => '0.00', - 'residence_country' => 'US', - 'test_ipn' => '1', - 'transaction_subject' => '', - 'payment_gross' => '60.00', - 'auth' => 'Abp7Rv87UBZqp18HlystBhVYkr5U-wOEufLDnbUuLIli4sta-Jr-4G1kw4uwGLNlopOjLer38dL3Zp-rBnaT3wg', -), $t ); - $this->assertEquals( EEM_Payment::status_id_approved, $p->status() ); - $this->assertEquals( $t->total(), $p->amount() ); - } - - - public function test_handle_payment_update__refund(){ - /** @type EE_Payment_Method $ppm */ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Paypal_Standard' ) ); - /** @type EEG_Paypal_Standard $ppg */ - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings(array( - 'paypal_id' => $this->_paypal_id - )); - $t = $this->new_typical_transaction(); - /** @type EE_Payment $p */ - // PLZ NOTE: refunds have a negative value for their amount - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => ( $t->total() * -1 ) ) ); - $p_in_map = EE_Registry::instance()->load_model('Payment')->get_from_entity_map( $p->ID() ); - $this->assertInstanceOf( 'EE_Payment', $p_in_map ); - //skip IPN validation with paypal - add_filter( 'FHEE__EEG_Paypal_Standard__validate_ipn__skip', '__return_true' ); - add_filter( 'FHEE__EEG_Paypal_Standard__handle_payment_update__kill_refund_request', '__return_false' ); - $ppg->handle_payment_update( - array ( - 'e_reg_url_link' => '1-bfcffeb307c5f5e275643de154fe7192', - 'mc_gross' => ( $t->total() * -1 ), - 'protection_eligibility' => 'Eligible', - 'address_status' => 'confirmed', - 'item_number1' => '', - 'item_number2' => '', - 'payer_id' => 'XN873NKAXAAE2', - 'tax' => '0.00', - 'address_street' => '1 Main St', - 'payment_date' => '10:55:09 Jul 03, 2014 PDT', - 'payment_status' => 'Refunded', - 'option_selection1_2' => 'http://localhost/wp-develop/src/transactions/?e_reg_url_link=1-bfcffeb307c5f5e275643de154fe7192&ee_payment_method=paypal_standard', - 'charset' => 'windows-1252', - 'address_zip' => '95131', - 'mc_shipping' => '0.00', - 'mc_handling' => '0.00', - 'first_name' => 'Event', - 'mc_fee' => '2.04', - 'address_country_code' => 'US', - 'address_name' => 'Event Espresso', - 'notify_version' => '3.8', - 'custom' => '', - 'payer_status' => 'verified', - 'business' => 'sell_1359059457_biz@eventespresso.com', - 'address_country' => 'United States', - 'num_cart_items' => '2', - 'mc_handling1' => '0.00', - 'mc_handling2' => '0.00', - 'address_city' => 'San Jose', - 'payer_email' => 'buyer_1359059233_per@eventespresso.com', - 'verify_sign' => 'An5ns1Kso7MWUdW4ErQKJJJ4qi4-A7ueXcNiuE.6nTwMSoqIZ1cXOQTF', - 'mc_shipping1' => '0.00', - 'mc_shipping2' => '0.00', - 'tax1' => '0.00', - 'tax2' => '0.00', - 'option_name1_2' => 'NOTIFY URL', - 'txn_id' => '2UT88371J0075792R', - 'payment_type' => 'instant', - 'last_name' => 'Espresso', - 'item_name1' => 'Free Ticket', - 'address_state' => 'CA', - 'receiver_email' => 'sell_1359059457_biz@eventespresso.com', - 'item_name2' => 'DEBUG INFO (this item only added in sandbox mode', - 'payment_fee' => '2.04', - 'quantity1' => '1', - 'quantity2' => '1', - 'receiver_id' => 'M33RRGRH82CUN', - 'txn_type' => 'cart', - 'mc_gross_1' => $t->primary_registration()->ticket()->price(), - 'mc_currency' => 'USD', - 'mc_gross_2' => '0.00', - 'residence_country' => 'US', - 'test_ipn' => '1', - 'transaction_subject' => '', - 'payment_gross' => '60.00', - 'auth' => 'Abp7Rv87UBZqp18HlystBhVYkr5U-wOEufLDnbUuLIli4sta-Jr-4G1kw4uwGLNlopOjLer38dL3Zp-rBnaT3wg', - ), - $t - ); - $this->assertEquals( EEM_Payment::status_id_approved, $p->status() ); - $this->assertEquals( ( $t->total() * -1 ), $p->amount() ); - } - - /** - * @group 4710 - */ - public function test_handle_payment_update__paypal_adds_taxes_and_shipping(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Paypal_Standard' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings(array( - 'paypal_id' => $this->_paypal_id, - 'paypal_taxes' => TRUE, - 'paypal_shipping' => TRUE - )); - $t = $this->new_typical_transaction(); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() ) ); - $p->update_extra_meta( EEG_Paypal_Standard::itemized_payment_option_name, true ); - $old_pretax_total = EEH_Line_Item::get_pre_tax_subtotal( $t->total_line_item() )->total(); - $old_taxable_total = $t->total_line_item()->taxable_total(); - $this->assertNotEmpty( $old_taxable_total ); - $old_tax_total = $t->tax_total(); - $this->assertNotEmpty( $old_tax_total ); - //skip IPN validation with paypal - add_filter( 'FHEE__EEG_Paypal_Standard__validate_ipn__skip', '__return_true' ); - - //pretend we sent an itemized report to paypal, and thus told them to calculate taxes on it. - $p->update_extra_meta( 'itemized_payment', true ); - $tax_in_ipn = 2.80; - //if the old tax matches what's going to be in the IPN data, we can't verify the IPN data - //updated the tax can we? - $this->assertNotEquals( $tax_in_ipn, $old_tax_total ); - $ipn_args = array ( - 'e_reg_url_link' => '1-203446311152995f326e9ca81b64c95b', - 'mc_gross' => $old_pretax_total + 8 + 2.8,//pretax total plus shipping and tax - 'protection_eligibility' => 'Eligible', - 'address_status' => 'confirmed', - 'item_number1' => '', - 'item_number2' => '', - 'payer_id' => 'DQUX5EF8CFFQ2', - 'tax' => "$tax_in_ipn",//IMPORTANT - 'address_street' => '1 Maire-Victorin', - 'payment_date' => '15:21:18 Jul 04, 2014 PDT', - 'payment_status' => 'Completed', - 'option_selection1_2' => 'http://localhost/wp-develop/src/transactions/?e_reg_url_link=1-203446311152995f326e9ca81b64c95b&ee_payment_method=paypal_standard', - 'charset' => 'windows-1252', - 'address_zip' => 'M5A 1E1', - 'mc_shipping' => '8.00',//IMPORTANT - 'mc_handling' => '0.00',//MAYBE IMPORTANT - 'first_name' => 'canadaman', - 'mc_fee' => '1.50', - 'address_country_code' => 'CA', - 'address_name' => 'canadaman eh', - 'notify_version' => '3.8', - 'custom' => '', - 'payer_status' => 'verified', - 'business' => 'sell_tax_and_ship@eventespresso.com', - 'address_country' => 'Canada', - 'num_cart_items' => '2', - 'mc_handling1' => '0.00', - 'mc_handling2' => '0.00', - 'address_city' => 'Toronto', - 'payer_email' => 'canada_buy_eh@eventespresso.com', - 'verify_sign' => 'Asuc-38eoonqdqSbDHczw6533JekAJTc2w.QEYe.bLdd3C9Sk1FmgQur', - 'mc_shipping1' => '0.00', - 'mc_shipping2' => '0.00', - 'tax1' => '0.00', - 'tax2' => '0.00', - 'option_name1_2' => 'NOTIFY URL', - 'txn_id' => '4W884024TK795542J', - 'payment_type' => 'instant', - 'last_name' => 'eh', - 'item_name1' => 'Free Ticket', - 'address_state' => 'Ontario', - 'receiver_email' => 'sell_tax_and_ship@eventespresso.com', - 'item_name2' => 'DEBUG INFO (this item only added in sandbox mode', - 'payment_fee' => '1.50', - 'shipping_discount' => '0.00', - 'quantity1' => '1', - 'insurance_amount' => '0.00', - 'quantity2' => '1', - 'receiver_id' => '8STUBD4V9ZUUN', - 'txn_type' => 'cart', - 'discount' => '0.00', - 'mc_gross_1' => '20.00', - 'mc_currency' => 'USD', - 'mc_gross_2' => '0.00', - 'residence_country' => 'CA', - 'test_ipn' => '1', - 'shipping_method' => 'International Economy',//IMPORTANT - 'transaction_subject' => '', - 'payment_gross' => '30.80',//IMPORTANT - 'auth' => 'A7v0XCv0MTRMLTC3ib4B4zYtTI7Wt-pU5StpnoQBIGsiMj5pXBoOr8z8kiKzYdNkeTmwiWW3xlus4rZhBUOqj6g', - ); - $ppg->handle_payment_update( $ipn_args, $t ); - $ppg->update_txn_based_on_payment( $p ); - //check the new tax is correct - $this->assertNotEquals( $old_tax_total, $t->tax_total(), 'Its not necessarily wrong for the old tax to match the new tax; but if they match we can\'t be very sure the tax total was updated' ); - $this->assertEquals( floatval( $ipn_args[ 'tax' ] ), $t->tax_total() ); - $tax_line_items = EEH_Line_Item::get_taxes_subtotal( $t->total_line_item() )->children(); - $this->assertEquals( 1, count( $tax_line_items ) ); - $only_tax = array_shift( $tax_line_items ); - $this->assertEquals( __( 'Taxes', 'event_espresso' ), $only_tax->name() ); - $this->assertEquals( EEM_Payment::status_id_approved, $p->status() ); - $this->assertEquals( $t->total(), $p->amount() ); - //check that the shipping surcharge is correct - $items_subtotal = EEH_Line_Item::get_pre_tax_subtotal( $t->total_line_item() ); - $items = $items_subtotal->children(); - $first_item = array_shift( $items ); - $this->assertEquals( 10, $first_item->total() ); - $second_item = array_shift( $items); - $this->assertEquals( 8, $second_item->total() ); - //EEH_Line_Item::visualize($t->total_line_item()); - $this->assertEquals( $old_pretax_total + 8, $items_subtotal->total() ); - //check that the transaction's total got updated to match the total line item's - $this->assertEquals( $t->total_line_item()->total(), $t->total() ); - //check that if we re-calculate all the prices everything is still the same - $updated_line_item_total = $t->total_line_item()->total(); - $t->total_line_item()->recalculate_total_including_taxes(); - $this->assertEquals( $updated_line_item_total, $t->total_line_item()->total() ); - } - - /** - * @group 4710 - */ - public function test_update_txn_based_on_payment__paypal_adds_taxes_and_shipping__twice(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Paypal_Standard' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings(array( - 'paypal_id' => $this->_paypal_id, - 'paypal_taxes' => TRUE, - 'paypal_shipping' => TRUE - )); - $t = $this->new_typical_transaction(); - $old_taxable_total = $t->total_line_item()->taxable_total(); - $this->assertNotEmpty( $old_taxable_total ); - $old_tax_total = $t->tax_total(); - $this->assertNotEmpty( $old_tax_total ); - - $tax_in_1st_ipn = 1.80; - $ship_in_1st_ipn = 3.00; - $p = $this->new_model_obj_with_dependencies( 'Payment', - array( - 'TXN_ID'=>$t->ID(), - 'STS_ID' => EEM_Payment::status_id_approved, - 'PMD_ID' => $ppm->ID(), - 'PAY_amount' => $t->total() / 2, - 'PAY_details' => array ( - 'tax' => "$tax_in_1st_ipn",//IMPORTANT - 'mc_shipping' => "$ship_in_1st_ipn",//IMPORTANT - ), - ) ); - $p->update_extra_meta( EEG_Paypal_Standard::itemized_payment_option_name, false ); - //taxes shouldn't have been changed, despite whatever paypal says, because - //we didnt send them an itemized total so they cant have calculated taxes right anyways - $this->assertNotEquals( $tax_in_1st_ipn, $old_tax_total, 'Its not necessarily wrong for the old tax to match the new tax; but if they match we can\'t be very sure the tax total wasnt updated' ); - - - $ppg->update_txn_based_on_payment( $p ); - //check the new tax wasnt changed - $this->assertEquals( $old_tax_total, $t->tax_total() ); - $this->assertNotEquals( $tax_in_1st_ipn, $t->tax_total() );//taxes shouldnt have changed - $pre_tax_total = EEH_Line_Item::get_pre_tax_subtotal( $t->total_line_item() ); - $shipping1_line_item = $pre_tax_total->get_child_line_item( 'paypal_shipping_' . $t->ID() ); - $this->assertNull( $shipping1_line_item ); - - //ok now let's pretend they made another payment via paypal and added more onto the taxes. - //but we only update taxes when paypal received an itemized payment from us, which it didn't - $tax_in_2nd_ipn = 1.5; - $ship_in_2nd_ipn = 8.00; - $p2 = $this->new_model_obj_with_dependencies( 'Payment', - array( - 'TXN_ID'=>$t->ID(), - 'STS_ID' => EEM_Payment::status_id_approved, - 'PMD_ID' => $ppm->ID(), - 'PAY_amount' => $t->remaining(), - 'PAY_details' => array( - 'tax' => "$tax_in_2nd_ipn", - 'mc_shipping' => "$ship_in_2nd_ipn")) ); - $p2->update_extra_meta( EEG_Paypal_Standard::itemized_payment_option_name, false ); - $ppg->update_txn_based_on_payment( $p2 ); - //assert that the total tax is now the SUM of both IPN's tax amounts - $this->assertEquals( $tax_in_2nd_ipn, $t->tax_total() ); - //verify the old shipping is still there - $shipping1_line_item = $pre_tax_total->get_child_line_item( 'paypal_shipping_' . $t->ID() ); - $this->assertNull( $shipping1_line_item ); - } - - - /** - * verifies that previous payments get added onto the discount - * @group 4710 - */ - public function test_set_redirect_info__partial_payment_for_remainder(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Paypal_Standard' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( $this->_test_settings ); - $paid_so_far = 1.00; - $t = $this->new_typical_transaction( array( 'ticket_types' => 2)); - $t->set_paid( $paid_so_far ); - $previous_payment = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $paid_so_far, 'STS_ID' => EEM_Payment::status_id_approved ) ); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() - $paid_so_far ) ); - $this->assertNotEquals( EEM_Payment::status_id_approved, $p->status() ); - - $p = $ppg->set_redirection_info( $p, NULL, self::return_url, self::notify_url, self::cancel_url ); - - $this->assertNotEmpty( $p->redirect_url() ); - $rargs = $p->redirect_args(); - //also check we DID try to enumerat ethe line items - $this->assertFalse( isset( $rargs[ 'discount_amount_cart' ] ) ); - $this->assertTrue( isset( $rargs[ 'item_name_1' ] ) ); - $this->assertTrue( isset( $rargs[ 'amount_1' ] ) ); - $this->assertFalse( isset( $rargs[ 'item_name_2' ] ) ); - $this->assertFalse( isset( $rargs[ 'amount_2' ] ) ); - $this->assertFalse( isset( $rargs[ 'quantity_2' ] ) ); - } - - /** - * This is a legitimate partial payment (different from a total mismatch in that the itemized total - * equals the transaction total as expected, but the payment is for less than the transaction - * and there are no previous payments - * @group 4710 - */ - public function test_set_redirect_info__partial_payment_initial(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Paypal_Standard' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( $this->_test_settings ); - $t = $this->new_typical_transaction( array( 'ticket_types' => 2)); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => 10 ) ); - $this->assertNotEquals( EEM_Payment::status_id_approved, $p->status() ); - - $p = $ppg->set_redirection_info( $p, NULL, self::return_url, self::notify_url, self::cancel_url ); - - $this->assertNotEmpty( $p->redirect_url() ); - $rargs = $p->redirect_args(); - //also check we DID NOT try to enumerat ethe line items - $this->assertTrue( isset( $rargs[ 'item_name_1' ] ) ); - $this->assertTrue( isset( $rargs[ 'amount_1' ] ) ); - $this->assertFalse( isset( $rargs[ 'item_name_2' ] ) ); - $this->assertFalse( isset( $rargs[ 'amount_2' ] ) ); - $this->assertFalse( isset( $rargs[ 'quantity_2' ] ) ); - } - /** - * Verifies that we don't re-add shipping if it's already been added - * @group 4710 - */ - public function test_set_redirect_info__with_promotion() { - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Paypal_Standard' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( $this->_test_settings ); - $t = $this->new_typical_transaction( array( 'ticket_types' => 2)); - $event = EEM_Event::instance()->get_one( array( array( 'Registration.TXN_ID' => $t->ID() ) ) ); - $event_li = EEH_Line_Item::get_event_line_item( $t->total_line_item(), $event ); - $discount_li = $this->new_model_obj_with_dependencies( - 'Line_Item', - array( - 'LIN_parent' => $event_li->ID(), - 'LIN_name' => 'discount', - 'LIN_code' => 'discount', - 'LIN_unit_price' => -10, - 'LIN_quantity' => 1, - 'LIN_percent' => 0, - 'LIN_type' => EEM_Line_Item::type_line_item, - 'LIN_is_taxable' => false, - 'TXN_ID' => $t->ID() - )); - $t->total_line_item()->recalculate_total_including_taxes(); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() ) ); - $this->assertNotEquals( EEM_Payment::status_id_approved, $p->status() ); - - $p = $ppg->set_redirection_info( $p, NULL, self::return_url, self::notify_url, self::cancel_url ); - - $rargs = $p->redirect_args(); - //also check we DID enumerat ethe line items - $this->assertEquals( '10', $rargs[ 'discount_amount_cart' ] ); - $this->assertTrue( isset( $rargs[ 'item_name_1' ] ) ); - $this->assertTrue( isset( $rargs[ 'amount_1' ] ) ); - //although we shouldn't be mentioning how much taxes are per item. leave that to paypal - $this->assertFalse( isset( $rargs[ 'tax_1' ] ) ); - $this->assertTrue( isset( $rargs[ 'item_name_2' ] ) ); - $this->assertTrue( isset( $rargs[ 'amount_2' ] ) ); - $this->assertTrue( isset( $rargs[ 'quantity_2' ] ) ); - $this->assertFalse( isset( $rargs[ 'tax_2' ] ) ); - } - - /** - * tests that even if the line items are too complicated for the gateway to handle, - * it can at least send the total payable - * @group 4710 - */ - public function test_set_redirect_info__total_mismatch__itemized_higher(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Paypal_Standard' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( $this->_test_settings ); - $t = $this->new_typical_transaction( array( 'ticket_types' => 2) ); - $t->set_total( $t->total() - 10 ); - $t->total_line_item()->set_total ( $t->total() ); - $t->save(); - $t->total_line_item()->save(); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() ) ); - $this->assertNotEquals( EEM_Payment::status_id_approved, $p->status() ); - - $p = $ppg->set_redirection_info( $p, NULL, self::return_url, self::notify_url, self::cancel_url ); - - $this->assertNotEmpty( $p->redirect_url() ); - $rargs = $p->redirect_args(); - //also check we DID manage to enumerat ethe line items, just with a discount - //the amount missing is equal to - $this->assertEquals( 10, intval( $rargs[ 'discount_amount_cart' ] ) ); - $this->assertTrue( isset( $rargs[ 'item_name_1' ] ) ); - $this->assertTrue( isset( $rargs[ 'amount_1' ] ) ); - $this->assertTrue( isset( $rargs[ 'item_name_2' ] ) ); - $this->assertTrue( isset( $rargs[ 'amount_2' ] ) ); - $this->assertTrue( isset( $rargs[ 'quantity_2' ] ) ); - } - - /** - * tests that even if the line items are too complicated for the gateway to handle, - * it can at least send the total payable - * @group 4710 - */ - public function test_set_redirect_info__total_mismatch__itemized_lower(){ - $ppm = $this->new_model_obj_with_dependencies( 'Payment_Method', array( 'PMD_type' => 'Paypal_Standard' ) ); - $ppg = $ppm->type_obj()->get_gateway(); - $ppg->set_settings( $this->_test_settings ); - $t = $this->new_typical_transaction( array( 'ticket_types' => 2) ); - $t->set_total( $t->total() + 5 ); - $t->total_line_item()->set_total ( $t->total() ); - $t->save(); - $t->total_line_item()->save(); - $p = $this->new_model_obj_with_dependencies( 'Payment', array('TXN_ID'=>$t->ID(), 'PMD_ID' => $ppm->ID(), 'PAY_amount' => $t->total() ) ); - $this->assertNotEquals( EEM_Payment::status_id_approved, $p->status() ); - - $p = $ppg->set_redirection_info( $p, NULL, self::return_url, self::notify_url, self::cancel_url ); - - $this->assertNotEmpty( $p->redirect_url() ); - $rargs = $p->redirect_args(); - //also check we DID manage to enumerat ethe line items, just with an extra item for the surplus - $this->assertTrue( isset( $rargs[ 'item_name_1' ] ) ); - $this->assertTrue( isset( $rargs[ 'amount_1' ] ) ); - $this->assertTrue( isset( $rargs[ 'item_name_2' ] ) ); - $this->assertTrue( isset( $rargs[ 'amount_2' ] ) ); - $this->assertTrue( isset( $rargs[ 'quantity_2' ] ) ); - //check that we've also added another item to make up for the difference - $this->assertTrue( isset( $rargs[ 'item_name_3' ] ) ); - $this->assertTrue( isset( $rargs[ 'amount_3' ] ) ); - $this->assertTrue( isset( $rargs[ 'quantity_3' ] ) ); - $this->assertEquals( 5, $rargs[ 'amount_3' ] ); - } -} - -// End of file EE_PMT_Paypal_Standard_Test.php -// Location: /tests/testcases/payment_methods/EE_PMT_Paypal_Standard_Test.php diff --git a/wp-assets/banner-772x250.jpg b/wp-assets/banner-772x250.jpg deleted file mode 100644 index 1309dd13339..00000000000 Binary files a/wp-assets/banner-772x250.jpg and /dev/null differ diff --git a/wp-assets/icon-128x128.png b/wp-assets/icon-128x128.png deleted file mode 100644 index 9347adb78dc..00000000000 Binary files a/wp-assets/icon-128x128.png and /dev/null differ diff --git a/wp-assets/icon-256x256.png b/wp-assets/icon-256x256.png deleted file mode 100644 index 84970f89db8..00000000000 Binary files a/wp-assets/icon-256x256.png and /dev/null differ diff --git a/wp-assets/icon.svg b/wp-assets/icon.svg deleted file mode 100644 index 2bf6cb04d57..00000000000 --- a/wp-assets/icon.svg +++ /dev/null @@ -1,134 +0,0 @@ - - - -image/svg+xml - - - - - - - - - \ No newline at end of file diff --git a/wp-assets/screenshot-1.jpg b/wp-assets/screenshot-1.jpg deleted file mode 100644 index 94377fa87c9..00000000000 Binary files a/wp-assets/screenshot-1.jpg and /dev/null differ diff --git a/wp-assets/screenshot-2.jpg b/wp-assets/screenshot-2.jpg deleted file mode 100644 index 0bc36251602..00000000000 Binary files a/wp-assets/screenshot-2.jpg and /dev/null differ diff --git a/wp-assets/screenshot-3.jpg b/wp-assets/screenshot-3.jpg deleted file mode 100644 index a526361cdd1..00000000000 Binary files a/wp-assets/screenshot-3.jpg and /dev/null differ diff --git a/wp-assets/screenshot-4.jpg b/wp-assets/screenshot-4.jpg deleted file mode 100644 index b1600c8e978..00000000000 Binary files a/wp-assets/screenshot-4.jpg and /dev/null differ diff --git a/wp-assets/screenshot-5.jpg b/wp-assets/screenshot-5.jpg deleted file mode 100644 index 514b9c7203d..00000000000 Binary files a/wp-assets/screenshot-5.jpg and /dev/null differ diff --git a/wp-assets/screenshot-6.jpg b/wp-assets/screenshot-6.jpg deleted file mode 100644 index d53abcf9225..00000000000 Binary files a/wp-assets/screenshot-6.jpg and /dev/null differ diff --git a/wp-assets/screenshot-7.jpg b/wp-assets/screenshot-7.jpg deleted file mode 100644 index 1cfdb13b916..00000000000 Binary files a/wp-assets/screenshot-7.jpg and /dev/null differ diff --git a/wp-assets/screenshot-8.jpg b/wp-assets/screenshot-8.jpg deleted file mode 100644 index 31f1f0641bc..00000000000 Binary files a/wp-assets/screenshot-8.jpg and /dev/null differ