├── .eslintrc.js ├── .gitattributes ├── .gitignore ├── .huskyrc.js ├── .lintstagedrc.js ├── .nvmrc ├── .phpcs.xml ├── .stylelintrc.json ├── Gruntfile.js ├── README.md ├── composer.json ├── composer.lock ├── package-lock.json ├── package.json └── tawkto ├── assets ├── css │ └── tawk.admin.css ├── js │ ├── tawk.admin.js │ └── tawk.selection.js └── tawky_big.png ├── includes └── default_config.php ├── index.php ├── readme.txt ├── screenshot-1.png ├── screenshot-2.png ├── screenshot-3.png ├── screenshot-4.png ├── screenshot-5.png ├── screenshot-6.png ├── tawkto.php ├── templates ├── settings.php └── widget.php ├── upgrade.manager.php └── upgrades ├── base.php ├── version.070.php └── version.090.php /.eslintrc.js: -------------------------------------------------------------------------------- 1 | 'use-strict'; 2 | 3 | module.exports = { 4 | 'root': true, 5 | 'env': { 6 | 'browser': true, 7 | 'jquery': true 8 | }, 9 | 'extends': 'wordpress' 10 | }; 11 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # ignore .github files 2 | /.github export-ignore 3 | 4 | # export-ignore test files 5 | /phpunit.xml export-ignore 6 | /tests export-ignore 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | tawkto.zip 2 | vendor 3 | .phpunit* 4 | tawkto/vendor 5 | node_modules 6 | .phpcs.cache 7 | .eslintcache 8 | .stylelintcache 9 | **/*.env.local 10 | tmp 11 | dev 12 | -------------------------------------------------------------------------------- /.huskyrc.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = { 4 | hooks: { 5 | 'pre-commit': 'lint-staged' 6 | } 7 | }; 8 | -------------------------------------------------------------------------------- /.lintstagedrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | '*.js': 'eslint --cache --fix', 3 | '*.css': 'stylelint --cache --fix', 4 | '*.php': [ 5 | 'composer run lint:fix', 6 | 'composer run lint' 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.nvmrc: -------------------------------------------------------------------------------- 1 | 12.22.7 2 | -------------------------------------------------------------------------------- /.phpcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | Custom coding standards. 4 | 5 | \.github/* 6 | vendor/* 7 | tawkto/vendor/* 8 | node_modules/* 9 | assets/* 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | tests/* 30 | 31 | 32 | tests/* 33 | 34 | 35 | tests/* 36 | 37 | 38 | tests/* 39 | 40 | 41 | tests/* 42 | 43 | 44 | -------------------------------------------------------------------------------- /.stylelintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@wordpress/stylelint-config" 3 | } 4 | -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | module.exports = function( grunt ) { 4 | grunt.initConfig({ 5 | eslint: { 6 | target: { 7 | src: [ '**/*.js', '!node_modules/**/*', '!vendor/**/*' ], 8 | dot: true 9 | } 10 | }, 11 | stylelint: { 12 | target: { 13 | src: [ '**/*.css', '!node_modules/**/*', '!vendor/**/*' ] 14 | } 15 | }, 16 | phpcs: { 17 | target: { 18 | src: [ '**/*.php', '!node_modules/**/*', '!vendor/**/*' ] 19 | }, 20 | options: { 21 | bin: 'vendor/bin/phpcs' 22 | } 23 | } 24 | }); 25 | 26 | grunt.loadNpmTasks( 'grunt-eslint' ); 27 | grunt.loadNpmTasks( 'grunt-stylelint' ); 28 | grunt.loadNpmTasks( 'grunt-phpcs' ); 29 | grunt.registerTask( 'default', [ 'eslint', 'stylelint', 'phpcs' ]); 30 | }; 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Tests 2 | 3 | ## Test setup and configuration 4 | 5 | ### Building package to test 6 | 7 | Run `composer run build` to build both dev and prod dependencies. 8 | 9 | Run `composer run package` to build the tawk.to plugin zip file that will be tested. 10 | 11 | ### Setting up docker environment 12 | 13 | Docker-compose is used for test dependency setup and is required to run these tests 14 | 15 | #### Configuring docker environment 16 | 17 | Environment variables used in the `docker-compose.yml` file can be found in `.env` file. 18 | 19 | | Environment Variable | Description | Default Value | 20 | |---|---|---| 21 | | WORDPRESS_DB_HOST | MySQL Service DB Host | db:3306 | 22 | | WORDPRESS_DB_NAME | MySQL Service DB Name | wordpress | 23 | | WORDPRESS_DB_USER | MySQL Service DB User | wordpress | 24 | | WORDPRESS_DB_PASSWORD | MySQL Service DB Password | wordpress | 25 | | WORDPRESS_DB_ROOT_PASSWORD | MySQL Service DB Root Password | somewordpress | 26 | | WEB_HOST | WordPress Web Host | wordpress | 27 | | WORDPRESS_DEBUG | WordPress Debug Mode | 1 | 28 | | WORDPRESS_ADMIN_USER | WordPress Admin User | admin | 29 | | WORDPRESS_ADMIN_PASSWORD | WordPress Admin Password | admin | 30 | | WORDPRESS_ADMIN_EMAIL | WordPress Admin Email | admin@example.com | 31 | | SELENIUM_BROWSER | Selenium Server Browser Type | chrome | 32 | | SELENIUM_PORT | Selenium Server Port | 4444 | 33 | 34 | #### Wordpress and WooCommerce setup 35 | 36 | Docker environment is setup up to automatically populate test data 37 | This is done by `wordpress-cli` service in compose file 38 | 39 | For more details on setup, see setup script 40 | 41 | #### Running the test environment 42 | 43 | To run docker environment for testing this repository, start docker compose file found in `/tests/docker/docker-compose.yml` 44 | 45 | Example (assuming from root of repository) 46 | 47 | ```sh 48 | docker-compose -f ./tests/docker/docker-compose.yml up -d 49 | ``` 50 | 51 | Environment is ready when `wordpress-cli` successfully exists. 52 | To monitor its status, you can tail it's logs using `docker logs -f wordpress-cli` 53 | 54 | ### Configuring local test environment 55 | 56 | These are the environment variables needed to run the selenium tests locally using composer script 57 | 58 | | Environment Variable | Description | Required | 59 | |---|---|---| 60 | | TAWK_PROPERTY_ID | Property Id | Yes | 61 | | TAWK_WIDGET_ID | Widget Id | Yes | 62 | | TAWK_USERNAME | tawk.to account username | Yes | 63 | | TAWK_PASSWORD | tawk.to account password | Yes | 64 | | WEB_HOST | Wordpress web hostname | Yes | 65 | | WEB_PORT | Wordpress web port | No | 66 | | SELENIUM_BROWSER | Browser type (chrome, firefox, edge) | Yes | 67 | | SELENIUM_HOST | Selenium host | Yes | 68 | | SELENIUM_PORT | Selenium port | No | 69 | 70 | #### Command Sample 71 | ``` 72 | TAWK_PROPERTY_ID= \ 73 | TAWK_WIDGET_ID= \ 74 | TAWK_USERNAME= \ 75 | TAWK_PASSWORD= \ 76 | WEB_HOST=wordpress \ 77 | SELENIUM_BROWSER=chrome \ 78 | SELENIUM_HOST=localhost \ 79 | SELENIUM_PORT=4444 \ 80 | composer run test 81 | ``` 82 | 83 | #### Storing local environments in a file for easy reference 84 | 85 | To simplify testing, you can place your environment configuration in a `.env.local` file. 86 | 87 | Example contents: 88 | ``` 89 | export TAWK_PROPERTY_ID='' 90 | export TAWK_WIDGET_ID='' 91 | export TAWK_USERNAME='' 92 | export TAWK_PASSWORD='' 93 | export WEB_HOST='wordpress' 94 | export SELENIUM_BROWSER='chrome' 95 | export SELENIUM_HOST='localhost' 96 | export SELENIUM_PORT='4444' 97 | ``` 98 | 99 | And simply run 100 | 101 | `source .env.local && composer run test` 102 | 103 | ## Debugging the test environment/Developing 104 | 105 | Ensure you have this line in your `/etc/hosts` 106 | ``` 107 | 127.0.0.1 108 | ``` 109 | 110 | Then go to `http:///wp-admin` and login with `WORDPRESS_ADMIN_USER` & `WORDPRESS_ADMIN_PASSWORD` 111 | 112 | ## Running Tests on Github Actions 113 | 114 | This repository is set up to use Github Actions to perform automated testing. 115 | 116 | To use actions in this repository, the following secrets need to be configured: 117 | 118 | | Secret | Description | 119 | |---|---| 120 | | TAWK_PROPERTY_ID | Property Id | 121 | | TAWK_WIDGET_ID | Widget Id | 122 | | TAWK_USERNAME | tawk.to account username | 123 | | TAWK_PASSWORD | tawk.to account password | 124 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tawk/tawk-wordpress", 3 | "description": "Wordpress plugin for tawk.to", 4 | "type": "project", 5 | "license": "GPL-3.0", 6 | "version": "0.9.2", 7 | "require": { 8 | "tawk/url-utils": "2.0.1" 9 | }, 10 | "require-dev": { 11 | "php-webdriver/webdriver": "^1.12", 12 | "phpcompatibility/php-compatibility": "^9.3", 13 | "phpunit/phpunit": "^9.5", 14 | "squizlabs/php_codesniffer": "^3.6", 15 | "woocommerce/woocommerce-sniffs": "^0.1.1", 16 | "wp-coding-standards/wpcs": "^2.3" 17 | }, 18 | "autoload-dev": { 19 | "psr-4": { 20 | "Tawk\\Tests\\": "tests" 21 | } 22 | }, 23 | "repositories": { 24 | "tawk-url-utils": { 25 | "type": "vcs", 26 | "url": "https://github.com/tawk/tawk-url-utils.git" 27 | } 28 | }, 29 | "scripts": { 30 | "test": "phpunit", 31 | "build": "composer run build:dev && composer run build:prod", 32 | "build:dev": "COMPOSER_VENDOR_DIR=vendor composer install", 33 | "build:prod": "COMPOSER_VENDOR_DIR=tawkto/vendor composer install --no-dev", 34 | "lint": "phpcs -p -s -v --ignore=tmp/* --runtime-set ignore_warnings_on_exit true .", 35 | "lint:fix": "phpcbf -p -s -v .; err=$?; if [ $err -eq 1 ]; then exit 0; else exit $err; fi;", 36 | "package": "composer run clean && mkdir -p ./tmp/tawkto-live-chat && cp -r ./tawkto/* ./tmp/tawkto-live-chat && (cd ./tmp && zip -9 -rq ./tawkto-live-chat.zip ./tawkto-live-chat)", 37 | "clean": "rm -rf ./tmp" 38 | }, 39 | "config": { 40 | "process-timeout": 0, 41 | "allow-plugins": { 42 | "dealerdirect/phpcodesniffer-composer-installer": true 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", 5 | "This file is @generated automatically" 6 | ], 7 | "content-hash": "9025254fc381777df07bd83da5448298", 8 | "packages": [ 9 | { 10 | "name": "tawk/url-utils", 11 | "version": "2.0.1", 12 | "source": { 13 | "type": "git", 14 | "url": "https://github.com/tawk/tawk-url-utils.git", 15 | "reference": "73c166333707d893b0160fa9b5eae7aa8fbfa03c" 16 | }, 17 | "dist": { 18 | "type": "zip", 19 | "url": "https://api.github.com/repos/tawk/tawk-url-utils/zipball/73c166333707d893b0160fa9b5eae7aa8fbfa03c", 20 | "reference": "73c166333707d893b0160fa9b5eae7aa8fbfa03c", 21 | "shasum": "" 22 | }, 23 | "require-dev": { 24 | "phpcompatibility/php-compatibility": "^9.3", 25 | "phpunit/phpunit": "^9.5", 26 | "squizlabs/php_codesniffer": "^3.6" 27 | }, 28 | "type": "library", 29 | "autoload": { 30 | "psr-4": { 31 | "Tawk\\": "lib", 32 | "Tawk\\Tests\\": "tests" 33 | } 34 | }, 35 | "scripts": { 36 | "post-install-cmd": [ 37 | "([ $COMPOSER_DEV_MODE -eq 0 ] || vendor/bin/phpcs --config-set installed_paths vendor/phpcompatibility/php-compatibility)" 38 | ], 39 | "post-update-cmd": [ 40 | "([ $COMPOSER_DEV_MODE -eq 0 ] || vendor/bin/phpcs --config-set installed_paths vendor/phpcompatibility/php-compatibility)" 41 | ], 42 | "test": [ 43 | "phpunit" 44 | ], 45 | "lint": [ 46 | "phpcs -p -s -v --runtime-set ignore_warnings_on_exit true ." 47 | ], 48 | "lint:fix": [ 49 | "phpcbf -p -s -v .; err=$?; if [ $err -eq 1 ]; then exit 0; else exit $err; fi;" 50 | ] 51 | }, 52 | "support": { 53 | "source": "https://github.com/tawk/tawk-url-utils/tree/2.0.1", 54 | "issues": "https://github.com/tawk/tawk-url-utils/issues" 55 | }, 56 | "time": "2022-01-28T11:14:45+00:00" 57 | } 58 | ], 59 | "packages-dev": [ 60 | { 61 | "name": "dealerdirect/phpcodesniffer-composer-installer", 62 | "version": "v0.7.2", 63 | "source": { 64 | "type": "git", 65 | "url": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer.git", 66 | "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db" 67 | }, 68 | "dist": { 69 | "type": "zip", 70 | "url": "https://api.github.com/repos/Dealerdirect/phpcodesniffer-composer-installer/zipball/1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", 71 | "reference": "1c968e542d8843d7cd71de3c5c9c3ff3ad71a1db", 72 | "shasum": "" 73 | }, 74 | "require": { 75 | "composer-plugin-api": "^1.0 || ^2.0", 76 | "php": ">=5.3", 77 | "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" 78 | }, 79 | "require-dev": { 80 | "composer/composer": "*", 81 | "php-parallel-lint/php-parallel-lint": "^1.3.1", 82 | "phpcompatibility/php-compatibility": "^9.0" 83 | }, 84 | "type": "composer-plugin", 85 | "extra": { 86 | "class": "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" 87 | }, 88 | "autoload": { 89 | "psr-4": { 90 | "Dealerdirect\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" 91 | } 92 | }, 93 | "notification-url": "https://packagist.org/downloads/", 94 | "license": [ 95 | "MIT" 96 | ], 97 | "authors": [ 98 | { 99 | "name": "Franck Nijhof", 100 | "email": "franck.nijhof@dealerdirect.com", 101 | "homepage": "http://www.frenck.nl", 102 | "role": "Developer / IT Manager" 103 | }, 104 | { 105 | "name": "Contributors", 106 | "homepage": "https://github.com/Dealerdirect/phpcodesniffer-composer-installer/graphs/contributors" 107 | } 108 | ], 109 | "description": "PHP_CodeSniffer Standards Composer Installer Plugin", 110 | "homepage": "http://www.dealerdirect.com", 111 | "keywords": [ 112 | "PHPCodeSniffer", 113 | "PHP_CodeSniffer", 114 | "code quality", 115 | "codesniffer", 116 | "composer", 117 | "installer", 118 | "phpcbf", 119 | "phpcs", 120 | "plugin", 121 | "qa", 122 | "quality", 123 | "standard", 124 | "standards", 125 | "style guide", 126 | "stylecheck", 127 | "tests" 128 | ], 129 | "support": { 130 | "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", 131 | "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" 132 | }, 133 | "time": "2022-02-04T12:51:07+00:00" 134 | }, 135 | { 136 | "name": "doctrine/instantiator", 137 | "version": "2.0.0", 138 | "source": { 139 | "type": "git", 140 | "url": "https://github.com/doctrine/instantiator.git", 141 | "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" 142 | }, 143 | "dist": { 144 | "type": "zip", 145 | "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", 146 | "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", 147 | "shasum": "" 148 | }, 149 | "require": { 150 | "php": "^8.1" 151 | }, 152 | "require-dev": { 153 | "doctrine/coding-standard": "^11", 154 | "ext-pdo": "*", 155 | "ext-phar": "*", 156 | "phpbench/phpbench": "^1.2", 157 | "phpstan/phpstan": "^1.9.4", 158 | "phpstan/phpstan-phpunit": "^1.3", 159 | "phpunit/phpunit": "^9.5.27", 160 | "vimeo/psalm": "^5.4" 161 | }, 162 | "type": "library", 163 | "autoload": { 164 | "psr-4": { 165 | "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" 166 | } 167 | }, 168 | "notification-url": "https://packagist.org/downloads/", 169 | "license": [ 170 | "MIT" 171 | ], 172 | "authors": [ 173 | { 174 | "name": "Marco Pivetta", 175 | "email": "ocramius@gmail.com", 176 | "homepage": "https://ocramius.github.io/" 177 | } 178 | ], 179 | "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", 180 | "homepage": "https://www.doctrine-project.org/projects/instantiator.html", 181 | "keywords": [ 182 | "constructor", 183 | "instantiate" 184 | ], 185 | "support": { 186 | "issues": "https://github.com/doctrine/instantiator/issues", 187 | "source": "https://github.com/doctrine/instantiator/tree/2.0.0" 188 | }, 189 | "funding": [ 190 | { 191 | "url": "https://www.doctrine-project.org/sponsorship.html", 192 | "type": "custom" 193 | }, 194 | { 195 | "url": "https://www.patreon.com/phpdoctrine", 196 | "type": "patreon" 197 | }, 198 | { 199 | "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", 200 | "type": "tidelift" 201 | } 202 | ], 203 | "time": "2022-12-30T00:23:10+00:00" 204 | }, 205 | { 206 | "name": "myclabs/deep-copy", 207 | "version": "1.12.0", 208 | "source": { 209 | "type": "git", 210 | "url": "https://github.com/myclabs/DeepCopy.git", 211 | "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c" 212 | }, 213 | "dist": { 214 | "type": "zip", 215 | "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", 216 | "reference": "3a6b9a42cd8f8771bd4295d13e1423fa7f3d942c", 217 | "shasum": "" 218 | }, 219 | "require": { 220 | "php": "^7.1 || ^8.0" 221 | }, 222 | "conflict": { 223 | "doctrine/collections": "<1.6.8", 224 | "doctrine/common": "<2.13.3 || >=3 <3.2.2" 225 | }, 226 | "require-dev": { 227 | "doctrine/collections": "^1.6.8", 228 | "doctrine/common": "^2.13.3 || ^3.2.2", 229 | "phpspec/prophecy": "^1.10", 230 | "phpunit/phpunit": "^7.5.20 || ^8.5.23 || ^9.5.13" 231 | }, 232 | "type": "library", 233 | "autoload": { 234 | "files": [ 235 | "src/DeepCopy/deep_copy.php" 236 | ], 237 | "psr-4": { 238 | "DeepCopy\\": "src/DeepCopy/" 239 | } 240 | }, 241 | "notification-url": "https://packagist.org/downloads/", 242 | "license": [ 243 | "MIT" 244 | ], 245 | "description": "Create deep copies (clones) of your objects", 246 | "keywords": [ 247 | "clone", 248 | "copy", 249 | "duplicate", 250 | "object", 251 | "object graph" 252 | ], 253 | "support": { 254 | "issues": "https://github.com/myclabs/DeepCopy/issues", 255 | "source": "https://github.com/myclabs/DeepCopy/tree/1.12.0" 256 | }, 257 | "funding": [ 258 | { 259 | "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", 260 | "type": "tidelift" 261 | } 262 | ], 263 | "time": "2024-06-12T14:39:25+00:00" 264 | }, 265 | { 266 | "name": "nikic/php-parser", 267 | "version": "v5.1.0", 268 | "source": { 269 | "type": "git", 270 | "url": "https://github.com/nikic/PHP-Parser.git", 271 | "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1" 272 | }, 273 | "dist": { 274 | "type": "zip", 275 | "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/683130c2ff8c2739f4822ff7ac5c873ec529abd1", 276 | "reference": "683130c2ff8c2739f4822ff7ac5c873ec529abd1", 277 | "shasum": "" 278 | }, 279 | "require": { 280 | "ext-ctype": "*", 281 | "ext-json": "*", 282 | "ext-tokenizer": "*", 283 | "php": ">=7.4" 284 | }, 285 | "require-dev": { 286 | "ircmaxell/php-yacc": "^0.0.7", 287 | "phpunit/phpunit": "^9.0" 288 | }, 289 | "bin": [ 290 | "bin/php-parse" 291 | ], 292 | "type": "library", 293 | "extra": { 294 | "branch-alias": { 295 | "dev-master": "5.0-dev" 296 | } 297 | }, 298 | "autoload": { 299 | "psr-4": { 300 | "PhpParser\\": "lib/PhpParser" 301 | } 302 | }, 303 | "notification-url": "https://packagist.org/downloads/", 304 | "license": [ 305 | "BSD-3-Clause" 306 | ], 307 | "authors": [ 308 | { 309 | "name": "Nikita Popov" 310 | } 311 | ], 312 | "description": "A PHP parser written in PHP", 313 | "keywords": [ 314 | "parser", 315 | "php" 316 | ], 317 | "support": { 318 | "issues": "https://github.com/nikic/PHP-Parser/issues", 319 | "source": "https://github.com/nikic/PHP-Parser/tree/v5.1.0" 320 | }, 321 | "time": "2024-07-01T20:03:41+00:00" 322 | }, 323 | { 324 | "name": "phar-io/manifest", 325 | "version": "2.0.4", 326 | "source": { 327 | "type": "git", 328 | "url": "https://github.com/phar-io/manifest.git", 329 | "reference": "54750ef60c58e43759730615a392c31c80e23176" 330 | }, 331 | "dist": { 332 | "type": "zip", 333 | "url": "https://api.github.com/repos/phar-io/manifest/zipball/54750ef60c58e43759730615a392c31c80e23176", 334 | "reference": "54750ef60c58e43759730615a392c31c80e23176", 335 | "shasum": "" 336 | }, 337 | "require": { 338 | "ext-dom": "*", 339 | "ext-libxml": "*", 340 | "ext-phar": "*", 341 | "ext-xmlwriter": "*", 342 | "phar-io/version": "^3.0.1", 343 | "php": "^7.2 || ^8.0" 344 | }, 345 | "type": "library", 346 | "extra": { 347 | "branch-alias": { 348 | "dev-master": "2.0.x-dev" 349 | } 350 | }, 351 | "autoload": { 352 | "classmap": [ 353 | "src/" 354 | ] 355 | }, 356 | "notification-url": "https://packagist.org/downloads/", 357 | "license": [ 358 | "BSD-3-Clause" 359 | ], 360 | "authors": [ 361 | { 362 | "name": "Arne Blankerts", 363 | "email": "arne@blankerts.de", 364 | "role": "Developer" 365 | }, 366 | { 367 | "name": "Sebastian Heuer", 368 | "email": "sebastian@phpeople.de", 369 | "role": "Developer" 370 | }, 371 | { 372 | "name": "Sebastian Bergmann", 373 | "email": "sebastian@phpunit.de", 374 | "role": "Developer" 375 | } 376 | ], 377 | "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", 378 | "support": { 379 | "issues": "https://github.com/phar-io/manifest/issues", 380 | "source": "https://github.com/phar-io/manifest/tree/2.0.4" 381 | }, 382 | "funding": [ 383 | { 384 | "url": "https://github.com/theseer", 385 | "type": "github" 386 | } 387 | ], 388 | "time": "2024-03-03T12:33:53+00:00" 389 | }, 390 | { 391 | "name": "phar-io/version", 392 | "version": "3.2.1", 393 | "source": { 394 | "type": "git", 395 | "url": "https://github.com/phar-io/version.git", 396 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74" 397 | }, 398 | "dist": { 399 | "type": "zip", 400 | "url": "https://api.github.com/repos/phar-io/version/zipball/4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 401 | "reference": "4f7fd7836c6f332bb2933569e566a0d6c4cbed74", 402 | "shasum": "" 403 | }, 404 | "require": { 405 | "php": "^7.2 || ^8.0" 406 | }, 407 | "type": "library", 408 | "autoload": { 409 | "classmap": [ 410 | "src/" 411 | ] 412 | }, 413 | "notification-url": "https://packagist.org/downloads/", 414 | "license": [ 415 | "BSD-3-Clause" 416 | ], 417 | "authors": [ 418 | { 419 | "name": "Arne Blankerts", 420 | "email": "arne@blankerts.de", 421 | "role": "Developer" 422 | }, 423 | { 424 | "name": "Sebastian Heuer", 425 | "email": "sebastian@phpeople.de", 426 | "role": "Developer" 427 | }, 428 | { 429 | "name": "Sebastian Bergmann", 430 | "email": "sebastian@phpunit.de", 431 | "role": "Developer" 432 | } 433 | ], 434 | "description": "Library for handling version information and constraints", 435 | "support": { 436 | "issues": "https://github.com/phar-io/version/issues", 437 | "source": "https://github.com/phar-io/version/tree/3.2.1" 438 | }, 439 | "time": "2022-02-21T01:04:05+00:00" 440 | }, 441 | { 442 | "name": "php-webdriver/webdriver", 443 | "version": "1.15.1", 444 | "source": { 445 | "type": "git", 446 | "url": "https://github.com/php-webdriver/php-webdriver.git", 447 | "reference": "cd52d9342c5aa738c2e75a67e47a1b6df97154e8" 448 | }, 449 | "dist": { 450 | "type": "zip", 451 | "url": "https://api.github.com/repos/php-webdriver/php-webdriver/zipball/cd52d9342c5aa738c2e75a67e47a1b6df97154e8", 452 | "reference": "cd52d9342c5aa738c2e75a67e47a1b6df97154e8", 453 | "shasum": "" 454 | }, 455 | "require": { 456 | "ext-curl": "*", 457 | "ext-json": "*", 458 | "ext-zip": "*", 459 | "php": "^7.3 || ^8.0", 460 | "symfony/polyfill-mbstring": "^1.12", 461 | "symfony/process": "^5.0 || ^6.0 || ^7.0" 462 | }, 463 | "replace": { 464 | "facebook/webdriver": "*" 465 | }, 466 | "require-dev": { 467 | "ergebnis/composer-normalize": "^2.20.0", 468 | "ondram/ci-detector": "^4.0", 469 | "php-coveralls/php-coveralls": "^2.4", 470 | "php-mock/php-mock-phpunit": "^2.0", 471 | "php-parallel-lint/php-parallel-lint": "^1.2", 472 | "phpunit/phpunit": "^9.3", 473 | "squizlabs/php_codesniffer": "^3.5", 474 | "symfony/var-dumper": "^5.0 || ^6.0" 475 | }, 476 | "suggest": { 477 | "ext-SimpleXML": "For Firefox profile creation" 478 | }, 479 | "type": "library", 480 | "autoload": { 481 | "files": [ 482 | "lib/Exception/TimeoutException.php" 483 | ], 484 | "psr-4": { 485 | "Facebook\\WebDriver\\": "lib/" 486 | } 487 | }, 488 | "notification-url": "https://packagist.org/downloads/", 489 | "license": [ 490 | "MIT" 491 | ], 492 | "description": "A PHP client for Selenium WebDriver. Previously facebook/webdriver.", 493 | "homepage": "https://github.com/php-webdriver/php-webdriver", 494 | "keywords": [ 495 | "Chromedriver", 496 | "geckodriver", 497 | "php", 498 | "selenium", 499 | "webdriver" 500 | ], 501 | "support": { 502 | "issues": "https://github.com/php-webdriver/php-webdriver/issues", 503 | "source": "https://github.com/php-webdriver/php-webdriver/tree/1.15.1" 504 | }, 505 | "time": "2023-10-20T12:21:20+00:00" 506 | }, 507 | { 508 | "name": "phpcompatibility/php-compatibility", 509 | "version": "9.3.5", 510 | "source": { 511 | "type": "git", 512 | "url": "https://github.com/PHPCompatibility/PHPCompatibility.git", 513 | "reference": "9fb324479acf6f39452e0655d2429cc0d3914243" 514 | }, 515 | "dist": { 516 | "type": "zip", 517 | "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibility/zipball/9fb324479acf6f39452e0655d2429cc0d3914243", 518 | "reference": "9fb324479acf6f39452e0655d2429cc0d3914243", 519 | "shasum": "" 520 | }, 521 | "require": { 522 | "php": ">=5.3", 523 | "squizlabs/php_codesniffer": "^2.3 || ^3.0.2" 524 | }, 525 | "conflict": { 526 | "squizlabs/php_codesniffer": "2.6.2" 527 | }, 528 | "require-dev": { 529 | "phpunit/phpunit": "~4.5 || ^5.0 || ^6.0 || ^7.0" 530 | }, 531 | "suggest": { 532 | "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically.", 533 | "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." 534 | }, 535 | "type": "phpcodesniffer-standard", 536 | "notification-url": "https://packagist.org/downloads/", 537 | "license": [ 538 | "LGPL-3.0-or-later" 539 | ], 540 | "authors": [ 541 | { 542 | "name": "Wim Godden", 543 | "homepage": "https://github.com/wimg", 544 | "role": "lead" 545 | }, 546 | { 547 | "name": "Juliette Reinders Folmer", 548 | "homepage": "https://github.com/jrfnl", 549 | "role": "lead" 550 | }, 551 | { 552 | "name": "Contributors", 553 | "homepage": "https://github.com/PHPCompatibility/PHPCompatibility/graphs/contributors" 554 | } 555 | ], 556 | "description": "A set of sniffs for PHP_CodeSniffer that checks for PHP cross-version compatibility.", 557 | "homepage": "http://techblog.wimgodden.be/tag/codesniffer/", 558 | "keywords": [ 559 | "compatibility", 560 | "phpcs", 561 | "standards" 562 | ], 563 | "support": { 564 | "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues", 565 | "source": "https://github.com/PHPCompatibility/PHPCompatibility" 566 | }, 567 | "time": "2019-12-27T09:44:58+00:00" 568 | }, 569 | { 570 | "name": "phpcompatibility/phpcompatibility-paragonie", 571 | "version": "1.3.3", 572 | "source": { 573 | "type": "git", 574 | "url": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie.git", 575 | "reference": "293975b465e0e709b571cbf0c957c6c0a7b9a2ac" 576 | }, 577 | "dist": { 578 | "type": "zip", 579 | "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityParagonie/zipball/293975b465e0e709b571cbf0c957c6c0a7b9a2ac", 580 | "reference": "293975b465e0e709b571cbf0c957c6c0a7b9a2ac", 581 | "shasum": "" 582 | }, 583 | "require": { 584 | "phpcompatibility/php-compatibility": "^9.0" 585 | }, 586 | "require-dev": { 587 | "dealerdirect/phpcodesniffer-composer-installer": "^1.0", 588 | "paragonie/random_compat": "dev-master", 589 | "paragonie/sodium_compat": "dev-master" 590 | }, 591 | "suggest": { 592 | "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", 593 | "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." 594 | }, 595 | "type": "phpcodesniffer-standard", 596 | "notification-url": "https://packagist.org/downloads/", 597 | "license": [ 598 | "LGPL-3.0-or-later" 599 | ], 600 | "authors": [ 601 | { 602 | "name": "Wim Godden", 603 | "role": "lead" 604 | }, 605 | { 606 | "name": "Juliette Reinders Folmer", 607 | "role": "lead" 608 | } 609 | ], 610 | "description": "A set of rulesets for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by the Paragonie polyfill libraries.", 611 | "homepage": "http://phpcompatibility.com/", 612 | "keywords": [ 613 | "compatibility", 614 | "paragonie", 615 | "phpcs", 616 | "polyfill", 617 | "standards", 618 | "static analysis" 619 | ], 620 | "support": { 621 | "issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues", 622 | "security": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/security/policy", 623 | "source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie" 624 | }, 625 | "funding": [ 626 | { 627 | "url": "https://github.com/PHPCompatibility", 628 | "type": "github" 629 | }, 630 | { 631 | "url": "https://github.com/jrfnl", 632 | "type": "github" 633 | }, 634 | { 635 | "url": "https://opencollective.com/php_codesniffer", 636 | "type": "open_collective" 637 | } 638 | ], 639 | "time": "2024-04-24T21:30:46+00:00" 640 | }, 641 | { 642 | "name": "phpcompatibility/phpcompatibility-wp", 643 | "version": "2.1.5", 644 | "source": { 645 | "type": "git", 646 | "url": "https://github.com/PHPCompatibility/PHPCompatibilityWP.git", 647 | "reference": "01c1ff2704a58e46f0cb1ca9d06aee07b3589082" 648 | }, 649 | "dist": { 650 | "type": "zip", 651 | "url": "https://api.github.com/repos/PHPCompatibility/PHPCompatibilityWP/zipball/01c1ff2704a58e46f0cb1ca9d06aee07b3589082", 652 | "reference": "01c1ff2704a58e46f0cb1ca9d06aee07b3589082", 653 | "shasum": "" 654 | }, 655 | "require": { 656 | "phpcompatibility/php-compatibility": "^9.0", 657 | "phpcompatibility/phpcompatibility-paragonie": "^1.0" 658 | }, 659 | "require-dev": { 660 | "dealerdirect/phpcodesniffer-composer-installer": "^1.0" 661 | }, 662 | "suggest": { 663 | "dealerdirect/phpcodesniffer-composer-installer": "^1.0 || This Composer plugin will sort out the PHP_CodeSniffer 'installed_paths' automatically.", 664 | "roave/security-advisories": "dev-master || Helps prevent installing dependencies with known security issues." 665 | }, 666 | "type": "phpcodesniffer-standard", 667 | "notification-url": "https://packagist.org/downloads/", 668 | "license": [ 669 | "LGPL-3.0-or-later" 670 | ], 671 | "authors": [ 672 | { 673 | "name": "Wim Godden", 674 | "role": "lead" 675 | }, 676 | { 677 | "name": "Juliette Reinders Folmer", 678 | "role": "lead" 679 | } 680 | ], 681 | "description": "A ruleset for PHP_CodeSniffer to check for PHP cross-version compatibility issues in projects, while accounting for polyfills provided by WordPress.", 682 | "homepage": "http://phpcompatibility.com/", 683 | "keywords": [ 684 | "compatibility", 685 | "phpcs", 686 | "standards", 687 | "static analysis", 688 | "wordpress" 689 | ], 690 | "support": { 691 | "issues": "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues", 692 | "security": "https://github.com/PHPCompatibility/PHPCompatibilityWP/security/policy", 693 | "source": "https://github.com/PHPCompatibility/PHPCompatibilityWP" 694 | }, 695 | "funding": [ 696 | { 697 | "url": "https://github.com/PHPCompatibility", 698 | "type": "github" 699 | }, 700 | { 701 | "url": "https://github.com/jrfnl", 702 | "type": "github" 703 | }, 704 | { 705 | "url": "https://opencollective.com/php_codesniffer", 706 | "type": "open_collective" 707 | } 708 | ], 709 | "time": "2024-04-24T21:37:59+00:00" 710 | }, 711 | { 712 | "name": "phpunit/php-code-coverage", 713 | "version": "9.2.31", 714 | "source": { 715 | "type": "git", 716 | "url": "https://github.com/sebastianbergmann/php-code-coverage.git", 717 | "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965" 718 | }, 719 | "dist": { 720 | "type": "zip", 721 | "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/48c34b5d8d983006bd2adc2d0de92963b9155965", 722 | "reference": "48c34b5d8d983006bd2adc2d0de92963b9155965", 723 | "shasum": "" 724 | }, 725 | "require": { 726 | "ext-dom": "*", 727 | "ext-libxml": "*", 728 | "ext-xmlwriter": "*", 729 | "nikic/php-parser": "^4.18 || ^5.0", 730 | "php": ">=7.3", 731 | "phpunit/php-file-iterator": "^3.0.3", 732 | "phpunit/php-text-template": "^2.0.2", 733 | "sebastian/code-unit-reverse-lookup": "^2.0.2", 734 | "sebastian/complexity": "^2.0", 735 | "sebastian/environment": "^5.1.2", 736 | "sebastian/lines-of-code": "^1.0.3", 737 | "sebastian/version": "^3.0.1", 738 | "theseer/tokenizer": "^1.2.0" 739 | }, 740 | "require-dev": { 741 | "phpunit/phpunit": "^9.3" 742 | }, 743 | "suggest": { 744 | "ext-pcov": "PHP extension that provides line coverage", 745 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" 746 | }, 747 | "type": "library", 748 | "extra": { 749 | "branch-alias": { 750 | "dev-master": "9.2-dev" 751 | } 752 | }, 753 | "autoload": { 754 | "classmap": [ 755 | "src/" 756 | ] 757 | }, 758 | "notification-url": "https://packagist.org/downloads/", 759 | "license": [ 760 | "BSD-3-Clause" 761 | ], 762 | "authors": [ 763 | { 764 | "name": "Sebastian Bergmann", 765 | "email": "sebastian@phpunit.de", 766 | "role": "lead" 767 | } 768 | ], 769 | "description": "Library that provides collection, processing, and rendering functionality for PHP code coverage information.", 770 | "homepage": "https://github.com/sebastianbergmann/php-code-coverage", 771 | "keywords": [ 772 | "coverage", 773 | "testing", 774 | "xunit" 775 | ], 776 | "support": { 777 | "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", 778 | "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", 779 | "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.31" 780 | }, 781 | "funding": [ 782 | { 783 | "url": "https://github.com/sebastianbergmann", 784 | "type": "github" 785 | } 786 | ], 787 | "time": "2024-03-02T06:37:42+00:00" 788 | }, 789 | { 790 | "name": "phpunit/php-file-iterator", 791 | "version": "3.0.6", 792 | "source": { 793 | "type": "git", 794 | "url": "https://github.com/sebastianbergmann/php-file-iterator.git", 795 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" 796 | }, 797 | "dist": { 798 | "type": "zip", 799 | "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", 800 | "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", 801 | "shasum": "" 802 | }, 803 | "require": { 804 | "php": ">=7.3" 805 | }, 806 | "require-dev": { 807 | "phpunit/phpunit": "^9.3" 808 | }, 809 | "type": "library", 810 | "extra": { 811 | "branch-alias": { 812 | "dev-master": "3.0-dev" 813 | } 814 | }, 815 | "autoload": { 816 | "classmap": [ 817 | "src/" 818 | ] 819 | }, 820 | "notification-url": "https://packagist.org/downloads/", 821 | "license": [ 822 | "BSD-3-Clause" 823 | ], 824 | "authors": [ 825 | { 826 | "name": "Sebastian Bergmann", 827 | "email": "sebastian@phpunit.de", 828 | "role": "lead" 829 | } 830 | ], 831 | "description": "FilterIterator implementation that filters files based on a list of suffixes.", 832 | "homepage": "https://github.com/sebastianbergmann/php-file-iterator/", 833 | "keywords": [ 834 | "filesystem", 835 | "iterator" 836 | ], 837 | "support": { 838 | "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", 839 | "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" 840 | }, 841 | "funding": [ 842 | { 843 | "url": "https://github.com/sebastianbergmann", 844 | "type": "github" 845 | } 846 | ], 847 | "time": "2021-12-02T12:48:52+00:00" 848 | }, 849 | { 850 | "name": "phpunit/php-invoker", 851 | "version": "3.1.1", 852 | "source": { 853 | "type": "git", 854 | "url": "https://github.com/sebastianbergmann/php-invoker.git", 855 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" 856 | }, 857 | "dist": { 858 | "type": "zip", 859 | "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", 860 | "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", 861 | "shasum": "" 862 | }, 863 | "require": { 864 | "php": ">=7.3" 865 | }, 866 | "require-dev": { 867 | "ext-pcntl": "*", 868 | "phpunit/phpunit": "^9.3" 869 | }, 870 | "suggest": { 871 | "ext-pcntl": "*" 872 | }, 873 | "type": "library", 874 | "extra": { 875 | "branch-alias": { 876 | "dev-master": "3.1-dev" 877 | } 878 | }, 879 | "autoload": { 880 | "classmap": [ 881 | "src/" 882 | ] 883 | }, 884 | "notification-url": "https://packagist.org/downloads/", 885 | "license": [ 886 | "BSD-3-Clause" 887 | ], 888 | "authors": [ 889 | { 890 | "name": "Sebastian Bergmann", 891 | "email": "sebastian@phpunit.de", 892 | "role": "lead" 893 | } 894 | ], 895 | "description": "Invoke callables with a timeout", 896 | "homepage": "https://github.com/sebastianbergmann/php-invoker/", 897 | "keywords": [ 898 | "process" 899 | ], 900 | "support": { 901 | "issues": "https://github.com/sebastianbergmann/php-invoker/issues", 902 | "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" 903 | }, 904 | "funding": [ 905 | { 906 | "url": "https://github.com/sebastianbergmann", 907 | "type": "github" 908 | } 909 | ], 910 | "time": "2020-09-28T05:58:55+00:00" 911 | }, 912 | { 913 | "name": "phpunit/php-text-template", 914 | "version": "2.0.4", 915 | "source": { 916 | "type": "git", 917 | "url": "https://github.com/sebastianbergmann/php-text-template.git", 918 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" 919 | }, 920 | "dist": { 921 | "type": "zip", 922 | "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", 923 | "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", 924 | "shasum": "" 925 | }, 926 | "require": { 927 | "php": ">=7.3" 928 | }, 929 | "require-dev": { 930 | "phpunit/phpunit": "^9.3" 931 | }, 932 | "type": "library", 933 | "extra": { 934 | "branch-alias": { 935 | "dev-master": "2.0-dev" 936 | } 937 | }, 938 | "autoload": { 939 | "classmap": [ 940 | "src/" 941 | ] 942 | }, 943 | "notification-url": "https://packagist.org/downloads/", 944 | "license": [ 945 | "BSD-3-Clause" 946 | ], 947 | "authors": [ 948 | { 949 | "name": "Sebastian Bergmann", 950 | "email": "sebastian@phpunit.de", 951 | "role": "lead" 952 | } 953 | ], 954 | "description": "Simple template engine.", 955 | "homepage": "https://github.com/sebastianbergmann/php-text-template/", 956 | "keywords": [ 957 | "template" 958 | ], 959 | "support": { 960 | "issues": "https://github.com/sebastianbergmann/php-text-template/issues", 961 | "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" 962 | }, 963 | "funding": [ 964 | { 965 | "url": "https://github.com/sebastianbergmann", 966 | "type": "github" 967 | } 968 | ], 969 | "time": "2020-10-26T05:33:50+00:00" 970 | }, 971 | { 972 | "name": "phpunit/php-timer", 973 | "version": "5.0.3", 974 | "source": { 975 | "type": "git", 976 | "url": "https://github.com/sebastianbergmann/php-timer.git", 977 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" 978 | }, 979 | "dist": { 980 | "type": "zip", 981 | "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", 982 | "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", 983 | "shasum": "" 984 | }, 985 | "require": { 986 | "php": ">=7.3" 987 | }, 988 | "require-dev": { 989 | "phpunit/phpunit": "^9.3" 990 | }, 991 | "type": "library", 992 | "extra": { 993 | "branch-alias": { 994 | "dev-master": "5.0-dev" 995 | } 996 | }, 997 | "autoload": { 998 | "classmap": [ 999 | "src/" 1000 | ] 1001 | }, 1002 | "notification-url": "https://packagist.org/downloads/", 1003 | "license": [ 1004 | "BSD-3-Clause" 1005 | ], 1006 | "authors": [ 1007 | { 1008 | "name": "Sebastian Bergmann", 1009 | "email": "sebastian@phpunit.de", 1010 | "role": "lead" 1011 | } 1012 | ], 1013 | "description": "Utility class for timing", 1014 | "homepage": "https://github.com/sebastianbergmann/php-timer/", 1015 | "keywords": [ 1016 | "timer" 1017 | ], 1018 | "support": { 1019 | "issues": "https://github.com/sebastianbergmann/php-timer/issues", 1020 | "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" 1021 | }, 1022 | "funding": [ 1023 | { 1024 | "url": "https://github.com/sebastianbergmann", 1025 | "type": "github" 1026 | } 1027 | ], 1028 | "time": "2020-10-26T13:16:10+00:00" 1029 | }, 1030 | { 1031 | "name": "phpunit/phpunit", 1032 | "version": "9.6.19", 1033 | "source": { 1034 | "type": "git", 1035 | "url": "https://github.com/sebastianbergmann/phpunit.git", 1036 | "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8" 1037 | }, 1038 | "dist": { 1039 | "type": "zip", 1040 | "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a1a54a473501ef4cdeaae4e06891674114d79db8", 1041 | "reference": "a1a54a473501ef4cdeaae4e06891674114d79db8", 1042 | "shasum": "" 1043 | }, 1044 | "require": { 1045 | "doctrine/instantiator": "^1.3.1 || ^2", 1046 | "ext-dom": "*", 1047 | "ext-json": "*", 1048 | "ext-libxml": "*", 1049 | "ext-mbstring": "*", 1050 | "ext-xml": "*", 1051 | "ext-xmlwriter": "*", 1052 | "myclabs/deep-copy": "^1.10.1", 1053 | "phar-io/manifest": "^2.0.3", 1054 | "phar-io/version": "^3.0.2", 1055 | "php": ">=7.3", 1056 | "phpunit/php-code-coverage": "^9.2.28", 1057 | "phpunit/php-file-iterator": "^3.0.5", 1058 | "phpunit/php-invoker": "^3.1.1", 1059 | "phpunit/php-text-template": "^2.0.3", 1060 | "phpunit/php-timer": "^5.0.2", 1061 | "sebastian/cli-parser": "^1.0.1", 1062 | "sebastian/code-unit": "^1.0.6", 1063 | "sebastian/comparator": "^4.0.8", 1064 | "sebastian/diff": "^4.0.3", 1065 | "sebastian/environment": "^5.1.3", 1066 | "sebastian/exporter": "^4.0.5", 1067 | "sebastian/global-state": "^5.0.1", 1068 | "sebastian/object-enumerator": "^4.0.3", 1069 | "sebastian/resource-operations": "^3.0.3", 1070 | "sebastian/type": "^3.2", 1071 | "sebastian/version": "^3.0.2" 1072 | }, 1073 | "suggest": { 1074 | "ext-soap": "To be able to generate mocks based on WSDL files", 1075 | "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" 1076 | }, 1077 | "bin": [ 1078 | "phpunit" 1079 | ], 1080 | "type": "library", 1081 | "extra": { 1082 | "branch-alias": { 1083 | "dev-master": "9.6-dev" 1084 | } 1085 | }, 1086 | "autoload": { 1087 | "files": [ 1088 | "src/Framework/Assert/Functions.php" 1089 | ], 1090 | "classmap": [ 1091 | "src/" 1092 | ] 1093 | }, 1094 | "notification-url": "https://packagist.org/downloads/", 1095 | "license": [ 1096 | "BSD-3-Clause" 1097 | ], 1098 | "authors": [ 1099 | { 1100 | "name": "Sebastian Bergmann", 1101 | "email": "sebastian@phpunit.de", 1102 | "role": "lead" 1103 | } 1104 | ], 1105 | "description": "The PHP Unit Testing framework.", 1106 | "homepage": "https://phpunit.de/", 1107 | "keywords": [ 1108 | "phpunit", 1109 | "testing", 1110 | "xunit" 1111 | ], 1112 | "support": { 1113 | "issues": "https://github.com/sebastianbergmann/phpunit/issues", 1114 | "security": "https://github.com/sebastianbergmann/phpunit/security/policy", 1115 | "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.19" 1116 | }, 1117 | "funding": [ 1118 | { 1119 | "url": "https://phpunit.de/sponsors.html", 1120 | "type": "custom" 1121 | }, 1122 | { 1123 | "url": "https://github.com/sebastianbergmann", 1124 | "type": "github" 1125 | }, 1126 | { 1127 | "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", 1128 | "type": "tidelift" 1129 | } 1130 | ], 1131 | "time": "2024-04-05T04:35:58+00:00" 1132 | }, 1133 | { 1134 | "name": "sebastian/cli-parser", 1135 | "version": "1.0.2", 1136 | "source": { 1137 | "type": "git", 1138 | "url": "https://github.com/sebastianbergmann/cli-parser.git", 1139 | "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" 1140 | }, 1141 | "dist": { 1142 | "type": "zip", 1143 | "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", 1144 | "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", 1145 | "shasum": "" 1146 | }, 1147 | "require": { 1148 | "php": ">=7.3" 1149 | }, 1150 | "require-dev": { 1151 | "phpunit/phpunit": "^9.3" 1152 | }, 1153 | "type": "library", 1154 | "extra": { 1155 | "branch-alias": { 1156 | "dev-master": "1.0-dev" 1157 | } 1158 | }, 1159 | "autoload": { 1160 | "classmap": [ 1161 | "src/" 1162 | ] 1163 | }, 1164 | "notification-url": "https://packagist.org/downloads/", 1165 | "license": [ 1166 | "BSD-3-Clause" 1167 | ], 1168 | "authors": [ 1169 | { 1170 | "name": "Sebastian Bergmann", 1171 | "email": "sebastian@phpunit.de", 1172 | "role": "lead" 1173 | } 1174 | ], 1175 | "description": "Library for parsing CLI options", 1176 | "homepage": "https://github.com/sebastianbergmann/cli-parser", 1177 | "support": { 1178 | "issues": "https://github.com/sebastianbergmann/cli-parser/issues", 1179 | "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" 1180 | }, 1181 | "funding": [ 1182 | { 1183 | "url": "https://github.com/sebastianbergmann", 1184 | "type": "github" 1185 | } 1186 | ], 1187 | "time": "2024-03-02T06:27:43+00:00" 1188 | }, 1189 | { 1190 | "name": "sebastian/code-unit", 1191 | "version": "1.0.8", 1192 | "source": { 1193 | "type": "git", 1194 | "url": "https://github.com/sebastianbergmann/code-unit.git", 1195 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" 1196 | }, 1197 | "dist": { 1198 | "type": "zip", 1199 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", 1200 | "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", 1201 | "shasum": "" 1202 | }, 1203 | "require": { 1204 | "php": ">=7.3" 1205 | }, 1206 | "require-dev": { 1207 | "phpunit/phpunit": "^9.3" 1208 | }, 1209 | "type": "library", 1210 | "extra": { 1211 | "branch-alias": { 1212 | "dev-master": "1.0-dev" 1213 | } 1214 | }, 1215 | "autoload": { 1216 | "classmap": [ 1217 | "src/" 1218 | ] 1219 | }, 1220 | "notification-url": "https://packagist.org/downloads/", 1221 | "license": [ 1222 | "BSD-3-Clause" 1223 | ], 1224 | "authors": [ 1225 | { 1226 | "name": "Sebastian Bergmann", 1227 | "email": "sebastian@phpunit.de", 1228 | "role": "lead" 1229 | } 1230 | ], 1231 | "description": "Collection of value objects that represent the PHP code units", 1232 | "homepage": "https://github.com/sebastianbergmann/code-unit", 1233 | "support": { 1234 | "issues": "https://github.com/sebastianbergmann/code-unit/issues", 1235 | "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" 1236 | }, 1237 | "funding": [ 1238 | { 1239 | "url": "https://github.com/sebastianbergmann", 1240 | "type": "github" 1241 | } 1242 | ], 1243 | "time": "2020-10-26T13:08:54+00:00" 1244 | }, 1245 | { 1246 | "name": "sebastian/code-unit-reverse-lookup", 1247 | "version": "2.0.3", 1248 | "source": { 1249 | "type": "git", 1250 | "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", 1251 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" 1252 | }, 1253 | "dist": { 1254 | "type": "zip", 1255 | "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", 1256 | "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", 1257 | "shasum": "" 1258 | }, 1259 | "require": { 1260 | "php": ">=7.3" 1261 | }, 1262 | "require-dev": { 1263 | "phpunit/phpunit": "^9.3" 1264 | }, 1265 | "type": "library", 1266 | "extra": { 1267 | "branch-alias": { 1268 | "dev-master": "2.0-dev" 1269 | } 1270 | }, 1271 | "autoload": { 1272 | "classmap": [ 1273 | "src/" 1274 | ] 1275 | }, 1276 | "notification-url": "https://packagist.org/downloads/", 1277 | "license": [ 1278 | "BSD-3-Clause" 1279 | ], 1280 | "authors": [ 1281 | { 1282 | "name": "Sebastian Bergmann", 1283 | "email": "sebastian@phpunit.de" 1284 | } 1285 | ], 1286 | "description": "Looks up which function or method a line of code belongs to", 1287 | "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", 1288 | "support": { 1289 | "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", 1290 | "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" 1291 | }, 1292 | "funding": [ 1293 | { 1294 | "url": "https://github.com/sebastianbergmann", 1295 | "type": "github" 1296 | } 1297 | ], 1298 | "time": "2020-09-28T05:30:19+00:00" 1299 | }, 1300 | { 1301 | "name": "sebastian/comparator", 1302 | "version": "4.0.8", 1303 | "source": { 1304 | "type": "git", 1305 | "url": "https://github.com/sebastianbergmann/comparator.git", 1306 | "reference": "fa0f136dd2334583309d32b62544682ee972b51a" 1307 | }, 1308 | "dist": { 1309 | "type": "zip", 1310 | "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a", 1311 | "reference": "fa0f136dd2334583309d32b62544682ee972b51a", 1312 | "shasum": "" 1313 | }, 1314 | "require": { 1315 | "php": ">=7.3", 1316 | "sebastian/diff": "^4.0", 1317 | "sebastian/exporter": "^4.0" 1318 | }, 1319 | "require-dev": { 1320 | "phpunit/phpunit": "^9.3" 1321 | }, 1322 | "type": "library", 1323 | "extra": { 1324 | "branch-alias": { 1325 | "dev-master": "4.0-dev" 1326 | } 1327 | }, 1328 | "autoload": { 1329 | "classmap": [ 1330 | "src/" 1331 | ] 1332 | }, 1333 | "notification-url": "https://packagist.org/downloads/", 1334 | "license": [ 1335 | "BSD-3-Clause" 1336 | ], 1337 | "authors": [ 1338 | { 1339 | "name": "Sebastian Bergmann", 1340 | "email": "sebastian@phpunit.de" 1341 | }, 1342 | { 1343 | "name": "Jeff Welch", 1344 | "email": "whatthejeff@gmail.com" 1345 | }, 1346 | { 1347 | "name": "Volker Dusch", 1348 | "email": "github@wallbash.com" 1349 | }, 1350 | { 1351 | "name": "Bernhard Schussek", 1352 | "email": "bschussek@2bepublished.at" 1353 | } 1354 | ], 1355 | "description": "Provides the functionality to compare PHP values for equality", 1356 | "homepage": "https://github.com/sebastianbergmann/comparator", 1357 | "keywords": [ 1358 | "comparator", 1359 | "compare", 1360 | "equality" 1361 | ], 1362 | "support": { 1363 | "issues": "https://github.com/sebastianbergmann/comparator/issues", 1364 | "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8" 1365 | }, 1366 | "funding": [ 1367 | { 1368 | "url": "https://github.com/sebastianbergmann", 1369 | "type": "github" 1370 | } 1371 | ], 1372 | "time": "2022-09-14T12:41:17+00:00" 1373 | }, 1374 | { 1375 | "name": "sebastian/complexity", 1376 | "version": "2.0.3", 1377 | "source": { 1378 | "type": "git", 1379 | "url": "https://github.com/sebastianbergmann/complexity.git", 1380 | "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" 1381 | }, 1382 | "dist": { 1383 | "type": "zip", 1384 | "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", 1385 | "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", 1386 | "shasum": "" 1387 | }, 1388 | "require": { 1389 | "nikic/php-parser": "^4.18 || ^5.0", 1390 | "php": ">=7.3" 1391 | }, 1392 | "require-dev": { 1393 | "phpunit/phpunit": "^9.3" 1394 | }, 1395 | "type": "library", 1396 | "extra": { 1397 | "branch-alias": { 1398 | "dev-master": "2.0-dev" 1399 | } 1400 | }, 1401 | "autoload": { 1402 | "classmap": [ 1403 | "src/" 1404 | ] 1405 | }, 1406 | "notification-url": "https://packagist.org/downloads/", 1407 | "license": [ 1408 | "BSD-3-Clause" 1409 | ], 1410 | "authors": [ 1411 | { 1412 | "name": "Sebastian Bergmann", 1413 | "email": "sebastian@phpunit.de", 1414 | "role": "lead" 1415 | } 1416 | ], 1417 | "description": "Library for calculating the complexity of PHP code units", 1418 | "homepage": "https://github.com/sebastianbergmann/complexity", 1419 | "support": { 1420 | "issues": "https://github.com/sebastianbergmann/complexity/issues", 1421 | "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" 1422 | }, 1423 | "funding": [ 1424 | { 1425 | "url": "https://github.com/sebastianbergmann", 1426 | "type": "github" 1427 | } 1428 | ], 1429 | "time": "2023-12-22T06:19:30+00:00" 1430 | }, 1431 | { 1432 | "name": "sebastian/diff", 1433 | "version": "4.0.6", 1434 | "source": { 1435 | "type": "git", 1436 | "url": "https://github.com/sebastianbergmann/diff.git", 1437 | "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" 1438 | }, 1439 | "dist": { 1440 | "type": "zip", 1441 | "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", 1442 | "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", 1443 | "shasum": "" 1444 | }, 1445 | "require": { 1446 | "php": ">=7.3" 1447 | }, 1448 | "require-dev": { 1449 | "phpunit/phpunit": "^9.3", 1450 | "symfony/process": "^4.2 || ^5" 1451 | }, 1452 | "type": "library", 1453 | "extra": { 1454 | "branch-alias": { 1455 | "dev-master": "4.0-dev" 1456 | } 1457 | }, 1458 | "autoload": { 1459 | "classmap": [ 1460 | "src/" 1461 | ] 1462 | }, 1463 | "notification-url": "https://packagist.org/downloads/", 1464 | "license": [ 1465 | "BSD-3-Clause" 1466 | ], 1467 | "authors": [ 1468 | { 1469 | "name": "Sebastian Bergmann", 1470 | "email": "sebastian@phpunit.de" 1471 | }, 1472 | { 1473 | "name": "Kore Nordmann", 1474 | "email": "mail@kore-nordmann.de" 1475 | } 1476 | ], 1477 | "description": "Diff implementation", 1478 | "homepage": "https://github.com/sebastianbergmann/diff", 1479 | "keywords": [ 1480 | "diff", 1481 | "udiff", 1482 | "unidiff", 1483 | "unified diff" 1484 | ], 1485 | "support": { 1486 | "issues": "https://github.com/sebastianbergmann/diff/issues", 1487 | "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" 1488 | }, 1489 | "funding": [ 1490 | { 1491 | "url": "https://github.com/sebastianbergmann", 1492 | "type": "github" 1493 | } 1494 | ], 1495 | "time": "2024-03-02T06:30:58+00:00" 1496 | }, 1497 | { 1498 | "name": "sebastian/environment", 1499 | "version": "5.1.5", 1500 | "source": { 1501 | "type": "git", 1502 | "url": "https://github.com/sebastianbergmann/environment.git", 1503 | "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" 1504 | }, 1505 | "dist": { 1506 | "type": "zip", 1507 | "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", 1508 | "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", 1509 | "shasum": "" 1510 | }, 1511 | "require": { 1512 | "php": ">=7.3" 1513 | }, 1514 | "require-dev": { 1515 | "phpunit/phpunit": "^9.3" 1516 | }, 1517 | "suggest": { 1518 | "ext-posix": "*" 1519 | }, 1520 | "type": "library", 1521 | "extra": { 1522 | "branch-alias": { 1523 | "dev-master": "5.1-dev" 1524 | } 1525 | }, 1526 | "autoload": { 1527 | "classmap": [ 1528 | "src/" 1529 | ] 1530 | }, 1531 | "notification-url": "https://packagist.org/downloads/", 1532 | "license": [ 1533 | "BSD-3-Clause" 1534 | ], 1535 | "authors": [ 1536 | { 1537 | "name": "Sebastian Bergmann", 1538 | "email": "sebastian@phpunit.de" 1539 | } 1540 | ], 1541 | "description": "Provides functionality to handle HHVM/PHP environments", 1542 | "homepage": "http://www.github.com/sebastianbergmann/environment", 1543 | "keywords": [ 1544 | "Xdebug", 1545 | "environment", 1546 | "hhvm" 1547 | ], 1548 | "support": { 1549 | "issues": "https://github.com/sebastianbergmann/environment/issues", 1550 | "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" 1551 | }, 1552 | "funding": [ 1553 | { 1554 | "url": "https://github.com/sebastianbergmann", 1555 | "type": "github" 1556 | } 1557 | ], 1558 | "time": "2023-02-03T06:03:51+00:00" 1559 | }, 1560 | { 1561 | "name": "sebastian/exporter", 1562 | "version": "4.0.6", 1563 | "source": { 1564 | "type": "git", 1565 | "url": "https://github.com/sebastianbergmann/exporter.git", 1566 | "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72" 1567 | }, 1568 | "dist": { 1569 | "type": "zip", 1570 | "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72", 1571 | "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72", 1572 | "shasum": "" 1573 | }, 1574 | "require": { 1575 | "php": ">=7.3", 1576 | "sebastian/recursion-context": "^4.0" 1577 | }, 1578 | "require-dev": { 1579 | "ext-mbstring": "*", 1580 | "phpunit/phpunit": "^9.3" 1581 | }, 1582 | "type": "library", 1583 | "extra": { 1584 | "branch-alias": { 1585 | "dev-master": "4.0-dev" 1586 | } 1587 | }, 1588 | "autoload": { 1589 | "classmap": [ 1590 | "src/" 1591 | ] 1592 | }, 1593 | "notification-url": "https://packagist.org/downloads/", 1594 | "license": [ 1595 | "BSD-3-Clause" 1596 | ], 1597 | "authors": [ 1598 | { 1599 | "name": "Sebastian Bergmann", 1600 | "email": "sebastian@phpunit.de" 1601 | }, 1602 | { 1603 | "name": "Jeff Welch", 1604 | "email": "whatthejeff@gmail.com" 1605 | }, 1606 | { 1607 | "name": "Volker Dusch", 1608 | "email": "github@wallbash.com" 1609 | }, 1610 | { 1611 | "name": "Adam Harvey", 1612 | "email": "aharvey@php.net" 1613 | }, 1614 | { 1615 | "name": "Bernhard Schussek", 1616 | "email": "bschussek@gmail.com" 1617 | } 1618 | ], 1619 | "description": "Provides the functionality to export PHP variables for visualization", 1620 | "homepage": "https://www.github.com/sebastianbergmann/exporter", 1621 | "keywords": [ 1622 | "export", 1623 | "exporter" 1624 | ], 1625 | "support": { 1626 | "issues": "https://github.com/sebastianbergmann/exporter/issues", 1627 | "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6" 1628 | }, 1629 | "funding": [ 1630 | { 1631 | "url": "https://github.com/sebastianbergmann", 1632 | "type": "github" 1633 | } 1634 | ], 1635 | "time": "2024-03-02T06:33:00+00:00" 1636 | }, 1637 | { 1638 | "name": "sebastian/global-state", 1639 | "version": "5.0.7", 1640 | "source": { 1641 | "type": "git", 1642 | "url": "https://github.com/sebastianbergmann/global-state.git", 1643 | "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9" 1644 | }, 1645 | "dist": { 1646 | "type": "zip", 1647 | "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", 1648 | "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9", 1649 | "shasum": "" 1650 | }, 1651 | "require": { 1652 | "php": ">=7.3", 1653 | "sebastian/object-reflector": "^2.0", 1654 | "sebastian/recursion-context": "^4.0" 1655 | }, 1656 | "require-dev": { 1657 | "ext-dom": "*", 1658 | "phpunit/phpunit": "^9.3" 1659 | }, 1660 | "suggest": { 1661 | "ext-uopz": "*" 1662 | }, 1663 | "type": "library", 1664 | "extra": { 1665 | "branch-alias": { 1666 | "dev-master": "5.0-dev" 1667 | } 1668 | }, 1669 | "autoload": { 1670 | "classmap": [ 1671 | "src/" 1672 | ] 1673 | }, 1674 | "notification-url": "https://packagist.org/downloads/", 1675 | "license": [ 1676 | "BSD-3-Clause" 1677 | ], 1678 | "authors": [ 1679 | { 1680 | "name": "Sebastian Bergmann", 1681 | "email": "sebastian@phpunit.de" 1682 | } 1683 | ], 1684 | "description": "Snapshotting of global state", 1685 | "homepage": "http://www.github.com/sebastianbergmann/global-state", 1686 | "keywords": [ 1687 | "global state" 1688 | ], 1689 | "support": { 1690 | "issues": "https://github.com/sebastianbergmann/global-state/issues", 1691 | "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7" 1692 | }, 1693 | "funding": [ 1694 | { 1695 | "url": "https://github.com/sebastianbergmann", 1696 | "type": "github" 1697 | } 1698 | ], 1699 | "time": "2024-03-02T06:35:11+00:00" 1700 | }, 1701 | { 1702 | "name": "sebastian/lines-of-code", 1703 | "version": "1.0.4", 1704 | "source": { 1705 | "type": "git", 1706 | "url": "https://github.com/sebastianbergmann/lines-of-code.git", 1707 | "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" 1708 | }, 1709 | "dist": { 1710 | "type": "zip", 1711 | "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", 1712 | "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", 1713 | "shasum": "" 1714 | }, 1715 | "require": { 1716 | "nikic/php-parser": "^4.18 || ^5.0", 1717 | "php": ">=7.3" 1718 | }, 1719 | "require-dev": { 1720 | "phpunit/phpunit": "^9.3" 1721 | }, 1722 | "type": "library", 1723 | "extra": { 1724 | "branch-alias": { 1725 | "dev-master": "1.0-dev" 1726 | } 1727 | }, 1728 | "autoload": { 1729 | "classmap": [ 1730 | "src/" 1731 | ] 1732 | }, 1733 | "notification-url": "https://packagist.org/downloads/", 1734 | "license": [ 1735 | "BSD-3-Clause" 1736 | ], 1737 | "authors": [ 1738 | { 1739 | "name": "Sebastian Bergmann", 1740 | "email": "sebastian@phpunit.de", 1741 | "role": "lead" 1742 | } 1743 | ], 1744 | "description": "Library for counting the lines of code in PHP source code", 1745 | "homepage": "https://github.com/sebastianbergmann/lines-of-code", 1746 | "support": { 1747 | "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", 1748 | "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" 1749 | }, 1750 | "funding": [ 1751 | { 1752 | "url": "https://github.com/sebastianbergmann", 1753 | "type": "github" 1754 | } 1755 | ], 1756 | "time": "2023-12-22T06:20:34+00:00" 1757 | }, 1758 | { 1759 | "name": "sebastian/object-enumerator", 1760 | "version": "4.0.4", 1761 | "source": { 1762 | "type": "git", 1763 | "url": "https://github.com/sebastianbergmann/object-enumerator.git", 1764 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" 1765 | }, 1766 | "dist": { 1767 | "type": "zip", 1768 | "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", 1769 | "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", 1770 | "shasum": "" 1771 | }, 1772 | "require": { 1773 | "php": ">=7.3", 1774 | "sebastian/object-reflector": "^2.0", 1775 | "sebastian/recursion-context": "^4.0" 1776 | }, 1777 | "require-dev": { 1778 | "phpunit/phpunit": "^9.3" 1779 | }, 1780 | "type": "library", 1781 | "extra": { 1782 | "branch-alias": { 1783 | "dev-master": "4.0-dev" 1784 | } 1785 | }, 1786 | "autoload": { 1787 | "classmap": [ 1788 | "src/" 1789 | ] 1790 | }, 1791 | "notification-url": "https://packagist.org/downloads/", 1792 | "license": [ 1793 | "BSD-3-Clause" 1794 | ], 1795 | "authors": [ 1796 | { 1797 | "name": "Sebastian Bergmann", 1798 | "email": "sebastian@phpunit.de" 1799 | } 1800 | ], 1801 | "description": "Traverses array structures and object graphs to enumerate all referenced objects", 1802 | "homepage": "https://github.com/sebastianbergmann/object-enumerator/", 1803 | "support": { 1804 | "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", 1805 | "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" 1806 | }, 1807 | "funding": [ 1808 | { 1809 | "url": "https://github.com/sebastianbergmann", 1810 | "type": "github" 1811 | } 1812 | ], 1813 | "time": "2020-10-26T13:12:34+00:00" 1814 | }, 1815 | { 1816 | "name": "sebastian/object-reflector", 1817 | "version": "2.0.4", 1818 | "source": { 1819 | "type": "git", 1820 | "url": "https://github.com/sebastianbergmann/object-reflector.git", 1821 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" 1822 | }, 1823 | "dist": { 1824 | "type": "zip", 1825 | "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", 1826 | "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", 1827 | "shasum": "" 1828 | }, 1829 | "require": { 1830 | "php": ">=7.3" 1831 | }, 1832 | "require-dev": { 1833 | "phpunit/phpunit": "^9.3" 1834 | }, 1835 | "type": "library", 1836 | "extra": { 1837 | "branch-alias": { 1838 | "dev-master": "2.0-dev" 1839 | } 1840 | }, 1841 | "autoload": { 1842 | "classmap": [ 1843 | "src/" 1844 | ] 1845 | }, 1846 | "notification-url": "https://packagist.org/downloads/", 1847 | "license": [ 1848 | "BSD-3-Clause" 1849 | ], 1850 | "authors": [ 1851 | { 1852 | "name": "Sebastian Bergmann", 1853 | "email": "sebastian@phpunit.de" 1854 | } 1855 | ], 1856 | "description": "Allows reflection of object attributes, including inherited and non-public ones", 1857 | "homepage": "https://github.com/sebastianbergmann/object-reflector/", 1858 | "support": { 1859 | "issues": "https://github.com/sebastianbergmann/object-reflector/issues", 1860 | "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" 1861 | }, 1862 | "funding": [ 1863 | { 1864 | "url": "https://github.com/sebastianbergmann", 1865 | "type": "github" 1866 | } 1867 | ], 1868 | "time": "2020-10-26T13:14:26+00:00" 1869 | }, 1870 | { 1871 | "name": "sebastian/recursion-context", 1872 | "version": "4.0.5", 1873 | "source": { 1874 | "type": "git", 1875 | "url": "https://github.com/sebastianbergmann/recursion-context.git", 1876 | "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1" 1877 | }, 1878 | "dist": { 1879 | "type": "zip", 1880 | "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", 1881 | "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1", 1882 | "shasum": "" 1883 | }, 1884 | "require": { 1885 | "php": ">=7.3" 1886 | }, 1887 | "require-dev": { 1888 | "phpunit/phpunit": "^9.3" 1889 | }, 1890 | "type": "library", 1891 | "extra": { 1892 | "branch-alias": { 1893 | "dev-master": "4.0-dev" 1894 | } 1895 | }, 1896 | "autoload": { 1897 | "classmap": [ 1898 | "src/" 1899 | ] 1900 | }, 1901 | "notification-url": "https://packagist.org/downloads/", 1902 | "license": [ 1903 | "BSD-3-Clause" 1904 | ], 1905 | "authors": [ 1906 | { 1907 | "name": "Sebastian Bergmann", 1908 | "email": "sebastian@phpunit.de" 1909 | }, 1910 | { 1911 | "name": "Jeff Welch", 1912 | "email": "whatthejeff@gmail.com" 1913 | }, 1914 | { 1915 | "name": "Adam Harvey", 1916 | "email": "aharvey@php.net" 1917 | } 1918 | ], 1919 | "description": "Provides functionality to recursively process PHP variables", 1920 | "homepage": "https://github.com/sebastianbergmann/recursion-context", 1921 | "support": { 1922 | "issues": "https://github.com/sebastianbergmann/recursion-context/issues", 1923 | "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5" 1924 | }, 1925 | "funding": [ 1926 | { 1927 | "url": "https://github.com/sebastianbergmann", 1928 | "type": "github" 1929 | } 1930 | ], 1931 | "time": "2023-02-03T06:07:39+00:00" 1932 | }, 1933 | { 1934 | "name": "sebastian/resource-operations", 1935 | "version": "3.0.4", 1936 | "source": { 1937 | "type": "git", 1938 | "url": "https://github.com/sebastianbergmann/resource-operations.git", 1939 | "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" 1940 | }, 1941 | "dist": { 1942 | "type": "zip", 1943 | "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", 1944 | "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", 1945 | "shasum": "" 1946 | }, 1947 | "require": { 1948 | "php": ">=7.3" 1949 | }, 1950 | "require-dev": { 1951 | "phpunit/phpunit": "^9.0" 1952 | }, 1953 | "type": "library", 1954 | "extra": { 1955 | "branch-alias": { 1956 | "dev-main": "3.0-dev" 1957 | } 1958 | }, 1959 | "autoload": { 1960 | "classmap": [ 1961 | "src/" 1962 | ] 1963 | }, 1964 | "notification-url": "https://packagist.org/downloads/", 1965 | "license": [ 1966 | "BSD-3-Clause" 1967 | ], 1968 | "authors": [ 1969 | { 1970 | "name": "Sebastian Bergmann", 1971 | "email": "sebastian@phpunit.de" 1972 | } 1973 | ], 1974 | "description": "Provides a list of PHP built-in functions that operate on resources", 1975 | "homepage": "https://www.github.com/sebastianbergmann/resource-operations", 1976 | "support": { 1977 | "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" 1978 | }, 1979 | "funding": [ 1980 | { 1981 | "url": "https://github.com/sebastianbergmann", 1982 | "type": "github" 1983 | } 1984 | ], 1985 | "time": "2024-03-14T16:00:52+00:00" 1986 | }, 1987 | { 1988 | "name": "sebastian/type", 1989 | "version": "3.2.1", 1990 | "source": { 1991 | "type": "git", 1992 | "url": "https://github.com/sebastianbergmann/type.git", 1993 | "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" 1994 | }, 1995 | "dist": { 1996 | "type": "zip", 1997 | "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", 1998 | "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", 1999 | "shasum": "" 2000 | }, 2001 | "require": { 2002 | "php": ">=7.3" 2003 | }, 2004 | "require-dev": { 2005 | "phpunit/phpunit": "^9.5" 2006 | }, 2007 | "type": "library", 2008 | "extra": { 2009 | "branch-alias": { 2010 | "dev-master": "3.2-dev" 2011 | } 2012 | }, 2013 | "autoload": { 2014 | "classmap": [ 2015 | "src/" 2016 | ] 2017 | }, 2018 | "notification-url": "https://packagist.org/downloads/", 2019 | "license": [ 2020 | "BSD-3-Clause" 2021 | ], 2022 | "authors": [ 2023 | { 2024 | "name": "Sebastian Bergmann", 2025 | "email": "sebastian@phpunit.de", 2026 | "role": "lead" 2027 | } 2028 | ], 2029 | "description": "Collection of value objects that represent the types of the PHP type system", 2030 | "homepage": "https://github.com/sebastianbergmann/type", 2031 | "support": { 2032 | "issues": "https://github.com/sebastianbergmann/type/issues", 2033 | "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" 2034 | }, 2035 | "funding": [ 2036 | { 2037 | "url": "https://github.com/sebastianbergmann", 2038 | "type": "github" 2039 | } 2040 | ], 2041 | "time": "2023-02-03T06:13:03+00:00" 2042 | }, 2043 | { 2044 | "name": "sebastian/version", 2045 | "version": "3.0.2", 2046 | "source": { 2047 | "type": "git", 2048 | "url": "https://github.com/sebastianbergmann/version.git", 2049 | "reference": "c6c1022351a901512170118436c764e473f6de8c" 2050 | }, 2051 | "dist": { 2052 | "type": "zip", 2053 | "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", 2054 | "reference": "c6c1022351a901512170118436c764e473f6de8c", 2055 | "shasum": "" 2056 | }, 2057 | "require": { 2058 | "php": ">=7.3" 2059 | }, 2060 | "type": "library", 2061 | "extra": { 2062 | "branch-alias": { 2063 | "dev-master": "3.0-dev" 2064 | } 2065 | }, 2066 | "autoload": { 2067 | "classmap": [ 2068 | "src/" 2069 | ] 2070 | }, 2071 | "notification-url": "https://packagist.org/downloads/", 2072 | "license": [ 2073 | "BSD-3-Clause" 2074 | ], 2075 | "authors": [ 2076 | { 2077 | "name": "Sebastian Bergmann", 2078 | "email": "sebastian@phpunit.de", 2079 | "role": "lead" 2080 | } 2081 | ], 2082 | "description": "Library that helps with managing the version number of Git-hosted PHP projects", 2083 | "homepage": "https://github.com/sebastianbergmann/version", 2084 | "support": { 2085 | "issues": "https://github.com/sebastianbergmann/version/issues", 2086 | "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" 2087 | }, 2088 | "funding": [ 2089 | { 2090 | "url": "https://github.com/sebastianbergmann", 2091 | "type": "github" 2092 | } 2093 | ], 2094 | "time": "2020-09-28T06:39:44+00:00" 2095 | }, 2096 | { 2097 | "name": "squizlabs/php_codesniffer", 2098 | "version": "3.10.1", 2099 | "source": { 2100 | "type": "git", 2101 | "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", 2102 | "reference": "8f90f7a53ce271935282967f53d0894f8f1ff877" 2103 | }, 2104 | "dist": { 2105 | "type": "zip", 2106 | "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/8f90f7a53ce271935282967f53d0894f8f1ff877", 2107 | "reference": "8f90f7a53ce271935282967f53d0894f8f1ff877", 2108 | "shasum": "" 2109 | }, 2110 | "require": { 2111 | "ext-simplexml": "*", 2112 | "ext-tokenizer": "*", 2113 | "ext-xmlwriter": "*", 2114 | "php": ">=5.4.0" 2115 | }, 2116 | "require-dev": { 2117 | "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" 2118 | }, 2119 | "bin": [ 2120 | "bin/phpcbf", 2121 | "bin/phpcs" 2122 | ], 2123 | "type": "library", 2124 | "extra": { 2125 | "branch-alias": { 2126 | "dev-master": "3.x-dev" 2127 | } 2128 | }, 2129 | "notification-url": "https://packagist.org/downloads/", 2130 | "license": [ 2131 | "BSD-3-Clause" 2132 | ], 2133 | "authors": [ 2134 | { 2135 | "name": "Greg Sherwood", 2136 | "role": "Former lead" 2137 | }, 2138 | { 2139 | "name": "Juliette Reinders Folmer", 2140 | "role": "Current lead" 2141 | }, 2142 | { 2143 | "name": "Contributors", 2144 | "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" 2145 | } 2146 | ], 2147 | "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", 2148 | "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", 2149 | "keywords": [ 2150 | "phpcs", 2151 | "standards", 2152 | "static analysis" 2153 | ], 2154 | "support": { 2155 | "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", 2156 | "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", 2157 | "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", 2158 | "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" 2159 | }, 2160 | "funding": [ 2161 | { 2162 | "url": "https://github.com/PHPCSStandards", 2163 | "type": "github" 2164 | }, 2165 | { 2166 | "url": "https://github.com/jrfnl", 2167 | "type": "github" 2168 | }, 2169 | { 2170 | "url": "https://opencollective.com/php_codesniffer", 2171 | "type": "open_collective" 2172 | } 2173 | ], 2174 | "time": "2024-05-22T21:24:41+00:00" 2175 | }, 2176 | { 2177 | "name": "symfony/polyfill-mbstring", 2178 | "version": "v1.30.0", 2179 | "source": { 2180 | "type": "git", 2181 | "url": "https://github.com/symfony/polyfill-mbstring.git", 2182 | "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c" 2183 | }, 2184 | "dist": { 2185 | "type": "zip", 2186 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fd22ab50000ef01661e2a31d850ebaa297f8e03c", 2187 | "reference": "fd22ab50000ef01661e2a31d850ebaa297f8e03c", 2188 | "shasum": "" 2189 | }, 2190 | "require": { 2191 | "php": ">=7.1" 2192 | }, 2193 | "provide": { 2194 | "ext-mbstring": "*" 2195 | }, 2196 | "suggest": { 2197 | "ext-mbstring": "For best performance" 2198 | }, 2199 | "type": "library", 2200 | "extra": { 2201 | "thanks": { 2202 | "name": "symfony/polyfill", 2203 | "url": "https://github.com/symfony/polyfill" 2204 | } 2205 | }, 2206 | "autoload": { 2207 | "files": [ 2208 | "bootstrap.php" 2209 | ], 2210 | "psr-4": { 2211 | "Symfony\\Polyfill\\Mbstring\\": "" 2212 | } 2213 | }, 2214 | "notification-url": "https://packagist.org/downloads/", 2215 | "license": [ 2216 | "MIT" 2217 | ], 2218 | "authors": [ 2219 | { 2220 | "name": "Nicolas Grekas", 2221 | "email": "p@tchwork.com" 2222 | }, 2223 | { 2224 | "name": "Symfony Community", 2225 | "homepage": "https://symfony.com/contributors" 2226 | } 2227 | ], 2228 | "description": "Symfony polyfill for the Mbstring extension", 2229 | "homepage": "https://symfony.com", 2230 | "keywords": [ 2231 | "compatibility", 2232 | "mbstring", 2233 | "polyfill", 2234 | "portable", 2235 | "shim" 2236 | ], 2237 | "support": { 2238 | "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.30.0" 2239 | }, 2240 | "funding": [ 2241 | { 2242 | "url": "https://symfony.com/sponsor", 2243 | "type": "custom" 2244 | }, 2245 | { 2246 | "url": "https://github.com/fabpot", 2247 | "type": "github" 2248 | }, 2249 | { 2250 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2251 | "type": "tidelift" 2252 | } 2253 | ], 2254 | "time": "2024-06-19T12:30:46+00:00" 2255 | }, 2256 | { 2257 | "name": "symfony/process", 2258 | "version": "v7.1.1", 2259 | "source": { 2260 | "type": "git", 2261 | "url": "https://github.com/symfony/process.git", 2262 | "reference": "febf90124323a093c7ee06fdb30e765ca3c20028" 2263 | }, 2264 | "dist": { 2265 | "type": "zip", 2266 | "url": "https://api.github.com/repos/symfony/process/zipball/febf90124323a093c7ee06fdb30e765ca3c20028", 2267 | "reference": "febf90124323a093c7ee06fdb30e765ca3c20028", 2268 | "shasum": "" 2269 | }, 2270 | "require": { 2271 | "php": ">=8.2" 2272 | }, 2273 | "type": "library", 2274 | "autoload": { 2275 | "psr-4": { 2276 | "Symfony\\Component\\Process\\": "" 2277 | }, 2278 | "exclude-from-classmap": [ 2279 | "/Tests/" 2280 | ] 2281 | }, 2282 | "notification-url": "https://packagist.org/downloads/", 2283 | "license": [ 2284 | "MIT" 2285 | ], 2286 | "authors": [ 2287 | { 2288 | "name": "Fabien Potencier", 2289 | "email": "fabien@symfony.com" 2290 | }, 2291 | { 2292 | "name": "Symfony Community", 2293 | "homepage": "https://symfony.com/contributors" 2294 | } 2295 | ], 2296 | "description": "Executes commands in sub-processes", 2297 | "homepage": "https://symfony.com", 2298 | "support": { 2299 | "source": "https://github.com/symfony/process/tree/v7.1.1" 2300 | }, 2301 | "funding": [ 2302 | { 2303 | "url": "https://symfony.com/sponsor", 2304 | "type": "custom" 2305 | }, 2306 | { 2307 | "url": "https://github.com/fabpot", 2308 | "type": "github" 2309 | }, 2310 | { 2311 | "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", 2312 | "type": "tidelift" 2313 | } 2314 | ], 2315 | "time": "2024-05-31T14:57:53+00:00" 2316 | }, 2317 | { 2318 | "name": "theseer/tokenizer", 2319 | "version": "1.2.3", 2320 | "source": { 2321 | "type": "git", 2322 | "url": "https://github.com/theseer/tokenizer.git", 2323 | "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2" 2324 | }, 2325 | "dist": { 2326 | "type": "zip", 2327 | "url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", 2328 | "reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2", 2329 | "shasum": "" 2330 | }, 2331 | "require": { 2332 | "ext-dom": "*", 2333 | "ext-tokenizer": "*", 2334 | "ext-xmlwriter": "*", 2335 | "php": "^7.2 || ^8.0" 2336 | }, 2337 | "type": "library", 2338 | "autoload": { 2339 | "classmap": [ 2340 | "src/" 2341 | ] 2342 | }, 2343 | "notification-url": "https://packagist.org/downloads/", 2344 | "license": [ 2345 | "BSD-3-Clause" 2346 | ], 2347 | "authors": [ 2348 | { 2349 | "name": "Arne Blankerts", 2350 | "email": "arne@blankerts.de", 2351 | "role": "Developer" 2352 | } 2353 | ], 2354 | "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", 2355 | "support": { 2356 | "issues": "https://github.com/theseer/tokenizer/issues", 2357 | "source": "https://github.com/theseer/tokenizer/tree/1.2.3" 2358 | }, 2359 | "funding": [ 2360 | { 2361 | "url": "https://github.com/theseer", 2362 | "type": "github" 2363 | } 2364 | ], 2365 | "time": "2024-03-03T12:36:25+00:00" 2366 | }, 2367 | { 2368 | "name": "woocommerce/woocommerce-sniffs", 2369 | "version": "0.1.3", 2370 | "source": { 2371 | "type": "git", 2372 | "url": "https://github.com/woocommerce/woocommerce-sniffs.git", 2373 | "reference": "4576d54595614d689bc4436acff8baaece3c5bb0" 2374 | }, 2375 | "dist": { 2376 | "type": "zip", 2377 | "url": "https://api.github.com/repos/woocommerce/woocommerce-sniffs/zipball/4576d54595614d689bc4436acff8baaece3c5bb0", 2378 | "reference": "4576d54595614d689bc4436acff8baaece3c5bb0", 2379 | "shasum": "" 2380 | }, 2381 | "require": { 2382 | "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", 2383 | "php": ">=7.0", 2384 | "phpcompatibility/phpcompatibility-wp": "^2.1.0", 2385 | "wp-coding-standards/wpcs": "^2.3.0" 2386 | }, 2387 | "type": "phpcodesniffer-standard", 2388 | "notification-url": "https://packagist.org/downloads/", 2389 | "license": [ 2390 | "MIT" 2391 | ], 2392 | "authors": [ 2393 | { 2394 | "name": "Claudio Sanches", 2395 | "email": "claudio@automattic.com" 2396 | } 2397 | ], 2398 | "description": "WooCommerce sniffs", 2399 | "keywords": [ 2400 | "phpcs", 2401 | "standards", 2402 | "woocommerce", 2403 | "wordpress" 2404 | ], 2405 | "support": { 2406 | "issues": "https://github.com/woocommerce/woocommerce-sniffs/issues", 2407 | "source": "https://github.com/woocommerce/woocommerce-sniffs/tree/0.1.3" 2408 | }, 2409 | "time": "2022-02-17T15:34:51+00:00" 2410 | }, 2411 | { 2412 | "name": "wp-coding-standards/wpcs", 2413 | "version": "2.3.0", 2414 | "source": { 2415 | "type": "git", 2416 | "url": "https://github.com/WordPress/WordPress-Coding-Standards.git", 2417 | "reference": "7da1894633f168fe244afc6de00d141f27517b62" 2418 | }, 2419 | "dist": { 2420 | "type": "zip", 2421 | "url": "https://api.github.com/repos/WordPress/WordPress-Coding-Standards/zipball/7da1894633f168fe244afc6de00d141f27517b62", 2422 | "reference": "7da1894633f168fe244afc6de00d141f27517b62", 2423 | "shasum": "" 2424 | }, 2425 | "require": { 2426 | "php": ">=5.4", 2427 | "squizlabs/php_codesniffer": "^3.3.1" 2428 | }, 2429 | "require-dev": { 2430 | "dealerdirect/phpcodesniffer-composer-installer": "^0.5 || ^0.6", 2431 | "phpcompatibility/php-compatibility": "^9.0", 2432 | "phpcsstandards/phpcsdevtools": "^1.0", 2433 | "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0" 2434 | }, 2435 | "suggest": { 2436 | "dealerdirect/phpcodesniffer-composer-installer": "^0.6 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically." 2437 | }, 2438 | "type": "phpcodesniffer-standard", 2439 | "notification-url": "https://packagist.org/downloads/", 2440 | "license": [ 2441 | "MIT" 2442 | ], 2443 | "authors": [ 2444 | { 2445 | "name": "Contributors", 2446 | "homepage": "https://github.com/WordPress/WordPress-Coding-Standards/graphs/contributors" 2447 | } 2448 | ], 2449 | "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress coding conventions", 2450 | "keywords": [ 2451 | "phpcs", 2452 | "standards", 2453 | "wordpress" 2454 | ], 2455 | "support": { 2456 | "issues": "https://github.com/WordPress/WordPress-Coding-Standards/issues", 2457 | "source": "https://github.com/WordPress/WordPress-Coding-Standards", 2458 | "wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki" 2459 | }, 2460 | "time": "2020-05-13T23:57:56+00:00" 2461 | } 2462 | ], 2463 | "aliases": [], 2464 | "minimum-stability": "stable", 2465 | "stability-flags": [], 2466 | "prefer-stable": false, 2467 | "prefer-lowest": false, 2468 | "platform": [], 2469 | "platform-dev": [], 2470 | "plugin-api-version": "2.6.0" 2471 | } 2472 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tawk-wordpress", 3 | "version": "0.9.2", 4 | "description": "tawk.to wordpress plugin", 5 | "main": "index.js", 6 | "directories": { 7 | "test": "tests" 8 | }, 9 | "scripts": { 10 | "lint": "npm run eslint && npm run stylelint", 11 | "eslint": "eslint ./tawkto/**/*.js", 12 | "stylelint": "stylelint ./tawkto/**/*.css" 13 | }, 14 | "author": "tawk.to", 15 | "license": "GPL-3.0", 16 | "devDependencies": { 17 | "@wordpress/stylelint-config": "^19.1.0", 18 | "eslint": "^8.4.1", 19 | "eslint-config-wordpress": "^2.0.0", 20 | "grunt": "^1.4.1", 21 | "grunt-eslint": "^24.0.0", 22 | "grunt-phpcs": "^0.4.0", 23 | "grunt-stylelint": "^0.17.0", 24 | "husky": "^4.3.8", 25 | "lint-staged": "^12.1.2", 26 | "stylelint": "^13.13.1" 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /tawkto/assets/css/tawk.admin.css: -------------------------------------------------------------------------------- 1 | /** 2 | * #.# Header section 3 | * 4 | * Styles in the header section of the settings panel 5 | */ 6 | #tawk-header { 7 | background-color: #fff; 8 | overflow: hidden; 9 | width: 95%; 10 | margin-top: 20px; 11 | padding: 6px 12px 0; 12 | border-style: solid; 13 | border-color: #ccc; 14 | border-width: 1px 1px 0 1px; 15 | font-size: 2em; 16 | } 17 | 18 | div.tawk-mel { 19 | float: left; 20 | min-width: 75px; 21 | min-height: 80px; 22 | width: 10%; 23 | text-align: center; 24 | } 25 | 26 | div.tawk-header-text { 27 | float: left; 28 | line-height: 86px; 29 | } 30 | 31 | /** 32 | * #.# Form Action 33 | * 34 | * Styles for the form action button 35 | */ 36 | .tawk-action { 37 | background-color: #fff; 38 | overflow: hidden; 39 | width: 95%; 40 | padding: 6px 12px; 41 | border: 1px solid #ccc; 42 | } 43 | 44 | .tawk-action p { 45 | margin: 0; 46 | padding: 0; 47 | } 48 | 49 | div.tawk-footer-action { 50 | width: 10%; 51 | min-width: 75px; 52 | float: left; 53 | } 54 | 55 | div.tawk-footer-text { 56 | float: right; 57 | text-align: right; 58 | } 59 | 60 | /** 61 | * #.# Settings Body 62 | * 63 | * Styles for the settings panel body container 64 | */ 65 | #tawk-settings-body { 66 | background-color: #fff; 67 | overflow: hidden; 68 | width: 95%; 69 | padding: 0 24px 0 0; 70 | border-style: solid; 71 | border-color: #ccc; 72 | border-width: 0 1px 0 1px; 73 | } 74 | 75 | /** 76 | * #.# Tabs 77 | * 78 | * Styles for the tabs section in the settings panel 79 | */ 80 | #tawk-tabs { 81 | background-color: #fff; 82 | overflow: hidden; 83 | float: left; 84 | min-width: 75px; 85 | width: 10%; 86 | } 87 | 88 | #tawk-tabs button { 89 | background-color: inherit; 90 | float: left; 91 | width: 100%; 92 | border: none; 93 | padding: 14px 0; 94 | outline: none; 95 | cursor: pointer; 96 | transition: 0.3s; 97 | } 98 | 99 | #tawk-tabs button:hover { 100 | background-color: #ddd; 101 | color: #0085ba; 102 | } 103 | 104 | #tawk-tabs button.active { 105 | background-color: #f1f1f1; 106 | } 107 | 108 | /** 109 | * #.# Tab Content 110 | * 111 | * Styles for the tab content of the settings panel 112 | */ 113 | .tawk-tab-content { 114 | background-color: #fff; 115 | display: none; 116 | float: left; 117 | min-width: 240px; 118 | width: 85%; 119 | padding: 6px 12px; 120 | border-style: solid; 121 | border-color: #ccc; 122 | border-width: 0 0 0 1px; 123 | border-top: none; 124 | } 125 | 126 | #tawk-iframe { 127 | min-height: 295px; 128 | width: 100%; 129 | margin-top: 20px; 130 | border: none; 131 | } 132 | 133 | .tawk-notice { 134 | font-size: 14px; 135 | max-width: 578px; 136 | } 137 | 138 | .form-table th.tawk-setting { 139 | width: 350px; 140 | } 141 | 142 | #exlucded-urls-container, 143 | #included-urls-container { 144 | padding: 15px; 145 | } 146 | 147 | #visibility-content { 148 | display: flex; 149 | justify-content: space-between; 150 | flex-wrap: wrap; 151 | } 152 | 153 | #visibility-content #visibility-info { 154 | max-width: 250px; 155 | } 156 | 157 | .list-type-bullet { 158 | list-style: circle; 159 | padding: 0 20px; 160 | } 161 | 162 | /** 163 | * #.# Switch and Slider 164 | * 165 | * Styles for the switch/toggle/slider in the settings panel 166 | */ 167 | .switch { 168 | display: inline-block; 169 | height: 34px; 170 | width: 60px; 171 | position: relative; 172 | } 173 | 174 | .switch input { 175 | display: none; 176 | } 177 | 178 | .slider { 179 | background-color: #ccc; 180 | position: absolute; 181 | top: 0; 182 | left: 0; 183 | right: 0; 184 | bottom: 0; 185 | -webkit-transition: 0.4s; 186 | transition: 0.4s; 187 | cursor: pointer; 188 | } 189 | 190 | .slider::before { 191 | background-color: #fff; 192 | height: 26px; 193 | width: 26px; 194 | position: absolute; 195 | left: 4px; 196 | bottom: 4px; 197 | -webkit-transition: 0.4s; 198 | transition: 0.4s; 199 | content: ""; 200 | } 201 | 202 | .slider.round { 203 | border-radius: 34px; 204 | } 205 | 206 | .slider.round::before { 207 | border-radius: 50%; 208 | } 209 | 210 | input:checked + .slider { 211 | background-color: #2196f3; 212 | } 213 | 214 | input:focus + .slider { 215 | box-shadow: 0 0 1px #2196f3; 216 | } 217 | 218 | input:checked + .slider::before { 219 | -webkit-transform: translateX(26px); 220 | -ms-transform: translateX(26px); 221 | transform: translateX(26px); 222 | } 223 | 224 | /** 225 | * #.# Links 226 | * 227 | * Styles for links 228 | */ 229 | a.tawk-link { 230 | color: #7fb06f; 231 | text-decoration: none; 232 | } 233 | 234 | a.tawk-link:hover { 235 | text-decoration: underline; 236 | } 237 | 238 | /** 239 | * #.# Tooltip 240 | * 241 | * Styles for tooltip 242 | */ 243 | .tooltip { 244 | position: relative; 245 | display: inline; 246 | color: #03a84e; 247 | } 248 | 249 | .tooltip .tooltiptext { 250 | visibility: hidden; 251 | background-color: #545454; 252 | color: #fff; 253 | text-align: center; 254 | padding: 0.5rem; 255 | max-width: 300px; 256 | border-radius: 0.5rem; 257 | font-size: 0.7rem; 258 | font-weight: 600; 259 | line-height: 0.8; 260 | 261 | /* Position the tooltip text - see examples below! */ 262 | position: absolute; 263 | z-index: 1000; 264 | top: 5px; 265 | } 266 | 267 | .tooltip.reverse .tooltiptext { 268 | top: unset; 269 | bottom: 5px; 270 | } 271 | 272 | .tooltip .tooltiptext::before { 273 | content: ""; 274 | display: block; 275 | width: 0; 276 | height: 0; 277 | position: absolute; 278 | 279 | border-left: 5px solid transparent; 280 | border-right: 5px solid transparent; 281 | border-bottom: 5px solid #545454; 282 | top: -5px; 283 | left: 5px; 284 | } 285 | 286 | .tooltip.reverse .tooltiptext::before { 287 | top: unset; 288 | border-bottom: unset; 289 | bottom: -5px; 290 | border-top: 5px solid #545454; 291 | } 292 | 293 | .tooltip:hover .tooltiptext { 294 | visibility: visible; 295 | } 296 | 297 | /** 298 | * #.# Media Queries 299 | * 300 | * Mobile view 301 | */ 302 | 303 | @media only screen and (max-width: 712px) { 304 | 305 | /** 306 | * #.# Settings Body 307 | * 308 | * Styles for the settings panel body container 309 | */ 310 | #tawk-settings-body { 311 | max-width: 712px; 312 | width: 100%; 313 | padding: 0 0 0 0; 314 | } 315 | 316 | /** 317 | * #.# Tabs 318 | * 319 | * Styles for the tabs section in the settings panel 320 | */ 321 | #tawk-tabs { 322 | background-color: #fff; 323 | min-width: 75px; 324 | width: 100%; 325 | border-bottom: 1px solid #ccc; 326 | } 327 | } 328 | -------------------------------------------------------------------------------- /tawkto/assets/js/tawk.admin.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | jQuery( 4 | function() { 5 | document.getElementById( 'account-settings-tab' ).click(); 6 | 7 | if ( jQuery( '#always-display' ).prop( 'checked' ) ) { 8 | jQuery( '.tawk-selected-display' ).hide(); 9 | jQuery( '#show-onfrontpage' ).prop( 'disabled', true ); 10 | jQuery( '#show-oncategory' ).prop( 'disabled', true ); 11 | jQuery( '#show-ontagpage' ).prop( 'disabled', true ); 12 | jQuery( '#show-onarticlepages' ).prop( 'disabled', true ); 13 | jQuery( '#include-url' ).prop( 'disabled', true ); 14 | } else { 15 | jQuery( '.tawk-selected-display' ).show(); 16 | } 17 | 18 | jQuery( '#always-display' ).change( 19 | function() { 20 | if ( this.checked ) { 21 | jQuery( '.tawk-selected-display' ).fadeOut(); 22 | jQuery( '#show-onfrontpage' ).prop( 'disabled', true ); 23 | jQuery( '#show-oncategory' ).prop( 'disabled', true ); 24 | jQuery( '#show-ontagpage' ).prop( 'disabled', true ); 25 | jQuery( '#show-onarticlepages' ).prop( 'disabled', true ); 26 | jQuery( '#include-url' ).prop( 'disabled', true ); 27 | } else { 28 | jQuery( '.tawk-selected-display' ).fadeIn(); 29 | jQuery( '#show-onfrontpage' ).prop( 'disabled', false ); 30 | jQuery( '#show-oncategory' ).prop( 'disabled', false ); 31 | jQuery( '#show-ontagpage' ).prop( 'disabled', false ); 32 | jQuery( '#show-onarticlepages' ).prop( 'disabled', false ); 33 | jQuery( '#include-url' ).prop( 'disabled', false ); 34 | } 35 | } 36 | ); 37 | 38 | jQuery( '#exclude-url' ).change( 39 | function() { 40 | if ( this.checked ) { 41 | jQuery( '#exlucded-urls-container' ).fadeIn(); 42 | } else { 43 | jQuery( '#exlucded-urls-container' ).fadeOut(); 44 | } 45 | } 46 | ); 47 | 48 | if ( jQuery( '#include-url' ).prop( 'checked' ) ) { 49 | jQuery( '#included-urls-container' ).show(); 50 | } 51 | 52 | jQuery( '#include-url' ).change( 53 | function() { 54 | if ( this.checked ) { 55 | jQuery( '#included-urls-container' ).fadeIn(); 56 | } else { 57 | jQuery( '#included-urls-container' ).fadeOut(); 58 | } 59 | } 60 | ); 61 | 62 | if ( jQuery( '#exclude-url' ).prop( 'checked' ) ) { 63 | jQuery( '#exlucded-urls-container' ).fadeIn(); 64 | } 65 | 66 | jQuery( '.tooltip' ).on( 'mouseenter', function() { 67 | var tooltipTextHeight = jQuery( this ).find( '.tooltiptext' ).height(); 68 | if ( jQuery( '#url-exclusion' ).height() > tooltipTextHeight ) { 69 | jQuery( this ).removeClass( 'reverse' ); 70 | return; 71 | } 72 | 73 | jQuery( this ).addClass( 'reverse' ); 74 | }); 75 | 76 | if ( jQuery( '#enable-visitor-recognition' ).prop( 'checked' ) ) { 77 | jQuery( '.tawk-selected-visitor' ).show(); 78 | jQuery( '#js-api-key' ).prop( 'disabled', false ); 79 | } else { 80 | jQuery( '.tawk-selected-visitor' ).hide(); 81 | jQuery( '#js-api-key' ).prop( 'disabled', true ); 82 | } 83 | 84 | jQuery( '#enable-visitor-recognition' ).change( 85 | function() { 86 | if ( this.checked ) { 87 | jQuery( '.tawk-selected-visitor' ).fadeIn(); 88 | jQuery( '#js-api-key' ).prop( 'disabled', false ); 89 | } else { 90 | jQuery( '.tawk-selected-visitor' ).fadeOut(); 91 | jQuery( '#js-api-key' ).prop( 'disabled', true ); 92 | } 93 | } 94 | ); 95 | } 96 | ); 97 | 98 | function opentab( evt, tabName ) { 99 | var i, tabcontent, tablinks; 100 | 101 | tabcontent = document.getElementsByClassName( 'tawk-tab-content' ); 102 | for ( i = 0; i < tabcontent.length; i++ ) { 103 | tabcontent[i].style.display = 'none'; 104 | } 105 | 106 | tablinks = document.getElementsByClassName( 'tawk-tab-links' ); 107 | for ( i = 0; i < tablinks.length; i++ ) { 108 | tablinks[i].className = tablinks[i].className.replace( ' active', '' ); 109 | } 110 | 111 | document.getElementById( tabName ).style.display = 'block'; 112 | 113 | evt.currentTarget.className += ' active'; 114 | } 115 | -------------------------------------------------------------------------------- /tawkto/assets/js/tawk.selection.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var currentHost = window.location.protocol + '//' + window.location.host; 4 | var iframeUrl = tawkSelectionData.url.iframe + '&parentDomain=' + currentHost; 5 | var baseUrl = tawkSelectionData.url.base; 6 | 7 | jQuery( '#tawk-iframe' ).attr( 'src', iframeUrl ); 8 | 9 | window.addEventListener( 10 | 'message', 11 | function( e ) { 12 | if ( baseUrl === e.origin ) { 13 | 14 | if ( 'setWidget' === e.data.action ) { 15 | setWidget( e ); 16 | } 17 | 18 | if ( 'removeWidget' === e.data.action ) { 19 | removeWidget( e ); 20 | } 21 | 22 | if ( 'reloadHeight' === e.data.action ) { 23 | reloadIframeHeight( e.data.height ); 24 | } 25 | } 26 | } 27 | ); 28 | 29 | function setWidget( e ) { 30 | var data = { 31 | pageId: e.data.pageId, 32 | widgetId: e.data.widgetId, 33 | nonce: tawkSelectionData.nonce.setWidget 34 | }; 35 | 36 | jQuery.ajax( 37 | { 38 | type: 'POST', 39 | url: ajaxurl + '?action=tawkto_setwidget', 40 | contentType: 'application/json', 41 | dataType: 'json', 42 | data: JSON.stringify( data ), 43 | success: function( r ) { 44 | if ( ! r.success ) { 45 | return e.source.postMessage({ action: 'setFail' }, baseUrl ); 46 | } 47 | e.source.postMessage({ action: 'setDone' }, baseUrl ); 48 | }, 49 | error: function() { 50 | e.source.postMessage({ action: 'setFail' }, baseUrl ); 51 | } 52 | } 53 | ); 54 | } 55 | 56 | function removeWidget( e ) { 57 | var data = { 58 | nonce: tawkSelectionData.nonce.removeWidget 59 | }; 60 | 61 | jQuery.ajax( 62 | { 63 | type: 'POST', 64 | url: ajaxurl + '?action=tawkto_removewidget', 65 | contentType: 'application/json', 66 | dataType: 'json', 67 | data: JSON.stringify( data ), 68 | success: function( r ) { 69 | if ( ! r.success ) { 70 | return e.source.postMessage({ action: 'removeFail' }, baseUrl ); 71 | } 72 | e.source.postMessage({ action: 'removeDone' }, baseUrl ); 73 | }, 74 | error: function() { 75 | e.source.postMessage({ action: 'removeFail' }, baseUrl ); 76 | } 77 | } 78 | ); 79 | } 80 | 81 | function reloadIframeHeight( height ) { 82 | var iframe = jQuery( '#tawk-iframe' ); 83 | 84 | if ( ! height ) { 85 | return; 86 | } 87 | if ( height === iframe.height() ) { 88 | return; 89 | } 90 | 91 | iframe.height( height ); 92 | } 93 | -------------------------------------------------------------------------------- /tawkto/assets/tawky_big.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tawk/tawk-wordpress/d612385fc5a3eb5a1bbbc362e845716c2137986a/tawkto/assets/tawky_big.png -------------------------------------------------------------------------------- /tawkto/includes/default_config.php: -------------------------------------------------------------------------------- 1 | array( 5 | 'always_display' => 1, 6 | 'show_onfrontpage' => 0, 7 | 'show_oncategory' => 0, 8 | 'show_ontagpage' => 0, 9 | 'show_onarticlepages' => 0, 10 | 'exclude_url' => 0, 11 | 'excluded_url_list' => '', 12 | 'include_url' => 0, 13 | 'included_url_list' => '', 14 | 'display_on_shop' => 0, 15 | 'display_on_productcategory' => 0, 16 | 'display_on_productpage' => 0, 17 | 'display_on_producttag' => 0, 18 | ), 19 | 'privacy' => array( 20 | 'enable_visitor_recognition' => 1, 21 | ), 22 | 'security' => array( 23 | 'js_api_key' => '', 24 | ), 25 | ); 26 | -------------------------------------------------------------------------------- /tawkto/index.php: -------------------------------------------------------------------------------- 1 | = 5.6. 116 | 117 | = 0.7.0 = 118 | * Enhanced URL pattern matching. 119 | * Supported version bump 5.9. 120 | 121 | = 0.6.0 = 122 | * **Security Update** Add CSRF tokens and specific action access checks. 123 | * **Security Update** Use `application/json` content type for ajax requests. 124 | 125 | = 0.5.5 = 126 | * Supported version bump 5.8. 127 | 128 | = 0.5.4 = 129 | * Added function for widget selection iframe to auto resize. 130 | * Provided platform identifier to widget selection iframe. 131 | 132 | = 0.5.3 = 133 | * Fixed issues for checking enabled_visitor_recognition on embed script pre render. 134 | 135 | = 0.5.2 = 136 | * Fixed checking of $customer_details variable. 137 | * Fixed undefined index issues on validating visibility options. 138 | 139 | = 0.5.1 = 140 | * Supported version bump 5.7. 141 | * Fixed undefined index issue of the enable/disable visitor recognition feature. 142 | * Fixed default value for enable/disable visitor recognition feature after updating plugin. 143 | 144 | = 0.5.0 = 145 | * Added option to enable/disable visitor recognition 146 | * Escaped widget embed URL to prevent possible XSS issues 147 | 148 | = 0.4.4 = 149 | * supported version bump 5.6.2 150 | 151 | = 0.4.3 = 152 | * supported version bumbp 5.5.1 153 | 154 | = 0.4.2 = 155 | * supported version bump 5.4 156 | 157 | = 0.4.1 = 158 | * Fixed plugin version mismatch in readme and plugin file 159 | 160 | = 0.4.0 = 161 | * Added support for wildcard url match for include URL and exclude URL 162 | 163 | = 0.3.8 = 164 | * supported version bump 5.2.2 165 | 166 | = 0.3.7 = 167 | * supported version bump 5.2.1 168 | 169 | = 0.3.6 = 170 | * supported version bump 5.1 171 | 172 | = 0.3.5 = 173 | * supported version bump 174 | 175 | = 0.3.4 = 176 | * supported version bump 177 | 178 | = 0.3.3 = 179 | * fixed user recognition vulnerability 180 | * updated admin page texts 181 | * moved wp_footer hook to last item 182 | 183 | = 0.3.2 = 184 | * fixed issues on widget settings on fresh install 185 | 186 | = 0.3.1 = 187 | * plugin notifications update 188 | * logged in user recognition 189 | If user is logged in, the widget will fill the pre-chat form automatically 190 | 191 | = 0.3.0 = 192 | * fixed issues with visibility filters 193 | 194 | = 0.3.0 = 195 | * fixed issues with visibility filters 196 | 197 | = 0.2.9 = 198 | * fixed issue with assets folder 199 | 200 | = 0.2.8 = 201 | * added updated plugin admin interface 202 | 203 | = 0.2.7 = 204 | * added woocommerce support 205 | 206 | = 0.2.6 = 207 | * wrapped all hard-coded text in plugin settings with gettext functions 208 | 209 | = 0.2.5 = 210 | * Fixed include url warning message thrown 211 | 212 | = 0.2.4 = 213 | * updated session handling 214 | * Added the ability to include a specific url slug 215 | * modified plugin settings page interface 216 | 217 | = 0.2.3 = 218 | * Updating widget code due to known conflict 219 | 220 | = 0.2.2 = 221 | * Supported version bump to 4.7 222 | 223 | = 0.2.1 = 224 | * Supported version bump 225 | 226 | = 0.2.0 = 227 | * Added multisite support * 228 | 229 | = 0.1.9 = 230 | * Added the ability to exclude a specific url slug 231 | 232 | = 0.1.8 = 233 | * Fixed bug causing conflict with another plugin, and tested on 4.5 234 | 235 | = 0.1.7 = 236 | * Fixed naming convention causing a conflict with another plugin 237 | 238 | = 0.1.6 = 239 | * Modified visibility options to fix a bug, and implemented a better shortcode. 240 | 241 | = 0.1.0 = 242 | * Add the tawk.to live chat widget to your site! 243 | 244 | = 0.1.5 = 245 | * Implemented visibility options, you can now choose to Always show the script, show it only on the front page, only on category pages or only on pages tagged with a shortcode. 246 | 247 | = 0.1.4 = 248 | * Supported version bump 249 | 250 | = 0.1.3 = 251 | * Supported version bump 252 | 253 | = 0.1.2 = 254 | * Supported version bump 255 | 256 | = 0.1.1 = 257 | * No more manual embed code copying, choose desired widget and it will be inserted in your site 258 | 259 | == Upgrade Notice == 260 | 261 | = 0.7.0 = 262 | We have released an update for the URL include/exclude feature of our plugin. You can now enter either full URLs or paths with wildcards using any of the following placements: 263 | 264 | * start of the path (ex. */to/somewhere) 265 | * middle of the path (ex. /path/*/somewhere) 266 | * end of the path (ex. /path/to/somewhere) 267 | * start AND middle of the path (ex. */lead/*/somewhere) 268 | * middle AND end of the path (ex. /path/*/to/*) 269 | 270 | ## Frequently Asked Questions 271 | 272 | = How much does this cost? = 273 | 274 | This tawk.to app is completely free. 275 | 276 | = Do you provide support? = 277 | 278 | Yes, we provide 24x7-365 real-time support via both live chat and email. We never close. 279 | 280 | = Can I choose which pages to put the widget on? = 281 | 282 | Yes, you can use the visibility options in the Plugin settings to select specific pages, or you can show the tawk.to widget on any page independent of the visibility options by simply using the [tawkto] shortcode in the post or page. 283 | 284 | = Can I customize the widget design? = 285 | 286 | Yes, you can customize colors, content, border radius, position and more. Select any of 45+ different languages. You can even customize your widget with an Attention Grabber — an image designed to catch your visitor’s attention so they know you’re ready to chat. 287 | 288 | = Can I schedule when the widget will be shown? = 289 | 290 | Yes, there is a complete widget scheduler. 291 | 292 | = Do you have any documentation or support articles? = 293 | 294 | Yes, we have a detailed [Help Center](https://help.tawk.to/) and [Academy](https://www.tawk.to/academy/introduction/), which include videos and tutorials on all the features of tawk.to. 295 | 296 | = Can multiple users chat at one time? = 297 | 298 | Yes, you can add an unlimited number of Agents to your account so that your entire team can chat with your website visitors. tawk.to also enables you to create Departments for grouping your agents. E.g., Sales, Support, etc. 299 | -------------------------------------------------------------------------------- /tawkto/screenshot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tawk/tawk-wordpress/d612385fc5a3eb5a1bbbc362e845716c2137986a/tawkto/screenshot-1.png -------------------------------------------------------------------------------- /tawkto/screenshot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tawk/tawk-wordpress/d612385fc5a3eb5a1bbbc362e845716c2137986a/tawkto/screenshot-2.png -------------------------------------------------------------------------------- /tawkto/screenshot-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tawk/tawk-wordpress/d612385fc5a3eb5a1bbbc362e845716c2137986a/tawkto/screenshot-3.png -------------------------------------------------------------------------------- /tawkto/screenshot-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tawk/tawk-wordpress/d612385fc5a3eb5a1bbbc362e845716c2137986a/tawkto/screenshot-4.png -------------------------------------------------------------------------------- /tawkto/screenshot-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tawk/tawk-wordpress/d612385fc5a3eb5a1bbbc362e845716c2137986a/tawkto/screenshot-5.png -------------------------------------------------------------------------------- /tawkto/screenshot-6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tawk/tawk-wordpress/d612385fc5a3eb5a1bbbc362e845716c2137986a/tawkto/screenshot-6.png -------------------------------------------------------------------------------- /tawkto/tawkto.php: -------------------------------------------------------------------------------- 1 | plugin_ver = $plugin_data['Version']; 73 | } 74 | } 75 | 76 | /** 77 | * Initialize default option values 78 | * 79 | * @return void 80 | */ 81 | public static function init_options() { 82 | $options = self::get_default_options(); 83 | 84 | if ( ! get_option( self::TAWK_VISIBILITY_OPTIONS, false ) ) { 85 | update_option( self::TAWK_VISIBILITY_OPTIONS, $options['visibility'] ); 86 | } 87 | 88 | if ( ! get_option( self::TAWK_PRIVACY_OPTIONS, false ) ) { 89 | update_option( self::TAWK_PRIVACY_OPTIONS, $options['privacy'] ); 90 | } 91 | 92 | if ( ! get_option( self::TAWK_SECURITY_OPTIONS, false ) ) { 93 | update_option( self::TAWK_SECURITY_OPTIONS, $options['security'] ); 94 | } 95 | } 96 | 97 | /** 98 | * Retrieves tawk.to admin settings assets 99 | * 100 | * @param string $hook - hook name. 101 | * @return void 102 | */ 103 | public function tawk_settings_assets( $hook ) { 104 | if ( 'settings_page_tawkto_plugin' !== $hook ) { 105 | return; 106 | } 107 | 108 | wp_register_style( 109 | 'tawk_admin_style', 110 | plugins_url( 'assets/css/tawk.admin.css', __FILE__ ), 111 | array(), 112 | $this->plugin_ver 113 | ); 114 | wp_enqueue_style( 'tawk_admin_style' ); 115 | 116 | wp_enqueue_script( 117 | 'tawk_admin_script', 118 | plugins_url( 'assets/js/tawk.admin.js', __FILE__ ), 119 | array(), 120 | $this->plugin_ver, 121 | true 122 | ); 123 | 124 | } 125 | 126 | /** 127 | * Initialize plugin settings 128 | * 129 | * @return void 130 | */ 131 | public function admin_init() { 132 | register_setting( 'tawk_options', self::TAWK_VISIBILITY_OPTIONS, array( &$this, 'validate_visibility_options' ) ); 133 | register_setting( 'tawk_options', self::TAWK_PRIVACY_OPTIONS, array( &$this, 'validate_privacy_options' ) ); 134 | register_setting( 'tawk_options', self::TAWK_SECURITY_OPTIONS, array( &$this, 'validate_security_options' ) ); 135 | register_setting( 'tawk_options', self::TAWK_CONFIG_VERSION, array( &$this, 'update_config_version' ) ); 136 | } 137 | 138 | /** 139 | * Saves the selected property and widget to the database. 140 | */ 141 | public function action_setwidget() { 142 | header( 'Content-Type: application/json' ); 143 | 144 | if ( false === wp_is_json_request() ) { 145 | $response['success'] = false; 146 | $response['message'] = 'Invalid request'; 147 | wp_send_json( $response ); 148 | wp_die(); 149 | }; 150 | 151 | $post_data = json_decode( file_get_contents( 'php://input' ), true ); 152 | 153 | $response = array( 154 | 'success' => true, 155 | ); 156 | 157 | if ( false === $this->validate_request_auth( self::TAWK_ACTION_SET_WIDGET, $post_data ) ) { 158 | $response['success'] = false; 159 | $response['message'] = 'Unauthorized'; 160 | wp_send_json( $response ); 161 | wp_die(); 162 | }; 163 | 164 | if ( ! isset( $post_data['pageId'] ) || ! isset( $post_data['widgetId'] ) ) { 165 | $response['success'] = false; 166 | wp_send_json( $response ); 167 | wp_die(); 168 | } 169 | 170 | if ( ! self::ids_are_correct( $post_data['pageId'], $post_data['widgetId'] ) ) { 171 | $response['success'] = false; 172 | wp_send_json( $response ); 173 | wp_die(); 174 | } 175 | 176 | update_option( self::TAWK_PAGE_ID_VARIABLE, $post_data['pageId'] ); 177 | update_option( self::TAWK_WIDGET_ID_VARIABLE, $post_data['widgetId'] ); 178 | 179 | wp_send_json( $response ); 180 | wp_die(); 181 | } 182 | 183 | /** 184 | * Plugin notice for tawk.to 185 | */ 186 | public function tawk_admin_notice() { 187 | $settings_updated = filter_input( INPUT_GET, 'settings-updated', FILTER_VALIDATE_BOOLEAN ); 188 | if ( true === $settings_updated ) { 189 | ?> 190 |
191 |

