diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57872d0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/vendor/ diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..61290a6 --- /dev/null +++ b/composer.json @@ -0,0 +1,17 @@ +{ + "name": "patrick/xero", + "description": "A wordpress plugin for Xero integration specifically for Hair-on-the-Move", + "type": "wordpress-plugin", + "require": { + "xeroapi/xero-php-oauth2": "^2.6", + "htmlburger/carbon-fields": "^3.3", + "guzzlehttp/psr7": "1.8" + }, + "license": "Private-for-hotm-team", + "authors": [ + { + "name": "vmbox", + "email": "hotm-dev@biukop.com.au" + } + ] +} diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..aa097e4 --- /dev/null +++ b/composer.lock @@ -0,0 +1,777 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "1c56c7e7d5c18bb884d41ee07db16c52", + "packages": [ + { + "name": "firebase/php-jwt", + "version": "v5.4.0", + "source": { + "type": "git", + "url": "https://github.com/firebase/php-jwt.git", + "reference": "d2113d9b2e0e349796e72d2a63cf9319100382d2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/firebase/php-jwt/zipball/d2113d9b2e0e349796e72d2a63cf9319100382d2", + "reference": "d2113d9b2e0e349796e72d2a63cf9319100382d2", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": ">=4.8 <=9" + }, + "suggest": { + "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" + }, + "type": "library", + "autoload": { + "psr-4": { + "Firebase\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" + }, + { + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" + } + ], + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", + "keywords": [ + "jwt", + "php" + ], + "support": { + "issues": "https://github.com/firebase/php-jwt/issues", + "source": "https://github.com/firebase/php-jwt/tree/v5.4.0" + }, + "time": "2021-06-23T19:00:23+00:00" + }, + { + "name": "guzzlehttp/guzzle", + "version": "7.3.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/guzzle.git", + "reference": "7008573787b430c1c1f650e3722d9bba59967628" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/7008573787b430c1c1f650e3722d9bba59967628", + "reference": "7008573787b430c1c1f650e3722d9bba59967628", + "shasum": "" + }, + "require": { + "ext-json": "*", + "guzzlehttp/promises": "^1.4", + "guzzlehttp/psr7": "^1.7 || ^2.0", + "php": "^7.2.5 || ^8.0", + "psr/http-client": "^1.0" + }, + "provide": { + "psr/http-client-implementation": "1.0" + }, + "require-dev": { + "bamarni/composer-bin-plugin": "^1.4.1", + "ext-curl": "*", + "php-http/client-integration-tests": "^3.0", + "phpunit/phpunit": "^8.5.5 || ^9.3.5", + "psr/log": "^1.1" + }, + "suggest": { + "ext-curl": "Required for CURL handler support", + "ext-intl": "Required for Internationalized Domain Name (IDN) support", + "psr/log": "Required for using the Log middleware" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "7.3-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Márk Sági-Kazár", + "email": "mark.sagikazar@gmail.com", + "homepage": "https://sagikazarmark.hu" + } + ], + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", + "keywords": [ + "client", + "curl", + "framework", + "http", + "http client", + "psr-18", + "psr-7", + "rest", + "web service" + ], + "support": { + "issues": "https://github.com/guzzle/guzzle/issues", + "source": "https://github.com/guzzle/guzzle/tree/7.3.0" + }, + "funding": [ + { + "url": "https://github.com/GrahamCampbell", + "type": "github" + }, + { + "url": "https://github.com/Nyholm", + "type": "github" + }, + { + "url": "https://github.com/alexeyshockov", + "type": "github" + }, + { + "url": "https://github.com/gmponos", + "type": "github" + } + ], + "time": "2021-03-23T11:33:13+00:00" + }, + { + "name": "guzzlehttp/promises", + "version": "1.4.1", + "source": { + "type": "git", + "url": "https://github.com/guzzle/promises.git", + "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/promises/zipball/8e7d04f1f6450fef59366c399cfad4b9383aa30d", + "reference": "8e7d04f1f6450fef59366c399cfad4b9383aa30d", + "shasum": "" + }, + "require": { + "php": ">=5.5" + }, + "require-dev": { + "symfony/phpunit-bridge": "^4.4 || ^5.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.4-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + } + ], + "description": "Guzzle promises library", + "keywords": [ + "promise" + ], + "support": { + "issues": "https://github.com/guzzle/promises/issues", + "source": "https://github.com/guzzle/promises/tree/1.4.1" + }, + "time": "2021-03-07T09:25:29+00:00" + }, + { + "name": "guzzlehttp/psr7", + "version": "1.8.0", + "source": { + "type": "git", + "url": "https://github.com/guzzle/psr7.git", + "reference": "043f17d447dc88045a13b5b1b6d9f902e2820685" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/043f17d447dc88045a13b5b1b6d9f902e2820685", + "reference": "043f17d447dc88045a13b5b1b6d9f902e2820685", + "shasum": "" + }, + "require": { + "php": ">=5.4.0", + "psr/http-message": "~1.0", + "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" + }, + "provide": { + "psr/http-message-implementation": "1.0" + }, + "require-dev": { + "ext-zlib": "*", + "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.14 || ^7.5.20 || ^8.5.8 || ^9.3.10" + }, + "suggest": { + "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7-dev" + } + }, + "autoload": { + "psr-4": { + "GuzzleHttp\\Psr7\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" + }, + { + "name": "Tobias Schultze", + "homepage": "https://github.com/Tobion" + } + ], + "description": "PSR-7 message implementation that also provides common utility methods", + "keywords": [ + "http", + "message", + "psr-7", + "request", + "response", + "stream", + "uri", + "url" + ], + "support": { + "issues": "https://github.com/guzzle/psr7/issues", + "source": "https://github.com/guzzle/psr7/tree/1.8.0" + }, + "time": "2021-03-21T12:38:22+00:00" + }, + { + "name": "htmlburger/carbon-fields", + "version": "v3.3.2", + "source": { + "type": "git", + "url": "https://github.com/htmlburger/carbon-fields.git", + "reference": "dd5663e14c6db365323b688dbae1cfbeaf14bee7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/htmlburger/carbon-fields/zipball/dd5663e14c6db365323b688dbae1cfbeaf14bee7", + "reference": "dd5663e14c6db365323b688dbae1cfbeaf14bee7", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "require-dev": { + "mockery/mockery": "^0.9.7", + "phpunit/phpunit": "~4.8" + }, + "type": "library", + "autoload": { + "psr-4": { + "Carbon_Fields\\": "core/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0-only" + ], + "authors": [ + { + "name": "htmlBurger", + "email": "wordpress@htmlburger.com", + "homepage": "https://htmlburger.com/", + "role": "Developer" + }, + { + "name": "Miroslav Mitev", + "email": "mmitev.2create@gmail.com", + "role": "Developer" + }, + { + "name": "Atanas Angelov", + "email": "atanas.angelov.dev@gmail.com", + "role": "Developer" + }, + { + "name": "Georgi Stoyanov", + "email": "stoyanov.gs@gmail.com", + "role": "Developer" + }, + { + "name": "Plamen Kostadinov", + "email": "pkostadinov.2create@gmail.com", + "homepage": "http://plasmen.info/", + "role": "Developer" + }, + { + "name": "Stanimir Panchev", + "email": "Stan4omir@gmail.com", + "role": "Developer" + }, + { + "name": "Marin Atanasov", + "email": "contact@marinatanasov.com", + "homepage": "http://marinatanasov.com/", + "role": "Developer" + }, + { + "name": "Siyan Panayotov", + "homepage": "http://siyanpanayotov.com/", + "role": "Developer" + }, + { + "name": "Peter Petrov", + "email": "peter.petrov89@gmail.com", + "role": "Developer" + }, + { + "name": "Stanimir Stoyanov", + "email": "stanimir.k.stoyanov@gmail.com", + "role": "Developer" + }, + { + "name": "Kaloyan Ivanov", + "email": "kaloyanxivanov@gmail.com", + "homepage": "http://vilepixels.com/", + "role": "Developer" + }, + { + "name": "Georgi Popov", + "homepage": "http://magadanski.com/", + "role": "Developer" + }, + { + "name": "German Velchev", + "email": "germozy@gmail.com", + "role": "Developer" + }, + { + "name": "Rashko Petrov", + "email": "brutalenemy666@gmail.com", + "homepage": "http://errorfactory.com/", + "role": "Developer" + }, + { + "name": "Alexander Panayotov", + "email": "alexander.panayotov@gmail.com", + "homepage": "http://alexanderpanayotov.com/", + "role": "Developer" + }, + { + "name": "Viktor Vasilev", + "email": "liberalcho@gmail.com", + "role": "Developer" + }, + { + "name": "Georgi Georgiev", + "email": "george.georgiev96@gmail.com", + "role": "Developer" + }, + { + "name": "Atanas Vasilev", + "email": "atanasvasilev91@gmail.com", + "role": "Developer" + } + ], + "description": "WordPress developer-friendly custom fields for post types, taxonomy terms, users, comments, widgets, options and more.", + "homepage": "http://carbonfields.net/", + "support": { + "docs": "http://carbonfields.net/docs/", + "email": "wordpress@htmlburger.com", + "issues": "https://github.com/htmlburger/carbon-fields/issues", + "source": "https://github.com/htmlburger/carbon-fields" + }, + "time": "2021-04-22T13:24:34+00:00" + }, + { + "name": "league/oauth2-client", + "version": "2.6.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/oauth2-client.git", + "reference": "badb01e62383430706433191b82506b6df24ad98" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/badb01e62383430706433191b82506b6df24ad98", + "reference": "badb01e62383430706433191b82506b6df24ad98", + "shasum": "" + }, + "require": { + "guzzlehttp/guzzle": "^6.0 || ^7.0", + "paragonie/random_compat": "^1 || ^2 || ^9.99", + "php": "^5.6 || ^7.0 || ^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.3", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpunit/phpunit": "^5.7 || ^6.0 || ^9.3", + "squizlabs/php_codesniffer": "^2.3 || ^3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-2.x": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\OAuth2\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alex Bilbie", + "email": "hello@alexbilbie.com", + "homepage": "http://www.alexbilbie.com", + "role": "Developer" + }, + { + "name": "Woody Gilk", + "homepage": "https://github.com/shadowhand", + "role": "Contributor" + } + ], + "description": "OAuth 2.0 Client Library", + "keywords": [ + "Authentication", + "SSO", + "authorization", + "identity", + "idp", + "oauth", + "oauth2", + "single sign on" + ], + "support": { + "issues": "https://github.com/thephpleague/oauth2-client/issues", + "source": "https://github.com/thephpleague/oauth2-client/tree/2.6.0" + }, + "time": "2020-10-28T02:03:40+00:00" + }, + { + "name": "paragonie/random_compat", + "version": "v9.99.100", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a", + "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a", + "shasum": "" + }, + "require": { + "php": ">= 7" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*", + "vimeo/psalm": "^1" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "polyfill", + "pseudorandom", + "random" + ], + "support": { + "email": "info@paragonie.com", + "issues": "https://github.com/paragonie/random_compat/issues", + "source": "https://github.com/paragonie/random_compat" + }, + "time": "2020-10-15T08:29:30+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client/tree/master" + }, + "time": "2020-06-29T06:28:15+00:00" + }, + { + "name": "psr/http-message", + "version": "1.0.1", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/master" + }, + "time": "2016-08-06T14:39:51+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "support": { + "issues": "https://github.com/ralouphie/getallheaders/issues", + "source": "https://github.com/ralouphie/getallheaders/tree/develop" + }, + "time": "2019-03-08T08:55:37+00:00" + }, + { + "name": "xeroapi/xero-php-oauth2", + "version": "2.6.0", + "source": { + "type": "git", + "url": "https://github.com/XeroAPI/xero-php-oauth2.git", + "reference": "b2fa507314f9388c2212cd564c9ec411ababc8e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/XeroAPI/xero-php-oauth2/zipball/b2fa507314f9388c2212cd564c9ec411ababc8e8", + "reference": "b2fa507314f9388c2212cd564c9ec411ababc8e8", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "firebase/php-jwt": "^5.0", + "guzzlehttp/guzzle": "^6.2 | ^7.0", + "league/oauth2-client": "^2.5.0", + "php": ">=5.6" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "~2.12", + "phpunit/phpunit": "^4.8", + "squizlabs/php_codesniffer": "~2.6" + }, + "type": "library", + "autoload": { + "psr-4": { + "XeroAPI\\XeroPHP\\": "lib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Xero API Team", + "homepage": "https://developer.xero.com" + } + ], + "description": "Xero official PHP SDK for oAuth2 generated with OpenAPI spec 3", + "homepage": "https://github.com/xeroapi/xero-php-oauth2", + "keywords": [ + "api", + "openapispec", + "php", + "rest", + "sdk", + "xero" + ], + "support": { + "issues": "https://github.com/XeroAPI/xero-php-oauth2/issues", + "source": "https://github.com/XeroAPI/xero-php-oauth2/tree/2.6.0" + }, + "time": "2021-06-01T21:04:37+00:00" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [], + "plugin-api-version": "2.1.0" +} diff --git a/storage.php b/storage.php new file mode 100644 index 0000000..ef7b1b7 --- /dev/null +++ b/storage.php @@ -0,0 +1,155 @@ +init_session(); + // } + } + + public function read_value() { + $this->oauth2state = carbon_get_theme_option("xero_oauth2state"); + $this->oauth2["token"] = carbon_get_theme_option("xero_token"); + $this->oauth2["refresh_token"] = carbon_get_theme_option("xero_refresh_token"); + $this->oauth2["expires"] = carbon_get_theme_option("xero_expires"); + $this->oauth2["tenant_id"] = carbon_get_theme_option("xero_tenant_id"); + $this->oauth2["id_token"] = carbon_get_theme_option("xero_id_token"); + + $this->oauth2['expires_human'] = $this->getExpiresHuman($this->oauth2["expires"]); + } + + public function init_session(){ + // session_start(); + } + + public function getSession() { + return $this->oauth2; + // return $_SESSION['oauth2']; + } + + public function startSession($token, $secret, $expires = null) + { + // session_start(); + } + + public function setToken($token, $expires = null, $tenantId, $refreshToken, $idToken) + { + // $_SESSION['oauth2'] = [ + // 'token' => $token, + // 'expires' => $expires, + // 'tenant_id' => $tenantId, + // 'refresh_token' => $refreshToken, + // 'id_token' => $idToken + // ]; + + $this->oauth2 = [ + 'token' => $token, + 'expires' => $expires, + 'tenant_id' => $tenantId, + 'refresh_token' => $refreshToken, + 'id_token' => $idToken, + 'expires_human' => $this->getExpiresHuman($expires) + ]; + + carbon_set_theme_option("xero_token", $token); + carbon_set_theme_option("xero_refresh_token", $refreshToken); + carbon_set_theme_option("xero_expires", $expires); + carbon_set_theme_option("xero_tenant_id", $tenantId); + carbon_set_theme_option("xero_id_token", $idToken); + carbon_set_theme_option("xero_expires_human", $this->getExpiresHuman($expires)); + + } + + public function getOauth2State() { + $this->oauth2state = carbon_get_theme_option("xero_oauth2state"); + return $this->oauth2state; + } + + public function setOauth2State($state) { + $this->oauth2state = $state; + carbon_set_theme_option("xero_oauth2state", $state); + } + + + private function getExpiresHuman($time_stamp) { + $expire = date("Y-m-d H:i:s", $time_stamp); + $utc_date = \DateTime::createFromFormat( + "Y-m-d H:i:s", + $expire, + new \DateTimeZone('UTC') + ); + + $sydney_date = $utc_date; + $sydney_date->setTimeZone(new \DateTimeZone('Australia/Sydney')); + $str = $sydney_date->format("Y-m-d H:i:s"); + return $str; + } + + public function getToken() + { + //If it doesn't exist or is expired, return null + // if (empty($this->getSession()) + // || ($_SESSION['oauth2']['expires'] !== null + // && $_SESSION['oauth2']['expires'] <= time()) + // ) { + // return null; + // } + // return $this->getSession(); + + if ( $this->oauth2['expires'] !== null && $this->oauth2['expires'] <= time() ) { + return null; + } + return $this->oauth2; + } + + public function getAccessToken() + { + //return $_SESSION['oauth2']['token']; + return $this->oauth2['token']; + } + + public function getRefreshToken() + { + // return $_SESSION['oauth2']['refresh_token']; + return $this->oauth2['refresh_token']; + } + + public function getExpires() + { + //return $_SESSION['oauth2']['expires']; + return $this->oauth2['expires']; + } + + public function getXeroTenantId() + { + //return $_SESSION['oauth2']['tenant_id']; + return $this->oauth2['tenant_id']; + } + + public function getIdToken() + { + // return $_SESSION['oauth2']['id_token']; + return $this->oauth2['id_token']; + } + + public function getHasExpired() + { + if (!empty($this->getSession())) + { + if(time() > $this->getExpires()) + { + return true; + } else { + return false; + } + } else { + return true; + } + } +} +?> \ No newline at end of file diff --git a/xero.php b/xero.php index cda6ac7..a7ad8e6 100644 --- a/xero.php +++ b/xero.php @@ -10,16 +10,304 @@ */ namespace Biukop; +require_once(dirname(__FILE__) . '/vendor/autoload.php'); +require_once (ABSPATH . 'wp-includes/pluggable.php'); +require_once('storage.php'); + +use Carbon_Fields\Container; +use Carbon_Fields\Field; class Xero { + + public $provider; + public $options = [ + 'scope' => ['openid email profile offline_access assets projects accounting.settings accounting.transactions accounting.contacts accounting.journals.read accounting.reports.read accounting.attachments'] + ]; + public $storage; + public $config; + public $apiInstance; + public $xeroTenantId; + public function __construct() { + add_action( 'after_setup_theme', array($this,'boot_carbon' )); + add_action( 'carbon_fields_register_fields', array($this, 'build_settings_page' )); + add_action( 'carbon_fields_container_activated', array($this, 'field_activated')); + add_action( 'parse_request', array($this, 'xero_callback')); + + add_shortcode( 'xero_org_name', array($this, 'xero_org_name')); + add_shortcode( 'xero_org_contacts', array($this, 'xero_org_contacts')); + add_shortcode( 'xero_org_invoices', array($this, 'xero_org_invoices')); + add_action('init', array($this, "xero_init")); + add_action('plugins_loaded', array($this, load_storage)); + // $this->xero_init(); + $this->storage = new StorageClass(); } public function xero_init() { - //wp_set_password("admin", 2623); - // echo "password set"; + $this->provider = new \League\OAuth2\Client\Provider\GenericProvider([ + 'clientId' => '85B4A7B8AF35442CBB9943799B402FE1', + 'clientSecret' => 'bNSYPDdBTGNMVF7kB56iOLhEmqQTlsitwH6cc4kQy83XW3iO', + 'redirectUri' => 'https://procomhost.com/?xero_callback', + 'urlAuthorize' => 'https://login.xero.com/identity/connect/authorize', + 'urlAccessToken' => 'https://identity.xero.com/connect/token', + 'urlResourceOwnerDetails' => 'https://api.xero.com/api.xro/2.0/Organisation' + ]); + } + + public function load_storage() { + //$this->storage->read_value(); + } + + public function boot_carbon() { + \Carbon_Fields\Carbon_Fields::boot(); + } + + + function build_settings_page() { + Container::make( 'theme_options', __( 'Xero Integration' ) ) + ->set_page_parent( 'options-general.php' ) + ->add_fields( array( + Field::make( 'text', 'xero_oauth2state', 'Xero Oauth2 State' ) + ->set_attribute( 'maxLength', 2048) + ->set_attribute( 'readOnly', true) + ->set_default_value($this->storage->getOauth2State()), + Field::make( 'text', 'xero_token', 'Xero Token' ) + ->set_attribute( 'maxLength', 2048) + ->set_attribute( 'readOnly', true) + ->set_default_value($this->storage->getSession()['token']), + Field::make( 'text', 'xero_refresh_token', 'RefreshToken' ) + ->set_attribute( 'readOnly', true) + ->set_default_value( $this->storage->getSession()['refresh_token'] ), + Field::make( 'text', 'xero_id_token', 'ID Token' ) + ->set_attribute( 'readOnly', true) + ->set_default_value( $this->storage->getSession()['id_token'] ), + Field::make( 'text', 'xero_tenant_id', 'Tenant ID' ) + ->set_attribute( 'readOnly', true) + ->set_default_value( $this->storage->getSession()['tenant_id'] ), + Field::make( 'text', 'xero_expires', 'Expires' ) + ->set_attribute( 'readOnly', true) + ->set_default_value( $this->storage->getSession()['expires'] ), + Field::make( 'text', 'xero_expires_human', 'Expires' ) + ->set_attribute( 'readOnly', true) + ->set_default_value( $this->storage->getSession()['expires_human'] ), + + Field::make( 'html', 'crb_information_text' ) + ->set_html( '

Connect/Reconnect

if the above field is empty, + or the expire date looks suspicous, please reconnect to Xero

+
+ + +
' ) + ) ); + + $this->storage->read_value(); + } + + + function field_activated() { + $this->storage->read_value(); + $xeroTenantId = (string)$this->storage->getSession()['tenant_id']; + if ( $xeroTenantId == "" ){ + $this->startAuthorization(); + }else{ + $this->refresh_token(); + } + } + + public function startAuthorization() { + // This returns the authorizeUrl with necessary parameters applied (e.g. state). + $authorizationUrl = $this->provider->getAuthorizationUrl($this->options); + + // Save the state generated for you and store it to the session. + // For security, on callback we compare the saved state with the one returned to ensure they match. + $this->storage->setOauth2State($this->provider->getState()); + + // Redirect the user to the authorization URL. + header('Location: ' . $authorizationUrl); + exit(); + } + + + function xero_callback() { + if( isset($_GET['xero_reauth']) ) { + $this->startAuthorization(); + return; + } + if( ! isset($_GET['xero_callback']) ) { + return ; + } + // If we don't have an authorization code then get one + if (!isset($_GET['code'])) { + echo "Something went wrong, no authorization code found"; + exit("Something went wrong, no authorization code found"); + + // Check given state against previously stored one to mitigate CSRF attack + } elseif (empty($_GET['state']) || ($_GET['state'] !== $this->storage->getOauth2State() )) { + echo "Invalid State"; + $this->storage->setOauth2State(""); + exit('Invalid state'); + } else { + + try { + // Try to get an access token using the authorization code grant. + $accessToken = $this->provider->getAccessToken('authorization_code', [ + 'code' => $_GET['code'] + ]); + + $config = \XeroAPI\XeroPHP\Configuration::getDefaultConfiguration()->setAccessToken( (string)$accessToken->getToken() ); + $identityInstance = new \XeroAPI\XeroPHP\Api\IdentityApi( + new \GuzzleHttp\Client(), + $config + ); + + $result = $identityInstance->getConnections(); + + // Save my tokens, expiration tenant_id + $this->storage->setToken( + $accessToken->getToken(), + $accessToken->getExpires(), + $result[0]->getTenantId(), + $accessToken->getRefreshToken(), + $accessToken->getValues()["id_token"] + ); + + // related to $this->build_settings_page + $url = "/wp-admin/options-general.php?page=crb_carbon_fields_container_xero_integration.php"; + header('Location: ' . $url); + exit(); + + } catch (\League\OAuth2\Client\Provider\Exception\IdentityProviderException $e) { + echo "Xero Callback failed"; + exit(); + } + } + } + + function refresh_token() { + $this->storage->read_value(); + $this->xeroTenantId = (string)$this->storage->getSession()['tenant_id']; + + if ($this->storage->getHasExpired()) { + $provider = new \League\OAuth2\Client\Provider\GenericProvider([ + 'clientId' => '85B4A7B8AF35442CBB9943799B402FE1', + 'clientSecret' => 'bNSYPDdBTGNMVF7kB56iOLhEmqQTlsitwH6cc4kQy83XW3iO', + 'redirectUri' => 'https://procomhost.com/test/xero-php-oauth2-starter/callback.php', + 'urlAuthorize' => 'https://login.xero.com/identity/connect/authorize', + 'urlAccessToken' => 'https://identity.xero.com/connect/token', + 'urlResourceOwnerDetails' => 'https://api.xero.com/api.xro/2.0/Organisation' + ]); + + $newAccessToken = $provider->getAccessToken('refresh_token', [ + 'refresh_token' => $this->storage->getRefreshToken() + ]); + + // Save my token, expiration and refresh token + $this->storage->setToken( + $newAccessToken->getToken(), + $newAccessToken->getExpires(), + $this->xeroTenantId, + $newAccessToken->getRefreshToken(), + $newAccessToken->getValues()["id_token"] ); + } + + if ( $this->apiInstance == null ){ + $this->config = \XeroAPI\XeroPHP\Configuration::getDefaultConfiguration()->setAccessToken( (string)$this->storage->getSession()['token'] ); + $this->apiInstance = new \XeroAPI\XeroPHP\Api\AccountingApi( + new \GuzzleHttp\Client(), + $this->config + ); + } + } + + public function xero_org_name() { + ini_set('display_errors', 'On'); + $this->refresh_token(); + + $apiResponse = $this->apiInstance->getOrganisations($this->xeroTenantId); + $message = 'Organisation Name: ' . $apiResponse->getOrganisations()[0]->getName() . " "; + return $message; + } + + public function xero_org_contacts() { + ini_set('display_errors', 'On'); + $this->refresh_token(); + + $apiResponse = $this->apiInstance->getContacts($this->xeroTenantId); + $contacts = $apiResponse->getContacts(); + $message = " "; + $message .= " + + + + + + "; + $count = 1; + foreach ( $contacts as $c) { + + $group = ""; + foreach ( $c->getContactGroups() as $g) { + $group .= $g->getName() . " - " . $g->getStatus() . "
"; + } + + $message .= " " . + " " . + " " . + " " . + " " . + " " . + " " . + ""; + } + $message .= "
# unique-id name Supplier Customer Group Status
" . $count ++ . " " . $c->getContactId() . " " . $c->getName() . " " . ( $c->getIsSupplier() ? "yes" : " - " ) . " " . ( $c->getIsCustomer() ? "yes" : " - " ) . " " . $group . " " . $c->getContactStatus() . "
"; + return $message; + } + + public function xero_org_invoices() { + ini_set('display_errors', 'On'); + $this->refresh_token(); + + $apiResponse = $this->apiInstance->getInvoices($this->xeroTenantId); + $invoices = $apiResponse->getInvoices(); + + $message = " "; + $message .= " + + + + + + "; + $count = 1; + + foreach ( $invoices as $c) { + $strDate = ""; + $d = $c->getDate(); + if ( $d != null) { + $da = $c->getDateAsDate(); + $strDate = $da->format("Y-m-d"); + } else { + $strDate = $d; + } + + $message .= " " . + " " . + " " . + " " . + " " . + " " . + " " . + ""; + } + $message .= "
# invoice id date contact amount Type Status
" . $count ++ . " " . $c->getInvoiceNumber() . " " . $strDate . " " . $c->getContact()->getName() . " " . $c->getTotal() . " " . $c->getType() . " " . $c->getStatus() . "
"; + return $message; + } + } -$b = new Xero(); \ No newline at end of file + + +$b = new Xero(); +