mirror of
https://github.com/Dolibarr/dolibarr.git
synced 2026-02-13 19:25:22 +01:00
Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into develop
This commit is contained in:
@@ -49,8 +49,10 @@ repos:
|
||||
hooks:
|
||||
- id: php-cbf
|
||||
files: \.(php)$
|
||||
args: [--standard=dev/setup/codesniffer/ruleset.xml, -p]
|
||||
args: [--standard=dev/setup/codesniffer/ruleset.xml -p]
|
||||
- id: php-cs
|
||||
files: \.(php)$
|
||||
args: [--standard=dev/setup/codesniffer/ruleset.xml -p]
|
||||
- id: php-lint
|
||||
|
||||
# Prettier (format code, only for non common files)
|
||||
|
||||
@@ -11,10 +11,22 @@
|
||||
# ```shell
|
||||
# echo > dev/tools/codespell/codespell-lines-ignore.txt
|
||||
# ```
|
||||
# and then execute this script
|
||||
# and then execute this script.
|
||||
#
|
||||
# author: https://github.com/mdeweerd
|
||||
|
||||
#
|
||||
# :warning:
|
||||
#
|
||||
# This script only works properly if codespell is install for your CLI.
|
||||
# As the configuration is in pyproject.toml, you also need tomli.
|
||||
#
|
||||
# ```shell
|
||||
# python -m pip install codespell tomli
|
||||
# # or
|
||||
# pip install codespell tomli
|
||||
# ```
|
||||
|
||||
codespell_ignore_file=dev/tools/codespell/codespell-lines-ignore.txt
|
||||
if [ -z "${0##*.sh}" ] ; then
|
||||
# Suppose running from inside script
|
||||
|
||||
@@ -323,7 +323,7 @@ if (empty($reshook)) {
|
||||
}
|
||||
$object->birth = $birthdate;
|
||||
$object->default_lang = GETPOST('default_lang', 'alpha');
|
||||
$object->typeid = GETPOST("typeid", 'int');
|
||||
$object->typeid = GETPOSTINT("typeid");
|
||||
//$object->note = trim(GETPOST("comment", "restricthtml"));
|
||||
$object->morphy = GETPOST("morphy", 'alpha');
|
||||
|
||||
@@ -1118,7 +1118,7 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
|
||||
|
||||
// Birth Date
|
||||
print "<tr><td>".$langs->trans("DateOfBirth")."</td><td>\n";
|
||||
print $form->selectDate(($object->birth ? $object->birth : -1), 'birth', '', '', 1, 'formsoc');
|
||||
print img_picto('', 'object_calendar', 'class="pictofixedwidth"').$form->selectDate(($object->birth ? $object->birth : -1), 'birth', '', '', 1, 'formsoc');
|
||||
print "</td></tr>\n";
|
||||
|
||||
// Public profil
|
||||
@@ -1364,13 +1364,13 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) {
|
||||
|
||||
// Birth Date
|
||||
print "<tr><td>".$langs->trans("DateOfBirth")."</td><td>\n";
|
||||
print $form->selectDate(($object->birth ? $object->birth : -1), 'birth', '', '', 1, 'formsoc');
|
||||
print img_picto('', 'object_calendar', 'class="pictofixedwidth"').$form->selectDate(($object->birth ? $object->birth : -1), 'birth', '', '', 1, 'formsoc');
|
||||
print "</td></tr>\n";
|
||||
|
||||
// Default language
|
||||
if (getDolGlobalInt('MAIN_MULTILANGS')) {
|
||||
print '<tr><td>'.$form->editfieldkey('DefaultLang', 'default_lang', '', $object, 0).'</td><td colspan="3">'."\n";
|
||||
print img_picto('', 'language').$formadmin->select_language($object->default_lang, 'default_lang', 0, 0, 1);
|
||||
print img_picto('', 'language', 'class="pictofixedwidth"').$formadmin->select_language($object->default_lang, 'default_lang', 0, 0, 1);
|
||||
print '</td>';
|
||||
print '</tr>';
|
||||
}
|
||||
|
||||
14
htdocs/ai/README.md
Normal file
14
htdocs/ai/README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# AI FOR [DOLIBARR ERP CRM](https://www.dolibarr.org)
|
||||
|
||||
## Features
|
||||
|
||||
Provides an api key for chatchpt for use it in other modules
|
||||
|
||||
|
||||
### Main code
|
||||
|
||||
GPLv3 or (at your option) any later version. See file COPYING for more information.
|
||||
|
||||
### Documentation
|
||||
|
||||
All texts and readmes are licensed under GFDL.
|
||||
239
htdocs/ai/admin/setup.php
Normal file
239
htdocs/ai/admin/setup.php
Normal file
@@ -0,0 +1,239 @@
|
||||
<?php
|
||||
/* Copyright (C) 2004-2017 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2022 Alice Adminson <aadminson@example.com>
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file ai/admin/setup.php
|
||||
* \ingroup ai
|
||||
* \brief Ai setup page.
|
||||
*/
|
||||
|
||||
// Load Dolibarr environment
|
||||
require '../../main.inc.php';
|
||||
|
||||
global $langs, $user;
|
||||
|
||||
// Libraries
|
||||
require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php";
|
||||
require_once '../lib/ai.lib.php';
|
||||
|
||||
// Access control
|
||||
if (!$user->admin) {
|
||||
accessforbidden();
|
||||
}
|
||||
|
||||
// Parameters
|
||||
$action = GETPOST('action', 'aZ09');
|
||||
$backtopage = GETPOST('backtopage', 'alpha');
|
||||
$modulepart = GETPOST('modulepart', 'aZ09'); // Used by actions_setmoduleoptions.inc.php
|
||||
|
||||
$value = GETPOST('value', 'alpha');
|
||||
$label = GETPOST('label', 'alpha');
|
||||
$scandir = GETPOST('scan_dir', 'alpha');
|
||||
$type = 'myobject';
|
||||
|
||||
|
||||
$error = 0;
|
||||
$setupnotempty = 0;
|
||||
|
||||
// Set this to 1 to use the factory to manage constants. Warning, the generated module will be compatible with version v15+ only
|
||||
$useFormSetup = 1;
|
||||
|
||||
if (!class_exists('FormSetup')) {
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formsetup.class.php';
|
||||
}
|
||||
|
||||
$formSetup = new FormSetup($db);
|
||||
|
||||
// Setup conf AI_PUBLIC_INTERFACE_TOPIC
|
||||
$item = $formSetup->newItem('AI_KEY_API_CHATGPT');
|
||||
$item->defaultFieldValue = '';
|
||||
|
||||
|
||||
// Save API Key
|
||||
if ($_SERVER["REQUEST_METHOD"] == "POST") {
|
||||
$apiKey = GETPOST('api_key', 'alpha');
|
||||
// Validate and clean $apiKey here
|
||||
dolibarr_set_const($db, 'MAIN_AI_CHATGPT_API_KEY', $apiKey, 'chaine', 0, '', $conf->entity);
|
||||
}
|
||||
|
||||
// Retrieve existing API Key
|
||||
$apiKey = dolibarr_get_const($db, 'MAIN_AI_CHATGPT_API_KEY');
|
||||
|
||||
$setupnotempty =+ count($formSetup->items);
|
||||
|
||||
|
||||
$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
|
||||
|
||||
|
||||
/*
|
||||
* Actions
|
||||
*/
|
||||
|
||||
// For retrocompatibility Dolibarr < 15.0
|
||||
if (versioncompare(explode('.', DOL_VERSION), array(15)) < 0 && $action == 'update' && !empty($user->admin)) {
|
||||
$formSetup->saveConfFromPost();
|
||||
}
|
||||
|
||||
include DOL_DOCUMENT_ROOT.'/core/actions_setmoduleoptions.inc.php';
|
||||
|
||||
if ($action == 'updateMask') {
|
||||
$maskconst = GETPOST('maskconst', 'aZ09');
|
||||
$maskvalue = GETPOST('maskvalue', 'alpha');
|
||||
|
||||
if ($maskconst && preg_match('/_MASK$/', $maskconst)) {
|
||||
$res = dolibarr_set_const($db, $maskconst, $maskvalue, 'chaine', 0, '', $conf->entity);
|
||||
if (!($res > 0)) {
|
||||
$error++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$error) {
|
||||
setEventMessages($langs->trans("SetupSaved"), null, 'mesgs');
|
||||
} else {
|
||||
setEventMessages($langs->trans("Error"), null, 'errors');
|
||||
}
|
||||
} elseif ($action == 'specimen') {
|
||||
$modele = GETPOST('module', 'alpha');
|
||||
$tmpobjectkey = GETPOST('object');
|
||||
|
||||
$tmpobject = new $tmpobjectkey($db);
|
||||
$tmpobject->initAsSpecimen();
|
||||
|
||||
// Search template files
|
||||
$file = '';
|
||||
$classname = '';
|
||||
$filefound = 0;
|
||||
$dirmodels = array_merge(array('/'), (array) $conf->modules_parts['models']);
|
||||
foreach ($dirmodels as $reldir) {
|
||||
$file = dol_buildpath($reldir."core/modules/ai/doc/pdf_".$modele."_".strtolower($tmpobjectkey).".modules.php", 0);
|
||||
if (file_exists($file)) {
|
||||
$filefound = 1;
|
||||
$classname = "pdf_".$modele."_".strtolower($tmpobjectkey);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($filefound) {
|
||||
require_once $file;
|
||||
|
||||
$module = new $classname($db);
|
||||
|
||||
if ($module->write_file($tmpobject, $langs) > 0) {
|
||||
header("Location: ".DOL_URL_ROOT."/document.php?modulepart=bookcal-".strtolower($tmpobjectkey)."&file=SPECIMEN.pdf");
|
||||
return;
|
||||
} else {
|
||||
setEventMessages($module->error, null, 'errors');
|
||||
dol_syslog($module->error, LOG_ERR);
|
||||
}
|
||||
} else {
|
||||
setEventMessages($langs->trans("ErrorModuleNotFound"), null, 'errors');
|
||||
dol_syslog($langs->trans("ErrorModuleNotFound"), LOG_ERR);
|
||||
}
|
||||
} elseif ($action == 'setmod') {
|
||||
// TODO Check if numbering module chosen can be activated by calling method canBeActivated
|
||||
$tmpobjectkey = GETPOST('object');
|
||||
if (!empty($tmpobjectkey)) {
|
||||
$constforval = 'Ai_'.strtoupper($tmpobjectkey)."_ADDON";
|
||||
dolibarr_set_const($db, $constforval, $value, 'chaine', 0, '', $conf->entity);
|
||||
}
|
||||
} elseif ($action == 'set') {
|
||||
// Activate a model
|
||||
$ret = addDocumentModel($value, $type, $label, $scandir);
|
||||
} elseif ($action == 'del') {
|
||||
$ret = delDocumentModel($value, $type);
|
||||
if ($ret > 0) {
|
||||
$tmpobjectkey = GETPOST('object');
|
||||
if (!empty($tmpobjectkey)) {
|
||||
$constforval = 'Ai_'.strtoupper($tmpobjectkey).'_ADDON_PDF';
|
||||
if (getDolGlobalString($constforval) == "$value") {
|
||||
dolibarr_del_const($db, $constforval, $conf->entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
} elseif ($action == 'setdoc') {
|
||||
// Set or unset default model
|
||||
$tmpobjectkey = GETPOST('object');
|
||||
if (!empty($tmpobjectkey)) {
|
||||
$constforval = 'Ai_'.strtoupper($tmpobjectkey).'_ADDON_PDF';
|
||||
if (dolibarr_set_const($db, $constforval, $value, 'chaine', 0, '', $conf->entity)) {
|
||||
// The constant that was read before the new set
|
||||
// We therefore requires a variable to have a coherent view
|
||||
$conf->global->$constforval = $value;
|
||||
}
|
||||
|
||||
// We disable/enable the document template (into llx_document_model table)
|
||||
$ret = delDocumentModel($value, $type);
|
||||
if ($ret > 0) {
|
||||
$ret = addDocumentModel($value, $type, $label, $scandir);
|
||||
}
|
||||
}
|
||||
} elseif ($action == 'unsetdoc') {
|
||||
$tmpobjectkey = GETPOST('object');
|
||||
if (!empty($tmpobjectkey)) {
|
||||
$constforval = 'Ai_'.strtoupper($tmpobjectkey).'_ADDON_PDF';
|
||||
dolibarr_del_const($db, $constforval, $conf->entity);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* View
|
||||
*/
|
||||
|
||||
$form = new Form($db);
|
||||
|
||||
$help_url = '';
|
||||
$page_name = "AiSetup";
|
||||
|
||||
llxHeader('', $langs->trans($page_name), $help_url);
|
||||
|
||||
// Subheader
|
||||
$linkback = '<a href="'.($backtopage ? $backtopage : DOL_URL_ROOT.'/admin/modules.php?restore_lastsearch_values=1').'">'.$langs->trans("BackToModuleList").'</a>';
|
||||
|
||||
print load_fiche_titre($langs->trans($page_name), $linkback, 'title_setup');
|
||||
|
||||
// Configuration header
|
||||
$head = aiAdminPrepareHead();
|
||||
print dol_get_fiche_head($head, 'settings', $langs->trans($page_name), -1, "fa-microchip");
|
||||
|
||||
// Setup page goes here
|
||||
//echo '<span class="opacitymedium">'.$langs->trans("AiSetupPage").'</span><br><br>';
|
||||
|
||||
|
||||
if ($action == 'edit') {
|
||||
print $formSetup->generateOutput(true);
|
||||
print '<br>';
|
||||
} elseif (!empty($formSetup->items)) {
|
||||
print $formSetup->generateOutput();
|
||||
print '<div class="tabsAction">';
|
||||
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?action=edit&token='.newToken().'">'.$langs->trans("Modify").'</a>';
|
||||
print '</div>';
|
||||
} else {
|
||||
print '<br>'.$langs->trans("NothingToSetup");
|
||||
}
|
||||
|
||||
|
||||
if (empty($setupnotempty)) {
|
||||
print '<br>'.$langs->trans("NothingToSetup");
|
||||
}
|
||||
|
||||
// Page end
|
||||
print dol_get_fiche_end();
|
||||
|
||||
llxFooter();
|
||||
$db->close();
|
||||
90
htdocs/ai/class/ai.class.php
Normal file
90
htdocs/ai/class/ai.class.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/* Copyright (C) 2008-2011 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2005-2016 Regis Houssin <regis.houssin@inodbox.com>
|
||||
* Copyright (C) 2012 J. Fernando Lagrange <fernando@demo-tic.org>
|
||||
* Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
|
||||
* Copyright (C) 2023 Eric Seigne <eric.seigne@cap-rel.fr>
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
* or see https://www.gnu.org/
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class for AI
|
||||
*/
|
||||
class Ai
|
||||
{
|
||||
|
||||
/**
|
||||
* @var DoliDB $db Database object
|
||||
*/
|
||||
protected $db;
|
||||
/**
|
||||
* @var string $apiEndpoint
|
||||
*/
|
||||
private $apiEndpoint;
|
||||
|
||||
/**
|
||||
* @var string $apiKey
|
||||
*/
|
||||
private $apiKey;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $apiEndpoint Endpoint of api
|
||||
* @param boolean $apiKey key of api
|
||||
*/
|
||||
public function __construct($apiEndpoint, $apiKey)
|
||||
{
|
||||
$this->apiEndpoint = $apiEndpoint;
|
||||
$this->apiKey = $apiKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate response of instructions
|
||||
* @param string $instructions instruction for generate content
|
||||
* @return mixed $response
|
||||
*/
|
||||
public function generateContent($instructions)
|
||||
{
|
||||
try {
|
||||
$ch = curl_init($this->apiEndpoint);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode(['prompt' => $instructions]));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Authorization: Bearer ' . $this->apiKey,
|
||||
'Content-Type: application/json'
|
||||
]);
|
||||
|
||||
$response = curl_exec($ch);
|
||||
|
||||
if (curl_errno($ch)) {
|
||||
throw new Exception('cURL error: ' . curl_error($ch));
|
||||
}
|
||||
|
||||
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||
if ($statusCode != 200) {
|
||||
throw new Exception('API request failed with status code ' . $statusCode);
|
||||
}
|
||||
|
||||
return $response;
|
||||
} catch (Exception $e) {
|
||||
error_log($e->getMessage());
|
||||
return null;
|
||||
} finally {
|
||||
curl_close($ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
63
htdocs/ai/lib/ai.lib.php
Normal file
63
htdocs/ai/lib/ai.lib.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/* Copyright (C) 2022 Alice Adminson <aadminson@example.com>
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file ai/lib/ai.lib.php
|
||||
* \ingroup ai
|
||||
* \brief Library files with common functions for Ai
|
||||
*/
|
||||
|
||||
/**
|
||||
* Prepare admin pages header
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function aiAdminPrepareHead()
|
||||
{
|
||||
global $langs, $conf;
|
||||
|
||||
$langs->load("agenda");
|
||||
|
||||
$h = 0;
|
||||
$head = array();
|
||||
|
||||
$head[$h][0] = dol_buildpath("/ai/admin/setup.php", 1);
|
||||
$head[$h][1] = $langs->trans("Settings");
|
||||
$head[$h][2] = 'settings';
|
||||
$h++;
|
||||
|
||||
/*
|
||||
$head[$h][0] = dol_buildpath("/ai/admin/myobject_extrafields.php", 1);
|
||||
$head[$h][1] = $langs->trans("ExtraFields");
|
||||
$head[$h][2] = 'myobject_extrafields';
|
||||
$h++;
|
||||
*/
|
||||
|
||||
// Show more tabs from modules
|
||||
// Entries must be declared in modules descriptor with line
|
||||
//$this->tabs = array(
|
||||
// 'entity:+tabname:Title:@ai:/ai/mypage.php?id=__ID__'
|
||||
//); // to add new tab
|
||||
//$this->tabs = array(
|
||||
// 'entity:-tabname:Title:@ai:/ai/mypage.php?id=__ID__'
|
||||
//); // to remove a tab
|
||||
complete_head_from_modules($conf, $langs, null, $head, $h, 'ai@ai');
|
||||
|
||||
complete_head_from_modules($conf, $langs, null, $head, $h, 'ai@ai', 'remove');
|
||||
|
||||
return $head;
|
||||
}
|
||||
70
htdocs/ai/lib/generate_content.lib.php
Normal file
70
htdocs/ai/lib/generate_content.lib.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
/* Copyright (C) 2008-2011 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2005-2016 Regis Houssin <regis.houssin@inodbox.com>
|
||||
* Copyright (C) 2012 J. Fernando Lagrange <fernando@demo-tic.org>
|
||||
* Copyright (C) 2015 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
|
||||
* Copyright (C) 2023 Eric Seigne <eric.seigne@cap-rel.fr>
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
* or see https://www.gnu.org/
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file htdocs/ai/lib/generate_content.lib.php
|
||||
* \brief Library of ai script
|
||||
*/
|
||||
|
||||
if (!defined('NOTOKENRENEWAL')) {
|
||||
define('NOTOKENRENEWAL', '1'); // Disables token renewal
|
||||
}
|
||||
if (!defined('NOREQUIREMENU')) {
|
||||
define('NOREQUIREMENU', '1');
|
||||
}
|
||||
if (!defined('NOREQUIREHTML')) {
|
||||
define('NOREQUIREHTML', '1');
|
||||
}
|
||||
if (!defined('NOREQUIREAJAX')) {
|
||||
define('NOREQUIREAJAX', '1');
|
||||
}
|
||||
if (!defined('NOREQUIRESOC')) {
|
||||
define('NOREQUIRESOC', '1');
|
||||
}
|
||||
|
||||
require_once '../../main.inc.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/ai/class/ai.class.php';
|
||||
|
||||
|
||||
//get data from AJAX
|
||||
$rawData = file_get_contents('php://input');
|
||||
$jsonData = json_decode($rawData, true);
|
||||
|
||||
if (is_null($jsonData)) {
|
||||
dol_print_error('data with format JSON valide.');
|
||||
}
|
||||
$token = GETPOST('token');
|
||||
if ($token !== currentToken()) { // Remplacez 'newToken' par le nom de votre variable de session contenant le token
|
||||
dol_print_error('CSRF token validation failed.');
|
||||
exit;
|
||||
}
|
||||
$chatGPT = new Ai('API_ENDPOINT', 'API_KEY');
|
||||
|
||||
$instructions = dol_string_nohtmltag($jsonData['instructions'], 1, 'UTF-8');
|
||||
|
||||
$generatedContent = $chatGPT->generateContent($instructions);
|
||||
|
||||
if ($generatedContent) {
|
||||
print $generatedContent;
|
||||
} else {
|
||||
dol_print_error('error!!');
|
||||
}
|
||||
@@ -22,62 +22,14 @@
|
||||
* \brief Tab of events on Calendar
|
||||
*/
|
||||
|
||||
//if (! defined('NOREQUIREDB')) define('NOREQUIREDB', '1'); // Do not create database handler $db
|
||||
//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER', '1'); // Do not load object $user
|
||||
//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC', '1'); // Do not load object $mysoc
|
||||
//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN', '1'); // Do not load object $langs
|
||||
//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION', '1'); // Do not check injection attack on GET parameters
|
||||
//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION', '1'); // Do not check injection attack on POST parameters
|
||||
//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL', '1'); // Do not roll the Anti CSRF token (used if MAIN_SECURITY_CSRF_WITH_TOKEN is on)
|
||||
//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK', '1'); // Do not check style html tag into posted data
|
||||
//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU', '1'); // If there is no need to load and show top and left menu
|
||||
//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML', '1'); // If we don't need to load the html.form.class.php
|
||||
//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX', '1'); // Do not load ajax.lib.php library
|
||||
//if (! defined("NOLOGIN")) define("NOLOGIN", '1'); // If this page is public (can be called outside logged session). This include the NOIPCHECK too.
|
||||
//if (! defined('NOIPCHECK')) define('NOIPCHECK', '1'); // Do not check IP defined into conf $dolibarr_main_restrict_ip
|
||||
//if (! defined("MAIN_LANG_DEFAULT")) define('MAIN_LANG_DEFAULT', 'auto'); // Force lang to a particular value
|
||||
//if (! defined("MAIN_AUTHENTICATION_MODE")) define('MAIN_AUTHENTICATION_MODE', 'aloginmodule'); // Force authentication handler
|
||||
//if (! defined("MAIN_SECURITY_FORCECSP")) define('MAIN_SECURITY_FORCECSP', 'none'); // Disable all Content Security Policies
|
||||
//if (! defined('CSRFCHECK_WITH_TOKEN')) define('CSRFCHECK_WITH_TOKEN', '1'); // Force use of CSRF protection with tokens even for GET
|
||||
//if (! defined('NOBROWSERNOTIF')) define('NOBROWSERNOTIF', '1'); // Disable browser notification
|
||||
|
||||
// Load Dolibarr environment
|
||||
$res = 0;
|
||||
// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined)
|
||||
if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) {
|
||||
$res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
|
||||
}
|
||||
// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME
|
||||
$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1;
|
||||
while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) {
|
||||
$i--;
|
||||
$j--;
|
||||
}
|
||||
if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) {
|
||||
$res = @include substr($tmp, 0, ($i + 1))."/main.inc.php";
|
||||
}
|
||||
if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) {
|
||||
$res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php";
|
||||
}
|
||||
// Try main.inc.php using relative path
|
||||
if (!$res && file_exists("../main.inc.php")) {
|
||||
$res = @include "../main.inc.php";
|
||||
}
|
||||
if (!$res && file_exists("../../main.inc.php")) {
|
||||
$res = @include "../../main.inc.php";
|
||||
}
|
||||
if (!$res && file_exists("../../../main.inc.php")) {
|
||||
$res = @include "../../../main.inc.php";
|
||||
}
|
||||
if (!$res) {
|
||||
die("Include of main fails");
|
||||
}
|
||||
require '../main.inc.php';
|
||||
|
||||
require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
|
||||
dol_include_once('/bookcal/class/calendar.class.php');
|
||||
dol_include_once('/bookcal/lib/bookcal_calendar.lib.php');
|
||||
require_once DOL_DOCUMENT_ROOT.'/bookcal/class/calendar.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/bookcal/lib/bookcal_calendar.lib.php';
|
||||
|
||||
// Load translation files required by the page
|
||||
$langs->loadLangs(array("bookcal@bookcal", "other"));
|
||||
|
||||
@@ -169,6 +169,12 @@ class FormAdvTargetEmailing extends Form
|
||||
if (getDolGlobalString('USER_HIDE_INACTIVE_IN_COMBOBOX')) {
|
||||
$sql_usr .= " AND u2.statut <> 0";
|
||||
}
|
||||
if (!empty($conf->global->USER_HIDE_NONEMPLOYEE_IN_COMBOBOX)) {
|
||||
$sql_usr .= " AND u2.employee<>0 ";
|
||||
}
|
||||
if (!empty($conf->global->USER_HIDE_EXTERNAL_IN_COMBOBOX)) {
|
||||
$sql_usr .= " AND u2.fk_soc IS NULL ";
|
||||
}
|
||||
$sql_usr .= " ORDER BY name ASC";
|
||||
// print $sql_usr;exit;
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@ if ($action == 'update' && is_array($arrayofparameters) && !empty($user->admin))
|
||||
} else {
|
||||
$val_const = GETPOST($key, 'int');
|
||||
}
|
||||
} else if ($val['type'] == 'html') {
|
||||
$val_const = GETPOST($key, 'restricthtml');
|
||||
} else {
|
||||
$val_const = GETPOST($key, 'alpha');
|
||||
}
|
||||
|
||||
@@ -2081,6 +2081,12 @@ class Form
|
||||
if (getDolGlobalString('USER_HIDE_INACTIVE_IN_COMBOBOX') || $notdisabled) {
|
||||
$sql .= " AND u.statut <> 0";
|
||||
}
|
||||
if (!empty($conf->global->USER_HIDE_NONEMPLOYEE_IN_COMBOBOX) || $notdisabled) {
|
||||
$sql .= " AND u.employee <> 0";
|
||||
}
|
||||
if (!empty($conf->global->USER_HIDE_EXTERNAL_IN_COMBOBOX) || $notdisabled) {
|
||||
$sql .= " AND u.fk_soc IS NULL";
|
||||
}
|
||||
if (!empty($morefilter)) {
|
||||
$sql .= " " . $morefilter;
|
||||
}
|
||||
|
||||
@@ -755,7 +755,7 @@ class FormMail extends Form
|
||||
if (!empty($this->withtoccuser) && is_array($this->withtoccuser) && getDolGlobalString('MAIN_MAIL_ENABLED_USER_DEST_SELECT')) {
|
||||
$out .= '<tr><td>';
|
||||
$out .= $langs->trans("MailToCCUsers");
|
||||
$out .= '</td><td>';
|
||||
$out .= '</td>';
|
||||
|
||||
// multiselect array convert html entities into options tags, even if we don't want this, so we encode them a second time
|
||||
$tmparray = $this->withtoccuser;
|
||||
@@ -887,6 +887,11 @@ class FormMail extends Form
|
||||
$out .= "</td></tr>\n";
|
||||
}
|
||||
|
||||
//input prompt AI
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php';
|
||||
if (isModEnabled('ai')) {
|
||||
$out .= $this->getHtmlForInstruction();
|
||||
}
|
||||
// Message
|
||||
if (!empty($this->withbody)) {
|
||||
$defaultmessage = GETPOST('message', 'restricthtml');
|
||||
@@ -1363,6 +1368,57 @@ class FormMail extends Form
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* get Html For instruction of message
|
||||
* @return string Text for instructions
|
||||
*/
|
||||
public function getHtmlForInstruction()
|
||||
{
|
||||
global $langs, $form;
|
||||
|
||||
$baseUrl = dol_buildpath('/', 1);
|
||||
|
||||
$out = '<tr>';
|
||||
$out .= '<td>';
|
||||
$out .= $form->textwithpicto($langs->trans('helpWithAi'), $langs->trans("YouCanMakeSomeInstructionForEmail"));
|
||||
$out .= '</td>';
|
||||
|
||||
$out .= '<td>';
|
||||
$out .= '<input type="hidden" id="csrf_token" name="token" value="'.newToken().'">';
|
||||
$out .= '<input type="text" class="quatrevingtpercent" id="ai_instructions" name="instruction" placeholder="message with AI"/>';
|
||||
$out .= '<button id="generate_button" type="button" class="button smallpaddingimp">'.$langs->trans('Generate').'</button>';
|
||||
$out .= "</td></tr>\n";
|
||||
$out .= "<script type='text/javascript'>
|
||||
$(document).ready(function() {
|
||||
$('#generate_button').click(function() {
|
||||
var instructions = $('#ai_instructions').val();
|
||||
var token = $('#csrf_token').val();
|
||||
|
||||
$.ajax({
|
||||
url: '".$baseUrl."ai/lib/generate_content.lib.php',
|
||||
method: 'POST',
|
||||
dataType: 'json',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({
|
||||
'token': token,
|
||||
'instructions': instructions,
|
||||
}),
|
||||
success: function(response) {
|
||||
console.log(response);
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('error ajax', status, error);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
";
|
||||
return $out;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return templates of email with type = $type_template or type = 'all'.
|
||||
* This search into table c_email_templates. Used by the get_form function.
|
||||
|
||||
@@ -522,6 +522,15 @@ class FormOther
|
||||
if (!empty($user->socid)) {
|
||||
$sql_usr .= " AND u.fk_soc = ".((int) $user->socid);
|
||||
}
|
||||
if (!empty($conf->global->USER_HIDE_NONEMPLOYEE_IN_COMBOBOX)) {
|
||||
$sql_usr .= " AND u.employee <> 0";
|
||||
}
|
||||
if (!empty($conf->global->USER_HIDE_EXTERNAL_IN_COMBOBOX)) {
|
||||
$sql_usr .= " AND u.fk_soc IS NULL";
|
||||
}
|
||||
if (!empty($conf->global->USER_HIDE_INACTIVE_IN_COMBOBOX)) {
|
||||
$sql_usr .= " AND u.statut <> 0";
|
||||
}
|
||||
|
||||
//Add hook to filter on user (for example on usergroup define in custom modules)
|
||||
if (!empty($reshook)) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Copyright (C) 2004 Benoit Mortier <benoit.mortier@opensides.be>
|
||||
* Copyright (C) 2005-2021 Regis Houssin <regis.houssin@inodbox.com>
|
||||
* Copyright (C) 2006-2021 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2024 William Mead <william.mead@manchenumerique.fr>
|
||||
*
|
||||
* 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
|
||||
@@ -44,12 +45,12 @@ class Ldap
|
||||
public $errors = array();
|
||||
|
||||
/**
|
||||
* Tableau des serveurs (IP addresses ou nom d'hotes)
|
||||
* @var array Servers (IP addresses or hostnames)
|
||||
*/
|
||||
public $server = array();
|
||||
|
||||
/**
|
||||
* Current connected server
|
||||
* @var string Current connected server
|
||||
*/
|
||||
public $connectedServer;
|
||||
|
||||
@@ -59,51 +60,62 @@ class Ldap
|
||||
public $serverPort;
|
||||
|
||||
/**
|
||||
* Base DN (e.g. "dc=foo,dc=com")
|
||||
* @var string Base DN (e.g. "dc=foo,dc=com")
|
||||
*/
|
||||
|
||||
public $dn;
|
||||
/**
|
||||
* type de serveur, actuellement OpenLdap et Active Directory
|
||||
* @var string Server type: OpenLDAP or Active Directory
|
||||
*/
|
||||
|
||||
public $serverType;
|
||||
/**
|
||||
* Version du protocole ldap
|
||||
* @var string LDAP protocol version
|
||||
*/
|
||||
|
||||
public $ldapProtocolVersion;
|
||||
/**
|
||||
* Server DN
|
||||
* @var string Server DN
|
||||
*/
|
||||
|
||||
public $domain;
|
||||
|
||||
/**
|
||||
* @var string Server FQDN
|
||||
*/
|
||||
public $domainFQDN;
|
||||
|
||||
/**
|
||||
* @var int bind
|
||||
* @var bool LDAP bind
|
||||
*/
|
||||
public $bind;
|
||||
|
||||
/**
|
||||
* User administrateur Ldap
|
||||
* @var string LDAP administrator user
|
||||
* Active Directory does not allow anonymous connections
|
||||
*/
|
||||
public $searchUser;
|
||||
/**
|
||||
* Administraot Password
|
||||
* @var string LDAP administrator password
|
||||
* Active Directory does not allow anonymous connections
|
||||
*/
|
||||
public $searchPassword;
|
||||
|
||||
/**
|
||||
* Users DN
|
||||
* @var string Users DN
|
||||
*/
|
||||
public $people;
|
||||
|
||||
/**
|
||||
* Groups DN
|
||||
* @var string Groups DN
|
||||
*/
|
||||
public $groups;
|
||||
|
||||
/**
|
||||
* @var string|null Error code provided by the LDAP server
|
||||
* @var int|null Error code provided by the LDAP server
|
||||
*/
|
||||
public $ldapErrorCode;
|
||||
|
||||
/**
|
||||
* @var string|null Error text message
|
||||
*/
|
||||
@@ -113,10 +125,12 @@ class Ldap
|
||||
* @var string
|
||||
*/
|
||||
public $filter;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
public $filtergroup;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
@@ -168,56 +182,91 @@ class Ldap
|
||||
public $badpwdtime;
|
||||
|
||||
/**
|
||||
* @var string ladpUserDN
|
||||
* @var string LDAP user DN
|
||||
*/
|
||||
public $ldapUserDN;
|
||||
|
||||
//Fetch user
|
||||
/**
|
||||
* @var string Fetched username
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* @var string Fetched user first name
|
||||
*/
|
||||
public $firstname;
|
||||
|
||||
/**
|
||||
* @var string Fetched user login
|
||||
*/
|
||||
public $login;
|
||||
|
||||
/**
|
||||
* @var string Fetched user phone number
|
||||
*/
|
||||
public $phone;
|
||||
|
||||
/**
|
||||
* @var string Fetched user fax number
|
||||
*/
|
||||
public $fax;
|
||||
|
||||
/**
|
||||
* @var string Fetched user email
|
||||
*/
|
||||
public $mail;
|
||||
|
||||
/**
|
||||
* @var string Fetched user mobile number
|
||||
*/
|
||||
public $mobile;
|
||||
|
||||
/**
|
||||
* @var array UserAccountControl Flags
|
||||
*/
|
||||
public $uacf;
|
||||
|
||||
/**
|
||||
* @var int Password last set time
|
||||
*/
|
||||
public $pwdlastset;
|
||||
|
||||
public $ldapcharset = 'UTF-8'; // LDAP should be UTF-8 encoded
|
||||
|
||||
/**
|
||||
* @var string LDAP charset.
|
||||
* LDAP should be UTF-8 encoded
|
||||
*/
|
||||
public $ldapcharset = 'UTF-8';
|
||||
|
||||
/**
|
||||
* The internal LDAP connection handle
|
||||
* @var bool|resource The internal LDAP connection handle
|
||||
*/
|
||||
public $connection;
|
||||
|
||||
/**
|
||||
* Result of any connections etc.
|
||||
* @var bool|resource Result of any connections or search.
|
||||
*/
|
||||
public $result;
|
||||
|
||||
/**
|
||||
* No Ldap synchronization
|
||||
* @var int No LDAP synchronization
|
||||
*/
|
||||
const SYNCHRO_NONE = 0;
|
||||
|
||||
/**
|
||||
* Dolibarr to Ldap synchronization
|
||||
* @var int Dolibarr to LDAP synchronization
|
||||
*/
|
||||
const SYNCHRO_DOLIBARR_TO_LDAP = 1;
|
||||
|
||||
/**
|
||||
* Ldap to Dolibarr synchronization
|
||||
* @var int LDAP to Dolibarr synchronization
|
||||
*/
|
||||
const SYNCHRO_LDAP_TO_DOLIBARR = 2;
|
||||
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
global $conf;
|
||||
|
||||
// Server
|
||||
if (getDolGlobalString('LDAP_SERVER_HOST')) {
|
||||
@@ -260,17 +309,16 @@ class Ldap
|
||||
* Use this->server, this->serverPort, this->ldapProtocolVersion, this->serverType, this->searchUser, this->searchPassword
|
||||
* After return, this->connection and $this->bind are defined
|
||||
*
|
||||
* @return int Return integer <0 if KO, 1 if bind anonymous, 2 if bind auth
|
||||
* @return int if KO: <0 || if bind anonymous: 1 || if bind auth: 2
|
||||
*/
|
||||
public function connect_bind()
|
||||
{
|
||||
// phpcs:enable
|
||||
global $conf;
|
||||
global $dolibarr_main_auth_ldap_debug;
|
||||
|
||||
$connected = 0;
|
||||
$this->bind = 0;
|
||||
$this->error = 0;
|
||||
$this->bind = false;
|
||||
$this->error = '';
|
||||
$this->connectedServer = '';
|
||||
|
||||
$ldapdebug = ((empty($dolibarr_main_auth_ldap_debug) || $dolibarr_main_auth_ldap_debug == "false") ? false : true);
|
||||
@@ -290,7 +338,7 @@ class Ldap
|
||||
if (!function_exists("ldap_connect")) {
|
||||
$this->error = 'LDAPFunctionsNotAvailableOnPHP';
|
||||
dol_syslog(get_class($this)."::connect_bind ".$this->error, LOG_WARNING);
|
||||
$return = -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (empty($this->error)) {
|
||||
@@ -303,9 +351,9 @@ class Ldap
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($this->serverPing($host, $this->serverPort) === true) {
|
||||
if ($this->serverPing($host, $this->serverPort)) {
|
||||
if ($ldapdebug) {
|
||||
dol_syslog(get_class($this)."::connect_bind serverPing true, we try ldap_connect to ".$host);
|
||||
dol_syslog(get_class($this)."::connect_bind serverPing true, we try ldap_connect to ".$host, LOG_DEBUG);
|
||||
}
|
||||
$this->connection = ldap_connect($host, $this->serverPort);
|
||||
} else {
|
||||
@@ -313,10 +361,13 @@ class Ldap
|
||||
// With host = ldaps://server, the serverPing to ssl://server sometimes fails, even if the ldap_connect succeed, so
|
||||
// we test this case and continue in such a case even if serverPing fails.
|
||||
if ($ldapdebug) {
|
||||
dol_syslog(get_class($this)."::connect_bind serverPing false, we try ldap_connect to ".$host);
|
||||
dol_syslog(get_class($this)."::connect_bind serverPing false, we try ldap_connect to ".$host, LOG_DEBUG);
|
||||
}
|
||||
$this->connection = ldap_connect($host, $this->serverPort);
|
||||
} else {
|
||||
if ($ldapdebug) {
|
||||
dol_syslog(get_class($this)."::connect_bind serverPing false, no ldap_connect ".$host, LOG_DEBUG);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -344,8 +395,7 @@ class Ldap
|
||||
|
||||
// Execute the ldap_set_option here (after connect and before bind)
|
||||
$this->setVersion();
|
||||
ldap_set_option($this->connection, LDAP_OPT_SIZELIMIT, 0); // no limit here. should return true.
|
||||
|
||||
$this->setSizeLimit();
|
||||
|
||||
if ($this->serverType == "activedirectory") {
|
||||
$result = $this->setReferrals();
|
||||
@@ -396,15 +446,13 @@ class Ldap
|
||||
}
|
||||
|
||||
if ($connected) {
|
||||
$return = $connected;
|
||||
dol_syslog(get_class($this)."::connect_bind return=".$return, LOG_DEBUG);
|
||||
dol_syslog(get_class($this)."::connect_bind ".$connected, LOG_DEBUG);
|
||||
return $connected;
|
||||
} else {
|
||||
$this->error = 'Failed to connect to LDAP'.($this->error ? ': '.$this->error : '');
|
||||
$return = -1;
|
||||
dol_syslog(get_class($this)."::connect_bind return=".$return.' - '.$this->error, LOG_WARNING);
|
||||
dol_syslog(get_class($this)."::connect_bind ".$this->error, LOG_WARNING);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -481,50 +529,57 @@ class Ldap
|
||||
|
||||
|
||||
/**
|
||||
* Verification de la version du serveur ldap.
|
||||
* Verify LDAP server version
|
||||
*
|
||||
* @return string version
|
||||
* @return int version
|
||||
*/
|
||||
public function getVersion()
|
||||
{
|
||||
$version = 0;
|
||||
$version = @ldap_get_option($this->connection, LDAP_OPT_PROTOCOL_VERSION, $version);
|
||||
@ldap_get_option($this->connection, LDAP_OPT_PROTOCOL_VERSION, $version);
|
||||
return $version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change ldap protocol version to use.
|
||||
* Set LDAP protocol version.
|
||||
* LDAP_OPT_PROTOCOL_VERSION is a constant equal to 3
|
||||
*
|
||||
* @return boolean version
|
||||
* @return boolean if set LDAP option OK: true, if KO: false
|
||||
*/
|
||||
public function setVersion()
|
||||
{
|
||||
// LDAP_OPT_PROTOCOL_VERSION est une constante qui vaut 17
|
||||
$ldapsetversion = ldap_set_option($this->connection, LDAP_OPT_PROTOCOL_VERSION, $this->ldapProtocolVersion);
|
||||
return $ldapsetversion;
|
||||
return ldap_set_option($this->connection, LDAP_OPT_PROTOCOL_VERSION, $this->ldapProtocolVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
* changement du referrals.
|
||||
* Set LDAP size limit.
|
||||
*
|
||||
* @return boolean referrals
|
||||
* @return boolean if set LDAP option OK: true, if KO: false
|
||||
*/
|
||||
public function setSizeLimit()
|
||||
{
|
||||
return ldap_set_option($this->connection, LDAP_OPT_SIZELIMIT, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set LDAP referrals.
|
||||
* LDAP_OPT_REFERRALS is a constant equal to ?
|
||||
*
|
||||
* @return boolean if set LDAP option OK: true, if KO: false
|
||||
*/
|
||||
public function setReferrals()
|
||||
{
|
||||
// LDAP_OPT_REFERRALS est une constante qui vaut ?
|
||||
$ldapreferrals = ldap_set_option($this->connection, LDAP_OPT_REFERRALS, 0);
|
||||
return $ldapreferrals;
|
||||
return ldap_set_option($this->connection, LDAP_OPT_REFERRALS, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a LDAP entry
|
||||
* Ldap object connect and bind must have been done
|
||||
* Add an LDAP entry
|
||||
* LDAP object connect and bind must have been done
|
||||
*
|
||||
* @param string $dn DN entry key
|
||||
* @param array $info Attributes array
|
||||
* @param User $user Object user that create
|
||||
* @return int Return integer <0 if KO, >0 if OK
|
||||
* @return int if KO: <0 || if OK: >0
|
||||
*/
|
||||
public function add($dn, $info, $user)
|
||||
{
|
||||
@@ -566,13 +621,13 @@ class Ldap
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify a LDAP entry
|
||||
* Ldap object connect and bind must have been done
|
||||
* Modify an LDAP entry
|
||||
* LDAP object connect and bind must have been done
|
||||
*
|
||||
* @param string $dn DN entry key
|
||||
* @param array $info Attributes array
|
||||
* @param User $user Object user that modify
|
||||
* @return int Return integer <0 if KO, >0 if OK
|
||||
* @return int if KO: <0 || if OK: >0
|
||||
*/
|
||||
public function modify($dn, $info, $user)
|
||||
{
|
||||
@@ -622,15 +677,15 @@ class Ldap
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename a LDAP entry
|
||||
* Ldap object connect and bind must have been done
|
||||
* Rename an LDAP entry
|
||||
* LDAP object connect and bind must have been done
|
||||
*
|
||||
* @param string $dn Old DN entry key (uid=qqq,ou=xxx,dc=aaa,dc=bbb) (before update)
|
||||
* @param string $newrdn New RDN entry key (uid=qqq)
|
||||
* @param string $newparent New parent (ou=xxx,dc=aaa,dc=bbb)
|
||||
* @param User $user Object user that modify
|
||||
* @param bool $deleteoldrdn If true the old RDN value(s) is removed, else the old RDN value(s) is retained as non-distinguished values of the entry.
|
||||
* @return int Return integer <0 if KO, >0 if OK
|
||||
* @return int if KO: <0 || if OK: >0
|
||||
*/
|
||||
public function rename($dn, $newrdn, $newparent, $user, $deleteoldrdn = true)
|
||||
{
|
||||
@@ -665,8 +720,8 @@ class Ldap
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify a LDAP entry (to use if dn != olddn)
|
||||
* Ldap object connect and bind must have been done
|
||||
* Modify an LDAP entry (to use if dn != olddn)
|
||||
* LDAP object connect and bind must have been done
|
||||
*
|
||||
* @param string $dn DN entry key
|
||||
* @param array $info Attributes array
|
||||
@@ -674,7 +729,7 @@ class Ldap
|
||||
* @param string $olddn Old DN entry key (before update)
|
||||
* @param string $newrdn New RDN entry key (uid=qqq) (for ldap_rename)
|
||||
* @param string $newparent New parent (ou=xxx,dc=aaa,dc=bbb) (for ldap_rename)
|
||||
* @return int Return integer <0 if KO, >0 if OK
|
||||
* @return int if KO: <0 || if OK: >0
|
||||
*/
|
||||
public function update($dn, $info, $user, $olddn, $newrdn = '', $newparent = '')
|
||||
{
|
||||
@@ -720,11 +775,11 @@ class Ldap
|
||||
|
||||
|
||||
/**
|
||||
* Delete a LDAP entry
|
||||
* Ldap object connect and bind must have been done
|
||||
* Delete an LDAP entry
|
||||
* LDAP object connect and bind must have been done
|
||||
*
|
||||
* @param string $dn DN entry key
|
||||
* @return int Return integer <0 if KO, >0 if OK
|
||||
* @return int if KO: <0 || if OK: >0
|
||||
*/
|
||||
public function delete($dn)
|
||||
{
|
||||
@@ -753,7 +808,7 @@ class Ldap
|
||||
|
||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||
/**
|
||||
* Build a LDAP message
|
||||
* Build an LDAP message
|
||||
*
|
||||
* @param string $dn DN entry key
|
||||
* @param array $info Attributes array
|
||||
@@ -790,29 +845,32 @@ class Ldap
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump a LDAP message to ldapinput.in file
|
||||
* Dump an LDAP message to ldapinput.in file
|
||||
*
|
||||
* @param string $dn DN entry key
|
||||
* @param array $info Attributes array
|
||||
* @return int Return integer <0 if KO, >0 if OK
|
||||
* @return int if KO: <0 || if OK: >0
|
||||
*/
|
||||
public function dump($dn, $info)
|
||||
{
|
||||
global $conf;
|
||||
|
||||
$ldapDirTemp = $conf->ldap->dir_temp;
|
||||
// Create content
|
||||
$content = $this->dump_content($dn, $info);
|
||||
|
||||
//Create file
|
||||
$result = dol_mkdir($conf->ldap->dir_temp);
|
||||
|
||||
$outputfile = $conf->ldap->dir_temp.'/ldapinput.in';
|
||||
$fp = fopen($outputfile, "w");
|
||||
if ($fp) {
|
||||
fputs($fp, $content);
|
||||
fclose($fp);
|
||||
dolChmod($outputfile);
|
||||
return 1;
|
||||
//Create directory & file
|
||||
$result = dol_mkdir($ldapDirTemp);
|
||||
if ($result != 0) {
|
||||
$outputfile = $ldapDirTemp.'/ldapinput.in';
|
||||
$fp = fopen($outputfile, "w");
|
||||
if ($fp) {
|
||||
fputs($fp, $content);
|
||||
fclose($fp);
|
||||
dolChmod($outputfile);
|
||||
return 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
@@ -821,10 +879,10 @@ class Ldap
|
||||
/**
|
||||
* Ping a server before ldap_connect for avoid waiting
|
||||
*
|
||||
* @param string $host Server host or address
|
||||
* @param int $port Server port (default 389)
|
||||
* @param int $timeout Timeout in second (default 1s)
|
||||
* @return boolean true or false
|
||||
* @param string $host Server host or address
|
||||
* @param int $port Server port (default 389)
|
||||
* @param int $timeout Timeout in second (default 1s)
|
||||
* @return boolean true or false
|
||||
*/
|
||||
public function serverPing($host, $port = 389, $timeout = 1)
|
||||
{
|
||||
@@ -865,13 +923,13 @@ class Ldap
|
||||
// Attribute methods -----------------------------------------------------
|
||||
|
||||
/**
|
||||
* Add a LDAP attribute in entry
|
||||
* Ldap object connect and bind must have been done
|
||||
* Add an LDAP attribute in entry
|
||||
* LDAP object connect and bind must have been done
|
||||
*
|
||||
* @param string $dn DN entry key
|
||||
* @param array $info Attributes array
|
||||
* @param User $user Object user that create
|
||||
* @return int Return integer <0 if KO, >0 if OK
|
||||
* @return int if KO: <0 || if OK: >0
|
||||
*/
|
||||
public function addAttribute($dn, $info, $user)
|
||||
{
|
||||
@@ -911,13 +969,13 @@ class Ldap
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a LDAP attribute in entry
|
||||
* Ldap object connect and bind must have been done
|
||||
* Update an LDAP attribute in entry
|
||||
* LDAP object connect and bind must have been done
|
||||
*
|
||||
* @param string $dn DN entry key
|
||||
* @param array $info Attributes array
|
||||
* @param User $user Object user that create
|
||||
* @return int Return integer <0 if KO, >0 if OK
|
||||
* @return int if KO: <0 || if OK: >0
|
||||
*/
|
||||
public function updateAttribute($dn, $info, $user)
|
||||
{
|
||||
@@ -957,13 +1015,13 @@ class Ldap
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a LDAP attribute in entry
|
||||
* Ldap object connect and bind must have been done
|
||||
* Delete an LDAP attribute in entry
|
||||
* LDAP object connect and bind must have been done
|
||||
*
|
||||
* @param string $dn DN entry key
|
||||
* @param array $info Attributes array
|
||||
* @param User $user Object user that create
|
||||
* @return int Return integer <0 if KO, >0 if OK
|
||||
* @return int if KO: <0 || if OK: >0
|
||||
*/
|
||||
public function deleteAttribute($dn, $info, $user)
|
||||
{
|
||||
@@ -1007,7 +1065,7 @@ class Ldap
|
||||
*
|
||||
* @param string $dn DN entry key
|
||||
* @param string $filter Filter
|
||||
* @return int|array Return integer <0 or false if KO, array if OK
|
||||
* @return int|array if KO: <=0 || if OK: array
|
||||
*/
|
||||
public function getAttribute($dn, $filter)
|
||||
{
|
||||
@@ -1046,9 +1104,9 @@ class Ldap
|
||||
/**
|
||||
* Returns an array containing values for an attribute and for first record matching filterrecord
|
||||
*
|
||||
* @param string $filterrecord Record
|
||||
* @param string $attribute Attributes
|
||||
* @return array|boolean
|
||||
* @param string $filterrecord Record
|
||||
* @param string $attribute Attributes
|
||||
* @return array|boolean
|
||||
*/
|
||||
public function getAttributeValues($filterrecord, $attribute)
|
||||
{
|
||||
@@ -1082,16 +1140,16 @@ class Ldap
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array containing a details or list of LDAP record(s).
|
||||
* ldapsearch -LLLx -hlocalhost -Dcn=admin,dc=parinux,dc=org -w password -b "ou=adherents,ou=people,dc=parinux,dc=org" userPassword
|
||||
* Returns an array containing a details or list of LDAP record(s).
|
||||
* ldapsearch -LLLx -hlocalhost -Dcn=admin,dc=parinux,dc=org -w password -b "ou=adherents,ou=people,dc=parinux,dc=org" userPassword
|
||||
*
|
||||
* @param string $search Value of field to search, '*' for all. Not used if $activefilter is set.
|
||||
* @param string $userDn DN (Ex: ou=adherents,ou=people,dc=parinux,dc=org)
|
||||
* @param string $useridentifier Name of key field (Ex: uid).
|
||||
* @param array $attributeArray Array of fields required. Note this array must also contains field $useridentifier (Ex: sn,userPassword)
|
||||
* @param array $attributeArray Array of fields required. Note this array must also contain field $useridentifier (Ex: sn,userPassword)
|
||||
* @param int $activefilter '1' or 'user'=use field this->filter as filter instead of parameter $search, 'group'=use field this->filtergroup as filter, 'member'=use field this->filtermember as filter
|
||||
* @param array $attributeAsArray Array of fields wanted as an array not a string
|
||||
* @return array|int Array of [id_record][ldap_field]=value
|
||||
* @return array|int if KO: <0 || if OK: array of [id_record][ldap_field]=value
|
||||
*/
|
||||
public function getRecords($search, $userDn, $useridentifier, $attributeArray, $activefilter = 0, $attributeAsArray = array())
|
||||
{
|
||||
@@ -1179,7 +1237,7 @@ class Ldap
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a little-endian hex-number to one, that 'hexdec' can convert
|
||||
* Converts a little-endian hex-number to one, that 'hexdec' can convert
|
||||
* Required by Active Directory
|
||||
*
|
||||
* @param string $hex Hex value
|
||||
@@ -1196,11 +1254,11 @@ class Ldap
|
||||
|
||||
|
||||
/**
|
||||
* Recupere le SID de l'utilisateur
|
||||
* Gets LDAP user SID.
|
||||
* Required by Active Directory
|
||||
*
|
||||
* @param string $ldapUser Login de l'utilisateur
|
||||
* @return string Sid
|
||||
* @param string $ldapUser User login
|
||||
* @return int|string if SID OK: SID string, if KO: -1
|
||||
*/
|
||||
public function getObjectSid($ldapUser)
|
||||
{
|
||||
@@ -1241,13 +1299,13 @@ class Ldap
|
||||
return $SIDText;
|
||||
} else {
|
||||
$this->error = ldap_errno($this->connection)." ".ldap_error($this->connection);
|
||||
return '?';
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the textual SID
|
||||
* Indispensable pour Active Directory
|
||||
* Required by Active Directory
|
||||
*
|
||||
* @param string $binsid Binary SID
|
||||
* @return string Textual SID
|
||||
@@ -1267,15 +1325,17 @@ class Ldap
|
||||
|
||||
|
||||
/**
|
||||
* Fonction de recherche avec filtre
|
||||
* this->connection doit etre defini donc la methode bind ou bindauth doit avoir deja ete appelee
|
||||
* Ne pas utiliser pour recherche d'une liste donnee de proprietes
|
||||
* car conflict majuscule-minuscule. A n'utiliser que pour les pages
|
||||
* 'Fiche LDAP' qui affiche champ lisibles par default.
|
||||
* Search method with filter
|
||||
* this->connection must be defined. The bind or bindauth methods must already have been called.
|
||||
* Do not use for search of a given properties list because of upper-lower case conflict.
|
||||
* Only use for pages.
|
||||
* 'Fiche LDAP' shows readable fields by default.
|
||||
* @see bind
|
||||
* @see bindauth
|
||||
*
|
||||
* @param string $checkDn DN de recherche (Ex: ou=users,cn=my-domain,cn=com)
|
||||
* @param string $filter Search filter (ex: (sn=nom_personne) )
|
||||
* @return array|int Array with answers (key lowercased - value)
|
||||
* @param string $checkDn Search DN (Ex: ou=users,cn=my-domain,cn=com)
|
||||
* @param string $filter Search filter (ex: (sn=name_person) )
|
||||
* @return array|int Array with answers (lowercase key - value)
|
||||
*/
|
||||
public function search($checkDn, $filter)
|
||||
{
|
||||
@@ -1303,12 +1363,12 @@ class Ldap
|
||||
|
||||
|
||||
/**
|
||||
* Load all attribute of a LDAP user
|
||||
* Load all attributes of an LDAP user
|
||||
*
|
||||
* @param User|string $user Not used.
|
||||
* @param string $filter Filter for search. Must start with &.
|
||||
* Examples: &(objectClass=inetOrgPerson) &(objectClass=user)(objectCategory=person) &(isMemberOf=cn=Sales,ou=Groups,dc=opencsi,dc=com)
|
||||
* @return int >0 if OK, <0 if KO
|
||||
* @param User|string $user Not used.
|
||||
* @param string $filter Filter for search. Must start with &.
|
||||
* Examples: &(objectClass=inetOrgPerson) &(objectClass=user)(objectCategory=person) &(isMemberOf=cn=Sales,ou=Groups,dc=opencsi,dc=com)
|
||||
* @return int if KO: <0 || if OK: > 0
|
||||
*/
|
||||
public function fetch($user, $filter)
|
||||
{
|
||||
@@ -1363,14 +1423,14 @@ class Ldap
|
||||
|
||||
$this->uacf = $this->parseUACF($this->convToOutputCharset($result[0]["useraccountcontrol"][0], $this->ldapcharset));
|
||||
if (isset($result[0]["pwdlastset"][0])) { // If expiration on password exists
|
||||
$this->pwdlastset = ($result[0]["pwdlastset"][0] != 0) ? $this->convert_time($this->convToOutputCharset($result[0]["pwdlastset"][0], $this->ldapcharset)) : 0;
|
||||
$this->pwdlastset = ($result[0]["pwdlastset"][0] != 0) ? $this->convertTime($this->convToOutputCharset($result[0]["pwdlastset"][0], $this->ldapcharset)) : 0;
|
||||
} else {
|
||||
$this->pwdlastset = -1;
|
||||
}
|
||||
if (!$this->name && !$this->login) {
|
||||
$this->pwdlastset = -1;
|
||||
}
|
||||
$this->badpwdtime = $this->convert_time($this->convToOutputCharset($result[0]["badpasswordtime"][0], $this->ldapcharset));
|
||||
$this->badpwdtime = $this->convertTime($this->convToOutputCharset($result[0]["badpasswordtime"][0], $this->ldapcharset));
|
||||
|
||||
// FQDN domain
|
||||
$domain = str_replace('dc=', '', $this->domain);
|
||||
@@ -1390,7 +1450,7 @@ class Ldap
|
||||
// helper methods
|
||||
|
||||
/**
|
||||
* Returns the correct user identifier to use, based on the ldap server type
|
||||
* Returns the correct user identifier to use, based on the LDAP server type
|
||||
*
|
||||
* @return string Login
|
||||
*/
|
||||
@@ -1404,7 +1464,7 @@ class Ldap
|
||||
}
|
||||
|
||||
/**
|
||||
* UserAccountControl Flgs to more human understandable form...
|
||||
* UserAccountControl Flags to more human understandable form...
|
||||
*
|
||||
* @param string $uacf UACF
|
||||
* @return array
|
||||
@@ -1482,16 +1542,14 @@ class Ldap
|
||||
return $retval;
|
||||
}
|
||||
|
||||
// phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps
|
||||
/**
|
||||
* Convertit le temps ActiveDirectory en Unix timestamp
|
||||
* Converts ActiveDirectory time to Unix timestamp
|
||||
*
|
||||
* @param string $value AD time to convert
|
||||
* @return integer Unix timestamp
|
||||
*/
|
||||
public function convert_time($value)
|
||||
public function convertTime($value)
|
||||
{
|
||||
// phpcs:enable
|
||||
$dateLargeInt = $value; // nano secondes depuis 1601 !!!!
|
||||
$secsAfterADEpoch = $dateLargeInt / (10000000); // secondes depuis le 1 jan 1601
|
||||
$ADToUnixConvertor = ((1970 - 1601) * 365.242190) * 86400; // UNIX start date - AD start date * jours * secondes
|
||||
@@ -1503,9 +1561,9 @@ class Ldap
|
||||
/**
|
||||
* Convert a string into output/memory charset
|
||||
*
|
||||
* @param string $str String to convert
|
||||
* @param string $str String to convert
|
||||
* @param string $pagecodefrom Page code of src string
|
||||
* @return string Converted string
|
||||
* @return string Converted string
|
||||
*/
|
||||
private function convToOutputCharset($str, $pagecodefrom = 'UTF-8')
|
||||
{
|
||||
@@ -1522,9 +1580,9 @@ class Ldap
|
||||
/**
|
||||
* Convert a string from output/memory charset
|
||||
*
|
||||
* @param string $str String to convert
|
||||
* @param string $str String to convert
|
||||
* @param string $pagecodeto Page code for result string
|
||||
* @return string Converted string
|
||||
* @return string Converted string
|
||||
*/
|
||||
public function convFromOutputCharset($str, $pagecodeto = 'UTF-8')
|
||||
{
|
||||
@@ -1547,7 +1605,6 @@ class Ldap
|
||||
*/
|
||||
public function getNextGroupGid($keygroup = 'LDAP_KEY_GROUPS')
|
||||
{
|
||||
global $conf;
|
||||
|
||||
if (empty($keygroup)) {
|
||||
$keygroup = 'LDAP_KEY_GROUPS';
|
||||
|
||||
@@ -587,7 +587,7 @@ function dol_get_next_week($day, $week, $month, $year)
|
||||
* True or 1 or 'gmt' to compare with GMT date.
|
||||
* Example: dol_get_first_day(1970,1,false) will return -3600 with TZ+1, a dol_print_date on it will return 1970-01-01 00:00:00
|
||||
* Example: dol_get_first_day(1970,1,true) will return 0 whatever is TZ, a dol_print_date on it will return 1970-01-01 00:00:00
|
||||
* @return int Date for first day, '' if error
|
||||
* @return int|string Date as a timestamp, '' if error
|
||||
*/
|
||||
function dol_get_first_day($year, $month = 1, $gm = false)
|
||||
{
|
||||
@@ -606,7 +606,7 @@ function dol_get_first_day($year, $month = 1, $gm = false)
|
||||
* @param int $month Month
|
||||
* @param mixed $gm False or 0 or 'tzserver' = Return date to compare with server TZ,
|
||||
* True or 1 or 'gmt' to compare with GMT date.
|
||||
* @return int Date for first day, '' if error
|
||||
* @return int|string Date as a timestamp, '' if error
|
||||
*/
|
||||
function dol_get_last_day($year, $month = 12, $gm = false)
|
||||
{
|
||||
@@ -1187,5 +1187,5 @@ function getWeekNumber($day, $month, $year)
|
||||
{
|
||||
$date = new DateTime($year.'-'.$month.'-'.$day);
|
||||
$week = $date->format("W");
|
||||
return $week;
|
||||
return (int) $week;
|
||||
}
|
||||
|
||||
@@ -186,7 +186,36 @@ function user_prepare_head(User $object)
|
||||
$h++;
|
||||
|
||||
$head[$h][0] = DOL_URL_ROOT.'/user/info.php?id='.$object->id;
|
||||
$head[$h][1] = $langs->trans("Info");
|
||||
$head[$h][1] = $langs->trans("Events");
|
||||
if (isModEnabled('agenda')&& ($user->hasRight('agenda', 'myactions', 'read') || $user->hasRight('agenda', 'allactions', 'read'))) {
|
||||
$nbEvent = 0;
|
||||
// Enable caching of thirdparty count actioncomm
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php';
|
||||
$cachekey = 'count_events_user_'.$object->id;
|
||||
$dataretrieved = dol_getcache($cachekey);
|
||||
if (!is_null($dataretrieved)) {
|
||||
$nbEvent = $dataretrieved;
|
||||
} else {
|
||||
$sql = "SELECT COUNT(id) as nb";
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."actioncomm";
|
||||
$sql .= " WHERE fk_user_done = ".((int) $object->id);
|
||||
$sql .= " AND entity IN (".getEntity('agenda').")";
|
||||
$resql = $db->query($sql);
|
||||
if ($resql) {
|
||||
$obj = $db->fetch_object($resql);
|
||||
$nbEvent = $obj->nb;
|
||||
} else {
|
||||
dol_syslog('Failed to count actioncomm '.$db->lasterror(), LOG_ERR);
|
||||
}
|
||||
dol_setcache($cachekey, $nbEvent, 120); // If setting cache fails, this is not a problem, so we do not test result.
|
||||
}
|
||||
|
||||
$head[$h][1] .= '/';
|
||||
$head[$h][1] .= $langs->trans("Agenda");
|
||||
if ($nbEvent > 0) {
|
||||
$head[$h][1] .= '<span class="badge marginleftonlyshort">'.$nbEvent.'</span>';
|
||||
}
|
||||
}
|
||||
$head[$h][2] = 'info';
|
||||
$h++;
|
||||
}
|
||||
@@ -1173,3 +1202,523 @@ function showSkins($fuser, $edit = 0, $foruserprofile = false)
|
||||
print '</table>';
|
||||
print '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Show html area with actions (done or not, ignore the name of function).
|
||||
* Note: Global parameter $param must be defined.
|
||||
*
|
||||
* @param Conf $conf Object conf
|
||||
* @param Translate $langs Object langs
|
||||
* @param DoliDB $db Object db
|
||||
* @param mixed $filterobj Filter on object Adherent|Societe|Project|Product|CommandeFournisseur|Dolresource|Ticket... to list events linked to an object
|
||||
* @param Contact $objcon Filter on object contact to filter events on a contact
|
||||
* @param int $noprint Return string but does not output it
|
||||
* @param string|string[] $actioncode Filter on actioncode
|
||||
* @param string $donetodo Filter on event 'done' or 'todo' or ''=nofilter (all).
|
||||
* @param array $filters Filter on other fields
|
||||
* @param string $sortfield Sort field
|
||||
* @param string $sortorder Sort order
|
||||
* @param string $module You can add module name here if elementtype in table llx_actioncomm is objectkey@module
|
||||
* @return string|void Return html part or void if noprint is 1
|
||||
*/
|
||||
function show_actions_done_user($conf, $langs, $db, $filterobj, $objcon = '', $noprint = 0, $actioncode = '', $donetodo = 'done', $filters = array(), $sortfield = 'a.datep,a.id', $sortorder = 'DESC', $module = '')
|
||||
{
|
||||
global $user, $conf, $hookmanager;
|
||||
global $form;
|
||||
global $param, $massactionbutton;
|
||||
|
||||
$start_year = GETPOST('dateevent_startyear', 'int');
|
||||
$start_month = GETPOST('dateevent_startmonth', 'int');
|
||||
$start_day = GETPOST('dateevent_startday', 'int');
|
||||
$end_year = GETPOST('dateevent_endyear', 'int');
|
||||
$end_month = GETPOST('dateevent_endmonth', 'int');
|
||||
$end_day = GETPOST('dateevent_endday', 'int');
|
||||
$tms_start = '';
|
||||
$tms_end = '';
|
||||
|
||||
if (!empty($start_year) && !empty($start_month) && !empty($start_day)) {
|
||||
$tms_start = dol_mktime(0, 0, 0, $start_month, $start_day, $start_year, 'tzuserrel');
|
||||
}
|
||||
if (!empty($end_year) && !empty($end_month) && !empty($end_day)) {
|
||||
$tms_end = dol_mktime(23, 59, 59, $end_month, $end_day, $end_year, 'tzuserrel');
|
||||
}
|
||||
if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All test are required to be compatible with all browsers
|
||||
$tms_start = '';
|
||||
$tms_end = '';
|
||||
}
|
||||
dol_include_once('/comm/action/class/actioncomm.class.php');
|
||||
|
||||
// Check parameters
|
||||
if (!is_object($filterobj) && !is_object($objcon)) {
|
||||
dol_print_error('', 'BadParameter');
|
||||
}
|
||||
|
||||
$out = '';
|
||||
$histo = array();
|
||||
$numaction = 0;
|
||||
$now = dol_now('tzuser');
|
||||
|
||||
// Open DSI -- Fix order by -- Begin
|
||||
$sortfield_list = explode(',', $sortfield);
|
||||
$sortfield_label_list = array('a.id' => 'id', 'a.datep' => 'dp', 'a.percent' => 'percent');
|
||||
$sortfield_new_list = array();
|
||||
foreach ($sortfield_list as $sortfield_value) {
|
||||
$sortfield_new_list[] = $sortfield_label_list[trim($sortfield_value)];
|
||||
}
|
||||
$sortfield_new = implode(',', $sortfield_new_list);
|
||||
|
||||
$sql = '';
|
||||
|
||||
if (isModEnabled('agenda')) {
|
||||
// Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
|
||||
$hookmanager->initHooks(array('agendadao'));
|
||||
|
||||
// Recherche histo sur actioncomm
|
||||
if (is_object($objcon) && $objcon->id > 0) {
|
||||
$sql = "SELECT DISTINCT a.id, a.label as label,";
|
||||
} else {
|
||||
$sql = "SELECT a.id, a.label as label,";
|
||||
}
|
||||
$sql .= " a.datep as dp,";
|
||||
$sql .= " a.datep2 as dp2,";
|
||||
$sql .= " a.percent as percent, 'action' as type,";
|
||||
$sql .= " a.fk_element, a.elementtype,";
|
||||
$sql .= " c.code as acode, c.libelle as alabel, c.picto as apicto,";
|
||||
$sql .= " u.rowid as user_id, u.login as user_login, u.photo as user_photo, u.firstname as user_firstname, u.lastname as user_lastname";
|
||||
if (is_object($filterobj) && in_array(get_class($filterobj), array('Societe', 'Client', 'Fournisseur'))) {
|
||||
$sql .= ", sp.lastname, sp.firstname";
|
||||
} elseif (is_object($filterobj) && get_class($filterobj) == 'Dolresource') {
|
||||
/* Nothing */
|
||||
} elseif (is_object($filterobj) && get_class($filterobj) == 'Project') {
|
||||
/* Nothing */
|
||||
} elseif (is_object($filterobj) && get_class($filterobj) == 'Adherent') {
|
||||
$sql .= ", m.lastname, m.firstname";
|
||||
} elseif (is_object($filterobj) && get_class($filterobj) == 'CommandeFournisseur') {
|
||||
$sql .= ", o.ref";
|
||||
} elseif (is_object($filterobj) && get_class($filterobj) == 'Product') {
|
||||
$sql .= ", o.ref";
|
||||
} elseif (is_object($filterobj) && get_class($filterobj) == 'Ticket') {
|
||||
$sql .= ", o.ref";
|
||||
} elseif (is_object($filterobj) && get_class($filterobj) == 'BOM') {
|
||||
$sql .= ", o.ref";
|
||||
} elseif (is_object($filterobj) && get_class($filterobj) == 'Contrat') {
|
||||
$sql .= ", o.ref";
|
||||
} elseif (is_object($filterobj) && is_array($filterobj->fields) && is_array($filterobj->fields['rowid']) && $filterobj->table_element && $filterobj->element) {
|
||||
if (!empty($filterobj->fields['ref'])) {
|
||||
$sql .= ", o.ref";
|
||||
} elseif (!empty($filterobj->fields['label'])) {
|
||||
$sql .= ", o.label";
|
||||
}
|
||||
}
|
||||
|
||||
// Fields from hook
|
||||
$parameters = array('sql' => &$sql, 'filterobj' => $filterobj, 'objcon' => $objcon);
|
||||
$reshook = $hookmanager->executeHooks('showActionsDoneListSelect', $parameters); // Note that $action and $object may have been modified by hook
|
||||
if (!empty($hookmanager->resPrint)) {
|
||||
$sql.= $hookmanager->resPrint;
|
||||
}
|
||||
|
||||
$sql .= " FROM ".MAIN_DB_PREFIX."actioncomm as a";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."user as u on u.rowid = a.fk_user_action";
|
||||
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."c_actioncomm as c ON a.fk_action = c.id";
|
||||
$force_filter_contact = false;
|
||||
if (is_object($objcon) && $objcon->id > 0) {
|
||||
$force_filter_contact = true;
|
||||
$sql .= " INNER JOIN ".MAIN_DB_PREFIX."actioncomm_resources as r ON a.id = r.fk_actioncomm";
|
||||
$sql .= " AND r.element_type = '".$db->escape($objcon->table_element)."' AND r.fk_element = ".((int) $objcon->id);
|
||||
}
|
||||
|
||||
|
||||
// Fields from hook
|
||||
$parameters = array('sql' => &$sql, 'filterobj' => $filterobj, 'objcon' => $objcon);
|
||||
$reshook = $hookmanager->executeHooks('showActionsDoneListFrom', $parameters); // Note that $action and $object may have been modified by hook
|
||||
if (!empty($hookmanager->resPrint)) {
|
||||
$sql.= $hookmanager->resPrint;
|
||||
}
|
||||
|
||||
$sql .= " WHERE a.entity IN (".getEntity('agenda').")";
|
||||
$sql .= " AND u.rowid = ".((int) $filterobj->id);
|
||||
|
||||
|
||||
if (!empty($tms_start) && !empty($tms_end)) {
|
||||
$sql .= " AND ((a.datep BETWEEN '".$db->idate($tms_start)."' AND '".$db->idate($tms_end)."') OR (a.datep2 BETWEEN '".$db->idate($tms_start)."' AND '".$db->idate($tms_end)."'))";
|
||||
} elseif (empty($tms_start) && !empty($tms_end)) {
|
||||
$sql .= " AND ((a.datep <= '".$db->idate($tms_end)."') OR (a.datep2 <= '".$db->idate($tms_end)."'))";
|
||||
} elseif (!empty($tms_start) && empty($tms_end)) {
|
||||
$sql .= " AND ((a.datep >= '".$db->idate($tms_start)."') OR (a.datep2 >= '".$db->idate($tms_start)."'))";
|
||||
}
|
||||
if (is_array($actioncode) && !empty($actioncode)) {
|
||||
$sql .= ' AND (';
|
||||
foreach ($actioncode as $key => $code) {
|
||||
if ($key != 0) {
|
||||
$sql .= " OR ";
|
||||
}
|
||||
if (!empty($code)) {
|
||||
addEventTypeSQL($sql, $code, "");
|
||||
}
|
||||
}
|
||||
$sql .= ')';
|
||||
} elseif (!empty($actioncode)) {
|
||||
addEventTypeSQL($sql, $actioncode);
|
||||
}
|
||||
|
||||
addOtherFilterSQL($sql, $donetodo, $now, $filters);
|
||||
|
||||
// Fields from hook
|
||||
$parameters = array('sql' => &$sql, 'filterobj' => $filterobj, 'objcon' => $objcon, 'module' => $module);
|
||||
$reshook = $hookmanager->executeHooks('showActionsDoneListWhere', $parameters); // Note that $action and $object may have been modified by hook
|
||||
if (!empty($hookmanager->resPrint)) {
|
||||
$sql.= $hookmanager->resPrint;
|
||||
}
|
||||
|
||||
if (is_array($actioncode)) {
|
||||
foreach ($actioncode as $code) {
|
||||
$sql2 = addMailingEventTypeSQL($code, $objcon, $filterobj);
|
||||
if (!empty($sql2)) {
|
||||
if (!empty($sql)) {
|
||||
$sql = $sql." UNION ".$sql2;
|
||||
} elseif (empty($sql)) {
|
||||
$sql = $sql2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$sql2 = addMailingEventTypeSQL($actioncode, $objcon, $filterobj);
|
||||
if (!empty($sql) && !empty($sql2)) {
|
||||
$sql = $sql." UNION ".$sql2;
|
||||
} elseif (empty($sql) && !empty($sql2)) {
|
||||
$sql = $sql2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO Add limit in nb of results
|
||||
if ($sql) {
|
||||
$sql .= $db->order($sortfield_new, $sortorder);
|
||||
|
||||
dol_syslog("usergroups.lib::show_actions_dones", LOG_DEBUG);
|
||||
|
||||
$resql = $db->query($sql);
|
||||
if ($resql) {
|
||||
$i = 0;
|
||||
$num = $db->num_rows($resql);
|
||||
|
||||
while ($i < $num) {
|
||||
$obj = $db->fetch_object($resql);
|
||||
|
||||
if ($obj->type == 'action') {
|
||||
$contactaction = new ActionComm($db);
|
||||
$contactaction->id = $obj->id;
|
||||
$result = $contactaction->fetchResources();
|
||||
if ($result < 0) {
|
||||
dol_print_error($db);
|
||||
setEventMessage("user.lib::show_actions_done Error fetch resource", 'errors');
|
||||
}
|
||||
|
||||
//if ($donetodo == 'todo') $sql.= " AND ((a.percent >= 0 AND a.percent < 100) OR (a.percent = -1 AND a.datep > '".$db->idate($now)."'))";
|
||||
//elseif ($donetodo == 'done') $sql.= " AND (a.percent = 100 OR (a.percent = -1 AND a.datep <= '".$db->idate($now)."'))";
|
||||
$tododone = '';
|
||||
if (($obj->percent >= 0 and $obj->percent < 100) || ($obj->percent == -1 && (!empty($obj->datep) && $obj->datep > $now))) {
|
||||
$tododone = 'todo';
|
||||
}
|
||||
|
||||
$histo[$numaction] = array(
|
||||
'type'=>$obj->type,
|
||||
'tododone'=>$tododone,
|
||||
'id'=>$obj->id,
|
||||
'datestart'=>$db->jdate($obj->dp),
|
||||
'dateend'=>$db->jdate($obj->dp2),
|
||||
'note'=>$obj->label,
|
||||
'percent'=>$obj->percent,
|
||||
|
||||
'userid'=>$obj->user_id,
|
||||
'login'=>$obj->user_login,
|
||||
'userfirstname'=>$obj->user_firstname,
|
||||
'userlastname'=>$obj->user_lastname,
|
||||
'userphoto'=>$obj->user_photo,
|
||||
|
||||
'contact_id'=>$obj->fk_contact,
|
||||
'socpeopleassigned' => $contactaction->socpeopleassigned,
|
||||
'lastname' => empty($obj->lastname) ? '' : $obj->lastname,
|
||||
'firstname' => empty($obj->firstname) ? '' : $obj->firstname,
|
||||
'fk_element'=>$obj->fk_element,
|
||||
'elementtype'=>$obj->elementtype,
|
||||
// Type of event
|
||||
'acode'=>$obj->acode,
|
||||
'alabel'=>$obj->alabel,
|
||||
'libelle'=>$obj->alabel, // deprecated
|
||||
'apicto'=>$obj->apicto
|
||||
);
|
||||
} else {
|
||||
$histo[$numaction] = array(
|
||||
'type'=>$obj->type,
|
||||
'tododone'=>'done',
|
||||
'id'=>$obj->id,
|
||||
'datestart'=>$db->jdate($obj->dp),
|
||||
'dateend'=>$db->jdate($obj->dp2),
|
||||
'note'=>$obj->label,
|
||||
'percent'=>$obj->percent,
|
||||
'acode'=>$obj->acode,
|
||||
|
||||
'userid'=>$obj->user_id,
|
||||
'login'=>$obj->user_login,
|
||||
'userfirstname'=>$obj->user_firstname,
|
||||
'userlastname'=>$obj->user_lastname,
|
||||
'userphoto'=>$obj->user_photo
|
||||
);
|
||||
}
|
||||
|
||||
$numaction++;
|
||||
$i++;
|
||||
}
|
||||
} else {
|
||||
dol_print_error($db);
|
||||
}
|
||||
}
|
||||
|
||||
if (isModEnabled('agenda')|| (isModEnabled('mailing') && !empty($objcon->email))) {
|
||||
$delay_warning = $conf->global->MAIN_DELAY_ACTIONS_TODO * 24 * 60 * 60;
|
||||
|
||||
require_once DOL_DOCUMENT_ROOT.'/comm/action/class/actioncomm.class.php';
|
||||
include_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formactions.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/contact/class/contact.class.php';
|
||||
|
||||
$formactions = new FormActions($db);
|
||||
|
||||
$actionstatic = new ActionComm($db);
|
||||
$userstatic = new User($db);
|
||||
$userlinkcache = array();
|
||||
$contactstatic = new Contact($db);
|
||||
$elementlinkcache = array();
|
||||
|
||||
$out .= '<form name="listactionsfilter" class="listactionsfilter" action="'.$_SERVER["PHP_SELF"].'?id='.$filterobj->id.'" method="POST">';
|
||||
$out .= '<input type="hidden" name="token" value="'.newToken().'">';
|
||||
if ($objcon && get_class($objcon) == 'User' &&
|
||||
(is_null($filterobj) || get_class($filterobj) == 'User')) {
|
||||
$out .= '<input type="hidden" name="id" value="'.$objcon->id.'" />';
|
||||
} else {
|
||||
$out .= '<input type="hidden" name="id" value="'.$filterobj->id.'" />';
|
||||
}
|
||||
if ($filterobj && get_class($filterobj) == 'User') {
|
||||
$out .= '<input type="hidden" name="id" value="'.$filterobj->id.'" />';
|
||||
}
|
||||
|
||||
$out .= "\n";
|
||||
|
||||
$out .= '<div class="div-table-responsive-no-min">';
|
||||
$out .= '<table class="noborder centpercent">';
|
||||
|
||||
$out .= '<tr class="liste_titre">';
|
||||
|
||||
// Action column
|
||||
if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
|
||||
$out .= '<th class="liste_titre width50 middle">';
|
||||
$searchpicto = $form->showFilterAndCheckAddButtons($massactionbutton ? 1 : 0, 'checkforselect', 1);
|
||||
$out .= $searchpicto;
|
||||
$out .= '</th>';
|
||||
}
|
||||
|
||||
if ($donetodo) {
|
||||
$out .= '<td class="liste_titre"></td>';
|
||||
}
|
||||
|
||||
$out .= '<td class="liste_titre"><input type="text" class="width50" name="search_rowid" value="'.(isset($filters['search_rowid']) ? $filters['search_rowid'] : '').'"></td>';
|
||||
$out .= '<td class="liste_titre"></td>';
|
||||
$out .= '<td class="liste_titre">';
|
||||
$out .= $formactions->select_type_actions($actioncode, "actioncode", '', !getDolGlobalString('AGENDA_USE_EVENT_TYPE') ? 1 : -1, 0, (!getDolGlobalString('AGENDA_USE_MULTISELECT_TYPE') ? 0 : 1), 1, 'minwidth100 maxwidth150');
|
||||
$out .= '</td>';
|
||||
$out .= '<td class="liste_titre maxwidth100onsmartphone"><input type="text" class="maxwidth100onsmartphone" name="search_agenda_label" value="'.$filters['search_agenda_label'].'"></td>';
|
||||
$out .= '<td class="liste_titre center">';
|
||||
$out .= $form->selectDateToDate($tms_start, $tms_end, 'dateevent', 1);
|
||||
$out .= '</td>';
|
||||
$out .= '<td class="liste_titre"></td>';
|
||||
$out .= '<td class="liste_titre"></td>';
|
||||
// Action column
|
||||
if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
|
||||
$out .= '<td class="liste_titre" align="middle">';
|
||||
$searchpicto = $form->showFilterAndCheckAddButtons($massactionbutton ? 1 : 0, 'checkforselect', 1);
|
||||
$out .= $searchpicto;
|
||||
$out .= '</td>';
|
||||
}
|
||||
$out .= '</tr>';
|
||||
|
||||
$out .= '<tr class="liste_titre">';
|
||||
// Action column
|
||||
if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
|
||||
$out .= getTitleFieldOfList('', 0, $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'maxwidthsearch ');
|
||||
}
|
||||
if ($donetodo) {
|
||||
$tmp = '';
|
||||
if (get_class($filterobj) == 'User') {
|
||||
$tmp .= '<a href="'.DOL_URL_ROOT.'/comm/action/list.php?mode=show_list&userid='.$filterobj->id.'&status=done">';
|
||||
}
|
||||
$tmp .= ($donetodo != 'done' ? $langs->trans("ActionsToDoShort") : '');
|
||||
$tmp .= ($donetodo != 'done' && $donetodo != 'todo' ? ' / ' : '');
|
||||
$tmp .= ($donetodo != 'todo' ? $langs->trans("ActionsDoneShort") : '');
|
||||
//$out.=$langs->trans("ActionsToDoShort").' / '.$langs->trans("ActionsDoneShort");
|
||||
if (get_class($filterobj) == 'User') {
|
||||
$tmp .= '</a>';
|
||||
}
|
||||
$out .= getTitleFieldOfList($tmp);
|
||||
}
|
||||
$out .= getTitleFieldOfList("Ref", 0, $_SERVER["PHP_SELF"], 'a.id', '', $param, '', $sortfield, $sortorder);
|
||||
$out .= getTitleFieldOfList("Owner");
|
||||
$out .= getTitleFieldOfList("Type");
|
||||
$out .= getTitleFieldOfList("Label", 0, $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder);
|
||||
$out .= getTitleFieldOfList("Date", 0, $_SERVER["PHP_SELF"], 'a.datep,a.id', '', $param, '', $sortfield, $sortorder, 'center ');
|
||||
$out .= getTitleFieldOfList("Status", 0, $_SERVER["PHP_SELF"], 'a.percent', '', $param, '', $sortfield, $sortorder, 'center ');
|
||||
// Action column
|
||||
if (!getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
|
||||
$out .= getTitleFieldOfList('', 0, $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'maxwidthsearch ');
|
||||
}
|
||||
$out .= '<td></td>';
|
||||
$out .= '</tr>';
|
||||
|
||||
require_once DOL_DOCUMENT_ROOT.'/comm/action/class/cactioncomm.class.php';
|
||||
$caction = new CActionComm($db);
|
||||
$arraylist = $caction->liste_array(1, 'code', '', (!getDolGlobalString('AGENDA_USE_EVENT_TYPE') ? 1 : 0), '', 1);
|
||||
|
||||
foreach ($histo as $key => $value) {
|
||||
$actionstatic->fetch($histo[$key]['id']); // TODO Do we need this, we already have a lot of data of line into $histo
|
||||
|
||||
$actionstatic->type_picto = $histo[$key]['apicto'];
|
||||
$actionstatic->type_code = $histo[$key]['acode'];
|
||||
|
||||
$out .= '<tr class="oddeven">';
|
||||
|
||||
// Action column
|
||||
if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
|
||||
$out .= '<td></td>';
|
||||
}
|
||||
|
||||
// Done or todo
|
||||
if ($donetodo) {
|
||||
$out .= '<td class="nowrap">';
|
||||
$out .= '</td>';
|
||||
}
|
||||
|
||||
// Ref
|
||||
$out .= '<td class="nowraponall">';
|
||||
if (isset($histo[$key]['type']) && $histo[$key]['type'] == 'mailing') {
|
||||
$out .= '<a href="'.DOL_URL_ROOT.'/comm/mailing/card.php?id='.$histo[$key]['id'].'">'.img_object($langs->trans("ShowEMailing"), "email").' ';
|
||||
$out .= $histo[$key]['id'];
|
||||
$out .= '</a>';
|
||||
} else {
|
||||
$out .= $actionstatic->getNomUrl(1, -1);
|
||||
}
|
||||
$out .= '</td>';
|
||||
|
||||
// Author of event
|
||||
$out .= '<td class="tdoverflowmax125">';
|
||||
if ($histo[$key]['userid'] > 0) {
|
||||
if (isset($userlinkcache[$histo[$key]['userid']])) {
|
||||
$link = $userlinkcache[$histo[$key]['userid']];
|
||||
} else {
|
||||
$userstatic->fetch($histo[$key]['userid']);
|
||||
$link = $userstatic->getNomUrl(-1, '', 0, 0, 16, 0, 'firstelselast', '');
|
||||
$userlinkcache[$histo[$key]['userid']] = $link;
|
||||
}
|
||||
$out .= $link;
|
||||
}
|
||||
$out .= '</td>';
|
||||
|
||||
// Type
|
||||
$labeltype = $actionstatic->type_code;
|
||||
if (!getDolGlobalString('AGENDA_USE_EVENT_TYPE') && empty($arraylist[$labeltype])) {
|
||||
$labeltype = 'AC_OTH';
|
||||
}
|
||||
if (!empty($actionstatic->code) && preg_match('/^TICKET_MSG/', $actionstatic->code)) {
|
||||
$labeltype = $langs->trans("Message");
|
||||
} else {
|
||||
if (!empty($arraylist[$labeltype])) {
|
||||
$labeltype = $arraylist[$labeltype];
|
||||
}
|
||||
if ($actionstatic->type_code == 'AC_OTH_AUTO' && ($actionstatic->type_code != $actionstatic->code) && $labeltype && !empty($arraylist[$actionstatic->code])) {
|
||||
$labeltype .= ' - '.$arraylist[$actionstatic->code]; // Use code in priority on type_code
|
||||
}
|
||||
}
|
||||
$out .= '<td class="tdoverflowmax125" title="'.$labeltype.'">';
|
||||
$out .= $actionstatic->getTypePicto();
|
||||
//if (empty($conf->dol_optimize_smallscreen)) {
|
||||
$out .= $labeltype;
|
||||
//}
|
||||
$out .= '</td>';
|
||||
|
||||
// Title/Label of event
|
||||
$out .= '<td class="tdoverflowmax300"';
|
||||
if (isset($histo[$key]['type']) && $histo[$key]['type'] == 'action') {
|
||||
$transcode = $langs->trans("Action".$histo[$key]['acode']);
|
||||
//$libelle = ($transcode != "Action".$histo[$key]['acode'] ? $transcode : $histo[$key]['alabel']);
|
||||
$libelle = $histo[$key]['note'];
|
||||
$actionstatic->id = $histo[$key]['id'];
|
||||
$out .= ' title="'.dol_escape_htmltag($libelle).'">';
|
||||
$out .= dol_trunc($libelle, 120);
|
||||
}
|
||||
if (isset($histo[$key]['type']) && $histo[$key]['type'] == 'mailing') {
|
||||
$out .= '<a href="'.DOL_URL_ROOT.'/comm/mailing/card.php?id='.$histo[$key]['id'].'">'.img_object($langs->trans("ShowEMailing"), "email").' ';
|
||||
$transcode = $langs->trans("Action".$histo[$key]['acode']);
|
||||
$libelle = ($transcode != "Action".$histo[$key]['acode'] ? $transcode : 'Send mass mailing');
|
||||
$out .= ' title="'.dol_escape_htmltag($libelle).'">';
|
||||
$out .= dol_trunc($libelle, 120);
|
||||
}
|
||||
$out .= '</td>';
|
||||
|
||||
// Date
|
||||
$out .= '<td class="center nowraponall">';
|
||||
$out .= dol_print_date($histo[$key]['datestart'], 'dayhour', 'tzuserrel');
|
||||
if ($histo[$key]['dateend'] && $histo[$key]['dateend'] != $histo[$key]['datestart']) {
|
||||
$tmpa = dol_getdate($histo[$key]['datestart'], true);
|
||||
$tmpb = dol_getdate($histo[$key]['dateend'], true);
|
||||
if ($tmpa['mday'] == $tmpb['mday'] && $tmpa['mon'] == $tmpb['mon'] && $tmpa['year'] == $tmpb['year']) {
|
||||
$out .= '-'.dol_print_date($histo[$key]['dateend'], 'hour', 'tzuserrel');
|
||||
} else {
|
||||
$out .= '-'.dol_print_date($histo[$key]['dateend'], 'dayhour', 'tzuserrel');
|
||||
}
|
||||
}
|
||||
$late = 0;
|
||||
if ($histo[$key]['percent'] == 0 && $histo[$key]['datestart'] && $histo[$key]['datestart'] < ($now - $delay_warning)) {
|
||||
$late = 1;
|
||||
}
|
||||
if ($histo[$key]['percent'] == 0 && !$histo[$key]['datestart'] && $histo[$key]['dateend'] && $histo[$key]['datestart'] < ($now - $delay_warning)) {
|
||||
$late = 1;
|
||||
}
|
||||
if ($histo[$key]['percent'] > 0 && $histo[$key]['percent'] < 100 && $histo[$key]['dateend'] && $histo[$key]['dateend'] < ($now - $delay_warning)) {
|
||||
$late = 1;
|
||||
}
|
||||
if ($histo[$key]['percent'] > 0 && $histo[$key]['percent'] < 100 && !$histo[$key]['dateend'] && $histo[$key]['datestart'] && $histo[$key]['datestart'] < ($now - $delay_warning)) {
|
||||
$late = 1;
|
||||
}
|
||||
if ($late) {
|
||||
$out .= img_warning($langs->trans("Late")).' ';
|
||||
}
|
||||
$out .= "</td>\n";
|
||||
|
||||
// Status
|
||||
$out .= '<td class="nowrap center">'.$actionstatic->LibStatut($histo[$key]['percent'], 2, 0, $histo[$key]['datestart']).'</td>';
|
||||
// Action column
|
||||
if (getDolGlobalString('MAIN_CHECKBOX_LEFT_COLUMN')) {
|
||||
$out .= '<td></td>';
|
||||
}
|
||||
|
||||
$out .= "</tr>\n";
|
||||
$i++;
|
||||
}
|
||||
if (empty($histo)) {
|
||||
$colspan = 9;
|
||||
$out .= '<tr><td colspan="'.$colspan.'"><span class="opacitymedium">'.$langs->trans("NoRecordFound").'</span></td></tr>';
|
||||
}
|
||||
|
||||
$out .= "</table>\n";
|
||||
$out .= "</div>\n";
|
||||
|
||||
$out .= '</form>';
|
||||
}
|
||||
|
||||
if ($noprint) {
|
||||
return $out;
|
||||
} else {
|
||||
print $out;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
/* Copyright (C) 2006-2015 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2012 Marcos García <marcosgdf@gmail.com>
|
||||
* Copyright (C) 2024 William Mead <william.mead@manchenumerique.fr>
|
||||
*
|
||||
* 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
|
||||
@@ -651,11 +652,11 @@ class ExportExcel2007 extends ModeleExports
|
||||
/**
|
||||
* Set a value cell and merging it by giving a starting cell and a length
|
||||
*
|
||||
* @param string $val Cell value
|
||||
* @param string $startCell Starting cell
|
||||
* @param int $length Length
|
||||
* @param int $offset Starting offset
|
||||
* @return string Coordinate or -1 if KO
|
||||
* @param string $val Cell value
|
||||
* @param string $startCell Starting cell
|
||||
* @param int $length Length
|
||||
* @param int $offset Starting offset
|
||||
* @return int|string Coordinate or if KO: -1
|
||||
*/
|
||||
public function setMergeCellValueByLength($val, $startCell, $length, $offset = 0)
|
||||
{
|
||||
|
||||
570
htdocs/core/modules/modAi.class.php
Normal file
570
htdocs/core/modules/modAi.class.php
Normal file
@@ -0,0 +1,570 @@
|
||||
<?php
|
||||
/* Copyright (C) 2004-2018 Laurent Destailleur <eldy@users.sourceforge.net>
|
||||
* Copyright (C) 2018-2019 Nicolas ZABOURI <info@inovea-conseil.com>
|
||||
* Copyright (C) 2019-2022 Frédéric France <frederic.france@netlogic.fr>
|
||||
*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* \defgroup ai Module Ai
|
||||
* \brief Ai module descriptor.
|
||||
*
|
||||
* \file htdocs/ai/core/modules/modAi.class.php
|
||||
* \ingroup ai
|
||||
* \brief Description and activation file for module Ai
|
||||
*/
|
||||
include_once DOL_DOCUMENT_ROOT.'/core/modules/DolibarrModules.class.php';
|
||||
|
||||
/**
|
||||
* Description and activation class for module Ai
|
||||
*/
|
||||
class modAi extends DolibarrModules
|
||||
{
|
||||
/**
|
||||
* Constructor. Define names, constants, directories, boxes, permissions
|
||||
*
|
||||
* @param DoliDB $db Database handler
|
||||
*/
|
||||
public function __construct($db)
|
||||
{
|
||||
global $langs, $conf;
|
||||
|
||||
$this->db = $db;
|
||||
|
||||
// Id for module (must be unique).
|
||||
// Use here a free id (See in Home -> System information -> Dolibarr for list of used modules id).
|
||||
$this->numero = 4560;
|
||||
|
||||
// Key text used to identify module (for permissions, menus, etc...)
|
||||
$this->rights_class = 'ai';
|
||||
|
||||
// Family can be 'base' (core modules),'crm','financial','hr','projects','products','ecm','technic' (transverse modules),'interface' (link with external tools),'other','...'
|
||||
// It is used to group modules by family in module setup page
|
||||
$this->family = "mailings";
|
||||
|
||||
// Module position in the family on 2 digits ('01', '10', '20', ...)
|
||||
$this->module_position = '50';
|
||||
|
||||
// Gives the possibility for the module, to provide his own family info and position of this family (Overwrite $this->family and $this->module_position. Avoid this)
|
||||
//$this->familyinfo = array('myownfamily' => array('position' => '01', 'label' => $langs->trans("MyOwnFamily")));
|
||||
// Module label (no space allowed), used if translation string 'ModuleAiName' not found (Ai is name of module).
|
||||
$this->name = preg_replace('/^mod/i', '', get_class($this));
|
||||
|
||||
// Module description, used if translation string 'ModuleAiDesc' not found (Ai is name of module).
|
||||
$this->description = "AiDescription";
|
||||
// Used only if file README.md and README-LL.md not found.
|
||||
$this->descriptionlong = "AiDescription";
|
||||
|
||||
// Possible values for version are: 'development', 'experimental', 'dolibarr', 'dolibarr_deprecated' or a version string like 'x.y.z'
|
||||
$this->version = 'development';
|
||||
|
||||
// Key used in llx_const table to save module status enabled/disabled (where BOOKCAL is value of property name of module in uppercase)
|
||||
$this->const_name = 'MAIN_MODULE_'.strtoupper($this->name);
|
||||
|
||||
// Name of image file used for this module.
|
||||
// If file is in theme/yourtheme/img directory under name object_pictovalue.png, use this->picto='pictovalue'
|
||||
// If file is in module/img directory under name object_pictovalue.png, use this->picto='pictovalue@module'
|
||||
// To use a supported fa-xxx css style of font awesome, use this->picto='xxx'
|
||||
$this->picto = 'fa-microchip"';
|
||||
|
||||
// Define some features supported by module (triggers, login, substitutions, menus, css, etc...)
|
||||
$this->module_parts = array(
|
||||
// Set this to 1 if module has its own trigger directory (core/triggers)
|
||||
'triggers' => 0,
|
||||
// Set this to 1 if module has its own login method file (core/login)
|
||||
'login' => 0,
|
||||
// Set this to 1 if module has its own substitution function file (core/substitutions)
|
||||
'substitutions' => 0,
|
||||
// Set this to 1 if module has its own menus handler directory (core/menus)
|
||||
'menus' => 0,
|
||||
// Set this to 1 if module overwrite template dir (core/tpl)
|
||||
'tpl' => 0,
|
||||
// Set this to 1 if module has its own barcode directory (core/modules/barcode)
|
||||
'barcode' => 0,
|
||||
// Set this to 1 if module has its own models directory (core/modules/xxx)
|
||||
'models' => 0,
|
||||
// Set this to 1 if module has its own printing directory (core/modules/printing)
|
||||
'printing' => 0,
|
||||
// Set this to 1 if module has its own theme directory (theme)
|
||||
'theme' => 0,
|
||||
// Set this to relative path of css file if module has its own css file
|
||||
'css' => array(
|
||||
// '/ai/css/ai.css.php',
|
||||
),
|
||||
// Set this to relative path of js file if module must load a js on all pages
|
||||
'js' => array(
|
||||
// '/ai/js/ai.js.php',
|
||||
),
|
||||
// Set here all hooks context managed by module. To find available hook context, make a "grep -r '>initHooks(' *" on source code. You can also set hook context to 'all'
|
||||
'hooks' => array(
|
||||
// 'data' => array(
|
||||
// 'hookcontext1',
|
||||
// 'hookcontext2',
|
||||
// ),
|
||||
// 'entity' => '0',
|
||||
),
|
||||
// Set this to 1 if features of module are opened to external users
|
||||
'moduleforexternal' => 0,
|
||||
);
|
||||
|
||||
// Data directories to create when module is enabled.
|
||||
// Example: this->dirs = array("/ai/temp","/ai/subdir");
|
||||
$this->dirs = array("/ai/temp");
|
||||
|
||||
// Config pages. Put here list of php page, stored into ai/admin directory, to use to setup module.
|
||||
$this->config_page_url = array("setup.php@ai");
|
||||
|
||||
// Dependencies
|
||||
// A condition to hide module
|
||||
$this->hidden = false;
|
||||
// List of module class names as string that must be enabled if this module is enabled. Example: array('always'=>array('modModuleToEnable1','modModuleToEnable2'), 'FR'=>array('modModuleToEnableFR'...))
|
||||
$this->depends = array();
|
||||
$this->requiredby = array(); // List of module class names as string to disable if this one is disabled. Example: array('modModuleToDisable1', ...)
|
||||
$this->conflictwith = array(); // List of module class names as string this module is in conflict with. Example: array('modModuleToDisable1', ...)
|
||||
|
||||
// The language file dedicated to your module
|
||||
$this->langfiles = array("ai");
|
||||
|
||||
// Prerequisites
|
||||
$this->phpmin = array(7, 0); // Minimum version of PHP required by module
|
||||
|
||||
// Messages at activation
|
||||
$this->warnings_activation = array(); // Warning to show when we activate module. array('always'='text') or array('FR'='textfr','MX'='textmx'...)
|
||||
$this->warnings_activation_ext = array(); // Warning to show when we activate an external module. array('always'='text') or array('FR'='textfr','MX'='textmx'...)
|
||||
//$this->automatic_activation = array('FR'=>'AiWasAutomaticallyActivatedBecauseOfYourCountryChoice');
|
||||
//$this->always_enabled = true; // If true, can't be disabled
|
||||
|
||||
// Constants
|
||||
// List of particular constants to add when module is enabled (key, 'chaine', value, desc, visible, 'current' or 'allentities', deleteonunactive)
|
||||
// Example: $this->const=array(1 => array('BOOKCAL_MYNEWCONST1', 'chaine', 'myvalue', 'This is a constant to add', 1),
|
||||
// 2 => array('BOOKCAL_MYNEWCONST2', 'chaine', 'myvalue', 'This is another constant to add', 0, 'current', 1)
|
||||
// );
|
||||
$this->const = array();
|
||||
|
||||
// Some keys to add into the overwriting translation tables
|
||||
/*$this->overwrite_translation = array(
|
||||
'en_US:ParentCompany'=>'Parent company or reseller',
|
||||
'fr_FR:ParentCompany'=>'Maison mère ou revendeur'
|
||||
)*/
|
||||
|
||||
if (!isset($conf->ai) || !isset($conf->ai->enabled)) {
|
||||
$conf->ai = new stdClass();
|
||||
$conf->ai->enabled = 0;
|
||||
}
|
||||
|
||||
// Array to add new pages in new tabs
|
||||
$this->tabs = array();
|
||||
// Example:
|
||||
// $this->tabs[] = array('data'=>'objecttype:+tabname1:Title1:mylangfile@ai:$user->rights->ai->read:/ai/mynewtab1.php?id=__ID__'); // To add a new tab identified by code tabname1
|
||||
// $this->tabs[] = array('data'=>'objecttype:+tabname2:SUBSTITUTION_Title2:mylangfile@ai:$user->rights->othermodule->read:/ai/mynewtab2.php?id=__ID__', // To add another new tab identified by code tabname2. Label will be result of calling all substitution functions on 'Title2' key.
|
||||
// $this->tabs[] = array('data'=>'objecttype:-tabname:NU:conditiontoremove'); // To remove an existing tab identified by code tabname
|
||||
//
|
||||
// Where objecttype can be
|
||||
// 'categories_x' to add a tab in category view (replace 'x' by type of category (0=product, 1=supplier, 2=customer, 3=member)
|
||||
// 'contact' to add a tab in contact view
|
||||
// 'contract' to add a tab in contract view
|
||||
// 'group' to add a tab in group view
|
||||
// 'intervention' to add a tab in intervention view
|
||||
// 'invoice' to add a tab in customer invoice view
|
||||
// 'invoice_supplier' to add a tab in supplier invoice view
|
||||
// 'member' to add a tab in foundation member view
|
||||
// 'opensurveypoll' to add a tab in opensurvey poll view
|
||||
// 'order' to add a tab in customer order view
|
||||
// 'order_supplier' to add a tab in supplier order view
|
||||
// 'payment' to add a tab in payment view
|
||||
// 'payment_supplier' to add a tab in supplier payment view
|
||||
// 'product' to add a tab in product view
|
||||
// 'propal' to add a tab in propal view
|
||||
// 'project' to add a tab in project view
|
||||
// 'stock' to add a tab in stock view
|
||||
// 'thirdparty' to add a tab in third party view
|
||||
// 'user' to add a tab in user view
|
||||
|
||||
// Dictionaries
|
||||
$this->dictionaries = array();
|
||||
/* Example:
|
||||
$this->dictionaries=array(
|
||||
'langs'=>'ai@ai',
|
||||
// List of tables we want to see into dictonnary editor
|
||||
'tabname'=>array("table1", "table2", "table3"),
|
||||
// Label of tables
|
||||
'tablib'=>array("Table1", "Table2", "Table3"),
|
||||
// Request to select fields
|
||||
'tabsql'=>array('SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table1 as f', 'SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table2 as f', 'SELECT f.rowid as rowid, f.code, f.label, f.active FROM '.MAIN_DB_PREFIX.'table3 as f'),
|
||||
// Sort order
|
||||
'tabsqlsort'=>array("label ASC", "label ASC", "label ASC"),
|
||||
// List of fields (result of select to show dictionary)
|
||||
'tabfield'=>array("code,label", "code,label", "code,label"),
|
||||
// List of fields (list of fields to edit a record)
|
||||
'tabfieldvalue'=>array("code,label", "code,label", "code,label"),
|
||||
// List of fields (list of fields for insert)
|
||||
'tabfieldinsert'=>array("code,label", "code,label", "code,label"),
|
||||
// Name of columns with primary key (try to always name it 'rowid')
|
||||
'tabrowid'=>array("rowid", "rowid", "rowid"),
|
||||
// Condition to show each dictionary
|
||||
'tabcond'=>array($conf->ai->enabled, $conf->ai->enabled, $conf->ai->enabled)
|
||||
// Help tooltip for each fields of the dictionary
|
||||
'tabhelp'=>array(array('code'=>$langs->trans('CodeTooltipHelp')))
|
||||
);
|
||||
*/
|
||||
|
||||
// Boxes/Widgets
|
||||
// Add here list of php file(s) stored in ai/core/boxes that contains a class to show a widget.
|
||||
$this->boxes = array(
|
||||
// 0 => array(
|
||||
// 'file' => 'aiwidget1.php@ai',
|
||||
// 'note' => 'Widget provided by Ai',
|
||||
// 'enabledbydefaulton' => 'Home',
|
||||
// ),
|
||||
// ...
|
||||
);
|
||||
|
||||
// Cronjobs (List of cron jobs entries to add when module is enabled)
|
||||
// unit_frequency must be 60 for minute, 3600 for hour, 86400 for day, 604800 for week
|
||||
$this->cronjobs = array(
|
||||
// 0 => array(
|
||||
// 'label' => 'MyJob label',
|
||||
// 'jobtype' => 'method',
|
||||
// 'class' => '/ai/class/availabilities.class.php',
|
||||
// 'objectname' => 'Availabilities',
|
||||
// 'method' => 'doScheduledJob',
|
||||
// 'parameters' => '',
|
||||
// 'comment' => 'Comment',
|
||||
// 'frequency' => 2,
|
||||
// 'unitfrequency' => 3600,
|
||||
// 'status' => 0,
|
||||
// 'test' => '$conf->ai->enabled',
|
||||
// 'priority' => 50,
|
||||
// ),
|
||||
);
|
||||
// Example: $this->cronjobs=array(
|
||||
// 0=>array('label'=>'My label', 'jobtype'=>'method', 'class'=>'/dir/class/file.class.php', 'objectname'=>'MyClass', 'method'=>'myMethod', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>2, 'unitfrequency'=>3600, 'status'=>0, 'test'=>'$conf->ai->enabled', 'priority'=>50),
|
||||
// 1=>array('label'=>'My label', 'jobtype'=>'command', 'command'=>'', 'parameters'=>'param1, param2', 'comment'=>'Comment', 'frequency'=>1, 'unitfrequency'=>3600*24, 'status'=>0, 'test'=>'$conf->ai->enabled', 'priority'=>50)
|
||||
// );
|
||||
|
||||
// Permissions provided by this module
|
||||
$this->rights = array();
|
||||
$r = 0;
|
||||
// Add here entries to declare new permissions
|
||||
/* BEGIN MODULEBUILDER PERMISSIONS */
|
||||
$this->rights[$r][0] = $this->numero . sprintf('%02d', (0 * 10) + 1);
|
||||
$this->rights[$r][1] = 'Read objects of Ai';
|
||||
$this->rights[$r][4] = 'availabilities';
|
||||
$this->rights[$r][5] = 'read';
|
||||
$r++;
|
||||
$this->rights[$r][0] = $this->numero . sprintf('%02d', (0 * 10) + 2);
|
||||
$this->rights[$r][1] = 'Create/Update objects of Ai';
|
||||
$this->rights[$r][4] = 'availabilities';
|
||||
$this->rights[$r][5] = 'write';
|
||||
$r++;
|
||||
$this->rights[$r][0] = $this->numero . sprintf('%02d', (0 * 10) + 3);
|
||||
$this->rights[$r][1] = 'Delete objects of Ai';
|
||||
$this->rights[$r][4] = 'availabilities';
|
||||
$this->rights[$r][5] = 'delete';
|
||||
$r++;
|
||||
$this->rights[$r][0] = $this->numero . sprintf('%02d', (1 * 10) + 1);
|
||||
$this->rights[$r][1] = 'Read Calendar object of Ai';
|
||||
$this->rights[$r][4] = 'calendar';
|
||||
$this->rights[$r][5] = 'read';
|
||||
$r++;
|
||||
$this->rights[$r][0] = $this->numero . sprintf('%02d', (1 * 10) + 2);
|
||||
$this->rights[$r][1] = 'Create/Update Calendar object of Ai';
|
||||
$this->rights[$r][4] = 'calendar';
|
||||
$this->rights[$r][5] = 'write';
|
||||
$r++;
|
||||
$this->rights[$r][0] = $this->numero . sprintf('%02d', (1 * 10) + 3);
|
||||
$this->rights[$r][1] = 'Delete Calendar object of Ai';
|
||||
$this->rights[$r][4] = 'calendar';
|
||||
$this->rights[$r][5] = 'delete';
|
||||
$r++;
|
||||
|
||||
/* END MODULEBUILDER PERMISSIONS */
|
||||
|
||||
// Main menu entries to add
|
||||
$this->menu = array();
|
||||
$r = 0;
|
||||
// Add here entries to declare new menus
|
||||
/* BEGIN MODULEBUILDER TOPMENU */
|
||||
/*$this->menu[$r++] = array(
|
||||
'fk_menu'=>'', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode
|
||||
'type'=>'top', // This is a Top menu entry
|
||||
'titre'=>'ModuleAiName',
|
||||
'prefix' => img_picto('', $this->picto, 'class="pictofixedwidth valignmiddle"'),
|
||||
'mainmenu'=>'ai',
|
||||
'leftmenu'=>'',
|
||||
'url'=>'/ai/aiindex.php',
|
||||
'langs'=>'ai', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.
|
||||
'position'=>1000 + $r,
|
||||
'enabled'=>'$conf->ai->enabled', // Define condition to show or hide menu entry. Use '$conf->ai->enabled' if entry must be visible if module is enabled.
|
||||
'perms'=>'$user->rights->ai->availabilities->read', // Use 'perms'=>'$user->rights->ai->availabilities->read' if you want your menu with a permission rules
|
||||
'target'=>'',
|
||||
'user'=>2, // 0=Menu for internal users, 1=external users, 2=both
|
||||
);*/
|
||||
/* END MODULEBUILDER TOPMENU */
|
||||
|
||||
/* BEGIN MODULEBUILDER LEFTMENU CALENDAR */
|
||||
$this->menu[$r++] = array(
|
||||
'fk_menu'=>'fk_mainmenu=agenda',
|
||||
'type'=>'left',
|
||||
'titre'=> 'MenuBookcalIndex',
|
||||
'prefix' => img_picto('', $this->picto, 'class="paddingright pictofixedwidth em92"'),
|
||||
'mainmenu'=>'agenda',
|
||||
'leftmenu'=> 'ai',
|
||||
'url'=> '/ai/aiindex.php',
|
||||
'langs'=> 'ai',
|
||||
'position'=> 1100+$r,
|
||||
'enabled'=> '1',
|
||||
'perms'=> '$user->rights->ai->read',
|
||||
'user'=> 0
|
||||
);
|
||||
|
||||
$this->menu[$r++]=array(
|
||||
// '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode
|
||||
'fk_menu'=>'fk_mainmenu=agenda,fk_leftmenu=ai',
|
||||
// This is a Left menu entry
|
||||
'type'=>'left',
|
||||
'titre'=>'Calendar',
|
||||
'mainmenu'=>'agenda',
|
||||
'leftmenu'=>'ai_list',
|
||||
'url'=>'/ai/list.php',
|
||||
// Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.
|
||||
'langs'=>'ai',
|
||||
'position'=>1100+$r,
|
||||
// Define condition to show or hide menu entry. Use '$conf->ai->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected.
|
||||
'enabled'=>'$conf->ai->enabled',
|
||||
// Use 'perms'=>'$user->rights->ai->level1->level2' if you want your menu with a permission rules
|
||||
'perms'=>'$user->rights->ai->read',
|
||||
'target'=>'',
|
||||
// 0=Menu for internal users, 1=external users, 2=both
|
||||
'user'=>2,
|
||||
);
|
||||
$this->menu[$r++]=array(
|
||||
// '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode
|
||||
'fk_menu'=>'fk_mainmenu=agenda,fk_leftmenu=ai_list',
|
||||
// This is a Left menu entry
|
||||
'type'=>'left',
|
||||
'titre'=>'NewKey',
|
||||
'mainmenu'=>'agenda',
|
||||
'leftmenu'=>'ai_new_key',
|
||||
'url'=>'/ai/ai_card.php?action=create',
|
||||
// Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.
|
||||
'langs'=>'ai',
|
||||
'position'=>1100+$r,
|
||||
// Define condition to show or hide menu entry. Use '$conf->ai->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected.
|
||||
'enabled'=>'$conf->ai->enabled',
|
||||
// Use 'perms'=>'$user->rights->ai->level1->level2' if you want your menu with a permission rules
|
||||
'perms'=>'$user->rights->ai->read',
|
||||
'target'=>'',
|
||||
// 0=Menu for internal users, 1=external users, 2=both
|
||||
'user'=>2
|
||||
);
|
||||
/* END MODULEBUILDER LEFTMENU CALENDAR */
|
||||
|
||||
/* BEGIN MODULEBUILDER LEFTMENU AVAILABILITIES
|
||||
$this->menu[$r++]=array(
|
||||
'fk_menu'=>'fk_mainmenu=ai', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode
|
||||
'type'=>'left', // This is a Left menu entry
|
||||
'titre'=>'Availabilities',
|
||||
'prefix' => img_picto('', $this->picto, 'class="paddingright pictofixedwidth valignmiddle"'),
|
||||
'mainmenu'=>'ai',
|
||||
'leftmenu'=>'availabilities',
|
||||
'url'=>'/ai/aiindex.php',
|
||||
'langs'=>'ai@ai', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.
|
||||
'position'=>1000+$r,
|
||||
'enabled'=>'$conf->ai->enabled', // Define condition to show or hide menu entry. Use '$conf->ai->enabled' if entry must be visible if module is enabled.
|
||||
'perms'=>'$user->rights->ai->availabilities->read', // Use 'perms'=>'$user->rights->ai->level1->level2' if you want your menu with a permission rules
|
||||
'target'=>'',
|
||||
'user'=>2, // 0=Menu for internal users, 1=external users, 2=both
|
||||
);
|
||||
$this->menu[$r++]=array(
|
||||
'fk_menu'=>'fk_mainmenu=ai,fk_leftmenu=availabilities', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode
|
||||
'type'=>'left', // This is a Left menu entry
|
||||
'titre'=>'List_Availabilities',
|
||||
'mainmenu'=>'ai',
|
||||
'leftmenu'=>'ai_availabilities_list',
|
||||
'url'=>'/ai/availabilities_list.php',
|
||||
'langs'=>'ai@ai', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.
|
||||
'position'=>1000+$r,
|
||||
'enabled'=>'$conf->ai->enabled', // Define condition to show or hide menu entry. Use '$conf->ai->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected.
|
||||
'perms'=>'$user->rights->ai->availabilities->read', // Use 'perms'=>'$user->rights->ai->level1->level2' if you want your menu with a permission rules
|
||||
'target'=>'',
|
||||
'user'=>2, // 0=Menu for internal users, 1=external users, 2=both
|
||||
);
|
||||
$this->menu[$r++]=array(
|
||||
'fk_menu'=>'fk_mainmenu=ai,fk_leftmenu=availabilities', // '' if this is a top menu. For left menu, use 'fk_mainmenu=xxx' or 'fk_mainmenu=xxx,fk_leftmenu=yyy' where xxx is mainmenucode and yyy is a leftmenucode
|
||||
'type'=>'left', // This is a Left menu entry
|
||||
'titre'=>'New_Availabilities',
|
||||
'mainmenu'=>'ai',
|
||||
'leftmenu'=>'ai_availabilities_new',
|
||||
'url'=>'/ai/availabilities_card.php?action=create',
|
||||
'langs'=>'ai@ai', // Lang file to use (without .lang) by module. File must be in langs/code_CODE/ directory.
|
||||
'position'=>1000+$r,
|
||||
'enabled'=>'$conf->ai->enabled', // Define condition to show or hide menu entry. Use '$conf->ai->enabled' if entry must be visible if module is enabled. Use '$leftmenu==\'system\'' to show if leftmenu system is selected.
|
||||
'perms'=>'$user->rights->ai->availabilities->write', // Use 'perms'=>'$user->rights->ai->level1->level2' if you want your menu with a permission rules
|
||||
'target'=>'',
|
||||
'user'=>2, // 0=Menu for internal users, 1=external users, 2=both
|
||||
);
|
||||
*/
|
||||
|
||||
/* END MODULEBUILDER LEFTMENU AVAILABILITIES */
|
||||
// Exports profiles provided by this module
|
||||
$r = 1;
|
||||
/* BEGIN MODULEBUILDER EXPORT AVAILABILITIES */
|
||||
/*
|
||||
$langs->load("agenda");
|
||||
$this->export_code[$r]=$this->rights_class.'_'.$r;
|
||||
$this->export_label[$r]='AvailabilitiesLines'; // Translation key (used only if key ExportDataset_xxx_z not found)
|
||||
$this->export_icon[$r]='availabilities@ai';
|
||||
// Define $this->export_fields_array, $this->export_TypeFields_array and $this->export_entities_array
|
||||
$keyforclass = 'Availabilities'; $keyforclassfile='/ai/class/availabilities.class.php'; $keyforelement='availabilities@ai';
|
||||
include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php';
|
||||
//$this->export_fields_array[$r]['t.fieldtoadd']='FieldToAdd'; $this->export_TypeFields_array[$r]['t.fieldtoadd']='Text';
|
||||
//unset($this->export_fields_array[$r]['t.fieldtoremove']);
|
||||
//$keyforclass = 'AvailabilitiesLine'; $keyforclassfile='/ai/class/availabilities.class.php'; $keyforelement='availabilitiesline@ai'; $keyforalias='tl';
|
||||
//include DOL_DOCUMENT_ROOT.'/core/commonfieldsinexport.inc.php';
|
||||
$keyforselect='availabilities'; $keyforaliasextra='extra'; $keyforelement='availabilities@ai';
|
||||
include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php';
|
||||
//$keyforselect='availabilitiesline'; $keyforaliasextra='extraline'; $keyforelement='availabilitiesline@ai';
|
||||
//include DOL_DOCUMENT_ROOT.'/core/extrafieldsinexport.inc.php';
|
||||
//$this->export_dependencies_array[$r] = array('availabilitiesline'=>array('tl.rowid','tl.ref')); // To force to activate one or several fields if we select some fields that need same (like to select a unique key if we ask a field of a child to avoid the DISTINCT to discard them, or for computed field than need several other fields)
|
||||
//$this->export_special_array[$r] = array('t.field'=>'...');
|
||||
//$this->export_examplevalues_array[$r] = array('t.field'=>'Example');
|
||||
//$this->export_help_array[$r] = array('t.field'=>'FieldDescHelp');
|
||||
$this->export_sql_start[$r]='SELECT DISTINCT ';
|
||||
$this->export_sql_end[$r] =' FROM '.MAIN_DB_PREFIX.'availabilities as t';
|
||||
//$this->export_sql_end[$r] =' LEFT JOIN '.MAIN_DB_PREFIX.'availabilities_line as tl ON tl.fk_availabilities = t.rowid';
|
||||
$this->export_sql_end[$r] .=' WHERE 1 = 1';
|
||||
$this->export_sql_end[$r] .=' AND t.entity IN ('.getEntity('availabilities').')';
|
||||
$r++; */
|
||||
/* END MODULEBUILDER EXPORT AVAILABILITIES */
|
||||
|
||||
// Imports profiles provided by this module
|
||||
$r = 1;
|
||||
/* BEGIN MODULEBUILDER IMPORT AVAILABILITIES */
|
||||
/*
|
||||
$langs->load("agenda");
|
||||
$this->import_code[$r]=$this->rights_class.'_'.$r;
|
||||
$this->import_label[$r]='AvailabilitiesLines'; // Translation key (used only if key ExportDataset_xxx_z not found)
|
||||
$this->import_icon[$r]='availabilities@ai';
|
||||
$this->import_tables_array[$r] = array('t' => MAIN_DB_PREFIX.'ai_availabilities', 'extra' => MAIN_DB_PREFIX.'ai_availabilities_extrafields');
|
||||
$this->import_tables_creator_array[$r] = array('t' => 'fk_user_author'); // Fields to store import user id
|
||||
$import_sample = array();
|
||||
$keyforclass = 'Availabilities'; $keyforclassfile='/ai/class/availabilities.class.php'; $keyforelement='availabilities@ai';
|
||||
include DOL_DOCUMENT_ROOT.'/core/commonfieldsinimport.inc.php';
|
||||
$import_extrafield_sample = array();
|
||||
$keyforselect='availabilities'; $keyforaliasextra='extra'; $keyforelement='availabilities@ai';
|
||||
include DOL_DOCUMENT_ROOT.'/core/extrafieldsinimport.inc.php';
|
||||
$this->import_fieldshidden_array[$r] = array('extra.fk_object' => 'lastrowid-'.MAIN_DB_PREFIX.'ai_availabilities');
|
||||
$this->import_regex_array[$r] = array();
|
||||
$this->import_examplevalues_array[$r] = array_merge($import_sample, $import_extrafield_sample);
|
||||
$this->import_updatekeys_array[$r] = array('t.ref' => 'Ref');
|
||||
$this->import_convertvalue_array[$r] = array(
|
||||
't.ref' => array(
|
||||
'rule'=>'getrefifauto',
|
||||
'class'=>(empty($conf->global->BOOKCAL_AVAILABILITIES_ADDON) ? 'mod_availabilities_standard' : $conf->global->BOOKCAL_AVAILABILITIES_ADDON),
|
||||
'path'=>"/core/modules/commande/".(empty($conf->global->BOOKCAL_AVAILABILITIES_ADDON) ? 'mod_availabilities_standard' : $conf->global->BOOKCAL_AVAILABILITIES_ADDON).'.php'
|
||||
'classobject'=>'Availabilities',
|
||||
'pathobject'=>'/ai/class/availabilities.class.php',
|
||||
),
|
||||
't.fk_soc' => array('rule' => 'fetchidfromref', 'file' => '/societe/class/societe.class.php', 'class' => 'Societe', 'method' => 'fetch', 'element' => 'ThirdParty'),
|
||||
't.fk_user_valid' => array('rule' => 'fetchidfromref', 'file' => '/user/class/user.class.php', 'class' => 'User', 'method' => 'fetch', 'element' => 'user'),
|
||||
't.fk_mode_reglement' => array('rule' => 'fetchidfromcodeorlabel', 'file' => '/compta/paiement/class/cpaiement.class.php', 'class' => 'Cpaiement', 'method' => 'fetch', 'element' => 'cpayment'),
|
||||
);
|
||||
$r++; */
|
||||
/* END MODULEBUILDER IMPORT AVAILABILITIES */
|
||||
}
|
||||
|
||||
/**
|
||||
* Function called when module is enabled.
|
||||
* The init function add constants, boxes, permissions and menus (defined in constructor) into Dolibarr database.
|
||||
* It also creates data directories
|
||||
*
|
||||
* @param string $options Options when enabling module ('', 'noboxes')
|
||||
* @return int 1 if OK, 0 if KO
|
||||
*/
|
||||
public function init($options = '')
|
||||
{
|
||||
global $conf, $langs;
|
||||
|
||||
// $result = $this->_load_tables('/install/mysql/', 'ai');
|
||||
// if ($result < 0) {
|
||||
// return -1; // Do not activate module if error 'not allowed' returned when loading module SQL queries (the _load_table run sql with run_sql with the error allowed parameter set to 'default')
|
||||
// }
|
||||
|
||||
// Create extrafields during init
|
||||
//include_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
|
||||
//$extrafields = new ExtraFields($this->db);
|
||||
//$result1=$extrafields->addExtraField('ai_myattr1', "New Attr 1 label", 'boolean', 1, 3, 'thirdparty', 0, 0, '', '', 1, '', 0, 0, '', '', 'ai@ai', '$conf->ai->enabled');
|
||||
//$result2=$extrafields->addExtraField('ai_myattr2', "New Attr 2 label", 'varchar', 1, 10, 'project', 0, 0, '', '', 1, '', 0, 0, '', '', 'ai@ai', '$conf->ai->enabled');
|
||||
//$result3=$extrafields->addExtraField('ai_myattr3', "New Attr 3 label", 'varchar', 1, 10, 'bank_account', 0, 0, '', '', 1, '', 0, 0, '', '', 'ai@ai', '$conf->ai->enabled');
|
||||
//$result4=$extrafields->addExtraField('ai_myattr4', "New Attr 4 label", 'select', 1, 3, 'thirdparty', 0, 1, '', array('options'=>array('code1'=>'Val1','code2'=>'Val2','code3'=>'Val3')), 1,'', 0, 0, '', '', 'ai@ai', '$conf->ai->enabled');
|
||||
//$result5=$extrafields->addExtraField('ai_myattr5', "New Attr 5 label", 'text', 1, 10, 'user', 0, 0, '', '', 1, '', 0, 0, '', '', 'ai@ai', '$conf->ai->enabled');
|
||||
|
||||
// Permissions
|
||||
$this->remove($options);
|
||||
|
||||
$sql = array();
|
||||
|
||||
// Document templates
|
||||
$moduledir = dol_sanitizeFileName('ai');
|
||||
$myTmpObjects = array();
|
||||
$myTmpObjects['Availabilities'] = array('includerefgeneration'=>0, 'includedocgeneration'=>0);
|
||||
|
||||
// foreach ($myTmpObjects as $myTmpObjectKey => $myTmpObjectArray) {
|
||||
// if ($myTmpObjectKey == 'Availabilities') {
|
||||
// continue;
|
||||
// }
|
||||
// if ($myTmpObjectArray['includerefgeneration']) {
|
||||
// $src = DOL_DOCUMENT_ROOT.'/install/doctemplates/'.$moduledir.'/template_availabilitiess.odt';
|
||||
// $dirodt = DOL_DATA_ROOT.'/doctemplates/'.$moduledir;
|
||||
// $dest = $dirodt.'/template_availabilitiess.odt';
|
||||
|
||||
// if (file_exists($src) && !file_exists($dest)) {
|
||||
// require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
|
||||
// dol_mkdir($dirodt);
|
||||
// $result = dol_copy($src, $dest, 0, 0);
|
||||
// if ($result < 0) {
|
||||
// $langs->load("errors");
|
||||
// $this->error = $langs->trans('ErrorFailToCopyFile', $src, $dest);
|
||||
// return 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
// $sql = array_merge($sql, array(
|
||||
// "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = 'standard_".strtolower($myTmpObjectKey)."' AND type = '".$this->db->escape(strtolower($myTmpObjectKey))."' AND entity = ".((int) $conf->entity),
|
||||
// "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('standard_".strtolower($myTmpObjectKey)."', '".$this->db->escape(strtolower($myTmpObjectKey))."', ".((int) $conf->entity).")",
|
||||
// "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = 'generic_".strtolower($myTmpObjectKey)."_odt' AND type = '".$this->db->escape(strtolower($myTmpObjectKey))."' AND entity = ".((int) $conf->entity),
|
||||
// "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('generic_".strtolower($myTmpObjectKey)."_odt', '".$this->db->escape(strtolower($myTmpObjectKey))."', ".((int) $conf->entity).")"
|
||||
// ));
|
||||
// }
|
||||
// }
|
||||
|
||||
return $this->_init($sql, $options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function called when module is disabled.
|
||||
* Remove from database constants, boxes and permissions from Dolibarr database.
|
||||
* Data directories are not deleted
|
||||
*
|
||||
* @param string $options Options when enabling module ('', 'noboxes')
|
||||
* @return int 1 if OK, 0 if KO
|
||||
*/
|
||||
public function remove($options = '')
|
||||
{
|
||||
$sql = array();
|
||||
return $this->_remove($sql, $options);
|
||||
}
|
||||
}
|
||||
@@ -143,7 +143,7 @@ class pdf_zenith extends ModelePDFSupplierProposal
|
||||
* @param int $hideref Do not show ref
|
||||
* @return int 1=OK, 0=KO
|
||||
*/
|
||||
public function write_file($object, $outputlangs = '', $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
|
||||
public function write_file($object, $outputlangs = null, $srctemplatepath = '', $hidedetails = 0, $hidedesc = 0, $hideref = 0)
|
||||
{
|
||||
// phpcs:enable
|
||||
global $user, $langs, $conf, $hookmanager, $mysoc, $nblines;
|
||||
|
||||
@@ -387,7 +387,6 @@ if ($action == 'presend') {
|
||||
$formmail->param['id'] = $object->id;
|
||||
$formmail->param['returnurl'] = $_SERVER["PHP_SELF"].'?id='.$object->id;
|
||||
$formmail->param['fileinit'] = array($file);
|
||||
|
||||
// Show form
|
||||
print $formmail->get_form();
|
||||
|
||||
|
||||
@@ -1020,7 +1020,6 @@ if ($resql) {
|
||||
exit;
|
||||
}
|
||||
|
||||
llxHeader('', $title, $help_url);
|
||||
llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-supplier-order page-list');
|
||||
|
||||
$param = '';
|
||||
|
||||
@@ -203,3 +203,5 @@ ALTER TABLE llx_expensereport DROP INDEX idx_expensereport_fk_refuse, ADD INDEX
|
||||
INSERT INTO llx_c_forme_juridique (fk_pays, code, libelle) VALUES (1,'66','Société publique locale');
|
||||
|
||||
ALTER TABLE llx_prelevement_lignes ADD COLUMN tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
|
||||
|
||||
ALTER TABLE llx_bom_bomline ADD COLUMN tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
|
||||
|
||||
@@ -19,6 +19,7 @@ CREATE TABLE llx_bom_bomline(
|
||||
fk_bom integer NOT NULL,
|
||||
fk_product integer NOT NULL,
|
||||
fk_bom_child integer NULL,
|
||||
tms timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
description text,
|
||||
import_key varchar(14),
|
||||
qty double(24,8) NOT NULL,
|
||||
|
||||
@@ -1430,6 +1430,8 @@ DisableForgetPasswordLinkOnLogonPage=Do not show the "Password Forgotten" link o
|
||||
UsersSetup=Users module setup
|
||||
UserMailRequired=Email required to create a new user
|
||||
UserHideInactive=Hide inactive users from all combo lists of users (Not recommended: this may means you won't be able to filter or search on old users on some pages)
|
||||
UserHideExternal=Hide external users (not linked to a third party) from all combo lists of users (Not recommended: this may means you won't be able to filter or search on external users on some pages)
|
||||
UserHideNonEmployee=Hide non employee users from all combo lists of users (Not recommended: this may means you won't be able to filter or search on non employee users on some pages)
|
||||
UsersDocModules=Document templates for documents generated from user record
|
||||
GroupsDocModules=Document templates for documents generated from a group record
|
||||
##### HRM setup #####
|
||||
|
||||
1
htdocs/langs/en_US/ai.lang
Normal file
1
htdocs/langs/en_US/ai.lang
Normal file
@@ -0,0 +1 @@
|
||||
AI_KEY_API_CHATGPT= Key for IA api
|
||||
@@ -184,3 +184,5 @@ EmailOptedOut=Email owner has requested to not contact him with this email anymo
|
||||
EvenUnsubscribe=Include opt-out emails
|
||||
EvenUnsubscribeDesc=Include opt-out emails when you select emails as targets. Useful for mandatory service emails for example.
|
||||
XEmailsDoneYActionsDone=%s emails pre-qualified, %s emails successfully processed (for %s record/actions done)
|
||||
helpWithAi=Add instructions
|
||||
YouCanMakeSomeInstructionForEmail=You Can Make Some Instruction For your Email (Exemple: generate image in email template...)
|
||||
@@ -1429,6 +1429,8 @@ DisableForgetPasswordLinkOnLogonPage=Cacher le lien "Mot de passe oublié" sur l
|
||||
UsersSetup=Configuration du module utilisateurs
|
||||
UserMailRequired=Email requis pour créer un nouvel utilisateur
|
||||
UserHideInactive=Masquer les utilisateurs inactifs sur toutes les listes déroulantes d'utilisateurs (non recommandé: cela peut signifier que vous ne pourrez pas filtrer ou rechercher les anciens utilisateurs sur certaines pages)
|
||||
UserHideExternal=Masquer les utilisateurs externes (non liés à un tiers) sur toutes les listes déroulantes d'utilisateurs (non recommandé: cela peut signifier que vous ne pourrez pas filtrer ou rechercher les utilisateurs externes sur certaines pages)
|
||||
UserHideNonEmployee=Masquer les utilisateurs externes (non salariés) sur toutes les listes déroulantes d'utilisateurs (non recommandé: cela peut signifier que vous ne pourrez pas filtrer ou rechercher les utilisateurs non salariés sur certaines pages)
|
||||
UsersDocModules=Modèles de documents pour les documents générés à partir de la fiche utilisateur
|
||||
GroupsDocModules=Modèles de documents pour les documents générés à partir de la fiche d'un groupe
|
||||
##### HRM setup #####
|
||||
|
||||
1
htdocs/langs/fr_FR/ai.lang
Normal file
1
htdocs/langs/fr_FR/ai.lang
Normal file
@@ -0,0 +1 @@
|
||||
AI_KEY_API_CHATGPT= Clé pour l'api IA
|
||||
@@ -27,33 +27,9 @@
|
||||
*/
|
||||
|
||||
// Load Dolibarr environment
|
||||
$res = 0;
|
||||
// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined)
|
||||
if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) {
|
||||
$res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
|
||||
}
|
||||
// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME
|
||||
$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1;
|
||||
while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) {
|
||||
$i--;
|
||||
$j--;
|
||||
}
|
||||
if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) {
|
||||
$res = @include substr($tmp, 0, ($i + 1))."/main.inc.php";
|
||||
}
|
||||
if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) {
|
||||
$res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php";
|
||||
}
|
||||
// Try main.inc.php using relative path
|
||||
if (!$res && file_exists("../../main.inc.php")) {
|
||||
$res = @include "../../main.inc.php";
|
||||
}
|
||||
if (!$res && file_exists("../../../main.inc.php")) {
|
||||
$res = @include "../../../main.inc.php";
|
||||
}
|
||||
if (!$res) {
|
||||
die("Include of main fails");
|
||||
}
|
||||
require '../../main.inc.php';
|
||||
|
||||
global $conf, $langs, $user;
|
||||
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/stock.lib.php';
|
||||
@@ -94,7 +70,7 @@ require DOL_DOCUMENT_ROOT.'/core/actions_extrafields.inc.php';
|
||||
|
||||
$textobject = $langs->transnoentitiesnoconv("Inventory");
|
||||
|
||||
llxHeader('', $langs->trans("InventorySetup"), $help_url);
|
||||
llxHeader('', $langs->trans("InventorySetup"));
|
||||
|
||||
|
||||
$linkback = '<a href="'.DOL_URL_ROOT.'/admin/modules.php?restore_lastsearch_values=1">'.$langs->trans("BackToModuleList").'</a>';
|
||||
|
||||
@@ -27,34 +27,7 @@
|
||||
*/
|
||||
|
||||
// Load Dolibarr environment
|
||||
$res = 0;
|
||||
// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined)
|
||||
if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) {
|
||||
$res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
|
||||
}
|
||||
// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME
|
||||
$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1;
|
||||
while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) {
|
||||
$i--;
|
||||
$j--;
|
||||
}
|
||||
if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) {
|
||||
$res = @include substr($tmp, 0, ($i + 1))."/main.inc.php";
|
||||
}
|
||||
if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) {
|
||||
$res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php";
|
||||
}
|
||||
// Try main.inc.php using relative path
|
||||
if (!$res && file_exists("../../main.inc.php")) {
|
||||
$res = @include "../../main.inc.php";
|
||||
}
|
||||
if (!$res && file_exists("../../../main.inc.php")) {
|
||||
$res = @include "../../../main.inc.php";
|
||||
}
|
||||
if (!$res) {
|
||||
die("Include of main fails");
|
||||
}
|
||||
|
||||
require '../../main.inc.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/stock.lib.php';
|
||||
|
||||
@@ -94,7 +67,7 @@ require DOL_DOCUMENT_ROOT.'/core/actions_extrafields.inc.php';
|
||||
|
||||
$textobject = $langs->transnoentitiesnoconv("StockMovement");
|
||||
|
||||
llxHeader('', $langs->trans("StockSetup"), $help_url);
|
||||
llxHeader('', $langs->trans("StockSetup"));
|
||||
|
||||
|
||||
$linkback = '<a href="'.DOL_URL_ROOT.'/admin/modules.php?restore_lastsearch_values=1">'.$langs->trans("BackToModuleList").'</a>';
|
||||
|
||||
@@ -22,35 +22,9 @@
|
||||
*/
|
||||
|
||||
// Load Dolibarr environment
|
||||
$res = 0;
|
||||
// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined)
|
||||
if (!$res && !empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) {
|
||||
$res = @include $_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php";
|
||||
}
|
||||
// Try main.inc.php into web root detected using web root calculated from SCRIPT_FILENAME
|
||||
$tmp = empty($_SERVER['SCRIPT_FILENAME']) ? '' : $_SERVER['SCRIPT_FILENAME']; $tmp2 = realpath(__FILE__); $i = strlen($tmp) - 1; $j = strlen($tmp2) - 1;
|
||||
while ($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i] == $tmp2[$j]) {
|
||||
$i--;
|
||||
$j--;
|
||||
}
|
||||
if (!$res && $i > 0 && file_exists(substr($tmp, 0, ($i + 1))."/main.inc.php")) {
|
||||
$res = @include substr($tmp, 0, ($i + 1))."/main.inc.php";
|
||||
}
|
||||
if (!$res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php")) {
|
||||
$res = @include dirname(substr($tmp, 0, ($i + 1)))."/main.inc.php";
|
||||
}
|
||||
// Try main.inc.php using relative path
|
||||
if (!$res && file_exists("../../main.inc.php")) {
|
||||
$res = @include "../../main.inc.php";
|
||||
}
|
||||
if (!$res && file_exists("../../../main.inc.php")) {
|
||||
$res = @include "../../../main.inc.php";
|
||||
}
|
||||
if (!$res) {
|
||||
die("Include of main fails");
|
||||
}
|
||||
require '../../main.inc.php';
|
||||
|
||||
global $langs, $user;
|
||||
global $conf, $langs, $user;
|
||||
|
||||
// Libraries
|
||||
require_once DOL_DOCUMENT_ROOT."/core/lib/admin.lib.php";
|
||||
|
||||
@@ -27,6 +27,7 @@ require '../main.inc.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/usergroups.lib.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/user/class/user.class.php';
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/company.lib.php';
|
||||
|
||||
// Load translation files required by page
|
||||
$langs->load("users");
|
||||
@@ -39,6 +40,35 @@ if (!isset($id) || empty($id)) {
|
||||
accessforbidden();
|
||||
}
|
||||
|
||||
if (GETPOST('actioncode', 'array')) {
|
||||
$actioncode = GETPOST('actioncode', 'array', 3);
|
||||
if (!count($actioncode)) {
|
||||
$actioncode = '0';
|
||||
}
|
||||
} else {
|
||||
$actioncode = GETPOST("actioncode", "alpha", 3) ? GETPOST("actioncode", "alpha", 3) : (GETPOST("actioncode") == '0' ? '0' : getDolGlobalString('AGENDA_DEFAULT_FILTER_TYPE_FOR_OBJECT'));
|
||||
}
|
||||
|
||||
$search_rowid = GETPOST('search_rowid');
|
||||
$search_agenda_label = GETPOST('search_agenda_label');
|
||||
|
||||
$limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit;
|
||||
$sortfield = GETPOST('sortfield', 'aZ09comma');
|
||||
$sortorder = GETPOST('sortorder', 'aZ09comma');
|
||||
$page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
|
||||
if (empty($page) || $page == -1) {
|
||||
$page = 0;
|
||||
} // If $page is not defined, or '' or -1
|
||||
$offset = $limit * $page;
|
||||
$pageprev = $page - 1;
|
||||
$pagenext = $page + 1;
|
||||
if (!$sortfield) {
|
||||
$sortfield = 'a.datep,a.id';
|
||||
}
|
||||
if (!$sortorder) {
|
||||
$sortorder = 'DESC,DESC';
|
||||
}
|
||||
|
||||
$object = new User($db);
|
||||
if ($id > 0 || !empty($ref)) {
|
||||
$result = $object->fetch($id, $ref, '', 1);
|
||||
@@ -59,6 +89,24 @@ if (($object->id != $user->id) && !$user->hasRight('user', 'user', 'lire')) {
|
||||
accessforbidden();
|
||||
}
|
||||
|
||||
$parameters = array('id'=>$userId);
|
||||
$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
|
||||
if ($reshook < 0) {
|
||||
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
|
||||
}
|
||||
if (empty($reshook)) {
|
||||
// Cancel
|
||||
if (GETPOST('cancel', 'alpha') && !empty($backtopage)) {
|
||||
header("Location: ".$backtopage);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Purge search criteria
|
||||
if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) { // All tests are required to be compatible with all browsers
|
||||
$actioncode = '';
|
||||
$search_agenda_label = '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@@ -109,6 +157,62 @@ print '</div>';
|
||||
|
||||
print dol_get_fiche_end();
|
||||
|
||||
$objUser = $object;
|
||||
$objcon = new stdClass();
|
||||
|
||||
$out = '';
|
||||
$permok = $user->hasRight('agenda', 'myactions', 'create');
|
||||
if ((!empty($objUser->id) || !empty($objcon->id)) && $permok) {
|
||||
if (is_object($objUser) && get_class($objUser) == 'User') {
|
||||
$out .= '&originid='.$objUser->id.($objUser->id > 0 ? '&userid='.$objUser->id : '').'&backtopage='.urlencode($_SERVER['PHP_SELF'].($objUser->id > 0 ? '?userid='.$objUser->id : ''));
|
||||
}
|
||||
$out .= (!empty($objcon->id) ? '&contactid='.$objcon->id : '');
|
||||
$out .= '&datep='.dol_print_date(dol_now(), 'dayhourlog', 'tzuserrel');
|
||||
}
|
||||
|
||||
$morehtmlright = '';
|
||||
|
||||
$messagingUrl = DOL_URL_ROOT.'/societe/messaging.php?userid='.$object->id;
|
||||
$morehtmlright .= dolGetButtonTitle($langs->trans('ShowAsConversation'), '', 'fa fa-comments imgforviewmode', $messagingUrl, '', 1);
|
||||
$messagingUrl = DOL_URL_ROOT.'/user/info.php?id='.$object->id;
|
||||
$morehtmlright .= dolGetButtonTitle($langs->trans('MessageListViewType'), '', 'fa fa-bars imgforviewmode', $messagingUrl, '', 2);
|
||||
|
||||
if (isModEnabled('agenda')) {
|
||||
if ($user->hasRight('agenda', 'myactions', 'create') || $user->hasRight('agenda', 'allactions', 'create')) {
|
||||
$morehtmlright .= dolGetButtonTitle($langs->trans('AddAction'), '', 'fa fa-plus-circle', DOL_URL_ROOT.'/comm/action/card.php?action=create'.$out);
|
||||
}
|
||||
}
|
||||
|
||||
if (isModEnabled('agenda') && ($user->hasRight('agenda', 'myactions', 'read') || $user->hasRight('agenda', 'allaactions', 'read'))) {
|
||||
print '<br>';
|
||||
$param = '&id='.urlencode($id);
|
||||
|
||||
if ($limit > 0 && $limit != $conf->liste_limit) {
|
||||
$param .= '&limit='.((int) $limit);
|
||||
}
|
||||
|
||||
|
||||
// Try to know count of actioncomm from cache
|
||||
require_once DOL_DOCUMENT_ROOT.'/core/lib/memory.lib.php';
|
||||
$cachekey = 'count_events_user_'.$object->id;
|
||||
$nbEvent = dol_getcache($cachekey);
|
||||
|
||||
$titlelist = $langs->trans("ActionsOnCompany").(is_numeric($nbEvent) ? '<span class="opacitymedium colorblack paddingleft">('.$nbEvent.')</span>' : '');
|
||||
if (!empty($conf->dol_optimize_smallscreen)) {
|
||||
$titlelist = $langs->trans("Actions").(is_numeric($nbEvent) ? '<span class="opacitymedium colorblack paddingleft">('.$nbEvent.')</span>' : '');
|
||||
}
|
||||
|
||||
print_barre_liste($titlelist, 0, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, '', 0, -1, '', 0, $morehtmlright, '', 0, 1, 0);
|
||||
|
||||
// List of all actions
|
||||
$filters = array();
|
||||
$filters['search_agenda_label'] = $search_agenda_label;
|
||||
$filters['search_rowid'] = $search_rowid;
|
||||
|
||||
// TODO Replace this with same code than into list.php
|
||||
show_actions_done_user($conf, $langs, $db, $object, null, 0, $actioncode, '', $filters, $sortfield, $sortorder, $object->module);
|
||||
}
|
||||
|
||||
// End of page
|
||||
llxFooter();
|
||||
$db->close();
|
||||
|
||||
Reference in New Issue
Block a user