diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8a95a53 --- /dev/null +++ b/.gitignore @@ -0,0 +1,49 @@ +### Node template +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directory +# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git- +node_modules + + +### Composer template +composer.phar +vendor/ + +# Commit your application's lock file http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file +# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file +# composer.lock + +### Release +release/ + +### Docs +docs/ + +### Compiled translations +*.mo + +### CI target +wordpress/ diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..3d6f933 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +language: php + +php: + - 5.3 + - 5.4 + +before_install: npm install -g grunt-cli +install: npm install +script: grunt test diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3b7a96d..d192e04 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -38,6 +38,8 @@ We'll integrate your contributions a few weeks before release. Documentation ------------- -The documentation is maintained on the [Wiki](https://github.com/GPCsolutions/doliwoo/wiki). +The main documentation is maintained on the [Wiki](https://github.com/GPCsolutions/doliwoo/wiki). Access is currently restricted but you can suggest edits in the [Issues](https://github.com/GPCsolutions/doliwoo/issues). + +Code documentation can be generated with ```grunt phpdoc``` and is output into the ./docs subdirectory. diff --git a/Gruntfile.js b/Gruntfile.js new file mode 100644 index 0000000..e652dc1 --- /dev/null +++ b/Gruntfile.js @@ -0,0 +1,218 @@ +module.exports = function (grunt) { + // Load tasks + require('load-grunt-tasks')(grunt); + + // Display task timing + require('time-grunt')(grunt); + + // Project configuration + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + paths: { + // PHP assets + php: { + files_std: [ + '*.php', + '**/*.php', + '!assets/**/*.php', + '!docs/**/*.php', + '!node_modules/**/*.php', + '!release/**/*.php', + '!vendor/**/*.php', + '!wordpress/**/*.php' + ], // Standard file match + files: '<%= paths.php.files_std %>', // Dynamic file match + exclude: [ + 'assets/.*', + 'composer.json', + 'composer.lock', + 'CONTRIBUTING.md', + 'docs/.*', + '.git/.*', + '.gitignore', + '.gitmodules', + 'Gruntfile.js', + 'node_modules/.*', + 'package.json', + 'README.md', + 'release/.*', + '.sensiolabs.yml', + '.travis.yml', + '.tx', + 'vendor/.*', + 'wordpress/.*' + ] // PHP regex match + } + }, + phpcs: { + application: { + dir: '<%= paths.php.files %>' + }, + options: { + bin: 'vendor/bin/phpcs', + standard: 'Wordpress-Extra' + } + }, + phplint: { + options: { + phpArgs: { + '-lf': null + } + }, + all: { + src: '<%= paths.php.files %>' + } + }, + phpdoc: { + target: { + src: [ + 'doliwoo.php', + 'includes' + ], + dest: 'docs' + } + }, + makepot: { + target: { + options: { + mainFile: 'doliwoo.php', + exclude: '<%= paths.php.exclude %>', + type: 'wp-plugin', + potHeaders: { + poedit: true, + 'report-msgid-bugs-to': 'https://github.com/GPCsolutions/doliwoo/issues' + } + } + } + }, + po2mo: { + files: { + src: 'languages/*.po', + expand: true + } + }, + clean: { + main: ['release/<%= pkg.version %>'] + }, + copy: { + // Copy the plugin to a versioned release directory + main: { + src: [ + '**', + '!assets/**', + '!wordpress/**', + '!composer.json', + '!composer.lock', + '!CONTRIBUTING.md', + '!docs/**', + '!.git/**', + '!.gitignore', + '!.gitmodules', + '!Gruntfile.js', + '!node_modules/**', + '!package.json', + '!README.md', + '!release/**', + '!.sensiolabs.yml', + '!.travis.yml', + '!.tx', + '!vendor/**' + ], + dest: 'release/<%= pkg.version %>/' + } + }, + compress: { + main: { + options: { + mode: 'zip', + archive: './release/doliwoo-v<%= pkg.version %>.zip' + }, + expand: true, + cwd: 'release/<%= pkg.version %>/', + src: ['**/*'], + dest: 'doliwoo/' + } + }, + exec: { + txpush: { + cmd: 'tx push -s' + }, + txpull: { + cmd: 'tx pull -a' + } + }, + wp_readme_to_markdown: { + main: { + files: { + 'README.md': 'readme.txt' + } + } + }, + checkwpversion: { + check: { //Check plug-in version and stable tag match + version1: 'plugin', + version2: 'readme', + compare: '>=' + }, + check2: { //Check plug-in version and package.json match + version1: 'plugin', + version2: '<%= pkg.version %>', + compare: '==' + } + }, + "sync-json": { + options: { + indent: 2, + include: [ + 'description', + 'keywords', + 'homepage', + 'license' + ] + }, + composer: { + files: { + 'composer.json': 'package.json' + } + } + } + }); + + grunt.registerTask('default', [ + 'test', + 'sync-json', + 'wp_readme_to_markdown', + 'phpdoc' + ]); + + grunt.registerTask('test', [ + 'composer:update', + 'phpcs', + 'phplint', + 'checkwpversion' + ]); + + grunt.registerTask('potupdate', [ + 'makepot', + 'exec:txpush' + ]); + + grunt.registerTask('poupdate', [ + 'exec:txpull' + ]); + + grunt.registerTask('i18n', [ + 'potupdate', + 'poupdate', + 'po2mo' + ]); + + grunt.registerTask('release', [ + 'default', + 'i18n', + 'clean', + 'copy', + 'compress' + ]); + +}; diff --git a/README.md b/README.md new file mode 100644 index 0000000..e23c4e0 --- /dev/null +++ b/README.md @@ -0,0 +1,117 @@ +# DoliWoo # +**Contributors:** GPC.solutions +**Tags:** dolibarr, woocommerce, ecommerce, erp, integration +**Author URI:** https://gpcsolutions.fr +**Plugin URI:** https://gpcsolutions.github.io/doliwoo +**Requires at least:** 3.7.1 +**Tested up to:** 3.7.1 +**Stable tag:** 1.0.0 +**License:** GPL-3.0+ +**License URI:** http://www.gnu.org/licenses/gpl-3.0.html + +Integrate Dolibarr with a WooCommerce shop. + +## Description ## +Doliwoo allows integration of Dolibarr into WooCommerce. + +It leverages Dolibarr webservices feature to exchange data. + +### Features ### + +**Dolibarr to WooCommerce** + +* Periodic sync of products informations including images and stock informations +* Link customers to existing thirdparties + +**WooCommerce to Dolibarr** + +* Create thirdparties +* Create customer orders + +**Known missing (TODO)** + +* Products stock informations resync on orders +* Invoicing +* Payments +* Multiple languages products management + +**Known issues** + +WooCommerce VAT management vastly differs from Dolibarr and we need equivalence tables. +Only French and italian equivalence tables are shipped at the moment. + +### Requirements ### + +**PHP extensions** + +* SOAP +* OpenSSL + +**WordPress plugins** + +* Woocommerce >= 2.0.0 + +**Dolibarr** + +* HTTPS access with a valid certificate +* Dolibarr >= 3.4.0 +* Modules: + * Webservices + * Thirdparties + * Products + * Categories (Products) + * Orders + +## Installation ## + +1. Make sure the WooCommerce plugin is installed into your WordPress +2. Extract the zip file to the 'wp-content/plugins/' directory of your WordPress installation +3. Activate the plugin from 'Plugins' WordPress settings page +4. Go to 'WooCommerce' 'Settings' under the 'Integration' tab and configure the 'Doliwoo' section + +## Frequently Asked Questions ## + +### Is this plugin stable and useable in a production environment? ### + +NO! This is beta code. This project started as an internal proof of concept and has just been reviewed. +But you're very welcome to test it on a pre-production environment. + +### OK, so how can I make it happen then? ### + +You can help by testing, providing detailed bug reports, documentation or even code. +**Alternatively, you can buy paid support and/or development services from us:** [GPC.solutions](https://gpcsolutions.fr). + +### Why do I need to use HTTPS with a good known SSL certificate? ### + +Otherwise SOAP requests will fail. +This is a security feature to make sure your important data is properly encrypted in transit between WooCommerce and Dolibarr. +You may allow insecure requests by tweaking the source code if you know what you're doing but we don't recommend that. + +## Screenshots ## + +### 1. The configuration page ### +![The configuration page](/assets/screenshot-1.png) + + +## Changelog ## + +### 1.0.0 ### + +* First stable release +* Polished errors reporting +* Polished interface +* Basic international VAT rates management + +### 0.0.1 ### + +* First beta release +* Periodically sync products from a Dolibarr category +* Use a generic thirdparty for sales without user creation +* Create or reuse a thirdparty for sales with a logged in user +* Create an order into Dolibarr for each sale + +## Upgrade Notice ## + +### 1.0.0 ### + +Stable release diff --git a/assets/banner-1544x500.png b/assets/banner-1544x500.png index e69de29..c3451d5 100644 Binary files a/assets/banner-1544x500.png and b/assets/banner-1544x500.png differ diff --git a/assets/banner-772x250.png b/assets/banner-772x250.png index e69de29..f8afae1 100644 Binary files a/assets/banner-772x250.png and b/assets/banner-772x250.png differ diff --git a/assets/screenshot-1.png b/assets/screenshot-1.png index e69de29..0c40ad5 100644 Binary files a/assets/screenshot-1.png and b/assets/screenshot-1.png differ diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..4e3bb1c --- /dev/null +++ b/composer.json @@ -0,0 +1,58 @@ +{ + "name": "gpcsolutions/doliwoo", + "description": "Integrate Dolibarr with a WooCommerce shop.", + "type": "wordpress-plugin", + "keywords": [ + "wordpress", + "dolibarr", + "woocommerce", + "ecommerce", + "erp", + "integration" + ], + "homepage": "https://gpcsolutions.github.io/doliwoo", + "license": "GPL-3.0+", + "authors": [ + { + "name": "GPC.solutions", + "email": "contact@gpcsolutions.fr", + "homepage": "https://gpcsolutions.fr" + } + ], + "support": { + "issues": "https://github.com/GPCsolutions/doliwoo/issues", + "wiki": "https://github.com/GPCsolutions/doliwoo/wiki", + "source": "https://github.com/GPCsolutions/doliwoo" + }, + "require": { + "composer/installers": ">=1.0.6", + "php": ">=5.3.0", + "ext-openssl": "*", + "johnpbloch/wordpress": ">=3.7.1", + "wpackagist-plugin/woocommerce": ">=2.0.0" + }, + "require-dev": { + "wp-coding-standards/wpcs": "dev-master" + }, + "repositories": [ + { + "type": "composer", + "url": "http://wpackagist.org" + } + ], + "extra": { + "installer-paths": { + "wordpress/wp-content/plugins/{$name}": [ + "wpackagist-plugin/woocommerce" + ] + } + }, + "scripts": { + "post-install-cmd": [ + "vendor/bin/phpcs --config-set installed_paths vendor/wp-coding-standards/wpcs" + ], + "post-update-cmd": [ + "vendor/bin/phpcs --config-set installed_paths vendor/wp-coding-standards/wpcs" + ] + } +} \ No newline at end of file diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..063ebdf --- /dev/null +++ b/composer.lock @@ -0,0 +1,335 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "556747e74bd6aa3b56d40bb22874eb5a", + "packages": [ + { + "name": "composer/installers", + "version": "v1.0.21", + "source": { + "type": "git", + "url": "https://github.com/composer/installers.git", + "reference": "d64e23fce42a4063d63262b19b8e7c0f3b5e4c45" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/installers/zipball/d64e23fce42a4063d63262b19b8e7c0f3b5e4c45", + "reference": "d64e23fce42a4063d63262b19b8e7c0f3b5e4c45", + "shasum": "" + }, + "replace": { + "roundcube/plugin-installer": "*", + "shama/baton": "*" + }, + "require-dev": { + "composer/composer": "1.0.*@dev", + "phpunit/phpunit": "4.1.*" + }, + "type": "composer-installer", + "extra": { + "class": "Composer\\Installers\\Installer", + "branch-alias": { + "dev-master": "1.0-dev" + } + }, + "autoload": { + "psr-0": { + "Composer\\Installers\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Kyle Robinson Young", + "email": "kyle@dontkry.com", + "homepage": "https://github.com/shama" + } + ], + "description": "A multi-framework Composer library installer", + "homepage": "http://composer.github.com/installers/", + "keywords": [ + "Craft", + "Dolibarr", + "Hurad", + "MODX Evo", + "OXID", + "SMF", + "Thelia", + "WolfCMS", + "agl", + "aimeos", + "annotatecms", + "bitrix", + "cakephp", + "chef", + "codeigniter", + "concrete5", + "croogo", + "dokuwiki", + "drupal", + "elgg", + "fuelphp", + "grav", + "installer", + "joomla", + "kohana", + "laravel", + "lithium", + "magento", + "mako", + "mediawiki", + "modulework", + "moodle", + "phpbb", + "piwik", + "ppi", + "puppet", + "roundcube", + "shopware", + "silverstripe", + "symfony", + "typo3", + "wordpress", + "zend", + "zikula" + ], + "time": "2015-02-18 17:17:01" + }, + { + "name": "johnpbloch/wordpress", + "version": "4.1.1", + "source": { + "type": "git", + "url": "https://github.com/johnpbloch/wordpress.git", + "reference": "b6a0e3c2ef178f97ce8b709897fd4411420b3ccb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/johnpbloch/wordpress/zipball/b6a0e3c2ef178f97ce8b709897fd4411420b3ccb", + "reference": "b6a0e3c2ef178f97ce8b709897fd4411420b3ccb", + "shasum": "" + }, + "require": { + "johnpbloch/wordpress-core-installer": "~0.2", + "php": ">=5.3.2" + }, + "type": "wordpress-core", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0+" + ], + "authors": [ + { + "name": "WordPress Community", + "homepage": "http://wordpress.org/about/" + } + ], + "description": "WordPress is web software you can use to create a beautiful website or blog.", + "homepage": "http://wordpress.org/", + "keywords": [ + "blog", + "cms" + ], + "time": "2015-02-18 22:16:06" + }, + { + "name": "johnpbloch/wordpress-core-installer", + "version": "0.2.0", + "source": { + "type": "git", + "url": "https://github.com/johnpbloch/wordpress-core-installer.git", + "reference": "a4c08e91be99e858c7778c2f52a4d73820147c2e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/johnpbloch/wordpress-core-installer/zipball/a4c08e91be99e858c7778c2f52a4d73820147c2e", + "reference": "a4c08e91be99e858c7778c2f52a4d73820147c2e", + "shasum": "" + }, + "require": { + "composer-plugin-api": "1.0.0" + }, + "conflict": { + "composer/installers": "<1.0.6" + }, + "require-dev": { + "composer/composer": "1.0.*@dev" + }, + "type": "composer-plugin", + "extra": { + "class": "johnpbloch\\Composer\\WordPressCorePlugin" + }, + "autoload": { + "psr-0": { + "johnpbloch\\Composer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "GPL-2.0+" + ], + "authors": [ + { + "name": "John P. Bloch", + "email": "me@johnpbloch.com" + } + ], + "description": "A custom installer to handle deploying WordPress with composer", + "time": "2013-09-09 15:04:54" + }, + { + "name": "wpackagist-plugin/woocommerce", + "version": "2.3.5", + "source": { + "type": "svn", + "url": "http://plugins.svn.wordpress.org/woocommerce/", + "reference": "tags/2.3.5" + }, + "dist": { + "type": "zip", + "url": "http://downloads.wordpress.org/plugin/woocommerce.2.3.5.zip", + "reference": null, + "shasum": null + }, + "require": { + "composer/installers": "~1.0" + }, + "type": "wordpress-plugin", + "homepage": "https://wordpress.org/plugins/woocommerce/" + } + ], + "packages-dev": [ + { + "name": "squizlabs/php_codesniffer", + "version": "2.3.0", + "source": { + "type": "git", + "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", + "reference": "5046b0e01c416fc2b06df961d0673c85bcdc896c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/5046b0e01c416fc2b06df961d0673c85bcdc896c", + "reference": "5046b0e01c416fc2b06df961d0673c85bcdc896c", + "shasum": "" + }, + "require": { + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.1.2" + }, + "bin": [ + "scripts/phpcs", + "scripts/phpcbf" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "classmap": [ + "CodeSniffer.php", + "CodeSniffer/CLI.php", + "CodeSniffer/Exception.php", + "CodeSniffer/File.php", + "CodeSniffer/Fixer.php", + "CodeSniffer/Report.php", + "CodeSniffer/Reporting.php", + "CodeSniffer/Sniff.php", + "CodeSniffer/Tokens.php", + "CodeSniffer/Reports/", + "CodeSniffer/Tokenizers/", + "CodeSniffer/DocGenerators/", + "CodeSniffer/Standards/AbstractPatternSniff.php", + "CodeSniffer/Standards/AbstractScopeSniff.php", + "CodeSniffer/Standards/AbstractVariableSniff.php", + "CodeSniffer/Standards/IncorrectPatternException.php", + "CodeSniffer/Standards/Generic/Sniffs/", + "CodeSniffer/Standards/MySource/Sniffs/", + "CodeSniffer/Standards/PEAR/Sniffs/", + "CodeSniffer/Standards/PSR1/Sniffs/", + "CodeSniffer/Standards/PSR2/Sniffs/", + "CodeSniffer/Standards/Squiz/Sniffs/", + "CodeSniffer/Standards/Zend/Sniffs/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "lead" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "http://www.squizlabs.com/php-codesniffer", + "keywords": [ + "phpcs", + "standards" + ], + "time": "2015-03-04 02:07:03" + }, + { + "name": "wp-coding-standards/wpcs", + "version": "dev-master", + "source": { + "type": "git", + "url": "https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards.git", + "reference": "e68ce329fee8efcee8891327f3e42dcacf0f001c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/WordPress-Coding-Standards/WordPress-Coding-Standards/zipball/e68ce329fee8efcee8891327f3e42dcacf0f001c", + "reference": "e68ce329fee8efcee8891327f3e42dcacf0f001c", + "shasum": "" + }, + "require": { + "squizlabs/php_codesniffer": "~2.0" + }, + "type": "library", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "X-Team", + "homepage": "http://x-team.com/" + }, + { + "name": "Contributors", + "homepage": "https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer rules (sniffs) to enforce WordPress coding conventions", + "keywords": [ + "phpcs", + "standards", + "wordpress" + ], + "time": "2014-12-24 09:37:55" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": { + "wp-coding-standards/wpcs": 20 + }, + "prefer-stable": false, + "prefer-lowest": false, + "platform": { + "php": ">=5.3.0", + "ext-openssl": "*" + }, + "platform-dev": [] +} diff --git a/doliwoo.php b/doliwoo.php index 7a1a73e..0dd49cf 100644 --- a/doliwoo.php +++ b/doliwoo.php @@ -3,9 +3,10 @@ Plugin Name: DoliWoo Plugin URI: http://gpcsolutions.github.io/doliwoo Description: Dolibarr WooCommerce integration -Version: 0.0.1 +Version: 1.0.0 Author: GPC.solutions -License: GPL3 +Author URI: https://gpcsolutions.fr +License: GPL-3.0+ Text Domain: doliwoo Domain Path: /languages */ @@ -29,7 +30,7 @@ */ /** - * DoliWoo plugin + * DoliWoo plugin. * * Dolibarr WooCommerce integration. * @@ -40,103 +41,115 @@ exit; // Exit if accessed directly } -load_plugin_textdomain( 'doliwoo', +load_plugin_textdomain( + 'doliwoo', false, - dirname( plugin_basename( __FILE__ ) ) . '/languages/' ); + dirname( plugin_basename( __FILE__ ) ) . '/languages/' +); // Check required extensions -if ( false === extension_loaded( 'soap' ) - && false === extension_loaded( 'openssl' ) -) { - echo __( 'This plugin needs SOAP and OpenSSL PHP extensions.' ); +if ( false === extension_loaded( 'soap' ) && false === extension_loaded( 'openssl' ) ) { + esc_html_e( __( 'This plugin needs SOAP and OpenSSL PHP extensions.', 'doliwoo' ) ); exit; } if ( false === extension_loaded( 'soap' ) ) { - echo __( 'This plugin needs SOAP PHP extension.' ); + esc_html_e( __( 'This plugin needs SOAP PHP extension.', 'doliwoo' ) ); exit; } if ( false === extension_loaded( 'openssl' ) ) { - echo __( 'This plugin needs OpenSSL PHP extension.' ); + esc_html_e( __( 'This plugin needs OpenSSL PHP extension.', 'doliwoo' ) ); exit; } // Make sure the settings class is available -if ( ! class_exists( 'WC_Integration_Doliwoo_Settings' ) ) : +if ( ! class_exists( 'Doliwoo_WC_Integration' ) ) : // If WooCommerce is active - if ( in_array( 'woocommerce/woocommerce.php', - apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) { + if ( in_array( + 'woocommerce/woocommerce.php', + apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) + ) ) { if ( ! class_exists( 'Doliwoo' ) ) { /** - * Class Doliwoo - * * Dolibarr Integration for WooCommerce */ class Doliwoo { - /** @var WC_Integration_Doliwoo_Settings Doliwoo Settings */ + /** @var Doliwoo_WC_Integration Doliwoo Settings */ public $settings; /** @var array SOAP authentication parameters */ public $ws_auth = array(); - /** @var WC_Tax_Doliwoo WooCommerce taxes informations */ - public $taxes; - - /** @var Woocomerce_Parameters custom parameters */ + /** @var Doliwoo_WC_Params custom parameters */ public $woocommerce_parameters; - /** @var Dolibarr external requests */ + /** @var Doliwoo_Dolibarr external requests */ public $dolibarr; /** - * Constructor + * DoliWoo plugin */ public function __construct() { - require_once 'includes/class-doliwoo-parameters.php'; + require_once 'includes/class-wc-params.php'; require_once 'includes/class-dolibarr.php'; - $this->woocommerce_parameters = new Woocomerce_Parameters(); - $this->dolibarr = new Dolibarr(); + $this->woocommerce_parameters = new Doliwoo_WC_Params(); + $this->dolibarr = new Doliwoo_Dolibarr(); // Initialize plugin settings add_action( 'plugins_loaded', array( $this, 'init' ) ); - add_action( 'woocommerce_loaded', - array( &$this->dolibarr, 'set_woocommerce' ) ); + // Add a link to settings + add_filter( + 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_action_links' ) + ); + + // Setup dolibarr environment + add_action( 'woocommerce_loaded', array( &$this->dolibarr, 'set_woocommerce' ) ); + add_action( 'woocommerce_init', array( $this, 'set_settings' ) ); // Create custom tax classes and VAT rates on plugin settings saved - add_action( 'woocommerce_settings_saved', - array( &$this->taxes, 'create_custom_tax_classes' ) ); + add_action( 'woocommerce_settings_saved', array( &$this->dolibarr->taxes, 'create_custom_tax_classes' ) ); // Import Dolibarr products on plugin settings saved - add_action( 'woocommerce_settings_saved', - array( &$this->dolibarr, 'dolibarr_import_products' ) ); + add_action( 'woocommerce_settings_saved', array( &$this->dolibarr, 'dolibarr_import_products' ) ); + + // Reschedule products imporrt + add_action( 'woocommerce_settings_saved', array( $this, 'reschedule_import_products' ) ); - // Hook on woocommerce_checkout_process to create a Dolibarr order using WooCommerce order data - add_action( 'woocommerce_checkout_order_processed', - array( &$this->dolibarr, 'dolibarr_create_order' ) ); + // Create a Dolibarr order on each WooCommerce order + add_action( + 'woocommerce_checkout_order_processed', + array( &$this->dolibarr, 'dolibarr_create_order' ) + ); + + // Add Dolibarr import products hook + add_action( 'import_products', array( &$this->dolibarr, 'dolibarr_import_products' ) ); + + // Dolibarr ID User admin custom meta + add_filter( 'manage_users_columns', array( &$this->woocommerce_parameters, 'user_columns' ) ); + add_action( 'show_user_profile', array( &$this->woocommerce_parameters, 'customer_meta_fields' ) ); + add_action( 'edit_user_profile', array( &$this->woocommerce_parameters, 'customer_meta_fields' ) ); + add_action( + 'personal_options_update', + array( &$this->woocommerce_parameters, 'save_customer_meta_fields' ) + ); + add_action( + 'edit_user_profile_update', + array( &$this->woocommerce_parameters, 'save_customer_meta_fields' ) + ); + add_action( + 'manage_users_custom_column', + array( &$this->woocommerce_parameters, 'user_column_values' ), + 10, // Prio + 3 // Args count + ); // Schedule the import of product data from Dolibarr - add_action( 'wp', - array( &$this, 'schedule_import_products' ) ); - add_action( 'import_products', - array( &$this->dolibarr, 'dolibarr_import_products' ) ); - - // Dolibarr ID custom field - add_filter( 'manage_users_columns', - array( &$this->woocommerce_parameters, 'user_columns' ) ); - add_action( 'show_user_profile', - array( &$this->woocommerce_parameters, 'customer_meta_fields' ) ); - add_action( 'edit_user_profile', - array( &$this->woocommerce_parameters, 'customer_meta_fields' ) ); - add_action( 'personal_options_update', - array( &$this->woocommerce_parameters, 'save_customer_meta_fields' ) ); - add_action( 'edit_user_profile_update', - array( &$this->woocommerce_parameters, 'save_customer_meta_fields' ) ); - add_action( 'manage_users_custom_column', - array( &$this->woocommerce_parameters, 'user_column_values' ), 10, 3 ); + register_activation_hook( __FILE__, 'activation' ); + register_deactivation_hook( __FILE__, 'deactivation' ); } /** @@ -146,17 +159,36 @@ public function __construct() { */ public function init() { - require_once 'includes/class-tax-doliwoo.php'; + require_once 'includes/class-wc-tax.php'; // Checks if WooCommerce is installed. if ( class_exists( 'WC_Integration' ) ) { // Include our integration class. - require_once 'includes/settings.php'; + require_once 'includes/class-wc-integration.php'; // Register the integration. - add_filter( 'woocommerce_integrations', - array( $this, 'add_integration' ) ); + add_filter( 'woocommerce_integrations', array( $this, 'add_integration' ) ); } - $this->taxes = new WC_Tax_Doliwoo(); + $this->dolibarr->taxes = new Doliwoo_WC_Tax(); + } + + /** + * On plugin activation + * + * @return void + */ + public function activation() { + // Schedule product import with a sensible default + wp_schedule_event( time(), 'daily', 'import_products' ); + } + + /** + * On plugin deactivation + * + * @return void + */ + public function deactivation() { + // Unschedule product import + wp_clear_scheduled_hook( 'import_products' ); } /** @@ -167,49 +199,61 @@ public function init() { * @return string[] WooCommerce integrations */ public function add_integration( $integrations ) { - $integrations[] = 'WC_Integration_Doliwoo_Settings'; + $integrations[] = 'Doliwoo_WC_Integration'; return $integrations; } /** - * Schedules the daily import of Dolibarr products - * - * @access public + * Reschedules the automatic import of Dolibarr products * * @return void */ - public function schedule_import_products() { + public function reschedule_import_products() { $delay = $this->settings->delay_update; - if ( ! wp_next_scheduled( 'import_products' ) ) { - wp_schedule_event( time(), $delay, 'import_products' ); - } + wp_clear_scheduled_hook( 'import_products' ); + wp_schedule_event( time(), $delay, 'import_products' ); } /** - * Extract settings from WooCommerce integration settings + * Show action links on the plugin screen. + * + * @param mixed $links Plugin Action links + * @return array + */ + public static function plugin_action_links( $links ) { + $action_links = array( + 'settings' => '' . esc_attr( + __( 'Settings', 'doliwoo' ) + ) . '', + ); + + return array_merge( $action_links, $links ); + } + + /** + * Set Dolibarr settings from WooCommerce integration settings * * @return void */ - public function get_settings() { + public function set_settings() { // Load settings - $this->settings = WC()->integrations->get_integrations()['doliwoo']; - $this->ws_auth = array( - 'dolibarrkey' => $this->settings->dolibarr_key, - 'sourceapplication' => $this->settings->sourceapplication, - 'login' => $this->settings->dolibarr_login, - 'password' => $this->settings->dolibarr_password, - 'entity' => $this->settings->dolibarr_entity - ); + $integrations = WC()->integrations->get_integrations(); + $this->dolibarr->settings = $integrations['doliwoo']; + $this->dolibarr->update_settings(); } } } } else { // WooCommerce is not available - echo __( 'This extension needs WooCommerce' ); + esc_html_e( __( 'This extension needs WooCommerce', 'doliwoo' ) ); exit; } $Doliwoo = new Doliwoo(); -endif; + endif; diff --git a/includes/class-dolibarr-soap-elements.php b/includes/class-dolibarr-soap-elements.php index dadbc1f..3495677 100644 --- a/includes/class-dolibarr-soap-elements.php +++ b/includes/class-dolibarr-soap-elements.php @@ -17,31 +17,38 @@ */ /** - * SOAP reprentations hinting classes + * SOAP reprentations hinting classes. + * + * Just hinting pseudo classes to ease development. + * These element can be used for or returned by Dolibarr SOAP requests. + * + * @package DoliWoo */ /** - * Class DolibarrOrder - * - * SOAP orders representation + * SOAP orders representation. */ -class DolibarrOrder { +class Dolibarr_Order { + /** @var string */ + public $id; + /** @var int */ public $thirdparty_id; + /** @var string ISO 8601 */ public $date; + /** @var int */ public $status; - /** @var DolibarrOrderLine[] */ + + /** @var Dolibarr_Order_Line[] */ public $lines; } /** - * Class DolibarrOrderLine - * * SOAP order lines representation */ -class DolibarrOrderLine { +class Dolibarr_Order_Line { /** @var int */ public $type; @@ -74,11 +81,12 @@ class DolibarrOrderLine { } /** - * Class DolibarrThirdparty - * * SOAP third parties representation */ -class DolibarrThirdparty { +class Dolibarr_Thirdparty { + /** @var string */ + public $id; + /** @var string */ public $ref; @@ -118,3 +126,83 @@ class DolibarrThirdparty { /** @var string */ public $firstname; } + +/** + * SOAP products representation + */ +class Dolibarr_Product { + /** @var string */ + public $id; + + /** @var string */ + public $ref; + + /** @var string */ + public $type; + + /** @var string */ + public $label; + + /** @var string */ + public $description; + + /** @var string */ + public $date_creation; + + /** @var string */ + public $date_modification; + + /** @var string */ + public $note; + + /** @var string */ + public $status_tobuy; + + /** @var string */ + public $status_tosell; + + /** @var string */ + public $barcode_type; + + /** @var string */ + public $country_id; + + /** @var string */ + public $country_code; + + /** @var string */ + public $price_net; + + /** @var string */ + public $price; + + /** @var string */ + public $price_min_net; + + /** @var string */ + public $price_min; + + /** @var string */ + public $price_base_type; + + /** @var string */ + public $vat_rate; + + /** @var string */ + public $vat_npr; + + /** @var string */ + public $localtax1_tx; + + /** @var string */ + public $localtax2_tx; + + /** @var string */ + public $stock_real; + + /** @var string */ + public $dir; + + /** @var array */ + public $images; +} diff --git a/includes/class-dolibarr.php b/includes/class-dolibarr.php index 0f2f639..3c07da0 100644 --- a/includes/class-dolibarr.php +++ b/includes/class-dolibarr.php @@ -18,22 +18,41 @@ */ /** - * Dolibarr interactions + * Dolibarr interactions. + * + * All Dolibarr interactions triggerred by WooCommerce are managed here. + * + * @package DoliWoo */ /** - * Class Dolibarr + * Dolibarr interactions. */ -class Dolibarr { +class Doliwoo_Dolibarr { /** @var WC_Logger Logging */ public $logger; - /** @var Doliwoo */ - public $Doliwoo; + /** @var Doliwoo_WC_Integration Settings */ + public $settings; - /** @var WC_Tax_Doliwoo WooCommerce taxes informations */ + /** @var Doliwoo_WC_Tax WooCommerce taxes informations */ public $taxes; + /** @var string Webservice endpoint */ + private $ws_endpoint; + + /** @var array Webservice authentication parameters */ + private $ws_auth; + + /** + * Doliwoo_Dolibarr webservices endpoints + */ + const ORDER_ENDPOINT = 'server_order.php'; + const THIRDPARTY_ENDPOINT = 'server_thirdparty.php'; + const PRODUCT_ENDPOINT = 'server_productorservice.php'; + const OTHER_ENDPOINT = 'server_other.php'; + const WSDL_MODE = '?wsdl'; + /** * Init parameters */ @@ -51,60 +70,66 @@ public function set_woocommerce() { /** * Hooks on process_checkout() * - * While the order is processed, use the data to create a Dolibarr order via webservice + * While the order is processed, use the data to create a Doliwoo_Dolibarr order via webservice * * @return void */ public function dolibarr_create_order() { - $this->taxes = new WC_Tax_Doliwoo(); - - $this->Doliwoo = new Doliwoo(); - $this->Doliwoo->get_settings(); + /* + * We use non WSDL mode to workaround Doliwoo_Dolibarr broken declaration marking all the fields as required + * when they're not. + */ + try { + $soap_client = new SoapClient( + null, + array( + 'location' => $this->ws_endpoint . self::ORDER_ENDPOINT, + 'uri' => 'http://www.dolibar.org/ns/', + ) + ); + } catch ( SoapFault $exception ) { + $this->logger->add( 'doliwoo', $exception->getMessage() ); - $dolibarr_ws_url = $this->Doliwoo->settings->webservs_url . 'server_order.php?wsdl'; + // Do nothing. + return; + } - // Set the WebService URL - $soap_client = new SoapClient( - null, - array( - 'location' => $dolibarr_ws_url, - 'uri' => "http://www.dolibar.org/ns/" - ) - ); - $order = new DolibarrOrder(); + $order = new Dolibarr_Order(); - // Fill this array with all data required to create an order in Dolibarr + // Fill this array with all data required to create an order in Doliwoo_Dolibarr $user_id = get_current_user_id(); if ( '' == $user_id ) { // default to the generic user - $thirdparty_id = $this->Doliwoo->settings->dolibarr_generic_id; + $thirdparty_id = $this->settings->dolibarr_generic_id; } else { - $thirdparty_id = get_user_meta( $user_id, 'dolibarr_id', - true ); + $thirdparty_id = get_user_meta( $user_id, 'dolibarr_id', true ); } if ( '' != $thirdparty_id ) { - $order->thirdparty_id = $thirdparty_id; + $order->thirdparty_id = intval( $thirdparty_id ); } else { - if ( get_user_meta( $user_id, 'billing_company', true ) - == '' - ) { - update_user_meta( $user_id, 'billing_company', - $_POST['billing_company'] ); + if ( get_user_meta( $user_id, 'billing_company', true ) == '' ) { + update_user_meta( $user_id, 'billing_company', $_POST['billing_company'] ); } $this->dolibarr_create_thirdparty_if_not_exists( $user_id ); - $order->thirdparty_id = get_user_meta( $user_id, - 'dolibarr_id', true ); + $order->thirdparty_id = intval( get_user_meta( $user_id, 'dolibarr_id', true ) ); } $order->date = date( 'Ymd' ); $order->status = 1; $this->create_order_lines( $order ); - $soap_client->createOrder( $this->Doliwoo->ws_auth, $order ); + try { + $soap_client->createOrder( $this->ws_auth, $order ); + } catch ( SoapFault $exception ) { + $this->logger->add( 'doliwoo', $exception->getMessage() ); + + // Do nothing. + return; + } } /** - * Creates a thirdparty in Dolibarr via webservice using WooCommerce user data, if it doesn't already exists + * Creates a thirdparty in Doliwoo_Dolibarr via webservice using WooCommerce user data, if it doesn't already exists * * @param int $user_id a Wordpress user id * @@ -117,49 +142,57 @@ private function dolibarr_create_thirdparty_if_not_exists( if ( $result ) { if ( $result['thirdparty'] - && get_user_meta( $user_id, 'dolibarr_id', true ) - != $result['thirdparty']->id + && get_user_meta( $user_id, 'dolibarr_id', true ) != $result['thirdparty']->id ) { - update_user_meta( $user_id, 'dolibarr_id', - $result['thirdparty']->id ); + update_user_meta( $user_id, 'dolibarr_id', $result['thirdparty']->id ); } elseif ( null === $result['thirdparty'] ) { $res = $this->dolibarr_create_thirdparty( $user_id ); if ( 'OK' == $res['result']->result_code ) { - update_user_meta( $user_id, 'dolibarr_id', - $res->id ); + update_user_meta( $user_id, 'dolibarr_id', $res->id ); } } } } /** - * Checks if a thirdparty exists in Dolibarr + * Checks if a thirdparty exists in Doliwoo_Dolibarr * - * @param int $user_id wordpress ID of an user + * @param int $user_id Wordpress ID of an user * - * @return mixed $result array with the request results if it succeeds, null if there's an error + * @return int $result Array with the request results if it succeeds, null if there's an error */ private function dolibarr_thirdparty_exists( $user_id ) { - $this->Doliwoo = new Doliwoo(); - $this->Doliwoo->get_settings(); - $dolibarr_ws_url = $this->Doliwoo->settings->webservs_url - . 'server_thirdparty.php?wsdl'; + try { + $soap_client = new SoapClient( + $this->ws_endpoint . self::THIRDPARTY_ENDPOINT . self::WSDL_MODE + ); + } catch ( SoapFault $exception ) { + $this->logger->add( 'doliwoo', $exception->getMessage() ); - // Set the WebService URL - $soap_client = new SoapClient( $dolibarr_ws_url ); + // Do nothing. + return null; + } $dol_id = get_user_meta( $user_id, 'dolibarr_id', true ); + $dol_ref = get_user_meta( $user_id, 'billing_company', true ); - // if the user has a Dolibarr ID, use it, else use his company name + // If the user has a Doliwoo_Dolibarr ID, use it, else search his company name if ( $dol_id ) { - $result = $soap_client->getThirdParty( $this->Doliwoo->ws_auth, - $dol_id ); + $dol_ref = null; } else { - $result = $soap_client->getThirdParty( $this->Doliwoo->ws_auth, - '', get_user_meta( $user_id, 'billing_company', - true ) ); + $dol_id = ''; + } + + try { + $result = $soap_client->getThirdParty( $this->ws_auth, $dol_id, $dol_ref ); + } catch ( SoapFault $exception ) { + $this->logger->add( 'doliwoo', $exception->getMessage() ); + + // Do nothing. + return null; } + if ( $result ) { return $result; } else { @@ -168,61 +201,63 @@ private function dolibarr_thirdparty_exists( $user_id ) { } /** - * Creates a thirdparty in Dolibarr via webservice using WooCommerce user data + * Creates a thirdparty in Doliwoo_Dolibarr via webservice using WooCommerce user data * * @param int $user_id a Wordpress user id * - * @return mixed $result the SOAP response + * @return int $result the SOAP response */ public function dolibarr_create_thirdparty( $user_id ) { - $this->Doliwoo = new Doliwoo(); - $this->Doliwoo->get_settings(); - - $dolibarr_ws_url = $this->Doliwoo->settings->webservs_url - . 'server_thirdparty.php?wsdl'; - // Set the WebService URL - $soap_client = new SoapClient( - null, - array( - 'location' => $dolibarr_ws_url, - 'uri' => "http://www.dolibar.org/ns/" - ) - ); + /* + * We use non WSDL mode to workaround Doliwoo_Dolibarr broken declaration marking all the fields as required + * when they're not. + */ + try { + $soap_client = new SoapClient( + null, + array( + 'location' => $this->ws_endpoint . self::THIRDPARTY_ENDPOINT, + 'uri' => 'http://www.dolibar.org/ns/', + ) + ); + } catch ( SoapFault $exception ) { + $this->logger->add( 'doliwoo', $exception->getMessage() ); - $ref = get_user_meta( $user_id, 'billing_company', - true ); + // Do nothing. + return null; + } + + $ref = get_user_meta( $user_id, 'billing_company', true ); $individual = 0; if ( '' == $ref ) { - $ref = get_user_meta( $user_id, - 'billing_last_name', true ); + // We could not find a company, let's get an indivual + $ref = get_user_meta( $user_id, 'billing_last_name', true ); $individual = 1; } - $new_thirdparty = new DolibarrThirdparty(); - - $new_thirdparty->ref = $ref; - $new_thirdparty->status = '1'; - $new_thirdparty->client = '1'; - $new_thirdparty->supplier = '0'; - - $new_thirdparty->address = get_user_meta( - $user_id, 'billing_address', true ); - $new_thirdparty->zip = get_user_meta( - $user_id, 'billing_postcode', true ); - $new_thirdparty->town = get_user_meta( - $user_id, 'billing_city', true ); - $new_thirdparty->country_code = get_user_meta( - $user_id, 'billing_country', true ); - $new_thirdparty->supplier_code = '0'; - $new_thirdparty->phone = get_user_meta( - $user_id, 'billing_phone', true ); - $new_thirdparty->email = get_user_meta( - $user_id, 'billing_email', true ); - $new_thirdparty->individual = $individual; - $new_thirdparty->firstname = get_user_meta( - $user_id, 'billing_first_name', true ); - - $result = $soap_client->createThirdParty( $this->Doliwoo->ws_auth, $new_thirdparty ); + $new_thirdparty = new Dolibarr_Thirdparty(); + + $new_thirdparty->ref = $ref; // Company name or individual last name + $new_thirdparty->individual = $individual; // Individual + $new_thirdparty->firstname = get_user_meta( $user_id, 'billing_first_name', true ); + $new_thirdparty->status = '1'; // Active + $new_thirdparty->client = '1'; // Is a client + $new_thirdparty->supplier = '0'; // Is not a supplier + $new_thirdparty->address = get_user_meta( $user_id, 'billing_address', true ); + $new_thirdparty->zip = get_user_meta( $user_id, 'billing_postcode', true ); + $new_thirdparty->town = get_user_meta( $user_id, 'billing_city', true ); + $new_thirdparty->country_code = get_user_meta( $user_id, 'billing_country', true ); + $new_thirdparty->phone = get_user_meta( $user_id, 'billing_phone', true ); + $new_thirdparty->email = get_user_meta( $user_id, 'billing_email', true ); + + try { + $result = $soap_client->createThirdParty( $this->ws_auth, $new_thirdparty ); + } catch ( SoapFault $exception ) { + $this->logger->add( 'doliwoo', $exception->getMessage() ); + + // Do nothing. + return null; + } return $result; } @@ -230,7 +265,7 @@ public function dolibarr_create_thirdparty( $user_id ) { /** * Create order lines * - * @param DolibarrOrder $order The order to add lines to + * @param Dolibarr_Order $order The order to add lines to */ private function create_order_lines( $order ) { $order->lines = array(); @@ -239,48 +274,35 @@ private function create_order_lines( $order ) { /** @var WC_Product $woocommerce_product */ $woocommerce_product = $product['data']; - $line = new DolibarrOrderLine(); - $line->type - = get_post_meta( $product['product_id'], - 'dolibarr_type', 1 ); - $line->desc - = $woocommerce_product->post->post_content; - $line->product_id - = get_post_meta( $product['product_id'], - 'dolibarr_id', 1 ); + $line = new Dolibarr_Order_Line(); + $line->type = intval( get_post_meta( $product['product_id'], 'dolibarr_type', true ) ); + $line->desc = $woocommerce_product->post->post_content; + $line->product_id = intval( get_post_meta( $product['product_id'], 'dolibarr_id', true ) ); $rates = $this->taxes->get_rates( $woocommerce_product->get_tax_class() ); + $rates = array_values( $rates ); // We get the first one - $line->vat_rate = array_values( $rates )[0]['rate']; + $line->vat_rate = $rates[0]['rate']; $line->qty = $product['quantity']; - $line->price = $woocommerce_product->get_price(); - $line->unitprice = $woocommerce_product->get_price(); - $line->total_net - = $woocommerce_product->get_price_excluding_tax( $line->qty ); - $line->total - = $woocommerce_product->get_price_including_tax( $line->qty ); - $line->total_vat - = $line->total - $line->total_net; + $line->price = floatval( $woocommerce_product->get_price() ); + $line->unitprice = floatval( $woocommerce_product->get_price() ); + $line->total_net = floatval( $woocommerce_product->get_price_excluding_tax( $line->qty ) ); + $line->total = floatval( $woocommerce_product->get_price_including_tax( $line->qty ) ); + $line->total_vat = $line->total - $line->total_net; $order->lines[] = $line; } } /** - * Pull products data from Dolibarr via webservice and save it in Wordpress + * Pull products data from Doliwoo_Dolibarr via webservice and save it in Wordpress * * @return void */ public function dolibarr_import_products() { - $this->taxes = new WC_Tax_Doliwoo(); - $this->Doliwoo = new Doliwoo(); - $this->Doliwoo->get_settings(); - - // Set the WebService URL try { $soap_client = new SoapClient( - $this->Doliwoo->settings->webservs_url - . 'server_productorservice.php?wsdl' + $this->ws_endpoint . self::PRODUCT_ENDPOINT . self::WSDL_MODE ); } catch ( SoapFault $exception ) { $this->logger->add( 'doliwoo', $exception->getMessage() ); @@ -290,16 +312,39 @@ public function dolibarr_import_products() { } // Get all products that are meant to be displayed on the website - $result - = $soap_client->getProductsForCategory( $this->Doliwoo->ws_auth, - $this->Doliwoo->settings->dolibarr_category_id ); + try { + $result = $soap_client->getProductsForCategory( + $this->ws_auth, + $this->settings->dolibarr_category_id + ); + } catch ( SoapFault $exception ) { + $this->logger->add( 'doliwoo', $exception->getMessage() ); + + // Do nothing. + return; + } - if ( $result['result']->result_code == 'OK' ) { - $dolibarr_products = $result['products']; + /** @var Dolibarr_Product[] $dolibarr_products */ + $dolibarr_products = $result['products']; + + if ( 'OK' == $result['result']->result_code && ! empty( $dolibarr_products ) ) { foreach ( $dolibarr_products as $dolibarr_product ) { - if ( $this->dolibarr_product_exists( $dolibarr_product->id ) ) { - $post_id = 0; + if ( 0 == $dolibarr_product->status_tosell ) { + // This product is not for sale, let's skip it. + continue; + } + + $existing_product = $this->dolibarr_product_exists( $dolibarr_product->id ); + if ( $existing_product ) { + // Update the product + $post = array( + 'ID' => $existing_product->ID, + 'post_title' => $dolibarr_product->label, + 'post_content' => $dolibarr_product->description, + ); + $post_id = wp_update_post( $post ); } else { + // Create a new product $post = array( 'post_title' => $dolibarr_product->label, 'post_content' => $dolibarr_product->description, @@ -309,42 +354,15 @@ public function dolibarr_import_products() { $post_id = wp_insert_post( $post ); } - if ( 0 < $post_id ) { - // Post metas management - add_post_meta( $post_id, 'dolibarr_id', - $dolibarr_product->id, true ); - add_post_meta( $post_id, 'dolibarr_type', $dolibarr_product->type, - true ); - update_post_meta( $post_id, '_regular_price', - $dolibarr_product->price_net ); - update_post_meta( $post_id, '_sale_price', - $dolibarr_product->price_net ); - update_post_meta( $post_id, '_price', - $dolibarr_product->price_net ); - update_post_meta( $post_id, '_visibility', - 'visible' ); - update_post_meta( $post_id, '_tax_class', - $this->taxes->get_tax_class( $dolibarr_product->vat_rate ) ); - - // Stock management - if ( get_option( 'woocommerce_manage_stock' ) - == 'yes' - ) { - if ( 0 < $dolibarr_product->stock_real ) { - update_post_meta( $post_id, - '_stock_status', 'instock' ); - update_post_meta( $post_id, '_stock', - $dolibarr_product->stock_real ); - } - } - - // Product images management - if ( $dolibarr_product->images ) { - $this->import_product_images( $dolibarr_product, $post_id ); - } - - // Cleanup - wc_delete_product_transients( $post_id ); + // Error management (logging) + if ( is_wp_error( $post_id ) ) { + /** @var WP_Error $post_id */ + $this->logger->add( 'doliwoo', $post_id->get_error_message() ); + } + + if ( 0 < $post_id && ! is_wp_error( $post_id ) ) { + /** @var int $post_id */ + $this->update_product_attributes( $dolibarr_product, $post_id ); } } } @@ -353,83 +371,131 @@ public function dolibarr_import_products() { /** * Checks for the existence of a product in Wordpress database * - * @param int $dolibarr_id ID of a product in Dolibarr + * @param int $dolibarr_id ID of a product in Doliwoo_Dolibarr * - * @return bool $exists + * @return WP_POST */ private function dolibarr_product_exists( $dolibarr_id ) { $args = array( 'post_type' => 'product', 'meta_key' => 'dolibarr_id', - 'meta_value' => $dolibarr_id + 'meta_value' => $dolibarr_id, ); $query = new WP_Query( $args ); - return $query->have_posts(); + return $query->post; + } + + /** + * Update the product attributes + * + * @param Dolibarr_Product $dolibarr_product The dolibarr product + * @param int $post_id The woocommerce product ID + */ + private function update_product_attributes( $dolibarr_product, $post_id ) { + + /** @var int $post_id */ + + // Post metas management + add_post_meta( $post_id, 'dolibarr_id', $dolibarr_product->id, true ); + add_post_meta( $post_id, 'dolibarr_type', $dolibarr_product->type, true ); + update_post_meta( $post_id, '_sku', $dolibarr_product->ref ); + update_post_meta( $post_id, '_purchase_note', $dolibarr_product->note ); + update_post_meta( $post_id, '_regular_price', $dolibarr_product->price_net ); + update_post_meta( $post_id, '_sale_price', $dolibarr_product->price_net ); + update_post_meta( $post_id, '_price', $dolibarr_product->price_net ); + update_post_meta( $post_id, '_visibility', 'visible' ); + update_post_meta( + $post_id, + '_tax_class', + $this->taxes->get_tax_class( $dolibarr_product->vat_rate ) + ); + update_post_meta( $post_id, '_manage_stock', 'no' ); + + // Stock management + if ( 'yes' == get_option( 'woocommerce_manage_stock' ) ) { + if ( 0 < $dolibarr_product->stock_real ) { + update_post_meta( $post_id, '_stock_status', 'instock' ); + update_post_meta( $post_id, '_stock', $dolibarr_product->stock_real ); + update_post_meta( $post_id, '_manage_stock', 'yes' ); + } + } + + // Product images management + if ( ! empty( $dolibarr_product->images ) ) { + $this->import_product_images( $dolibarr_product, $post_id ); + } + + // Cleanup + wc_delete_product_transients( $post_id ); } /** - * Import Dolibarr product images + * Import Doliwoo_Dolibarr product images * - * @param StdClass $dolibarr_product The Dolibarr product + * @param Dolibarr_Product $dolibarr_product The Doliwoo_Dolibarr product * @param int $post_id The WooCommerce product */ private function import_product_images( $dolibarr_product, $post_id ) { - $image_attachment_ids = $this->get_product_image( $dolibarr_product, - $post_id ); - - // Fill the image gallery - update_post_meta( $post_id, - '_product_image_gallery', - implode( ',', $image_attachment_ids ) ); + $image_attachment_ids = $this->get_product_image( $dolibarr_product, $post_id ); // Use the first image as the product thumbnail - update_post_meta( $post_id, '_thumbnail_id', - $image_attachment_ids[0] ); + update_post_meta( $post_id, '_thumbnail_id', array_shift( $image_attachment_ids ) ); + + // Fill the image gallery + update_post_meta( $post_id, '_product_image_gallery', implode( ',', $image_attachment_ids ) ); } /** * Webservice calls to get the product's images * - * @param stdClass $dolibarr_product SOAP product object + * @param Dolibarr_Product $dolibarr_product SOAP product object * @param int $post_id WooCommerce product ID * * @return int[] Attachment IDs */ - private function get_product_image( - stdClass $dolibarr_product, $post_id - ) { - $this->Doliwoo = new Doliwoo(); - $this->Doliwoo->get_settings(); + private function get_product_image( $dolibarr_product, $post_id ) { + try { + $soap_client = new SoapClient( + $this->ws_endpoint . self::OTHER_ENDPOINT . self::WSDL_MODE + ); + } catch ( SoapFault $exception ) { + $this->logger->add( 'doliwoo', $exception->getMessage() ); - $soap_client = new SoapClient( - $this->Doliwoo->settings->webservs_url - . 'server_other.php?wsdl' - ); + // Do nothing. + return null; + } $file_array = array(); $attach_ids = array(); foreach ( $dolibarr_product->images as $images ) { - // Get the image from Dolibarr - $result = $soap_client->getDocument( - $this->Doliwoo->ws_auth, - 'product', - $dolibarr_product->dir . $images->photo - ); + // Get the image from Doliwoo_Dolibarr + try { + $result = $soap_client->getDocument( + $this->ws_auth, + 'product', + $dolibarr_product->dir . $images->photo + ); + } catch ( SoapFault $exception ) { + $this->logger->add( 'doliwoo', $exception->getMessage() ); + + // Do nothing. + continue; + } if ( 'OK' == $result['result']->result_code ) { - $file_array['name'] = $images->photo; - $file_array['tmp_name'] - = - sys_get_temp_dir() . DIRECTORY_SEPARATOR . $images->photo; - file_put_contents( $file_array['tmp_name'], - base64_decode( $result['document']->content ) ); + $file_array['name'] = $images->photo; + $file_array['tmp_name'] = sys_get_temp_dir() . DIRECTORY_SEPARATOR . $images->photo; + file_put_contents( + $file_array['tmp_name'], + base64_decode( $result['document']->content ) + ); $res = media_handle_sideload( $file_array, $post_id ); - // handle errors nicely ( logging ) - if ( true === is_wp_error( $res ) ) { + // Handle errors nicely ( logging ) + if ( is_wp_error( $res ) ) { $message = $res->get_error_message(); $this->logger->add( 'doliwoo', $message ); } else { @@ -440,4 +506,18 @@ private function get_product_image( return $attach_ids; } + + /** + * Set settings in a more useable form + */ + public function update_settings() { + $this->ws_endpoint = $this->settings->dolibarr_ws_endpoint; + $this->ws_auth = array( + 'sourceapplication' => $this->settings->sourceapplication, + 'dolibarrkey' => $this->settings->dolibarr_key, + 'login' => $this->settings->dolibarr_login, + 'password' => $this->settings->dolibarr_password, + 'entity' => $this->settings->dolibarr_entity, + ); + } } diff --git a/includes/class-wc-integration.php b/includes/class-wc-integration.php new file mode 100644 index 0000000..1251181 --- /dev/null +++ b/includes/class-wc-integration.php @@ -0,0 +1,383 @@ + + * Copyright (C) 2015 Maxime Lafourcade + * Copyright (C) 2015 Raphaël Doursenaud + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * DoliWoo settings. + * + * WooCommerce settings integration. + * + * @package DoliWoo + */ + +if ( ! class_exists( 'Doliwoo_WC_Integration' ) ) : + + /** + * Doliwoo settings WooCommerce integration + * + * @see WC_Integration + */ + class Doliwoo_WC_Integration extends WC_Integration { + /** @var string The Dolibarr webservice URL */ + public $dolibarr_ws_endpoint; + + /** @var string WordPress pseudo cron update delay */ + public $delay_update; + + /** @var string The Dolibarr webservice key */ + public $dolibarr_key; + + /** @var string The application name declared when using the Dolibarr webservice */ + public $sourceapplication; + + /** @var string Username to connect to Dolibarr webservice */ + public $dolibarr_login; + + /** @var string Password to connect to Dolibarr webservice */ + public $dolibarr_password; + + /** @var string Dolibarr entity we want webservice responses from */ + public $dolibarr_entity; + + /** @var string ID of the Dolibarr category we sync products from */ + public $dolibarr_category_id; + + /** @var string ID of the Dolibarr thirdparty to use when we make a sale without a user logged in */ + public $dolibarr_generic_id; + + /** @var int[] The distant Dolibarr version */ + private $dolibarr_version; + + /** + * Init and hook in the integration. + */ + public function __construct() { + $this->id = 'doliwoo'; + $this->method_title = __( 'DoliWoo', 'doliwoo' ); + $this->method_description = __( 'Dolibarr webservices access', 'doliwoo' ); + + // Load the settings + $this->init_form_fields(); + $this->init_settings(); + + // Define user set variables + $this->dolibarr_ws_endpoint = $this->get_option( 'dolibarr_ws_endpoint' ); + $this->delay_update = $this->get_option( 'delay_update' ); + $this->dolibarr_key = $this->get_option( 'dolibarr_key' ); + $this->sourceapplication = $this->get_option( 'sourceapplication' ); + $this->dolibarr_login = $this->get_option( 'dolibarr_login' ); + $this->dolibarr_password = $this->get_option( 'dolibarr_password' ); + $this->dolibarr_entity = $this->get_option( 'dolibarr_entity' ); + $this->dolibarr_category_id = $this->get_option( 'dolibarr_category_id' ); + $this->dolibarr_generic_id = $this->get_option( 'dolibarr_generic_id' ); + + // Actions + add_action( + 'woocommerce_update_options_integration_' . $this->id, + array( $this, 'process_admin_options' ) + ); + + // Filters. + add_filter( + 'woocommerce_settings_api_sanitized_fields_' . $this->id, + array( $this, 'sanitize_settings' ) + ); + } + + /** + * Initialize integration settings form fields. + * + * @return void + */ + public function init_form_fields() { + $this->form_fields = array( + 'sourceapplication' => array( + 'title' => __( 'Source application', 'doliwoo' ), + 'description' => __( 'How this application will identify itself to the webservice.', 'doliwoo' ), + 'type' => 'text', + 'desc_tip' => false, + 'default' => 'WooCommerce', + ), + 'dolibarr_ws_endpoint' => array( + 'title' => __( 'URL', 'doliwoo' ), + 'description' => __( + 'Enter Dolibarr webservices root URL (i.e. https://mydolibarr.com/webservices)', + 'doliwoo' + ), + 'type' => 'text', + 'desc_tip' => false, + 'default' => '', + ), + 'delay_update' => array( + 'title' => __( 'Delay', 'doliwoo' ), + 'description' => __( 'Choose the automatic update frequency', 'doliwoo' ), + 'type' => 'select', + 'desc_tip' => false, + 'options' => array( + 'hourly' => __( 'Once Hourly' ), + 'twicedaily' => __( 'Twice Daily' ), + 'daily' => __( 'Once Daily' ), + ), + 'default' => 'daily', + ), + 'dolibarr_key' => array( + 'title' => __( 'Key', 'doliwoo' ), + 'description' => __( 'Enter your Dolibarr webservices key', 'doliwoo' ), + 'type' => 'text', + 'desc_tip' => false, + 'default' => '', + ), + 'dolibarr_login' => array( + 'title' => __( 'User login', 'doliwoo' ), + 'description' => __( 'Dolibarr actions will be done as this user', 'doliwoo' ), + 'type' => 'text', + 'desc_tip' => false, + 'default' => '', + ), + 'dolibarr_password' => array( + 'title' => __( 'User password', 'doliwoo' ), + 'type' => 'password', + 'desc_tip' => false, + 'default' => '', + ), + 'dolibarr_entity' => array( + 'title' => __( 'Entity', 'doliwoo' ), + 'description' => __( 'If you\'re using multicompany, the ID of the entity you want to integrate. Leave to 1 otherwise.', 'doliwoo' ), + 'type' => 'text', + 'desc_tip' => false, + 'default' => 1, + ), + 'dolibarr_category_id' => array( + 'title' => __( 'Products category', 'doliwoo' ), + 'description' => __( 'The ID of the products category you want to automatically import products from.', 'doliwoo' ), + 'type' => 'text', + 'desc_tip' => false, + 'default' => '', + ), + 'dolibarr_generic_id' => array( + 'title' => __( 'Generic thirdparty', 'doliwoo' ), + 'description' => __( 'The ID of the thirdparty that\'ll be used for anonymous orders.', 'doliwoo' ), + 'type' => 'text', + 'desc_tip' => false, + 'default' => '', + ), + 'dolibarr_version' => array( + 'title' => __( 'Dolibarr version', 'doliwoo' ), + 'description' => __( 'If the webservice communication is OK, it displays your Dolibarr version', 'doliwoo' ), + 'type' => 'info', + 'desc_tip' => false, + ), + ); + } + + /** + * Display Dolibarr version and compatibility + * + * @param string $key Settings key + * @param array $data Setting values + * + * @return string HTML to display + */ + protected function generate_info_html( $key, $data ) { + // Get Webservice infos + $this->test_webservice( ); + + $field = $this->plugin_id . $this->id . '_' . $key; + + $version_ok = false; + if ( + // Is version > 3.4.0 + 4 <= $this->dolibarr_version[0] + || ( 3 <= $this->dolibarr_version[0] && 4 <= $this->dolibarr_version[1] ) + ) { + $version_ok = true; + } + + $not_configured = __( 'Please configure the plugin.', 'doliwoo' ); + $not_compatible = __( 'Not compatible! Please use at least Dolibarr v3.4.0.', 'doliwoo' ); + $configuration_ok = __( 'OK!', 'doliwoo' ); + $detected = sprintf( __( '(Detected v%s)', 'doliwoo' ), implode( '.', $this->dolibarr_version ) ); + + ob_start(); + ?> + + + + get_tooltip_html( $data ) ); ?> + + + dolibarr_version ) ) { + esc_html_e( $not_configured ); + } else { + if ( $version_ok ) { + esc_html_e( $configuration_ok ); + } else { + esc_html_e( $not_compatible ); + } + esc_html_e( ' ' . $detected ); + } + ?> + + + plugin_id . $this->id . '_' . $key ]; + + // Make sure we use HTTPS + if ( 'https://' !== ( substr( $value, 0, 8 ) ) ) { + $this->errors[] = __( 'The protocol to use is https://', 'doliwoo' ); + } + + // Make sure we have the trailing slash + $value = trailingslashit( $value ); + + // Check that the server is available + try { + new SoapClient( $value . Doliwoo_Dolibarr::OTHER_ENDPOINT . Doliwoo_Dolibarr::WSDL_MODE ); + } catch ( SoapFault $exc ) { + $this->errors[] = __( 'The webservice is not available. Please check the URL.', 'doliwoo' ); + } + + return $value; + } + + /** + * Sanitize settings. + * Executed after validations. + * @see process_admin_options() + * + * @param array $settings Validated settings + * + * @return array Sanitized settings + */ + public function sanitize_settings( $settings ) { + // Check Dolibarr version and compatibility + + $endpoint = $settings['dolibarr_ws_endpoint']; + $ws_auth = array( + 'dolibarrkey' => $settings['dolibarr_key'], + 'sourceapplication' => $settings['sourceapplication'], + 'login' => $settings['dolibarr_login'], + 'password' => $settings['dolibarr_password'], + 'entity' => $settings['dolibarr_entity'], + ); + + $this->test_webservice( $endpoint, $ws_auth ); + + return $settings; + } + + /** + * Display HTTPS is needed + * @see WC_Integration::display_errors() + * + * @return void + */ + public function display_errors( ) { + if ( empty( $this->errors ) ) { + // Nothing to do + return; + } + + foreach ( $this->errors as $key => $value ) { + ?> +
+

