gestione gare pubbliche
Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 

1781 righe
50 KiB

<?php
use Mtownsend\XmlToArray\XmlToArray;
include_once 'BS4FormGenerator.trait.php';
include_once 'TedEsenderFieldsManager.trait.php';
include_once 'TedEsenderHelpersFuncions.trait.php';
include_once 'TedEsenderApiManager.trait.php';
include_once 'TedEsenderSuggestions.class.php';
class eSenderManager {
use BS4FormGenerator, TedEsenderFieldsManager, TedEsenderHelpersFuncions, TedEsenderApiManager, TedEsenderSuggestions;
const MUL = "£";
const DEFAULT = 0;
const REMOVED_SUBSECTIONS = 1;
const EDITED_SUBSECTION = 2;
/**
* XSD schema file name
*
* @var String
*/
private $xsd;
/**
*
* @var DOMXPath
*/
private $xpath;
/**
* Form Attributes
*
* @var Array
*/
public $formAttributes;
/**
* Form Sections
*
* @var Array
*/
public $sections;
/**
* Current Section
*
* @var Array
*/
private $current_section;
/**
* Record salvato nel database
*
* @var Array
*/
public $info;
/**
* Elements list
*
* @var Array
*/
private $elements;
/**
* Debug switch
*
* @var Bool
*/
public $debug;
/**
* Ignored Keys
*
* @var Array
*/
public $ignored_keys;
/**
* Settings
*
* @var Array
*/
public $setting;
/**
* title
*
* @var String
*/
public $title;
/**
* Check for form Rows
*
* @var boolean
*/
private $hasAnotherRow = false;
/**
* Total completed sections number;
*/
public $total_completed;
/**
* Suggestions from connected modules;
*
* @var Array
*/
private $suggestions;
/**
* Event to trigger after suggestions;
*
* @var Array
*/
private $suggestionTriggers;
/**
* Define if instance is deferred or not;
*/
public $deferred;
/**
* Connsessione al database
*
* @var mixed
*/
private $pdo;
/**
* Form ID
*
* @var mixed
*/
public $form_section;
/**
* Load XSD Form
*
* @param String $form
* @param String $directory
* @return void
*/
function __construct(String $form, Int $codice = 0, Array $settings, String $directory = "config/xml")
{
global $pdo, $root;
$this->pdo = $pdo;
if(!str_ends_with($form, ".xsd")) {
$form .= ".xsd";
}
$this->form_section = $this->notice = $form;
$this->init($codice);
if($directory == "config/xml") {
$directory = "{$root}/backend/guue/{$directory}";
}
$this->settings = $settings;
$this->fields = [];
$this->settings = file_get_contents("{$root}/backend/guue/config/settings.json");
$this->settings = json_decode($this->settings, true);
$this->title = $this->settings["forms"][$this->form_section]["name"];
ini_set('max_execution_time', 300);
ini_set('memory_limit', "512M");
$this->debug = false;
$this->group = 0;
$this->mapper = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . ".." . DIRECTORY_SEPARATOR . "config" . DIRECTORY_SEPARATOR . "localization.json");
$this->mapper = json_decode($this->mapper, TRUE);
$this->mapper["ERRORS_DICT"] = json_decode(file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . ".." . DIRECTORY_SEPARATOR . "config" . DIRECTORY_SEPARATOR . "errors.json"), true);
$this->translator = file_get_contents(__DIR__ . DIRECTORY_SEPARATOR . ".." . DIRECTORY_SEPARATOR . "config" . DIRECTORY_SEPARATOR . "translator.json");
$this->translator = json_decode($this->translator, TRUE);
$this->elements = [
"empty",
"email",
"url",
"text_ft_multi_lines",
"url",
"string_400",
"string_200",
"string_not_empty",
"string_with_letter",
"string",
"string_20",
"string_30",
"string_50",
"string_100",
"string_150",
"string_200",
"string_250",
"string_300",
"string_400",
"string_500",
"string_1000",
"text_ft_single_line",
"text_ft_multi_lines",
"text_ft_multi_lines_or_string",
"nonNegativeInteger",
"_2car",
"_3car",
"_4car",
"_5car",
"alphanum",
"nb",
"prct",
"decimal",
"time",
"date_full",
"date",
"duration_unit_m_d",
"duration_unit_m_y",
];
$this->ignored_keys = [
self::MUL,
"COUNTRY_ORIGIN",
"ADDRESS_CONTRACTING_BODY_ADDITIONAL",
"ADDRESS_FURTHER_INFO",
"_attributes",
"ADDRESS_PARTICIPATION",
"LOT_DIVISION",
"ADDRESS_PARTICIPATION",
"LOT_DIVISION_SETTINGS",
"LOT_DIVISION",
"LOT_MAX_NUMBER",
"CPV_MAIN",
"AC",
"AC_QUALITY",
"AC_COST",
"time_frame",
"RADIO_FOR_ECONOMIC_CRITERIA_DOC",
"RADIO_FOR_TECHNICAL_CRITERIA_DOC",
"RADIO_FOR_PT_RESTRICTED",
"LANGUAGES",
"LANGUAGE",
"TYPE_CONTRACT",
"RADIO_FOR_GPA",
"AC_QUALITY_SECTION",
"CPV_ADDITIONAL",
"DATE_RECEIPT_TENDERS",
"TIME_RECEIPT_TENDERS",
"OBJECT_DESCR",
"AWARDED_CONTRACT",
"NO_AWARDED_CONTRACT",
"PROCUREMENT_DISCONTINUED",
"ORIGINAL_OTHER_MEANS",
"RADIO_FOR_ORIGINAL_OTHER_MEANS_SECTION",
"CONTRACTORS",
"CONTRACTOR",
"VALUES",
"CONTRACTOR_SME_MAN",
"ITEM",
"TOWN",
"RADIO_FOR_DEPOSIT_GUARANTEE_REQUIRED",
"RADIO_FOR_MAIN_FINANCING_CONDITION",
"RADIO_FOR_LEGAL_FORM",
"RADIO_FOR_PARTICULAR_PROFESSION",
"PARTICULAR_PROFESSION",
"D_ACCORDANCE_ARTICLE",
"AGREE_TO_PUBLICATION_MAN",
"NON_COMMUNITY_ORIGIN",
"TED_ESENDERS.FORM_SECTION.F07_2014.LEFTI.SECTION_FOR_QUALIFICATION",
"NO_AWARDED_PRIZE",
"AWARDED_PRIZE",
"WINNER",
"ADDRESS_WINNER",
"RADIO_FOR_ENOTICES",
"ORIGINAL_ENOTICES",
"ORIGINAL_TED_ESENDER",
"CHANGE",
"SECTION_FOR_CHANGE",
"OLD_VALUE",
"NEW_VALUE",
"RADIO_FOR_ANNEX_D4_PART_1",
"PT_AWARD_CONTRACT_WITHOUT_PUBLICATION",
"RADIO_FOR_DOCUMENT_URL_OPT_SECTION",
"RADIO_FOR_ADDESS_PARTICIPATION",
"RADIO_FOR_OPENING_CONDITION",
"OBJECT_CONTRACT",
"LEGAL_FORM",
"OPENING_CONDITION",
"DATE_RECEIPT_TENDERS",
"RADIO_FOR_OPENING_CONDITION",
"DURATION_TENDER_VALID",
"DATE_OPENING_TENDERS",
"SEVERAL_OPERATORS",
"D_FROM_WINDING_PROVIDER",
"D_FROM_LIQUIDATOR_CREDITOR",
"AWARD_CONTRACT",
"RADIO_FOR_LIKELY_SUBCONTRACTED",
"NO_LOT_DIVISION",
"REDUCTION_RECOURSE_SECTION",
"NOTICE_NUMBER_OJ",
"FRAMEWORK",
"NB_PARTICIPANTS",
"DPS_ADDITIONAL_PURCHASERS",
"INFO_ADD",
"PLACE",
"TIME_OPENING_TENDERS",
"TITLE",
"LOT_NO",
"NUTS",
"MAIN_SITE",
"SHORT_DESCR",
"DURATION",
"DATE_START",
"DATE_END",
"AC_WEIGHTING",
"RENEWAL_DESCR",
"NO_EU_PROGR_RELATED",
"NB_MAX_LIMIT_CANDIDATE",
"NB_MIN_LIMIT_CANDIDATE",
"NB_ENVISAGED_CANDIDATE",
"CRITERIA_CANDIDATE",
"OPTIONS_DESCR",
"EU_PROGR_RELATED",
"ESTIMATED_TIMING",
"EORDERING",
"EPAYMENT",
"EINVOICING",
"OFFICIALNAME",
"ADDRESS",
"POSTAL_CODE",
"COUNTRY",
"TOWN",
"E_MAIL",
"PHONE",
"FAX",
"URL",
"DATE_DISPATCH_NOTICE",
"REVIEW_PROCEDURE",
"NATIONALID",
"CONTACT_POINT",
"URL_GENERAL",
"URL_BUYER",
"JOINT_PROCUREMENT_INVOLVED",
"PROCUREMENT_LAW",
"REFERENCE_NUMBER",
"PT_AWARD_CONTRACT_WITHOUT_CALL",
"D_NO_TENDERS_REQUESTS",
"D_PURE_RESEARCH",
"D_EXTREME_URGENCY",
"D_ADD_DELIVERIES_ORDERED",
"CTYPE",
"D_BARGAIN_PURCHASE",
"D_OUTSIDE_SCOPE",
"D_JUSTIFICATION",
"DPS",
"EAUCTION_USED",
"TERMINATION_DPS_SECTION",
"TERMINATION_PIN",
"CONTRACT_NO",
"NB_TENDERS_RECEIVED",
"NB_TENDERS_RECEIVED_SME",
"RADIO_FOR_ANNEX_D2_PART1",
"QUALIFICATION",
"RADIO_FOR_INFORMATION",
"PARTICIPANT_NAME",
"PARTICIPANT_NAME_ADDITIONAL",
"RADIO_FOR_VAL_PRIZE",
"VAL_PRIZE",
"DIRECTIVE_2014_23_EU",
"DIRECTIVE_2014_24_EU",
"DIRECTIVE_2014_25_EU",
"DIRECTIVE_2009_81_EC",
"AC_CRITERIA",
"RADIO_FOR_PT_NEGOTIATED_WITHOUT_PUBLICATION",
"PT_NEGOTIATED_WITHOUT_PUBLICATION",
"DESCRIPTION_PROCUREMENT",
"AC_CRITERION",
"ESENDER_LOGIN",
"CUSTOMER_LOGIN",
"JUSTIFICATION",
"D_CONTRACT_AWARDED_DESIGN_CONTEST",
"D_COMMODITY_MARKET",
"RADIO_FOR_D_MANUF_FOR_RESEARCH",
"QS",
"VAL_REVENUE",
"VAL_PRICE_PAYMENT",
"T"
];
$this->xsd = $form;
$this->directory = $directory;
$this->suggestionTriggers = [];
$this->dom = new DOMDocument();
$this->dom->load("{$this->directory}/{$this->xsd}", LIBXML_DTDLOAD|LIBXML_DTDATTR|LIBXML_NOENT|LIBXML_XINCLUDE);
$this->dom = $this->loadIncludes($this->dom, $this->directory);
$this->dom = $this->loadImports($this->dom, $this->directory);
$this->xml = $this->dom->saveXML();
$this->xml = str_replace(["xs:", "lb:", "n2016:"], "", $this->xml);
$this->dom = new SimpleXMLIterator($this->xml);
$this->form = $this->dom->xpath("element[@name='".str_replace(".xsd","",$form)."']");
if(is_array($this->form) && count($this->form) == 1) $this->form = reset($this->form);
$this->getSections();
}
/**
* List alla available notices' form
*
* @return Array
*/
static public function listAvailableNoticeForms() : ?Array {
global $config;
$path = dirname(__DIR__);
$forms = glob("{$path}/config/xml/F*_2014.xsd");
$settings = jsonToArray("{$path}/config/settings.json");
$select = [
'name' => 'form',
'title' => "Tipologia di avviso",
'attrs' => [
'rel' => 'S;12;12;A'
],
'options' => []
];
foreach ($forms as $value) {
if ($settings["forms"][basename($value)]["active"] || $config["developEnv"]) {
$select['options'][str_replace('.xsd', "", basename($value))] = $settings["forms"][basename($value)]["name"];
}
}
return $select;
}
/**
* Get eNotice version: eSender|eForms
*
* @return void
*/
static public function getVersion(Int $codice = 0) {
if(! empty($codice)) {
global $pdo;
return $pdo->go("SELECT `version` FROM b_guue WHERE codice = :codice", [":codice" => $codice])->fetch(PDO::FETCH_COLUMN, 0);
}
if(DEVELOP_ENV || strtotime('now') >= strtotime('2023-10-15 00:00:00')) {
return "eForms";
}
return "eSender";
}
/**
* Returns the modules that can provide data
*
* @param string $modulo
* @param integer $elemento
* @return array
*/
public static function moduliCollegati() {
return [
"gare" => "/gare/guue/init.php",
"pcp" => "/pcp/guue/init.php",
"concorsi" => "/concorsi/guue/init.php",
];
}
/**
* Returns all the pubblications of a specific platform's module
*
* @param string $modulo
* @param integer $elemento
* @return array
*/
public static function getPubblicazioniFromModulo(string $modulo, int $elemento) {
global $pdo;
if (!empty(self::moduliCollegati()[$modulo])) {
return $pdo->go("SELECT codice, titolo, numero, anno, numero_ojs, version, numero_tecnico, form, stato, data_trasmissione, data_pubblicazione
FROM b_guue
WHERE modulo = :modulo AND codice_elemento = :elemento AND soft_delete = 'N'",
[":modulo"=>$modulo,":elemento"=>$elemento])->fetchAll(PDO::FETCH_ASSOC);
}
}
/**
* Init the model retrieving stored data or it returning a new instance
*
* @param integer $codice
* @return void
*/
private function init($codice = 0)
{
$this->info = get_campi("b_guue");
$this->info["codice"] = 0;
$this->info["codice_ente"] = $_SESSION["ente"]->codice;
$this->info["form"] = $this->form_section;
$this->info["anno"] = date('Y');
$this->info["data_creazione"] = date('d/m/Y H:i:s');
$this->info["utente_modifica"] = $_SESSION["utente"]->codice ?? 0;
$this->info["valori"] = [];
if(! empty($codice)) {
$bind = [
':codice' => $codice,
];
$sql = "SELECT * FROM b_guue WHERE codice = :codice";
if (! empty($_SESSION["utente"]) && !isset($_SESSION["utente"]->elaborazioneCoda) && ! $_SESSION["utente"]->fromHere()) {
$sql = "{$sql} AND codice_ente = :codice_ente";
$bind[":codice_ente"] = $_SESSION["utente"]->codice_ente;
}
if (! empty($_SESSION["utente"]) && !isset($_SESSION["utente"]->elaborazioneCoda) && $_SESSION["utente"]->gerarchia > 10) {
$ids = Utente::getPermissionsInModulo($_SESSION["ente"]->codice,$_SESSION["utente"]->codice,"guue");
$ids = implode(",",$ids);
$sql .= " AND codice IN ({$ids}) ";
}
$ris = $this->pdo->go($sql, $bind);
if($ris->rowCount() == 1) {
$rec = $ris->fetch(PDO::FETCH_ASSOC);
$this->info = $rec;
if($this->isJson($this->info["valori"])) {
$this->info["valori"] = json_decode($this->info["valori"], 1);
}
}
}
}
/**
* Load includes in XML Schema
*
* @param DOMDocument $dom Instance of DOMDocument
* @param String $filepath
* @param String $namesp
* @return void
*/
private function loadIncludes(DOMDocument $dom, String $filepath = '', String $namespace = '') {
$query = "//*[local-name()='include']";
$xpath = new \DOMXPath($this->dom);
if($xpath->query($query)->length > 0) {
$this->dom = $this->loadExt($xpath->query($query), $dom, $filepath);
$this->dom = $this->loadIncludes($this->dom, $this->directory);
}
return $this->dom;
}
/**
* Load imports
*
* @param DOMDocument $dom Instance of DOMDocument
* @param String $filepath
*
* @return void
*/
private function loadImports($dom, String $filepath = '') {
$query = "//*[local-name()='import']";
$xpath = new \DOMXPath($this->dom);
if($xpath->query($query)->length > 0) {
$this->dom = $this->loadExt($xpath->query($query), $dom, $filepath);
$this->dom = $this->loadIncludes($this->dom, $this->directory);
}
return $this->dom;
}
/**
* Load imports o includes
*
* @param DOMDocument $dom Instance of DOMDocument
* @param String $filepath
*
* @return void
*/
private function loadExt($includes, $dom, $filepath)
{
if(! empty($includes->length)) {
foreach ($includes as $file) {
$parent = $file->parentNode;
$xsdFileName = realpath($filepath.DIRECTORY_SEPARATOR.$file->getAttribute("schemaLocation"));
if (! file_exists($xsdFileName)) continue;
if(in_array($xsdFileName, $this->loadedFiles ?? [])) continue;
$xsd = new \DOMDocument();
$result = $xsd->load($xsdFileName, LIBXML_DTDLOAD|LIBXML_DTDATTR|LIBXML_NOENT|LIBXML_XINCLUDE);
if($result) {
$this->loadedFiles[] = $xsdFileName;
foreach ($xsd->documentElement->childNodes as $node) {
$node = $dom->importNode($node, true);
$parent->insertBefore($node, $file);
}
}
$parent->removeChild($file);
}
}
return $dom;
}
/**
* Get Form Sections
*
* @return void
*/
private function getSections()
{
$this->sections = [];
$this->total_completed = 0;
foreach ($this->form->complexType->sequence->element as $element) {
if(empty($element["name"]) && empty($element["ref"])) continue;
$section = [
'name' => ! empty((string) $element["name"]) ? (string) $element["name"] : (string) $element["ref"],
'type' => (string) $element["type"] ?? null,
'object' => $element->getName()
];
$section["completed"] = false;
if ($this->sectionCompleted($section["name"])) {
$section["completed"] = true;
$this->total_completed++;
}
if(empty($section["type"]) && ! empty((string) $element["ref"])) $section["type"] = (string) $element["ref"];
$this->sections[] = $section;
$subsections = array_filter($this->settings["subsections"], function($subsection) use ($section){
return $subsection["parent"] == $section["name"];
});
if (count($subsections) > 0) {
foreach ($subsections as $sub) {
$sub["check"] = str_replace("[[FORM]]", $this->form_section, $sub["check"]);
$search = "//*[@name='{$sub["name"]}']";
if (count($this->dom->xpath($search)) > 0) {
$sub["type"] = $this->dom->xpath($search)[0]->attributes()["type"]->__toString();
$check = self::get($this->info["valori"], $sub["check"]);
$key = str_replace("[[FORM]]",$this->form_section,$sub["key"]);
if ($sub["name"] == $sub["parent"]) {
$key = "{$key}.{$sub["name"]}";
}
$subsection_contents = self::get($this->info["valori"], $key);
if(is_numeric($check) && $check > 0) {
for ($i=0; $i < (int) $check; $i++) {
$j = $i + 1;
if(empty($subsection_contents) || empty($subsection_contents["£"][$j])) {
//aggiungi le sottosezioni al draft se sono vuote o non valorizzate
//prima di verificare se le sezioni sono completate
$drafted_sections = self::get($this->info["valori"],"TED_ESENDERS.DRAFT_SECTIONS") ?? [];
$draft = str_replace("TED_ESENDERS.FORM_SECTION.[[FORM]].","",$sub["key"]). ".£." . $j;
if ($sub["parent"] == $sub["name"]) {
$draft = "{$sub['name']}.{$draft}";
}
if (!in_array($draft, $drafted_sections)) {
$drafted_sections[] = $draft;
}
self::set($this->info["valori"],"TED_ESENDERS.DRAFT_SECTIONS",$drafted_sections);
}
$completed = $this->sectionCompleted("{$section["name"]}.{$sub["name"]}.£.{$j}");
if ($completed) {
$this->total_completed++;
}
$section = [
"name" => $section["name"],
"subsection" => $sub["name"],
"type" => $sub["type"],
"object" => "element",
"completed" => $completed,
"index" => $i + 1
];
$this->sections[] = $section;
}
}
}
}
}
}
}
/**
* Check all form sections was completed
* @return bool
*/
public function ready() : bool {
return $this->total_completed == count($this->sections);
}
/**
* Check if given section is last needed to complete form
* @param String $section
* @return bool
*/
public function willFormBeReadyAfterSectionCompletion(String $section, String $index) : bool {
if ($this->total_completed == count($this->sections) - 1) {
$draft_sections = $this->get($this->info["valori"],"TED_ESENDERS.DRAFT_SECTIONS");
$section_check = $section;
if (!is_array($draft_sections)) {
return false;
}
#se non è presente un alcun index non siamo in una sottosezione, quindi possiamo essere più stringenti nella verifica
if (empty($index)) {
return count($draft_sections) == 0 || (count($draft_sections) == 1 && $draft_sections[array_keys($draft_sections)[0]] == $section);
}
#altrimenti controlla se è presente una corrispondenza per la sezione attuale
return count($draft_sections) == 0 || (count($draft_sections) == 1 && strpos($draft_sections[array_keys($draft_sections)[0]],$section_check . ".£.{$index}") !== false);
}
return false;
}
/**
* Check if given section is completed
* @param SimpleXMLIterator $element
* @return bool
*/
public function sectionCompleted(String $section) {
return $this->get($this->info["valori"], "TED_ESENDERS.FORM_SECTION.{$this->form_section}.{$section}") !== null && !in_array(
$section, $this->get($this->info["valori"],"TED_ESENDERS.DRAFT_SECTIONS") ?? []
);
}
/**
* Check if form is completed
*
* @return Bool|null
*/
public function completed() : ?Bool
{
$this->getSections();
$check = array_unique(array_column($this->sections, "completed"));
if(count($check) == 1 && $check[0]) {
return true;
}
return false;
}
/**
* Get fields For Section
*
* @param Array $section
* @param Bool $multiple
*
* @return void
*/
public function getFieldsForSection(Array $section, Array $name = [], $multiple = false)
{
$this->fields[$section["name"]] = [];
$this->optionals[$section["name"]] = [];
if(empty($name)) {
$name = [
"TED_ESENDERS",
"FORM_SECTION",
$this->form_section
];
}
if($section["object"] == "element") $name[] = $section["name"];
if($multiple) {
$name[] = TedEsender::MUL;
if(isset($section["index"])) {
$name[] = $section["index"];
}
}
$type = $this->getTypeElement($section["type"]);
if(! empty($type)) {
if(is_array($type)) $type = reset($type);
$this->getField($section["name"], $type, ["name" => $name]);
}
//if ($this->debug) dd($this->fields);
}
private function getFormContent() {
return $this->info["valori"]["TED_ESENDERS"]["FORM_SECTION"][((string) $this->form->attributes()["name"])];
}
/**
* unpack choices from XMLIterator
* @param Array $node
* @return Array
*/
private function unpackChoice(Array $node) {
$result = [];
foreach ($node as $key => $value) {
if ($key == "sequence") {
array_push($result, ...$this->unpackChoice($value));
}
if ($key == "element") {
if (is_array($value)) {
foreach ($value as $v) {
if (is_a( $v, SimpleXMLIterator::class ) ) {
array_push($result, ((string) $v->attributes()["name"]));
} else if (is_array($v)) {
if ($v["ref"]) {
array_push($result, $v["ref"]);
}
}
}
}
}
}
return array_filter($result, function($value) { return !is_null($value) && $value !== ''; });
}
/**
* Get the element description parameters
*
* @param String $t
* @return SimpleXMLElement
*/
private function getTypeElement(String $t)
{
$type = $this->dom->xpath("simpleType[@name='{$t}']");
if(empty($type)) $type = $this->dom->xpath("complexType[@name='{$t}']");
if(empty($type)) $type = $this->dom->xpath("group[@name='{$t}']");
if(empty($type)) $type = $this->dom->xpath("element[@name='{$t}']");
if(! empty($type) && is_array($type)) $type = reset($type);
return $type;
}
/**
* Questa funzione è da riscrivere, mo funziona a pezza
* Lo scopo di questa funzione è cercare all'interno di un array di array il primo ["name"] che trova
*/
private static function unpackUntil($arr, String $key, $or) {
#controlla se nell'array c'è la chiave ricercata
if (is_array($arr)) {
if (!empty($arr[$key])) {
return $arr[$key];
#se non è presente e l'array è numerico cercala negli indici
} else if (!empty($arr[$or]) && is_array($arr[$or])) {
if (!empty($arr[$or]["info"]) && !empty($arr[1])) {
$or = 1;
}
return self::unpackUntil($arr[$or], $key, $or);
#se non è numerico cercala all'interno delle chiavi
} else if (!empty($arr) && isAssociative($arr)) {
$last = array_keys($arr)[0];
return self::unpackUntil($arr[$last],$key, $or);
}
}
return null;
}
/**
* Print form fields
*
* @param Array $field
* @return void
*/
private function printField(Array $field, Bool $row = true)
{
if(! empty($field["info"]["title"])) {
if($row) { ?><div class="row"><? }
?>
<div class="col-12 my-3 <?=!empty($field["info"]["hidden"]) && $field["info"]["hidden"] == true ? "d-none" : null?>">
<?
switch($field["info"]["style"] ?? null) {
case "subtitle":
$style = "border-bottom mb-0 border-black text-muted h6";
break;
case "annotation":
$style = "border-dark mb-0 h6 text-muted small";
break;
default:
$style = "border-bottom border-dark mb-0 h5";
break;
}
$class = "";
if (!empty($field["info"]["attrs"]["class"])) {
$class = $field["info"]["attrs"]["class"];
}
?>
<p class="<?=$style?> <?=$class?>">
<?= $this->translate($field["info"]["title"], self::unpackUntil($field,"name",0)) ?>
</p>
</div>
<?
unset($field["info"]);
$this->printField($field, false);
if($row) { ?></div><? }
} else {
if(! empty($field["name"]) && ! empty($field["type"]) && method_exists($this, "__{$field["type"]}")) {
$key = trim(str_replace(['][', '[', ']'], '.', str_replace("guue", "", $field["name"])), '.');
$value = $this->get($this->info["valori"], $key);
if (!isset($value)) {
$value = (string) $this->getSuggetion($key);
if (isset($value) && !empty($field["attrs"]) && is_array($field["attrs"]) && (in_array("onChange",array_keys($field["attrs"])) !== false || in_array("onclick",array_keys($field["attrs"])) !== false)) {
$field["triggerOnChange"] = true;
}
}
if(isset($value) && is_string($value)) {
$field["val"] = $value;
}
echo $this->{$field["type"]}($field);
} else {
$fields = $field;
foreach ($fields as $key => $field) {
if( (strpos($key, "RADIO_FOR") !== false || empty($field["name"])) && ! in_array($key, $this->ignored_keys) && ! is_numeric($key)) {
$attrs = "";
$class = "";
$required_check = "";
if(is_array($field) && in_array("radio", array_column($field, "type"))) {
if ($field[0]["required"] ?? false) {
$required_check = " <?= TedEsender::MANDATORY_ASTERISK ?>";
}
$validation = array_unique(array_column($field, "group_validate"));
if(empty($validation) || (count($validation) == 1 && $validation[0])) {
$attrs = 'rel="S;0;0;checked;group_one" title="' . $this->translate($key, self::unpackUntil($field,"name",0)) . '"';
$class = "valida";
}
}
$title = $this->translate($key, self::unpackUntil($field,"name",0)) . $required_check;
if (!empty($this->settings["titles"][$key])) {
$title = $this->translate($this->settings["titles"][$key], self::unpackUntil($field,"name",0)) . $required_check;
}
?><div class="col-12 my-3 <?=strpos($key, "TITLE_FOR") !== false ? "d-none" : null ?>"><p class="border-bottom mb-0 <?= strpos($title ?? "", "):") === false ? "border-black text-muted h6" : "h5"?>"><?= $title ?></p></div><div class="col-12 form-group"><div class="<?= $class ?> row" <?= $attrs ?>><?
}
if(! empty($field["name"]) && empty($field["title"])) $field["title"] = $this->translate($key, self::unpackUntil($field,"name",$key));
$this->printField($field, false);
if( (strpos($key, "RADIO_FOR") !== false || empty($field["name"])) && ! in_array($key, $this->ignored_keys) && ! is_numeric($key)) {
?></div></div><?
}
}
}
}
}
/**
* Store data
*
* @param Array $data
* @return void
*/
public function save(Array $data) : array
{
$result = [
"action" => self::DEFAULT,
"codice" => null
];
$subsection = null;
$record = $this->info;
$draft = $record["valori"]["TED_ESENDERS"]["DRAFT_SECTIONS"] ?? [];
if (empty($record["codice"]) && empty($draft)) {
foreach ($this->sections as $section) {
$draft[] = $section["name"];
}
}
$to_draft = $data["current_section"];
if ($data["draft"] == "S" && empty($data["current_sub_section"])) {
array_push($draft, $to_draft);
} else if (in_array($to_draft, $draft) && empty($data["current_sub_section"])) {
unset($draft[(array_search($to_draft,$draft))]);
}
if(! empty($data["titolo"])) { $record["titolo"] = $data["titolo"]; }
if(! empty($this->settings["sections"][$data["current_section"]])) {
if(! empty($data["current_sub_section"])) {
$key = "{$this->settings["sections"][$data["current_section"]]}.{$data["current_sub_section"]}";
$key = str_replace("[[FORM]]", $this->form_section, $key);
if(! empty($data["current_sub_section_index"])) {
$key = "{$key}.£.{$data["current_sub_section_index"]}";
$draft_key = str_replace("TED_ESENDERS.FORM_SECTION.{$this->form_section}.","",$key);
if ($data["draft"] == "S") {
array_push($draft,$draft_key);
} else if (in_array($draft_key, $draft)) {
unset($draft[(array_search($draft_key,$draft))]);
}
}
self::set($record["valori"], $key, []);
$result["action"] = self::EDITED_SUBSECTION;
} else {
$key = "{$this->settings["sections"][$data["current_section"]]}";
$key = str_replace("[[FORM]]", $this->form_section, $key);
$subsections = array_filter($this->settings["subsections"], function($subsection) use ($data) {
return $subsection["parent"] == $data["current_section"] && !empty(
self::get($this->info["valori"], str_replace("[[FORM]]", $this->form_section, $subsection["check"]))
);
});
if (count($subsections) > 0) {
foreach ($subsections as $subsection) {
$subsection_check = str_replace("[[FORM]]", $this->form_section, $subsection["check"]);
$subsection_key = str_replace("[[FORM]]", $this->form_section, $subsection["key"]);
#se il valore risulta vuoto all'interno del form, viene inserito come zero
if (empty(self::get($data["guue"],$subsection_check)) && $subsection["name"] == $subsection["parent"]) {
self::set($data["guue"],$subsection_check,0);
}
$check = (int) (self::get($data["guue"], $subsection_check));
$valori = self::get($record["valori"], $subsection_key) ?? [];
if(is_numeric($check) && $check > 0) {
if (isset($valori["£"]) && count($valori["£"]) > $check ) {
$difference = count($valori["£"]) - $check;
$keys = array_slice(array_keys($valori["£"]),count($valori["£"]) - $difference, count($valori["£"]));
foreach ($keys as $key) {
unset($valori["£"][$key]);
}
} else if (isset($valori[$data["current_section"]]["£"]) && $valori[$data["current_section"]]["£"] > $check) {
$difference = count($valori[$data["current_section"]]["£"]) - $check;
$keys = array_slice(array_keys($valori[$data["current_section"]]["£"]),count($valori[$data["current_section"]]["£"]) - $difference, count($valori[$data["current_section"]]["£"]));
foreach ($keys as $key) {
unset($valori[$data["current_section"]]["£"][$key]);
}
}
self::set($subsection["valori"], $subsection_key, $valori);
} else { #nel caso in cui il check sia vuoto ma sono presenti dei contenuti rimuovili
foreach ($draft as $index => $draft_section) {
if (strpos($draft_section,"{$subsection['parent']}.{$subsection['name']}.£") !== false) {
unset($draft[$index]);
}
}
if (!empty($valori["£"])) {
unset($valori["£"]);
#controlla se la sezione è presente nelle draft
}
$result["action"] = self::REMOVED_SUBSECTIONS;
}
}
}
self::set($record["valori"], $key, []);
}
} else {
self::set($record["valori"],"TED_ESENDERS.FORM_SECTION.{$this->form_section}.{$data['current_section']}",[]);
}
$this->removeOverridedKeys($data["guue"]);
$record["valori"] = $this->md_array_merge($record["valori"], $data["guue"]);
$draft = array_unique($draft);
self::set($record["valori"],"TED_ESENDERS.DRAFT_SECTIONS",$draft);
if(! empty($subsection["valori"])) {
$record["valori"] = $this->md_array_merge($record["valori"], $subsection["valori"]);
}
$this->sortSections();
$record["valori"] = $this->fixHtmlVaues($record["valori"]);
array_walk_recursive($record["valori"], 'htmlentitiesdecode');
$record["valori"] = json_encode($record["valori"],JSON_INVALID_UTF8_IGNORE);
$record["data_aggiornamento"] = date('d/m/Y H:i:s');
$record["data_trasmissione"] = null;
$record["modulo"] = $_POST["modulo"] ?? null;
$record["codice_elemento"] = $_POST["codice_elemento"] ?? 0;
$record["stato"] = self::stati()[0]["title"];
if (! $_SESSION["utente"]->fromHere()) {
$record["codice_ente"] = $_SESSION["utente"]->codice_ente;
}
$salva = new Salva();
$salva->debug = false;
$salva->nome_tabella = "b_guue";
$salva->operazione = "INSERT";
$salva->ignore = ["soft_delete"];
if(! empty($record["codice"])) {
$salva->operazione = "UPDATE";
$salva->ignore[] = "data_creazione";
$salva->ignore[] = "utente_modifica";
$salva->ignore[] = "data_pubblicazione";
}
$salva->oggetto = $record;
$codice = $salva->save();
if(! empty($codice)) {
$this->info = $salva->oggetto;
$this->info["codice"] = $codice;
if($_SESSION["utente"]->gerarchia > 15 && $salva->operazione == "INSERT") {
$permesso = [];
$permesso["sezione"] = "guue";
$permesso["codice_elemento"] = $this->info["codice"];
$permesso["codice_gestore"] = $_SESSION["ente"]->codice;
$permesso["funzione"] = "0";
$permesso["codice_utente"] = $_SESSION["utente"]->codice;
$salva = new salva();
$salva->debug = false;
$salva->raw = true;
$salva->nome_tabella = "r_permessi";
$salva->operazione = "INSERT";
$salva->oggetto = $permesso;
$salva->save();
}
$this->info["valori"] = json_decode($this->info["valori"], 1);
$result["codice"] = $codice;
return $result;
}
$result["codice"] = $codice;
return $result;
}
public function getLastNumber() : int {
$number = 0;
$latest = $this->pdo->go("SELECT MAX(numero) FROM b_guue WHERE anno = :anno", [":anno" => date('Y')])->fetch(PDO::FETCH_COLUMN, 0);
if($latest > 0) { $number = $latest; }
return $number;
}
/**
* Create xml notice
*
* @param Array $valori
* @return void
*/
public function xml(Array $data = [], Array $ente = [], bool $update_state = true) : void
{
if(empty($ente) || empty($ente["id_guue"])) { $ente = $_SESSION["ente"]->getInfo(); }
if(empty($data)) { $data = $this->info; }
if(empty($data["numero"])) {
$data["numero"] = $this->getLastNumber() + 1;
$this->info["numero"] = $data["numero"];
$this->pdo->go(
"UPDATE b_guue SET numero = :numero WHERE codice = :codice",
[":numero" => $data["numero"], ":codice" => $this->info['codice']]
);
}
if(strlen($data["numero"]) < 6) {
$data["numero"] = str_repeat("0", 6 - strlen($data["numero"])) . $data["numero"];
}
$this->auth();
$TED_ESENDERS = $data["valori"]["TED_ESENDERS"];
$data["valori"]["TED_ESENDERS"] = [
"_attributes" => [
"xmlns" =>"http://publications.europa.eu/resource/schema/ted/R2.0.9/reception",
"xmlns:tg"=>"http://publications.europa.eu/resource/schema/ted/R2.0.9/reception",
"xmlns:tg-nuts"=>"http://publications.europa.eu/resource/schema/ted/2021/nuts",
"xmlns:tg-curr" => "http://publications.europa.eu/resource/authority/currency",
"xmlns:xsi"=>"http://www.w3.org/2001/XMLSchema-instance",
"xsi:schemaLocation"=>"http://publications.europa.eu/resource/schema/ted/R2.0.9.S05/publication TED_EXPORT.xsd",
"VERSION"=>"R2.0.9.S05",
],
"SENDER" => [
"IDENTIFICATION" => [
"ESENDER_LOGIN" => $this->username,
"CUSTOMER_LOGIN" => $ente["id_guue"] ?? "__£__",
"NO_DOC_EXT" => "{$data["anno"]}-{$data["numero"]}",
"SOFTWARE_VERSION" => "3.0",
],
"CONTACT" => [
"ORGANISATION" => "STUDIO AMICA SRL",
"COUNTRY" => [
"_attributes" => [
"VALUE" => "IT"
]
],
"PHONE" => "",
"E_MAIL" => "gaetano.lolli@studioamica.it",
]
]
];
$data["valori"]["TED_ESENDERS"] = array_merge($data["valori"]["TED_ESENDERS"], $TED_ESENDERS);
foreach ($data["valori"]["TED_ESENDERS"]["FORM_SECTION"] as $key => $form) {
$data["valori"]["TED_ESENDERS"]["FORM_SECTION"][$key] = array_merge([
"_attributes" => [
"LG" => "IT",
"CATEGORY" => "ORIGINAL",
"FORM" => substr($key, 0, strpos($key, "_")),
]
], $data["valori"]["TED_ESENDERS"]["FORM_SECTION"][$key]);
}
try {
$stati = $this->stati();
$stato = $stati[0]["title"];
$this->xml = $this->errors = "";
$this->fixArrayForXml($data["valori"]);
$this->xml = \Spatie\ArrayToXml\ArrayToXml::convert($data["valori"]["tg:TED_ESENDERS"], "tg:TED_ESENDERS");
$originalErrorHandling = libxml_use_internal_errors(true);
$document = new DOMDocument();
$document->loadXML($this->xml);
$document->schemaValidate(__DIR__ . "/../config/xml/TED_ESENDERS.xsd");
$errors = libxml_get_errors();
$this->errors = [];
if(! empty($errors)) {
foreach ($errors as $error) {
$e = str_replace(["{http://publications.europa.eu/resource/schema/ted/R2.0.9/reception}", "{http://publications.europa.eu/resource/schema/ted/2021/nuts}"], "", $error->message);
$e = preg_replace('/[[:cntrl:]]/', '', $e);
if(! in_array($e, $this->errors)) $this->errors[] = $e;
}
}
$this->errors = array_filter($this->errors);
libxml_clear_errors();
libxml_use_internal_errors($originalErrorHandling);
} catch (\Throwable $th) {
$message = "GUUE CODICE: {$this->info["codice"]} IMPOSSIBILE GENERARE XML. ERRORE: " . $th->getMessage();
if ($this->debug) {
echo $message;
}
error_log($message);
} finally {
if(! empty($this->xml) && empty($this->errors)) {
$stato = $stati[1]["title"];
}
$this->errors = base64_encode(json_encode($this->errors));
$s = array_flip(array_column($stati, 'title'));
if($stati[$s[$stato]]["status"] < 20) {
if ($update_state) {
$this->pdo->go("UPDATE b_guue
SET xml = :xml, errori = :errori, stato = :stato, data_aggiornamento = NOW()
WHERE codice = :codice",
[
":xml" => base64_encode($this->xml),
":errori" => $this->errors,
":stato" => $stato,
":codice" => $this->info["codice"]
]);
}
}
}
}
public function getBreadcrumb($breadcrumb = []) {
if (!empty($this->info["modulo"]) && !empty(!empty($this->info["codice_elemento"]))) {
if ($_SESSION["utente"]->permission($this->info["modulo"],$this->info["codice_elemento"])) {
global $beRoot;
if (file_exists("{$beRoot}/{$this->info["modulo"]}/panel.php")) {
$infoModulo = Modulo::getInfo($this->info["modulo"]);
$breadcrumb["/{$this->info["modulo"]}/panel.php?codice={$this->info["codice_elemento"]}"] = __guue($infoModulo["titolo"]) . " - " . __guue("Pannello");
}
}
}
return $breadcrumb;
}
/**
* It iterate form field group
*
* @param String $section
* @param array $fields
* @return void
*/
public function printFields(String $section, Array $fields = [])
{
if(empty($fields)) { $fields = $this->fields; }
foreach ($fields as $field) {
if(! isset($field[$section]) && is_array($field)) {
$this->printFields($section, $field);
} else {
$this->printField($field[$section]);
}
}
}
/**
* Main function to print a form section
*
* @param Array $section
* @return void
*/
public function printForm(Array $section)
{
if(! empty($section["name"])) {
$n = [];
$this->current_section = $s = $section;
if(! empty($section["subsection"])) {
$n = [
"TED_ESENDERS",
"FORM_SECTION",
$this->form_section,
$section["name"],
];
$s["name"] = $s["subsection"];
$m = true;
$this->getFieldsForSection($s, $n, $m);
$fields = $this->fields["TED_ESENDERS"]["FORM_SECTION"][$this->form_section][$section["name"]][$section["subsection"]];
if($m && isset($section["index"])) { $fields = $fields[TedEsender::MUL][$section["index"]]; }
$this->setMissingTitles($fields, $section["subsection"]);
} else {
$this->getFieldsForSection($s);
$fields = $this->fields["TED_ESENDERS"]["FORM_SECTION"][$this->form_section][$section["name"]];
$this->setMissingTitles($fields, $section["name"]);
}
if(! empty($this->fields["TED_ESENDERS"]["FORM_SECTION"][$this->form_section][$section["name"]])) {
?>
<p class="h3 mb-4"><?= $this->translate($section["name"], self::unpackUntil($section,"name",0)) ?></p>
<div class="row">
<?
$this->printField($fields, false);
?>
</div>
<?
}
}
?>
<script type="text/javascript">
var add2GUUE = function (target, data) {
$.ajax({
type: "POST",
url: "/backend/guue/add2GUUE.php?codice=<?= $this->info["codice"] ?>",
data: {data: data},
dataType: "html",
beforeSend: function() {
$("#wait_div").show();
}
})
.fail(function(response) {
swal(js_dict["error-retry"]);
})
.done(function(response) {
$(target).append(response);
f_ready();
})
.always(function() {
$("#wait_div").slideUp('fast');
});
}
var disableSibling = function (disabler, disabled) {
// console.log(disabled);
if ( $(disabler).val() != "" && $(disabler).val() != undefined && $(disabler).val() != null ) {
$(disabled).prop('disabled', true);
$(disabled).prop('disabled', true).trigger("chosen:updated");
} else {
$(disabled).prop('disabled', false);
$(disabled).prop('disabled', false).trigger("chosen:updated");
}
}
<?
if (!empty($this->suggestionTriggers)) {
foreach($this->suggestionTriggers AS $triggerID) {
?>
$("#<?= $triggerID ?>").trigger("change");
<?
}
}
?>
</script>
<?
}
/**
* Label translator
*
* @param String $string
* @return void
*/
public function translate(String $string, ?String $name = null)
{
if (!empty($this->settings["dynamic_translations"][$this->form_section])) {
$string = $this->settings["dynamic_translations"][$this->form_section][$string] ?? $string;
}
$name = explode("][",substr($name,5,-1));
$section = null;
if (count($name) > 3) { $section = $name[3]; }
//Parse settings name array searching for last subsection
foreach ([4,7] as $pos) {
if (count($name) > $pos && in_array($name[$pos], array_map(function($section){ return ($section["name"]); },$this->settings["subsections"]))) {
$section = $name[$pos];
}
}
$numeration = "";
if (
! empty($section) &&
! empty($this->settings["numeration_map"]) &&
! empty($this->settings["numeration_map"]["{$this->form_section}"]) &&
! empty($this->settings["numeration_map"]["{$this->form_section}"]["{$section}"]) &&
! empty($this->settings["numeration_map"]["{$this->form_section}"]["{$section}"]["{$string}"])
) {
$numeration = $this->settings["numeration_map"]["{$this->form_section}"]["{$section}"]["{$string}"];
}
$translate_functions = [
"PT_NEGOTIATED_WITHOUT_PUBLICATION" => function() use ($string, $name) : String {
if (in_array($name[count($name)-2], ["DIRECTIVE_2014_24_EU","DIRECTIVE_2014_25_EU","DIRECTIVE_2009_81_EC"]) && $string == "PT_NEGOTIATED_WITHOUT_PUBLICATION") {
return $name[count($name)-2] . "_SELECTION_WITHOUT_PUBLICATION";
}
return $string;
},
"PT_AWARD_CONTRACT_WITHOUT_CALL" => function() use ($string, $name) : String {
if (in_array($name[count($name)-2], ["DIRECTIVE_2014_24_EU","DIRECTIVE_2014_25_EU","DIRECTIVE_2009_81_EC"]) && $string == "PT_AWARD_CONTRACT_WITHOUT_CALL") {
return $name[count($name)-2] . "_SELECTION_WITHOUT_CALL";
}
return $string;
},
"ADDRESS_REVIEW_BODY_WARNING" => function() use ($string, $name) : String {
return __guue('(Indirizzo del corpo di revisione)');
},
"ADDRESS_MEDIATION_BODY_WARNING" => function() use ($string, $name) : String {
return __guue('(Responsabile delle procedure di mediazione)');
},
"ADDRESS_REVIEW_INFO_WARNING" => function() use ($string, $name) : String {
return __guue('(Informazioni sulla revisione)');
},
"ADDRESS_CONTRACTING_BODY_WARNING" => function() use ($string, $name) : String {
return __guue('(Denominazione e indirizzi)');
},
"ADDRESS_CONTRACTING_BODY_ADDITIONAL_WARNING" => function() use ($string, $name) : String {
return __guue('(Altre stazioni appaltanti)');
},
"ADDRESS_PARTICIPATION_WARNING" => function() use ($string, $name) : String {
return __guue("(Offerte e domande di partecipazione)");
},
"ADDRESS_FURTHER_INFO_WARNING" => function() use ($string, $name) : String {
return __guue("(Ulteriori informazioni sono disponibili presso)");
}
];
if (!empty($name) && in_array($string, array_keys($translate_functions))) {
$translate_func = $translate_functions[$string];
$string = $translate_func();
}
if(! empty($this->mapper[$string])) {
if(! empty($this->translator[$this->mapper[$string]]["it"])) $string = $this->translator[$this->mapper[$string]]["it"];
}
if (!empty($numeration)) {
return $numeration . " " . $string;
}
return $string;
}
#region [Validation Rules Traductions]
private function dateFormatValidationRule(Array $matches, String $raw_err) : String {
$key = str_replace($matches[1], "", $matches[0]);
if (!empty($this->mapper["ERRORS_DICT"][$key]["it"])) {
$err = $this->mapper["ERRORS_DICT"][$key]["it"];
$chunk = str_split($matches[1], 2);
$chunk[2] = $chunk[2] . $chunk[3];
unset($chunk[3]);
$err = str_replace("[[DATE]]",implode("/",$chunk),$err);
}
return $err ?? $matches[0];
}
private function phoneNumberValidationRule(Array $matches, String $raw_err) : String {
$err = null;
if (count($matches) > 2) {
if ($matches[1] == "phone") {
$matches[1] = "Tel";
}
$matches[1] = ucfirst($matches[1]);
$err = __guue($matches[1]) . " {$matches[2]} " . __guue("non è un numero telefonico valido.");
}
return $err ?? $matches[0];
}
private function numberNoticeValidationRule(Array $matches, String $raw_err) : String {
$err = null;
if (count($matches) > 1) {
$err = $matches[1] . " " . __guue("non è un numero di avviso valido.");
}
return $err;
}
private function annexD1ValidationRule(Array $matches, String $raw_err) : String {
$m = [];
preg_match_all('/[[][@]CTYPE[=](\w+)[]]/m', $raw_err, $m);
if (count($m) > 1 && count($m[1]) > 1) {
return __guue("Attenzione, la tipologia del contratto risulta incoerente con la giustificazione dell'allegato Annex D1, Tipologia del contratto ({$this->translate($m[1][0])}) è differente dalla tipologia accettata ({$this->translate($m[1][1])})");
}
return $raw_err;
}
private function publicationValidationRule(Array $matches, String $raw_err) : String {
$matches = [];
preg_match_all('/([A-Z0-9_]+)[\/][@][A-Z0-9_]+=\w+ and ([A-Z0-9_]+)[\/]([A-Z0-9_]+)[[].*[@]PUBLICATION[]]/',$raw_err,$matches);
if (count($matches) > 3) {
if ($matches[2] == [] || $matches[3] == []) {
return $raw_err;
}
$section2 = $matches[2][0];
$section3 = $matches[3][0];
$replacements = [
"AWARDED_CONTRACT" => "RADIO_FOR_SME_SECTION",
"CONTRACTORS" => "ADDRESS_CONTRACTOR",
"VALUES" => "VALUE",
"AC" => "AC_DEF"
];
if (!empty( $replacements[$section2]) ) {
$section2 = $replacements[$section2];
}
if (!empty( $replacements[$section3]) ) {
$section3 = $replacements[$section3];
}
$section = __guue("Sezione") . ": " . $this->translate($section2) . ", " . $this->translate($section3);
return __guue("La pubblicazione è richiesta per contratti sotto direttiva 2014/25/EU") . ". " . $section;
}
return $raw_err;
}
private function repeatValidationRule(Array $matches, String $raw_err) : String {
if ($matches > 2) {
$element = $this->translate(strtoupper($matches[2]));
$type = $this->translate(strtoupper($matches[1]));
return __guue("Non è possibile inserire molteplici elementi") . "(" . $element . " ), " . __guue("se la tipologia di avviso è") . " (" . $type . " )";
}
return $raw_err;
}
private function qualificationValidationRule(Array $matches, String $raw_err) : String {
$matches = [];
preg_match_all('/\w+[\/][@]TYPE[=](\w+) and (\w+)[[](\d)[]][\/](\w+)[[][\d][]][\/]QS[\/](\w+)/s',$raw_err, $matches);
if (count($matches) > 5) {
$type = $this->translate($matches[1][0]);
$section = $this->translate($matches[2][0]);
$index = $this->translate($matches[3][0]);
$subsection = $this->translate($matches[4][0]);
$field = $this->translate($matches[5][0]);
return " n.{$index} " . "(". $field . " ) " . __guue("è prevista solo se la tipologia del contratto è un Sistema di qualificazione ") . "(" . $type . " )";
}
return $raw_err;
}
#endregion
/**
* Convert validation rules errors into human readable errors
*
* @param array $errors
* @return array
*/
public function validationRuleToHuman(Array $errors) {
$latin = [
1 => "I",
2 => "II",
3 => "III",
4 => "IV",
5 => "V",
6 => "VI",
7 => "VII",
8 => "VIII",
9 => "IX",
10 => "X",
];
foreach ($errors as $index => $err) {
$raw_err = $err;
$matches = [];
preg_match('/[:](.*)[.][<]br[>]/s', $err, $matches);
if (count($matches) == 2) {
$err = trim($matches[1]);
} else {
$matches = [];
preg_match('/:([ ]\w+[-]\w+[-]\w+[:].*)[.][ ][<]br[>]/s', $err, $matches);
if (count($matches) != 0) {
$err = trim($matches[count($matches)-1]);
}
}
$err = str_replace(['"',';',',',"'","/","(",")","<br>"], "", $err);
$err = str_replace([":"," ","__"], "_", $err);
$err = str_replace("...","", $err);
$err = strtolower($err);
#TODO: Rimuove gli errori relativi al campo lingua, da adattare una volta implementate le altre lingue
$languages_errors = [
"s4-02-04_languages_not_foreseen_if_the_notice_aims_at_reducing_time_limits",
"s4-02-04_languages_not_foreseen_if_contract_award_notice",
"s4-02-04_languages_not_foreseen_if_it_is_about_a_qualification_system",
"s4-02-04_languages_not_foreseen_if_concession_award_notice",
"s4-02-04_languages_mandatory_if_this_notice_is_a_call_for_competition",
"s4-02-04_languages_mandatory_if_prior_information_notice"
];
if (in_array($err,$languages_errors)) {
unset($errors[$index]);
continue;
}
#################
if (!empty($this->mapper["ERRORS_DICT"][$err]["it"])) {
$err = $this->mapper["ERRORS_DICT"][$err]["it"];
} else {
foreach ([
'/and_lefti_s3_legal_economic_financial_and_technical_information_not_foreseen_if/s' => $this->mapper["ERRORS_DICT"]["and_lefti_s3_legal_economic_financial_and_technical_information_not_foreseen_if"]["it"],
'/notice_dispatch_date_element_must_contain_the_real_sending_date_of_xml_notice[.]dispatch_date_in_the_notice_is_(\d+)/s' => 'dateFormatValidationRule',
'/lot_no_must_be_unique_within/s' => __guue('Il numero dei lotti deve essere univoco.'),
'/element_(\w+)_(.*)_is_not_a_valid_value_of_the_atomic_type_phone/s' => 'phoneNumberValidationRule',
'/element_notice_number_oj_[[]facet_pattern[]]_the_value_(.*)_is_not/s' => 'numberNoticeValidationRule',
'/annex_d-1_justification_inconsistency_with_the_contract_type/s' => 'annexD1ValidationRule',
'/is_not_a_valid_value_of_the_atomic_type_noticeno/s' => __guue('Il numero dell\'avviso non è valido'),
'/duplicate_no_doc_ext_a_notice_with_the_same_identifier_has_already_been_received/s' => __guue('Attenzione, un form con lo stesso identificativo è già stato ricevuto'),
'/the_agreement_to_the_publication_of_information_is_required_only_in_case_of_a_notice_covered_by_directive_201425eu/s' => 'publicationValidationRule',
'/notice[@]type[=](\w+)_and_number(\w+)[=].*the_section_could_not_be_repeated/s' => 'repeatValidationRule',
'/s2-02-08_duration_of_the_qualification_system_foreseen_for_a_qualification_system/s' => 'qualificationValidationRule'
] as $regex => $callback) {
$matches = [];
preg_match($regex, $err, $matches);
if (count($matches) != 0) {
if (method_exists($this, $callback)) {
$err = $this->{$callback}($matches, $raw_err);
} else if (is_string($callback)) {
$err = $callback;
}
}
}
}
$section_matches = [];
preg_match('/S(\d+[-]\d+[-]\d+)[:]|S(\d+)/',$raw_err,$section_matches);
$err_sect = "";
if (!empty($section_matches) && count($section_matches) > 1) {
$section_matches = (explode("-",$section_matches[count($section_matches) - 1]));
foreach ($section_matches as $i => $identifier) {
$section_matches[$i] = (int) $identifier;
if ($i == 0) {
$section_matches[$i] = "{$latin[$identifier]})";
}
}
$err_sect = __guue("Sezione") . " {$section_matches[0]} " . (implode(".",array_slice($section_matches,1))) . " ";
}
$err = $err_sect . $err;
$errors[$index] = $err;
}
return array_unique($errors);
}
public function setMode(string $string) : void {}
public function manageChangeSection() : void {}
public function getReorderedSections() : void {}
}
include_once 'eFormsManager.class.php';