192 |
193 | true, 214 | ); 215 | 216 | if ( false === $this->validate_request_auth( self::TAWK_ACTION_REMOVE_WIDGET, $post_data ) ) { 217 | $response['success'] = false; 218 | $response['message'] = 'Unauthorized'; 219 | wp_send_json( $response ); 220 | wp_die(); 221 | }; 222 | 223 | update_option( self::TAWK_PAGE_ID_VARIABLE, '' ); 224 | update_option( self::TAWK_WIDGET_ID_VARIABLE, '' ); 225 | 226 | wp_send_json( $response ); 227 | wp_die(); 228 | } 229 | 230 | /** 231 | * Validates action requests auth 232 | * 233 | * @param string $action - Action to be done. 234 | * @param array $post_data - Parsed JSON payload for the action. 235 | * @return boolean 236 | */ 237 | private function validate_request_auth( $action, $post_data = array() ) { 238 | if ( false === current_user_can( 'administrator' ) ) { 239 | return false; 240 | } 241 | 242 | if ( false === isset( $post_data['nonce'] ) ) { 243 | return false; 244 | } 245 | 246 | if ( false === wp_verify_nonce( $post_data['nonce'], $action ) ) { 247 | return false; 248 | } 249 | 250 | return true; 251 | } 252 | 253 | /** 254 | * Validates the selected visibility options 255 | * 256 | * @param array $input - Visibility option fields. 257 | * @return mixed 258 | */ 259 | public function validate_visibility_options( $input ) { 260 | $toggle_fields = array( 261 | 'always_display', 262 | 'show_onfrontpage', 263 | 'show_oncategory', 264 | 'show_ontagpage', 265 | 'show_onarticlepages', 266 | 'exclude_url', 267 | 'include_url', 268 | 'display_on_shop', 269 | 'display_on_productcategory', 270 | 'display_on_productpage', 271 | 'display_on_producttag', 272 | ); 273 | 274 | $text_fields = array( 275 | 'excluded_url_list', 276 | 'included_url_list', 277 | ); 278 | 279 | $visibility = get_option( self::TAWK_VISIBILITY_OPTIONS, array() ); 280 | 281 | self::validate_toggle_fields( $input, $toggle_fields ); 282 | self::validate_text_fields( $input, $text_fields ); 283 | 284 | $visibility = array_merge( $visibility, $input ); 285 | 286 | return $visibility; 287 | } 288 | 289 | /** 290 | * Validates the selected privacy options 291 | * 292 | * @param mixed $input - Privacy option fields. 293 | * @return mixed 294 | */ 295 | public function validate_privacy_options( $input ) { 296 | $toggle_fields = array( 297 | 'enable_visitor_recognition', 298 | ); 299 | 300 | $privacy = get_option( self::TAWK_PRIVACY_OPTIONS, array() ); 301 | 302 | self::validate_toggle_fields( $input, $toggle_fields ); 303 | 304 | $privacy = array_merge( $privacy, $input ); 305 | 306 | return $privacy; 307 | } 308 | 309 | /** 310 | * Validates the selected security options 311 | * 312 | * @param mixed $input - Security option fields. 313 | * @return mixed 314 | */ 315 | public function validate_security_options( $input ) { 316 | $text_fields = array( 317 | 'js_api_key', 318 | ); 319 | 320 | $security = get_option( self::TAWK_SECURITY_OPTIONS, array() ); 321 | 322 | self::validate_text_fields( $input, $text_fields ); 323 | self::validate_js_api_key( $input ); 324 | 325 | $security = array_merge( $security, $input ); 326 | 327 | return $security; 328 | } 329 | 330 | /** 331 | * Updates the config version 332 | * 333 | * @return int 334 | */ 335 | public function update_config_version() { 336 | return get_option( self::TAWK_CONFIG_VERSION, 0 ) + 1; 337 | } 338 | 339 | /** 340 | * Adds the tawk.to plugin settings in the admin menu. 341 | */ 342 | public function add_menu() { 343 | add_options_page( 344 | __( 'Tawk.to Settings', 'tawk-to-live-chat' ), 345 | __( 'Tawk.to', 'tawk-to-live-chat' ), 346 | 'manage_options', 347 | 'tawkto_plugin', 348 | array( &$this, 'create_plugin_settings_page' ) 349 | ); 350 | } 351 | 352 | /** 353 | * Initializes the plugin settings page. 354 | */ 355 | public function create_plugin_settings_page() { 356 | global $wpdb; 357 | 358 | if ( ! current_user_can( 'manage_options' ) ) { 359 | wp_die( esc_html_e( 'You do not have sufficient permissions to access this page.' ) ); 360 | } 361 | 362 | $page_id = get_option( self::TAWK_PAGE_ID_VARIABLE ); 363 | $widget_id = get_option( self::TAWK_WIDGET_ID_VARIABLE ); 364 | $base_url = 'https://plugins.tawk.to'; 365 | 366 | $iframe_url = $base_url . '/generic/widgets' 367 | . '?currentWidgetId=' . $widget_id 368 | . '¤tPageId=' . $page_id 369 | . '&transparentBackground=1' 370 | . '&pltf=WordPress'; 371 | 372 | $set_widget_nonce = wp_create_nonce( self::TAWK_ACTION_SET_WIDGET ); 373 | $remove_widget_nonce = wp_create_nonce( self::TAWK_ACTION_REMOVE_WIDGET ); 374 | $plugin_ver = $this->plugin_ver; 375 | 376 | $default_options = self::get_default_options(); 377 | $visibility = get_option( self::TAWK_VISIBILITY_OPTIONS, array() ); 378 | $privacy = get_option( self::TAWK_PRIVACY_OPTIONS, array() ); 379 | $security = get_option( self::TAWK_SECURITY_OPTIONS, array() ); 380 | 381 | foreach ( $default_options['visibility'] as $key => $value ) { 382 | if ( ! isset( $visibility[ $key ] ) ) { 383 | $visibility[ $key ] = $value; 384 | } 385 | } 386 | 387 | foreach ( $default_options['privacy'] as $key => $value ) { 388 | if ( ! isset( $privacy[ $key ] ) ) { 389 | $privacy[ $key ] = $value; 390 | } 391 | } 392 | 393 | foreach ( $default_options['security'] as $key => $value ) { 394 | if ( ! isset( $security[ $key ] ) ) { 395 | $security[ $key ] = $value; 396 | } 397 | } 398 | 399 | if ( ! empty( $security['js_api_key'] ) ) { 400 | $security['js_api_key'] = self::NO_CHANGE; 401 | } 402 | 403 | include sprintf( '%s/templates/settings.php', dirname( __FILE__ ) ); 404 | } 405 | 406 | 407 | /** 408 | * Verifies if the provided property and widget ids are correct. 409 | * 410 | * @param string $page_id - Property Id. 411 | * @param string $widget_id - Widget Id. 412 | * @return boolean 413 | */ 414 | public static function ids_are_correct( $page_id, $widget_id ) { 415 | return 1 === preg_match( '/^[0-9A-Fa-f]{24}$/', $page_id ) && 1 === preg_match( '/^[a-z0-9]{1,50}$/i', $widget_id ); 416 | } 417 | 418 | /** 419 | * Validate JS API Key field 420 | * 421 | * @param array $fields - List of fields. 422 | * @return void 423 | * @throws Exception - Error validating JS API Key. 424 | */ 425 | private static function validate_js_api_key( &$fields ) { 426 | if ( self::NO_CHANGE === $fields['js_api_key'] ) { 427 | unset( $fields['js_api_key'] ); 428 | return; 429 | } 430 | 431 | if ( '' === $fields['js_api_key'] ) { 432 | return; 433 | } 434 | 435 | $fields['js_api_key'] = trim( $fields['js_api_key'] ); 436 | 437 | if ( 40 !== strlen( $fields['js_api_key'] ) ) { 438 | self::show_tawk_options_error( 'Invalid API key' ); 439 | } 440 | 441 | try { 442 | $fields['js_api_key'] = self::get_encrypted_data( $fields['js_api_key'] ); 443 | } catch ( Exception $e ) { 444 | self::show_tawk_options_error( 'Error saving Javascript API Key' ); 445 | 446 | unset( $fields['js_api_key'] ); 447 | } 448 | } 449 | 450 | /** 451 | * Validates and sanitizes text fields 452 | * 453 | * @param array $fields - List of fields. 454 | * @param array $field_names - List of field names to be validated. 455 | * @return void 456 | */ 457 | private static function validate_text_fields( &$fields, $field_names ) { 458 | foreach ( $field_names as $field_name ) { 459 | if ( isset( $fields[ $field_name ] ) ) { 460 | $fields[ $field_name ] = sanitize_text_field( $fields[ $field_name ] ); 461 | continue; 462 | } 463 | 464 | $fields[ $field_name ] = ''; 465 | } 466 | } 467 | 468 | /** 469 | * Validates and sanitizes visibility toggle fields 470 | * 471 | * @param array $fields - List of fields. 472 | * @param array $field_names - List of field names to be validated. 473 | * @return void 474 | */ 475 | private static function validate_toggle_fields( &$fields, $field_names ) { 476 | foreach ( $field_names as $field_name ) { 477 | if ( isset( $fields[ $field_name ] ) && '1' === $fields[ $field_name ] ) { 478 | $fields[ $field_name ] = 1; 479 | continue; 480 | } 481 | 482 | $fields[ $field_name ] = 0; 483 | } 484 | } 485 | 486 | /** 487 | * Retrieves default visibility options 488 | * 489 | * @return array 490 | */ 491 | public static function get_default_options() { 492 | $config = include plugin_dir_path( __FILE__ ) . 'includes/default_config.php'; 493 | 494 | return $config; 495 | } 496 | 497 | /** 498 | * Encrypt data 499 | * 500 | * @param string $data - Data to be encrypted. 501 | * @return string 502 | * @throws Exception - Error encrypting data. 503 | */ 504 | private static function get_encrypted_data( $data ) { 505 | if ( ! defined( 'SECURE_AUTH_KEY' ) ) { 506 | throw new Exception( 'SECURE_AUTH_KEY is not defined' ); 507 | } 508 | 509 | try { 510 | $iv = random_bytes( self::CIPHER_IV_LENGTH ); 511 | } catch ( Exception $e ) { 512 | throw new Exception( 'Error generating IV' ); 513 | } 514 | 515 | $encrypted_data = openssl_encrypt( $data, self::CIPHER, SECURE_AUTH_KEY, 0, $iv ); 516 | 517 | if ( false === $encrypted_data ) { 518 | throw new Exception( 'Error encrypting data' ); 519 | } 520 | 521 | // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode 522 | $encrypted_data = base64_encode( $iv . $encrypted_data ); 523 | 524 | if ( false === $encrypted_data ) { 525 | throw new Exception( 'Error encoding data' ); 526 | } 527 | 528 | return $encrypted_data; 529 | } 530 | 531 | /** 532 | * Decrypt data 533 | * 534 | * @param string $data - Data to be decrypted. 535 | * @return string 536 | */ 537 | public static function get_decrypted_data( $data ) { 538 | // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode 539 | $decoded_data = base64_decode( $data ); 540 | 541 | if ( false === $decoded_data ) { 542 | return null; 543 | } 544 | 545 | $iv = substr( $decoded_data, 0, self::CIPHER_IV_LENGTH ); 546 | $encrypted_data = substr( $decoded_data, self::CIPHER_IV_LENGTH ); 547 | 548 | $decrypted_data = openssl_decrypt( $encrypted_data, self::CIPHER, SECURE_AUTH_KEY, 0, $iv ); 549 | 550 | if ( false === $decrypted_data ) { 551 | return null; 552 | } 553 | 554 | return $decrypted_data; 555 | } 556 | 557 | /** 558 | * Adds settings error 559 | * 560 | * @param string $message - Error message. 561 | * @return void 562 | */ 563 | private static function show_tawk_options_error( $message ) { 564 | add_settings_error( 565 | 'tawk_options', 566 | 'tawk_error', 567 | $message, 568 | 'error' 569 | ); 570 | } 571 | } 572 | } 573 | 574 | if ( ! class_exists( 'TawkTo' ) ) { 575 | 576 | $plugin_file_data = get_file_data( 577 | __FILE__, 578 | array( 579 | 'Version' => 'Version', 580 | ), 581 | 'plugin' 582 | ); 583 | 584 | /** 585 | * Main tawk.to module 586 | */ 587 | class TawkTo { 588 | const PLUGIN_VERSION_VARIABLE = 'tawkto-version'; 589 | const TAWK_VISITOR_SESSION = 'tawkto-visitor-session'; 590 | 591 | /** 592 | * @var $plugin_version Plugin version 593 | */ 594 | private static $plugin_version; 595 | 596 | /** 597 | * __construct 598 | * 599 | * @return void 600 | */ 601 | public function __construct() { 602 | $tawkto_settings = new TawkTo_Settings(); 603 | add_shortcode( 'tawkto', array( $this, 'shortcode_print_embed_code' ) ); 604 | 605 | add_action( 'init', array( $this, 'start_session' ) ); 606 | } 607 | 608 | 609 | /** 610 | * Starts user session 611 | * 612 | * @return void 613 | */ 614 | public function start_session() { 615 | $privacy = get_option( TawkTo_Settings::TAWK_PRIVACY_OPTIONS ); 616 | 617 | if ( empty( $privacy['enable_visitor_recognition'] ) ) { 618 | return; 619 | } 620 | 621 | $security = get_option( TawkTo_Settings::TAWK_SECURITY_OPTIONS ); 622 | 623 | if ( empty( $security['js_api_key'] ) ) { 624 | return; 625 | } 626 | 627 | if ( session_status() === PHP_SESSION_NONE ) { 628 | session_start(); 629 | 630 | // If user is not logged in, remove the visitor session and close the session. 631 | // Session cannot be updated if it is not started. 632 | if ( ! is_user_logged_in() ) { 633 | if ( isset( $_SESSION[ self::TAWK_VISITOR_SESSION ] ) ) { 634 | unset( $_SESSION[ self::TAWK_VISITOR_SESSION ] ); 635 | } 636 | session_write_close(); 637 | } 638 | } 639 | } 640 | 641 | /** 642 | * Retrieves plugin version 643 | * 644 | * @return string plugin version 645 | */ 646 | public static function get_plugin_version() { 647 | if ( false === isset( self::$plugin_version ) ) { 648 | $plugin_file_data = get_file_data( 649 | __FILE__, 650 | array( 651 | 'Version' => 'Version', 652 | ), 653 | 'plugin' 654 | ); 655 | 656 | self::$plugin_version = $plugin_file_data['Version']; 657 | } 658 | 659 | return self::$plugin_version; 660 | } 661 | 662 | /** 663 | * Initializes plugin data on activation. 664 | */ 665 | public static function activate() { 666 | global $plugin_file_data; 667 | 668 | TawkTo_Settings::init_options(); 669 | 670 | add_option( TawkTo_Settings::TAWK_PAGE_ID_VARIABLE, '', '', 'yes' ); 671 | add_option( TawkTo_Settings::TAWK_WIDGET_ID_VARIABLE, '', '', 'yes' ); 672 | add_option( self::PLUGIN_VERSION_VARIABLE, self::get_plugin_version(), '', 'yes' ); 673 | } 674 | 675 | /** 676 | * Cleans up plugin data on deactivation 677 | */ 678 | public static function deactivate() { 679 | delete_option( TawkTo_Settings::TAWK_PAGE_ID_VARIABLE ); 680 | delete_option( TawkTo_Settings::TAWK_WIDGET_ID_VARIABLE ); 681 | delete_option( TawkTo_Settings::TAWK_VISIBILITY_OPTIONS ); 682 | delete_option( TawkTo_Settings::TAWK_PRIVACY_OPTIONS ); 683 | delete_option( TawkTo_Settings::TAWK_SECURITY_OPTIONS ); 684 | delete_option( TawkTo_Settings::TAWK_CONFIG_VERSION ); 685 | delete_option( self::PLUGIN_VERSION_VARIABLE ); 686 | } 687 | 688 | /** 689 | * Shortcode for tawk.to to inject the embed code. 690 | */ 691 | public function shortcode_print_embed_code() { 692 | add_action( 'wp_footer', array( $this, 'embed_code' ), 100 ); 693 | } 694 | 695 | /** 696 | * Retrieves customer details 697 | * 698 | * @return array - Customer details 699 | */ 700 | public function get_current_customer_details() { 701 | if ( is_user_logged_in() ) { 702 | $current_user = wp_get_current_user(); 703 | $user_info = array( 704 | 'name' => $current_user->display_name, 705 | 'email' => $current_user->user_email, 706 | ); 707 | 708 | $hash = self::get_visitor_hash( $user_info['email'] ); 709 | if ( null !== $hash ) { 710 | $user_info['hash'] = $hash; 711 | } 712 | 713 | return wp_json_encode( $user_info ); 714 | } 715 | return null; 716 | } 717 | 718 | /** 719 | * Retrieves visitor hash 720 | * 721 | * @param string $email - Visitor email address. 722 | * @return string 723 | */ 724 | public static function get_visitor_hash( $email ) { 725 | $security = get_option( TawkTo_Settings::TAWK_SECURITY_OPTIONS ); 726 | 727 | if ( empty( $security['js_api_key'] ) ) { 728 | return null; 729 | } 730 | 731 | $config_version = get_option( TawkTo_Settings::TAWK_CONFIG_VERSION, 0 ); 732 | 733 | if ( isset( $_SESSION[ self::TAWK_VISITOR_SESSION ] ) ) { 734 | $current_session = $_SESSION[ self::TAWK_VISITOR_SESSION ]; 735 | 736 | if ( isset( $current_session['hash'] ) && 737 | $current_session['email'] === $email && 738 | $current_session['config_version'] === $config_version ) { 739 | return $current_session['hash']; 740 | } 741 | } 742 | 743 | $key = TawkTo_Settings::get_decrypted_data( $security['js_api_key'] ); 744 | 745 | if ( null === $key ) { 746 | return null; 747 | } 748 | 749 | $hash = hash_hmac( 'sha256', $email, $key ); 750 | 751 | $_SESSION[ self::TAWK_VISITOR_SESSION ] = array( 752 | 'hash' => $hash, 753 | 'email' => $email, 754 | 'config_version' => $config_version, 755 | ); 756 | 757 | return $hash; 758 | } 759 | 760 | /** 761 | * Creates the embed code 762 | */ 763 | public function embed_code() { 764 | $page_id = get_option( TawkTo_Settings::TAWK_PAGE_ID_VARIABLE ); 765 | $widget_id = get_option( TawkTo_Settings::TAWK_WIDGET_ID_VARIABLE ); 766 | $privacy = get_option( TawkTo_Settings::TAWK_PRIVACY_OPTIONS ); 767 | 768 | // default value. 769 | $enable_visitor_recognition = true; 770 | 771 | if ( isset( $privacy ) && isset( $privacy['enable_visitor_recognition'] ) ) { 772 | $enable_visitor_recognition = 1 === $privacy['enable_visitor_recognition']; 773 | } 774 | 775 | if ( $enable_visitor_recognition ) { 776 | $customer_details = $this->get_current_customer_details(); 777 | } 778 | 779 | if ( ! empty( $page_id ) && ! empty( $widget_id ) ) { 780 | include sprintf( '%s/templates/widget.php', dirname( __FILE__ ) ); 781 | } 782 | } 783 | 784 | /** 785 | * Retrieves current URL 786 | * 787 | * @return string 788 | */ 789 | private function get_current_url() { 790 | $http_host = ''; 791 | $request_uri = ''; 792 | 793 | // sanitize and remove backslashes. 794 | if ( true === isset( $_SERVER['HTTP_HOST'] ) ) { 795 | $http_host = sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ); 796 | } 797 | 798 | if ( true === isset( $_SERVER['REQUEST_URI'] ) ) { 799 | $request_uri = sanitize_text_field( wp_unslash( $_SERVER['REQUEST_URI'] ) ); 800 | } 801 | 802 | $current_url = urldecode( $http_host . $request_uri ); 803 | 804 | $protocol = ( ! empty( $_SERVER['HTTPS'] ) && 'on' === $_SERVER['HTTPS'] ) ? 'https://' : 'http://'; 805 | 806 | return strtolower( $protocol . $current_url ); 807 | } 808 | 809 | /** 810 | * Prints the embed code when it is allowed to be displayed. 811 | * 812 | * @return void 813 | */ 814 | public function print_embed_code() { 815 | $visibility = get_option( TawkTo_Settings::TAWK_VISIBILITY_OPTIONS ); 816 | $display = false; 817 | 818 | if ( 1 === $visibility['always_display'] ) { 819 | $display = true; 820 | } 821 | 822 | if ( ( 1 === $visibility['show_onfrontpage'] ) && ( is_home() || is_front_page() ) ) { 823 | $display = true; 824 | } 825 | 826 | if ( ( 1 === $visibility['show_oncategory'] ) && is_category() ) { 827 | $display = true; 828 | } 829 | 830 | if ( ( 1 === $visibility['show_ontagpage'] ) && is_tag() ) { 831 | $display = true; 832 | } 833 | 834 | if ( ( 1 === $visibility['show_onarticlepages'] ) && is_single() ) { 835 | $display = true; 836 | } 837 | 838 | if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ), true ) ) { 839 | if ( ( 1 === $visibility['display_on_shop'] ) && is_shop() ) { 840 | $display = true; 841 | } 842 | 843 | if ( ( 1 === $visibility['display_on_productcategory'] ) && is_product_category() ) { 844 | $display = true; 845 | } 846 | 847 | if ( ( 1 === $visibility['display_on_productpage'] ) && is_product() ) { 848 | $display = true; 849 | } 850 | 851 | if ( ( 1 === $visibility['display_on_producttag'] ) && is_product_tag() ) { 852 | $display = true; 853 | } 854 | } 855 | 856 | if ( isset( $visibility['include_url'] ) && 1 === $visibility['include_url'] ) { 857 | $current_url = $this->get_current_url(); 858 | 859 | $included_url_list = $visibility['included_url_list']; 860 | $included_url_list = array_map( 'trim', preg_split( '/,/', $included_url_list ) ); 861 | 862 | if ( UrlPatternMatcher::match( $current_url, $included_url_list ) ) { 863 | $display = true; 864 | } 865 | } 866 | 867 | if ( isset( $visibility['exclude_url'] ) && ( 1 === $visibility['exclude_url'] ) ) { 868 | $current_url = $this->get_current_url(); 869 | 870 | $excluded_url_list = $visibility['excluded_url_list']; 871 | $excluded_url_list = array_map( 'trim', preg_split( '/,/', $excluded_url_list ) ); 872 | 873 | if ( UrlPatternMatcher::match( $current_url, $excluded_url_list ) ) { 874 | $display = false; 875 | }; 876 | } 877 | 878 | if ( $display ) { 879 | $this->embed_code(); 880 | } 881 | } 882 | 883 | /** 884 | * Migrate old tawk to embed code to new version. 885 | * 886 | * Old version contained embed code script, from that 887 | * markup we need only page id and widget id 888 | */ 889 | public function migrate_embed_code() { 890 | $old_tawkto_embed_code = get_option( 'tawkto-embed-code' ); 891 | 892 | if ( empty( $old_tawkto_embed_code ) ) { 893 | return; 894 | } 895 | 896 | $matches = array(); 897 | preg_match( '/https:\/\/embed.tawk.to\/([0-9A-Fa-f]{24})\/([a-z0-9]{1,50})/', $old_tawkto_embed_code, $matches ); 898 | 899 | if ( isset( $matches[1] ) && isset( $matches[2] ) && TawkTo_Settings::ids_are_correct( $matches[1], $matches[2] ) ) { 900 | update_option( TawkTo_Settings::TAWK_PAGE_ID_VARIABLE, $matches[1] ); 901 | update_option( TawkTo_Settings::TAWK_WIDGET_ID_VARIABLE, $matches[2] ); 902 | } 903 | 904 | delete_option( 'tawkto-embed-code' ); 905 | } 906 | } 907 | } 908 | 909 | if ( class_exists( 'TawkTo' ) ) { 910 | register_activation_hook( __FILE__, array( 'TawkTo', 'activate' ) ); 911 | register_deactivation_hook( __FILE__, array( 'TawkTo', 'deactivate' ) ); 912 | 913 | $tawkto = new TawkTo(); 914 | 915 | $upgrade_manager = new TawkToUpgradeManager( 916 | TawkTo::get_plugin_version(), 917 | TawkTo::PLUGIN_VERSION_VARIABLE 918 | ); 919 | $upgrade_manager->register_hooks(); 920 | 921 | if ( isset( $tawkto ) ) { 922 | // these are called every page load. 923 | $tawkto->migrate_embed_code(); 924 | 925 | /** 926 | * Adds plugin settings link 927 | * 928 | * @param array $links - List of links from WordPress admin. 929 | * @return array Updated list of links 930 | */ 931 | function tawkto_plugin_settings_link( $links ) { 932 | $settings_link = 'Settings'; 933 | array_unshift( $links, $settings_link ); 934 | return $links; 935 | } 936 | 937 | $plugin_base_name = plugin_basename( __FILE__ ); 938 | add_filter( 'plugin_action_links_' . $plugin_base_name, 'tawkto_plugin_settings_link' ); 939 | } 940 | 941 | add_action( 'wp_footer', array( $tawkto, 'print_embed_code' ) ); 942 | } 943 | -------------------------------------------------------------------------------- /tawkto/templates/settings.php: -------------------------------------------------------------------------------- 1 | 22 | 23 |
24 |
25 | 29 |
30 |
31 | 32 |
33 | 'tawk-settings-form', 41 | ) 42 | ); 43 | ?> 44 |
45 | 46 |
47 |
48 | 53 | 58 | 63 | 64 | 69 | 70 |
71 | 72 |
73 | array( 103 | 'base' => $base_url, 104 | 'iframe' => $iframe_url, 105 | ), 106 | 'nonce' => array( 107 | 'setWidget' => $set_widget_nonce, 108 | 'removeWidget' => $remove_widget_nonce, 109 | ), 110 | ) 111 | ); 112 | ?> 113 | 114 | 118 |

