diff --git a/README.md b/README.md
index f695ac102..2e1f60799 100644
--- a/README.md
+++ b/README.md
@@ -16,10 +16,11 @@
[](https://docsify.js.org/)

[](https://www.youtube.com/channel/UCxI0ziSiRXXTqQ-XfFJr7-w)
+
Myddleware is the customisable free open-source platform that facilitates data migration and synchronisation between applications.
-
+
[On our documentation website,](https://myddleware.github.io/myddleware) you’ll find everything you’re looking for to master Myddleware, including step-by-step tutorials. You can also tailor Myddleware to your needs by creating you custom code. Please use [our github](https://github.com/Myddleware) to share it.
@@ -209,3 +210,10 @@ The MAILER_URL is optional. It is used by Myddleware to send you notification em
## Contributing
> Myddleware relies on the [Symfony Framework](https://symfony.com/), a free open-source PHP framework. If you would like to contribute to our source code, you can first familiarise yourself with the [Symfony documentation](https://symfony.com/doc/current/index.html)
+
+Myddleware is an Open Source community project. All contributions are welcome, no matter how big or small. There are many ways to contribute to the project.
+You can of course help us improve and debug our source code, but you can also start by simply reporting issues & bugs or suggesting new features on our [GitHub Issues forum](https://github.com/Myddleware/myddleware/issues), or review and leave comments on [Pull Requests](https://github.com/Myddleware/myddleware/pulls).
+
+If you would like to contribute to Myddleware source code, please refer to the [developer's guide](dev_guide.md) section of this documentation. We also kindly ask
+that you follow the [Symfony Coding Standards](https://symfony.com/doc/current/contributing/code/standards.html) to ensure uniformity and clarity of our source code across Myddleware.
+We recommend using the [PHP CS Fixer](https://github.com/FriendsOfPhp/PHP-CS-Fixer) tool to ensure these standards are respected across your contributed code.
diff --git a/docs/README.md b/docs/README.md
index 6eb66386f..f0396a2a1 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -16,10 +16,11 @@
[](https://docsify.js.org/)

[](https://www.youtube.com/channel/UCxI0ziSiRXXTqQ-XfFJr7-w)
+
Myddleware is the customisable free open-source platform that facilitates data migration and synchronisation between applications.
-
+
[On our documentation website,](https://myddleware.github.io/myddleware) you’ll find everything you’re looking for to master Myddleware, including step-by-step tutorials. You can also tailor Myddleware to your needs by creating you custom code. Please use [our github](https://github.com/Myddleware) to share it.
@@ -232,3 +233,11 @@ php bin/console doctrine:fixtures:load --append
## Contributing
> Myddleware relies on the [Symfony Framework](https://symfony.com/), a free open-source PHP framework. If you would like to contribute to our source code, you can first familiarise yourself with the [Symfony documentation](https://symfony.com/doc/current/index.html)
+
+Myddleware is an Open Source community project. All contributions are welcome, no matter how big or small. There are many ways to contribute to the project.
+You can of course help us improve and debug our source code, but you can also start by simply reporting issues & bugs or suggesting new features on our [GitHub Issues forum](https://github.com/Myddleware/myddleware/issues), or review and leave comments on [Pull Requests](https://github.com/Myddleware/myddleware/pulls).
+
+If you would like to contribute to Myddleware source code, please refer to the [developer's guide](dev_guide.md) section of this documentation. We also kindly ask
+that you follow the [Symfony Coding Standards](https://symfony.com/doc/current/contributing/code/standards.html) to ensure uniformity and clarity of our source code across Myddleware.
+We recommend using the [PHP CS Fixer](https://github.com/FriendsOfPhp/PHP-CS-Fixer) tool to ensure these standards are respected across your contributed code.
+
diff --git a/docs/_sidebar.md b/docs/_sidebar.md
index 009414143..ba3d41264 100644
--- a/docs/_sidebar.md
+++ b/docs/_sidebar.md
@@ -8,5 +8,6 @@
* [Job scheduler & cron tasks](cron_jobs.md)
* [Myddleware API](api.md)
* [Developer's Guide](dev_guide.md)
+* [Connectors](connectors_credentials.md)
* [Website](https://www.myddleware.com)
* [Contact Us](https://www.myddleware.com/contact-us)
diff --git a/docs/advanced_usage.md b/docs/advanced_usage.md
index 2f1f67588..6bbc8e08c 100644
--- a/docs/advanced_usage.md
+++ b/docs/advanced_usage.md
@@ -2,16 +2,126 @@
## Filters
-*This section is still under construction*
+You can apply filters to the data you want to send into your target application.
+To do so, click on the “Filters” tab while creating or editing your rule.
-## Relationships
+
-*This section is still under construction*
+For each of your fields, you can select from a pre-set list of filters to apply.
+
+
+
+And then input the reference to use as a filter. Myddleware will apply this filter to this field inside your rule, meaning
+that only the documents matching this exact filter will be sent to the read() method.
+
+
+
+## Formulae
+
+> Myddleware embarks a set of valuable tools to facilitate data transformation, including the possibility to add what we call ``formulae``.
+> Inside the Myddleware UI, you can create your own formulae to manipulate data before it is being transferred from your source application to your target.
+> For instance, let's image your source application contains a ``first_name`` & a ``last_name`` field, but your target application only accepts a ``fullName`` field.
+> This is no problem, as you can add a formula on the ``fullName`` target field in which you will be able to concatenate the 2 source fields for example.
+> This is a basic example, however you are free to make much more complex formulae if you wish, thanks to a bunch of built-in PHP functions embarked with Myddleware.
+
+### Fundamentals
+
+For starters, formulas allow you to format or to set the values that will be sent to a given target field.
+In other words, you have the option of adding fixed text to all uppercase, change timezones, concatenate several source fields etc.
+From inside the Myddleware UI, you can create & peruse the available methods to create formulae during the rule creation process,
+during the field mapping step. Indeed, once you've added a source field into a target field, you may then click on the ``Add formula`` button of
+each target field and then a modal window will open allowing you to add your formula.
+
+### Syntax
+
+To help, syntax highlighting (1) is available to you right on your text box.
+Furthermore, you will find below the list of source fields that you have chosen (2),
+the available functions and their categories (3) and one or two dropdown list(s) (4) containing the different values
+for the list type fields (as SalutationID example).
+
+
+
+**Examples**
+
+- To concatenate multiple fields, Myddleware uses the ``.`` symbol, just like in PHP
+
+````php
+{field1}.{field2}.' '.{field3}
+{salutation}.' '.{first_name}.' '.{last_name} // e.g. Miss Mary Spears
+````
+- To concatenate a fixed text with one or multiple fields “Client Name: “.{Firstname}.” “.{Lastname}
+
+- Three-valued condition , “If the Greeting field is ‘Mr.’ then send 1, otherwise send 2” is written as followed : (({Greeting} == “Mr.”) ? “1” : “2”), those three-valued conditions can be nested in order, for example, to make the data correspond. Thus, ({resolution} == “10” ? “Open” : ({resolution} == “20” ? “Fixed” : ({resolution} == “30” ? “Reopened” : “Suspended”))) is correct and functional, this formula means “If resolution is 10 then ‘Open’ is sent, otherwise if resolution is 20 then ‘Fixed‘ is sent, otherwise if resolution is 30 then ‘Reopened’ is sent, otherwise ‘Suspended ‘ is sent.
+
+- Add two fileds {field1} + {field2}
+
+In this article we‘ll look at an important point in your synchronization rules and one of the many setting options offered by Myddleware, formulas.
+
+**Functions**
+
+In the formula of Myddleware, you can use the functions listed at the bottom right (see of the previous image).
+
+
+Rounds a float, ([PHP](https://www.php.net/manual/fr/function.round.php)) **round(number [, clarification])**:
+
+ round(525.6352, 2) // Returns 525.64
+
+Rounds up, ([PHP](https://www.php.net/manual/fr/function.ceil.php)) **ceil(float)**:
+
+ ceil(525.6352) // Returns 526
+
+Returns the absolute value, ([PHP](https://www.php.net/manual/fr/function.abs.php)) **abs(number)**:
+
+ abs(-5) // Returns 5
+
+Deletes spaces (or other characters) at the beginning and the end of a string, ([PHP](https://www.php.net/manual/fr/function.trim.php)) **trim(string [, Masque])**:
+
+ trim(” bonjour “) // Returns “bonjour”
+
+Lowercases all characters, ([PHP](https://www.php.net/manual/fr/function.mb-strtolower.php)) **lower(STRING)**:
+
+ lower(“BONJOUR”) // Returns “bonjour”
+
+Uppercases all charachters, ([PHP](https://www.php.net/manual/fr/function.mb-strtoupper.php)) **upper(String)**:
+
+ upper(“bonjour”) // Returns “BONJOUR”
+
+Formats a local date/hour, ([PHP](https://www.php.net/manual/fr/function.date.php)) **date(Format [, Timestamp])**:
+
+ date(“Y:m:d”) // Returns “2014:09:16”
+
+Returns current Unix timestamp with microseconds, ([PHP](https://www.php.net/manual/fr/function.microtime.php)) **microtime([true if you want a float result])**:
+
+ microtime(true) // Returns 1410338028.5745
+
+Changes the timezone of the given date, ([PHP](https://www.php.net/manual/fr/timezones.php)) **changeTimeZone(Date you want to change, old timezone, new timezone)**:
+
+ changeTimeZone(“2014-09-16 12:00:00”, “America/Denver”, “America/New_York”) // Returns “2014-09-16 14:00:00”
+
+Changes the format of the given date, **changeFormatDate(Date you want to change, New format)**:
+
+ changeTimeZone(“2014-09-16 12:00:00”, “Y/m/d H:i:s”) // Returns “2014/09/16 12:00:00”
+
+Reads a string starting of the given Index, ([PHP](https://www.php.net/manual/fr/function.mb-substr.php)) **substr(String, Indexample)**:
+
+ substr(“abcdef”, -1) // Returns “f”
+
+Strips HTML and PHP tags from a string, ([PHP](https://www.php.net/manual/fr/function.strip-tags.php)) **striptags(String)**:
+
+ striptags(“
Test paragraph.
Other text”) // Returns “Test paragraph. Other text”
-## Mass actions
-*This section is still under construction*
## Relationships
*This section is still under construction*
+
+We can create relationships in Myddleware that not only allow us to transfer unrelated data items but whole data models entirely.
+
+For instance, let's imagine we have a Prestashop to SuiteCRM rule which transfers customers.
+Now, if for instance we wanted to add another rule allowing us to send Prestashop ``orders`` to SuiteCRM ``opportunities``.
+to send an ``order`` to SuiteCRM, we have to link it to the related ``account``.
+In order to do so, we need to retrieve the account's id corresponding to the customer linked to the order in Prestashop.
+
+To do that, we will link this new rule to the previous rule where we will be able to find the SuiteCRM account id.
+
diff --git a/docs/api.md b/docs/api.md
index e2808b807..d65d4dc07 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -1,8 +1,10 @@
+# Myddleware REST API
-# Myddleware API
-
-The Myddleware API was built using [API Platform](https://api-platform.com/). It therefore comes with a built-in Swagger UI documentation describing all available endpoints.
+The Myddleware API was built using [API Platform](https://api-platform.com/).
+It therefore comes with a built-in Swagger UI documentation describing all available endpoints.
We strongly recommend using that Swagger UI doc, which is available at the ````/api/docs```` endpoint of your Myddleware instance.
+You can find our [Postman collection & documentation here](https://documenter.getpostman.com/view/1328767/SzS7QmCj?version=latest#e564597d-ef6e-40e1-87f1-c69b7b2d7479)
+You can also find a PHP example of Myddleware API implementation [here](https://github.com/Myddleware/myddleware_api).
## Route
@@ -15,6 +17,29 @@ For instance, if you're running Myddleware on localhost, you can access the API
The Myddleware API is protected via JWT authentication, which means that in order to execute a Myddleware API action,
you will first need to authenticate using your Myddleware credentials by sending a POST request to the ````/api/login_check```` endpoint.
+### /api/login_check
+
+> POST http://localhost:8000/api/login_check
+
+Example authentication request :
+
+````json
+{
+ "username" : "sophie.example@email.com",
+ "password" : "myverysecretivepassword123"
+}
+````
+
+Example successful response :
+
+````json
+{
+ "token": "eyJ1c2VybmFtZSI6InNvcGhpZS5leGFtcGxlQGVtYWlsLmNvbSIsInBhc3N3b3JkIjoibXl2ZXJ5c2VjcmV0aXZlcGFzc3dvcmQxMjMiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.P0L7H4g9nZoHmVQRQHNi4G5Pfq6CS0JM9_xv-98OJ5Q"
+}
+````
+
+Upon success, you can now paste this token into all your other API requests into the Bearer Token header of each request.
+
## Actions
Currently, all Myddleware API endpoints are POST request endpoints.
@@ -23,6 +48,8 @@ Currently, all Myddleware API endpoints are POST request endpoints.
You can execute a rule or all your active rules. Simply send the rule ID.
+> POST http://localhost:8000/api/synchro
+
Example body:
````json
@@ -67,22 +94,521 @@ If you want to synchronise all your active rules at once, you need to send 'ALL
### /api/read_record
-POST http://localhost:8000/api/read_record
+Use the read record method to force Myddleware to read a specific record from your application. For example,
+you can call this method when a record is saved into your application.
+Myddleware will read it from your source application and send it to your target application.
+It is used when you need real time synchronisation.
+
+> POST http://localhost:8000/api/read_record
+
+You need to send the following parameters in your request body :
````json
{
"rule": "6331a6247f2140.75163260",
- "filterQuery": "",
- "filterValues" : ""
+ "filterQuery": "",
+ "filterValues" : ""
+}
+````
+
+| Parameter | Description |
+|-------------|---------------------------------------------------------------------------------------------------------------------------------------|
+| rule | The rule you want to run. |
+| filterQuery | The field used to build the query executed by Myddleware inside your application. It is usually the "id" field‘s name of your record. |
+| filterValue | The field value used as a filterQuery parameter. It is usually your record's id. |
+
+Example response:
+
+````json
+{
+ "error": "",
+ "jobId": "5e78c4c4ec8631.31640728",
+ "jobData": {
+ "Close": 0,
+ "Cancel": "1",
+ "Open": 0,
+ "Error": 0,
+ "paramJob": "read records wilth filter id IN (4×60)",
+ "solutions": "^6^,^27^",
+ "duration": 2.42,
+ "myddlewareId": "5e78c4c4ec8631.31640728",
+ "Manual": 1,
+ "Api": 1,
+ "jobError": "",
+ "documents": [
+ {
+ "id": "5e78c4c5f27231.38354025",
+ "rule_id": "5e5e5535564c0",
+ "date_created": "2020-03-23 14:16:37",
+ "date_modified": "2020-03-23 14:16:39",
+ "created_by": "1",
+ "modified_by": "1",
+ "status": "No_send",
+ "source_id": "4×60",
+ "target_id": "e559cfe4-4e41-e2da-235e-5e63a985d98e",
+ "source_date_modified": "2017-10-09 14:46:24",
+ "mode": "0",
+ "type": "U",
+ "attempt": "0",
+ "global_status": "Cancel",
+ "parent_id": "",
+ "deleted": "0"
+ }
+ ]
+ }
}
````
### /api/delete_record
+Use the delete_record method to delete a specific record inside the target application using the source application id.
+
+> POST http://localhost:8000/api/delete_record
+
+
+| Parameter | Description / value |
+|---------------|----------------------------------------------------------------------------------------------------------------------------------------|
+| **rule** | Rule ID. |
+| **recordId** | Record ID inside the source application. Myddleware will use the rule to get this record's id in the target application and delete it. |
+| **reference** | The reference date or id used in Myddleware. Use the reference field already configured for this rule. |
+| | All of the rule's fields have to be added as input parameters. |
+
+Example CURL request :
+
+````curl
+curl --location --request POST 'http://localhost:8000/api/delete_record' \
+--form 'rule=5e5e5535564c0' \
+--form 'recordId=4x65' \
+--form 'reference=2020-03-09 12:14:36' \
+--form 'lastname=lastname01' \
+--form 'email=test@test.test' \
+--form 'firstname=firstname01'
+````
+
+Example response:
+
+````json
+ {
+ "error": "",
+ "jobId": "5e78e7a7621400.01014726",
+ "jobData": {
+ "Close": 1,
+ "Cancel": 0,
+ "Open": 0,
+ "Error": 0,
+ "paramJob": "Delete record 4×63 in rule 5e5e5535564c0",
+ "solutions": "^6^,^27^",
+ "duration": 0.32,
+ "myddlewareId": "5e78e7a7621400.01014726",
+ "Manual": 1,
+ "Api": 1,
+ "jobError": "",
+ "documents": [
+ {
+ "id": "5e78e7a766e656.99183539",
+ "rule_id": "5e5e5535564c0",
+ "date_created": "2020-03-23 16:45:27",
+ "date_modified": "2020-03-23 16:45:27",
+ "created_by": "1",
+ "modified_by": "1",
+ "status": "Send",
+ "source_id": "4×63",
+ "target_id": null,
+ "source_date_modified": "2020-03-09 12:14:36",
+ "mode": "0",
+ "type": "D",
+ "attempt": "0",
+ "global_status": "Close",
+ "parent_id": "",
+ "deleted": "0"
+ }
+ ]
+ }
+ }
+````
+
### /api/mass_action
+Use the mass action method to change (rerun, cancel, remove, restore or change the status of) a group of data transfers (documents).
+
+> POST http://localhost:8000/api/mass_action
+
+ | Parameter | Description / value |
+|---------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| **action** | ``rerun``, ``cancel``, ``remove``, ``restore`` or ``changeStatus`` |
+| **dataType** | ``rule`` or ``document``
If you want to select documents using a rule (all of the rule's data transfers) as the filter set it to ``rule``, otherwise set it to ``document`` if you want to filter your search by data transfer (document) id. |
+| **ids** | Set the id(s) of the data transfer (document) or the rule depending on what you have set as a **dataType** parameter. If you put several ids, use commas to separate them. |
+| **forceAll** (OPTIONAL) | Set to ``Y`` to process action on all data transfers (not only open and error ones).
In this case, be careful, you could remove, cancel or change the status of data successfully sent to your target application.
Myddleware could generate duplicate data in your target application if you run your rule again without setting up the ``duplicate fields`` parameter. |
+| **fromStatus** | Only used when the **action** parameter is set to ``changeStatus``. Adds a filter to select documents based on their status. |
+| **toStatus** | Only used when the **action** parameter is set to ``changeStatus``. New status to be set on all selected documents. |
+
+Example response:
+
+````json
+ {
+ "error": "",
+ "jobId": "5e78dcacb8f1d0.97025863",
+ "jobData": {
+ "Close": "30",
+ "Cancel": "70",
+ "Open": 0,
+ "Error": 0,
+ "paramJob": "Mass remove on data type rule",
+ "solutions": "^6^,^27^",
+ "duration": 10.28,
+ "myddlewareId": "5e78dcacb8f1d0.97025863",
+ "Manual": 1,
+ "Api": 1,
+ "jobError": "",
+ "documents": [
+ {
+ "id": "5e6685af04d858.22701783",
+ "rule_id": "5e5e5535564c0",
+ "date_created": "2020-03-09 18:06:39",
+ "date_modified": "2020-03-23 15:58:36",
+ "created_by": "1",
+ "modified_by": "1",
+ "status": "Cancel",
+ "source_id": "4×72",
+ "target_id": null,
+ "source_date_modified": "2020-03-09 19:06:39",
+ "mode": "0",
+ "type": "D",
+ "attempt": "0",
+ "global_status": "Cancel",
+ "parent_id": "",
+ "deleted": "1"
+ },
+ {
+ "id": "5e6685fd2cfbb8.35868016",
+ "rule_id": "5e5e5535564c0",
+ "date_created": "2020-03-09 18:07:57",
+ "date_modified": "2020-03-23 15:58:36",
+ "created_by": "1",
+ "modified_by": "1",
+ "status": "Cancel",
+ "source_id": "4×72",
+ "target_id": null,
+ "source_date_modified": "2020-03-09 19:07:57",
+ "mode": "0",
+ "type": "D",
+ "attempt": "0",
+ "global_status": "Cancel",
+ "parent_id": "",
+ "deleted": "1"
+ },
+ {
+ "id": "5e668618964e93.34804135",
+ "rule_id": "5e5e5535564c0",
+ "date_created": "2020-03-09 18:08:24",
+ "date_modified": "2020-03-23 15:58:36",
+ "created_by": "1",
+ "modified_by": "1",
+ "status": "Cancel",
+ "source_id": "4×72",
+ "target_id": null,
+ "source_date_modified": "2020-03-09 19:08:24",
+ "mode": "0",
+ "type": "D",
+ "attempt": "0",
+ "global_status": "Cancel",
+ "parent_id": "",
+ "deleted": "1"
+ },
+ {
+ "id": "5e669dcd915191.00190986",
+ "rule_id": "5e5e5535564c0",
+ "date_created": "2020-03-09 19:49:33",
+ "date_modified": "2020-03-23 15:58:37",
+ "created_by": "1",
+ "modified_by": "1",
+ "status": "Cancel",
+ "source_id": "4×72",
+ "target_id": null,
+ "source_date_modified": "2020-03-09 20:49:33",
+ "mode": "0",
+ "type": "U",
+ "attempt": "1",
+ "global_status": "Close",
+ "parent_id": "",
+ "deleted": "1"
+ }
+ ]
+ }
+ }
+````
+
### /api/rerun_error
+Use the rerun_error method to execute documents in error again.
+
+> POST http://localhost:8000/api/rerun_error>
+
+| Parameter | Description / value |
+|-------------------------|--------------------------------------------------------------------------------------------------|
+| **limit** | limit the number of documents selected by the job. |
+| **attempt** | Myddleware will only read documents with a number of attempts less than or equal to this number. |
+
+Example response:
+
+````json
+ {
+ "error": "",
+ "jobId": "5e78e6cdd789e7.70152075",
+ "jobData": {
+ "Close": 0,
+ "Cancel": 0,
+ "Open": 0,
+ "Error": "3",
+ "paramJob": "Rerun error : limit 3, attempt 5",
+ "solutions": "^14^,^6^,^3^",
+ "duration": 1.09,
+ "myddlewareId": "5e78e6cdd789e7.70152075",
+ "Manual": 1,
+ "Api": 1,
+ "jobError": "",
+ "documents": [
+ {
+ "id": "5e612055c98da7.22680820",
+ "rule_id": "5e611b50c0a6f",
+ "date_created": "2020-03-05 15:52:53",
+ "date_modified": "2020-03-23 16:41:50",
+ "created_by": "1",
+ "modified_by": "1",
+ "status": "Error_sending",
+ "source_id": "efa139c1-5e46-b247-739d-5ba8412aa24a",
+ "target_id": null,
+ "source_date_modified": "2018-09-24 01:43:35",
+ "mode": "0",
+ "type": "C",
+ "attempt": "6",
+ "global_status": "Error",
+ "parent_id": "",
+ "deleted": "0"
+ },
+ {
+ "id": "5e72552e4fe687.45181957",
+ "rule_id": "5e5cc8984ba84",
+ "date_created": "2020-03-18 17:06:54",
+ "date_modified": "2020-03-23 16:41:50",
+ "created_by": "1",
+ "modified_by": "1",
+ "status": "Error_sending",
+ "source_id": "8",
+ "target_id": null,
+ "source_date_modified": "2019-02-06 22:07:59",
+ "mode": "0",
+ "type": "C",
+ "attempt": "6",
+ "global_status": "Error",
+ "parent_id": "",
+ "deleted": "0"
+ },
+ {
+ "id": "5e72552e51d612.98166090",
+ "rule_id": "5e5cc8984ba84",
+ "date_created": "2020-03-18 17:06:54",
+ "date_modified": "2020-03-23 16:41:50",
+ "created_by": "1",
+ "modified_by": "1",
+ "status": "Error_sending",
+ "source_id": "12",
+ "target_id": "15",
+ "source_date_modified": "2020-03-03 10:43:31",
+ "mode": "0",
+ "type": "U",
+ "attempt": "6",
+ "global_status": "Error",
+ "parent_id": "",
+ "deleted": "0"
+ }
+ ]
+ }
+ }
+````
+
### /api/statistics
+Get Myddleware statistics.
+> POST http://localhost:8000/api/statistics
+
+Example response:
+
+````json
+ {
+ "errorByRule": [
+ {
+ "name": "Product category",
+ "id": "5e5d3f8f570cb",
+ "cpt": "37"
+ },
+ {
+ "name": "Enrolment",
+ "id": "5a7dfcfaea8ee",
+ "cpt": "9"
+ },
+ {
+ "name": "Activity completion source",
+ "id": "5c7892bd02e90",
+ "cpt": "6"
+ },
+ {
+ "name": "Product Moodle to PS",
+ "id": "5e5cc8984ba84",
+ "cpt": "3"
+ },
+ {
+ "name": "Order datail",
+ "id": "5d63b4532292b",
+ "cpt": "2"
+ },
+ {
+ "name": "employee",
+ "id": "5e611b50c0a6f",
+ "cpt": "1"
+ },
+ {
+ "name": "Emails",
+ "id": "5ba1ba8c7c82f",
+ "cpt": "1"
+ },
+ {
+ "name": "Customers",
+ "id": "5d63d65dba522",
+ "cpt": "1"
+ },
+ {
+ "name": "Orders",
+ "id": "5d6010d1164fe",
+ "cpt": "1"
+ },
+ {
+ "name": "Shipping address",
+ "id": "5d63d4279a52a",
+ "cpt": "1"
+ },
+ {
+ "name": "Billing address",
+ "id": "5d63d54bc8310",
+ "cpt": "1"
+ },
+ {
+ "name": "Product Moodle get Stock id",
+ "id": "5e71ec0cd4a41",
+ "cpt": "1"
+ }
+ ],
+ "countTypeDoc": [
+ {
+ "nb": "1074",
+ "global_status": "Cancel"
+ },
+ {
+ "nb": "1056",
+ "global_status": "Close"
+ },
+ {
+ "nb": "44",
+ "global_status": "Open"
+ },
+ {
+ "nb": "22",
+ "global_status": "Error"
+ }
+ ],
+ "listJobDetail": [
+ {
+ "id": "5e78e7a7621400.01014726",
+ "begin": "2020-03-23 16:45:27",
+ "end": "2020-03-23 16:45:27",
+ "status": "End",
+ "message": "",
+ "duration": "0"
+ },
+ {
+ "id": "5e78e7981dcdf7.88565484",
+ "begin": "2020-03-23 16:45:12",
+ "end": "2020-03-23 16:45:12",
+ "status": "End",
+ "message": "",
+ "duration": "0"
+ },
+ {
+ "id": "5e78e791ed9662.98391952",
+ "begin": "2020-03-23 16:45:05",
+ "end": "2020-03-23 16:45:06",
+ "status": "End",
+ "message": "",
+ "duration": "1"
+ },
+ {
+ "id": "5e78e78d169314.78840502",
+ "begin": "2020-03-23 16:45:01",
+ "end": "2020-03-23 16:45:01",
+ "status": "End",
+ "message": "",
+ "duration": "0"
+ },
+ {
+ "id": "5e78e786166de0.64116198",
+ "begin": "2020-03-23 16:44:54",
+ "end": "2020-03-23 16:44:54",
+ "status": "End",
+ "message": "",
+ "duration": "0"
+ }
+ ],
+ "countTransferHisto": {
+ "2020-03-17": {
+ "date": "Mar-17",
+ "open": 0,
+ "error": 0,
+ "cancel": 0,
+ "close": 0
+ },
+ "2020-03-18": {
+ "date": "Mar-18",
+ "open": 0,
+ "error": "1",
+ "cancel": "16",
+ "close": "28"
+ },
+ "2020-03-19": {
+ "date": "Mar-19",
+ "open": 0,
+ "error": 0,
+ "cancel": "1",
+ "close": "1"
+ },
+ "2020-03-20": {
+ "date": "Mar-20",
+ "open": 0,
+ "error": 0,
+ "cancel": "1",
+ "close": "1"
+ },
+ "2020-03-21": {
+ "date": "Mar-21",
+ "open": 0,
+ "error": 0,
+ "cancel": 0,
+ "close": 0
+ },
+ "2020-03-22": {
+ "date": "Mar-22",
+ "open": 0,
+ "error": 0,
+ "cancel": 0,
+ "close": 0
+ },
+ "2020-03-23": {
+ "date": "Mar-23",
+ "open": 0,
+ "error": "10",
+ "cancel": "6",
+ "close": 0
+ }
+ }
+ }
+````
diff --git a/docs/basic_usage.md b/docs/basic_usage.md
index 65c3069f7..2d92c26a1 100644
--- a/docs/basic_usage.md
+++ b/docs/basic_usage.md
@@ -254,7 +254,7 @@ You can also view the list of all the previously ran tasks.
#### Documents
-Documents (data transfers) can then be opened by clicking on **Display documents**.
+Documents (data transfers) can be opened by clicking on **Display documents**.

@@ -264,6 +264,23 @@ You can also access the detail for each individual document by clicking on it.
You will then be able to see what Myddleware has read in the source application and what has been sent into the target application.
+##### Handling documents in error
+
+When a document (data transfer) is in error, you can modify it, by resending it or cancelling it.
+To be able to modify the document data, double-click on target data, change the data and click on the validation icon.
+
+
+
+##### Mass actions
+
+You can reload or cancel multiple documents at the same time.
+
+> Only documents in error can be reloaded or cancelled.
+
+Click on the checkboxes to select the transfer(s) you want to reload or cancel and click on ``Cancel transfers`` or ``Reload transfers``.
+
+
+
## Going further
If you would like to find out about more complex use cases, such as adding relationships between rules, filters and other amazing features, please checkout the [Advanced Usage section](advanced_usage.md)
diff --git a/docs/connectors_credentials.md b/docs/connectors_credentials.md
new file mode 100644
index 000000000..252e29efd
--- /dev/null
+++ b/docs/connectors_credentials.md
@@ -0,0 +1,641 @@
+# Available Myddleware connectors
+
+Each connector will require a different set of credentials for Myddleware to be able to link your applications together.
+This page aims to give you some guidance on how to obtain your credentials depending on the app you intend to connect to Myddleware.
+
+!> Disclaimer: some of these connectors are currently under scrutiny / maintenance due to the fact that when an app provider decides to
+update their webservice, Myddleware code needs to be updated to reflect these changes too. If you detect any errors or missing information, please do not hesitate
+to let us know by raising an issue on our [GitHub Issues forum](https://github.com/Myddleware/myddleware/issues).
+
+## CMS apps
+
+### WordPress
+
+Tne WordPress API is public and does not require any login credentials. Therefore, all you will need to be able to create
+your WordPress connector will be your website's ``URL``.
+
+Myddleware can currently read the following modules :
+
+| Module | Source | Target |
+|----------|--------|--------|
+| Posts | Yes | No |
+| Pages | Yes | No |
+| Comments | Yes | No |
+
+## CRM apps
+
+### Airtable
+
+Airtable modules are entirely custom and Myddleware is able to read, write & delete data in any Airtable base.
+For Myddleware to be able to connect to your Airtable application, you need to provide the following:
+
+- your project ID (Airtable base)
+- your API key / token
+
+
+
+To get your project (base) ID, you can obtain it from many ways. For example, by clicking on your
+base's logo and accessing it, it will then be displayed in your URL.
+
+
+
+Or, from your base, you can access the API documentation of that specific base by clicking on the ``Help`` icon, which will
+open a sidebar menu. Scroll down to ``ÀPI documentation``. This will open a new page with the API documentation for this
+particular base and you will find the ``project's base ID`` at the top.
+
+
+
+
+
+To get your ``API key``, login to Airtable and go to your [account](https://airtable.com/account).
+
+
+
+### Cirrusshield
+
+Myddleware is able to read and write all Cirrus Shield modules, even the custom ones.
+
+To create your Cirrus Shield connector, you will need :
+
+- Your username
+- Your password
+
+
+### Hubspot
+
+Here is the list of available modules in source (reading) and target (writing) :
+
+
+| Module | Source | Target |
+|---------------------------------------------------|--------|--------|
+| Companies | Yes | Yes |
+| Contacts | Yes | Yes |
+| Deals | Yes | Yes |
+| Engagement (task, email, meeting, note and call) | Yes | No |
+
+To create your hubspot connector, you will need your API key.
+
+> Please, follow this tutorial to get your API key : https://knowledge.hubspot.com/articles/kcs_article/integrations/how-do-i-get-my-hubspot-api-key
+
+
+
+### SageCRM
+
+Myddleware can read and write all Sage CRM modules, even the custom ones.
+
+To create a SageCRM connector, you will need:
+
+– Your user email address
+– Your password
+– A WSDL file that you need to download
+
+The user and the password are those you use to access your SageCRM account.
+
+To download the WSDL file, you must connect to your SageCRM account and click on “Administration”.
+
+Once you’re in “Manage My Account”, click on “External Access” and then on “View Web Services WSDL”.
+
+A new page opens. You have to save it.
+
+Now, go to your Myddleware environment where you will create a new connector.
+After typing in your email address and password, click on “wsdl file”. Choose the file you just downloaded and then transfer it.
+
+The file has been transferred successfully.
+
+Test your connection. If the light bulb is green, you're good to go!
+
+Choose a name for your connector and save it.
+
+### Salesforce
+
+Myddleware can read and write all Salesforce modules, even the custom ones.
+
+To create your Salesforce connector, you will need the following credentials:
+
+- Your username
+- Your password
+- Your token
+- Your consumer key
+- Your consumer secret
+- Indicate if you are connecting a sandbox or not (0 or 1)
+
+
+
+#### Where to find your security token ?
+
+Log in to Salesforce with your username and password.
+1) From the homepage of your account, click on your name in the top right corner, then on ``Setup``.
+2) Then, on the left-hand side, in the ``Personal Setup`` section of the menu, click on ``My Personal Information`` then ``Reset My Security Token``.
+3) Finally, click on ``Reset my security token`` (it will be sent by email).
+
+
+
+#### Consumer Key and Consumer Secret
+
+You need to create an app.
+
+1) To do so, click on your name, then on ``Setup``.
+
+2) Then, on the left-hand side, go to the ``App Setup`` section, then click on ``Create``, then ``Apps``.
+
+
+
+Create a connected app by clicking on ``New`` at the bottom, inside the ``Connected Apps`` panel.
+
+
+
+1) Input your App's name, API name and email address.
+2) Then, enable OAuth Settings by clicking on the checkbox.
+3) Insert your Salesforce URL in the ``Callback URL`` section.
+4) Then, select ``Full access`` by double-clicking on it.
+5) Click on the small arrow on the right
+6) The selected `` Full access`` scope should now have moved to the ``Selected OAuth Scopes`` box.
+7) Save.
+
+
+
+Click on ``Continue``. You will be redirected to the presentation page of your app.
+
+To get your Consumer Key & Consumer Secret, you will then need to click on the ``Manage Consumer Details`` button.
+At this stage, 2-factor authentication will require a code, which will have been sent to you via email. Insert this code.
+
+
+
+You will then be redirected to the Consumer Key & Secret page.
+Here, you’ll find your ``Consumer Key`` and ``Consumer Secret`` which you can now copy & paste into the Myddleware credentials form.
+
+
+
+### SAP CRM
+
+The SAP CRM connector can only be installed by our team.
+
+To know more about this connector, please fill in [this contact form](http://www.myddleware.com/contact-us).
+
+
+### SugarCRM
+
+Myddleware is compatible with SugarCRM CE and SugarCRM PRO v6.2 and upper versions.
+
+Myddleware can read and write all SugarCRM modules, even the custom ones.
+
+To connect SugarCRM to Myddleware, you need :
+
+- your username
+- your password
+- your URL
+
+
+
+> Tip: Use the username and password of a user with sufficient access control privileges to make the rules, write access, read, edit.
+
+### SuiteCRM 7
+
+Myddleware can read and write in all SuiteCRM modules, even the custom ones.
+
+
+To connect SuiteCRM to Myddleware, you need:
+
+- your username
+- your password
+- your URL
+
+
+
+
+
+### VTiger
+
+Myddleware can read and write into all Vtiger modules, even the custom ones.
+
+To connect Vtiger to Myddleware, you need
+- your username
+- your access key
+- your URL
+
+
+
+To get your access key, click on the user menu in the top right corner, then click on ``My preferences``, scroll down,
+your ``Access Key`` should be at the bottom.
+
+
+
+## ERP apps
+
+### ERPNExt
+
+Myddleware can read and write all ERPNext modules, even the custom ones.
+
+To connect ERPNext to Myddleware, you need :
+
+- your username
+- your password
+- your URL
+
+
+
+## E-commerce apps
+
+### Magento
+
+Myddleware is compatible with Magento 2.
+
+Here is the list of available modules in source (reading) and target (writing) :
+
+| Module | Source | Target |
+|----------------------------------------------------|--------|--------|
+| Customers | Yes | Yes |
+| Customer Addresses | Yes | No |
+| Orders | Yes | No |
+
+
+To connect Magento to Myddleware, you need :
+
+- your username
+- your password
+- your shop's URL
+
+!> Use the username and password of a user that has sufficient access rights you need to use Myddleware.
+
+
+
+### Prestashop
+
+Every module can be read by Myddleware as a source & target.
+
+It will allow you to create the PrestaShop connector.
+
+To do so, you will need :
+
+- your shop's URL
+- an API key which you will have to generate yourself
+
+
+
+#### How do you generate your API key?
+
+To generate this key, you should go in the back office of your shop. Go to ``Advanced Settings`` and then ``Webservice``.
+Click on “enable webservice” (save if the webservice was not activated) then click on “Add new webservice key” (black arrow)
+Finally, click on “generate” to generate the key and set the “Status” button to “Yes”.
+
+Select the checkboxes “View”, “Edit”, “Add” and “Fast view” (just like in the example below).
+
+Finally, save and get your API key to create your connector.
+
+### WooCommerce (WordPress)
+
+In order to link your WooCommerce shop to Myddleware, you need to provide the following information :
+
+- your shop's URL
+- your Consumer Key
+- your Consumer Secret
+
+
+
+#### Where to generate your Consumer Secret & Consumer Key?
+
+Login to your WordPress admin interface. Then, go to the WooCommerce section.
+Select ``Settings``, then ``Advanced``, then click on ``REST API``.
+
+
+
+Then, fill in the form by selecting the appropriate user, and select Read/Write permissions to allow Myddleware to both read & write into your application.
+
+
+
+When submitting the form, your credentials will be displayed. Make sure to copy them down as they will only be displayed once, you won't be able to access them anymore later.
+
+
+
+
+### Shop Application
+
+Myddleware can write all Shop Application modules and read the module customer.
+
+To connect Shop application to Myddleware, you need these parameters :
+
+- URL of your shop application
+- API key. Ask the shop application team to give it to you.
+
+
+## E-marketing platforms
+
+### Dolist
+
+Here is the list of available modules in source (reading) and target (writing) :
+
+| Module | Source | Target |
+|----------------------------|--------|-------|
+| Campaign | Yes | No |
+| Contacts | Yes | Yes |
+| Body segment statistics | No | Yes |
+| Header segment statistics | No | Yes |
+| Finished statistics | Yes | No |
+| Clicks statistics | Yes | No |
+| Unsubscribed statistics | Yes | No |
+| Unfinished statistics | Yes | No |
+| Open statistics | Yes | No |
+
+– Connecting to your Dolist environment
+– Creating a Dolist authentication
+– Retrieving the information needed to create the connector in Myddleware.
+
+1st step: Connect to your Dolist environment:
+
+Go to your Dolist login portal and log in.
+
+Once you are logged in, you will be redirected to the home page. Click on the administration tab as shown in the image below :
+
+The administration tab is now open. You will find in the left menu a subsection named “Web Services”. Click on it.
+
+The following tabs should appear. The one which interests us is “key management”.
+
+You are now ready to move to the second step.
+
+2nd step: Creating a Dolist authentication
+
+While you are on the “manage keys” tab, click on “Add a new Authentication”
+
+You must now fill in the necessary fields. We advise you not to choose the restriction by IP and to check the “permanent validity”. If you however wish to add Myddleware IP to your restrictions, please contact us.
+
+Congratulations, you’ve just created your Dolist authentication for Myddleware !
+
+3rd Step: Retrieving the necessary information
+
+For this last step, just click on the “See Key” button or the “See the authentication key” button, if you are still on of your authentication page.
+
+Enter your logins to display the following information:
+
+Take note of your Account ID and your authentication key so that you can fill in the fields when creating your Dolist connector in Myddleware.
+
+### Mailchimp
+
+Here is the list of available modules in source (reading) and target (writing) :
+
+| Module | Source | Target |
+|----------------------------------|--------|---------|
+| Campaigns | No | Yes |
+| Lists | No | Yes |
+| List members | No | Yes |
+
+Connect to Mailchimp an open your profile
+
+Then click on « Extra -> API Keys » and copy you API key :
+
+Add this key in your Myddleware connector :
+
+### Mautic
+
+Here is the list of available modules in source (reading) and target (writing) :
+
+| Module | Source | Target |
+|----------|--------|--------|
+| Company | No | Yes |
+| Contacts | No | Yes |
+
+To connect Mautic to Myddleware, you need :
+
+- your username
+- your password
+- your URL
+
+### Sendinblue
+
+Myddleware is able to read the following modules :
+
+| Module | Source | Target |
+|-------------------------------|--------|--------|
+| Contacts | Yes | Yes |
+| Transactional emails | Yes | Yes |
+| Transactional email activity | Yes | Yes |
+
+
+To create a Sendinblue connector, you need to provide the following information:
+
+- login (your email address)
+- API key
+
+
+
+#### Where to find your API key?
+
+You can get your Sendinblue API key by going to the user menu, then go to ``SMTP & API`` or directly to https://account.sendinblue.com/advanced/api.
+
+
+
+## Database apps
+
+### Microsoft SQL Server
+
+Myddleware can write and read all tables of your Microsoft SQL database.
+
+To connect a Microsoft SQL database to Myddleware, you need these parameters :
+
+- User
+- Password
+- Host server
+- Database name
+- Database port access
+
+
+
+
+You need to enable the PDO php module. This page should help you do so : [Installing/Configuring PDO](https://www.php.net/manual/en/pdo.installation.php)
+
+If you installed Myddleware on a Windows server, you need to install the [sqlsrv PDO driver](https://www.php.net/manual/en/sqlsrv.installation.php).
+
+If you installed Myddleware on a Linux server, you need to install the [dblib PDO driver](https://www.php.net/manual/en/ref.pdo-dblib.php).
+
+### MySQL
+
+Myddleware can write and read all table of your MySQL database.
+
+To connect a MySQL database to Myddleware, you need these parameters :
+
+- User
+- Password
+- Host server
+- Database name
+- Database port access
+
+
+
+Myddleware uses the MySQL PDO driver.
+
+You need to enable the PDO PHP module.
+This manual should help you : [Installing/Configuring PDO](https://www.php.net/manual/en/pdo.installation.php)
+
+### Oracle
+
+
+
+### PostgreSQL
+
+
+
+## Others
+
+### Eventbrite
+
+- 'Organizer' => 'User
+- 'Events' => 'User
+- 'Tickets' => 'User
+- 'Venues' => 'User
+- 'Access_Codes' => 'Event
+- 'Discount_Codes' => 'Event
+- 'Attendees' => 'Event
+- 'Users' => 'User
+
+### Facebook
+
+Here is the list of available modules in source (reading) and target (writing) :
+
+| Module | Source | Target |
+|-------------------------|--------|--------|
+| Read capture lead form | Yes | No |
+
+To connect a Facebook to Myddleware, you need these parameters :
+
+- Client ID
+- Client secret
+- User access token
+
+You will find your client ID and client secret in your app.
+You will find your app here, You will be able to create an app if you don’t have one. https://developers.facebook.com/apps/
+
+To get you access token, open the Graph API Explorer : https://developers.facebook.com/tools/explorer
+
+Select your app, user token and add autorisations : ``manage_page`` and ``leads_retrieval`` :
+
+Then, copy your token. However, this token will expire in a few hours.
+If you want to extend the life of this token, click on the ``i`` icon :
+Then click on ``Open in Access Token Tool`` :
+Then click on ``Extend Access Token``.
+Your token will expire in 2 month. After this time you will have to refresh the token in your Myddleware Facebook connector.
+
+### File (FTP)
+
+Myddleware can be connected to your server via an FTP connection.
+It can read csv/txt files stored on your server and transfer the data to another application.
+
+To connect Myddleware to an FTP server, you need these parameters :
+
+- User
+- Password
+- Host server
+- Port
+- Directory where the files will be stored (eg : ``/home/myddleware/my_directory``)
+
+Myddleware uses the [ssh2_connect()](https://www.php.net/manual/en/function.ssh2-connect.php)
+and [ssh2_auth_password()](https://www.php.net/manual/en/function.ssh2-auth-password.php) PHP functions to connect to your FTP server.
+
+### Moodle
+
+Here is the list of available modules in source (reading) and target (writing) :
+
+| Module | Source | Target |
+|--------------------------------|--------|--------|
+| Courses | Yes | Yes |
+| Users | Yes | Yes |
+| Group members | No | Yes |
+| Groups | No | Yes |
+| Enrollment | Yes | Yes |
+| Unenrollment | No | Yes |
+| Notes | No | Yes |
+| Courses completion | Yes | No |
+| Activities completion | Yes | No |
+| Courses last access | Yes | No |
+| Competencies module completion | Yes | No |
+| User competencies | Yes | No |
+| User grades | Yes | No |
+
+
+Please, first install the [Myddleware Moodle plugin](https://moodle.org/plugins/local_myddleware).
+
+Generate your token by following [this Moodle tutorial](https://docs.moodle.org/400/en/Using_web_services).
+
+You can use this system role and assign it to the user linked to your token.
+Click on this link to download it, then unzip it before importing it in Moodle : [myddleware_moodle_role](https://moodle.org/plugins/local_myddleware)
+
+To assign a role, go to ``Site administration`` -> ``Users`` -> ``Assign system roles``
+
+Choose Myddleware role
+
+Then add the user you want to use in Myddleware :
+
+Myddleware uses the REST API architecture.
+
+Then open your external service :
+
+Please add these functions to your external services :
+
+In the blue box you can see the standard functions. In the red box are the custom functions used by Myddleware to read data from Moodle.
+The custom functions all have a name beginning with ``local_myddleware`` (there are more functions than displayed on the screenshot).
+Make sure you have installed the [Myddleware Moodle plugin](https://moodle.org/plugins/local_myddleware) if you don’t find these functions in the list.
+
+Add the URL of your Moodle instance and your token in Myddleware :
+
+
+
+### RingCentral
+
+Here is the list of available modules in source (reading) and target (writing) :
+
+
+| Module | Source | Target |
+|-----------|--------|--------|
+| Call log | Yes | No |
+| Messages | Yes | No |
+| Presence | No | No |
+
+To create your RingCentral connector, you will need :
+
+- Username
+- Password
+- API key
+- API secret
+
+Click [here](https://devcommunity.ringcentral.com/ringcentraldev/topics/how-do-i-get-my-production-app-key) to get more
+information about these parameters.
+
+
+### Sage50
+
+Myddleware can read and write all Sage50 module available with Sage Sdata API
+
+To create your Sage50 connector, you will need the following :
+
+- Username
+- Password
+- Host server
+
+Don’t forget to activate your Sage50 Sdata API :
+
+### WooCommerce Event Manager Plugin (WordPress)
+
+This WordPress plugin is provided by [MagePeople](https://mage-people.com/product/mage-woo-event-booking-manager-pro/).
+This connector relies on the WordPress connector.
+The list of available modules is based on this [documentation](https://docs.mage-people.com/woocommerce-event-manager/rest-api-details-of-event-manager/).
+Currently, Myddleware is able to read the following modules :
+
+| Module | Source | Target |
+|------------------|--------|--------|
+| Events | Yes | No |
+| Categories | Yes | No |
+| Organizers | Yes | No |
+| Event More Date | Yes | No |
+
+### Zuora
+
+Myddleware can read and write in all Zuora modules.
+
+To create a Zuora connector, you will need:
+
+- Your username
+- Your password
+- WSDL file that you need to download. You will find more information about WSDL [here](https://knowledgecenter.zuora.com/DC_Developers/G_SOAP_API/AB_Getting_started_with_the__SOAP_API/B_Zuora_WSDL)
+- Finally, if you're connecting to a sandbox, please write ``1`` or ``0`` if you're connecting a production environment
+
+
+
+
diff --git a/docs/dev_guide.md b/docs/dev_guide.md
index 97f15178f..720009647 100644
--- a/docs/dev_guide.md
+++ b/docs/dev_guide.md
@@ -1,49 +1,59 @@
# Developer's guide
+All Myddleware improvements are welcome, and we particularly encourage community members to contribute to our connectors list by making a pull request so that the whole community can benefit from your work.
+To help you write your own connector, please read the following guidelines for successful connector creation.
+We also strongly recommend checking out the source code of all existing connectors inside the [/src/Solutions folder](https://github.com/Myddleware/myddleware/blob/main/src/Solutions/) to help you implementing all the required methods.
+
+!>You may also have some very specific needs that simply require customising Myddleware to fit your own context. If that's the case, please refer to the "Ensuring your custom code is upgrade-safe in Myddleware" section of this documentation.
+
## Create your own connectors
### Requirements
-The application you want to connect needs to have a webservice API with methods to read data (at the very least) and hopefully have a documentation website available to help you connect Myddleware to the target application.
+Before you can connect a new application to Myddleware, you need to check that the application you want to connect has a webservice API with methods to read data (at the very least)
+and hopefully has a documentation website available to help you connect Myddleware to the target application.
> Most Myddleware applications are connected using REST API, however this is not the only option.
-First you will need to add your new connector to the solution table in your database, using Doctrine Fixtures, and more specifically the LoadSolutionData class, located in [/src/DataFixtures/LoadSolutionData.php](https://github.com/Myddleware/myddleware/blob/main/src/DataFixtures/LoadSolutionData.php). To do so, add a new entry in $solutionData in for your new connector :
+#### Declare your new connector's name
+
+First you will need to add your new connector to the ``solution`` table in your database, using Doctrine Fixtures,
+and more specifically the ``LoadSolutionData`` class, located in
+[/src/DataFixtures/LoadSolutionData.php](https://github.com/Myddleware/myddleware/blob/main/src/DataFixtures/LoadSolutionData.php).
+To do so, add a new entry in ``$solutionData`` in for your new connector :
```php
- protected $solutionData = [
- ['name' => 'sugarcrm', 'active' => 1, 'source' => 1, 'target' => 1],
- ['name' => 'vtigercrm', 'active' => 1, 'source' => 1, 'target' => 1],
- ['name' => 'salesforce', 'active' => 1, 'source' => 1, 'target' => 1],
- ['name' => 'prestashop', 'active' => 1, 'source' => 1, 'target' => 1],
- // Your connector
- ['name' => 'myconnector', 'active' => 1, 'source' => 1, 'target' => 1],
- ];
+ protected $solutionData = [
+ ['name' => 'sugarcrm', 'active' => 1, 'source' => 1, 'target' => 1],
+ ['name' => 'vtigercrm', 'active' => 1, 'source' => 1, 'target' => 1],
+ ['name' => 'salesforce', 'active' => 1, 'source' => 1, 'target' => 1],
+ ['name' => 'prestashop', 'active' => 1, 'source' => 1, 'target' => 1],
+ // Your connector
+ ['name' => 'myconnector', 'active' => 1, 'source' => 1, 'target' => 1],
+ ];
```
-In [/src/Manager/SolutionManager.php](https://github.com/Myddleware/myddleware/blob/main/src/Manager/SolutionManager.php), add your new connector to the SolutionManager class.
+In [/src/Manager/SolutionManager.php](https://github.com/Myddleware/myddleware/blob/main/src/Manager/SolutionManager.php), add your new connector to the ``SolutionManager`` class.
First, add the use statement at the top of the SolutionManager class :
```php
-...
-use App\Solutions\WooEventManager;
-use App\Solutions\WordPress;
-use App\Solutions\Zuora;
-// Your new connector
-use App\Solutions\MyConnector;
+ use App\Solutions\WooEventManager;
+ use App\Solutions\WordPress;
+ use App\Solutions\Zuora;
+ // Your new connector
+ use App\Solutions\MyConnector;
```
-Then still in SolutionManager, add the new connector to the constructor.
+Then still in ``SolutionManager``, add the new connector to the constructor.
```php
- public function __construct(
+ public function __construct(
WordPress $wordPress,
WooCommerce $wooCommerce,
WooEventManager $wooEventManager,
// Your connector
MyConnector $myConnector
-
) {
$this->classes = [
'wordpress' => $wordPress,
@@ -55,27 +65,112 @@ Then still in SolutionManager, add the new connector to the constructor.
}
```
-#### Download source API SDKs
+#### Download source API SDKs (optional)
!> This step is optional and will vary according to the type of API you would like to connect to Myddleware. For this part, you must refer to the source API documentation.
-In your terminal, you might need to download an SDK for the new API. For instance, [the WooCommerce REST API documentation](https://woocommerce.github.io/woocommerce-rest-api-docs/#introduction) tells us that we need to add the **automattic/woocommerce** dependency to our Myddleware project in order to be able to login to the REST API. To do so, we ran :
+In your terminal, you might need to download an SDK for the new API.
+For instance, [the WooCommerce REST API documentation](https://woocommerce.github.io/woocommerce-rest-api-docs/#introduction)
+tells us that we need to add the **automattic/woocommerce** dependency to our Myddleware project in order to be able to login to the REST API. To do so, we ran :
```bash
composer require automattic/woocommerce
```
-#### Add the new connector to your current database
+Then, we implemented the Client described in their documentation inside our login(), create(), update() & read() methods.
+Here is a sample of the code using the third-party client:
+
+````php
+woocommerce = new Client(
+ $this->paramConnexion['url'],
+ $this->paramConnexion['consumerkey'],
+ $this->paramConnexion['consumersecret'],
+ [
+ 'wp_api' => true,
+ 'version' => 'wc/v3',
+ ]
+ );
+ if ($this->woocommerce->get('data')) {
+ $this->connexion_valide = true;
+ }
+ }
+}
+
+ public function upsert($method, $param)
+ {
+ ...
+ foreach ($param['data'] as $idDoc => $data) {
+ $param['method'] = $method;
+ $module = $param['module'];
+ $data = $this->checkDataBeforeCreate($param, $data, $idDoc);
+
+ if ('create' === $method) {
+ unset($data['target_id']);
+ $recordResult = $this->woocommerce->post($module, $data);
+ } else {
+ $targetId = $data['target_id'];
+ unset($data['target_id']);
+ $recordResult = $this->woocommerce->put($module.'/'.$targetId, $data);
+ }
+ ...
+ }
+ }
+
+ public function read($param){
+ ...
+ $response = $this->woocommerce->get($module, [
+ 'orderby' => 'modified',
+ 'per_page' => $this->callLimit,
+ 'page' => $page, ]
+ );
+ ...
+ }
+ ...
+````
+
+### Add the new connector to your current database
+
+In your terminal, load Myddleware fixtures. This will store your new connector's name inside the database.
```bash
php bin/console doctrine:fixtures:load --append
```
+Your new connector should appear inside the ``solution`` table of your database
+
+
+
+> Go to your Myddleware interface to check whether the new connector is already available.
-> Check in Myddleware if the new connector is already available.
+### Creating the Connector file
-Now, let's create a new connector class, in [/src/Solutions](https://github.com/Myddleware/myddleware/tree/main/src/Solutions), the file name must be the same as the name of your class (this is due to autoloading). You can use the code of another class for inspiration. For example, check out "SuiteCRM.php":
+Now, let's create a new solution(connector) class, in [/src/Solutions](https://github.com/Myddleware/myddleware/tree/main/src/Solutions).
+The file name must be the same as the name of your class (this is due to autoloading).
+
+!> All Connectors (Solutions) extend the Myddleware parent class ```Solution```. This class contains a variety of methods which you may override to fit your connector's needs.
+We strongly recommend you [check it out](https://github.com/Myddleware/myddleware/blob/main/src/Solutions/solution.php) when in doubt as this class acts as the backbone of all Myddleware connectors.
+
+You can use the code of another class for inspiration. For example, check out [SuiteCRM.php](https://github.com/Myddleware/myddleware/tree/main/src/Solutions/suitecrm.php):
```php
namespace App\Solutions;
@@ -100,8 +195,14 @@ Now, let's create a new connector class, in [/src/Solutions](https://github.com/
#### Add the solution's logo
Finally, if you want to display the application's logo, add the image corresponding to your application with the png format and size 64*64 pixels in [assets/images/solution](https://github.com/Myddleware/myddleware/tree/main/assets/images/solution)
+Once you've added the new image to the assets directory, you need to build Myddleware again in order for the image to be loaded to the Myddleware UI.
+To do so, you can run either ``yarn watch`` (in dev environment) or ```yarn build``` (in production environment).
+
-> Tip: regarding error handling, there are several options. You should throw exceptions using a try/catch method. You should also log errors using Symfony logger. In case of errors, the error message will be sent to the ```background.log```, ```prod.log``` & ```dev.log`` files, depending on your environment.
+### Error handling
+
+!> Tip: regarding error handling, there are several options. You should throw exceptions using a try/catch method.
+You should also log errors using [Symfony logger](https://symfony.com/doc/current/logging.html). In case of errors, the error message will be sent to the ```background.log```, ```prod.log``` & ```dev.log``` files, depending on your environment.
Here is an example method from our [WordPress.php](https://github.com/Myddleware/myddleware/blob/main/src/Solutions/wordpress.php) file :
@@ -118,36 +219,63 @@ Here is an example method from our [WordPress.php](https://github.com/Myddleware
}
```
+### Compulsory methods to implement
+
+Here's a non-exhaustive list of all the methods you will need to implement inside your Connector class. Each method's implementation will vary according to your source application's specificities.
+Please make sure you refer to its documentation for specifics such as modules lists, fields, formats, way to log in, etc.
+
+!> Warning: these method names (and signatures), as well as some class names, properties & namespaces, will undergo some slight changes in Myddleware 4 for code quality & consistency reasons. For instance, get_module_fields() will become getModuleFields() to respect the camelCase standard. Some typos & spelling mistakes might get fixed too.
+
+| Method | Description | Arguments | Return type |
+|------------------------------|------------------------------------------------------------------------------------------------------------------------------------|--------------------------------|---------------------------|
+| **getFieldsLogin()** | This method retrieves the list of fields required to login to your source app. For instance, an email, a password & a URL. | | array |
+| **login()** | Connects to the source app. | array $paramConnexion | void |
+| **get_modules()** | Retrieves the list of modules your connector can read from inside your source application solution. | string $type = 'source' | array |
+| **get_modules_fields()** | Retrieves the list of fields for each module your connector can read from inside your source application solution. | string $module, string $type = 'source', array $param = null | array $this->moduleFields |
+| **read()** | The heart of Myddleware: this method reads data (documents) inside your source application and transforms it to Myddleware format. | array $param | array |
+| **createData()** *OPTIONAL* | Writes data inside your target application solution. (Not all APIs allow you to do so). | array $param | array |
+| **updateData()** *OPTIONAL* | Similarly to createData(), this method allows you to update documents inside your target application solution. | array $param | array |
+
### getFieldsLogin() method
-In the new connector class, you need to implement the getFieldsLogin() method. Here, you have to put the parameters required to connect to your solution.
+In the new connector class, you need to implement the ``getFieldsLogin()`` method.
+Here, you have to put the parameters required to connect to your solution.
-For example, to login to the WooCommerce API, we need a URL, Consumer Key & Consumer Secret :
+For example, to log in to the WooCommerce API, we need a URL, a Consumer Key & a Consumer Secret :
```php
- public function getFieldsLogin()
+
+use Symfony\Component\Form\Extension\Core\Type\PasswordType;
+use Symfony\Component\Form\Extension\Core\Type\TextType;
+
+...
+
+class woocommercecore extends solution
+{
+ public function getFieldsLogin()
{
return [
- [
- 'name' => 'url',
- 'type' => TextType::class,
- 'label' => 'solution.fields.url',
- ],
- [
- 'name' => 'consumerkey',
- 'type' => PasswordType::class,
- 'label' => 'solution.fields.consumerkey',
- ],
- [
- 'name' => 'consumersecret',
- 'type' => PasswordType::class,
- 'label' => 'solution.fields.consumersecret',
- ],
- ];
+ [
+ 'name' => 'url',
+ 'type' => TextType::class,
+ 'label' => 'solution.fields.url',
+ ],
+ [
+ 'name' => 'consumerkey',
+ 'type' => PasswordType::class,
+ 'label' => 'solution.fields.consumerkey',
+ ],
+ [
+ 'name' => 'consumersecret',
+ 'type' => PasswordType::class,
+ 'label' => 'solution.fields.consumersecret',
+ ],
+ ];
}
+}
```
-> Check that everything is working in Myddleware
+> Check that everything is working in Myddleware UI by clicking on Connector->Creation, then select your application, the parameters you have added in your function should be visible.

@@ -155,16 +283,15 @@ For example, to login to the WooCommerce API, we need a URL, Consumer Key & Cons
### login() method
-Now to connect your connector, we need to create a new function in your class, we will call it "login".
+Now to connect your connector, we need to implement the login() method in order for Myddleware to be able to connect to your source application when creating a connector & running a rule.
+This method takes a ``$paramConnexion`` parameter which is an array containing the necessary data required to be able to log in.
-Example code, available in the file ```myddleware/src/Solution/suitecrm.php```
+Make sure every error is caught and ``this->connexion_valide`` is set to ``true`` if the connection was successful.
-You have to add this function login to check the connexion with you application.
-
-Make sure every error is catched and "this->connexion_valide = true" if the connexion works.
+Example implementation :
```php
- public function login($paramConnexion)
+ public function login($paramConnexion)
{
parent::login($paramConnexion);
try {
@@ -202,23 +329,30 @@ Make sure every error is catched and "this->connexion_valide = true" if the conn
}
```
-To debug this function, you can click on the button "Test" and check the result in firebug for example. The function will be called each time you click on "Test", no need to refresh the page.
+If you want to test out this method inside the Myddleware UI, you can already do it by filling in the "Create connector" form, filling in the fields & click on the "Test" button to check whether the Request & Response flow works properly.
+In case of a successful connection to your source application, the light bulb icon should colour itself. Otherwise, an error message should appear below.
-*Let's now create the first rule*
+
-### Method get_modules
+### get_modules() method
-Still in your connector class, we need to create a function that will display the list of modules in our connector. Create a "get_modules" function.
+We now need to create a method which will display the list of modules available in our connector. As mentioned before, the way to retrieve modules will depend on your source application.
+For instance, some applications will give you access to a method which will retrieve an up-to-date list of all available modules. You would then need to call this service and return its value as an
+array here. However, some apps do not provide such method and you will therefore need to manually input the list of modules you would like to retrieve.
-Here, you have to add the module you want to connect in the method.
+The ``type`` argument allows you to return a different set of modules depending on whether you are reading(``source``) or writing(``target``) inside your app.
+Indeed,some modules may be available as a source or as target only.
-In input you have access to the type of connexion, if your solution is in the target or in source of the rule. Some module could be available only source or only in target.
+```php
+ 'Contacts',
@@ -228,882 +362,523 @@ You then return an array with a list of module:
}
```
-**Other code examples are available in the:**
-```myddleware/src/Solutions/sugarcrm.php```
+Now you can test out whether this method worked inside the Myddleware UI by going to the rule creation view, select your solution & then check whether the module list returned in "Choose your module" is accurate.
-Now you can debug (with firebug for example) your function when the module list is called in the rule creation view(in "Choose your module") :
+
-
-Next step is the fields mapping, we now need to create a function for it.
+### get_module_fields() method
-### Method get_module_fields
+You have to indicate to Myddleware what fields are available for each module.
+If your application has a method which describes all fields for every module, you should use it.
+For example, you can check out the Salesforce & Prestashop connectors which resort to this strategy.
+Otherwise, you will have to provide an array of all fields with a simple descrition for each one.
+We often store these lists in metadata files inside the [/src/Solutions/lib](https://github.com/Myddleware/myddleware/tree/main/src/Solutions/lib) folder.
-You have to indicate to Myddleware what fields are available for each module. If your application has a function which describe all fields for every module, you should use it. For example, we did it for Salesforce or Prestashop. Otherwise you have to describe every field.
+#### Arguments
-- Add the function get_module_fields in you class.
+| Arguments | Description / values |
+|-----------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------|
+| string **$module** | The module to which a fields belongs to. |
+| string **$type = 'source'** | ``source`` or ``target``
If a module is only available as a target, set it to ``target``, else, the default is source (which works for both source & target) |
+| array **$param = null()** | Additional optional parameters. |
-
-
-#### **Input**
-
-- Module indicate from which module we need the fields
-
-- Type indicate if the module is in source or in target in the rule
-
-#### **Output**
+#### Signature
- An array with all the fields for the module
-You should then add the fields related (field available to create relationship) and the class attribute this->fieldsRelate
-
-- Your fields will then be displayed after clicking on the button “Go to fields mapping”. You can refresh this page, your function will be called each time this page is loaded :
-
-
-
-
-*Create a mapping and save the rule. We will now create the function read*
+You should then add the related fields (field available to create relationship) and the property $this->fieldsRelate.
-### Method read
+Example implementation :
-> The read function is one of the most important function in the connector.
+````php
+ only if you use your application as a target, not only a source
-- You can open your rule, tab parameter, and click “Simulate transfer”, this button will call the read function :
-
-
+...
-You can also run your rule in a command prompt :
+class wordpresscore extends solution {
+
+ ...
- php bin/console myddleware:synchro –env=background
+ public function get_module_fields($module, $type = 'source', $param = null)
+ {
+ parent::get_module_fields($module, $type);
+ try {
+ require_once 'lib/wordpress/metadata.php';
+ if (!empty($moduleFields[$module])) {
+ $this->moduleFields = array_merge($this->moduleFields, $moduleFields[$module]);
+ }
-Here is an example of input value :
+ if (!empty($fieldsRelate[$module])) {
+ $this->fieldsRelate = $fieldsRelate[$module];
+ }
-
+ if (!empty($this->fieldsRelate)) {
+ $this->moduleFields = array_merge($this->moduleFields, $this->fieldsRelate);
+ }
-Parameters :
+ return $this->moduleFields;
+ } catch (\Exception $e) {
+ $this->logger->error($e->getMessage().' '.$e->getFile().' '.$e->getLine());
+ return false;
+ }
+ }
+}
+````
-- Module is the module to read in your application
-- Rule contains the parameters of the rule
-- Date_ref is used to search all data modified or created after this reference
-- RuleParams is the parameters of the rule
-- Fields contains every fields mapped in the rule.
-- Offset and limit are used only if your application has to be read with limited data
-- jobId is the if of the job
-- Manual indicate if the rule is run manually
+Your fields will then be displayed after clicking on the button ``Go to fields mapping``.
+You can refresh this page, your method will be called each time this page is loaded.
-Myddleware has to be able to read records from the source application. The list of fields returns must be the ones in the rule field mapping (input entry : fields). But some other fields are requiered : the id of the record and its reference (usually the modified record datetime). But the id and reference can be named differently depending on the application and the module.
+
-> It is the reason why you have to create the attribute required_fields in your class :
-IMAGE
+### read() method
-The next step is to call the webservice function of your application depending on the input parameter :
+> The read() method is the most important method of a connector. This is the true heart of Myddleware, where all the magic happens. Indeed, this method is the one that allows you to retrieve documents from your source application.
-If the entry query exists in input then it is prioritary, you have to use the query parameter to search records
-If the entry query is empty then you have to use the reference. Myddleware must search all records created/modified ather the content of the parameter date_ref
-The function should return an array with these entries :
+The read() method needs to be able to :
-count with the number of records read. Has to be 2 if no record are read.
-date_ref with the new date_ref. It has to be the max date found in the list records returns.
-values with an array of records. The key of these entries has to be the id of the record. The entry id and date_modified has to be present for each record. Date modified contains the value of the date_created or date_modified depending the type of the rule .
+- Read records using a **reference** (usually a ``date_modified`` or ``updatedAt`` property)
+- Read a specific record using the **record's id**
+- Search for a record based on criteria (used in duplicate search) => only if you use your application as a target
-> Tips: for the date format, we need to create a function "DateTimeMyddleware", which converts the date Myddleware format, we can take inspiration from the function created in the ```myddleware/src/Solutions/woocommerce.php```. We will also need to convert the Myddleware format to your connector fromat if necessary.
+If you want to check whether this method is correctly implemented inside the Myddleware UI, you can open your rule, click on the ``Parameters`` tab, and click on ``Simulate documents``.
-The output of the function read should look like this:
+!> When you do, please remember to set a reference date in the past and to click on the ``Save`` button before launching the simulation, otherwise no documents will be read.
-IMAGE
+If all went well, you should get a number of documents to be read in the ``Estimated documents`` input.
-### Method create
+
-Create a rule now with your application in target. Then create the function public function create($param) in your class.
+You can also run your rule using a command prompt with :
-Run your rule as you did while developing the method read.
+````php
+ php bin/console myddleware:synchro –-env=background
+````
Here is an example of input value :
-
-
-Parameters :
-
-- data contains all the record Myddleware want to create in tour application. The key of each record is the id of the data trasfer in Myddleware
-- module is the module to write in your application
-- ruleId is teh id of the rule
-- rule contains the parameters of the rule
-- ruleFields contains the fields of the rule
-- ruleParams is the parameters of the rule
-- ruleRelationships contains the relationships with the current rule
-- fieldsType contains the type of all fields in the rule
-- jobId is the if of the job
-
-The output of the function created should look like these :
-
- [
- [583f4dd2c4c843.39717569] => [
- [id] => 65
- [error] =>
- ]
-
- [583f4dd2c4c843.39717569] => [
- [id] => 66
- [error] =>
- ]
- ]
-
-> To help writing code and not recreate time-consuming manipulation in Myddleware, we can use in your terminal :
-
-Read a record:
-
- bin/console myddleware:readrecord --env=background
-
-Reread a document:
-
- bin/console myddleware:massaction rerun document --env=background
-
-### Method update
-
-The method update works in the same way as the method create. The output parameter must be built exactly like in the method create.
-
-The only difference is that you have the entry “target_id” for each record in the array data. You will need this entry to update your data in your application.
-
-## Create formula
-
-In this article we‘ll look at an important point in your synchronization rules and one of the many setting options offered by Myddleware, formulas.
-
-### The fundamentals
-
-For starters, formulas allow you to format or to set the values that will be sent to a given target field . In other words, you have the option of adding fixed text to all uppercase, change timezones, concatenate several source fields etc.
-
-### The syntaxe
-
-To help, syntax highlighting (1) is available to you right on your text box. Furthermore you will find below, the list of source fields that you have chosen (2), the available functions and their categories (3) and one or two drop list(s) (4) of the different values for the list type fields (as SalutationID example).
-
-
-
-**Examples**
-
-- Concatenate multiple fields, Myddleware uses the “.” as in PHP {field1}.{field2}.{fields3}
-
-- Concatenate a fixed text with one or multiple fields “Client Name: “.{Firstname}.” “.{Lastname}
-
-- Three-valued condition , “If the Greeting field is ‘Mr.’ then send 1, otherwise send 2” is written as followed : (({Greeting} == “Mr.”) ? “1” : “2”), those three-valued conditions can be nested in order, for example, to make the data correspond. Thus, ({resolution} == “10” ? “Open” : ({resolution} == “20” ? “Fixed” : ({resolution} == “30” ? “Reopened” : “Suspended”))) is correct and functional, this formula means “If resolution is 10 then ‘Open’ is sent, otherwise if resolution is 20 then ‘Fixed‘ is sent, otherwise if resolution is 30 then ‘Reopened’ is sent, otherwise ‘Suspended ‘ is sent.
-
-- Add two fileds {field1} + {field2}
-
-In this article we‘ll look at an important point in your synchronization rules and one of the many setting options offered by Myddleware, formulas.
-
-**Functions**
-
-In the formula of Myddleware, you can use the functions listed at the bottom right (see of the previous image).
-
-
-This function round floating point (up), ([PHP](https://www.php.net/manual/fr/function.round.php)) **round(numbre [, clarification])**:
-
- round(525.6352, 2) // Gives 525.64
-
-Rounds up, ([PHP](https://www.php.net/manual/fr/function.ceil.php)) **ceil(float)**:
-
- ceil(525.6352) // Gives 526
-
-Returns the absolute value, ([PHP](https://www.php.net/manual/fr/function.abs.php)) **abs(number)**:
-
- abs(-5) // Gives 5
-
-Deletes spaces (or other charachters) at the begenning and the end of a string, ([PHP](https://www.php.net/manual/fr/function.trim.php)) **trim(string [, Masque])**:
-
- trim(” bonjour “) // Returns “bonjour”
-
-Lowercases all charachters, ([PHP](https://www.php.net/manual/fr/function.mb-strtolower.php)) **lower(STRING)**:
+
+
+| Parameters | Description / values |
+|----------------------|------------------------------------------------------------------------------------------------------------------------------------|
+| string **module** | The module to read in your application. |
+| array **rule** | Contains the parameters of the rule (``id``, ``conn_id_source``, ``conn_id_target``, ``date_modified``, ...). |
+| string **date_ref** | Reference date from which to look for newly-created or modified documents. |
+| array **ruleParams** | Rule parameters (``limit``, ``delete``, ``datereference``, ``mode``, ``duplicate_fields``). |
+| array **fields** | List of mapped fields for this rule.The read() method has to return a value for all these fields in each records. |
+| array **query** | If defined, the read method has to return the result of the query. Otherwise, Myddleware will user the reference date to read data. |
+| int **offset** | Used only if your application has to be read with limited data. |
+| int **limit** | Used only if your application has to be read with limited data. |
+| string **jobId** | ID of the job (task). |
+| string **manual** | Indicates whether the rule is ran manually. |
+
+#### Defining which fields to be read (required fields)
+
+Myddleware has to be able to read records from the source application.
+The array of fields returned must be the ones provided during the fields mapping stage of rule creation (input entry : fields).
+
+!> Some fields are always required to be mapped for Myddleware to be able to launch a synchro / read() command : the record's ``id`` and its ``reference`` (usually the record's modified datetime).
+Watch out though as the id and reference can be named differently depending on the application and module.
+For that reason, each newly developed connector class must include a ``$required_fields`` class property.
+
+To do so, you need to make sure you set the ``default`` entry of required fields. You should then only add entries for modules whose required fields are different from the default ones.
+Example of required fields list (Prestashop connector):
+
+````php
+class prestashopcore extends solution
+{
+ protected $required_fields = [
+ 'default' => ['id', 'date_upd', 'date_add'],
+ 'product_options' => ['id'],
+ 'product_option_values' => ['id'],
+ 'combinations' => ['id'],
+ 'stock_availables' => ['id'],
+ 'order_histories' => ['id', 'date_add'],
+ 'order_details' => ['id'],
+ 'customer_messages' => ['id', 'date_add'],
+ 'order_carriers' => ['id', 'date_add'],
+ 'order_payments' => ['id', 'date_add', 'order_reference'],
+ ];
+ ...
+}
+````
+
+The ``addRequiredField($fields, $module = 'default', $mode = null)`` method from the Solution parent class will be called in the background to load these required fields you've defined.
+
+#### Handling date formats - dateTimeToMyddleware() & dateTimeFromMyddleware()
+
+Regarding dates format, you may need to override the ``dateTimeToMyddleware()`` method, which converts the source application's date into Myddleware-readable format.
+we can take inspiration from the function created in the ```myddleware/src/Solutions/woocommerce.php```.
+Inversely, you may need to override the ``dateTimeFromMyddleware()`` method in order to convert the dates provided by Myddleware to your source application's format.
+Here is an [example](https://github.com/Myddleware/myddleware/blob/1d840df4fec23eddd47026cafb064ce109155c45/src/Solutions/woocommerce.php#L160) of connector resorting to these methods.
+
+````php
+
+namespace App\Solutions;
+
+use Automattic\WooCommerce\Client;
+
+class woocommercecore extends solution
+{
- lower(“BONJOUR”) // Returns “bonjour”
-
-Uppercases all charachters, ([PHP](https://www.php.net/manual/fr/function.mb-strtoupper.php)) **upper(String)**:
-
- upper(“bonjour”) // Returns “BONJOUR”
-
-Formats a local date/hour, ([PHP](https://www.php.net/manual/fr/function.date.php)) **date(Format [, Timestamp])**:
-
- date(“Y:m:d”) // Returns “2014:09:16”
-
-Returns current Unix timestamp with microseconds, ([PHP](https://www.php.net/manual/fr/function.microtime.php)) **microtime([true if you want a float result])**:
+...
- microtime(true) // Returns 1410338028.5745
+ protected $woocommerce; // HTTP Client
-Changes the timezone of the given date, ([PHP](https://www.php.net/manual/fr/timezones.php)) **changeTimeZone(Date you want to change, old timezone, new timezone)**:
+ public function read($param)
+ {
+ try {
+ $module = $param['module'];
+ $result = [];
+ // format the reference date
+ $dateRefWooFormat = $this->dateTimeFromMyddleware($param['date_ref']);
+ // Set the limit
+ if (empty($param['limit'])) {
+ $param['limit'] = $this->callLimit;
+ }
- changeTimeZone(“2014-09-16 12:00:00”, “America/Denver”, “America/New_York”) // Returns “2014-09-16 14:00:00”
+ // adding query parameters into the request
+ if (!empty($param['query'])) {
+ $query = '';
+ foreach ($param['query'] as $key => $value) {
+ if ('id' === $key) {
+ $query = strval('/'.$value);
+ } else {
+ // in case of query on sub module, we check if that the search field is the parent id
+ if (
+ !empty($this->subModules[$param['module']])
+ and $this->subModules[$param['module']]['parent_id'] == $key
+ ) {
+ $query = strval('/'.$value);
+ }
+ }
+ }
+ }
-Changes the format of the given date, **changeFormatDate(Date you want to change, New format)**:
+ //for submodules, we first send the parent module in the request before working on the submodule with convertResponse()
+ if (!empty($this->subModules[$param['module']])) {
+ $module = $this->subModules[$param['module']]['parent_module'];
+ }
- changeTimeZone(“2014-09-16 12:00:00”, “Y/m/d H:i:s”) // Returns “2014/09/16 12:00:00”
+ $stop = false;
+ $count = 0;
+ $page = 1;
+ do {
+ //for specific requests (e.g. readrecord with an id)
+ if (!empty($query)) {
+ $response = $this->woocommerce->get($module.$query, ['per_page' => $this->callLimit,
+ 'page' => $page, ]);
+ //when reading a specific record only we need to add a layer to the array
+ $records = $response;
+ $response = [];
+ $response[] = $records;
+ } elseif ('customers' === $module) {
+ //orderby modified isn't available for customers in the API filters so we sort by creation date
+ $response = $this->woocommerce->get($module, ['orderby' => 'registered_date',
+ 'order' => 'asc',
+ 'per_page' => $this->callLimit,
+ 'page' => $page, ]);
+ //get all data, sorted by date_modified
+ } else {
+ $response = $this->woocommerce->get($module, ['orderby' => 'modified',
+ 'per_page' => $this->callLimit,
+ 'page' => $page, ]);
+ }
+ if (!empty($response)) {
+ //used for submodules (e.g. line_items)
+ $response = $this->convertResponse($param, $response);
+ foreach ($response as $record) {
+ $row = [];
+ //either we read all from a date_ref or we read based on a query (readrecord)
+ if ($dateRefWooFormat < $record->date_modified || (!empty($query))) {
+ foreach ($param['fields'] as $field) {
+ // If we have a 2 dimensional array we break it down
+ $fieldStructure = explode('__', $field);
+ $fieldGroup = '';
+ $fieldName = '';
+ if (!empty($fieldStructure[1])) {
+ $fieldGroup = $fieldStructure[0];
+ $fieldName = $fieldStructure[1];
+ $row[$field] = (!empty($record->$fieldGroup->$fieldName) ? $record->$fieldGroup->$fieldName : '');
+ } else {
+ $row[$field] = (!empty($record->$field) ? $record->$field : '');
+ }
+ }
+ $row['id'] = $record->id;
+ ++$count;
+ $result[] = $row;
+ } else {
+ $stop = true;
+ }
+ }
+ } else {
+ $stop = true;
+ }
+ if (!empty($query)) {
+ $stop = true;
+ }
+ ++$page;
+ } while (!$stop && $count < $param['limit']);
+ } catch (\Exception $e) {
+ $result['error'] = 'Error : '.$e->getMessage().' '.$e->getFile().' Line : ( '.$e->getLine().' )';
+ }
-Reads a string starting of the given Index, ([PHP](https://www.php.net/manual/fr/function.mb-substr.php)) **substr(String, Indexample)**:
+ return $result;
+ }
+
+ // Convert date to Myddleware format
+ // 2020-07-08T12:33:06 to 2020-07-08 10:33:06
+ protected function dateTimeToMyddleware($dateTime)
+ {
+ $dto = new \DateTime($dateTime);
- substr(“abcdef”, -1) // Returns “f”
+ return $dto->format('Y-m-d H:i:s');
+ }
-Strips HTML and PHP tags from a string, ([PHP](https://www.php.net/manual/fr/function.strip-tags.php)) **striptags(String)**:
+ //convert from Myddleware format to Woocommerce format
+ protected function dateTimeFromMyddleware($dateTime)
+ {
+ $dto = new \DateTime($dateTime);
+ // Return date to UTC timezone
+ return $dto->format('Y-m-d\TH:i:s');
+ }
- striptags(“Test paragraph.
Other text”) // Returns “Test paragraph. Other text”
+ public function getRefFieldName($moduleSource, $ruleMode)
+ {
+ return 'date_modified';
+ }
+
+}
-## API Overwiew
+````
-The API is built to allow you to call Myddleware from your application using REST protocol. For example, you will be able to call a specific Myddlewere ‘s rule when a specific event happends in your application. You will also be able to synchronize a specific record using a call to Myddleware.
+#### Signature
-Please find the [postman collection here](https://documenter.getpostman.com/view/1328767/SzS7QmCj?version=latest#e564597d-ef6e-40e1-87f1-c69b7b2d7479).
+Myddleware must search for all records created/modified after the content of the ``date_ref`` parameter.
+If set, the query parameter takes priority to return results.
+The read() method should return an ``array`` containing the following entries :
-Please find our [php sample code](https://github.com/Myddleware/myddleware_api).
+- ``count`` : the number of records read. Has to be 2 if no records were read.
+- ``date_ref`` which should be set to the new ``date_ref``. It has to be the max date found in the returned records list.
+- ``values`` which should contain an ``array`` of records. The key of these entries has to be the ``id`` of the record.
+ - Each record should have an ``id`` and ``date_modified`` entry. Date modified contains the value of ``date_created`` or ``date_modified``, depending on the type of rule.
-### Authentification
+The ``read()`` method's output should look like this :
-The function login_check is used to get a bearer tocken from Myddleware. This token well be required for all calls to Myddleware.
+
-Here are [CURL info](https://documenter.getpostman.com/view/1328767/SzS7QmCj?version=latest#e564597d-ef6e-40e1-87f1-c69b7b2d7479) :
+### create() method - OPTIONAL
-```
- curl --location --request POST 'http://localhost/myddleware/web/api/v1_0/login_check' \
- --header 'Content-Type: application/json' \
- --data-raw '{
- "username":"username",
- "password":"password"
- }'
-```
+> This method will allow Myddleware to add new records into your application when it is set as a target. However, not all solutions allow
+> for third-party software to write into them. Hence why this method is optional in Myddleware.
-**Output :**
-
-#### **if success :**
+Here is an example of input value :
-```php
- {
- « token »:
- }
-```
+
-#### **If error :**
-```php
- {
- « code »: ,
- « message »:
- }
-```
-
-### Function synchro
+| Parameters | Description / values |
+|-----------------------------|-----------------------------------------------------------------------------------------------------------------------------------------|
+| array **data** | Records which Myddleware will attempt to create in your target application. The key of each record is the document ``id`` in Myddleware |
+| string **module** | The module into which to write into in your application. |
+| string **ruleId** | The rule's ``id`` |
+| array **rule** | Contains the rule's parameters (``id``, ``conn_id_source``, ``conn_id_target``, ``date_modified``, ...). |
+| array **ruleFields** | Fields to be mapped inside the rule. |
+| array **ruleParams** | Rule parameters (``limit``, ``delete``, ``datereference``, ``mode``, ``duplicate_fields``). |
+| array **ruleRelationships** | Potential relationships with other rules this rule may have. |
+| string **fieldsType** | The type of all fields in the rule. |
+| string **jobId** | ID of the job (task). |
-Use the synchro function to run a specific rule or every active rules.
-Here are [CURL info](https://documenter.getpostman.com/view/1328767/SzS7QmCj?version=latest#96de2d5c-7a77-4d50-aa15-2657663459b2) :
+#### Signature
-```
- curl --location --request POST 'http://localhost/myddleware/web/api/v1_0/synchro' \
- --header 'Content-Type: application/json' \
- --form 'rule='
-```
+The method's output should return an array with an array (key = ``id`` of the Myddleware document) for each record created.
+This array has 2 entries :
-Set the rule id you want to run in Myddleware. Set ALL if you want to reun avery active rules.
+| Parameters | Description / values |
+|-------------------|----------------------------------------------------------------|
+| string **id** | ID of the record inside the target application. |
+| string **error** | Error message or empty if the record was successfully created. |
-**Output :**
+Example output:
-```php
- {
- « error »: « »,
- « jobId »: « 5e78c2cc32c926.66619369 »,
- « jobData »: {
- « Close »: « 2 »,
- « Cancel »: 0,
- « Open »: 0,
- « Error »: 0,
- « paramJob »: « Synchro : 5e5e5535564c0 »,
- « solutions »: « ^6^,^27^ »,
- « duration »: 13.43,
- « myddlewareId »: « 5e78c2cc32c926.66619369 »,
- « Manual »: 1,
- « Api »: 1,
- « jobError »: « »,
- « documents »: [
- {
- « id »: « 5e78c2cd317ac3.60227368 »,
- « rule_id »: « 5e5e5535564c0 »,
- « date_created »: « 2020-03-23 14:08:13 »,
- « date_modified »: « 2020-03-23 14:08:24 »,
- « created_by »: « 1 »,
- « modified_by »: « 1 »,
- « status »: « Send »,
- « source_id »: « 4×72 »,
- « target_id »: « 878987c2-4000-7c15-c353-5e63a95c2397 »,
- « source_date_modified »: « 2017-10-09 14:46:34 »,
- « mode »: « 0 »,
- « type »: « U »,
- « attempt »: « 1 »,
- « global_status »: « Close »,
- « parent_id »: « »,
- « deleted »: « 0 »
- },
- {
- « id »: « 5e78c2ceab9782.10596576 »,
- « rule_id »: « 5e5e5535564c0 »,
- « date_created »: « 2020-03-23 14:08:14 »,
- « date_modified »: « 2020-03-23 14:08:25 »,
- « created_by »: « 1 »,
- « modified_by »: « 1 »,
- « status »: « Send »,
- « source_id »: « 4×73 »,
- « target_id »: « d28dc52c-68db-f679-5c80-5e63a9287457 »,
- « source_date_modified »: « 2020-03-09 15:33:14 »,
- « mode »: « 0 »,
- « type »: « U »,
- « attempt »: « 1 »,
- « global_status »: « Close »,
- « parent_id »: « »,
- « deleted »: « 0 »
- }
+````php
+ [
+ [583f4dd2c4c843.39717569] => [
+ [id] => 65
+ [error] =>
]
- }
- }
-```
-### Function read record
-
-Use the read record function to force Myddleware to read a specific record into your application. For example. you can call this function when a record is saved into your application. Myddleware will read it from your source application and send it to your target application. It is used when you need a real time synchronisation.
-
-Here are [CURL info](https://documenter.getpostman.com/view/1328767/SzS7QmCj?version=latest#68ee49d2-2fea-47ca-92ad-5d2345b6ba0c) :
-
-```
- curl --location --request POST 'http://localhost/myddleware/web/api/v1_0/read_record' \
- --form 'rule=' \
- --form 'filterQuery=' \
- --form 'filterValues='
-```
+ [583f4dd2c4c843.39717569] => [
+ [id] => 66
+ [error] =>
+ ]
+ ]
+````
-**Set these parameters :**
+> Tip: during the testing / debugging phase, to help writing code and not recreate time-consuming manipulation in Myddleware,
+> you can run the following commands in your terminal
-- rule : The rule you want to run
-- filterQuery : The field used to build the query executed into your application by Myddleware. It is usually the « id » field ‘s name of your record.
-- filterValue : The field value used in the parameter filterQuery. It is usually the id of your record.
+Read a record:
-**Output :**
+ bin/console myddleware:readrecord --env=background
-```php
- {
- « error »: « »,
- « jobId »: « 5e78c4c4ec8631.31640728 »,
- « jobData »: {
- « Close »: 0,
- « Cancel »: « 1 »,
- « Open »: 0,
- « Error »: 0,
- « paramJob »: « read records wilth filter id IN (4×60) »,
- « solutions »: « ^6^,^27^ »,
- « duration »: 2.42,
- « myddlewareId »: « 5e78c4c4ec8631.31640728 »,
- « Manual »: 1,
- « Api »: 1,
- « jobError »: « »,
- « documents »: [
- {
- « id »: « 5e78c4c5f27231.38354025 »,
- « rule_id »: « 5e5e5535564c0 »,
- « date_created »: « 2020-03-23 14:16:37 »,
- « date_modified »: « 2020-03-23 14:16:39 »,
- « created_by »: « 1 »,
- « modified_by »: « 1 »,
- « status »: « No_send »,
- « source_id »: « 4×60 »,
- « target_id »: « e559cfe4-4e41-e2da-235e-5e63a985d98e »,
- « source_date_modified »: « 2017-10-09 14:46:24 »,
- « mode »: « 0 »,
- « type »: « U »,
- « attempt »: « 0 »,
- « global_status »: « Cancel »,
- « parent_id »: « »,
- « deleted »: « 0 »
- }
- ]
- }
- }
-```
+Reread a document:
-### Function mass action
+ bin/console myddleware:massaction rerun document --env=background
-Use the mass action function to change (rerun, cancel, remove, restore or change the status) a group of data transfer.
-Here are [CURL info](https://documenter.getpostman.com/view/1328767/SzS7QmCj?version=latest#eef6a218-fc20-4d3b-8d49-59b9d3d221cb) :
-```
- curl --location --request POST 'http://localhost/myddleware/web/api/v1_0/mass_action' \
- --header 'action: ' \
- --form 'action=restore' \
- --form 'dataType=rule' \
- --form 'ids=5e5e5535564c0' \
- --form 'forceAll=Y'
-```
+Here is [an example of implementation](https://github.com/Myddleware/myddleware/blob/1d840df4fec23eddd47026cafb064ce109155c45/src/Solutions/sendinblue.php#L445):
-**Set these parameters :**
+````php
-- action : rerun, cancel, remove, restore or changeStatus.
-- dataType : rule or document. If you want to select data transfer using a rule (all data transfer of the rule) as the filter set « rule ». Otherwise set « document » if you want to filter your search by data transfer id.
-- ids : set the id(s) of the data transfer (document) or the rule depending of what you have set in the parameter dataType. If you put several ids, then put commas to separate them.
-- forceAll (optional) : Set Y to process action on all data transfer (not only open and error ones). In this case, be carefull, you could remove, cancel or change status of data successfully sent to your target application. Myddleware could generate duplicate data in your target application if you run again your rule without setting duplicate fields.
-- fromStatus : Only used with action changeStatus action. Add filter to select data transfer depending of their status.
-- toStatus : Only used with action changeStatus action. New status to be set on all data transfer selected.
+namespace App\Solutions;
-**Output :**
+use ApiPlatform\Core\OpenApi\Model\Contact;
+use SendinBlue\Client\Model\GetContacts;
-```php
- {
- « error »: « »,
- « jobId »: « 5e78dcacb8f1d0.97025863 »,
- « jobData »: {
- « Close »: « 30 »,
- « Cancel »: « 70 »,
- « Open »: 0,
- « Error »: 0,
- « paramJob »: « Mass remove on data type rule »,
- « solutions »: « ^6^,^27^ »,
- « duration »: 10.28,
- « myddlewareId »: « 5e78dcacb8f1d0.97025863 »,
- « Manual »: 1,
- « Api »: 1,
- « jobError »: « »,
- « documents »: [
- {
- « id »: « 5e6685af04d858.22701783 »,
- « rule_id »: « 5e5e5535564c0 »,
- « date_created »: « 2020-03-09 18:06:39 »,
- « date_modified »: « 2020-03-23 15:58:36 »,
- « created_by »: « 1 »,
- « modified_by »: « 1 »,
- « status »: « Cancel »,
- « source_id »: « 4×72 »,
- « target_id »: null,
- « source_date_modified »: « 2020-03-09 19:06:39 »,
- « mode »: « 0 »,
- « type »: « D »,
- « attempt »: « 0 »,
- « global_status »: « Cancel »,
- « parent_id »: « »,
- « deleted »: « 1 »
- },
- {
- « id »: « 5e6685fd2cfbb8.35868016 »,
- « rule_id »: « 5e5e5535564c0 »,
- « date_created »: « 2020-03-09 18:07:57 »,
- « date_modified »: « 2020-03-23 15:58:36 »,
- « created_by »: « 1 »,
- « modified_by »: « 1 »,
- « status »: « Cancel »,
- « source_id »: « 4×72 »,
- « target_id »: null,
- « source_date_modified »: « 2020-03-09 19:07:57 »,
- « mode »: « 0 »,
- « type »: « D »,
- « attempt »: « 0 »,
- « global_status »: « Cancel »,
- « parent_id »: « »,
- « deleted »: « 1 »
- },
- {
- « id »: « 5e668618964e93.34804135 »,
- « rule_id »: « 5e5e5535564c0 »,
- « date_created »: « 2020-03-09 18:08:24 »,
- « date_modified »: « 2020-03-23 15:58:36 »,
- « created_by »: « 1 »,
- « modified_by »: « 1 »,
- « status »: « Cancel »,
- « source_id »: « 4×72 »,
- « target_id »: null,
- « source_date_modified »: « 2020-03-09 19:08:24 »,
- « mode »: « 0 »,
- « type »: « D »,
- « attempt »: « 0 »,
- « global_status »: « Cancel »,
- « parent_id »: « »,
- « deleted »: « 1 »
- },
- {
- « id »: « 5e669dcd915191.00190986 »,
- « rule_id »: « 5e5e5535564c0 »,
- « date_created »: « 2020-03-09 19:49:33 »,
- « date_modified »: « 2020-03-23 15:58:37 »,
- « created_by »: « 1 »,
- « modified_by »: « 1 »,
- « status »: « Cancel »,
- « source_id »: « 4×72 »,
- « target_id »: null,
- « source_date_modified »: « 2020-03-09 20:49:33 »,
+class sendinbluecore extends solution
+{
+ protected function create($param, $record, $idDoc = null)
+ {
+ // Import or create new contact for sendinblue
+ $apiInstance = new \SendinBlue\Client\Api\ContactsApi(new \GuzzleHttp\Client(), $this->config);
+ $createContact = new \SendinBlue\Client\Model\CreateContact(); // Values to create a contact
+ $createContact['email'] = $record['email'];
+ // Add attributes
+ $createContact['attributes'] = $record;
+ $result = $apiInstance->createContact($createContact);
+
+ return $result->getId();
+ }
+}
-```
+````
-```
- […………………………………………………………………………]
- « mode »: « 0 »,
- « type »: « U »,
- « attempt »: « 1 »,
- « global_status »: « Close »,
- « parent_id »: « »,
- « deleted »: « 1 »
- }
- ]
- }
- }
-```
-### Function rerun error
+### update() method - OPTIONAL
-Use the rerun error function to run again data transfer in error.
+The update() method is similar to the create() method. The output parameters should therefore be exactly the same as create().
-Here are [CURL info](https://documenter.getpostman.com/view/1328767/SzS7QmCj?version=latest#34418cf2-e545-4423-8411-c2784785b2bd) :
+The only difference is that there should be a ``target_id`` entry for each record. This entry is required in order to update data inside the target application.
-```
- curl --location --request POST 'http://localhost/myddleware/web/api/v1_0/rerun_error' \
- --form 'limit=10' \
- --form 'attempt=5'
-```
+Here is [an example of implementation](https://github.com/Myddleware/myddleware/blob/1d840df4fec23eddd47026cafb064ce109155c45/src/Solutions/sendinblue.php#L459):
-**Set these parameters :**
+````php
-- limit : set the limit parameter to limit the number of data transfer selected by the job.
-- attempt : Myddleware will read only data transfer with a number of attemps <= at this parameter
+namespace App\Solutions;
-**Output :**
+use ApiPlatform\Core\OpenApi\Model\Contact;
+use SendinBlue\Client\Model\GetContacts;
-```php
- {
- « error »: « »,
- « jobId »: « 5e78e6cdd789e7.70152075 »,
- « jobData »: {
- « Close »: 0,
- « Cancel »: 0,
- « Open »: 0,
- « Error »: « 3 »,
- « paramJob »: « Rerun error : limit 3, attempt 5 »,
- « solutions »: « ^14^,^6^,^3^ »,
- « duration »: 1.09,
- « myddlewareId »: « 5e78e6cdd789e7.70152075 »,
- « Manual »: 1,
- « Api »: 1,
- « jobError »: « »,
- « documents »: [
- {
- « id »: « 5e612055c98da7.22680820 »,
- « rule_id »: « 5e611b50c0a6f »,
- « date_created »: « 2020-03-05 15:52:53 »,
- « date_modified »: « 2020-03-23 16:41:50 »,
- « created_by »: « 1 »,
- « modified_by »: « 1 »,
- « status »: « Error_sending »,
- « source_id »: « efa139c1-5e46-b247-739d-5ba8412aa24a »,
- « target_id »: null,
- « source_date_modified »: « 2018-09-24 01:43:35 »,
- « mode »: « 0 »,
- « type »: « C »,
- « attempt »: « 6 »,
- « global_status »: « Error »,
- « parent_id »: « »,
- « deleted »: « 0 »
- },
- {
- « id »: « 5e72552e4fe687.45181957 »,
- « rule_id »: « 5e5cc8984ba84 »,
- « date_created »: « 2020-03-18 17:06:54 »,
- « date_modified »: « 2020-03-23 16:41:50 »,
- « created_by »: « 1 »,
- « modified_by »: « 1 »,
- « status »: « Error_sending »,
- « source_id »: « 8 »,
- « target_id »: null,
- « source_date_modified »: « 2019-02-06 22:07:59 »,
- « mode »: « 0 »,
- « type »: « C »,
- « attempt »: « 6 »,
- « global_status »: « Error »,
- « parent_id »: « »,
- « deleted »: « 0 »
- },
- {
- « id »: « 5e72552e51d612.98166090 »,
- « rule_id »: « 5e5cc8984ba84 »,
- « date_created »: « 2020-03-18 17:06:54 »,
- « date_modified »: « 2020-03-23 16:41:50 »,
- « created_by »: « 1 »,
- « modified_by »: « 1 »,
- « status »: « Error_sending »,
- « source_id »: « 12 »,
- « target_id »: « 15 »,
- « source_date_modified »: « 2020-03-03 10:43:31 »,
- « mode »: « 0 »,
- « type »: « U »,
- « attempt »: « 6 »,
- « global_status »: « Error »,
- « parent_id »: « »,
- « deleted »: « 0 »
- }
- ]
- }
+class sendinbluecore extends solution
+{
+ protected function update($param, $record, $idDoc = null)
+ {
+ try {
+ $apiInstance = new \SendinBlue\Client\Api\ContactsApi(new \GuzzleHttp\Client(), $this->config);
+ $updateContact = new \SendinBlue\Client\Model\UpdateContact(); // Values to create a contact
+ // target_id contains the id of the record to be modified
+ $identifier = $record['target_id'];
+ $updateContact['attributes'] = $record;
+ $result = $apiInstance->updateContact($identifier, $updateContact);
+ } catch (\Exception $e) {
+ throw new \Exception('Exception when calling ContactsApi->updateContact: '.$e->getMessage());
}
-```
-
-### Function delete record
-Use the delete record function to delete a specific record into the target application using the id of the source application.
-
-Here are [CURL info](https://documenter.getpostman.com/view/1328767/SzS7QmCj?version=latest#5f6f441e-ac1e-468e-bd5f-ab8fd67c6c88) :
+ return $identifier;
+ }
+}
-```
- curl --location --request POST 'http://localhost/myddleware/web/api/v1_0/delete_record' \
- --form 'rule=5e5e5535564c0' \
- --form 'recordId=4x65' \
- --form 'reference=2020-03-09 12:14:36' \
- --form 'lastname=lastname01' \
- --form 'email=test@test.test' \
- --form 'firstname=firstname01'
-```
+````
-**Set these parameters :**
-- rule : The id of the rule
-- recordId : The id of the record in the source application. Then Myddleware will use the rule to get the id of this record in the target application and delete it.
-- reference : the reference date or id used in Myddleware. Use the reference field already used in this rule.
-- Each field of the rule have to be added as input parameters
+### createData() & updateData() alternative methods - OPTIONAL
-**Output :**
+Instead of overriding the create() & update() methods, you may wish to override the createData() & updateData() methods instead.
+Here is an [example of implementation](https://github.com/Myddleware/myddleware/blob/1d840df4fec23eddd47026cafb064ce109155c45/src/Solutions/woocommerce.php#L286) :
-```php
- {
- « error »: « »,
- « jobId »: « 5e78e7a7621400.01014726 »,
- « jobData »: {
- « Close »: 1,
- « Cancel »: 0,
- « Open »: 0,
- « Error »: 0,
- « paramJob »: « Delete record 4×63 in rule 5e5e5535564c0 »,
- « solutions »: « ^6^,^27^ »,
- « duration »: 0.32,
- « myddlewareId »: « 5e78e7a7621400.01014726 »,
- « Manual »: 1,
- « Api »: 1,
- « jobError »: « »,
- « documents »: [
- {
- « id »: « 5e78e7a766e656.99183539 »,
- « rule_id »: « 5e5e5535564c0 »,
- « date_created »: « 2020-03-23 16:45:27 »,
- « date_modified »: « 2020-03-23 16:45:27 »,
- « created_by »: « 1 »,
- « modified_by »: « 1 »,
- « status »: « Send »,
- « source_id »: « 4×63 »,
- « target_id »: null,
- « source_date_modified »: « 2020-03-09 12:14:36 »,
- « mode »: « 0 »,
- « type »: « D »,
- « attempt »: « 0 »,
- « global_status »: « Close »,
- « parent_id »: « »,
- « deleted »: « 0 »
- }
- ]
- }
- }
-```
+````php
+namespace App\Solutions;
-### Function statistics
+use Automattic\WooCommerce\Client;
-Use the statistics function to get the statistics from Myddleware.
+class woocommercecore extends solution
+{
-Here are [CURL info]() :
+...
-```
- curl --location --request POST 'http://localhost/myddleware/web/api/v1_0/statistics'
- No input parameter.
-```
+ /**
+ * @param $param
+ *
+ * @return mixed
+ */
+ public function createData($param)
+ {
+ return $this->upsert('create', $param);
+ }
-**Output :**
+ /**
+ * @param $param
+ *
+ * @return mixed
+ */
+ public function updateData($param)
+ {
+ return $this->upsert('update', $param);
+ }
-```php
- {
- « errorByRule »: [
- {
- « name »: « Product category »,
- « id »: « 5e5d3f8f570cb »,
- « cpt »: « 37 »
- },
- {
- « name »: « Enrolment »,
- « id »: « 5a7dfcfaea8ee »,
- « cpt »: « 9 »
- },
- {
- « name »: « Activity completion source »,
- « id »: « 5c7892bd02e90 »,
- « cpt »: « 6 »
- },
- {
- « name »: « Product Moodle to PS »,
- « id »: « 5e5cc8984ba84 »,
- « cpt »: « 3 »
- },
- {
- « name »: « Order datail »,
- « id »: « 5d63b4532292b »,
- « cpt »: « 2 »
- },
- {
- « name »: « employee »,
- « id »: « 5e611b50c0a6f »,
- « cpt »: « 1 »
- },
- {
- « name »: « Emails »,
- « id »: « 5ba1ba8c7c82f »,
- « cpt »: « 1 »
- },
- {
- « name »: « Customers »,
- « id »: « 5d63d65dba522 »,
- « cpt »: « 1 »
- },
- {
- « name »: « Orders »,
- « id »: « 5d6010d1164fe »,
- « cpt »: « 1 »
- },
- {
- « name »: « Shipping address »,
- « id »: « 5d63d4279a52a »,
- « cpt »: « 1 »
- },
- {
- « name »: « Billing address »,
- « id »: « 5d63d54bc8310 »,
- « cpt »: « 1 »
- },
- {
- « name »: « Product Moodle get Stock id »,
- « id »: « 5e71ec0cd4a41 »,
- « cpt »: « 1 »
- }
- ],
- « countTypeDoc »: [
- {
- « nb »: « 1074 »,
- « global_status »: « Cancel »
- },
- {
- « nb »: « 1056 »,
- « global_status »: « Close »
- },
- {
- « nb »: « 44 »,
- « global_status »: « Open »
- },
- {
- « nb »: « 22 »,
- « global_status »: « Error »
- }
- ],
- « listJobDetail »: [
- {
- « id »: « 5e78e7a7621400.01014726 »,
- « begin »: « 2020-03-23 16:45:27 »,
- « end »: « 2020-03-23 16:45:27 »,
- « status »: « End »,
- « message »: « »,
- « duration »: « 0 »
- },
- {
- « id »: « 5e78e7981dcdf7.88565484 »,
- « begin »: « 2020-03-23 16:45:12 »,
- « end »: « 2020-03-23 16:45:12 »,
- « status »: « End »,
- « message »: « »,
- « duration »: « 0 »
- },
- {
- « id »: « 5e78e791ed9662.98391952 »,
- « begin »: « 2020-03-23 16:45:05 »,
- « end »: « 2020-03-23 16:45:06 »,
- « status »: « End »,
- « message »: « »,
- « duration »: « 1 »
- },
- {
- « id »: « 5e78e78d169314.78840502 »,
- « begin »: « 2020-03-23 16:45:01 »,
- « end »: « 2020-03-23 16:45:01 »,
- « status »: « End »,
- « message »: « »,
- « duration »: « 0 »
- },
- {
- « id »: « 5e78e786166de0.64116198 »,
- « begin »: « 2020-03-23 16:44:54 »,
- « end »: « 2020-03-23 16:44:54 »,
- « status »: « End »,
- « message »: « »,
- « duration »: « 0 »
+ public function upsert($method, $param)
+ {
+ foreach ($param['data'] as $idDoc => $data) {
+ try {
+ $result = [];
+ $param['method'] = $method;
+ $module = $param['module'];
+ $data = $this->checkDataBeforeCreate($param, $data, $idDoc);
+
+ if ('create' === $method) {
+ unset($data['target_id']);
+ $recordResult = $this->woocommerce->post($module, $data);
+ } else {
+ $targetId = $data['target_id'];
+ unset($data['target_id']);
+ $recordResult = $this->woocommerce->put($module.'/'.$targetId, $data);
}
- ],
- « countTransferHisto »: {
- « 2020-03-17 »: {
- « date »: « Mar-17 »,
- « open »: 0,
- « error »: 0,
- « cancel »: 0,
- « close »: 0
- },
- « 2020-03-18 »: {
- « date »: « Mar-18 »,
- « open »: 0,
- « error »: « 1 »,
- « cancel »: « 16 »,
- « close »: « 28 »
- },
- « 2020-03-19 »: {
- « date »: « Mar-19 »,
- « open »: 0,
- « error »: 0,
- « cancel »: « 1 »,
- « close »: « 1 »
- },
- « 2020-03-20 »: {
- « date »: « Mar-20 »,
- « open »: 0,
- « error »: 0,
- « cancel »: « 1 »,
- « close »: « 1 »
- },
- « 2020-03-21 »: {
- « date »: « Mar-21 »,
- « open »: 0,
- « error »: 0,
- « cancel »: 0,
- « close »: 0
- },
- « 2020-03-22 »: {
- « date »: « Mar-22 »,
- « open »: 0,
- « error »: 0,
- « cancel »: 0,
- « close »: 0
- },
- « 2020-03-23 »: {
- « date »: « Mar-23 »,
- « open »: 0,
- « error »: « 10 »,
- « cancel »: « 6 »,
- « close »: 0
+
+ $response = $recordResult;
+ if ($response) {
+ $record = $response;
+ if (!empty($record->id)) {
+ $result[$idDoc] = [
+ 'id' => $record->id,
+ 'error' => false,
+ ];
+ } else {
+ throw new \Exception('Error during '.print_r($response));
+ }
}
+ } catch (\Exception $e) {
+ $error = $e->getMessage();
+ $result[$idDoc] = [
+ 'id' => '-1',
+ 'error' => $error,
+ ];
+ }
+ // Modification du statut du flux
+ $this->updateDocumentStatus($idDoc, $result[$idDoc], $param);
}
- }
- ```
+ return $result;
+ }
+ }
+````
## Ensuring your custom code is upgrade-safe in Myddleware
diff --git a/docs/images/basic_usage/document/document_tweak_data_transfer_error.png b/docs/images/basic_usage/document/document_tweak_data_transfer_error.png
new file mode 100644
index 000000000..d10f8103a
Binary files /dev/null and b/docs/images/basic_usage/document/document_tweak_data_transfer_error.png differ
diff --git a/docs/images/basic_usage/document/documents_list_cancel_rerun_documents_in_error_buttons.png b/docs/images/basic_usage/document/documents_list_cancel_rerun_documents_in_error_buttons.png
new file mode 100644
index 000000000..36ada5146
Binary files /dev/null and b/docs/images/basic_usage/document/documents_list_cancel_rerun_documents_in_error_buttons.png differ
diff --git a/docs/images/credentials/airtable_api_key.png b/docs/images/credentials/airtable_api_key.png
new file mode 100644
index 000000000..b1fee8d24
Binary files /dev/null and b/docs/images/credentials/airtable_api_key.png differ
diff --git a/docs/images/credentials/airtable_app_id_api_doc.png b/docs/images/credentials/airtable_app_id_api_doc.png
new file mode 100644
index 000000000..b88f98f30
Binary files /dev/null and b/docs/images/credentials/airtable_app_id_api_doc.png differ
diff --git a/docs/images/credentials/airtable_app_id_url.png b/docs/images/credentials/airtable_app_id_url.png
new file mode 100644
index 000000000..c0464604b
Binary files /dev/null and b/docs/images/credentials/airtable_app_id_url.png differ
diff --git a/docs/images/credentials/airtable_connector_credentials.png b/docs/images/credentials/airtable_connector_credentials.png
new file mode 100644
index 000000000..bcbd42280
Binary files /dev/null and b/docs/images/credentials/airtable_connector_credentials.png differ
diff --git a/docs/images/credentials/airtable_help_menu.png b/docs/images/credentials/airtable_help_menu.png
new file mode 100644
index 000000000..60ea4776c
Binary files /dev/null and b/docs/images/credentials/airtable_help_menu.png differ
diff --git a/docs/images/credentials/erpnext_connector_credentials.png b/docs/images/credentials/erpnext_connector_credentials.png
new file mode 100644
index 000000000..08bfb0cea
Binary files /dev/null and b/docs/images/credentials/erpnext_connector_credentials.png differ
diff --git a/docs/images/credentials/hubspot_connector_credentials.png b/docs/images/credentials/hubspot_connector_credentials.png
new file mode 100644
index 000000000..3babbd4b4
Binary files /dev/null and b/docs/images/credentials/hubspot_connector_credentials.png differ
diff --git a/docs/images/credentials/magento_connector_credentials.png b/docs/images/credentials/magento_connector_credentials.png
new file mode 100644
index 000000000..eb7e3fead
Binary files /dev/null and b/docs/images/credentials/magento_connector_credentials.png differ
diff --git a/docs/images/credentials/microsoftsql_connector_credentials.png b/docs/images/credentials/microsoftsql_connector_credentials.png
new file mode 100644
index 000000000..3b501e14f
Binary files /dev/null and b/docs/images/credentials/microsoftsql_connector_credentials.png differ
diff --git a/docs/images/credentials/moodle_connector_credentials.png b/docs/images/credentials/moodle_connector_credentials.png
new file mode 100644
index 000000000..fa0039797
Binary files /dev/null and b/docs/images/credentials/moodle_connector_credentials.png differ
diff --git a/docs/images/credentials/mysql_connector_credentials.png b/docs/images/credentials/mysql_connector_credentials.png
new file mode 100644
index 000000000..d27bc9bd9
Binary files /dev/null and b/docs/images/credentials/mysql_connector_credentials.png differ
diff --git a/docs/images/credentials/oracle_connector_credentials.png b/docs/images/credentials/oracle_connector_credentials.png
new file mode 100644
index 000000000..964d793dc
Binary files /dev/null and b/docs/images/credentials/oracle_connector_credentials.png differ
diff --git a/docs/images/credentials/postgresql_connector_credentials.png b/docs/images/credentials/postgresql_connector_credentials.png
new file mode 100644
index 000000000..0378b5a53
Binary files /dev/null and b/docs/images/credentials/postgresql_connector_credentials.png differ
diff --git a/docs/images/credentials/prestashop_connector_credentials.png b/docs/images/credentials/prestashop_connector_credentials.png
new file mode 100644
index 000000000..8e1fda618
Binary files /dev/null and b/docs/images/credentials/prestashop_connector_credentials.png differ
diff --git a/docs/images/credentials/salesforce_access_token_nav.png b/docs/images/credentials/salesforce_access_token_nav.png
new file mode 100644
index 000000000..4f2318f29
Binary files /dev/null and b/docs/images/credentials/salesforce_access_token_nav.png differ
diff --git a/docs/images/credentials/salesforce_app_detail.png b/docs/images/credentials/salesforce_app_detail.png
new file mode 100644
index 000000000..5c465b063
Binary files /dev/null and b/docs/images/credentials/salesforce_app_detail.png differ
diff --git a/docs/images/credentials/salesforce_connector_credentials.png b/docs/images/credentials/salesforce_connector_credentials.png
new file mode 100644
index 000000000..794d0f46c
Binary files /dev/null and b/docs/images/credentials/salesforce_connector_credentials.png differ
diff --git a/docs/images/credentials/salesforce_consumer_key.png b/docs/images/credentials/salesforce_consumer_key.png
new file mode 100644
index 000000000..b7bd3e765
Binary files /dev/null and b/docs/images/credentials/salesforce_consumer_key.png differ
diff --git a/docs/images/credentials/salesforce_create_app.png b/docs/images/credentials/salesforce_create_app.png
new file mode 100644
index 000000000..80b7fb509
Binary files /dev/null and b/docs/images/credentials/salesforce_create_app.png differ
diff --git a/docs/images/credentials/salesforce_create_connected_app_form.png b/docs/images/credentials/salesforce_create_connected_app_form.png
new file mode 100644
index 000000000..520849408
Binary files /dev/null and b/docs/images/credentials/salesforce_create_connected_app_form.png differ
diff --git a/docs/images/credentials/salesforce_new_connected_app.png b/docs/images/credentials/salesforce_new_connected_app.png
new file mode 100644
index 000000000..6f2a158bb
Binary files /dev/null and b/docs/images/credentials/salesforce_new_connected_app.png differ
diff --git a/docs/images/credentials/sendinblue_api_key.png b/docs/images/credentials/sendinblue_api_key.png
new file mode 100644
index 000000000..f1a699adb
Binary files /dev/null and b/docs/images/credentials/sendinblue_api_key.png differ
diff --git a/docs/images/credentials/sendinblue_connector_credentials.png b/docs/images/credentials/sendinblue_connector_credentials.png
new file mode 100644
index 000000000..a6d91d9cd
Binary files /dev/null and b/docs/images/credentials/sendinblue_connector_credentials.png differ
diff --git a/docs/images/credentials/sugarcrm_connector_credentials.png b/docs/images/credentials/sugarcrm_connector_credentials.png
new file mode 100644
index 000000000..929cc2dc8
Binary files /dev/null and b/docs/images/credentials/sugarcrm_connector_credentials.png differ
diff --git a/docs/images/credentials/suitecrm_connector_credentials.png b/docs/images/credentials/suitecrm_connector_credentials.png
new file mode 100644
index 000000000..617a44f25
Binary files /dev/null and b/docs/images/credentials/suitecrm_connector_credentials.png differ
diff --git a/docs/images/credentials/suitecrm_login_form.png b/docs/images/credentials/suitecrm_login_form.png
new file mode 100644
index 000000000..97060e58d
Binary files /dev/null and b/docs/images/credentials/suitecrm_login_form.png differ
diff --git a/docs/images/credentials/vtiger_access_key.png b/docs/images/credentials/vtiger_access_key.png
new file mode 100644
index 000000000..b65ea0b83
Binary files /dev/null and b/docs/images/credentials/vtiger_access_key.png differ
diff --git a/docs/images/credentials/vtiger_connector_credentials.png b/docs/images/credentials/vtiger_connector_credentials.png
new file mode 100644
index 000000000..94da609ec
Binary files /dev/null and b/docs/images/credentials/vtiger_connector_credentials.png differ
diff --git a/docs/images/credentials/woocommerce_connector_credentials.png b/docs/images/credentials/woocommerce_connector_credentials.png
new file mode 100644
index 000000000..4ba8eec66
Binary files /dev/null and b/docs/images/credentials/woocommerce_connector_credentials.png differ
diff --git a/docs/images/credentials/woocommerce_consumer_key_consumer_secret.png b/docs/images/credentials/woocommerce_consumer_key_consumer_secret.png
new file mode 100644
index 000000000..b4a8d9e3d
Binary files /dev/null and b/docs/images/credentials/woocommerce_consumer_key_consumer_secret.png differ
diff --git a/docs/images/credentials/woocommerce_generate_api_key.png b/docs/images/credentials/woocommerce_generate_api_key.png
new file mode 100644
index 000000000..0cb391b61
Binary files /dev/null and b/docs/images/credentials/woocommerce_generate_api_key.png differ
diff --git a/docs/images/credentials/woocommerce_rest_api_list.png b/docs/images/credentials/woocommerce_rest_api_list.png
new file mode 100644
index 000000000..4f5715200
Binary files /dev/null and b/docs/images/credentials/woocommerce_rest_api_list.png differ
diff --git a/docs/images/credentials/zuora_connector_credentials.png b/docs/images/credentials/zuora_connector_credentials.png
new file mode 100644
index 000000000..3627fa84e
Binary files /dev/null and b/docs/images/credentials/zuora_connector_credentials.png differ
diff --git a/docs/images/dev_guide/connector_method_login_test.png b/docs/images/dev_guide/connector_method_login_test.png
new file mode 100644
index 000000000..fbd595738
Binary files /dev/null and b/docs/images/dev_guide/connector_method_login_test.png differ
diff --git a/docs/images/dev_guide/solutions_table.png b/docs/images/dev_guide/solutions_table.png
new file mode 100644
index 000000000..ff803b0f0
Binary files /dev/null and b/docs/images/dev_guide/solutions_table.png differ
diff --git a/docs/images/dev_guide/tuto_connecteur_method_read_output.png b/docs/images/dev_guide/tuto_connecteur_method_read_output.png
new file mode 100644
index 000000000..dd932a1c4
Binary files /dev/null and b/docs/images/dev_guide/tuto_connecteur_method_read_output.png differ
diff --git a/docs/images/rule_create_woo_vtiger.png b/docs/images/rule_create_woo_vtiger.png
new file mode 100644
index 000000000..536f7ea4a
Binary files /dev/null and b/docs/images/rule_create_woo_vtiger.png differ