From d6b9eb1a8562740adbcb41e1f2d544d8c9daa923 Mon Sep 17 00:00:00 2001 From: Xebax Date: Mon, 13 Jun 2016 14:24:09 +0200 Subject: [PATCH 01/23] REST API: enable the Restler API Explorer. --- htdocs/api/index.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/htdocs/api/index.php b/htdocs/api/index.php index 660c90d3476..fc4f8bb8dfd 100644 --- a/htdocs/api/index.php +++ b/htdocs/api/index.php @@ -58,7 +58,10 @@ if (empty($conf->global->MAIN_MODULE_API)) $api = new DolibarrApi($db); -$api->r->addAPIClass('Luracast\\Restler\\Resources'); //this creates resources.json at API Root +// Enable the Restler API Explorer. +// See https://github.com/Luracast/Restler-API-Explorer for more info. +$api->r->addAPIClass('Luracast\\Restler\\Explorer'); + $api->r->setSupportedFormats('JsonFormat', 'XmlFormat'); $api->r->addAuthenticationClass('DolibarrApiAccess',''); From 396d31e18edf21d036ccfd0c0b157fb8c8d25e81 Mon Sep 17 00:00:00 2001 From: Xebax Date: Mon, 13 Jun 2016 23:24:54 +0200 Subject: [PATCH 02/23] REST API: begin the refactoring. Simplify the code that looks for the API classes and replace the /contact/ and /user/ APIs by /contacts/ and /users/. --- htdocs/api/index.php | 29 ++++++------------- ...ntact.class.php => api_contacts.class.php} | 27 ++++------------- ...api_user.class.php => api_users.class.php} | 25 +++++----------- 3 files changed, 21 insertions(+), 60 deletions(-) rename htdocs/societe/class/{api_contact.class.php => api_contacts.class.php} (91%) rename htdocs/user/class/{api_user.class.php => api_users.class.php} (94%) diff --git a/htdocs/api/index.php b/htdocs/api/index.php index fc4f8bb8dfd..e0abd839b66 100644 --- a/htdocs/api/index.php +++ b/htdocs/api/index.php @@ -65,8 +65,6 @@ $api->r->addAPIClass('Luracast\\Restler\\Explorer'); $api->r->setSupportedFormats('JsonFormat', 'XmlFormat'); $api->r->addAuthenticationClass('DolibarrApiAccess',''); -$listofapis = array(); - $modulesdir = dolGetModulesDirs(); foreach ($modulesdir as $dir) { @@ -80,25 +78,19 @@ foreach ($modulesdir as $dir) { while (($file = readdir($handle))!==false) { - if (is_readable($dir.$file) && preg_match("/^(mod.*)\.class\.php$/i",$file,$reg)) + if (is_readable($dir.$file) && preg_match("/^mod(.*)\.class\.php$/i",$file,$reg)) { - $modulename=$reg[1]; + $module = $part = strtolower($reg[1]); - // Defined if module is enabled - $enabled=true; - $module=$part=$obj=strtolower(preg_replace('/^mod/i','',$modulename)); - //if ($part == 'propale') $part='propal'; - if ($module == 'societe') { - $obj = 'thirdparty'; - } if ($module == 'categorie') { $part = 'categories'; - $obj = 'category'; } if ($module == 'facture') { $part = 'compta/facture'; - $obj = 'facture'; } + + // Defined if module is enabled + $enabled=true; if (empty($conf->$module->enabled)) $enabled=false; if ($enabled) @@ -118,17 +110,14 @@ foreach ($modulesdir as $dir) { while (($file_searched = readdir($handle_part))!==false) { - if (is_readable($dir_part.$file_searched) && preg_match("/^(api_.*)\.class\.php$/i",$file_searched,$reg)) + if (is_readable($dir_part.$file_searched) && preg_match("/^api_(.*)\.class\.php$/i",$file_searched,$reg)) { - $classname=$reg[1]; - $classname = str_replace('Api_','',ucwords($reg[1])).'Api'; - $classname = ucfirst($classname); + $classname = ucwords($reg[1]); require_once $dir_part.$file_searched; - if (class_exists($classname)) + if (class_exists($classname)) { dol_syslog("Found API classname=".$classname); - $api->r->addAPIClass($classname,''); - $listofapis[]=array('classname'=>$classname, 'fullpath'=>$file_searched); + $api->r->addAPIClass($classname); } } } diff --git a/htdocs/societe/class/api_contact.class.php b/htdocs/societe/class/api_contacts.class.php similarity index 91% rename from htdocs/societe/class/api_contact.class.php rename to htdocs/societe/class/api_contacts.class.php index 5144c000b4d..d49be1bd4f1 100644 --- a/htdocs/societe/class/api_contact.class.php +++ b/htdocs/societe/class/api_contacts.class.php @@ -20,14 +20,12 @@ use Luracast\Restler\RestException; //require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php'; /** - * API class for contact object + * API class for contacts * - * @smart-auto-routing false * @access protected * @class DolibarrApiAccess {@requires user,external} - * */ -class ContactApi extends DolibarrApi +class Contacts extends DolibarrApi { /** * @@ -44,9 +42,6 @@ class ContactApi extends DolibarrApi /** * Constructor - * - * @url contact/ - * */ function __construct() { global $db, $conf; @@ -62,7 +57,6 @@ class ContactApi extends DolibarrApi * @param int $id ID of contact * @return array|mixed data without useless information * - * @url GET contact/{id} * @throws RestException */ function get($id) { @@ -96,15 +90,10 @@ class ContactApi extends DolibarrApi * @param int $limit Limit for list * @param int $page Page number * @return array Array of contact objects - * - * @url GET /contact/list - * @url GET /contact/list/{socid} - * @url GET /thirdparty/{socid}/contacts - * @url GET /customer/{socid}/contacts * * @throws RestException */ - function getList($socid = 0, $sortfield = "c.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { + function index($socid = 0, $sortfield = "c.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { global $db, $conf; $obj_ret = array(); @@ -191,8 +180,6 @@ class ContactApi extends DolibarrApi * * @param array $request_data Request datas * @return int ID of contact - * - * @url POST contact/ */ function post($request_data = NULL) { if (!DolibarrApiAccess::$user->rights->societe->contact->creer) @@ -215,8 +202,6 @@ class ContactApi extends DolibarrApi * @param int $id Id of contact to update * @param array $request_data Datas * @return int - * - * @url PUT contact/{id} */ function put($id, $request_data = NULL) { if (!DolibarrApiAccess::$user->rights->societe->contact->creer) @@ -251,11 +236,9 @@ class ContactApi extends DolibarrApi * * @param int $id Contact ID * @return integer - * - * @url DELETE contact/{id} */ function delete($id) { - if (!DolibarrApiAccess::$user->rights->contact->supprimer) + if (!DolibarrApiAccess::$user->rights->societe->contact->supprimer) { throw new RestException(401); } @@ -282,7 +265,7 @@ class ContactApi extends DolibarrApi */ function _validate($data) { $contact = array(); - foreach (ContactApi::$FIELDS as $field) + foreach (Contacts::$FIELDS as $field) { if (!isset($data[$field])) throw new RestException(400, "$field field missing"); diff --git a/htdocs/user/class/api_user.class.php b/htdocs/user/class/api_users.class.php similarity index 94% rename from htdocs/user/class/api_user.class.php rename to htdocs/user/class/api_users.class.php index e89a5faac0b..7b2396434de 100644 --- a/htdocs/user/class/api_user.class.php +++ b/htdocs/user/class/api_users.class.php @@ -20,14 +20,12 @@ use Luracast\Restler\RestException; //require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php'; /** - * API class for user object + * API class for users * - * @smart-auto-routing false * @access protected * @class DolibarrApiAccess {@requires user,external} - * */ -class UserApi extends DolibarrApi +class Users extends DolibarrApi { /** * @@ -44,9 +42,6 @@ class UserApi extends DolibarrApi /** * Constructor - * - * @url user/ - * */ function __construct() { global $db, $conf; @@ -62,7 +57,6 @@ class UserApi extends DolibarrApi * @param int $id ID of user * @return array|mixed data without useless information * - * @url GET user/{id} * @throws RestException */ function get($id) { @@ -85,6 +79,7 @@ class UserApi extends DolibarrApi } /** + * TODO move to the /contacts/ API * Create useraccount object from contact * * @param int $contactid Id of contact @@ -133,8 +128,6 @@ class UserApi extends DolibarrApi * * @param array $request_data New user data * @return int - * - * @url POST user/ */ function post($request_data = NULL) { // check user authorization @@ -170,8 +163,6 @@ class UserApi extends DolibarrApi * @param int $id Id of account to update * @param array $request_data Datas * @return int - * - * @url PUT user/{id} */ function put($id, $request_data = NULL) { //if (!DolibarrApiAccess::$user->rights->user->user->creer) { @@ -194,7 +185,7 @@ class UserApi extends DolibarrApi $this->useraccount->$field = $value; } - if ($this->useraccount->update($id, DolibarrApiAccess::$user, 1, '', '', 'update')) + if ($this->useraccount->update(DolibarrApiAccess::$user, 1)) return $this->get($id); return false; @@ -207,9 +198,9 @@ class UserApi extends DolibarrApi * @param int $group Group ID * @return int * - * @url GET user/{id}/setGroup/{group} + * @url GET {id}/setGroup/{group} */ - function setGroup($id,$group) { + function setGroup($id, $group) { //if (!DolibarrApiAccess::$user->rights->user->user->supprimer) { //throw new RestException(401); //} @@ -232,8 +223,6 @@ class UserApi extends DolibarrApi * * @param int $id Account ID * @return array - * - * @url DELETE user/{id} */ function delete($id) { //if (!DolibarrApiAccess::$user->rights->user->user->supprimer) { @@ -262,7 +251,7 @@ class UserApi extends DolibarrApi */ function _validate($data) { $account = array(); - foreach (UserApi::$FIELDS as $field) + foreach (Users::$FIELDS as $field) { if (!isset($data[$field])) throw new RestException(400, "$field field missing"); From db77efc067a5dd1fa37ebbdd42c48f4afddfbf62 Mon Sep 17 00:00:00 2001 From: Xebax Date: Tue, 14 Jun 2016 18:57:00 +0200 Subject: [PATCH 03/23] REST API: replace the /category/ API by /categories/. Remove several /category/list/xxx endpoints because they are redundant with the /categories/ endpoint whith the 'type' filter. --- ...ory.class.php => api_categories.class.php} | 109 ++---------------- 1 file changed, 11 insertions(+), 98 deletions(-) rename htdocs/categories/class/{api_category.class.php => api_categories.class.php} (79%) diff --git a/htdocs/categories/class/api_category.class.php b/htdocs/categories/class/api_categories.class.php similarity index 79% rename from htdocs/categories/class/api_category.class.php rename to htdocs/categories/class/api_categories.class.php index f5a5b1f037d..7a664718414 100644 --- a/htdocs/categories/class/api_category.class.php +++ b/htdocs/categories/class/api_categories.class.php @@ -21,15 +21,12 @@ require_once DOL_DOCUMENT_ROOT.'/societe/class/client.class.php'; /** - * API class for category object + * API class for categories * - * @smart-auto-routing false * @access protected * @class DolibarrApiAccess {@requires user,external} - * - * */ -class CategoryApi extends DolibarrApi +class Categories extends DolibarrApi { /** * @var array $FIELDS Mandatory fields, checked when create and update object @@ -55,16 +52,12 @@ class CategoryApi extends DolibarrApi /** * Constructor - * - * @url GET category/ - * */ function __construct() { global $db, $conf; $this->db = $db; $this->category = new Categorie($this->db); - } /** @@ -75,7 +68,6 @@ class CategoryApi extends DolibarrApi * @param int $id ID of category * @return array|mixed data without useless information * - * @url GET category/{id} * @throws RestException */ function get($id) @@ -108,9 +100,9 @@ class CategoryApi extends DolibarrApi * @param int $page Page number * @return array Array of category objects * - * @url GET /category/list + * @throws RestException */ - function getList($type='product', $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { + function index($type, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { global $db, $conf; $obj_ret = array(); @@ -122,7 +114,7 @@ class CategoryApi extends DolibarrApi $sql = "SELECT s.rowid"; $sql.= " FROM ".MAIN_DB_PREFIX."categorie as s"; $sql.= ' WHERE s.entity IN ('.getEntity('categorie', 1).')'; - $sql.= ' AND s.type='.array_search($type,CategoryApi::$TYPES); + $sql.= ' AND s.type='.array_search($type,Categories::$TYPES); $nbtotalofrecords = 0; if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) @@ -165,7 +157,9 @@ class CategoryApi extends DolibarrApi } return $obj_ret; } + /** + * TODO move to /members/, /products/ and /contacts/ * List categories of an entity * * Get a list of categories @@ -201,7 +195,7 @@ class CategoryApi extends DolibarrApi $sql.= " FROM ".MAIN_DB_PREFIX."categorie as s"; $sql.= " , ".MAIN_DB_PREFIX."categorie_".$sub_type." as sub "; $sql.= ' WHERE s.entity IN ('.getEntity('categorie', 1).')'; - $sql.= ' AND s.type='.array_search($type,CategoryApi::$TYPES); + $sql.= ' AND s.type='.array_search($type,Categories::$TYPES); $sql.= ' AND s.rowid = sub.fk_categorie'; $sql.= ' AND sub.'.$subcol_name.' = '.$item; @@ -248,36 +242,7 @@ class CategoryApi extends DolibarrApi } /** - * Get member categories list - * - * @param string $sortfield Sort field - * @param string $sortorder Sort order - * @param int $limit Limit for list - * @param int $page Page number - * @return mixed - * - * @url GET /category/list/member - */ - function getListCategoryMember($sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { - return $this->getList('member', $sortfield, $sortorder, $limit, $page); - } - - /** - * Get customer categories list - * - * @param string $sortfield Sort field - * @param string $sortorder Sort order - * @param int $limit Limit for list - * @param int $page Page number - * - * @return mixed - * - * @url GET /category/list/customer - */ - function getListCategoryCustomer($sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { - return $this->getList('customer', $sortfield, $sortorder, $limit, $page); - } - /** + * TODO move to /thirsparties/ or /customers/ * Get categories for a customer * * @param int $cusid Customer id filter @@ -295,6 +260,7 @@ class CategoryApi extends DolibarrApi } /** + * TODO move to /thirsparties/ or /customers/ * Add category to customer * * @param int $cusid Id of customer @@ -328,60 +294,11 @@ class CategoryApi extends DolibarrApi return $customer; } - /** - * Get supplier categories list - * - * @param string $sortfield Sort field - * @param string $sortorder Sort order - * @param int $limit Limit for list - * @param int $page Page number - * - * @return mixed - * - * @url GET /category/list/supplier - */ - function getListCategorySupplier($sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { - return $this->getList('supplier', $sortfield, $sortorder, $limit, $page); - } - - /** - * Get product categories list - * - * @param string $sortfield Sort field - * @param string $sortorder Sort order - * @param int $limit Limit for list - * @param int $page Page number - * - * @return mixed - * - * @url GET /category/list/product - */ - function getListCategoryProduct($sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { - return $this->getList('product', $sortfield, $sortorder, $limit, $page); - } - - /** - * Get contact categories list - * - * @param string $sortfield Sort field - * @param string $sortorder Sort order - * @param int $limit Limit for list - * @param int $page Page number - * @return mixed - * - * @url GET /category/list/contact - */ - function getListCategoryContact($sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { - return $this->getList('contact', $sortfield, $sortorder, $limit, $page); - } - /** * Create category object * * @param array $request_data Request data * @return int ID of category - * - * @url POST category/ */ function post($request_data = NULL) { @@ -406,8 +323,6 @@ class CategoryApi extends DolibarrApi * @param int $id Id of category to update * @param array $request_data Datas * @return int - * - * @url PUT category/{id} */ function put($id, $request_data = NULL) { @@ -439,8 +354,6 @@ class CategoryApi extends DolibarrApi * * @param int $id Category ID * @return array - * - * @url DELETE category/{id} */ function delete($id) { @@ -479,7 +392,7 @@ class CategoryApi extends DolibarrApi function _validate($data) { $category = array(); - foreach (CategoryApi::$FIELDS as $field) { + foreach (Categories::$FIELDS as $field) { if (!isset($data[$field])) throw new RestException(400, "$field field missing"); $category[$field] = $data[$field]; From 8cf0bceadd4b09b6ddfd7088282a0d2d3710045b Mon Sep 17 00:00:00 2001 From: Xebax Date: Tue, 14 Jun 2016 19:55:49 +0200 Subject: [PATCH 04/23] REST API: replace the /invoice/ API by /invoices/. Rename the 'mode' parameter to 'status' in GET /invoices. Fix the error handling in DELETE /invoices/{id}. --- ...voice.class.php => api_invoices.class.php} | 42 ++++++------------- 1 file changed, 13 insertions(+), 29 deletions(-) rename htdocs/compta/facture/class/{api_invoice.class.php => api_invoices.class.php} (89%) diff --git a/htdocs/compta/facture/class/api_invoice.class.php b/htdocs/compta/facture/class/api_invoices.class.php similarity index 89% rename from htdocs/compta/facture/class/api_invoice.class.php rename to htdocs/compta/facture/class/api_invoices.class.php index 60098a38b9f..8fc6274b1a6 100644 --- a/htdocs/compta/facture/class/api_invoice.class.php +++ b/htdocs/compta/facture/class/api_invoices.class.php @@ -20,14 +20,12 @@ require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; /** - * API class for invoice object + * API class for invoices * - * @smart-auto-routing false * @access protected * @class DolibarrApiAccess {@requires user,external} - * */ -class InvoiceApi extends DolibarrApi +class Invoices extends DolibarrApi { /** * @@ -44,9 +42,6 @@ class InvoiceApi extends DolibarrApi /** * Constructor - * - * @url GET invoice/ - * */ function __construct() { @@ -63,7 +58,6 @@ class InvoiceApi extends DolibarrApi * @param int $id ID of invoice * @return array|mixed data without useless information * - * @url GET invoice/{id} * @throws RestException */ function get($id) @@ -89,21 +83,18 @@ class InvoiceApi extends DolibarrApi * * Get a list of invoices * + * FIXME this parameter is overwritten in the code and thus ignored * @param int $socid Filter list with thirdparty ID - * @param string $mode Filter by invoice status : draft | unpaid | paid | cancelled + * @param string $status Filter by invoice status : draft | unpaid | paid | cancelled * @param string $sortfield Sort field * @param string $sortorder Sort order * @param int $limit Limit for list * @param int $page Page number - * * @return array Array of invoice objects * - * @url GET invoice/list - * @url GET invoice/list/{mode} - * @url GET thirdparty/{socid}/invoice/list - * @url GET thirdparty/{socid}/invoice/list/{mode} + * @throws RestException */ - function getList($socid=0, $mode='', $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { + function index($socid=0, $status='', $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { global $db, $conf; $obj_ret = array(); @@ -125,11 +116,11 @@ class InvoiceApi extends DolibarrApi if ($search_sale > 0) $sql.= " AND s.rowid = sc.fk_soc"; // Join for the needed table to filter by sale - // Example of use $mode - if ($mode == 'draft') $sql.= " AND s.fk_statut IN (0)"; - if ($mode == 'unpaid') $sql.= " AND s.fk_statut IN (1)"; - if ($mode == 'paid') $sql.= " AND s.fk_statut IN (2)"; - if ($mode == 'cancelled') $sql.= " AND s.fk_statut IN (3)"; + // Filter by status + if ($status == 'draft') $sql.= " AND s.fk_statut IN (0)"; + if ($status == 'unpaid') $sql.= " AND s.fk_statut IN (1)"; + if ($status == 'paid') $sql.= " AND s.fk_statut IN (2)"; + if ($status == 'cancelled') $sql.= " AND s.fk_statut IN (3)"; // Insert sale filter if ($search_sale > 0) @@ -183,8 +174,6 @@ class InvoiceApi extends DolibarrApi * * @param array $request_data Request datas * @return int ID of invoice - * - * @url POST invoice/ */ function post($request_data = NULL) { @@ -212,8 +201,6 @@ class InvoiceApi extends DolibarrApi * @param int $id Id of invoice to update * @param array $request_data Datas * @return int - * - * @url PUT invoice/{id} */ function put($id, $request_data = NULL) { @@ -245,8 +232,6 @@ class InvoiceApi extends DolibarrApi * * @param int $id Invoice ID * @return type - * - * @url DELETE invoice/{id} */ function delete($id) { @@ -262,7 +247,7 @@ class InvoiceApi extends DolibarrApi throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - if( !$this->invoice->delete($id)) + if( $this->invoice->delete($id) < 0) { throw new RestException(500); } @@ -273,7 +258,6 @@ class InvoiceApi extends DolibarrApi 'message' => 'Facture deleted' ) ); - } /** @@ -287,7 +271,7 @@ class InvoiceApi extends DolibarrApi function _validate($data) { $invoice = array(); - foreach (InvoiceApi::$FIELDS as $field) { + foreach (Invoices::$FIELDS as $field) { if (!isset($data[$field])) throw new RestException(400, "$field field missing"); $invoice[$field] = $data[$field]; From f03d6e1bed90639790631d802279ac54bf50fc3b Mon Sep 17 00:00:00 2001 From: Xebax Date: Tue, 14 Jun 2016 21:29:38 +0200 Subject: [PATCH 05/23] REST API: replace the /product/ API by /products/. Added some FIXME: - the put() method does its job but the API returns an error 500 - delete() does not work. --- ...oduct.class.php => api_products.class.php} | 45 +++++++------------ 1 file changed, 16 insertions(+), 29 deletions(-) rename htdocs/product/class/{api_product.class.php => api_products.class.php} (91%) diff --git a/htdocs/product/class/api_product.class.php b/htdocs/product/class/api_products.class.php similarity index 91% rename from htdocs/product/class/api_product.class.php rename to htdocs/product/class/api_products.class.php index 1e485fd6733..b5eb3d6bd87 100644 --- a/htdocs/product/class/api_product.class.php +++ b/htdocs/product/class/api_products.class.php @@ -21,14 +21,12 @@ require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; /** - * API class for product object + * API class for products * - * @smart-auto-routing false * @access protected * @class DolibarrApiAccess {@requires user,external} - * */ -class ProductApi extends DolibarrApi +class Products extends DolibarrApi { /** * @var array $FIELDS Mandatory fields, checked when create and update object @@ -45,9 +43,6 @@ class ProductApi extends DolibarrApi /** * Constructor - * - * @url product/ - * */ function __construct() { @@ -58,24 +53,22 @@ class ProductApi extends DolibarrApi /** * Get properties of a product object - * + * * Return an array with product informations * * @param int $id ID of product - * @param string $ref Product ref - * @param string $ref_ext Product ref ext * @return array|mixed data without useless information * - * @url GET product/{id} * @throws RestException + * TODO implement getting a product by ref or by $ref_ext */ - function get($id='', $ref='', $ref_ext='') + function get($id) { - if(! DolibarrApiAccess::$user->rights->produit->lire) { + if(! DolibarrApiAccess::$user->rights->produit->lire) { throw new RestException(401); } - $result = $this->product->fetch($id,$ref,$ref_ext); + $result = $this->product->fetch($id); if( ! $result ) { throw new RestException(404, 'Product not found'); } @@ -86,7 +79,7 @@ class ProductApi extends DolibarrApi $this->product->load_stock(); - return $this->_cleanObjectDatas($this->product); + return $this->_cleanObjectDatas($this->product); } /** @@ -96,17 +89,15 @@ class ProductApi extends DolibarrApi * * @param int $mode Use this param to filter list (0 for all, 1 for only product, 2 for only service) * @param mixed $to_sell Filter products to sell (1) or not to sell (0) - * @param mixed $to_buy Filter products to nuy (1) or not to buy (0) + * @param mixed $to_buy Filter products to buy (1) or not to buy (0) * @param string $sortfield Sort field * @param string $sortorder Sort order * @param int $limit Limit for list * @param int $page Page number * * @return array Array of product objects - * - * @url GET /product/list */ - function getList($mode=0, $to_sell='', $to_buy='', $sortfield = "p.ref", $sortorder = 'ASC', $limit = 0, $page = 0) { + function index($mode=0, $to_sell='', $to_buy='', $sortfield = "p.ref", $sortorder = 'ASC', $limit = 0, $page = 0) { global $db, $conf; $obj_ret = array(); @@ -169,6 +160,7 @@ class ProductApi extends DolibarrApi /** + * TODO implement this as a filter in /products/ * List products in a category * * Get a list of products @@ -257,8 +249,6 @@ class ProductApi extends DolibarrApi * * @param array $request_data Request data * @return int ID of product - * - * @url POST product/ */ function post($request_data = NULL) { @@ -277,7 +267,6 @@ class ProductApi extends DolibarrApi } return $this->product->id; - } /** @@ -286,8 +275,7 @@ class ProductApi extends DolibarrApi * @param int $id Id of product to update * @param array $request_data Datas * @return int - * - * @url PUT product/{id} + * FIXME The product is correctluy updated but the API returns an error 500. */ function put($id, $request_data = NULL) { @@ -308,7 +296,7 @@ class ProductApi extends DolibarrApi $this->product->$field = $value; } - if($this->product->update($id, DolibarrApiAccess::$user,1,'','','update')) + if($this->product->update($id, DolibarrApiAccess::$user,1,'update')) return $this->get ($id); return false; @@ -319,12 +307,11 @@ class ProductApi extends DolibarrApi * * @param int $id Product ID * @return array - * - * @url DELETE product/{id} + * FIXME Deleting a product/service does not work because the Product::delete() method uses a global $user but it is not set. */ function delete($id) { - if(! DolibarrApiAccess::$user->rights->product->supprimer) { + if(! DolibarrApiAccess::$user->rights->produit->supprimer) { throw new RestException(401); } $result = $this->product->fetch($id); @@ -349,7 +336,7 @@ class ProductApi extends DolibarrApi function _validate($data) { $product = array(); - foreach (ProductApi::$FIELDS as $field) { + foreach (Products::$FIELDS as $field) { if (!isset($data[$field])) throw new RestException(400, "$field field missing"); $product[$field] = $data[$field]; From 571f6b8a26fae4924c3f83dd6bd25ce05d671004 Mon Sep 17 00:00:00 2001 From: Xebax Date: Wed, 15 Jun 2016 00:52:09 +0200 Subject: [PATCH 06/23] REST API: replace the /order/ API by /orders/. Remove the /thirdparty/{socid}/order/list endpoint because it is redundant with the /orders/ endpoint whith the 'societe' filter. --- ...ommande.class.php => api_orders.class.php} | 71 ++++--------------- 1 file changed, 15 insertions(+), 56 deletions(-) rename htdocs/commande/class/{api_commande.class.php => api_orders.class.php} (90%) diff --git a/htdocs/commande/class/api_commande.class.php b/htdocs/commande/class/api_orders.class.php similarity index 90% rename from htdocs/commande/class/api_commande.class.php rename to htdocs/commande/class/api_orders.class.php index d6a2a3d0f82..fbbad50bd93 100644 --- a/htdocs/commande/class/api_commande.class.php +++ b/htdocs/commande/class/api_orders.class.php @@ -20,18 +20,12 @@ require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; /** - * API class for commande object + * API class for orders * - * @smart-auto-routing false * @access protected * @class DolibarrApiAccess {@requires user,external} - * - * @category Api - * @package Api - * - * */ -class CommandeApi extends DolibarrApi +class Orders extends DolibarrApi { /** @@ -48,9 +42,6 @@ class CommandeApi extends DolibarrApi /** * Constructor - * - * @url GET order/ - * */ function __construct() { @@ -65,15 +56,11 @@ class CommandeApi extends DolibarrApi * Return an array with commande informations * * @param int $id ID of order - * @param string $ref Ref of object - * @param string $ref_ext External reference of object - * @param string $ref_int Internal reference of other object * @return array|mixed data without useless information * - * @url GET order/{id} * @throws RestException */ - function get($id='',$ref='', $ref_ext='', $ref_int='') + function get($id) { if(! DolibarrApiAccess::$user->rights->commande->lire) { throw new RestException(401); @@ -97,17 +84,15 @@ class CommandeApi extends DolibarrApi * * Get a list of orders * - * @param int $mode Use this param to filter list * @param string $sortfield Sort field * @param string $sortorder Sort order * @param int $limit Limit for list * @param int $page Page number * @param string $societe Societe filter field * - * @url GET /order/list * @return array Array of order objects */ - function getList($mode=0, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0, $societe = 0) { + function index($sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0, $societe = 0) { global $db, $conf; $obj_ret = array(); @@ -122,10 +107,6 @@ class CommandeApi extends DolibarrApi $sql.= " FROM ".MAIN_DB_PREFIX."commande as s"; if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale - - // Example of use $mode - //if ($mode == 1) $sql.= " AND s.client IN (1, 3)"; - //if ($mode == 2) $sql.= " AND s.client IN (2, 3)"; $sql.= ' WHERE s.entity IN ('.getEntity('commande', 1).')'; if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= " AND s.fk_soc = sc.fk_soc"; @@ -180,29 +161,10 @@ class CommandeApi extends DolibarrApi return $obj_ret; } - /** - * List orders for specific thirdparty - * - * Get a list of orders - * - * @param int $socid Id of customer - * - * @url GET /customer/{socid}/order/list - * @url GET /thirdparty/{socid}/order/list - * @return array Array of order objects - */ - function getListForSoc($socid = 0) { - return getList(0,"s.rowid","ASC",0,0,$socid); - } - - /** * Create order object * - * @param array $request_data Request datas - * - * @url POST order/ - * + * @param array $request_data Request data * @return int ID of commande */ function post($request_data = NULL) @@ -229,13 +191,13 @@ class CommandeApi extends DolibarrApi return $this->commande->id; } + /** * Get lines of an order * - * * @param int $id Id of order * - * @url GET order/{id}/line/list + * @url GET {id}/lines * * @return int */ @@ -259,14 +221,14 @@ class CommandeApi extends DolibarrApi } return $result; } + /** * Add a line to given order * - * * @param int $id Id of commande to update * @param array $request_data Orderline data * - * @url POST order/{id}/line + * @url POST {id}/lines * * @return int */ @@ -318,15 +280,15 @@ class CommandeApi extends DolibarrApi } return false; } + /** * Update a line to given order * - * * @param int $id Id of commande to update * @param int $lineid Id of line to update * @param array $request_data Orderline data * - * @url PUT order/{id}/line/{lineid} + * @url PUT {id}/lines/{lineid} * * @return object */ @@ -375,6 +337,7 @@ class CommandeApi extends DolibarrApi } return false; } + /** * Delete a line to given order * @@ -382,7 +345,7 @@ class CommandeApi extends DolibarrApi * @param int $id Id of commande to update * @param int $lineid Id of line to delete * - * @url DELETE order/{id}/line/{lineid} + * @url DELETE {id}/lines/{lineid} * * @return int */ @@ -413,8 +376,6 @@ class CommandeApi extends DolibarrApi * @param int $id Id of commande to update * @param array $request_data Datas * - * @url PUT order/{id} - * * @return int */ function put($id, $request_data = NULL) { @@ -445,8 +406,6 @@ class CommandeApi extends DolibarrApi * * @param int $id Order ID * - * @url DELETE order/{id} - * * @return array */ function delete($id) @@ -486,7 +445,7 @@ class CommandeApi extends DolibarrApi * @url POST order/{id}/validate * * @return array - * + * TODO keep only one of the two verbs above (and fix the URL: {id}/validate) */ function validOrder($id, $idwarehouse=0) { @@ -524,7 +483,7 @@ class CommandeApi extends DolibarrApi function _validate($data) { $commande = array(); - foreach (CommandeApi::$FIELDS as $field) { + foreach (Orders::$FIELDS as $field) { if (!isset($data[$field])) throw new RestException(400, "$field field missing"); $commande[$field] = $data[$field]; From 04778f932e5d7abe57cd585c598764174419dd74 Mon Sep 17 00:00:00 2001 From: Xebax Date: Wed, 15 Jun 2016 17:08:17 +0200 Subject: [PATCH 07/23] REST API: replace the /thirdparty/ API by /thirdparties/. Remove several /thirdparty/list/xxx endpoints because they are redundant with the /thirdparties/ endpoint whith the 'mode' filter. Remove the customer/byemail/{email} endpoint because it is redundant with the /thirdparties/ endpoint whith the 'email' filter. Remove all the /customer/ endpoints because they do the same thing as the corresponding /thirdparty/ endpoints. --- ...y.class.php => api_thirdparties.class.php} | 157 +----------------- 1 file changed, 5 insertions(+), 152 deletions(-) rename htdocs/societe/class/{api_thirdparty.class.php => api_thirdparties.class.php} (67%) diff --git a/htdocs/societe/class/api_thirdparty.class.php b/htdocs/societe/class/api_thirdparties.class.php similarity index 67% rename from htdocs/societe/class/api_thirdparty.class.php rename to htdocs/societe/class/api_thirdparties.class.php index 507d95639e6..cb898991f7b 100644 --- a/htdocs/societe/class/api_thirdparty.class.php +++ b/htdocs/societe/class/api_thirdparties.class.php @@ -19,14 +19,12 @@ /** - * API class for thirdparty object + * API class for thirdparties * - * @smart-auto-routing false * @access protected * @class DolibarrApiAccess {@requires user,external} - * */ -class ThirdpartyApi extends DolibarrApi +class Thirdparties extends DolibarrApi { /** * @@ -40,76 +38,21 @@ class ThirdpartyApi extends DolibarrApi * @var Societe $company {@type Societe} */ public $company; - /** - * @var Customer $customer {@type Client} - */ - public $customer; /** * Constructor - * - * @url thirdparty/ - * */ function __construct() { global $db, $conf; $this->db = $db; $this->company = new Societe($this->db); - $this->customer = new Client($this->db); if (! empty($conf->global->SOCIETE_MAIL_REQUIRED)) { static::$FIELDS[] = 'email'; } } - /** - * Get properties of a customer object - * - * Return an array with customer informations - * - * @param int $id ID of customer - * @return array|mixed data without useless information - * - * @url GET customer/{id} - * @throws RestException - */ - function getCustomer($id) - { - if(! DolibarrApiAccess::$user->rights->societe->lire) { - throw new RestException(401); - } - - $result = $this->customer->fetch($id); - if( ! $result ) { - throw new RestException(404, 'Customer not found'); - } - - if( ! DolibarrApi::_checkAccessToResource('societe',$this->customer->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); - } - - return $this->_cleanObjectDatas($this->customer); - } - - /** - * Search customer by email - * - * @param string $email email id - * - * @return object client with given email - * - * @url GET customer/byemail/{email} - */ - function getByEmail($email) { - $res = $this->getList(1,$email); - if (count($res) == 1) { - $customer = $res[0]; - return $customer; - } - return $res; - } - /** * Get properties of a thirdparty object * @@ -118,7 +61,6 @@ class ThirdpartyApi extends DolibarrApi * @param int $id ID of thirdparty * @return array|mixed data without useless information * - * @url GET thirdparty/{id} * @throws RestException */ function get($id) @@ -147,17 +89,14 @@ class ThirdpartyApi extends DolibarrApi * @param int $mode Set to 1 to show only customers * Set to 2 to show only prospects * Set to 3 to show only those are not customer neither prospect - * @param Text $email Search by email filter + * @param string $email Search by email filter * @param string $sortfield Sort field * @param string $sortorder Sort order * @param int $limit Limit for list * @param int $page Page number * @return array Array of thirdparty objects - * - * @url GET /thirdparty/list - * */ - function getList($mode=0, $email=NULL, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { + function index($mode=0, $email=NULL, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { global $db, $conf; $obj_ret = array(); @@ -231,47 +170,11 @@ class ThirdpartyApi extends DolibarrApi return $obj_ret; } - /** - * Show customers - * - * @return array List of customers - * - * @url GET /thirdparty/list/customers - * @url GET /customer/list - */ - function getListCustomers() { - return $this->getList(1); - } - - /** - * Show prospects - * - * @return array List of prospects - * - * @url GET /thirdparty/list/prospects - */ - function getListProspects() { - return $this->getList(2); - } - - /** - * Show other - * - * @return array List of thirpdparties who are not customer neither prospect - * - * @url GET /thirdparty/list/others - */ - function getListOthers() { - return $this->getList(3); - } - /** * Create thirdparty object * * @param array $request_data Request datas * @return int ID of thirdparty - * - * @url POST thirdparty/ */ function post($request_data = NULL) { @@ -287,29 +190,12 @@ class ThirdpartyApi extends DolibarrApi return $this->company->create(DolibarrApiAccess::$user); } - - /** - * Create customer object - * - * @param array $request_data Request datas - * @return int ID of thirdparty - * - * @url POST customer/ - */ - function postCustomer($request_data) { - $this->post($request_data); - $this->company->set_as_client(); - return $this->company->id; - } - /** * Update thirdparty * * @param int $id Id of thirdparty to update * @param array $request_data Datas * @return int - * - * @url PUT thirdparty/{id} */ function put($id, $request_data = NULL) { @@ -335,45 +221,12 @@ class ThirdpartyApi extends DolibarrApi return false; } - /** - * Update customer - * - * @param int $id Id of thirdparty to update - * @param array $request_data Datas - * @return int - * - * @url PUT customer/{id} - */ - function putClient($id, $request_data = NULL) { - if(! DolibarrApiAccess::$user->rights->societe->creer) { - throw new RestException(401); - } - $result = $this->customer->fetch($id); - if( ! $result ) { - throw new RestException(404, 'Customer not found'); - } - if( ! DolibarrApi::_checkAccessToResource('societe',$this->customer->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); - } - - foreach($request_data as $field => $value) { - $this->customer->$field = $value; - } - - if($this->customer->update($id, DolibarrApiAccess::$user,1,'','','update')) - return $this->get ($id); - - return false; - } /** * Delete thirdparty * * @param int $id Thirparty ID * @return integer - * - * @url DELETE thirdparty/{id} - * @url DELETE customer/{id} */ function delete($id) { @@ -401,7 +254,7 @@ class ThirdpartyApi extends DolibarrApi function _validate($data) { $thirdparty = array(); - foreach (ThirdpartyApi::$FIELDS as $field) { + foreach (Thirdparties::$FIELDS as $field) { if (!isset($data[$field])) throw new RestException(400, "$field field missing"); $thirdparty[$field] = $data[$field]; From 5ea526c29e3e2fc023655beea401dfdbe7f45757 Mon Sep 17 00:00:00 2001 From: Xebax Date: Wed, 15 Jun 2016 18:26:31 +0200 Subject: [PATCH 08/23] REST API: update the API to have /login and /status. Replace the GenericApi class by two classes, Login and Status, else the endpoints would be /generic/login and /generic/status. --- ..._generic.class.php => api_login.class.php} | 25 ++---------- htdocs/api/class/api_status.class.php | 39 +++++++++++++++++++ 2 files changed, 42 insertions(+), 22 deletions(-) rename htdocs/api/class/{api_generic.class.php => api_login.class.php} (84%) create mode 100644 htdocs/api/class/api_status.class.php diff --git a/htdocs/api/class/api_generic.class.php b/htdocs/api/class/api_login.class.php similarity index 84% rename from htdocs/api/class/api_generic.class.php rename to htdocs/api/class/api_login.class.php index 9a630a9da47..1fa08b96179 100644 --- a/htdocs/api/class/api_generic.class.php +++ b/htdocs/api/class/api_login.class.php @@ -18,14 +18,11 @@ use Luracast\Restler\RestException; require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php'; -require_once DOL_DOCUMENT_ROOT.'/api/class/api.class.php'; - /** - * API generic (login, status, ...) - * + * API that allows to log in with an user account. */ -class GenericApi extends DolibarrApi +class Login { function __construct() { @@ -46,7 +43,7 @@ class GenericApi extends DolibarrApi * * @throws RestException */ - public function login($login, $password, $entity=0, $reset=0) { + public function index($login, $password, $entity=0, $reset=0) { global $conf, $dolibarr_main_authentication, $dolibarr_auto_user; @@ -103,20 +100,4 @@ class GenericApi extends DolibarrApi ) ); } - - /** - * Get status (Dolibarr version) - * - * @access protected - * @class DolibarrApiAccess {@requires admin} - */ - function status() { - require_once DOL_DOCUMENT_ROOT . '/core/lib/functions.lib.php'; - return array( - 'success' => array( - 'code' => 200, - 'dolibarr_version' => DOL_VERSION - ) - ); - } } diff --git a/htdocs/api/class/api_status.class.php b/htdocs/api/class/api_status.class.php new file mode 100644 index 00000000000..a4df6dbba7c --- /dev/null +++ b/htdocs/api/class/api_status.class.php @@ -0,0 +1,39 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +require_once DOL_DOCUMENT_ROOT . '/core/lib/functions.lib.php'; + +/** + * API that gives the status of the Dolibarr instance. + * + * @access protected + * @class DolibarrApiAccess {@requires user,external} + */ +class Status +{ + /** + * Get status (Dolibarr version) + */ + function index() { + return array( + 'success' => array( + 'code' => 200, + 'dolibarr_version' => DOL_VERSION + ) + ); + } +} From f6eac2b643cb92d0aebccb0def8fd95555510afd Mon Sep 17 00:00:00 2001 From: Xebax Date: Mon, 20 Jun 2016 15:55:46 +0200 Subject: [PATCH 09/23] REST API: replace the home made API explorer by the Restler API Explorer. --- htdocs/api/admin/explorer.php | 197 ---------------------------------- htdocs/api/admin/index.php | 16 ++- 2 files changed, 15 insertions(+), 198 deletions(-) delete mode 100644 htdocs/api/admin/explorer.php diff --git a/htdocs/api/admin/explorer.php b/htdocs/api/admin/explorer.php deleted file mode 100644 index 53ff102e89b..00000000000 --- a/htdocs/api/admin/explorer.php +++ /dev/null @@ -1,197 +0,0 @@ - - * Copyright (C) 2016 Laurent Destailleur - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * \defgroup api Module DolibarrApi - * \brief API loader - * Search files htdocs//class/api_.class.php - * \file htdocs/api/admin/explorer.php - */ - -require_once '../../main.inc.php'; -require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php'; -require_once DOL_DOCUMENT_ROOT.'/api/class/api.class.php'; -require_once DOL_DOCUMENT_ROOT.'/api/class/api_access.class.php'; - - -/* - * View - */ - -// Enable and test if module Api is enabled -if (empty($conf->global->MAIN_MODULE_API)) -{ - $langs->load("admin"); - dol_syslog("Call Dolibarr API interfaces with module REST disabled"); - print $langs->trans("WarningModuleNotActive",'Api').'.