119 | 120 | >click here 121 | 122 |
123 | 124 |
125 | 129 |
130 |
131 |
132 |

133 |

134 | 135 | 136 | 137 | 138 | 139 |

140 | 141 |

142 | 143 | 144 | 147 | 158 | 159 | 160 | 163 | 174 | 175 | 176 | 179 | 190 | 191 | 192 | 195 | 206 | 207 | 208 | 211 | 222 | 223 |
145 | 146 | 148 | 157 |
161 | 162 | 164 | 173 |
177 | 178 | 180 | 189 |
193 | 194 | 196 | 205 |
209 | 210 | 212 | 221 |
224 | 225 |

226 |

227 | 228 | (,) 229 |

230 | 231 |
    232 |
  • *
  • 233 |
  • */to/somewhere
  • 234 |
  • /*/to/somewhere
  • 235 |
  • /path/*/somewhere
  • 236 |
  • /path/*/lead/*/somewhere
  • 237 |
  • /path/*/*/somewhere
  • 238 |
  • /path/to/*
  • 239 |
  • /path/to/*/
  • 240 |
  • */to/*/page
  • 241 |
  • /*/to/*/page
  • 242 |
  • /path/*/other/*
  • 243 |
  • /path/*/other/*/
  • 244 |
  • http://www.example.com/
  • 245 |
  • http://www.example.com/*
  • 246 |
  • http://www.example.com/*/to/somewhere
  • 247 |
  • http://www.example.com/path/*/somewhere
  • 248 |
  • http://www.example.com/path/*/lead/*/somewhere
  • 249 |
  • http://www.example.com/path/*/*/somewhere
  • 250 |
  • http://www.example.com/path/to/*
  • 251 |
  • http://www.example.com/path/to/*/
  • 252 |
  • http://www.example.com/*/to/*/page
  • 253 |
  • http://www.example.com/path/*/other/*
  • 254 |
  • http://www.example.com/path/*/other/*/
  • 255 |