+ +

+
+ errors ); + } + + /** + * Check that the webservice works. + * Tests endpoint, authentication and actual response + * + * @param string $webservice The webservice URL + * @param string[] $ws_auth The webservice authentication array + */ + private function test_webservice( + $webservice = '', + $ws_auth = array() + ) { + if ( empty ( $webservice ) && ! empty ( $this->dolibarr_ws_endpoint ) ) { + $webservice = $this->dolibarr_ws_endpoint; + } + if ( empty ( $webservice ) ) { + // We don't want to check unconfigured plugin + return; + } + + if ( empty ( $ws_auth ) ) { + $ws_auth = array( + 'dolibarrkey' => $this->dolibarr_key, + 'sourceapplication' => $this->sourceapplication, + 'login' => $this->dolibarr_login, + 'password' => $this->dolibarr_password, + 'entity' => $this->dolibarr_entity, + ); + } + + // Check that the server is available + try { + $soap_client = new SoapClient( $webservice . Doliwoo_Dolibarr::OTHER_ENDPOINT . Doliwoo_Dolibarr::WSDL_MODE ); + } catch ( SoapFault $exc ) { + $this->errors[] = __( 'The webservice is not available. Please check the URL.', 'doliwoo' ); + $this->display_errors(); + + // No point in doing the next test + return; + } + + try { + $response = $soap_client->getVersions( $ws_auth ); + } catch ( SoapFault $exc ) { + $this->errors[] = 'Webservice error:' . $exc->getMessage(); + $this->display_errors(); + + // No point in doing the next test + return; + } + + if ( 'OK' == $response['result']->result_code ) { + $this->dolibarr_version = explode( '.', $response['dolibarr'] ); + } else { + $this->errors[] = 'Webservice error:' . $response['result']->result_label; + $this->display_errors(); + } + } + } +endif; diff --git a/includes/class-doliwoo-parameters.php b/includes/class-wc-params.php similarity index 81% rename from includes/class-doliwoo-parameters.php rename to includes/class-wc-params.php index 0c3f6c0..2aa9ece 100644 --- a/includes/class-doliwoo-parameters.php +++ b/includes/class-wc-params.php @@ -18,13 +18,18 @@ */ /** - * Parameters management + * Parameters management. + * + * We store some properties to link imported Dolibarr elements to their WooCommerce counterparts. + * This class ties everything together. + * + * @package DoliWoo */ /** - * Class Woocomerce_Parameters + * Parameters management */ -Class Woocomerce_Parameters { +Class Doliwoo_WC_Params { /** * Save Dolibarr ID field on edit user pages @@ -38,8 +43,8 @@ public function save_customer_meta_fields( $user_id ) { foreach ( $save_fields as $fieldset ) { foreach ( $fieldset['fields'] as $key => $field ) { if ( isset( $_POST[ $key ] ) ) { - update_user_meta( $user_id, $key, - wc_clean( $_POST[ $key ] ) ); + update_user_meta( $user_id, $key, wc_clean( $_POST[ $key ] ) + ); } } } @@ -62,8 +67,8 @@ public function get_customer_meta_fields() { 'title' => __( 'Dolibarr', 'doliwoo' ), 'fields' => array( 'dolibarr_id' => array( - 'label' => __( 'Dolibarr User ID', 'doliwoo' ), - 'description' => 'The boss' + 'label' => __( 'User ID', 'doliwoo' ), + 'description' => __( 'The Dolibarr ID for this user', 'doliwoo' ), ) ) ) @@ -109,12 +114,18 @@ public function customer_meta_fields( WP_User $user ) { /** * Define value for the Dolibarr ID column * + * @param string $value The current value + * @param string $column_name The curent custom column * @param mixed $user_id The ID of the user being displayed * * @return string Value for the column */ - public function user_column_values( $user_id ) { - return get_user_meta( $user_id, 'dolibarr_id', true ); + public function user_column_values( $value, $column_name, $user_id ) { + $user = get_userdata( $user_id ); + if ( 'dolibarr_id' == $column_name ) { + return get_user_meta( $user->ID, 'dolibarr_id', true ); + } + return $value; } /** diff --git a/includes/class-tax-doliwoo.php b/includes/class-wc-tax.php similarity index 64% rename from includes/class-tax-doliwoo.php rename to includes/class-wc-tax.php index f9c9d3c..3bae082 100644 --- a/includes/class-tax-doliwoo.php +++ b/includes/class-wc-tax.php @@ -18,15 +18,18 @@ */ /** - * DoliWoo tax management + * Tax management + * + * Dolibarr and WooCommerce tax implementations differ vastly. + * We declare specific WooCommerce tax classes and rates to be used in Dolibarr syncing. + * + * @package DoliWoo */ /** - * Class WC_Tax_Doliwoo - * - * Extend WC_Tax() to insert and update tax rates + * Tax management */ -class WC_Tax_Doliwoo extends WC_Tax { +class Doliwoo_WC_Tax extends WC_Tax { /** * Get the tax class associated with a VAT rate @@ -43,7 +46,8 @@ public function get_tax_class( $tax_rate ) { foreach ( $tax_classes as $class ) { $rates = $this->get_rates( $class ); - if ( array_values( $rates )[0]['rate'] == $tax_rate ) { + $rates_values = array_values( $rates ); + if ( $rates_values[0]['rate'] == $tax_rate ) { // Use the first class found return $class; } @@ -62,59 +66,21 @@ public function create_custom_tax_classes() { global $wpdb; $tax_name = __( 'VAT', 'doliwoo' ); - // First, create the rates - $declared_rates = array( - array( - 'tax_rate_country' => 'FR', - 'tax_rate' => '20', - 'tax_rate_name' => $tax_name, - 'tax_rate_priority' => '1', - 'tax_rate_order' => '0', - 'tax_rate_class' => '' - ), - array( - 'tax_rate_country' => 'FR', - 'tax_rate' => '10', - 'tax_rate_name' => $tax_name, - 'tax_rate_priority' => '1', - 'tax_rate_order' => '0', - 'tax_rate_class' => 'reduced' - ), - array( - 'tax_rate_country' => 'FR', - 'tax_rate' => '5', - 'tax_rate_name' => $tax_name, - 'tax_rate_priority' => '1', - 'tax_rate_order' => '0', - 'tax_rate_class' => 'super-reduced' - ), - array( - 'tax_rate_country' => 'FR', - 'tax_rate' => '2.1', - 'tax_rate_name' => $tax_name, - 'tax_rate_priority' => '1', - 'tax_rate_order' => '0', - 'tax_rate_class' => 'minimum' - ), - array( - 'tax_rate_country' => 'FR', - 'tax_rate' => '0', - 'tax_rate_name' => $tax_name, - 'tax_rate_priority' => '1', - 'tax_rate_order' => '0', - 'tax_rate_class' => 'zero' - ) - ); + $default_country = substr( strtolower( get_option( 'woocommerce_default_country' ) ), 0, 2 ); + + /** @var array $declared_rates The contry's VAT rate */ + include( 'tax_rates/' . $default_country . '.php' ); $db_taxes = $wpdb->get_results( - "SELECT tax_rate_id - , tax_rate_country - , tax_rate, tax_rate_name - , tax_rate_priority - , tax_rate_order - , tax_rate_class - FROM " . $wpdb->prefix . "woocommerce_tax_rates;", - ARRAY_A ); + 'SELECT tax_rate_id +, tax_rate_country +, tax_rate +, tax_rate_name +, tax_rate_priority +, tax_rate_order +, tax_rate_class FROM ' . $wpdb->prefix . 'woocommerce_tax_rates;', + ARRAY_A + ); // Struture database results $database_rates = array(); @@ -125,8 +91,8 @@ public function create_custom_tax_classes() { } // Insert missing classes - $declared_classes = array_column( $declared_rates, 'tax_rate_class' ); - $database_classes = array_column( $database_rates, 'tax_rate_class' ); + $declared_classes = wp_list_pluck( $declared_rates, 'tax_rate_class' ); + $database_classes = wp_list_pluck( $database_rates, 'tax_rate_class' ); foreach ( $declared_classes as $key => $class ) { if ( ! in_array( $class, $database_classes ) ) { $to_create = $declared_rates[ $key ]; @@ -142,9 +108,10 @@ public function create_custom_tax_classes() { ) { // _assoc is important. It allows strict checking to take 0 into account! if ( array_diff_assoc( $declared_rate, $database_rate ) ) { - ( $this->update_tax( + $this->update_tax( $tax_rate_id, - $declared_rate ) ); + $declared_rate + ); } } } @@ -153,9 +120,10 @@ public function create_custom_tax_classes() { // Now declare the classes $declared_classes = array_map( 'ucfirst', $declared_classes ); $classes_names = implode( "\n", $declared_classes ); + $existing_classes = get_option( 'woocommerce_tax_classes' ); update_option( 'woocommerce_tax_classes', - $classes_names + $existing_classes . $classes_names ); } @@ -186,10 +154,10 @@ public function update_tax( $tax_rate_id, $tax_rate ) { global $wpdb; return $wpdb->update( - $wpdb->prefix . "woocommerce_tax_rates", + $wpdb->prefix . 'woocommerce_tax_rates', $tax_rate, array( - 'tax_rate_id' => $tax_rate_id + 'tax_rate_id' => $tax_rate_id, ) ); } diff --git a/includes/settings.php b/includes/settings.php deleted file mode 100644 index d700579..0000000 --- a/includes/settings.php +++ /dev/null @@ -1,191 +0,0 @@ - - * Copyright (C) 2015 Maxime Lafourcade - * Copyright (C) 2015 Raphaël Doursenaud - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * DoliWoo settings - * - * WooCommerce settings integration. - */ - -if ( ! class_exists( 'WC_Integration_Doliwoo_Settings' ) ) : - - /** - * Doliwoo settings WooCommerce integration - */ - class WC_Integration_Doliwoo_Settings extends WC_Integration { - /** - * Init and hook in the integration. - */ - public function __construct() { - $this->id = 'doliwoo'; - $this->method_title = __( 'DoliWoo Settings', 'doliwoo' ); - $this->method_description = __( 'Dolibarr webservices access', 'doliwoo' ); - - // Load the settings - $this->init_form_fields(); - $this->init_settings(); - - // Define user set variables - $this->webservs_url = $this->get_option( 'webservs_url' ); - - $this->delay_update = $this->get_option( 'delay_update' ); - - $this->dolibarr_key = $this->get_option( 'dolibarr_key' ); - $this->sourceapplication - = $this->get_option( 'sourceapplication' ); - $this->dolibarr_login = $this->get_option( 'dolibarr_login' ); - $this->dolibarr_password - = $this->get_option( 'dolibarr_password' ); - $this->dolibarr_entity - = $this->get_option( 'dolibarr_entity' ); - $this->dolibarr_category_id - = $this->get_option( 'dolibarr_category_id' ); - $this->dolibarr_generic_id - = $this->get_option( 'dolibarr_generic_id' ); - - // Actions - add_action( 'woocommerce_update_options_integration_' . $this->id, - array( $this, 'process_admin_options' ) ); - } - - /** - * Initialize integration settings form fields. - * - * @return void - */ - public function init_form_fields() { - $this->form_fields = array( - 'sourceapplication' => array( - 'title' => __( 'Source application', 'doliwoo' ), - 'description' => __( 'How this application will identify itself to the webservice.', 'doliwoo' ), - 'type' => 'text', - 'desc_tip' => false, - 'default' => 'WooCommerce' - ), - 'webservs_url' => array( - 'title' => __( 'URL', 'doliwoo' ), - 'description' => __( 'Enter Dolibarr webservices root URL (i.e. https://mydolibarr.com/webservices)', - 'doliwoo' ), - 'type' => 'text', - 'desc_tip' => false, - 'default' => '' - ), - 'delay_update' => array( - 'title' => __( 'Delay', 'doliwoo' ), - 'description' => __( 'Choose the automatic update frequency' ), - 'type' => 'select', - 'desc_tip' => false, - 'options' => array( - 'hourly' => __( 'Once Hourly' ), - 'twicedaily' => __( 'Twice Daily' ), - 'daily' => __( 'Once Daily' ), - ), - ), - 'dolibarr_key' => array( - 'title' => __( 'Key', 'doliwoo' ), - 'description' => __( 'Enter your Dolibarr webservices key', 'doliwoo' ), - 'type' => 'text', - 'desc_tip' => false, - 'default' => '' - ), - 'dolibarr_login' => array( - 'title' => __( 'User login', 'doliwoo' ), - 'description' => __( 'Dolibarr actions will be done as this user', 'doliwoo' ), - 'type' => 'text', - 'desc_tip' => false, - 'default' => '' - ), - 'dolibarr_password' => array( - 'title' => __( 'User password', 'doliwoo' ), - 'type' => 'password', - 'desc_tip' => false, - 'default' => '' - ), - 'dolibarr_entity' => array( - 'title' => __( 'Entity', 'doliwoo' ), - 'description' => __( 'If you\'re using multicompany, the ID of the entity you want to integrate. Leave to 1 otherwise.', 'doliwoo' ), - 'type' => 'text', - 'desc_tip' => false, - 'default' => 1 - ), - 'dolibarr_category_id' => array( - 'title' => __( 'Product category', 'doliwoo' ), - 'description' => __( 'The ID of the product category you want to automatically import products from.', 'doliwoo' ), - 'type' => 'text', - 'desc_tip' => false, - 'default' => '' - ), - 'dolibarr_generic_id' => array( - 'title' => __( 'Generic thirdparty', 'doliwoo' ), - 'description' => __( 'The ID of the thirdparty that\'ll be used for anonymous orders.', 'doliwoo' ), - 'type' => 'text', - 'desc_tip' => false, - 'default' => '' - ), - ); - } - - /** - * Check if the fields URL Webservs is HTTPS - * - * @param string $key The form setting - * - * @return string The form value - */ - public function validate_webservs_url_field( $key ) { - $value = $_POST['woocommerce_doliwoo_webservs_url']; - - // Make sure we use HTTPS - if ( ( substr( $value, 0, 8 ) ) !== 'https://' ) { - $this->errors[] = __('The protocol to use is https://'); - } - - // Make sure we have the trailing slash - $value = trailingslashit( $value ); - - // Check that the server is available - try { - new SoapClient( $value . 'server_other.php?wsdl' ); - } catch ( SoapFault $exc ) { - $this->errors[] = __('The webservice is not available. Please check the URL.'); - } - - return $value; - } - - /** - * Display HTTPS is needed - * - * @return void - */ - public function display_errors() { - foreach ( $this->errors as $key => $value ) { - ?> -
-

- -

-
- 'FR', + 'tax_rate' => '20', + 'tax_rate_name' => $tax_name, + 'tax_rate_priority' => '1', + 'tax_rate_order' => '0', + 'tax_rate_class' => '', + ), + array( + 'tax_rate_country' => 'FR', + 'tax_rate' => '10', + 'tax_rate_name' => $tax_name, + 'tax_rate_priority' => '1', + 'tax_rate_order' => '0', + 'tax_rate_class' => 'reduced', + ), + array( + 'tax_rate_country' => 'FR', + 'tax_rate' => '5', + 'tax_rate_name' => $tax_name, + 'tax_rate_priority' => '1', + 'tax_rate_order' => '0', + 'tax_rate_class' => 'super-reduced', + ), + array( + 'tax_rate_country' => 'FR', + 'tax_rate' => '2.1', + 'tax_rate_name' => $tax_name, + 'tax_rate_priority' => '1', + 'tax_rate_order' => '0', + 'tax_rate_class' => 'minimum', + ), + array( + 'tax_rate_country' => 'FR', + 'tax_rate' => '0', + 'tax_rate_name' => $tax_name, + 'tax_rate_priority' => '1', + 'tax_rate_order' => '0', + 'tax_rate_class' => 'zero', + ), +); diff --git a/includes/tax_rates/it.php b/includes/tax_rates/it.php new file mode 100644 index 0000000..939e4b1 --- /dev/null +++ b/includes/tax_rates/it.php @@ -0,0 +1,27 @@ + 'IT', + 'tax_rate' => '22', + 'tax_rate_name' => $tax_name, + 'tax_rate_priority' => '1', + 'tax_rate_order' => '0', + 'tax_rate_class' => '', + ), + array( + 'tax_rate_country' => 'IT', + 'tax_rate' => '10', + 'tax_rate_name' => $tax_name, + 'tax_rate_priority' => '1', + 'tax_rate_order' => '0', + 'tax_rate_class' => 'reduced', + ), + array( + 'tax_rate_country' => 'IT', + 'tax_rate' => '4', + 'tax_rate_name' => $tax_name, + 'tax_rate_priority' => '1', + 'tax_rate_order' => '0', + 'tax_rate_class' => 'super-reduced', + ), +); diff --git a/languages/doliwoo-ca.po b/languages/doliwoo-ca.po new file mode 100644 index 0000000..1922406 --- /dev/null +++ b/languages/doliwoo-ca.po @@ -0,0 +1,196 @@ +# Copyright (C) 2015 GPC.solutions +# This file is distributed under the GPL-3.0+. +# Translators: +# Raphaël Doursenaud , 2015 +msgid "" +msgstr "" +"Project-Id-Version: DoliWoo\n" +"Report-Msgid-Bugs-To: https://github.com/GPCsolutions/doliwoo/issues\n" +"POT-Creation-Date: 2015-03-05 14:30:00+00:00\n" +"PO-Revision-Date: 2015-03-05 14:30+0000\n" +"Last-Translator: Raphaël Doursenaud \n" +"Language-Team: Catalan (http://www.transifex.com/projects/p/doliwoo/language/ca/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: ca\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: grunt-wp-i18n 0.5.0\n" +"X-Poedit-Basepath: ../\n" +"X-Poedit-Bookmarks: \n" +"X-Poedit-Country: United States\n" +"X-Poedit-KeywordsList: __;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_attr__;esc_html__;esc_attr_e;esc_html_e;esc_attr_x:1,2c;esc_html_x:1,2c;\n" +"X-Poedit-SearchPath-0: .\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Textdomain-Support: yes\n" + +#: doliwoo.php:229 +msgid "View DoliWoo Settings" +msgstr "" + +#: doliwoo.php:231 +msgid "Settings" +msgstr "" + +#. Plugin Name of the plugin/theme +msgid "DoliWoo" +msgstr "DoliWoo" + +#: includes/class-wc-integration.php:72 +msgid "Dolibarr webservices access" +msgstr "Accés webservice de Dolibarr" + +#: includes/class-wc-integration.php:110 +msgid "Source application" +msgstr "Aplicació font" + +#: includes/class-wc-integration.php:111 +msgid "How this application will identify itself to the webservice." +msgstr "Com s'identificarà aquesta aplicació al webservice." + +#: includes/class-wc-integration.php:117 +msgid "URL" +msgstr "URL" + +#: includes/class-wc-integration.php:118 +msgid "" +"Enter Dolibarr webservices root URL (i.e. " +"https://mydolibarr.com/webservices)" +msgstr "Entra la URL arrel del webservice de Dolibarr (i.e. https://mydolibarr.com/webservices)" + +#: includes/class-wc-integration.php:127 +msgid "Delay" +msgstr "Retard" + +#: includes/class-wc-integration.php:128 +msgid "Choose the automatic update frequency" +msgstr "Escull la freqüència de l'actualització automàtica" + +#: includes/class-wc-integration.php:132 +msgid "Once Hourly" +msgstr "Un cop cada hora" + +#: includes/class-wc-integration.php:133 +msgid "Twice Daily" +msgstr "Dos cops al dia" + +#: includes/class-wc-integration.php:134 +msgid "Once Daily" +msgstr "Un cop al dia" + +#: includes/class-wc-integration.php:139 +msgid "Key" +msgstr "Clau" + +#: includes/class-wc-integration.php:140 +msgid "Enter your Dolibarr webservices key" +msgstr "Entra la teva clau del webservice de Dolibarr" + +#: includes/class-wc-integration.php:146 +msgid "User login" +msgstr "Usuari d'inici de sessió" + +#: includes/class-wc-integration.php:147 +msgid "Dolibarr actions will be done as this user" +msgstr "Les accions de Dolibarr es duran a terme amb aquest usuari" + +#: includes/class-wc-integration.php:153 +msgid "User password" +msgstr "Paraula de pas de l'usuari" + +#: includes/class-wc-integration.php:159 +msgid "Entity" +msgstr "Entitat (empresa)" + +#: includes/class-wc-integration.php:160 +msgid "" +"If you're using multicompany, the ID of the entity you want to integrate. " +"Leave to 1 otherwise." +msgstr "Si utilitzes multiempresa, l'ID de l'entitat (empresa) que vols integrar. Déixa-ho amb 1 si no és així." + +#: includes/class-wc-integration.php:166 +msgid "Products category" +msgstr "" + +#: includes/class-wc-integration.php:167 +msgid "" +"The ID of the products category you want to automatically import products " +"from." +msgstr "La ID de la categoria de producte de la que vols importar productes automàticament." + +#: includes/class-wc-integration.php:173 +msgid "Generic thirdparty" +msgstr "Tercer per defecte" + +#: includes/class-wc-integration.php:174 +msgid "The ID of the thirdparty that'll be used for anonymous orders." +msgstr "La ID del tercer per defecte que serà utilitzat en les comandes anònimes." + +#: includes/class-wc-integration.php:180 +msgid "Dolibarr version" +msgstr "" + +#: includes/class-wc-integration.php:181 +msgid "" +"If the webservice communication is OK, it displays your Dolibarr version" +msgstr "" + +#: includes/class-wc-integration.php:211 +msgid "Please configure the plugin." +msgstr "" + +#: includes/class-wc-integration.php:212 +msgid "Not compatible! Please use at least Dolibarr v3.4.0." +msgstr "" + +#: includes/class-wc-integration.php:213 +msgid "OK!" +msgstr "" + +#: includes/class-wc-integration.php:214 +msgid "(Detected v%s)" +msgstr "" + +#: includes/class-wc-integration.php:255 +msgid "The protocol to use is https://" +msgstr "El protocol per utilitzar és https://" + +#: includes/class-wc-integration.php:265 includes/class-wc-integration.php:358 +msgid "The webservice is not available. Please check the URL." +msgstr "El servei webservice no està disponible. Siusplau, comprova la URL." + +#: includes/class-wc-params.php:67 +msgid "Dolibarr" +msgstr "Dolibarr" + +#: includes/class-wc-params.php:70 +msgid "User ID" +msgstr "ID de l'usuari" + +#: includes/class-wc-params.php:71 +msgid "The Dolibarr ID for this user" +msgstr "" + +#: includes/class-wc-params.php:139 +msgid "Dolibarr User ID" +msgstr "ID de l'usuari Dolibarr" + +#: includes/class-wc-tax.php:67 +msgid "VAT" +msgstr "IVA" + +#. Plugin URI of the plugin/theme +msgid "http://gpcsolutions.github.io/doliwoo" +msgstr "http://gpcsolutions.github.io/doliwoo" + +#. Description of the plugin/theme +msgid "Dolibarr WooCommerce integration" +msgstr "Dolibarr WooCommerce integration" + +#. Author of the plugin/theme +msgid "GPC.solutions" +msgstr "GPC.solutions" + +#. Author URI of the plugin/theme +msgid "https://gpcsolutions.fr" +msgstr "" diff --git a/languages/doliwoo-es_ES.po b/languages/doliwoo-es_ES.po new file mode 100644 index 0000000..5d49a2f --- /dev/null +++ b/languages/doliwoo-es_ES.po @@ -0,0 +1,196 @@ +# Copyright (C) 2015 GPC.solutions +# This file is distributed under the GPL-3.0+. +# Translators: +# Raphaël Doursenaud , 2015 +msgid "" +msgstr "" +"Project-Id-Version: DoliWoo\n" +"Report-Msgid-Bugs-To: https://github.com/GPCsolutions/doliwoo/issues\n" +"POT-Creation-Date: 2015-03-05 14:30:00+00:00\n" +"PO-Revision-Date: 2015-03-05 14:30+0000\n" +"Last-Translator: Raphaël Doursenaud \n" +"Language-Team: Spanish (Spain) (http://www.transifex.com/projects/p/doliwoo/language/es_ES/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: es_ES\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: grunt-wp-i18n 0.5.0\n" +"X-Poedit-Basepath: ../\n" +"X-Poedit-Bookmarks: \n" +"X-Poedit-Country: United States\n" +"X-Poedit-KeywordsList: __;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_attr__;esc_html__;esc_attr_e;esc_html_e;esc_attr_x:1,2c;esc_html_x:1,2c;\n" +"X-Poedit-SearchPath-0: .\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Textdomain-Support: yes\n" + +#: doliwoo.php:229 +msgid "View DoliWoo Settings" +msgstr "" + +#: doliwoo.php:231 +msgid "Settings" +msgstr "" + +#. Plugin Name of the plugin/theme +msgid "DoliWoo" +msgstr "DoliWoo" + +#: includes/class-wc-integration.php:72 +msgid "Dolibarr webservices access" +msgstr "Acceso a webservices Dolibarr" + +#: includes/class-wc-integration.php:110 +msgid "Source application" +msgstr "Aplicación fuente" + +#: includes/class-wc-integration.php:111 +msgid "How this application will identify itself to the webservice." +msgstr "Cómo se identificará esta aplicación al webservice." + +#: includes/class-wc-integration.php:117 +msgid "URL" +msgstr "URL" + +#: includes/class-wc-integration.php:118 +msgid "" +"Enter Dolibarr webservices root URL (i.e. " +"https://mydolibarr.com/webservices)" +msgstr "Entra la URL raíz del webservice de Dolibarr (ej.: https://mydolibarr.com/webservices)" + +#: includes/class-wc-integration.php:127 +msgid "Delay" +msgstr "Retraso" + +#: includes/class-wc-integration.php:128 +msgid "Choose the automatic update frequency" +msgstr "Escoje la frecuencia de actualización automática" + +#: includes/class-wc-integration.php:132 +msgid "Once Hourly" +msgstr "Una vez cada hora" + +#: includes/class-wc-integration.php:133 +msgid "Twice Daily" +msgstr "Dos veces al día" + +#: includes/class-wc-integration.php:134 +msgid "Once Daily" +msgstr "Una vez al día" + +#: includes/class-wc-integration.php:139 +msgid "Key" +msgstr "Llave" + +#: includes/class-wc-integration.php:140 +msgid "Enter your Dolibarr webservices key" +msgstr "Entra la llave del webservice de Dolibarr" + +#: includes/class-wc-integration.php:146 +msgid "User login" +msgstr "Inicio de sesión de usuario" + +#: includes/class-wc-integration.php:147 +msgid "Dolibarr actions will be done as this user" +msgstr "Las acciones de Dolibarr ser harán con este usuario" + +#: includes/class-wc-integration.php:153 +msgid "User password" +msgstr "Contraseña de usuario" + +#: includes/class-wc-integration.php:159 +msgid "Entity" +msgstr "Entidad (empresa)" + +#: includes/class-wc-integration.php:160 +msgid "" +"If you're using multicompany, the ID of the entity you want to integrate. " +"Leave to 1 otherwise." +msgstr "Si estás usando multiempresa, el ID de la entidad que quieres integrar. Déjalo en 1 si no es así." + +#: includes/class-wc-integration.php:166 +msgid "Products category" +msgstr "Categoría de productos" + +#: includes/class-wc-integration.php:167 +msgid "" +"The ID of the products category you want to automatically import products " +"from." +msgstr "El ID de la categoría de productos de la que quieres importar productos." + +#: includes/class-wc-integration.php:173 +msgid "Generic thirdparty" +msgstr "Tercero por defecto" + +#: includes/class-wc-integration.php:174 +msgid "The ID of the thirdparty that'll be used for anonymous orders." +msgstr "El ID del tercero que será usado para los pedidos anónimos." + +#: includes/class-wc-integration.php:180 +msgid "Dolibarr version" +msgstr "" + +#: includes/class-wc-integration.php:181 +msgid "" +"If the webservice communication is OK, it displays your Dolibarr version" +msgstr "" + +#: includes/class-wc-integration.php:211 +msgid "Please configure the plugin." +msgstr "" + +#: includes/class-wc-integration.php:212 +msgid "Not compatible! Please use at least Dolibarr v3.4.0." +msgstr "" + +#: includes/class-wc-integration.php:213 +msgid "OK!" +msgstr "" + +#: includes/class-wc-integration.php:214 +msgid "(Detected v%s)" +msgstr "" + +#: includes/class-wc-integration.php:255 +msgid "The protocol to use is https://" +msgstr "El protocolo a usar es https://" + +#: includes/class-wc-integration.php:265 includes/class-wc-integration.php:358 +msgid "The webservice is not available. Please check the URL." +msgstr "El servicio webservice no está disponible. Por favor, comprueba la URL." + +#: includes/class-wc-params.php:67 +msgid "Dolibarr" +msgstr "Dolibarr" + +#: includes/class-wc-params.php:70 +msgid "User ID" +msgstr "ID de usuario" + +#: includes/class-wc-params.php:71 +msgid "The Dolibarr ID for this user" +msgstr "" + +#: includes/class-wc-params.php:139 +msgid "Dolibarr User ID" +msgstr "ID de usuario Dolibarr" + +#: includes/class-wc-tax.php:67 +msgid "VAT" +msgstr "IVA" + +#. Plugin URI of the plugin/theme +msgid "http://gpcsolutions.github.io/doliwoo" +msgstr "http://gpcsolutions.github.io/doliwoo" + +#. Description of the plugin/theme +msgid "Dolibarr WooCommerce integration" +msgstr "" + +#. Author of the plugin/theme +msgid "GPC.solutions" +msgstr "GPC.solutions" + +#. Author URI of the plugin/theme +msgid "https://gpcsolutions.fr" +msgstr "" diff --git a/languages/doliwoo-fr_FR.mo b/languages/doliwoo-fr_FR.mo deleted file mode 100644 index 83619c3..0000000 Binary files a/languages/doliwoo-fr_FR.mo and /dev/null differ diff --git a/languages/doliwoo-fr_FR.po b/languages/doliwoo-fr_FR.po index 04ad92a..8777f8e 100644 --- a/languages/doliwoo-fr_FR.po +++ b/languages/doliwoo-fr_FR.po @@ -1,13 +1,13 @@ -# Copyright (C) 2015 Doliwoo -# This file is distributed under the same license as the Doliwoo package. +# Copyright (C) 2015 GPC.solutions +# This file is distributed under the GPL-3.0+. # Translators: # Raphaël Doursenaud , 2015 msgid "" msgstr "" "Project-Id-Version: DoliWoo\n" -"Report-Msgid-Bugs-To: http://wordpress.org/support/plugin/doliwoo\n" -"POT-Creation-Date: 2015-02-18 16:23:59+00:00\n" -"PO-Revision-Date: 2015-02-18 18:45+0100\n" +"Report-Msgid-Bugs-To: https://github.com/GPCsolutions/doliwoo/issues\n" +"POT-Creation-Date: 2015-03-05 14:30:00+00:00\n" +"PO-Revision-Date: 2015-03-05 14:30+0000\n" "Last-Translator: Raphaël Doursenaud \n" "Language-Team: French (France) (http://www.transifex.com/projects/p/doliwoo/language/fr_FR/)\n" "MIME-Version: 1.0\n" @@ -15,139 +15,173 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Language: fr_FR\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Poedit 1.7.4\n" +"X-Generator: grunt-wp-i18n 0.5.0\n" +"X-Poedit-Basepath: ../\n" +"X-Poedit-Bookmarks: \n" +"X-Poedit-Country: United States\n" +"X-Poedit-KeywordsList: __;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_attr__;esc_html__;esc_attr_e;esc_html_e;esc_attr_x:1,2c;esc_html_x:1,2c;\n" +"X-Poedit-SearchPath-0: .\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Textdomain-Support: yes\n" + +#: doliwoo.php:229 +msgid "View DoliWoo Settings" +msgstr "Voir les réglages de DoliWoo" + +#: doliwoo.php:231 +msgid "Settings" +msgstr "Réglages" -#: doliwoo.php:51 -msgid "This plugin needs SOAP and OpenSSL PHP extensions." -msgstr "Cette extension nécessite les extensions PHP SOAP et OpenSSL." - -#: doliwoo.php:55 -msgid "This plugin needs SOAP PHP extension." -msgstr "Cette extension nécessite l'extension PHP SOAP." - -#: doliwoo.php:59 -msgid "This plugin needs OpenSSL PHP extension." -msgstr "Cette extension nécessite l'extension PHP OpenSSL." - -#: doliwoo.php:209 -msgid "This extension needs WooCommerce" -msgstr "Cette extension nécessite WooCommerce" - -#: includes/class-doliwoo-parameters.php:62 -msgid "Dolibarr" -msgstr "Dolibarr" - -#: includes/class-doliwoo-parameters.php:65 includes/class-doliwoo-parameters.php:128 -msgid "Dolibarr User ID" -msgstr "Identifiant Utilisateur Dolibarr" - -#: includes/class-tax-doliwoo.php:63 -msgid "VAT" -msgstr "TVA" - -#: includes/settings.php:37 -msgid "DoliWoo Settings" -msgstr "Réglages DoliWoo" +#. Plugin Name of the plugin/theme +msgid "DoliWoo" +msgstr "DoliWoo" -#: includes/settings.php:38 +#: includes/class-wc-integration.php:72 msgid "Dolibarr webservices access" msgstr "Accès aux webservices Dolibarr" -#: includes/settings.php:75 +#: includes/class-wc-integration.php:110 msgid "Source application" msgstr "Nom de l'application" -#: includes/settings.php:76 +#: includes/class-wc-integration.php:111 msgid "How this application will identify itself to the webservice." msgstr "Comment cette application s'identifie auprès du webservice." -#: includes/settings.php:82 +#: includes/class-wc-integration.php:117 msgid "URL" msgstr "URL" -#: includes/settings.php:83 -msgid "Enter Dolibarr webservices root URL (i.e. https://mydolibarr.com/webservices)" +#: includes/class-wc-integration.php:118 +msgid "" +"Enter Dolibarr webservices root URL (i.e. " +"https://mydolibarr.com/webservices)" msgstr "Entrez l'URL racine des webservices de Dolibarr (i.e. https://mydolibarr.com/webservices)" -#: includes/settings.php:90 +#: includes/class-wc-integration.php:127 msgid "Delay" msgstr "Délai" -#: includes/settings.php:91 +#: includes/class-wc-integration.php:128 msgid "Choose the automatic update frequency" msgstr "Choisissez la fréquence de mise à jour automatique" -#: includes/settings.php:95 +#: includes/class-wc-integration.php:132 msgid "Once Hourly" msgstr "Une fois par heure" -#: includes/settings.php:96 +#: includes/class-wc-integration.php:133 msgid "Twice Daily" msgstr "Deux fois par jour" -#: includes/settings.php:97 +#: includes/class-wc-integration.php:134 msgid "Once Daily" msgstr "Une fois par jour" -#: includes/settings.php:101 +#: includes/class-wc-integration.php:139 msgid "Key" msgstr "Clé" -#: includes/settings.php:102 +#: includes/class-wc-integration.php:140 msgid "Enter your Dolibarr webservices key" msgstr "Entrez votre clé du webservices de Dolibarr" -#: includes/settings.php:108 +#: includes/class-wc-integration.php:146 msgid "User login" msgstr "Identifiant utilisateur" -#: includes/settings.php:109 +#: includes/class-wc-integration.php:147 msgid "Dolibarr actions will be done as this user" msgstr "Les actions de Dolibarr seront attribuées à cet utilisateur" -#: includes/settings.php:115 +#: includes/class-wc-integration.php:153 msgid "User password" msgstr "Mot de passe utilisateur" -#: includes/settings.php:121 +#: includes/class-wc-integration.php:159 msgid "Entity" msgstr "Entité" -#: includes/settings.php:122 -msgid "If you're using multicompany, the ID of the entity you want to integrate. Leave to 1 otherwise." +#: includes/class-wc-integration.php:160 +msgid "" +"If you're using multicompany, the ID of the entity you want to integrate. " +"Leave to 1 otherwise." msgstr "Si vous utilisez multi-société, l'ID de l'entité que vous souhaitez intégrer. Sinon laissez à 1." -#: includes/settings.php:128 -msgid "Product category" -msgstr "Catégorie du Produit" +#: includes/class-wc-integration.php:166 +msgid "Products category" +msgstr "Catégorie des produits" -#: includes/settings.php:129 -msgid "The ID of the product category you want to automatically import products from." -msgstr "L'ID de la catégorie de produits que vous souhaitez importer automatiquement." +#: includes/class-wc-integration.php:167 +msgid "" +"The ID of the products category you want to automatically import products " +"from." +msgstr "L'ID de la catégorie des produits que vous souhaitez importer automatiquement." -#: includes/settings.php:135 +#: includes/class-wc-integration.php:173 msgid "Generic thirdparty" msgstr "Tiers générique" -#: includes/settings.php:136 +#: includes/class-wc-integration.php:174 msgid "The ID of the thirdparty that'll be used for anonymous orders." msgstr "L'Id du tiers qui va être utilisé pour les commandes anonymes" -#: includes/settings.php:156 +#: includes/class-wc-integration.php:180 +msgid "Dolibarr version" +msgstr "Version de Dolibarr" + +#: includes/class-wc-integration.php:181 +msgid "" +"If the webservice communication is OK, it displays your Dolibarr version" +msgstr "Vérifie si la communication est établie au travers du webservice et récupère la version de Dolibarr" + +#: includes/class-wc-integration.php:211 +msgid "Please configure the plugin." +msgstr "Veuillez configurer l'extension." + +#: includes/class-wc-integration.php:212 +msgid "Not compatible! Please use at least Dolibarr v3.4.0." +msgstr "Version incompatible. Veuillez utiliser Dolibarr v3.4.0 minimum." + +#: includes/class-wc-integration.php:213 +msgid "OK!" +msgstr "OK !" + +#: includes/class-wc-integration.php:214 +msgid "(Detected v%s)" +msgstr "(v%s détectée)" + +#: includes/class-wc-integration.php:255 msgid "The protocol to use is https://" msgstr "Le protocole à utiliser est https://" -#: includes/settings.php:166 +#: includes/class-wc-integration.php:265 includes/class-wc-integration.php:358 msgid "The webservice is not available. Please check the URL." msgstr "Le webservice n'est pas disponible. Merci de vérifier l'URL." -#. Plugin Name of the plugin/theme -msgid "Doliwoo" -msgstr "DoliWoo" +#: includes/class-wc-params.php:67 +msgid "Dolibarr" +msgstr "Dolibarr" + +#: includes/class-wc-params.php:70 +msgid "User ID" +msgstr "Identifiant utilisateur" + +#: includes/class-wc-params.php:71 +msgid "The Dolibarr ID for this user" +msgstr "L'identifiant Dolibarr pour cet utilisateur" + +#: includes/class-wc-params.php:139 +msgid "Dolibarr User ID" +msgstr "Identifiant Utilisateur Dolibarr" + +#: includes/class-wc-tax.php:67 +msgid "VAT" +msgstr "TVA" #. Plugin URI of the plugin/theme -msgid "TODO (https://gpcsolutions.fr/doliwoo)" -msgstr "https://gpcsolutions.fr/doliwoo" +msgid "http://gpcsolutions.github.io/doliwoo" +msgstr "http://gpcsolutions.github.io/doliwoo" #. Description of the plugin/theme msgid "Dolibarr WooCommerce integration" @@ -156,3 +190,7 @@ msgstr "Intégration Dolibarr WooCommerc" #. Author of the plugin/theme msgid "GPC.solutions" msgstr "GPC.solutions" + +#. Author URI of the plugin/theme +msgid "https://gpcsolutions.fr" +msgstr "https://gpcsolutions.fr" diff --git a/languages/doliwoo.pot b/languages/doliwoo.pot index 5ff65ba..5f88e1d 100644 --- a/languages/doliwoo.pot +++ b/languages/doliwoo.pot @@ -1,153 +1,185 @@ -# Copyright (C) 2015 DoliWoo -# This file is distributed under the same license as the Doliwoo package. +# Copyright (C) 2015 GPC.solutions +# This file is distributed under the GPL-3.0+. msgid "" msgstr "" -"Project-Id-Version: DoliWoo 0.0.1\n" -"Report-Msgid-Bugs-To: http://wordpress.org/support/plugin/doliwoo\n" -"POT-Creation-Date: 2015-02-18 16:23:59+00:00\n" +"Project-Id-Version: DoliWoo 0.0.2-alpha\n" +"Report-Msgid-Bugs-To: https://github.com/GPCsolutions/doliwoo/issues\n" +"POT-Creation-Date: 2015-03-05 14:30:32+00:00\n" "MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" +"Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "PO-Revision-Date: 2015-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" +"X-Generator: grunt-wp-i18n 0.5.0\n" +"X-Poedit-KeywordsList: " +"__;_e;_x:1,2c;_ex:1,2c;_n:1,2;_nx:1,2,4c;_n_noop:1,2;_nx_noop:1,2,3c;esc_" +"attr__;esc_html__;esc_attr_e;esc_html_e;esc_attr_x:1,2c;esc_html_x:1,2c;\n" +"Language: en\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Poedit-Country: United States\n" +"X-Poedit-SourceCharset: UTF-8\n" +"X-Poedit-Basepath: ../\n" +"X-Poedit-SearchPath-0: .\n" +"X-Poedit-Bookmarks: \n" +"X-Textdomain-Support: yes\n" -#: doliwoo.php:51 -msgid "This plugin needs SOAP and OpenSSL PHP extensions." +#: doliwoo.php:229 +msgid "View DoliWoo Settings" msgstr "" -#: doliwoo.php:55 -msgid "This plugin needs SOAP PHP extension." +#: doliwoo.php:231 +msgid "Settings" msgstr "" -#: doliwoo.php:59 -msgid "This plugin needs OpenSSL PHP extension." -msgstr "" - -#: doliwoo.php:209 -msgid "This extension needs WooCommerce" -msgstr "" - -#: includes/class-doliwoo-parameters.php:62 -msgid "Dolibarr" -msgstr "" - -#: includes/class-doliwoo-parameters.php:65 -#: includes/class-doliwoo-parameters.php:128 -msgid "Dolibarr User ID" -msgstr "" - -#: includes/class-tax-doliwoo.php:63 -msgid "VAT" -msgstr "" - -#: includes/settings.php:37 -msgid "DoliWoo Settings" +#. Plugin Name of the plugin/theme +msgid "DoliWoo" msgstr "" -#: includes/settings.php:38 +#: includes/class-wc-integration.php:72 msgid "Dolibarr webservices access" msgstr "" -#: includes/settings.php:75 +#: includes/class-wc-integration.php:110 msgid "Source application" msgstr "" -#: includes/settings.php:76 +#: includes/class-wc-integration.php:111 msgid "How this application will identify itself to the webservice." msgstr "" -#: includes/settings.php:82 +#: includes/class-wc-integration.php:117 msgid "URL" msgstr "" -#: includes/settings.php:83 +#: includes/class-wc-integration.php:118 msgid "" -"Enter Dolibarr webservices root URL (i.e. https://mydolibarr.com/webservices)" +"Enter Dolibarr webservices root URL (i.e. " +"https://mydolibarr.com/webservices)" msgstr "" -#: includes/settings.php:90 +#: includes/class-wc-integration.php:127 msgid "Delay" msgstr "" -#: includes/settings.php:91 +#: includes/class-wc-integration.php:128 msgid "Choose the automatic update frequency" msgstr "" -#: includes/settings.php:95 +#: includes/class-wc-integration.php:132 msgid "Once Hourly" msgstr "" -#: includes/settings.php:96 +#: includes/class-wc-integration.php:133 msgid "Twice Daily" msgstr "" -#: includes/settings.php:97 +#: includes/class-wc-integration.php:134 msgid "Once Daily" msgstr "" -#: includes/settings.php:101 +#: includes/class-wc-integration.php:139 msgid "Key" msgstr "" -#: includes/settings.php:102 +#: includes/class-wc-integration.php:140 msgid "Enter your Dolibarr webservices key" msgstr "" -#: includes/settings.php:108 +#: includes/class-wc-integration.php:146 msgid "User login" msgstr "" -#: includes/settings.php:109 +#: includes/class-wc-integration.php:147 msgid "Dolibarr actions will be done as this user" msgstr "" -#: includes/settings.php:115 +#: includes/class-wc-integration.php:153 msgid "User password" msgstr "" -#: includes/settings.php:121 +#: includes/class-wc-integration.php:159 msgid "Entity" msgstr "" -#: includes/settings.php:122 +#: includes/class-wc-integration.php:160 msgid "" "If you're using multicompany, the ID of the entity you want to integrate. " "Leave to 1 otherwise." msgstr "" -#: includes/settings.php:128 -msgid "Product category" +#: includes/class-wc-integration.php:166 +msgid "Products category" msgstr "" -#: includes/settings.php:129 +#: includes/class-wc-integration.php:167 msgid "" -"The ID of the product category you want to automatically import products " +"The ID of the products category you want to automatically import products " "from." msgstr "" -#: includes/settings.php:135 +#: includes/class-wc-integration.php:173 msgid "Generic thirdparty" msgstr "" -#: includes/settings.php:136 +#: includes/class-wc-integration.php:174 msgid "The ID of the thirdparty that'll be used for anonymous orders." msgstr "" -#: includes/settings.php:156 +#: includes/class-wc-integration.php:180 +msgid "Dolibarr version" +msgstr "" + +#: includes/class-wc-integration.php:181 +msgid "If the webservice communication is OK, it displays your Dolibarr version" +msgstr "" + +#: includes/class-wc-integration.php:211 +msgid "Please configure the plugin." +msgstr "" + +#: includes/class-wc-integration.php:212 +msgid "Not compatible! Please use at least Dolibarr v3.4.0." +msgstr "" + +#: includes/class-wc-integration.php:213 +msgid "OK!" +msgstr "" + +#: includes/class-wc-integration.php:214 +msgid "(Detected v%s)" +msgstr "" + +#: includes/class-wc-integration.php:255 msgid "The protocol to use is https://" msgstr "" -#: includes/settings.php:166 +#: includes/class-wc-integration.php:265 includes/class-wc-integration.php:358 msgid "The webservice is not available. Please check the URL." msgstr "" -#. Plugin Name of the plugin/theme -msgid "Doliwoo" +#: includes/class-wc-params.php:67 +msgid "Dolibarr" +msgstr "" + +#: includes/class-wc-params.php:70 +msgid "User ID" +msgstr "" + +#: includes/class-wc-params.php:71 +msgid "The Dolibarr ID for this user" +msgstr "" + +#: includes/class-wc-params.php:139 +msgid "Dolibarr User ID" +msgstr "" + +#: includes/class-wc-tax.php:67 +msgid "VAT" msgstr "" #. Plugin URI of the plugin/theme -msgid "TODO (https://gpcsolutions.fr/doliwoo)" +msgid "http://gpcsolutions.github.io/doliwoo" msgstr "" #. Description of the plugin/theme @@ -157,3 +189,7 @@ msgstr "" #. Author of the plugin/theme msgid "GPC.solutions" msgstr "" + +#. Author URI of the plugin/theme +msgid "https://gpcsolutions.fr" +msgstr "" \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..354a5c5 --- /dev/null +++ b/package.json @@ -0,0 +1,47 @@ +{ + "name": "doliwoo", + "version": "1.0.0", + "description": "Integrate Dolibarr with a WooCommerce shop.", + "keywords": [ + "wordpress", + "dolibarr", + "woocommerce", + "ecommerce", + "erp", + "integration" + ], + "homepage": "https://gpcsolutions.github.io/doliwoo", + "bugs": "https://github.com/GPCsolutions/doliwoo/issues", + "license": "GPL-3.0+", + "author": "GPC.solutions", + "maintainers": [ + "Raphaël Doursenaud " + ], + "contributors": [ + "Cédric Salvador", + "Maxime Lafourcade" + ], + "main": "doliwoo.php", + "repository": { + "type": "git", + "url": "https://github.com/GPCsolutions/doliwoo" + }, + "devDependencies": { + "grunt": "~0.4.2", + "grunt-checkwpversion": "^0.3.0", + "grunt-composer": "^0.4.4", + "grunt-contrib-clean": "^0.6.0", + "grunt-contrib-compress": "^0.13.0", + "grunt-contrib-copy": "^0.7.0", + "grunt-exec": "^0.4.6", + "grunt-phpcs": "^0.2.3", + "grunt-phpdoc": "^0.1.1", + "grunt-phplint": "0.0.5", + "grunt-po2mo": "^0.1.2", + "grunt-sync-json": "^0.3.1", + "grunt-wp-i18n": "^0.5.0", + "grunt-wp-readme-to-markdown": "^0.8.0", + "load-grunt-tasks": "^3.1.0", + "time-grunt": "^1.0.0" + } +} diff --git a/readme.txt b/readme.txt index a36002f..3b33b6f 100644 --- a/readme.txt +++ b/readme.txt @@ -1,14 +1,13 @@ -=== Doliwoo === -Contributors: GPC.solutions -Donate Link: TODO (https://gpcsolutions.fr/donate) -Tags: dolibarr, woocommerce, ecommerce, erp, integration -Author URI: https://gpcsolutions.fr -Plugin URI: https://gpcsolutions.github.io/doliwoo -Requires at least: 3.7.1 -Tested up to: 3.7.1 -Stable tag: master -License: GPLv3 -License URI: http://www.gnu.org/licenses/gpl-3.0.html +=== DoliWoo === +Contributors: GPC.solutions +Tags: dolibarr, woocommerce, ecommerce, erp, integration +Author URI: https://gpcsolutions.fr +Plugin URI: https://gpcsolutions.github.io/doliwoo +Requires at least: 3.7.1 +Tested up to: 3.7.1 +Stable tag: 1.0.0 +License: GPL-3.0+ +License URI: http://www.gnu.org/licenses/gpl-3.0.html Integrate Dolibarr with a WooCommerce shop. @@ -20,34 +19,40 @@ It leverages Dolibarr webservices feature to exchange data. = Features = **Dolibarr to WooCommerce** + * Periodic sync of products informations including images and stock informations * Link customers to existing thirdparties **WooCommerce to Dolibarr** + * Create thirdparties * Create customer orders **Known missing (TODO)** -* International VAT rates management + * Products stock informations resync on orders * Invoicing * Payments * Multiple languages products management **Known issues** -WooCommerce VAT management vastly differs from Dolibarr and we need equivalence tables. -Only French equivalence table is shipped at the moment. + +WooCommerce VAT management vastly differs from Dolibarr and we need equivalence tables. +Only French and italian equivalence tables are shipped at the moment. = Requirements = **PHP extensions** + * SOAP * OpenSSL **WordPress plugins** + * Woocommerce >= 2.0.0 **Dolibarr** + * HTTPS access with a valid certificate * Dolibarr >= 3.4.0 * Modules: @@ -58,37 +63,43 @@ Only French equivalence table is shipped at the moment. * Orders == Installation == -* Make sure the WooCommerce plugin is installed into your WordPress -* Extract the zip file to the 'wp-content/plugins/' directory of your WordPress installation -* Activate the plugin from 'Plugins' WordPress settings page -* Go to 'WooCommerce' 'Settings' under the 'Integration' tab and configure the 'Doliwoo' section + +1. Make sure the WooCommerce plugin is installed into your WordPress +2. Extract the zip file to the 'wp-content/plugins/' directory of your WordPress installation +3. Activate the plugin from 'Plugins' WordPress settings page +4. Go to 'WooCommerce' 'Settings' under the 'Integration' tab and configure the 'Doliwoo' section == Frequently Asked Questions == = Is this plugin stable and useable in a production environment? = -NO! This is beta code. This project started as an internal proof of concept and has just been reviewed. +NO! This is beta code. This project started as an internal proof of concept and has just been reviewed. But you're very welcome to test it on a pre-production environment. = OK, so how can I make it happen then? = -You can help by testing, providing detailed bug reports, documentation or even code. +You can help by testing, providing detailed bug reports, documentation or even code. Alternatively, you can buy paid support and/or development services from us: [GPC.solutions](https://gpcsolutions.fr). = Why do I need to use HTTPS with a good known SSL certificate? = -Otherwise SOAP requests will fail. - -This is a security feature to make sure your important data is properly encrypted in transit between WooCommerce and Dolibarr. - -You may allow insecure requests by tweaking the source code if you know what you're doing but we don't recommend that. +Otherwise SOAP requests will fail. +This is a security feature to make sure your important data is properly encrypted in transit between WooCommerce and Dolibarr. +You may allow insecure requests by tweaking the source code if you know what you're doing but we don't recommend that. == Screenshots == -1. FIXME: Placeholder +1. The configuration page == Changelog == += 1.0.0 = + +* First stable release +* Polished errors reporting +* Polished interface +* Basic international VAT rates management + = 0.0.1 = * First beta release @@ -99,6 +110,6 @@ You may allow insecure requests by tweaking the source code if you know what you == Upgrade Notice == -= 0.0.1 = += 1.0.0 = -N.A. +Stable release