'; - print $langs->trans("ToActivateModule"); - exit; -} - - -$api = new DolibarrApi($db); - -$api->r->addAPIClass('Luracast\\Restler\\Resources'); //this creates resources.json at API Root -$api->r->setSupportedFormats('JsonFormat', 'XmlFormat'); -$api->r->addAuthenticationClass('DolibarrApiAccess',''); - -$listofapis = array(); - -$modulesdir = dolGetModulesDirs(); -foreach ($modulesdir as $dir) -{ - /* - * Search available module - */ - dol_syslog("Scan directory ".$dir." for API modules"); - - $handle=@opendir(dol_osencode($dir)); - if (is_resource($handle)) - { - while (($file = readdir($handle))!==false) - { - if (is_readable($dir.$file) && preg_match("/^(mod.*)\.class\.php$/i",$file,$reg)) - { - $modulename=$reg[1]; - - // Defined if module is enabled - $enabled=true; - $module=$part=$obj=strtolower(preg_replace('/^mod/i','',$modulename)); - //if ($part == 'propale') $part='propal'; - if ($module == 'societe') { - $obj = 'thirdparty'; - } - if ($module == 'categorie') { - $part = 'categories'; - $obj = 'category'; - } - if ($module == 'facture') { - $part = 'compta/facture'; - $obj = 'facture'; - } - if (empty($conf->$module->enabled)) $enabled=false; - - if ($enabled) - { - /* - * If exists, load the API class for enable module - * - * Search files named api_.class.php into /htdocs//class directory - * - * @todo : take care of externals module! - * @todo : use getElementProperties() function ? - */ - $dir_part = DOL_DOCUMENT_ROOT.'/'.$part.'/class/'; - - $handle_part=@opendir(dol_osencode($dir_part)); - if (is_resource($handle_part)) - { - while (($file_searched = readdir($handle_part))!==false) - { - if (is_readable($dir_part.$file_searched) && preg_match("/^(api_.*)\.class\.php$/i",$file_searched,$reg)) - { - $classname=$reg[1]; - $classname = str_replace('Api_','',ucwords($reg[1])).'Api'; - $classname = ucfirst($classname); - require_once $dir_part.$file_searched; - if (class_exists($classname)) - { - dol_syslog("Found API classname=".$classname); - $api->r->addAPIClass($classname,''); - - /* - require_once DOL_DOCUMENT_ROOT.'/includes/restler/framework/Luracast/Restler/Routes.php'; - $tmpclass = new ReflectionClass($classname); - try { - $classMetadata = CommentParser::parse($tmpclass->getDocComment()); - } catch (Exception $e) { - throw new RestException(500, "Error while parsing comments of `$classname` class. " . $e->getMessage()); - }*/ - - //$listofapis[]=array('classname'=>$classname, 'fullpath'=>$file_searched); - } - } - } - } - } - } - } - } -} - - -$listofapis=Routes::toArray(); -//var_dump($listofapis); - - -llxHeader(); - -$linkback=''.$langs->trans("BackToModuleList").''; -print load_fiche_titre($langs->trans("ApiSetup"),$linkback,'title_setup'); - -// Define $urlwithroot -$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root)); -$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file -//$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current - -// Show message -print '
'; -$message=''; -$url=''.$urlwithroot.'/api/index.php/login?login='.urlencode($user->login).'&password=yourpassword[&reset=1]'; -$message.=$langs->trans("UrlToGetKeyToUseAPIs").':
'; -$message.=img_picto('','object_globe.png').' '.$url; -print $message; -print '
'; -print '
'; - -$oldclass=''; - -print $langs->trans("ListOfAvailableAPIs").':
'; -foreach($listofapis['v1'] as $key => $val) -{ - if ($key == 'login') continue; - - if ($key) - { - foreach($val as $method => $val2) - { - $newclass=$val2['className']; - - if (preg_match('/restler/i', $newclass)) continue; - - if ($oldclass != $newclass) - { - print "\n
\n".$langs->trans("Class").': '.$newclass.'
'."\n"; - $oldclass = $newclass; - } - //print $key.' - '.$val['classname'].' - '.$val['fullpath']." - ".DOL_MAIN_URL_ROOT.'/api/index.php/'.strtolower(preg_replace('/Api$/','',$val['classname']))."/xxx
\n"; - $url=$urlwithroot.'/api/index.php/'.$key; - $url.='?api_key=token'; - print img_picto('','object_globe.png').' '.$method.' '.$url."
\n"; - } - } -} - -print '
'; -print '
'; -print $langs->trans("OnlyActiveElementsAreExposed", DOL_URL_ROOT.'/admin/modules.php'); - - -llxFooter(); -$db->close(); - diff --git a/htdocs/api/admin/index.php b/htdocs/api/admin/index.php index 3a69dadaaba..08209b03668 100644 --- a/htdocs/api/admin/index.php +++ b/htdocs/api/admin/index.php @@ -95,9 +95,23 @@ print ''; print ''; print '