256 |
257 |

258 | 259 | 260 | 261 | 264 | 281 | 282 | 283 | 286 | 302 | 303 |
262 | 263 | 265 | 274 | 280 |
284 | 285 | 287 | 296 |
304 |
305 |
306 |
307 | 308 |
309 | 318 |
319 |

320 | 321 |

322 | 323 | 324 | 327 | 338 | 339 | 340 | 343 | 354 | 355 | 356 | 357 | 360 | 371 | 372 | 373 | 376 | 387 | 388 |
325 | 326 | 328 | 337 |
341 | 342 | 344 | 353 |
358 | 359 | 361 | 370 |
374 | 375 | 377 | 386 |
389 |
390 | 391 |
392 | 393 |
394 |

395 | 396 |

397 | 398 | 399 | 402 | 413 | 414 |
400 | 401 | 403 | 412 |
415 | 416 |
417 |

418 | 419 |

420 | 421 | 422 | 423 | 426 | 435 | 436 |
424 | 425 | 427 | 434 |
437 |
438 |
439 |
440 |
441 | 442 |
443 | 456 | 459 |
460 | -------------------------------------------------------------------------------- /tawkto/templates/widget.php: -------------------------------------------------------------------------------- 1 | 10 | 11 | 12 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /tawkto/upgrade.manager.php: -------------------------------------------------------------------------------- 1 | upgrades = array( 43 | TawkToUpgradeVersion070::get_version() => TawkToUpgradeVersion070::class, 44 | TawkToUpgradeVersion090::get_version() => TawkToUpgradeVersion090::class, 45 | ); 46 | 47 | $this->version_var_name = $version_var_name; 48 | $this->curr_ver = $version; 49 | $this->prev_ver = get_option( $version_var_name, '' ); 50 | } 51 | 52 | /** 53 | * Start doing upgrades 54 | */ 55 | public function start() { 56 | if ( ! empty( $this->prev_ver ) && version_compare( $this->prev_ver, $this->curr_ver ) >= 0 ) { 57 | // do not do anything. 58 | return; 59 | } 60 | 61 | // special case: we've never set the version before. 62 | // All plugins prior to the current version needs the upgrade. 63 | if ( version_compare( $this->prev_ver, $this->curr_ver ) < 0 ) { 64 | // are there upgrade steps depending on how out-of-date? 65 | foreach ( $this->upgrades as $upgrade_ver => $upgrade ) { 66 | // only run upgrades if upgrade version is lower than 67 | // and equal to the current version. 68 | if ( version_compare( $upgrade_ver, $this->curr_ver ) <= 0 ) { 69 | $this->do_upgrade( $upgrade_ver ); 70 | } 71 | 72 | update_option( $this->version_var_name, $upgrade_ver ); 73 | } 74 | } 75 | 76 | } 77 | 78 | /** 79 | * Gets upgrade class by provided version 80 | * 81 | * @param string $version Upgrade version. 82 | * 83 | * @return string|null Returns `upgrade class name` if version exists in the list. Otherwise, returns `null`. 84 | */ 85 | protected function get_upgrade_class( $version ) { 86 | if ( false === array_key_exists( $version, $this->upgrades ) ) { 87 | return null; 88 | } 89 | 90 | return $this->upgrades[ $version ]; 91 | } 92 | 93 | /** 94 | * Does the version upgrade depending on the provided plugin version. 95 | * 96 | * @param string $version Plugin version. 97 | * @return void 98 | */ 99 | protected function do_upgrade( $version ) { 100 | $upgrade_class = $this->get_upgrade_class( $version ); 101 | 102 | if ( true === is_null( $upgrade_class ) ) { 103 | return; 104 | } 105 | 106 | $upgrade_class::upgrade(); 107 | } 108 | 109 | /** 110 | * Registers hooks for upgrade. 111 | */ 112 | public function register_hooks() { 113 | add_action( 'plugins_loaded', array( $this, 'start' ) ); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /tawkto/upgrades/base.php: -------------------------------------------------------------------------------- 1 | $visibility['enable_visitor_recognition'] ) ); 23 | 24 | unset( $visibility['enable_visitor_recognition'] ); 25 | update_option( TawkTo_Settings::TAWK_VISIBILITY_OPTIONS, $visibility ); 26 | } 27 | 28 | update_option( TawkTo_Settings::TAWK_SECURITY_OPTIONS, array( 'js_api_key' => '' ) ); 29 | } 30 | } 31 | --------------------------------------------------------------------------------