diff --git a/.github/workflows/action.yml b/.github/workflows/action.yml
new file mode 100644
index 0000000..3bbfc3f
--- /dev/null
+++ b/.github/workflows/action.yml
@@ -0,0 +1,43 @@
+name: Add PRs to Combodo PRs Dashboard
+
+on:
+ pull_request_target:
+ types:
+ - opened
+
+jobs:
+ add-to-project:
+ name: Add PR to Combodo Project
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check if author is a member of the organization
+ id: check-membership
+ run: |
+ ORG="Combodo"
+ AUTHOR=$(jq -r .pull_request.user.login "$GITHUB_EVENT_PATH")
+ RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" -H "Authorization: token ${{ secrets.PR_AUTOMATICALLY_ADD_TO_PROJECT }}" \
+ "https://api.github.com/orgs/$ORG/members/$AUTHOR")
+ if [ "$RESPONSE" == "404" ]; then
+ echo "project_url=https://github.com/orgs/Combodo/projects/5" >> $GITHUB_ENV
+ echo "is_member=false" >> $GITHUB_ENV
+ else
+ echo "project_url=https://github.com/orgs/Combodo/projects/4" >> $GITHUB_ENV
+ echo "is_member=true" >> $GITHUB_ENV
+
+ fi
+
+ - name: Add internal tag if member
+ if: env.is_member == 'true'
+ run: |
+ curl -X POST -H "Authorization: token ${{ secrets.PR_AUTOMATICALLY_ADD_TO_PROJECT }}" \
+ -H "Accept: application/vnd.github.v3+json" \
+ https://api.github.com/repos/Combodo/itop-data-collector-base/issues/${{ github.event.pull_request.number }}/labels \
+ -d '{"labels":["internal"]}'
+ env:
+ is_member: ${{ env.is_member }}
+
+ - name: Add PR to the appropriate project
+ uses: actions/add-to-project@v1.0.2
+ with:
+ project-url: ${{ env.project_url }}
+ github-token: ${{ secrets.PR_AUTOMATICALLY_ADD_TO_PROJECT }}
diff --git a/composer.json b/composer.json
index feb3990..e347ec1 100644
--- a/composer.json
+++ b/composer.json
@@ -1,6 +1,6 @@
{
"require": {
- "php": "7.*",
+ "php": "7.* || 8.* <= 8.3",
"ext-libxml": "*"
},
"require-dev": {
diff --git a/conf/params.distrib.xml b/conf/params.distrib.xml
index c11fad3..0992f35 100644
--- a/conf/params.distrib.xml
+++ b/conf/params.distrib.xml
@@ -107,5 +107,5 @@
- Y-m-d
+ Y-m-d H:i:s
diff --git a/core/collector.class.inc.php b/core/collector.class.inc.php
index 3b4d624..189ae58 100644
--- a/core/collector.class.inc.php
+++ b/core/collector.class.inc.php
@@ -594,7 +594,7 @@ protected function AddRow($aRow)
{
$aData = array();
foreach ($this->aCSVHeaders as $sHeader) {
- if (is_null($aRow[$sHeader]) && $this->AttributeIsNullified($sHeader)) {
+ if (strlen($aRow[$sHeader] ?? '')===0 && $this->AttributeIsNullified($sHeader)) {
$aData[] = NULL_VALUE;
} else {
$aData[] = $aRow[$sHeader];
@@ -692,7 +692,7 @@ public function Synchronize($iMaxChunkSize = 0)
'output' => $sOutput,
'csvdata' => file_get_contents($sDataFile),
'charset' => $this->GetCharset(),
- 'date_format' => Utils::GetConfigurationValue('date_format', 'Y-m-d')
+ 'date_format' => Utils::GetConfigurationValue('date_format', 'Y-m-d H:i:s')
);
$sLoginform = Utils::GetLoginMode();
@@ -708,6 +708,8 @@ public function Synchronize($iMaxChunkSize = 0)
Utils::Log(LOG_ERR, $sTrimmedOutput);
return false;
+ } else {
+ Utils::Log(LOG_DEBUG, $sTrimmedOutput);
}
}
diff --git a/core/jsoncollector.class.inc.php b/core/jsoncollector.class.inc.php
index c9c472a..c7fabf2 100644
--- a/core/jsoncollector.class.inc.php
+++ b/core/jsoncollector.class.inc.php
@@ -150,7 +150,11 @@ public function Prepare()
Utils::Log(LOG_DEBUG, 'Source sFileJson: '.$this->sFileJson);
Utils::Log(LOG_INFO, 'Synchro URL (target): '.Utils::GetConfigurationValue('itop_url', array()));
} else {
- $this->sFileJson = file_get_contents($this->sFilePath);
+ $this->sFileJson = @file_get_contents($this->sFilePath);
+ if ($this->sFileJson === false) {
+ $this->sFilePath = APPROOT.$this->sFilePath;
+ $this->sFileJson = @file_get_contents($this->sFilePath);
+ }
Utils::Log(LOG_DEBUG, 'Source sFileJson: '.$this->sFileJson);
Utils::Log(LOG_INFO, 'Synchro URL (target): '.Utils::GetConfigurationValue('itop_url', array()));
}
diff --git a/core/orchestrator.class.inc.php b/core/orchestrator.class.inc.php
index 7ea3e2c..7a82860 100644
--- a/core/orchestrator.class.inc.php
+++ b/core/orchestrator.class.inc.php
@@ -17,7 +17,7 @@
class Orchestrator
{
static $aCollectors = array();
- static $aMinVersions = array('PHP' => '5.3.0', 'simplexml' => '0.1', 'dom' => '1.0');
+ static $aMinVersions = array('PHP' => '7.0', 'simplexml' => '7.0', 'dom' => '1');
/**
* Add a collector class to be run in the specified order
@@ -175,7 +175,7 @@ public function InitSynchroDataSources($aCollectors)
Utils::Log(LOG_ERR, "Unable to find the contact with email = '$sEmailToNotify'. No contact to notify will be defined.");
}
}
- $sSynchroUser = Utils::GetConfigurationValue('synchro_user', Utils::GetConfigurationValue('itop_login', ''));
+ $sSynchroUser = Utils::GetConfigurationValue('synchro_user') ?: Utils::GetConfigurationValue('itop_login');
$aPlaceholders['$synchro_user$'] = 0;
if ($sSynchroUser != '') {
$oRestClient = new RestClient();
diff --git a/test/CollectorTest.php b/test/CollectorTest.php
index 67004b5..49a72c2 100644
--- a/test/CollectorTest.php
+++ b/test/CollectorTest.php
@@ -109,15 +109,19 @@ public function testAttributeIsNullified($sCollectorXmlSubSection, $bExpectedIsN
$this->assertEquals($bExpectedIsNullified, $oCollector->AttributeIsNullified('phone'));
- $oCollector->Collect(1);
+ $oCollector->Collect();
$sExpectedCsv = <<;123456;9998877665544;issac.asimov@function.io;writer
+1;isaac;asimov_null;Demo;;123456;9998877665544;issac.asimov@function.io;writer
+2;isaac;asimov_empty;Demo;;123456;9998877665544;issac.asimov@function.io;writer
+3;isaac;asimov_notempty;Demo;"not empty";123456;9998877665544;issac.asimov@function.io;writer
CSV;
@@ -158,12 +162,12 @@ public function testUpdateSDSAttributes($aExpectedAttrDef, $aSynchroAttrDef, boo
$oCollector = new iTopPersonCollector();
$oMockClient = $this->CreateMock('RestClient');
$oMockClient->expects($this->exactly($bWillUpdate ? 1 : 0))->method("Update")->willReturn(['code' => 0]);
-
+
$bRet = $this->InvokeNonPublicMethod(get_class($oCollector), 'UpdateSDSAttributes', $oCollector, [$aExpectedAttrDef, $aSynchroAttrDef, '', $oMockClient]);
-
+
$this->assertTrue($bRet);
}
-
+
public function providerUpdateSDSAttributes()
{
return [
@@ -271,7 +275,7 @@ public function InvokeNonPublicMethod($sObjectClass, $sMethodName, $oObject, $aA
$class = new \ReflectionClass($sObjectClass);
$method = $class->getMethod($sMethodName);
$method->setAccessible(true);
-
+
return $method->invokeArgs($oObject, $aArgs);
}
}
diff --git a/test/JsonCollectorTest.php b/test/JsonCollectorTest.php
index 266bf90..a2ba7d1 100644
--- a/test/JsonCollectorTest.php
+++ b/test/JsonCollectorTest.php
@@ -108,7 +108,7 @@ public function testOrgCollector($sAdditionalDir = '')
$this->assertEquals($sExpected_content, file_get_contents(APPROOT."/data/ITopPersonJsonCollector-1.csv"));
}
- public function OrgCollectorProvider()
+ public static function OrgCollectorProvider()
{
return [
"default_value" => [ "default_value" ],
@@ -119,6 +119,7 @@ public function OrgCollectorProvider()
"sort of object xpath parsing via an index" => [ "format_json_5" ],
"first row nullified function" => [ "nullified_json_1" ],
"another row nullified function" => [ "nullified_json_2" ],
+ "json file with relative path" => [ "json_file_with_relative_path" ],
];
}
@@ -167,7 +168,7 @@ public function testJsonErrors($sAdditionalDir, $sErrorMsg, $sExceptionMsg = fal
}
}
- public function ErrorFileProvider()
+ public static function ErrorFileProvider()
{
return [
"error_json_1" => [
diff --git a/test/collector/attribute_isnullified/iTopPersonCollector.class.inc.php b/test/collector/attribute_isnullified/iTopPersonCollector.class.inc.php
index eb87c65..b12eb91 100644
--- a/test/collector/attribute_isnullified/iTopPersonCollector.class.inc.php
+++ b/test/collector/attribute_isnullified/iTopPersonCollector.class.inc.php
@@ -2,16 +2,18 @@
class iTopPersonCollector extends Collector
{
- private $bFetched;
+ private $i;
+ private $aCurrentData;
- protected function Fetch()
- {
- if (! $this->bFetched) {
- $this->bFetched = true;
- return [
+ public function __construct() {
+ parent::__construct();
+
+ $this->i = 0;
+ $this->aCurrentData = [
+ [
'primary_key' => 1,
'first_name' => "isaac",
- 'name' => "asimov",
+ 'name' => "asimov_null",
'org_id' => "Demo",
'phone' => null,
'mobile_phone' => "123456",
@@ -19,12 +21,41 @@ protected function Fetch()
'email' => "issac.asimov@function.io",
'function' => "writer",
'Status' => "Active",
- ];
- }
+ ],
+ [
+ 'primary_key' => 2,
+ 'first_name' => "isaac",
+ 'name' => "asimov_empty",
+ 'org_id' => "Demo",
+ 'phone' => "",
+ 'mobile_phone' => "123456",
+ 'employee_number' => "9998877665544",
+ 'email' => "issac.asimov@function.io",
+ 'function' => "writer",
+ 'Status' => "Active",
+ ],
+ [
+ 'primary_key' => 3,
+ 'first_name' => "isaac",
+ 'name' => "asimov_notempty",
+ 'org_id' => "Demo",
+ 'phone' => "not empty",
+ 'mobile_phone' => "123456",
+ 'employee_number' => "9998877665544",
+ 'email' => "issac.asimov@function.io",
+ 'function' => "writer",
+ 'Status' => "Active",
+ ],
+ ];
+ }
+ protected function Fetch()
+ {
+ $res = $this->aCurrentData[$this->i] ?? null;
+ $this->i++;
- return null;
+ return $res;
}
-
+
/**
* {@inheritDoc}
* @see Collector::AttributeIsOptional()
diff --git a/test/single_json/json_file_with_relative_path/dataTest.json b/test/single_json/json_file_with_relative_path/dataTest.json
new file mode 100644
index 0000000..07f1a38
--- /dev/null
+++ b/test/single_json/json_file_with_relative_path/dataTest.json
@@ -0,0 +1,38 @@
+{
+ "objects": {
+ "Person::1": {
+ "key": "1",
+ "name": {"bob": "My last name"},
+ "status": "active",
+ "org_id": "Blala",
+ "email": "my.email@foo.org",
+ "phone": "+00 000 000 000",
+ "notify": "yes",
+ "function": "",
+ "first_nameyo": "My first name"
+ },
+ "Person::2": {
+ "key": "2",
+ "name": {"bob": "Picasso"},
+ "status": "active",
+ "org_id": "Demo",
+ "email": "pablo@demo.com",
+ "phone": "",
+ "notify": "yes",
+ "function": "",
+ "first_nameyo": "Pablo"
+ },
+ "Person::3": {
+ "key": "3",
+ "name": {"bob": "Dali"},
+ "status": "active",
+ "email": "dali@demo.com",
+ "phone": "",
+ "notify": "yes",
+ "function": "",
+ "first_nameyo": "Salvador"
+ }
+ },
+ "code": 0,
+ "message": "Found: 1"
+}
\ No newline at end of file
diff --git a/test/single_json/json_file_with_relative_path/expected_generated.csv b/test/single_json/json_file_with_relative_path/expected_generated.csv
new file mode 100644
index 0000000..fdf85aa
--- /dev/null
+++ b/test/single_json/json_file_with_relative_path/expected_generated.csv
@@ -0,0 +1,4 @@
+primary_key;name;status;first_name;email;phone;function;org_id
+1;"My last name";active;"My first name";my.email@foo.org;"+00 000 000 000";;Blala
+2;Picasso;active;Pablo;pablo@demo.com;123456789;;Demo
+3;Dali;active;Salvador;dali@demo.com;123456789;;Demo
diff --git a/test/single_json/json_file_with_relative_path/params.distrib.xml b/test/single_json/json_file_with_relative_path/params.distrib.xml
new file mode 100644
index 0000000..ccdc98c
--- /dev/null
+++ b/test/single_json/json_file_with_relative_path/params.distrib.xml
@@ -0,0 +1,34 @@
+
+
+
+
+ collectors/dataTest.json
+ objects/*
+
+ key
+ name/bob
+ status
+ first_nameyo
+ email
+ phone
+ mobile
+ function
+ employeenumber
+ org_id
+
+
+ Demo
+ active
+ 123456789
+
+
+
+
+ $prefix$
+ synchro_data_person_1
+
+
diff --git a/test/single_json/nullified_json_1/expected_generated.csv b/test/single_json/nullified_json_1/expected_generated.csv
index 3bab6b3..468643d 100644
--- a/test/single_json/nullified_json_1/expected_generated.csv
+++ b/test/single_json/nullified_json_1/expected_generated.csv
@@ -1,4 +1,4 @@
primary_key;name;status;first_name;email;phone;org_id;function
1;"My last name";active;"My first name";my.email@foo.org;"+00 000 000 000";1;
-2;Picasso;active;Pablo;pablo@demo.com;;3;
-3;Dali;active;Salvador;dali@demo.com;;3;
+2;Picasso;active;Pablo;pablo@demo.com;;3;
+3;Dali;active;Salvador;dali@demo.com;;3;