'; +// Define $urlwithroot +$urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root)); +$urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file +//$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current + +// Show message +$message=''; +$url=''.$urlwithroot.'/api/index.php/login?login='.urlencode($user->login).'&password=yourpassword[&reset=1]'; +$message.=$langs->trans("UrlToGetKeyToUseAPIs").':
'; +$message.=img_picto('','object_globe.png').' '.$url; +print $message; +print '
'; +print '
'; + // Explorer print ''.$langs->trans("ApiExporerIs").':
'; -$url=DOL_MAIN_URL_ROOT.'/api/admin/explorer.php'; +$url=DOL_MAIN_URL_ROOT.'/api/index.php/explorer'; print img_picto('','object_globe.png').' '.$url."
\n"; From 9f526c512dceabf009a7d42e4ee9b96ef549d060 Mon Sep 17 00:00:00 2001 From: Xebax Date: Wed, 15 Jun 2016 22:53:05 +0200 Subject: [PATCH 10/23] REST API: sort the classes before adding them to Restler. The Restler API Explorer shows the classes in the order they are added and it's a mess if they are not sorted. --- htdocs/api/index.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/htdocs/api/index.php b/htdocs/api/index.php index e0abd839b66..e58d2370be7 100644 --- a/htdocs/api/index.php +++ b/htdocs/api/index.php @@ -65,6 +65,8 @@ $api->r->addAPIClass('Luracast\\Restler\\Explorer'); $api->r->setSupportedFormats('JsonFormat', 'XmlFormat'); $api->r->addAuthenticationClass('DolibarrApiAccess',''); +$listofapis = array(); + $modulesdir = dolGetModulesDirs(); foreach ($modulesdir as $dir) { @@ -117,7 +119,7 @@ foreach ($modulesdir as $dir) if (class_exists($classname)) { dol_syslog("Found API classname=".$classname); - $api->r->addAPIClass($classname); + $listofapis[] = $classname; } } } @@ -128,6 +130,14 @@ foreach ($modulesdir as $dir) } } +// Sort the classes before adding them to Restler. The Restler API Explorer +// shows the classes in the order they are added and it's a mess if they are +// not sorted. +sort($listofapis); +foreach ($listofapis as $classname) +{ + $api->r->addAPIClass($classname); +} // TODO If not found, redirect to explorer From 58c25ff665d0eb6f09772b1732433a6b86e57291 Mon Sep 17 00:00:00 2001 From: Xebax Date: Thu, 16 Jun 2016 22:31:34 +0200 Subject: [PATCH 11/23] REST API: fix the error 500 when updating a product. --- htdocs/api/class/api.class.php | 11 +++++++++++ htdocs/product/class/api_products.class.php | 1 - 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/htdocs/api/class/api.class.php b/htdocs/api/class/api.class.php index b3a2cdaf9d0..00621fdeb59 100644 --- a/htdocs/api/class/api.class.php +++ b/htdocs/api/class/api.class.php @@ -88,6 +88,17 @@ class DolibarrApi // Remove $db object property for object unset($object->db); + // Remove the $oldcopy property because it is not supported by the JSON + // encoder. The following error is generated when trying to serialize + // it: "Error encoding/decoding JSON: Type is not supported" + // Note: Event if this property was correctly handled by the JSON + // encoder, it should be ignored because keeping it would let the API + // have a very strange behavior: calling PUT and then GET on the same + // resource would give different results: + // PUT /objects/{id} -> returns object with oldcopy = previous version of the object + // GET /objects/{id} -> returns object with oldcopy empty + unset($object->oldcopy); + // If object has lines, remove $db property if(isset($object->lines) && count($object->lines) > 0) { $nboflines = count($object->lines); diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index b5eb3d6bd87..ce0a812558e 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -275,7 +275,6 @@ class Products extends DolibarrApi * @param int $id Id of product to update * @param array $request_data Datas * @return int - * FIXME The product is correctluy updated but the API returns an error 500. */ function put($id, $request_data = NULL) { From d7c8a466b12c99306a2080cd22d887a36c9f751d Mon Sep 17 00:00:00 2001 From: Xebax Date: Fri, 17 Jun 2016 00:50:07 +0200 Subject: [PATCH 12/23] REST API: fix deleting a product/service. Add a User parameter to the Product::delete() method to explicitly set the user that performs the action instead of using a global variable. In the calls to Product::delete() with a fetched object, remove the deprecated parameter $id. --- htdocs/product/card.php | 2 +- htdocs/product/class/api_products.class.php | 3 +-- htdocs/product/class/product.class.php | 5 +++-- htdocs/webservices/server_productorservice.php | 6 +----- test/phpunit/ProductTest.php | 2 +- 5 files changed, 7 insertions(+), 11 deletions(-) diff --git a/htdocs/product/card.php b/htdocs/product/card.php index 330e712cf1b..c2d7b76dac3 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -553,7 +553,7 @@ if (empty($reshook)) { if (($object->type == Product::TYPE_PRODUCT && $user->rights->produit->supprimer) || ($object->type == Product::TYPE_SERVICE && $user->rights->service->supprimer)) { - $result = $object->delete($object->id); + $result = $object->delete($user); } if ($result > 0) diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index ce0a812558e..c2273c4cf2d 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -306,7 +306,6 @@ class Products extends DolibarrApi * * @param int $id Product ID * @return array - * FIXME Deleting a product/service does not work because the Product::delete() method uses a global $user but it is not set. */ function delete($id) { @@ -322,7 +321,7 @@ class Products extends DolibarrApi throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - return $this->product->delete($id); + return $this->product->delete(DolibarrApiAccess::$user); } /** diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 982b109da99..908ccea68e9 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -878,18 +878,19 @@ class Product extends CommonObject /** * Delete a product from database (if not used) * + * @param User $user Object user that ask to delete * @param int $id Product id (usage of this is deprecated, delete should be called without parameters on a fetched object) * @param int $notrigger Do not execute trigger * @return int < 0 if KO, 0 = Not possible, > 0 if OK */ - function delete($id=0, $notrigger=0) + function delete($user, $id=0, $notrigger=0) { // Deprecation warning if ($id > 0) { dol_syslog(__METHOD__ . " with parameter is deprecated", LOG_WARNING); } - global $conf,$user,$langs; + global $conf,$langs; require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php'; $error=0; diff --git a/htdocs/webservices/server_productorservice.php b/htdocs/webservices/server_productorservice.php index aa43dbb185c..9da26495f76 100644 --- a/htdocs/webservices/server_productorservice.php +++ b/htdocs/webservices/server_productorservice.php @@ -841,10 +841,6 @@ function deleteProductOrService($authentication,$listofidstring) $error=0; $fuser=check_authentication($authentication,$error,$errorcode,$errorlabel); - // User must be defined to user authenticated - global $user; - $user=$fuser; - $listofid=explode(',',trim($listofidstring)); $listofiddeleted=array(); @@ -873,7 +869,7 @@ function deleteProductOrService($authentication,$listofidstring) } else { - $result=$newobject->delete(); + $result=$newobject->delete($fuser); if ($result <= 0) { $error++; diff --git a/test/phpunit/ProductTest.php b/test/phpunit/ProductTest.php index 199aace802c..87f290593f0 100644 --- a/test/phpunit/ProductTest.php +++ b/test/phpunit/ProductTest.php @@ -232,7 +232,7 @@ class ProductTest extends PHPUnit_Framework_TestCase $localobject=new Product($this->savdb); $result=$localobject->fetch($id); - $result=$localobject->delete($id); + $result=$localobject->delete($user); print __METHOD__." id=".$id." result=".$result."\n"; $this->assertLessThan($result, 0); From 6d673035016d138b7f9ede1a95ebc6a884f5a7dc Mon Sep 17 00:00:00 2001 From: Xebax Date: Fri, 17 Jun 2016 14:35:35 +0200 Subject: [PATCH 13/23] REST API: move the definition of /contacts/{id}/createUser from api_users.class.php to api_contacts.class.php. --- htdocs/societe/class/api_contacts.class.php | 44 +++++++++++++++++++++ htdocs/user/class/api_users.class.php | 44 --------------------- 2 files changed, 44 insertions(+), 44 deletions(-) diff --git a/htdocs/societe/class/api_contacts.class.php b/htdocs/societe/class/api_contacts.class.php index d49be1bd4f1..349fa8ecae2 100644 --- a/htdocs/societe/class/api_contacts.class.php +++ b/htdocs/societe/class/api_contacts.class.php @@ -256,6 +256,50 @@ class Contacts extends DolibarrApi return $this->contact->delete($id); } + /** + * Create useraccount object from contact + * + * @param int $id Id of contact + * @param array $request_data Request datas + * @return int ID of user + * + * @url POST {id}/createUser + */ + function createUser($id, $request_data = NULL) { + //if (!DolibarrApiAccess::$user->rights->user->user->creer) { + //throw new RestException(401); + //} + + if (!isset($request_data["login"])) + throw new RestException(400, "login field missing"); + if (!isset($request_data["password"])) + throw new RestException(400, "password field missing"); + if (!DolibarrApiAccess::$user->rights->societe->contact->lire) { + throw new RestException(401); + } + $contact = new Contact($this->db); + $contact->fetch($id); + if ($contact->id <= 0) { + throw new RestException(404, 'Contact not found'); + } + + if (!DolibarrApi::_checkAccessToResource('contact', $contact->id, 'socpeople&societe')) { + throw new RestException(401, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); + } + // Check mandatory fields + $login = $request_data["login"]; + $password = $request_data["password"]; + $useraccount = new User($this->db); + $result = $useraccount->create_from_contact($contact,$login,$password); + if ($result <= 0) { + throw new RestException(500, "User not created"); + } + // password parameter not used in create_from_contact + $useraccount->setPassword($useraccount,$password); + + return $result; + } + /** * Validate fields before create or update object * diff --git a/htdocs/user/class/api_users.class.php b/htdocs/user/class/api_users.class.php index 7b2396434de..a9eb7771d9d 100644 --- a/htdocs/user/class/api_users.class.php +++ b/htdocs/user/class/api_users.class.php @@ -77,50 +77,6 @@ class Users extends DolibarrApi return $this->_cleanObjectDatas($this->useraccount); } - - /** - * TODO move to the /contacts/ API - * Create useraccount object from contact - * - * @param int $contactid Id of contact - * @param array $request_data Request datas - * @return int ID of user - * - * @url POST /contact/{contactid}/createUser - */ - function createFromContact($contactid, $request_data = NULL) { - //if (!DolibarrApiAccess::$user->rights->user->user->creer) { - //throw new RestException(401); - //} - - if (!isset($request_data["login"])) - throw new RestException(400, "login field missing"); - if (!isset($request_data["password"])) - throw new RestException(400, "password field missing"); - if (!DolibarrApiAccess::$user->rights->societe->contact->lire) { - throw new RestException(401); - } - $contact = new Contact($this->db); - $contact->fetch($contactid); - if ($contact->id <= 0) { - throw new RestException(404, 'Contact not found'); - } - - if (!DolibarrApi::_checkAccessToResource('contact', $contact->id, 'socpeople&societe')) { - throw new RestException(401, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); - } - // Check mandatory fields - $login = $request_data["login"]; - $password = $request_data["password"]; - $result = $this->useraccount->create_from_contact($contact,$login,$password); - if ($result <= 0) { - throw new RestException(500, "User not created"); - } - // password parameter not used in create_from_contact - $this->useraccount->setPassword($this->useraccount,$password); - - return $result; - } /** From 9a509dd0ee3f3ec5bbeee4dc806c018381a82ab9 Mon Sep 17 00:00:00 2001 From: Xebax Date: Fri, 17 Jun 2016 15:29:51 +0200 Subject: [PATCH 14/23] REST API: add the 'category' filter in /products/ and fix the 'to_sell' and 'to_buy' filters. --- htdocs/product/class/api_products.class.php | 30 ++++++++++++++------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index c2273c4cf2d..d9ecbe31939 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -88,6 +88,7 @@ class Products extends DolibarrApi * Get a list of products * * @param int $mode Use this param to filter list (0 for all, 1 for only product, 2 for only service) + * @param int $category Use this param to filter list by category * @param mixed $to_sell Filter products to sell (1) or not to sell (0) * @param mixed $to_buy Filter products to buy (1) or not to buy (0) * @param string $sortfield Sort field @@ -97,25 +98,36 @@ class Products extends DolibarrApi * * @return array Array of product objects */ - function index($mode=0, $to_sell='', $to_buy='', $sortfield = "p.ref", $sortorder = 'ASC', $limit = 0, $page = 0) { + function index($mode=0, $category=0, $to_sell='', $to_buy='', $sortfield = "p.ref", $sortorder = 'ASC', $limit = 0, $page = 0) { global $db, $conf; $obj_ret = array(); $socid = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : ''; - $sql ="SELECT rowid, ref, ref_ext"; + $sql = "SELECT rowid, ref, ref_ext"; $sql.= " FROM ".MAIN_DB_PREFIX."product as p"; + if ($category > 0) + { + $sql.= ", ".MAIN_DB_PREFIX."categorie_product as c"; + } $sql.= ' WHERE p.entity IN ('.getEntity('product', 1).')'; - + + // Select products of given category + if ($category > 0) + { + $sql.= " AND c.fk_categorie = ".$db->escape($category); + $sql.= " AND c.fk_product = p.rowid "; + } + // Show products if ($mode == 1) $sql.= " AND p.fk_product_type = 0"; // Show services if ($mode == 2) $sql.= " AND p.fk_product_type = 1"; // Show product on sell - if ($to_sell) $sql.= " AND p.to_sell = ".$db->escape($to_sell); + if ($to_sell !== '') $sql.= " AND p.tosell = ".$db->escape($to_sell); // Show product on buy - if ($to_buy) $sql.= " AND p.to_nuy = ".$db->escape($to_nuy); + if ($to_buy !== '') $sql.= " AND p.tobuy = ".$db->escape($to_buy); $nbtotalofrecords = 0; if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) @@ -155,7 +167,7 @@ class Products extends DolibarrApi if( ! count($obj_ret)) { throw new RestException(404, 'No product found'); } - return $obj_ret; + return $obj_ret; } @@ -168,7 +180,7 @@ class Products extends DolibarrApi * @param int $mode Use this param to filter list (0 for all, 1 for only product, 2 for only service) * @param int $category Use this param to filter list by category * @param mixed $to_sell Filter products to sell (1) or not to sell (0) - * @param mixed $to_buy Filter products to nuy (1) or not to buy (0) + * @param mixed $to_buy Filter products to buy (1) or not to buy (0) * @param string $sortfield Sort field * @param string $sortorder Sort order * @param int $limit Limit for list @@ -193,7 +205,7 @@ class Products extends DolibarrApi // Select products of given category $sql.= " AND c.fk_categorie = ".$db->escape($category); $sql.= " AND c.fk_product = p.rowid "; - + // Show products if ($mode == 1) $sql.= " AND p.fk_product_type = 0"; // Show services @@ -201,7 +213,7 @@ class Products extends DolibarrApi // Show product on sell if ($to_sell) $sql.= " AND p.to_sell = ".$db->escape($to_sell); // Show product on buy - if ($to_buy) $sql.= " AND p.to_nuy = ".$db->escape($to_nuy); + if ($to_buy) $sql.= " AND p.to_buy = ".$db->escape($to_buy); $nbtotalofrecords = 0; if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) From ce6d7046becaad5b4915d192fd9d15565f341ff7 Mon Sep 17 00:00:00 2001 From: Xebax Date: Fri, 17 Jun 2016 15:31:57 +0200 Subject: [PATCH 15/23] REST API: remove getByCategory() from Products because the same feature is available with GET /products/. --- htdocs/product/class/api_products.class.php | 86 --------------------- 1 file changed, 86 deletions(-) diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index d9ecbe31939..e1a8b6824a0 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -169,92 +169,6 @@ class Products extends DolibarrApi } return $obj_ret; } - - - /** - * TODO implement this as a filter in /products/ - * List products in a category - * - * Get a list of products - * - * @param int $mode Use this param to filter list (0 for all, 1 for only product, 2 for only service) - * @param int $category Use this param to filter list by category - * @param mixed $to_sell Filter products to sell (1) or not to sell (0) - * @param mixed $to_buy Filter products to buy (1) or not to buy (0) - * @param string $sortfield Sort field - * @param string $sortorder Sort order - * @param int $limit Limit for list - * @param int $page Page number - * - * @return array Array of product objects - * - * @url GET /product/list/category/{category} - */ - function getByCategory($mode=0, $category=0, $to_sell='', $to_buy='', $sortfield = "p.ref", $sortorder = 'ASC', $limit = 0, $page = 0) { - global $db, $conf; - - $obj_ret = array(); - - $socid = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : ''; - - $sql = "SELECT rowid, ref, ref_ext"; - $sql.= " FROM ".MAIN_DB_PREFIX."product as p, "; - $sql.= MAIN_DB_PREFIX."categorie_product as c"; - $sql.= ' WHERE p.entity IN ('.getEntity('product', 1).')'; - - // Select products of given category - $sql.= " AND c.fk_categorie = ".$db->escape($category); - $sql.= " AND c.fk_product = p.rowid "; - - // Show products - if ($mode == 1) $sql.= " AND p.fk_product_type = 0"; - // Show services - if ($mode == 2) $sql.= " AND p.fk_product_type = 1"; - // Show product on sell - if ($to_sell) $sql.= " AND p.to_sell = ".$db->escape($to_sell); - // Show product on buy - if ($to_buy) $sql.= " AND p.to_buy = ".$db->escape($to_buy); - - $nbtotalofrecords = 0; - if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) - { - $result = $db->query($sql); - $nbtotalofrecords = $db->num_rows($result); - } - - $sql.= $db->order($sortfield, $sortorder); - if ($limit) { - if ($page < 0) - { - $page = 0; - } - $offset = $limit * $page; - - $sql.= $db->plimit($limit + 1, $offset); - } - - $result = $db->query($sql); - if ($result) - { - $num = $db->num_rows($result); - while ($i < $num) - { - $obj = $db->fetch_object($result); - $product_static = new Product($db); - if($product_static->fetch($obj->rowid)) { - $obj_ret[] = parent::_cleanObjectDatas($product_static); - } - $i++; - } - } - else { - throw new RestException(503, 'Error when retrieve product list'); - } - if( ! count($obj_ret)) { - throw new RestException(404, 'No product found'); - } - return $obj_ret; - } /** * Create product object From 8d86b8b37db53152492e661915b86023e6e074f2 Mon Sep 17 00:00:00 2001 From: Xebax Date: Fri, 17 Jun 2016 17:42:46 +0200 Subject: [PATCH 16/23] REST API: fix the definition of /orders/{id}/validate. --- htdocs/commande/class/api_orders.class.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/htdocs/commande/class/api_orders.class.php b/htdocs/commande/class/api_orders.class.php index fbbad50bd93..1f560775b7b 100644 --- a/htdocs/commande/class/api_orders.class.php +++ b/htdocs/commande/class/api_orders.class.php @@ -441,13 +441,17 @@ class Orders extends DolibarrApi * @param int $id Order ID * @param int $idwarehouse Warehouse ID * - * @url GET order/{id}/validate - * @url POST order/{id}/validate + * @url POST {id}/validate * * @return array - * TODO keep only one of the two verbs above (and fix the URL: {id}/validate) + * FIXME An error 403 is returned if the request has an empty body. + * Error message: "Forbidden: Content type `text/plain` is not supported." + * Workaround: send this in the body + * { + * "idwarehouse": 0 + * } */ - function validOrder($id, $idwarehouse=0) + function validate($id, $idwarehouse=0) { if(! DolibarrApiAccess::$user->rights->commande->creer) { throw new RestException(401); From 3b662d6ed88f6531a46fdf0038f9788e77b5950e Mon Sep 17 00:00:00 2001 From: Xebax Date: Fri, 17 Jun 2016 22:52:34 +0200 Subject: [PATCH 17/23] REST API: improve the API to get/add categories for an item. Move the GET /xxx/{id}/categories requests to the corresponding classes (Contacts, Products, Thirdparties). Move the addCustomerCategory() method to the Thirdparties class. Use the POST verb for the request instead of GET because the request modifies the state of the server. --- .../categories/class/api_categories.class.php | 64 ++----------------- htdocs/product/class/api_products.class.php | 18 ++++++ htdocs/societe/class/api_contacts.class.php | 18 ++++++ .../societe/class/api_thirdparties.class.php | 58 +++++++++++++++++ 4 files changed, 101 insertions(+), 57 deletions(-) diff --git a/htdocs/categories/class/api_categories.class.php b/htdocs/categories/class/api_categories.class.php index 7a664718414..22c40de0ef9 100644 --- a/htdocs/categories/class/api_categories.class.php +++ b/htdocs/categories/class/api_categories.class.php @@ -159,10 +159,10 @@ class Categories extends DolibarrApi } /** - * TODO move to /members/, /products/ and /contacts/ * List categories of an entity * - * Get a list of categories + * Note: This method is not directly exposed in the API, it is used + * in the GET /xxx/{id}/categories requests. * * @param string $type Type of category ('member', 'customer', 'supplier', 'product', 'contact') * @param string $sortfield Sort field @@ -172,9 +172,9 @@ class Categories extends DolibarrApi * @param int $item Id of the item to get categories for * @return array Array of category objects * - * @url GET /product/{item}/categories + * @access private */ - function getListForItem($type='product', $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0, $item = 0) { + function getListForItem($type, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0, $item = 0) { global $db, $conf; $obj_ret = array(); @@ -191,6 +191,9 @@ class Categories extends DolibarrApi $sub_type="societe"; $subcol_name="fk_soc"; } + if ($type=="contact") { + $subcol_name="fk_socpeople"; + } $sql = "SELECT s.rowid"; $sql.= " FROM ".MAIN_DB_PREFIX."categorie as s"; $sql.= " , ".MAIN_DB_PREFIX."categorie_".$sub_type." as sub "; @@ -240,60 +243,7 @@ class Categories extends DolibarrApi } return $obj_ret; } - - /** - * TODO move to /thirsparties/ or /customers/ - * Get categories for a customer - * - * @param int $cusid Customer id filter - * @param string $sortfield Sort field - * @param string $sortorder Sort order - * @param int $limit Limit for list - * @param int $page Page number - * - * @return mixed - * - * @url GET /customer/{cusid}/categories - */ - function getListCustomerCategories($cusid, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { - return $this->getListForItem('customer', $sortfield, $sortorder, $limit, $page, $cusid); - } - /** - * TODO move to /thirsparties/ or /customers/ - * Add category to customer - * - * @param int $cusid Id of customer - * @param int $catid Id of category - * - * @return mixed - * - * @url GET /customer/{cusid}/addCategory/{catid} - */ - function addCustomerCategory($cusid,$catid) { - if(! DolibarrApiAccess::$user->rights->societe->creer) { - throw new RestException(401); - } - $customer = new Client($this->db); - $customer->fetch($cusid); - if( ! $customer ) { - throw new RestException(404, 'customer not found'); - } - $result = $this->category->fetch($catid); - if( ! $result ) { - throw new RestException(404, 'category not found'); - } - - if( ! DolibarrApi::_checkAccessToResource('societe',$customer->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); - } - if( ! DolibarrApi::_checkAccessToResource('category',$this->category->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); - } - $this->category->add_type($customer,'customer'); - return $customer; - } - /** * Create category object * diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index e1a8b6824a0..bba6739ab68 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -250,6 +250,24 @@ class Products extends DolibarrApi return $this->product->delete(DolibarrApiAccess::$user); } + /** + * Get categories for a product + * + * @param int $id ID of product + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * + * @return mixed + * + * @url GET {id}/categories + */ + function getCategories($id, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { + $categories = new Categories(); + return $categories->getListForItem('product', $sortfield, $sortorder, $limit, $page, $id); + } + /** * Validate fields before create or update object * diff --git a/htdocs/societe/class/api_contacts.class.php b/htdocs/societe/class/api_contacts.class.php index 349fa8ecae2..cd0dd6ae38f 100644 --- a/htdocs/societe/class/api_contacts.class.php +++ b/htdocs/societe/class/api_contacts.class.php @@ -300,6 +300,24 @@ class Contacts extends DolibarrApi return $result; } + /** + * Get categories for a contact + * + * @param int $id ID of contact + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * + * @return mixed + * + * @url GET {id}/categories + */ + function getCategories($id, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { + $categories = new Categories(); + return $categories->getListForItem('contact', $sortfield, $sortorder, $limit, $page, $id); + } + /** * Validate fields before create or update object * diff --git a/htdocs/societe/class/api_thirdparties.class.php b/htdocs/societe/class/api_thirdparties.class.php index cb898991f7b..7c3d1eace04 100644 --- a/htdocs/societe/class/api_thirdparties.class.php +++ b/htdocs/societe/class/api_thirdparties.class.php @@ -243,6 +243,64 @@ class Thirdparties extends DolibarrApi return $this->company->delete($id); } + /** + * Get categories for a thirdparty + * + * @param int $id ID of thirdparty + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * + * @return mixed + * + * @url GET {id}/categories + */ + function getCategories($id, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { + $categories = new Categories(); + return $categories->getListForItem('customer', $sortfield, $sortorder, $limit, $page, $id); + } + + /** + * Add category to a thirdparty + * + * @param int $id Id of thirdparty + * @param array $request_data Request datas + * + * @return mixed + * + * @url POST {id}/addCategory + */ + function addCategory($id, $request_data = NULL) { + if (!isset($request_data["category_id"])) + throw new RestException(400, "category_id field missing"); + $category_id = $request_data["category_id"]; + + if(! DolibarrApiAccess::$user->rights->societe->creer) { + throw new RestException(401); + } + + $result = $this->company->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Thirdparty not found'); + } + $category = new Categorie($this->db); + $result = $category->fetch($category_id); + if( ! $result ) { + throw new RestException(404, 'category not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('societe',$this->company->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + if( ! DolibarrApi::_checkAccessToResource('category',$category->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + $category->add_type($this->company,'customer'); + return $this->company; + } + /** * Validate fields before create or update object * From 388839296e51d5b95d28d0b6f19ed364559ce192 Mon Sep 17 00:00:00 2001 From: Xebax Date: Sat, 18 Jun 2016 19:15:39 +0200 Subject: [PATCH 18/23] REST API: update the URLs in RestAPIUserTest.php. --- test/phpunit/RestAPIUserTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/phpunit/RestAPIUserTest.php b/test/phpunit/RestAPIUserTest.php index 189c17a0bd3..af1ae6b3622 100644 --- a/test/phpunit/RestAPIUserTest.php +++ b/test/phpunit/RestAPIUserTest.php @@ -147,7 +147,7 @@ class RestAPIUserTest extends PHPUnit_Framework_TestCase { global $conf,$user,$langs,$db; - $url = $this->api_url.'/user/123456789?api_key='.$this->api_key; + $url = $this->api_url.'/users/123456789?api_key='.$this->api_key; //$addheaders=array('Content-Type: application/json'); print __METHOD__." Request url=".$url."\n"; @@ -159,7 +159,7 @@ class RestAPIUserTest extends PHPUnit_Framework_TestCase $this->assertNotNull($object, "Parsing of json result must no be null"); $this->assertEquals(404, $object['error']['code']); - $url = $this->api_url.'/user/1?api_key='.$this->api_key; + $url = $this->api_url.'/users/1?api_key='.$this->api_key; print __METHOD__." Request url=".$url."\n"; $result=getURLContent($url, 'GET', '', 1, array()); @@ -174,7 +174,7 @@ class RestAPIUserTest extends PHPUnit_Framework_TestCase public function testRestCreateUser() { // attemp to create without mandatory fields : - $url = $this->api_url.'/user?api_key='.$this->api_key; + $url = $this->api_url.'/users?api_key='.$this->api_key; $addheaders=array('Content-Type: application/json'); $bodyobj = array( From 3cac54741da48ae2baa4896d3a39bcf029271f33 Mon Sep 17 00:00:00 2001 From: Xebax Date: Mon, 20 Jun 2016 12:16:19 +0200 Subject: [PATCH 19/23] REST API: fix the index() method in Categories. In the Categories class, set all the parameters of the index() method as optional to make this method compatible with the one of the parent class, DolibarrApi. --- htdocs/categories/class/api_categories.class.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/htdocs/categories/class/api_categories.class.php b/htdocs/categories/class/api_categories.class.php index 22c40de0ef9..cab36132944 100644 --- a/htdocs/categories/class/api_categories.class.php +++ b/htdocs/categories/class/api_categories.class.php @@ -102,7 +102,7 @@ class Categories extends DolibarrApi * * @throws RestException */ - function index($type, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { + function index($type = '', $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { global $db, $conf; $obj_ret = array(); @@ -114,7 +114,10 @@ class Categories extends DolibarrApi $sql = "SELECT s.rowid"; $sql.= " FROM ".MAIN_DB_PREFIX."categorie as s"; $sql.= ' WHERE s.entity IN ('.getEntity('categorie', 1).')'; - $sql.= ' AND s.type='.array_search($type,Categories::$TYPES); + if (!empty($type)) + { + $sql.= ' AND s.type='.array_search($type,Categories::$TYPES); + } $nbtotalofrecords = 0; if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) From 4a0d5549865ca7ab06462841e22a495c5af7245c Mon Sep 17 00:00:00 2001 From: Xebax Date: Tue, 21 Jun 2016 22:54:38 +0200 Subject: [PATCH 20/23] Revert "REST API: fix deleting a product/service." This reverts commit d7c8a466b12c99306a2080cd22d887a36c9f751d. --- htdocs/product/card.php | 2 +- htdocs/product/class/api_products.class.php | 3 ++- htdocs/product/class/product.class.php | 5 ++--- htdocs/webservices/server_productorservice.php | 6 +++++- test/phpunit/ProductTest.php | 2 +- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/htdocs/product/card.php b/htdocs/product/card.php index c2d7b76dac3..330e712cf1b 100644 --- a/htdocs/product/card.php +++ b/htdocs/product/card.php @@ -553,7 +553,7 @@ if (empty($reshook)) { if (($object->type == Product::TYPE_PRODUCT && $user->rights->produit->supprimer) || ($object->type == Product::TYPE_SERVICE && $user->rights->service->supprimer)) { - $result = $object->delete($user); + $result = $object->delete($object->id); } if ($result > 0) diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index bba6739ab68..bd5b37194c3 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -232,6 +232,7 @@ class Products extends DolibarrApi * * @param int $id Product ID * @return array + * FIXME Deleting a product/service does not work because the Product::delete() method uses a global $user but it is not set. */ function delete($id) { @@ -247,7 +248,7 @@ class Products extends DolibarrApi throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - return $this->product->delete(DolibarrApiAccess::$user); + return $this->product->delete($id); } /** diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 908ccea68e9..982b109da99 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -878,19 +878,18 @@ class Product extends CommonObject /** * Delete a product from database (if not used) * - * @param User $user Object user that ask to delete * @param int $id Product id (usage of this is deprecated, delete should be called without parameters on a fetched object) * @param int $notrigger Do not execute trigger * @return int < 0 if KO, 0 = Not possible, > 0 if OK */ - function delete($user, $id=0, $notrigger=0) + function delete($id=0, $notrigger=0) { // Deprecation warning if ($id > 0) { dol_syslog(__METHOD__ . " with parameter is deprecated", LOG_WARNING); } - global $conf,$langs; + global $conf,$user,$langs; require_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php'; $error=0; diff --git a/htdocs/webservices/server_productorservice.php b/htdocs/webservices/server_productorservice.php index 9da26495f76..aa43dbb185c 100644 --- a/htdocs/webservices/server_productorservice.php +++ b/htdocs/webservices/server_productorservice.php @@ -841,6 +841,10 @@ function deleteProductOrService($authentication,$listofidstring) $error=0; $fuser=check_authentication($authentication,$error,$errorcode,$errorlabel); + // User must be defined to user authenticated + global $user; + $user=$fuser; + $listofid=explode(',',trim($listofidstring)); $listofiddeleted=array(); @@ -869,7 +873,7 @@ function deleteProductOrService($authentication,$listofidstring) } else { - $result=$newobject->delete($fuser); + $result=$newobject->delete(); if ($result <= 0) { $error++; diff --git a/test/phpunit/ProductTest.php b/test/phpunit/ProductTest.php index 87f290593f0..199aace802c 100644 --- a/test/phpunit/ProductTest.php +++ b/test/phpunit/ProductTest.php @@ -232,7 +232,7 @@ class ProductTest extends PHPUnit_Framework_TestCase $localobject=new Product($this->savdb); $result=$localobject->fetch($id); - $result=$localobject->delete($user); + $result=$localobject->delete($id); print __METHOD__." id=".$id." result=".$result."\n"; $this->assertLessThan($result, 0); From 9e9e224c4634f20a4fc764d8e2394d9b96d3aaa6 Mon Sep 17 00:00:00 2001 From: Xebax Date: Tue, 21 Jun 2016 23:08:22 +0200 Subject: [PATCH 21/23] REST API: fix deleting a product/service. The global variable $user must be set before calling the Product::delete() method else the check of permissions fails. --- htdocs/product/class/api_products.class.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/htdocs/product/class/api_products.class.php b/htdocs/product/class/api_products.class.php index bd5b37194c3..d6dc8770b23 100644 --- a/htdocs/product/class/api_products.class.php +++ b/htdocs/product/class/api_products.class.php @@ -232,7 +232,6 @@ class Products extends DolibarrApi * * @param int $id Product ID * @return array - * FIXME Deleting a product/service does not work because the Product::delete() method uses a global $user but it is not set. */ function delete($id) { @@ -248,6 +247,10 @@ class Products extends DolibarrApi throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } + // The Product::delete() method uses the global variable $user. + global $user; + $user = DolibarrApiAccess::$user; + return $this->product->delete($id); } From 70ba8ec78db38acb55d65f1764ee56d4f793fea9 Mon Sep 17 00:00:00 2001 From: Xebax Date: Wed, 22 Jun 2016 10:08:54 +0200 Subject: [PATCH 22/23] REST API: Bring back the existing API (for backward compatibility). Bring back the existing API and mark all the operations as deprecated. Both the existing and the new API are documented and browsable with the Restler API Explorer. The existing API appears under "root". --- htdocs/api/index.php | 15 +- .../class/api_deprecated_category.class.php | 489 ++++++++++++++++ .../class/api_deprecated_commande.class.php | 535 ++++++++++++++++++ .../class/api_deprecated_invoice.class.php | 297 ++++++++++ .../class/api_deprecated_product.class.php | 359 ++++++++++++ .../class/api_deprecated_contact.class.php | 293 ++++++++++ .../class/api_deprecated_thirdparty.class.php | 411 ++++++++++++++ .../user/class/api_deprecated_user.class.php | 273 +++++++++ 8 files changed, 2670 insertions(+), 2 deletions(-) create mode 100644 htdocs/categories/class/api_deprecated_category.class.php create mode 100644 htdocs/commande/class/api_deprecated_commande.class.php create mode 100644 htdocs/compta/facture/class/api_deprecated_invoice.class.php create mode 100644 htdocs/product/class/api_deprecated_product.class.php create mode 100644 htdocs/societe/class/api_deprecated_contact.class.php create mode 100644 htdocs/societe/class/api_deprecated_thirdparty.class.php create mode 100644 htdocs/user/class/api_deprecated_user.class.php diff --git a/htdocs/api/index.php b/htdocs/api/index.php index e58d2370be7..28fb3d5f038 100644 --- a/htdocs/api/index.php +++ b/htdocs/api/index.php @@ -112,13 +112,24 @@ foreach ($modulesdir as $dir) { while (($file_searched = readdir($handle_part))!==false) { - if (is_readable($dir_part.$file_searched) && preg_match("/^api_(.*)\.class\.php$/i",$file_searched,$reg)) + // Support of the deprecated API. + if (is_readable($dir_part.$file_searched) && preg_match("/^api_deprecated_(.*)\.class\.php$/i",$file_searched,$reg)) + { + $classname = ucwords($reg[1]).'Api'; + require_once $dir_part.$file_searched; + if (class_exists($classname)) + { + dol_syslog("Found deprecated API classname=".$classname); + $api->r->addAPIClass($classname, ''); + } + } + else if (is_readable($dir_part.$file_searched) && preg_match("/^api_(.*)\.class\.php$/i",$file_searched,$reg)) { $classname = ucwords($reg[1]); require_once $dir_part.$file_searched; if (class_exists($classname)) { - dol_syslog("Found API classname=".$classname); + dol_syslog("Found API classname=".$classname); $listofapis[] = $classname; } } diff --git a/htdocs/categories/class/api_deprecated_category.class.php b/htdocs/categories/class/api_deprecated_category.class.php new file mode 100644 index 00000000000..c6a52f72035 --- /dev/null +++ b/htdocs/categories/class/api_deprecated_category.class.php @@ -0,0 +1,489 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + use Luracast\Restler\RestException; + + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; + require_once DOL_DOCUMENT_ROOT.'/societe/class/client.class.php'; + +/** + * API class for category object + * + * @smart-auto-routing false + * @access protected + * @class DolibarrApiAccess {@requires user,external} + * + * @deprecated + */ +class CategoryApi extends DolibarrApi +{ + /** + * @var array $FIELDS Mandatory fields, checked when create and update object + */ + static $FIELDS = array( + 'label', + 'type' + ); + + static $TYPES = array( + 0 => 'product', + 1 => 'supplier', + 2 => 'customer', + 3 => 'member', + 4 => 'contact', + 5 => 'account', + ); + + /** + * @var Categorie $category {@type Categorie} + */ + public $category; + + /** + * Constructor Warning: Deprecated + * + * @url GET category/ + * + */ + function __construct() + { + global $db, $conf; + $this->db = $db; + $this->category = new Categorie($this->db); + + } + + /** + * Get properties of a category object Warning: Deprecated + * + * Return an array with category informations + * + * @param int $id ID of category + * @return array|mixed data without useless information + * + * @url GET category/{id} + * @throws RestException + */ + function get($id) + { + if(! DolibarrApiAccess::$user->rights->categorie->lire) { + throw new RestException(401); + } + + $result = $this->category->fetch($id); + if( ! $result ) { + throw new RestException(404, 'category not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('category',$this->category->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + return $this->_cleanObjectDatas($this->category); + } + + /** + * List categories Warning: Deprecated + * + * Get a list of categories + * + * @param string $type Type of category ('member', 'customer', 'supplier', 'product', 'contact') + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * @return array Array of category objects + * + * @url GET /category/list + */ + function getList($type='product', $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { + global $db, $conf; + + $obj_ret = array(); + + if(! DolibarrApiAccess::$user->rights->categorie->lire) { + throw new RestException(401); + } + + $sql = "SELECT s.rowid"; + $sql.= " FROM ".MAIN_DB_PREFIX."categorie as s"; + $sql.= ' WHERE s.entity IN ('.getEntity('categorie', 1).')'; + $sql.= ' AND s.type='.array_search($type,CategoryApi::$TYPES); + + $nbtotalofrecords = 0; + if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) + { + $result = $db->query($sql); + $nbtotalofrecords = $db->num_rows($result); + } + + $sql.= $db->order($sortfield, $sortorder); + if ($limit) { + if ($page < 0) + { + $page = 0; + } + $offset = $limit * $page; + + $sql.= $db->plimit($limit + 1, $offset); + } + + $result = $db->query($sql); + if ($result) + { + $i=0; + $num = $db->num_rows($result); + while ($i < $num) + { + $obj = $db->fetch_object($result); + $category_static = new Categorie($db); + if($category_static->fetch($obj->rowid)) { + $obj_ret[] = parent::_cleanObjectDatas($category_static); + } + $i++; + } + } + else { + throw new RestException(503, 'Error when retrieve category list : '.$category_static->error); + } + if( ! count($obj_ret)) { + throw new RestException(404, 'No category found'); + } + return $obj_ret; + } + /** + * List categories of an entity Warning: Deprecated + * + * Get a list of categories + * + * @param string $type Type of category ('member', 'customer', 'supplier', 'product', 'contact') + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * @param int $item Id of the item to get categories for + * @return array Array of category objects + * + * @url GET /product/{item}/categories + */ + function getListForItem($type='product', $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0, $item = 0) { + global $db, $conf; + + $obj_ret = array(); + + if(! DolibarrApiAccess::$user->rights->categorie->lire) { + throw new RestException(401); + } + //if ($type == "") { + //$type="product"; + //} + $sub_type = $type; + $subcol_name = "fk_".$type; + if ($type=="customer" || $type=="supplier") { + $sub_type="societe"; + $subcol_name="fk_soc"; + } + $sql = "SELECT s.rowid"; + $sql.= " FROM ".MAIN_DB_PREFIX."categorie as s"; + $sql.= " , ".MAIN_DB_PREFIX."categorie_".$sub_type." as sub "; + $sql.= ' WHERE s.entity IN ('.getEntity('categorie', 1).')'; + $sql.= ' AND s.type='.array_search($type,CategoryApi::$TYPES); + $sql.= ' AND s.rowid = sub.fk_categorie'; + $sql.= ' AND sub.'.$subcol_name.' = '.$item; + + $nbtotalofrecords = 0; + if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) + { + $result = $db->query($sql); + $nbtotalofrecords = $db->num_rows($result); + } + + $sql.= $db->order($sortfield, $sortorder); + if ($limit) { + if ($page < 0) + { + $page = 0; + } + $offset = $limit * $page; + + $sql.= $db->plimit($limit + 1, $offset); + } + + $result = $db->query($sql); + if ($result) + { + $i=0; + $num = $db->num_rows($result); + while ($i < $num) + { + $obj = $db->fetch_object($result); + $category_static = new Categorie($db); + if($category_static->fetch($obj->rowid)) { + $obj_ret[] = parent::_cleanObjectDatas($category_static); + } + $i++; + } + } + else { + throw new RestException(503, 'Error when retrieve category list : '.$category_static->error); + } + if( ! count($obj_ret)) { + throw new RestException(404, 'No category found'); + } + return $obj_ret; + } + + /** + * Get member categories list Warning: Deprecated + * + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * @return mixed + * + * @url GET /category/list/member + */ + function getListCategoryMember($sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { + return $this->getList('member', $sortfield, $sortorder, $limit, $page); + } + + /** + * Get customer categories list Warning: Deprecated + * + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * + * @return mixed + * + * @url GET /category/list/customer + */ + function getListCategoryCustomer($sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { + return $this->getList('customer', $sortfield, $sortorder, $limit, $page); + } + /** + * Get categories for a customer Warning: Deprecated + * + * @param int $cusid Customer id filter + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * + * @return mixed + * + * @url GET /customer/{cusid}/categories + */ + function getListCustomerCategories($cusid, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { + return $this->getListForItem('customer', $sortfield, $sortorder, $limit, $page, $cusid); + } + + /** + * Add category to customer Warning: Deprecated + * + * @param int $cusid Id of customer + * @param int $catid Id of category + * + * @return mixed + * + * @url GET /customer/{cusid}/addCategory/{catid} + */ + function addCustomerCategory($cusid,$catid) { + if(! DolibarrApiAccess::$user->rights->societe->creer) { + throw new RestException(401); + } + $customer = new Client($this->db); + $customer->fetch($cusid); + if( ! $customer ) { + throw new RestException(404, 'customer not found'); + } + $result = $this->category->fetch($catid); + if( ! $result ) { + throw new RestException(404, 'category not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('societe',$customer->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + if( ! DolibarrApi::_checkAccessToResource('category',$this->category->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + $this->category->add_type($customer,'customer'); + return $customer; + } + + /** + * Get supplier categories list Warning: Deprecated + * + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * + * @return mixed + * + * @url GET /category/list/supplier + */ + function getListCategorySupplier($sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { + return $this->getList('supplier', $sortfield, $sortorder, $limit, $page); + } + + /** + * Get product categories list Warning: Deprecated + * + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * + * @return mixed + * + * @url GET /category/list/product + */ + function getListCategoryProduct($sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { + return $this->getList('product', $sortfield, $sortorder, $limit, $page); + } + + /** + * Get contact categories list Warning: Deprecated + * + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * @return mixed + * + * @url GET /category/list/contact + */ + function getListCategoryContact($sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { + return $this->getList('contact', $sortfield, $sortorder, $limit, $page); + } + + /** + * Create category object Warning: Deprecated + * + * @param array $request_data Request data + * @return int ID of category + * + * @url POST category/ + */ + function post($request_data = NULL) + { + if(! DolibarrApiAccess::$user->rights->categorie->creer) { + throw new RestException(401); + } + // Check mandatory fields + $result = $this->_validate($request_data); + + foreach($request_data as $field => $value) { + $this->category->$field = $value; + } + if($this->category->create(DolibarrApiAccess::$user) < 0) { + throw new RestException(503, 'Error when create category : '.$this->category->error); + } + return $this->category->id; + } + + /** + * Update category Warning: Deprecated + * + * @param int $id Id of category to update + * @param array $request_data Datas + * @return int + * + * @url PUT category/{id} + */ + function put($id, $request_data = NULL) + { + if(! DolibarrApiAccess::$user->rights->categorie->creer) { + throw new RestException(401); + } + + $result = $this->category->fetch($id); + if( ! $result ) { + throw new RestException(404, 'category not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('category',$this->category->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + foreach($request_data as $field => $value) { + $this->category->$field = $value; + } + + if($this->category->update(DolibarrApiAccess::$user)) + return $this->get ($id); + + return false; + } + + /** + * Delete category Warning: Deprecated + * + * @param int $id Category ID + * @return array + * + * @url DELETE category/{id} + */ + function delete($id) + { + if(! DolibarrApiAccess::$user->rights->categorie->supprimer) { + throw new RestException(401); + } + $result = $this->category->fetch($id); + if( ! $result ) { + throw new RestException(404, 'category not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('category',$this->category->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + if (! $this->category->delete(DolibarrApiAccess::$user)) { + throw new RestException(401,'error when delete category'); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Category deleted' + ) + ); + } + + /** + * Validate fields before create or update object + * + * @param array $data Data to validate + * @return array + * + * @throws RestException + */ + function _validate($data) + { + $category = array(); + foreach (CategoryApi::$FIELDS as $field) { + if (!isset($data[$field])) + throw new RestException(400, "$field field missing"); + $category[$field] = $data[$field]; + } + return $category; + } +} diff --git a/htdocs/commande/class/api_deprecated_commande.class.php b/htdocs/commande/class/api_deprecated_commande.class.php new file mode 100644 index 00000000000..557682b8cf7 --- /dev/null +++ b/htdocs/commande/class/api_deprecated_commande.class.php @@ -0,0 +1,535 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + use Luracast\Restler\RestException; + + require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php'; + +/** + * API class for commande object + * + * @smart-auto-routing false + * @access protected + * @class DolibarrApiAccess {@requires user,external} + * + * @category Api + * @package Api + * + * @deprecated + */ +class CommandeApi extends DolibarrApi +{ + + /** + * @var array $FIELDS Mandatory fields, checked when create and update object + */ + static $FIELDS = array( + 'socid' + ); + + /** + * @var Commande $commande {@type Commande} + */ + public $commande; + + /** + * Constructor Warning: Deprecated + * + * @url GET order/ + * + */ + function __construct() + { + global $db, $conf; + $this->db = $db; + $this->commande = new Commande($this->db); + } + + /** + * Get properties of a commande object Warning: Deprecated + * + * Return an array with commande informations + * + * @param int $id ID of order + * @param string $ref Ref of object + * @param string $ref_ext External reference of object + * @param string $ref_int Internal reference of other object + * @return array|mixed data without useless information + * + * @url GET order/{id} + * @throws RestException + */ + function get($id='',$ref='', $ref_ext='', $ref_int='') + { + if(! DolibarrApiAccess::$user->rights->commande->lire) { + throw new RestException(401); + } + + $result = $this->commande->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Order not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + $this->commande->fetchObjectLinked(); + return $this->_cleanObjectDatas($this->commande); + } + + /** + * List orders Warning: Deprecated + * + * Get a list of orders + * + * @param int $mode Use this param to filter list + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * @param string $societe Societe filter field + * + * @url GET /order/list + * @return array Array of order objects + */ + function getList($mode=0, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0, $societe = 0) { + global $db, $conf; + + $obj_ret = array(); + // case of external user, $societe param is ignored and replaced by user's socid + $socid = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : $societe; + + // If the internal user must only see his customers, force searching by him + if (! DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) $search_sale = DolibarrApiAccess::$user->id; + + $sql = "SELECT s.rowid"; + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) + $sql.= " FROM ".MAIN_DB_PREFIX."commande as s"; + + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale + + // Example of use $mode + //if ($mode == 1) $sql.= " AND s.client IN (1, 3)"; + //if ($mode == 2) $sql.= " AND s.client IN (2, 3)"; + + $sql.= ' WHERE s.entity IN ('.getEntity('commande', 1).')'; + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= " AND s.fk_soc = sc.fk_soc"; + if ($socid) $sql.= " AND s.fk_soc = ".$socid; + if ($search_sale > 0) $sql.= " AND s.rowid = sc.fk_soc"; // Join for the needed table to filter by sale + + // Insert sale filter + if ($search_sale > 0) + { + $sql .= " AND sc.fk_user = ".$search_sale; + } + + $nbtotalofrecords = 0; + if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) + { + $result = $db->query($sql); + $nbtotalofrecords = $db->num_rows($result); + } + + $sql.= $db->order($sortfield, $sortorder); + if ($limit) { + if ($page < 0) + { + $page = 0; + } + $offset = $limit * $page; + + $sql.= $db->plimit($limit + 1, $offset); + } + + $result = $db->query($sql); + + if ($result) + { + $num = $db->num_rows($result); + while ($i < $num) + { + $obj = $db->fetch_object($result); + $commande_static = new Commande($db); + if($commande_static->fetch($obj->rowid)) { + $obj_ret[] = parent::_cleanObjectDatas($commande_static); + } + $i++; + } + } + else { + throw new RestException(503, 'Error when retrieve commande list'); + } + if( ! count($obj_ret)) { + throw new RestException(404, 'No commande found'); + } + return $obj_ret; + } + + /** + * List orders for specific thirdparty Warning: Deprecated + * + * Get a list of orders + * + * @param int $socid Id of customer + * + * @url GET /customer/{socid}/order/list + * @url GET /thirdparty/{socid}/order/list + * @return array Array of order objects + */ + function getListForSoc($socid = 0) { + return getList(0,"s.rowid","ASC",0,0,$socid); + } + + + /** + * Create order object Warning: Deprecated + * + * @param array $request_data Request datas + * + * @url POST order/ + * + * @return int ID of commande + */ + function post($request_data = NULL) + { + if(! DolibarrApiAccess::$user->rights->commande->creer) { + throw new RestException(401, "Insuffisant rights"); + } + // Check mandatory fields + $result = $this->_validate($request_data); + + foreach($request_data as $field => $value) { + $this->commande->$field = $value; + } + if (isset($request_data["lines"])) { + $lines = array(); + foreach ($request_data["lines"] as $line) { + array_push($lines, (object) $line); + } + $this->commande->lines = $lines; + } + if(! $this->commande->create(DolibarrApiAccess::$user) ) { + throw new RestException(500, "Error while creating order"); + } + + return $this->commande->id; + } + /** + * Get lines of an order Warning: Deprecated + * + * + * @param int $id Id of order + * + * @url GET order/{id}/line/list + * + * @return int + */ + function getLines($id) { + if(! DolibarrApiAccess::$user->rights->commande->lire) { + throw new RestException(401); + } + + $result = $this->commande->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Commande not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + $this->commande->getLinesArray(); + $result = array(); + foreach ($this->commande->lines as $line) { + array_push($result,$this->_cleanObjectDatas($line)); + } + return $result; + } + /** + * Add a line to given order Warning: Deprecated + * + * + * @param int $id Id of commande to update + * @param array $request_data Orderline data + * + * @url POST order/{id}/line + * + * @return int + */ + function postLine($id, $request_data = NULL) { + if(! DolibarrApiAccess::$user->rights->commande->creer) { + throw new RestException(401); + } + + $result = $this->commande->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Commande not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + $request_data = (object) $request_data; + $updateRes = $this->commande->addline( + $request_data->desc, + $request_data->subprice, + $request_data->qty, + $request_data->tva_tx, + $request_data->localtax1_tx, + $request_data->localtax2_tx, + $request_data->fk_product, + $request_data->remise_percent, + $request_data->info_bits, + $request_data->fk_remise_except, + 'HT', + 0, + $request_data->date_start, + $request_data->date_end, + $request_data->product_type, + $request_data->rang, + $request_data->special_code, + $fk_parent_line, + $request_data->fk_fournprice, + $request_data->pa_ht, + $request_data->label, + $request_data->array_options, + $request_data->fk_unit, + $this->element, + $request_data->id + ); + + if ($updateRes > 0) { + return $this->get($id)->line->rowid; + + } + return false; + } + /** + * Update a line to given order Warning: Deprecated + * + * + * @param int $id Id of commande to update + * @param int $lineid Id of line to update + * @param array $request_data Orderline data + * + * @url PUT order/{id}/line/{lineid} + * + * @return object + */ + function putLine($id, $lineid, $request_data = NULL) { + if(! DolibarrApiAccess::$user->rights->commande->creer) { + throw new RestException(401); + } + + $result = $this->commande->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Commande not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + $request_data = (object) $request_data; + $updateRes = $this->commande->updateline( + $lineid, + $request_data->desc, + $request_data->subprice, + $request_data->qty, + $request_data->remise_percent, + $request_data->tva_tx, + $request_data->localtax1_tx, + $request_data->localtax2_tx, + 'HT', + $request_data->info_bits, + $request_data->date_start, + $request_data->date_end, + $request_data->product_type, + $request_data->fk_parent_line, + 0, + $request_data->fk_fournprice, + $request_data->pa_ht, + $request_data->label, + $request_data->special_code, + $request_data->array_options, + $request_data->fk_unit + ); + + if ($updateRes > 0) { + $result = $this->get($id); + unset($result->line); + return $this->_cleanObjectDatas($result); + } + return false; + } + /** + * Delete a line to given order Warning: Deprecated + * + * + * @param int $id Id of commande to update + * @param int $lineid Id of line to delete + * + * @url DELETE order/{id}/line/{lineid} + * + * @return int + */ + function delLine($id, $lineid) { + if(! DolibarrApiAccess::$user->rights->commande->creer) { + throw new RestException(401); + } + + $result = $this->commande->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Commande not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + $request_data = (object) $request_data; + $updateRes = $this->commande->deleteline($lineid); + if ($updateRes == 1) { + return $this->get($id); + } + return false; + } + + /** + * Update order general fields (won't touch lines of order) Warning: Deprecated + * + * @param int $id Id of commande to update + * @param array $request_data Datas + * + * @url PUT order/{id} + * + * @return int + */ + function put($id, $request_data = NULL) { + if(! DolibarrApiAccess::$user->rights->commande->creer) { + throw new RestException(401); + } + + $result = $this->commande->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Commande not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + foreach($request_data as $field => $value) { + $this->commande->$field = $value; + } + + if($this->commande->update($id, DolibarrApiAccess::$user,1,'','','update')) + return $this->get($id); + + return false; + } + + /** + * Delete order Warning: Deprecated + * + * @param int $id Order ID + * + * @url DELETE order/{id} + * + * @return array + */ + function delete($id) + { + if(! DolibarrApiAccess::$user->rights->commande->supprimer) { + throw new RestException(401); + } + $result = $this->commande->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Order not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + if( ! $this->commande->delete(DolibarrApiAccess::$user)) { + throw new RestException(500, 'Error when delete order : '.$this->commande->error); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Order deleted' + ) + ); + + } + + /** + * Validate an order Warning: Deprecated + * + * @param int $id Order ID + * @param int $idwarehouse Warehouse ID + * + * @url GET order/{id}/validate + * @url POST order/{id}/validate + * + * @return array + * + */ + function validOrder($id, $idwarehouse=0) + { + if(! DolibarrApiAccess::$user->rights->commande->creer) { + throw new RestException(401); + } + $result = $this->commande->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Order not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('commande',$this->commande->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + if( ! $this->commande->valid(DolibarrApiAccess::$user, $idwarehouse)) { + throw new RestException(500, 'Error when validate order'); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Order validated' + ) + ); + } + + /** + * Validate fields before create or update object + * + * @param array $data Array with data to verify + * @return array + * @throws RestException + */ + function _validate($data) + { + $commande = array(); + foreach (CommandeApi::$FIELDS as $field) { + if (!isset($data[$field])) + throw new RestException(400, "$field field missing"); + $commande[$field] = $data[$field]; + + } + return $commande; + } +} diff --git a/htdocs/compta/facture/class/api_deprecated_invoice.class.php b/htdocs/compta/facture/class/api_deprecated_invoice.class.php new file mode 100644 index 00000000000..2ba4873fe8f --- /dev/null +++ b/htdocs/compta/facture/class/api_deprecated_invoice.class.php @@ -0,0 +1,297 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + use Luracast\Restler\RestException; + + require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php'; + +/** + * API class for invoice object + * + * @smart-auto-routing false + * @access protected + * @class DolibarrApiAccess {@requires user,external} + * @deprecated + */ +class InvoiceApi extends DolibarrApi +{ + /** + * + * @var array $FIELDS Mandatory fields, checked when create and update object + */ + static $FIELDS = array( + 'socid' + ); + + /** + * @var Facture $invoice {@type Facture} + */ + public $invoice; + + /** + * Constructor Warning: Deprecated + * + * @url GET invoice/ + * + */ + function __construct() + { + global $db, $conf; + $this->db = $db; + $this->invoice = new Facture($this->db); + } + + /** + * Get properties of a invoice object Warning: Deprecated + * + * Return an array with invoice informations + * + * @param int $id ID of invoice + * @return array|mixed data without useless information + * + * @url GET invoice/{id} + * @throws RestException + */ + function get($id) + { + if(! DolibarrApiAccess::$user->rights->facture->lire) { + throw new RestException(401); + } + + $result = $this->invoice->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Facture not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + return $this->_cleanObjectDatas($this->invoice); + } + + /** + * List invoices Warning: Deprecated + * + * Get a list of invoices + * + * @param int $socid Filter list with thirdparty ID + * @param string $mode Filter by invoice status : draft | unpaid | paid | cancelled + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * + * @return array Array of invoice objects + * + * @url GET invoice/list + * @url GET invoice/list/{mode} + * @url GET thirdparty/{socid}/invoice/list + * @url GET thirdparty/{socid}/invoice/list/{mode} + */ + function getList($socid=0, $mode='', $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { + global $db, $conf; + + $obj_ret = array(); + + $socid = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : ''; + + // If the internal user must only see his customers, force searching by him + if (! DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) $search_sale = DolibarrApiAccess::$user->id; + + $sql = "SELECT s.rowid"; + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) + $sql.= " FROM ".MAIN_DB_PREFIX."facture as s"; + + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale + + $sql.= ' WHERE s.entity IN ('.getEntity('facture', 1).')'; + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= " AND s.fk_soc = sc.fk_soc"; + if ($socid) $sql.= " AND s.fk_soc = ".$socid; + if ($search_sale > 0) $sql.= " AND s.rowid = sc.fk_soc"; // Join for the needed table to filter by sale + + + // Example of use $mode + if ($mode == 'draft') $sql.= " AND s.fk_statut IN (0)"; + if ($mode == 'unpaid') $sql.= " AND s.fk_statut IN (1)"; + if ($mode == 'paid') $sql.= " AND s.fk_statut IN (2)"; + if ($mode == 'cancelled') $sql.= " AND s.fk_statut IN (3)"; + + // Insert sale filter + if ($search_sale > 0) + { + $sql .= " AND sc.fk_user = ".$search_sale; + } + + $nbtotalofrecords = 0; + if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) + { + $result = $db->query($sql); + $nbtotalofrecords = $db->num_rows($result); + } + + $sql.= $db->order($sortfield, $sortorder); + if ($limit) { + if ($page < 0) + { + $page = 0; + } + $offset = $limit * $page; + + $sql.= $db->plimit($limit + 1, $offset); + } + + $result = $db->query($sql); + if ($result) + { + $num = $db->num_rows($result); + while ($i < $num) + { + $obj = $db->fetch_object($result); + $invoice_static = new Facture($db); + if($invoice_static->fetch($obj->rowid)) { + $obj_ret[] = parent::_cleanObjectDatas($invoice_static); + } + $i++; + } + } + else { + throw new RestException(503, 'Error when retrieve invoice list'); + } + if( ! count($obj_ret)) { + throw new RestException(404, 'No invoice found'); + } + return $obj_ret; + } + + /** + * Create invoice object Warning: Deprecated + * + * @param array $request_data Request datas + * @return int ID of invoice + * + * @url POST invoice/ + */ + function post($request_data = NULL) + { + if(! DolibarrApiAccess::$user->rights->facture->creer) { + throw new RestException(401); + } + // Check mandatory fields + $result = $this->_validate($request_data); + + foreach($request_data as $field => $value) { + $this->invoice->$field = $value; + } + if(! array_keys($request_data,'date')) { + $this->invoice->date = dol_now(); + } + if( ! $this->invoice->create(DolibarrApiAccess::$user)) { + throw new RestException(500); + } + return $this->invoice->id; + } + + /** + * Update invoice Warning: Deprecated + * + * @param int $id Id of invoice to update + * @param array $request_data Datas + * @return int + * + * @url PUT invoice/{id} + */ + function put($id, $request_data = NULL) + { + if(! DolibarrApiAccess::$user->rights->facture->creer) { + throw new RestException(401); + } + + $result = $this->invoice->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Facture not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + foreach($request_data as $field => $value) { + $this->invoice->$field = $value; + } + + if($this->invoice->update($id, DolibarrApiAccess::$user)) + return $this->get ($id); + + return false; + } + + /** + * Delete invoice Warning: Deprecated + * + * @param int $id Invoice ID + * @return type + * + * @url DELETE invoice/{id} + */ + function delete($id) + { + if(! DolibarrApiAccess::$user->rights->facture->supprimer) { + throw new RestException(401); + } + $result = $this->invoice->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Facture not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('facture',$this->facture->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + if( !$this->invoice->delete($id)) + { + throw new RestException(500); + } + + return array( + 'success' => array( + 'code' => 200, + 'message' => 'Facture deleted' + ) + ); + + } + + /** + * Validate fields before create or update object + * + * @param array $data Datas to validate + * @return array + * + * @throws RestException + */ + function _validate($data) + { + $invoice = array(); + foreach (InvoiceApi::$FIELDS as $field) { + if (!isset($data[$field])) + throw new RestException(400, "$field field missing"); + $invoice[$field] = $data[$field]; + } + return $invoice; + } +} diff --git a/htdocs/product/class/api_deprecated_product.class.php b/htdocs/product/class/api_deprecated_product.class.php new file mode 100644 index 00000000000..784539230e5 --- /dev/null +++ b/htdocs/product/class/api_deprecated_product.class.php @@ -0,0 +1,359 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + use Luracast\Restler\RestException; + + require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; + require_once DOL_DOCUMENT_ROOT.'/categories/class/categorie.class.php'; + +/** + * API class for product object + * + * @smart-auto-routing false + * @access protected + * @class DolibarrApiAccess {@requires user,external} + * @deprecated + */ +class ProductApi extends DolibarrApi +{ + /** + * @var array $FIELDS Mandatory fields, checked when create and update object + */ + static $FIELDS = array( + 'ref', + 'label' + ); + + /** + * @var Product $product {@type Product} + */ + public $product; + + /** + * Constructor Warning: Deprecated + * + * @url product/ + * + */ + function __construct() + { + global $db, $conf; + $this->db = $db; + $this->product = new Product($this->db); + } + + /** + * Get properties of a product object Warning: Deprecated + * + * Return an array with product informations + * + * @param int $id ID of product + * @param string $ref Product ref + * @param string $ref_ext Product ref ext + * @return array|mixed data without useless information + * + * @url GET product/{id} + * @throws RestException + */ + function get($id='', $ref='', $ref_ext='') + { + if(! DolibarrApiAccess::$user->rights->produit->lire) { + throw new RestException(401); + } + + $result = $this->product->fetch($id,$ref,$ref_ext); + if( ! $result ) { + throw new RestException(404, 'Product not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('product',$this->product->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + $this->product->load_stock(); + + return $this->_cleanObjectDatas($this->product); + } + + /** + * List products Warning: Deprecated + * + * Get a list of products + * + * @param int $mode Use this param to filter list (0 for all, 1 for only product, 2 for only service) + * @param mixed $to_sell Filter products to sell (1) or not to sell (0) + * @param mixed $to_buy Filter products to nuy (1) or not to buy (0) + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * + * @return array Array of product objects + * + * @url GET /product/list + */ + function getList($mode=0, $to_sell='', $to_buy='', $sortfield = "p.ref", $sortorder = 'ASC', $limit = 0, $page = 0) { + global $db, $conf; + + $obj_ret = array(); + + $socid = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : ''; + + $sql ="SELECT rowid, ref, ref_ext"; + $sql.= " FROM ".MAIN_DB_PREFIX."product as p"; + $sql.= ' WHERE p.entity IN ('.getEntity('product', 1).')'; + + // Show products + if ($mode == 1) $sql.= " AND p.fk_product_type = 0"; + // Show services + if ($mode == 2) $sql.= " AND p.fk_product_type = 1"; + // Show product on sell + if ($to_sell) $sql.= " AND p.to_sell = ".$db->escape($to_sell); + // Show product on buy + if ($to_buy) $sql.= " AND p.to_nuy = ".$db->escape($to_nuy); + + $nbtotalofrecords = 0; + if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) + { + $result = $db->query($sql); + $nbtotalofrecords = $db->num_rows($result); + } + + $sql.= $db->order($sortfield, $sortorder); + if ($limit) { + if ($page < 0) + { + $page = 0; + } + $offset = $limit * $page; + + $sql.= $db->plimit($limit + 1, $offset); + } + + $result = $db->query($sql); + if ($result) + { + $num = $db->num_rows($result); + while ($i < $num) + { + $obj = $db->fetch_object($result); + $product_static = new Product($db); + if($product_static->fetch($obj->rowid)) { + $obj_ret[] = parent::_cleanObjectDatas($product_static); + } + $i++; + } + } + else { + throw new RestException(503, 'Error when retrieve product list'); + } + if( ! count($obj_ret)) { + throw new RestException(404, 'No product found'); + } + return $obj_ret; + } + + + /** + * List products in a category Warning: Deprecated + * + * Get a list of products + * + * @param int $mode Use this param to filter list (0 for all, 1 for only product, 2 for only service) + * @param int $category Use this param to filter list by category + * @param mixed $to_sell Filter products to sell (1) or not to sell (0) + * @param mixed $to_buy Filter products to nuy (1) or not to buy (0) + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * + * @return array Array of product objects + * + * @url GET /product/list/category/{category} + */ + function getByCategory($mode=0, $category=0, $to_sell='', $to_buy='', $sortfield = "p.ref", $sortorder = 'ASC', $limit = 0, $page = 0) { + global $db, $conf; + + $obj_ret = array(); + + $socid = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : ''; + + $sql = "SELECT rowid, ref, ref_ext"; + $sql.= " FROM ".MAIN_DB_PREFIX."product as p, "; + $sql.= MAIN_DB_PREFIX."categorie_product as c"; + $sql.= ' WHERE p.entity IN ('.getEntity('product', 1).')'; + + // Select products of given category + $sql.= " AND c.fk_categorie = ".$db->escape($category); + $sql.= " AND c.fk_product = p.rowid "; + + // Show products + if ($mode == 1) $sql.= " AND p.fk_product_type = 0"; + // Show services + if ($mode == 2) $sql.= " AND p.fk_product_type = 1"; + // Show product on sell + if ($to_sell) $sql.= " AND p.to_sell = ".$db->escape($to_sell); + // Show product on buy + if ($to_buy) $sql.= " AND p.to_nuy = ".$db->escape($to_nuy); + + $nbtotalofrecords = 0; + if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) + { + $result = $db->query($sql); + $nbtotalofrecords = $db->num_rows($result); + } + + $sql.= $db->order($sortfield, $sortorder); + if ($limit) { + if ($page < 0) + { + $page = 0; + } + $offset = $limit * $page; + + $sql.= $db->plimit($limit + 1, $offset); + } + + $result = $db->query($sql); + if ($result) + { + $num = $db->num_rows($result); + while ($i < $num) + { + $obj = $db->fetch_object($result); + $product_static = new Product($db); + if($product_static->fetch($obj->rowid)) { + $obj_ret[] = parent::_cleanObjectDatas($product_static); + } + $i++; + } + } + else { + throw new RestException(503, 'Error when retrieve product list'); + } + if( ! count($obj_ret)) { + throw new RestException(404, 'No product found'); + } + return $obj_ret; + } + + /** + * Create product object Warning: Deprecated + * + * @param array $request_data Request data + * @return int ID of product + * + * @url POST product/ + */ + function post($request_data = NULL) + { + if(! DolibarrApiAccess::$user->rights->produit->creer) { + throw new RestException(401); + } + // Check mandatory fields + $result = $this->_validate($request_data); + + foreach($request_data as $field => $value) { + $this->product->$field = $value; + } + $result = $this->product->create(DolibarrApiAccess::$user); + if($result < 0) { + throw new RestException(503,'Error when creating product : '.$this->product->error); + } + + return $this->product->id; + + } + + /** + * Update product Warning: Deprecated + * + * @param int $id Id of product to update + * @param array $request_data Datas + * @return int + * + * @url PUT product/{id} + */ + function put($id, $request_data = NULL) + { + if(! DolibarrApiAccess::$user->rights->produit->creer) { + throw new RestException(401); + } + + $result = $this->product->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Product not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('product',$this->product->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + foreach($request_data as $field => $value) { + $this->product->$field = $value; + } + + if($this->product->update($id, DolibarrApiAccess::$user,1,'','','update')) + return $this->get ($id); + + return false; + } + + /** + * Delete product Warning: Deprecated + * + * @param int $id Product ID + * @return array + * + * @url DELETE product/{id} + */ + function delete($id) + { + if(! DolibarrApiAccess::$user->rights->product->supprimer) { + throw new RestException(401); + } + $result = $this->product->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Product not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('product',$this->product->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + return $this->product->delete($id); + } + + /** + * Validate fields before create or update object + * + * @param array $data Datas to validate + * @return array + * @throws RestException + */ + function _validate($data) + { + $product = array(); + foreach (ProductApi::$FIELDS as $field) { + if (!isset($data[$field])) + throw new RestException(400, "$field field missing"); + $product[$field] = $data[$field]; + } + return $product; + } +} diff --git a/htdocs/societe/class/api_deprecated_contact.class.php b/htdocs/societe/class/api_deprecated_contact.class.php new file mode 100644 index 00000000000..c4b0c672e19 --- /dev/null +++ b/htdocs/societe/class/api_deprecated_contact.class.php @@ -0,0 +1,293 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use Luracast\Restler\RestException; + +//require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php'; + +/** + * API class for contact object + * + * @smart-auto-routing false + * @access protected + * @class DolibarrApiAccess {@requires user,external} + * @deprecated + */ +class ContactApi extends DolibarrApi +{ + /** + * + * @var array $FIELDS Mandatory fields, checked when create and update object + */ + static $FIELDS = array( + 'lastname' + ); + + /** + * @var Contact $contact {@type Contact} + */ + public $contact; + + /** + * Constructor Warning: Deprecated + * + * @url contact/ + * + */ + function __construct() { + global $db, $conf; + $this->db = $db; + $this->contact = new Contact($this->db); + } + + /** + * Get properties of a contact object Warning: Deprecated + * + * Return an array with contact informations + * + * @param int $id ID of contact + * @return array|mixed data without useless information + * + * @url GET contact/{id} + * @throws RestException + */ + function get($id) { + if (!DolibarrApiAccess::$user->rights->societe->contact->lire) + { + throw new RestException(401); + } + + $result = $this->contact->fetch($id); + if (!$result) + { + throw new RestException(404, 'Contact not found'); + } + + if (!DolibarrApi::_checkAccessToResource('contact', $this->contact->id, 'socpeople&societe')) + { + throw new RestException(401, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); + } + + return $this->_cleanObjectDatas($this->contact); + } + + /** + * List contacts Warning: Deprecated + * + * Get a list of contacts + * + * @param int $socid ID of thirdparty to filter list + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * @return array Array of contact objects + * + * @url GET /contact/list + * @url GET /contact/list/{socid} + * @url GET /thirdparty/{socid}/contacts + * @url GET /customer/{socid}/contacts + * + * @throws RestException + */ + function getList($socid = 0, $sortfield = "c.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { + global $db, $conf; + + $obj_ret = array(); + + if (!$socid) + { + $socid = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : ''; + } + + // If the internal user must only see his customers, force searching by him + if (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) + $search_sale = DolibarrApiAccess::$user->id; + + $sql = "SELECT c.rowid"; + $sql.= " FROM " . MAIN_DB_PREFIX . "socpeople as c"; + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) { + // We need this table joined to the select in order to filter by sale + $sql.= ", " . MAIN_DB_PREFIX . "societe_commerciaux as sc"; + } + $sql.= " LEFT JOIN " . MAIN_DB_PREFIX . "societe as s ON c.fk_soc = s.rowid"; + $sql.= ' WHERE c.entity IN (' . getEntity('contact', 1) . ')'; + if ($socid) + $sql.= " AND c.fk_soc = " . $socid; + + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) + $sql.= " AND c.fk_soc = sc.fk_soc"; + if ($search_sale > 0) + $sql.= " AND s.rowid = sc.fk_soc"; // Join for the needed table to filter by sale + + + + // Insert sale filter + if ($search_sale > 0) + { + $sql .= " AND sc.fk_user = " . $search_sale; + } + + $nbtotalofrecords = 0; + if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) + { + $result = $db->query($sql); + $nbtotalofrecords = $db->num_rows($result); + } + + $sql.= $db->order($sortfield, $sortorder); + + if ($limit) + { + if ($page < 0) + { + $page = 0; + } + $offset = $limit * $page; + + $sql.= $db->plimit($limit + 1, $offset); + } + $result = $db->query($sql); + if ($result) + { + $num = $db->num_rows($result); + while ($i < $num) + { + $obj = $db->fetch_object($result); + $contact_static = new Contact($db); + if ($contact_static->fetch($obj->rowid)) + { + $obj_ret[] = parent::_cleanObjectDatas($contact_static); + } + $i++; + } + } + else { + throw new RestException(503, 'Error when retreive contacts : ' . $sql); + } + if (!count($obj_ret)) + { + throw new RestException(404, 'Contacts not found'); + } + return $obj_ret; + } + + /** + * Create contact object Warning: Deprecated + * + * @param array $request_data Request datas + * @return int ID of contact + * + * @url POST contact/ + */ + function post($request_data = NULL) { + if (!DolibarrApiAccess::$user->rights->societe->contact->creer) + { + throw new RestException(401); + } + // Check mandatory fields + $result = $this->_validate($request_data); + + foreach ($request_data as $field => $value) + { + $this->contact->$field = $value; + } + return $this->contact->create(DolibarrApiAccess::$user); + } + + /** + * Update contact Warning: Deprecated + * + * @param int $id Id of contact to update + * @param array $request_data Datas + * @return int + * + * @url PUT contact/{id} + */ + function put($id, $request_data = NULL) { + if (!DolibarrApiAccess::$user->rights->societe->contact->creer) + { + throw new RestException(401); + } + + $result = $this->contact->fetch($id); + if (!$result) + { + throw new RestException(404, 'Contact not found'); + } + + if (!DolibarrApi::_checkAccessToResource('contact', $this->contact->id, 'socpeople&societe')) + { + throw new RestException(401, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); + } + + foreach ($request_data as $field => $value) + { + $this->contact->$field = $value; + } + + if ($this->contact->update($id, DolibarrApiAccess::$user, 1, '', '', 'update')) + return $this->get($id); + + return false; + } + + /** + * Delete contact Warning: Deprecated + * + * @param int $id Contact ID + * @return integer + * + * @url DELETE contact/{id} + */ + function delete($id) { + if (!DolibarrApiAccess::$user->rights->contact->supprimer) + { + throw new RestException(401); + } + $result = $this->contact->fetch($id); + if (!$result) + { + throw new RestException(404, 'Contact not found'); + } + + if (!DolibarrApi::_checkAccessToResource('contact', $this->contact->id, 'socpeople&societe')) + { + throw new RestException(401, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); + } + + return $this->contact->delete($id); + } + + /** + * Validate fields before create or update object + * + * @param array $data Data to validate + * @return array + * @throws RestException + */ + function _validate($data) { + $contact = array(); + foreach (ContactApi::$FIELDS as $field) + { + if (!isset($data[$field])) + throw new RestException(400, "$field field missing"); + $contact[$field] = $data[$field]; + } + return $contact; + } +} diff --git a/htdocs/societe/class/api_deprecated_thirdparty.class.php b/htdocs/societe/class/api_deprecated_thirdparty.class.php new file mode 100644 index 00000000000..5eb86405a5b --- /dev/null +++ b/htdocs/societe/class/api_deprecated_thirdparty.class.php @@ -0,0 +1,411 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + use Luracast\Restler\RestException; + + +/** + * API class for thirdparty object + * + * @smart-auto-routing false + * @access protected + * @class DolibarrApiAccess {@requires user,external} + * @deprecated + */ +class ThirdpartyApi extends DolibarrApi +{ + /** + * + * @var array $FIELDS Mandatory fields, checked when create and update object + */ + static $FIELDS = array( + 'name' + ); + + /** + * @var Societe $company {@type Societe} + */ + public $company; + /** + * @var Customer $customer {@type Client} + */ + public $customer; + + /** + * Constructor Warning: Deprecated + * + * @url thirdparty/ + * + */ + function __construct() + { + global $db, $conf; + $this->db = $db; + $this->company = new Societe($this->db); + $this->customer = new Client($this->db); + + if (! empty($conf->global->SOCIETE_MAIL_REQUIRED)) { + static::$FIELDS[] = 'email'; + } + } + + /** + * Get properties of a customer object Warning: Deprecated + * + * Return an array with customer informations + * + * @param int $id ID of customer + * @return array|mixed data without useless information + * + * @url GET customer/{id} + * @throws RestException + */ + function getCustomer($id) + { + if(! DolibarrApiAccess::$user->rights->societe->lire) { + throw new RestException(401); + } + + $result = $this->customer->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Customer not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('societe',$this->customer->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + return $this->_cleanObjectDatas($this->customer); + } + + /** + * Search customer by email Warning: Deprecated + * + * @param string $email email id + * + * @return object client with given email + * + * @url GET customer/byemail/{email} + */ + function getByEmail($email) { + $res = $this->getList(1,$email); + if (count($res) == 1) { + $customer = $res[0]; + return $customer; + } + return $res; + } + + /** + * Get properties of a thirdparty object Warning: Deprecated + * + * Return an array with thirdparty informations + * + * @param int $id ID of thirdparty + * @return array|mixed data without useless information + * + * @url GET thirdparty/{id} + * @throws RestException + */ + function get($id) + { + if(! DolibarrApiAccess::$user->rights->societe->lire) { + throw new RestException(401); + } + + $result = $this->company->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Thirdparty not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('societe',$this->company->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + return $this->_cleanObjectDatas($this->company); + } + + /** + * List thirdparties Warning: Deprecated + * + * Get a list of thirdparties + * + * @param int $mode Set to 1 to show only customers + * Set to 2 to show only prospects + * Set to 3 to show only those are not customer neither prospect + * @param Text $email Search by email filter + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * @param int $limit Limit for list + * @param int $page Page number + * @return array Array of thirdparty objects + * + * @url GET /thirdparty/list + * + */ + function getList($mode=0, $email=NULL, $sortfield = "s.rowid", $sortorder = 'ASC', $limit = 0, $page = 0) { + global $db, $conf; + + $obj_ret = array(); + + $socid = DolibarrApiAccess::$user->societe_id ? DolibarrApiAccess::$user->societe_id : ''; + + // If the internal user must only see his customers, force searching by him + if (! DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) $search_sale = DolibarrApiAccess::$user->id; + + $sql = "SELECT s.rowid"; + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects) + $sql.= " FROM ".MAIN_DB_PREFIX."societe as s"; + + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale + $sql.= ", ".MAIN_DB_PREFIX."c_stcomm as st"; + $sql.= " WHERE s.fk_stcomm = st.id"; + if ($mode == 1) $sql.= " AND s.client IN (1, 3)"; + if ($mode == 2) $sql.= " AND s.client IN (2, 3)"; + if ($mode == 3) $sql.= " AND s.client IN (0)"; + $sql.= ' AND s.entity IN ('.getEntity('societe', 1).')'; + if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socid) || $search_sale > 0) $sql.= " AND s.rowid = sc.fk_soc"; + if ($email != NULL) $sql.= " AND s.email = \"".$email."\""; + if ($socid) $sql.= " AND s.rowid = ".$socid; + if ($search_sale > 0) $sql.= " AND s.rowid = sc.fk_soc"; // Join for the needed table to filter by sale + + // Insert sale filter + if ($search_sale > 0) + { + $sql .= " AND sc.fk_user = ".$search_sale; + } + + $nbtotalofrecords = 0; + if (empty($conf->global->MAIN_DISABLE_FULL_SCANLIST)) + { + $result = $db->query($sql); + $nbtotalofrecords = $db->num_rows($result); + } + + $sql.= $db->order($sortfield, $sortorder); + + if ($limit) { + if ($page < 0) + { + $page = 0; + } + $offset = $limit * $page; + + $sql.= $db->plimit($limit + 1, $offset); + } + + $result = $db->query($sql); + if ($result) + { + $num = $db->num_rows($result); + while ($i < $num) + { + $obj = $db->fetch_object($result); + $soc_static = new Societe($db); + if($soc_static->fetch($obj->rowid)) { + $obj_ret[] = parent::_cleanObjectDatas($soc_static); + } + $i++; + } + } + else { + throw new RestException(503, 'Error when retrieve thirdparties : ' . $sql); + } + if( ! count($obj_ret)) { + throw new RestException(404, 'Thirdparties not found'); + } + return $obj_ret; + } + + /** + * Show customers Warning: Deprecated + * + * @return array List of customers + * + * @url GET /thirdparty/list/customers + * @url GET /customer/list + */ + function getListCustomers() { + return $this->getList(1); + } + + /** + * Show prospects Warning: Deprecated + * + * @return array List of prospects + * + * @url GET /thirdparty/list/prospects + */ + function getListProspects() { + return $this->getList(2); + } + + /** + * Show other Warning: Deprecated + * + * @return array List of thirpdparties who are not customer neither prospect + * + * @url GET /thirdparty/list/others + */ + function getListOthers() { + return $this->getList(3); + } + + /** + * Create thirdparty object Warning: Deprecated + * + * @param array $request_data Request datas + * @return int ID of thirdparty + * + * @url POST thirdparty/ + */ + function post($request_data = NULL) + { + if(! DolibarrApiAccess::$user->rights->societe->creer) { + throw new RestException(401); + } + // Check mandatory fields + $result = $this->_validate($request_data); + + foreach($request_data as $field => $value) { + $this->company->$field = $value; + } + return $this->company->create(DolibarrApiAccess::$user); + } + + + /** + * Create customer object Warning: Deprecated + * + * @param array $request_data Request datas + * @return int ID of thirdparty + * + * @url POST customer/ + */ + function postCustomer($request_data) { + $this->post($request_data); + $this->company->set_as_client(); + return $this->company->id; + } + + /** + * Update thirdparty Warning: Deprecated + * + * @param int $id Id of thirdparty to update + * @param array $request_data Datas + * @return int + * + * @url PUT thirdparty/{id} + */ + function put($id, $request_data = NULL) + { + if(! DolibarrApiAccess::$user->rights->societe->creer) { + throw new RestException(401); + } + + $result = $this->company->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Thirdparty not found'); + } + + if( ! DolibarrApi::_checkAccessToResource('societe',$this->company->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + foreach($request_data as $field => $value) { + $this->company->$field = $value; + } + + if($this->company->update($id, DolibarrApiAccess::$user,1,'','','update')) + return $this->get ($id); + + return false; + } + /** + * Update customer Warning: Deprecated + * + * @param int $id Id of thirdparty to update + * @param array $request_data Datas + * @return int + * + * @url PUT customer/{id} + */ + function putClient($id, $request_data = NULL) { + if(! DolibarrApiAccess::$user->rights->societe->creer) { + throw new RestException(401); + } + $result = $this->customer->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Customer not found'); + } + if( ! DolibarrApi::_checkAccessToResource('societe',$this->customer->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + foreach($request_data as $field => $value) { + $this->customer->$field = $value; + } + + if($this->customer->update($id, DolibarrApiAccess::$user,1,'','','update')) + return $this->get ($id); + + return false; + } + + /** + * Delete thirdparty Warning: Deprecated + * + * @param int $id Thirparty ID + * @return integer + * + * @url DELETE thirdparty/{id} + * @url DELETE customer/{id} + */ + function delete($id) + { + if(! DolibarrApiAccess::$user->rights->societe->supprimer) { + throw new RestException(401); + } + $result = $this->company->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Thirdparty not found'); + } + if( ! DolibarrApi::_checkAccessToResource('societe',$this->company->id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + return $this->company->delete($id); + } + + /** + * Validate fields before create or update object + * + * @param array $data Datas to validate + * @return array + * + * @throws RestException + */ + function _validate($data) + { + $thirdparty = array(); + foreach (ThirdpartyApi::$FIELDS as $field) { + if (!isset($data[$field])) + throw new RestException(400, "$field field missing"); + $thirdparty[$field] = $data[$field]; + } + return $thirdparty; + } +} diff --git a/htdocs/user/class/api_deprecated_user.class.php b/htdocs/user/class/api_deprecated_user.class.php new file mode 100644 index 00000000000..5c5e7abaca6 --- /dev/null +++ b/htdocs/user/class/api_deprecated_user.class.php @@ -0,0 +1,273 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +use Luracast\Restler\RestException; + +//require_once DOL_DOCUMENT_ROOT . '/contact/class/contact.class.php'; + +/** + * API class for user object + * + * @smart-auto-routing false + * @access protected + * @class DolibarrApiAccess {@requires user,external} + * @deprecated + */ +class UserApi extends DolibarrApi +{ + /** + * + * @var array $FIELDS Mandatory fields, checked when create and update object + */ + static $FIELDS = array( + 'login' + ); + + /** + * @var User $user {@type User} + */ + public $useraccount; + + /** + * Constructor Warning: Deprecated + * + * @url user/ + * + */ + function __construct() { + global $db, $conf; + $this->db = $db; + $this->useraccount = new User($this->db); + } + + /** + * Get properties of an user object Warning: Deprecated + * + * Return an array with user informations + * + * @param int $id ID of user + * @return array|mixed data without useless information + * + * @url GET user/{id} + * @throws RestException + */ + function get($id) { + //if (!DolibarrApiAccess::$user->rights->user->user->lire) { + //throw new RestException(401); + //} + + $result = $this->useraccount->fetch($id); + if (!$result) + { + throw new RestException(404, 'User not found'); + } + + if (!DolibarrApi::_checkAccessToResource('user', $this->useraccount->id, 'user')) + { + throw new RestException(401, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); + } + + return $this->_cleanObjectDatas($this->useraccount); + } + + /** + * Create useraccount object from contact Warning: Deprecated + * + * @param int $contactid Id of contact + * @param array $request_data Request datas + * @return int ID of user + * + * @url POST /contact/{contactid}/createUser + */ + function createFromContact($contactid, $request_data = NULL) { + //if (!DolibarrApiAccess::$user->rights->user->user->creer) { + //throw new RestException(401); + //} + + if (!isset($request_data["login"])) + throw new RestException(400, "login field missing"); + if (!isset($request_data["password"])) + throw new RestException(400, "password field missing"); + if (!DolibarrApiAccess::$user->rights->societe->contact->lire) { + throw new RestException(401); + } + $contact = new Contact($this->db); + $contact->fetch($contactid); + if ($contact->id <= 0) { + throw new RestException(404, 'Contact not found'); + } + + if (!DolibarrApi::_checkAccessToResource('contact', $contact->id, 'socpeople&societe')) { + throw new RestException(401, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); + } + // Check mandatory fields + $login = $request_data["login"]; + $password = $request_data["password"]; + $result = $this->useraccount->create_from_contact($contact,$login,$password); + if ($result <= 0) { + throw new RestException(500, "User not created"); + } + // password parameter not used in create_from_contact + $this->useraccount->setPassword($this->useraccount,$password); + + return $result; + } + + + /** + * Create user account Warning: Deprecated + * + * @param array $request_data New user data + * @return int + * + * @url POST user/ + */ + function post($request_data = NULL) { + // check user authorization + //if(! DolibarrApiAccess::$user->rights->user->creer) { + // throw new RestException(401, "User creation not allowed"); + //} + // check mandatory fields + /*if (!isset($request_data["login"])) + throw new RestException(400, "login field missing"); + if (!isset($request_data["password"])) + throw new RestException(400, "password field missing"); + if (!isset($request_data["lastname"])) + throw new RestException(400, "lastname field missing");*/ + //assign field values + $xxx=var_export($request_data, true); + dol_syslog("xxx=".$xxx); + foreach ($request_data as $field => $value) + { + $this->useraccount->$field = $value; + } + + $result = $this->useraccount->create(DolibarrApiAccess::$user); + if ($result <=0) { + throw new RestException(500, "User not created : ".$this->useraccount->error); + } + return array('id'=>$result); + } + + + /** + * Update account Warning: Deprecated + * + * @param int $id Id of account to update + * @param array $request_data Datas + * @return int + * + * @url PUT user/{id} + */ + function put($id, $request_data = NULL) { + //if (!DolibarrApiAccess::$user->rights->user->user->creer) { + //throw new RestException(401); + //} + + $result = $this->useraccount->fetch($id); + if (!$result) + { + throw new RestException(404, 'Account not found'); + } + + if (!DolibarrApi::_checkAccessToResource('user', $this->useraccount->id, 'user')) + { + throw new RestException(401, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); + } + + foreach ($request_data as $field => $value) + { + $this->useraccount->$field = $value; + } + + if ($this->useraccount->update($id, DolibarrApiAccess::$user, 1, '', '', 'update')) + return $this->get($id); + + return false; + } + + /** + * add user to group Warning: Deprecated + * + * @param int $id User ID + * @param int $group Group ID + * @return int + * + * @url GET user/{id}/setGroup/{group} + */ + function setGroup($id,$group) { + //if (!DolibarrApiAccess::$user->rights->user->user->supprimer) { + //throw new RestException(401); + //} + $result = $this->useraccount->fetch($id); + if (!$result) + { + throw new RestException(404, 'User not found'); + } + + if (!DolibarrApi::_checkAccessToResource('user', $this->useraccount->id, 'user')) + { + throw new RestException(401, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); + } + + return $this->useraccount->SetInGroup($group,1); + } + + /** + * Delete account Warning: Deprecated + * + * @param int $id Account ID + * @return array + * + * @url DELETE user/{id} + */ + function delete($id) { + //if (!DolibarrApiAccess::$user->rights->user->user->supprimer) { + //throw new RestException(401); + //} + $result = $this->useraccount->fetch($id); + if (!$result) + { + throw new RestException(404, 'User not found'); + } + + if (!DolibarrApi::_checkAccessToResource('user', $this->useraccount->id, 'user')) + { + throw new RestException(401, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); + } + + return $this->useraccount->delete($id); + } + + /** + * Validate fields before create or update object + * + * @param array $data Data to validate + * @return array + * @throws RestException + */ + function _validate($data) { + $account = array(); + foreach (UserApi::$FIELDS as $field) + { + if (!isset($data[$field])) + throw new RestException(400, "$field field missing"); + $account[$field] = $data[$field]; + } + return $account; + } +} From e12e1980fc0fee26b231600e73e349d478040074 Mon Sep 17 00:00:00 2001 From: Xebax Date: Wed, 22 Jun 2016 10:43:35 +0200 Subject: [PATCH 23/23] REST API: Add comments in the @deprecated tags. --- htdocs/categories/class/api_deprecated_category.class.php | 2 +- htdocs/commande/class/api_deprecated_commande.class.php | 2 +- htdocs/compta/facture/class/api_deprecated_invoice.class.php | 2 +- htdocs/product/class/api_deprecated_product.class.php | 2 +- htdocs/societe/class/api_deprecated_contact.class.php | 2 +- htdocs/societe/class/api_deprecated_thirdparty.class.php | 2 +- htdocs/user/class/api_deprecated_user.class.php | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/htdocs/categories/class/api_deprecated_category.class.php b/htdocs/categories/class/api_deprecated_category.class.php index c6a52f72035..656c769bed3 100644 --- a/htdocs/categories/class/api_deprecated_category.class.php +++ b/htdocs/categories/class/api_deprecated_category.class.php @@ -27,7 +27,7 @@ * @access protected * @class DolibarrApiAccess {@requires user,external} * - * @deprecated + * @deprecated Use Categories instead (defined in api_categories.class.php) */ class CategoryApi extends DolibarrApi { diff --git a/htdocs/commande/class/api_deprecated_commande.class.php b/htdocs/commande/class/api_deprecated_commande.class.php index 557682b8cf7..2a8caf5321e 100644 --- a/htdocs/commande/class/api_deprecated_commande.class.php +++ b/htdocs/commande/class/api_deprecated_commande.class.php @@ -29,7 +29,7 @@ * @category Api * @package Api * - * @deprecated + * @deprecated Use Orders instead (defined in api_orders.class.php) */ class CommandeApi extends DolibarrApi { diff --git a/htdocs/compta/facture/class/api_deprecated_invoice.class.php b/htdocs/compta/facture/class/api_deprecated_invoice.class.php index 2ba4873fe8f..99fe0d7fe52 100644 --- a/htdocs/compta/facture/class/api_deprecated_invoice.class.php +++ b/htdocs/compta/facture/class/api_deprecated_invoice.class.php @@ -25,7 +25,7 @@ * @smart-auto-routing false * @access protected * @class DolibarrApiAccess {@requires user,external} - * @deprecated + * @deprecated Use Invoices instead (defined in api_invoices.class.php) */ class InvoiceApi extends DolibarrApi { diff --git a/htdocs/product/class/api_deprecated_product.class.php b/htdocs/product/class/api_deprecated_product.class.php index 784539230e5..4efa2ef5502 100644 --- a/htdocs/product/class/api_deprecated_product.class.php +++ b/htdocs/product/class/api_deprecated_product.class.php @@ -26,7 +26,7 @@ * @smart-auto-routing false * @access protected * @class DolibarrApiAccess {@requires user,external} - * @deprecated + * @deprecated Use Products instead (defined in api_products.class.php) */ class ProductApi extends DolibarrApi { diff --git a/htdocs/societe/class/api_deprecated_contact.class.php b/htdocs/societe/class/api_deprecated_contact.class.php index c4b0c672e19..9509e276f32 100644 --- a/htdocs/societe/class/api_deprecated_contact.class.php +++ b/htdocs/societe/class/api_deprecated_contact.class.php @@ -25,7 +25,7 @@ use Luracast\Restler\RestException; * @smart-auto-routing false * @access protected * @class DolibarrApiAccess {@requires user,external} - * @deprecated + * @deprecated Use Contacts instead (defined in api_contacts.class.php) */ class ContactApi extends DolibarrApi { diff --git a/htdocs/societe/class/api_deprecated_thirdparty.class.php b/htdocs/societe/class/api_deprecated_thirdparty.class.php index 5eb86405a5b..db270142972 100644 --- a/htdocs/societe/class/api_deprecated_thirdparty.class.php +++ b/htdocs/societe/class/api_deprecated_thirdparty.class.php @@ -24,7 +24,7 @@ * @smart-auto-routing false * @access protected * @class DolibarrApiAccess {@requires user,external} - * @deprecated + * @deprecated Use Thirdparties instead (defined in api_thirdparties.class.php) */ class ThirdpartyApi extends DolibarrApi { diff --git a/htdocs/user/class/api_deprecated_user.class.php b/htdocs/user/class/api_deprecated_user.class.php index 5c5e7abaca6..c9fcb2b0dd7 100644 --- a/htdocs/user/class/api_deprecated_user.class.php +++ b/htdocs/user/class/api_deprecated_user.class.php @@ -25,7 +25,7 @@ use Luracast\Restler\RestException; * @smart-auto-routing false * @access protected * @class DolibarrApiAccess {@requires user,external} - * @deprecated + * @deprecated Use Users instead (defined in api_users.class.php) */ class UserApi extends DolibarrApi {