Skip to content
Snippets Groups Projects
Commit 34124e77 authored by Rodrigo Goncalves's avatar Rodrigo Goncalves Committed by Guilherme Arthur Gerônimo
Browse files

Data Ingress development. TikiWiki import and conversion to conceptual model...

Data Ingress development. TikiWiki import and conversion to conceptual model concluded. Pending insert and update SmartDataContext
parent d0f3bd9b
No related branches found
No related tags found
1 merge request!20Resolve "Data ingress for context information for tiki-wiki"
/run_env.sh
/vendor
\ No newline at end of file
<?php
namespace Ingress\Command;
use Console_CommandLine;
use Console_CommandLine_Command;
use Ingress\Services\CommandRegister;
class BaseCommand
{
protected static function addCommand(Console_CommandLine $commandLine, string $commandName, string $commandDescription, string $callback) {
$cmd = $commandLine->addCommand($commandName, [
'description' => $commandDescription
]);
CommandRegister::$commandMap[$commandName] = $callback;
return $cmd;
}
protected static function addArgument(Console_CommandLine_Command $command, $argumentName, $argumentDescription) {
$command->addArgument($argumentName, ["description" => $argumentDescription]);
return $command;
}
protected static function addOption(Console_CommandLine_Command $command, $optionName, $optionDescription) {
$command->addArgument($optionName, ["description" => $optionDescription]);
return $command;
}
}
\ No newline at end of file
<?php
namespace Ingress\Command\TikiWiki;
use Console_CommandLine;
use Ingress\Command\BaseCommand;
use Ingress\Services\Logger;
use Ingress\Services\tikiwiki\TikiWIkiConfig;
use Ingress\Services\tikiwiki\TikiWikiDB;
class ImportCommand extends BaseCommand
{
private const MAINTENANCE_REPORT_TRACKER_MAP = [
'rpmServiceNumber' => 'maintenanceServiceNumber',
'rpmPersonResponsible' => 'maintenanceResponsiblePerson',
'rpmMileage' => ['vehicleMileage', 'static::convertKM'],
'rpmOperationalStatus' => ['vehicleOperationalStatus', 'static::convertOperationalStatus'],
'rpmMotivation' => ['maintenanceMotivation', 'static::convertMotivation'],
'rpmWarrantyStatus' => ['vehicleWarrantyStatus', 'static::convertWarrantyStatus'],
'rpmOwner' => ['currentOwnwerCount', 'static::convertOwnerCount'],
'rpmDateOfLastService' => ['lastServiceData', 'static::convertDate'],
'rpmNextScheduledService' => ['nextScheduledService', 'static::convertDate'],
'rpmAverageKmLInTheLastYear' => ['averageKMPerLiter', 'static::convertKMLiter'],
'rpmMajorRepairs' => 'majorRepairsReport',
'rpmPartsReplaced' => 'partsReplacedReport',
'rpmServicesAndFinishes' => 'servicesAndFinishesReport',
];
private static function convertKM($value) {
// TODO implement conversion to SI
return ["value" => $value];
}
private static function convertOwnerCount($value) {
return preg_replace('/\D/', '', $value);
}
private static function convertDate($value) {
// TODO implement conversion to SI
return ["value" => $value];
}
private static function convertKMLiter($value) {
// TODO implement conversion to SI
return ["value" => $value];
}
private const OPERATIONAL_STATUS_MAP = [
'no apparent issues' => 'NO_APPARENT_ISSUES',
'maintenance required (please specify)' => 'MAINTENANCE_REQUIRED'
];
private const MAINTENANCE_MOTIVATION_MAP = [
'Periodic review' => 'PERIODIC_REVIEW',
'Specific failure' => 'SPECIFIC_FAILURE',
'Major failure' => 'MAJOR_FAILURE',
'Vehicle unavailability' => 'VEHICLE_UNAVAILABILITY'
];
private const WARRANTY_STATUS_MAP = [
'Under warranty' => 'UNDER_WARRANTY',
'Extended warranty' => 'EXTENDED_WARRANTY',
'Out of warranty' => 'OUT_OF_WARRANTY'
];
private static function convertValueMap($value, $map) {
if (array_key_exists($value, $map)) {
return $map[$value];
} else {
return null;
}
}
private static function convertOperationalStatus($value) {
return static::convertValueMap($value, static::OPERATIONAL_STATUS_MAP);
}
private static function convertMotivation($value) {
return static::convertValueMap($value, static::MAINTENANCE_MOTIVATION_MAP);
}
private static function convertWarrantyStatus($value) {
return static::convertValueMap($value, static::WARRANTY_STATUS_MAP);
}
private const MAINTENANCE_PLAN_TRACKER_FREQUENCY_MAP = [
'vehiclemaintenancereportInspectionOfInje_tricMotor' => 'ENGINE_INSPECTION',
'vehiclemaintenancereportSuspensionCheck' => 'SUSPENSION_CHECK',
'vehiclemaintenancereportTransmissionFluidChange' => 'TRANSMISSION_FLUID_CHANGE',
'vehiclemaintenancereportTimingBeltReplacement' => 'BELT_REPLACEMENT',
'vehiclemaintenancereportSparkPlugReplacement' => 'SPARK_PLUG_REPLACEMENT',
'vehiclemaintenancereportFrequencyForTireRotation' => 'TIRE_ROTATION',
'vehiclemaintenancereportFrequencyForBrak_nspection' => 'BREAK_INSPECTION',
'vehiclemaintenancereportFrequencyForFluidCheck' => 'FLUID_CHECK',
'vehiclemaintenancereportFrequencyForComp_nspection' => 'COMPLETE_VEHICLE_INSPECTION',
'vehiclemaintenancereportFrequencyForEmissionsTest' => 'EMISSIONS_TEST',
'vehiclemaintenancereportBatteryTest' => 'BATTERY_TEST',
'vehiclemaintenancereportFrequencyForOilA_terChange' => 'OIL_FILTER_CHANGE'
];
private const MAINTENANCE_REPORT_SERVICE_MAP = [
'rpmInspectionOfInjectionCombustionSystem_tricMotor' => 'ENGINE_INSPECTION',
'rpmSuspensionCheck' => 'SUSPENSION_CHECK',
'rpmTransmissionFluidChange' => 'TRANSMISSION_FLUID_CHANGE',
'rpmBeltReplacement' => 'BELT_REPLACEMENT',
'rpmSparkPlugReplacement' => 'SPARK_PLUG_REPLACEMENT',
'rpmTireRotation' => 'TIRE_ROTATION',
'rpmBrakeInspection' => 'BREAK_INSPECTION',
'rpmFluidCheck' => 'FLUID_CHECK',
'rpmEmissionsTest' => 'EMISSIONS_TEST',
'rpmBatteryTest' => 'BATTERY_TEST',
'rpmOilAndFilterChange' => 'OIL_FILTER_CHANGE'
];
private const VEHICLE_TRACKER_MAP = [
'vlVehicleModel' => 'signature',
'vlYear' => 'year',
'vlVehicleBrand' => 'model',
'vlSignature' => 'signature',
];
private const MAINTENANCE_REPORT_ERROR_CODE_MAP = [
'ffmProblem' => 'problemDescription',
'ffmDTCCode' => 'dtcCode'
];
private const USAGE_PATTERN_MAP = [
'personal vehicle' => 'PERSONAL_VEHICLE',
'fleet' => 'FLEET',
'service' => 'SERVICE'
];
public static function process(array $args, array $params) {
$domain = $args['domain'];
$db = new TikiWikiDB();
$trackerList = TikiWikiConfig::getTrackers($domain);
$vehicleMap = static::importVehicles($domain, $db, $trackerList['vehicleList']);
static::importMaintenancePlans($domain, $db, $trackerList['vehicleMaintenancePlan'], $vehicleMap);
$maintenanceReports = static::importMaintenanceReports($domain, $db, $trackerList['vehicleMaintenanceReport'], $vehicleMap);
$maintenanceReports = static::importMaintenanceReportsErrorCodes($domain, $db, $trackerList['vehicleMaintenanceReportErrorCodes'], $maintenanceReports);
}
private static function importMaintenanceReportsErrorCodes(string $domain, TikiWikiDB $db, string $trackerName, array $maintenanceReportsMap)
{
$maintenanceReportsErrorCodes = static::findTrackerItems($db, $trackerName);
foreach ($maintenanceReportsErrorCodes as $maintenanceReportsErrorCode) {
$maintenanceReportsMap = self::importMaintenanceReportsErrorCode($maintenanceReportsMap, $maintenanceReportsErrorCode);
}
Logger::log($maintenanceReportsMap);
return $maintenanceReportsMap;
}
private static function importMaintenanceReportsErrorCode(array $maintenanceReportsMap, mixed $maintenanceReportsErrorCodeData)
{
$maintenanceReportsErrorCode = static::buildJson(static::MAINTENANCE_REPORT_ERROR_CODE_MAP, $maintenanceReportsErrorCodeData);
$maintenanceReportId = $maintenanceReportsErrorCodeData['ffmVehicleMaintenanceReport']['fieldValue'];
if (array_key_exists($maintenanceReportId, $maintenanceReportsMap)) {
$maintenanceReportsMap[$maintenanceReportId]['vehicleFailures'][] = $maintenanceReportsErrorCode;
}
return $maintenanceReportsMap;
}
private static function importMaintenanceReports(string $domain, TikiWikiDB $db, string $trackerName, array $vehicleMap) {
$maintenanceReportsData = static::findTrackerItems($db, $trackerName);
$maintenanceReports = [];
foreach ($maintenanceReportsData as $maintenanceReportDatum) {
$maintenanceReports[$maintenanceReportDatum['tikiwikiid']] = static::importMaintenanceReport($maintenanceReportDatum, $vehicleMap);
}
return $maintenanceReports;
}
private static function importMaintenanceReport(array $maintenanceReportDatum, array $vehicleMap) {
$maintenanceReport = static::buildJson(static::MAINTENANCE_REPORT_TRACKER_MAP, $maintenanceReportDatum);
$maintenanceReport["vehicle"] = $vehicleMap[$maintenanceReportDatum['rpmVehicle']['fieldValue']];
foreach ($maintenanceReportDatum as $fieldName => $field) {
if (array_key_exists($fieldName, static::MAINTENANCE_REPORT_SERVICE_MAP)) {
if ($field['fieldValue'] == 'y') {
$maintenanceReport['executedServices'][] = static::MAINTENANCE_REPORT_SERVICE_MAP[$fieldName];
}
}
}
return $maintenanceReport;
}
private static function importMaintenancePlans(string $domain, TikiWikiDB $db, string $trackerName, array $vehicleMap) {
$maintenancePlansData = static::findTrackerItems($db, $trackerName);
$maintenancePlans = [];
foreach ($maintenancePlansData as $maintenancePlansDatum) {
$maintenancePlan = ["vehicle" => $vehicleMap[$maintenancePlansDatum['vehiclemaintenancereportVehicle']['fieldValue']]];
foreach ($maintenancePlansDatum as $fieldName => $field) {
if (array_key_exists($fieldName, static::MAINTENANCE_PLAN_TRACKER_FREQUENCY_MAP)) {
$maintenancePlan['servicesFrequencies'][] = static::convertServiceFrequency(static::MAINTENANCE_PLAN_TRACKER_FREQUENCY_MAP[$fieldName], $field['fieldValue']);
}
}
$maintenancePlans[] = $maintenancePlan;
}
Logger::log($maintenancePlans);
return $maintenancePlans;
}
private static function convertServiceFrequency($key, $value)
{
// TODO calculate frequency
return ["kind" => $key, 'internal' => ['value' => $value]];
}
private static function importVehicles(string $domain, TikiWikiDB $db, string $trackerName) {
$vehicles = static::findTrackerItems($db, $trackerName);
$result = [];
foreach ($vehicles as $vehicle) {
$result[$vehicle['tikiwikiid']] = static::importVehicle($vehicle);
}
Logger::log($result);
return $result;
}
private static function importVehicle($vehicleTrackerData) {
$vehicle = static::buildJson(static::VEHICLE_TRACKER_MAP, $vehicleTrackerData);
$vehicle['usagePatterns'] = static::convertUsagePatern($vehicleTrackerData['vlUsagePatterns']['fieldValue']);
return $vehicle;
}
private static function convertUsagePatern($patterns) {
$patternList = [];
foreach (preg_split('/,/', $patterns) as $pattern) {
$pattern = trim($pattern);
if (array_key_exists($pattern, static::USAGE_PATTERN_MAP)) {
$patternList[] = static::USAGE_PATTERN_MAP[$pattern];
}
}
return $patternList;
}
private static function findTrackerItems(TikiWikiDB $db, string $trackerName) {
$trackerData = $db->getTrackerData($trackerName);
return static::_extractItems($trackerData);
}
private static function buildJson(array $mapping, array $row): array
{
$result = [];
foreach ($mapping as $fieldName => $parameters) {
if (is_array($parameters)) {
$jsonPath = $parameters[0];
$convFunc = $parameters[1];
} else {
$jsonPath = $parameters;
}
if (!isset($row[$fieldName])) {
continue; // Skip if the field is not in the row
}
$value = $row[$fieldName];
$keys = explode('.', $jsonPath);
$current = &$result;
foreach ($keys as $key) {
if (!isset($current[$key])) {
$current[$key] = [];
}
$current = &$current[$key];
}
$current = isset($convFunc) ? call_user_func($convFunc, $value['fieldValue']): $value['fieldValue'];
}
return $result;
}
private static function _extractItems(array $rows): array
{
$result = [];
foreach ($rows as $row) {
$itemId = $row['item_id'];
$fieldName = $row['fieldName'];
if (!isset($result[$itemId])) {
$result[$itemId] = ['tikiwikiid' => $itemId];
}
$result[$itemId][$fieldName] = [
'fieldValue' => $row['fieldValue'],
'attachment_name' => $row['attachment_name'],
'attachment_size' => $row['attachment_size'],
'attachment_type' => $row['attachment_type'],
'attachment_data' => $row['attachment_data']
];
}
return $result;
}
public static function register(Console_CommandLine $commandLine, array $commandMap)
{
$cmd = BaseCommand::addCommand($commandLine, 'tikiwiki-import', 'Imports tracker data from a domain to SmartDataContext entities',
'Ingress\Command\TikiWiki\ImportCommand::process'
);
BaseCommand::addArgument($cmd, 'domain', 'Define the domain to import the data');
}
}
\ No newline at end of file
<?php
namespace Ingress\Services;
use Console_CommandLine;
use Console_CommandLine_Result;
class CommandRegister
{
/**
* @var array|mixed
*/
public static array $commandMap = [];
public static function registerCommand(string $class, Console_CommandLine $parser): void
{
call_user_func("Ingress\\Command\\$class::register", $parser, CommandRegister::$commandMap);
}
public static function process(Console_CommandLine_Result $parseResult)
{
call_user_func(CommandRegister::$commandMap[$parseResult->command_name], $parseResult->command->args, $parseResult->command->options);
}
}
<?php
namespace Ingress\Services;
class Logger
{
public static function log($message) {
if (is_array($message)) {
$message = json_encode($message, JSON_PRETTY_PRINT);
}
print("$message\n");
}
}
\ No newline at end of file
<?php
namespace Ingress\Services\tikiwiki;
class TikiWIkiConfig
{
private const CONFIG_PATH='./config/tikiwiki.json';
public static function getTrackers(string $domain) {
if (!file_exists(TikiWIkiConfig::CONFIG_PATH)) {
die("File not found: " . TikiWIkiConfig::CONFIG_PATH);
}
// Read the contents of the JSON file
$jsonContent = file_get_contents(TikiWIkiConfig::CONFIG_PATH);
if ($jsonContent === false) {
die("Error reading file: " . TikiWIkiConfig::CONFIG_PATH);
}
// Decode the JSON data into a PHP array
$dataArray = json_decode($jsonContent, true);
if (json_last_error() !== JSON_ERROR_NONE) {
die("Error decoding JSON: " . json_last_error_msg());
}
if (! array_key_exists('domains', $dataArray) || ! array_key_exists($domain, $dataArray['domains'])) {
die("Missing domain configuration: " . json_last_error_msg());
}
return $dataArray['domains'][$domain]['trackers'];
}
}
\ No newline at end of file
<?php
namespace Ingress\Services\tikiwiki;
use Exception;
use Ingress\Services\Logger;
use mysqli;
class TikiWikiDB
{
private const SQL_TRACKER_VALUES = <<<EOD
select * from (
select a.* from (
select tt.name tracker_name, tti.itemId item_id, tti.lastModif last_modified, ttf.permName fieldName, ttif.value fieldValue, null as attachment_name, null as attachment_size, null as attachment_type, null as attachment_data
from tiki_tracker_item_fields ttif
inner join tiki_tracker_fields ttf on (ttf.fieldId=ttif.fieldId)
inner join tiki_tracker_items tti on (tti.itemId=ttif.itemId)
inner join tiki_trackers tt on (tt.trackerId=ttf.trackerId)
where ttf.`type` <> 'FG'
UNION
select tt.name tracker_name, tti.itemId item_id, tti.lastModif last_modified, ttf.permName fieldName, ttif.value fieldValue, tf.filename attachment_name, tf.filesize attachment_size, tf.filetype attachment_type, tf.`data` attachment_data
from tiki_tracker_item_fields ttif
inner join tiki_tracker_fields ttf on (ttf.fieldId=ttif.fieldId)
inner join tiki_tracker_items tti on (tti.itemId=ttif.itemId)
inner join tiki_trackers tt on (tt.trackerId=ttf.trackerId)
left outer join tiki_tracker_item_attachments ttia on (ttia.itemId=ttif.itemId)
left outer join tiki_files tf on (ttf.`type`='FG' and tf.fileId=ttif.value)
where ttf.`type` = 'FG' ) as a
order by
a.tracker_name, a.item_id
) as b where b.tracker_name=?
EOD;
private $conn;
public function __construct()
{
$this->conn = $this->getConnection();
}
function getConnection(): mysqli
{
$host = getenv('TIKIWIKIDB_HOST') ?: '127.0.0.1';
$port = getenv('TIKIWIKIDB_PORT') ?: '3306';
$database = getenv('TIKIWIDB_DATABASE') ?: 'tikiwiki';
$username = getenv('TIKIWIKDB_USERNAME') ?: 'tikiwiki';
$password = getenv('TIKIWIKIDB_PASSWORD') ?: 'tikiwiki';
Logger::log("Connecting to TikiDB at $host:$port with database $database and user $username");
// Create a new mysqli instance
$mysqli = new mysqli($host, $username, $password, $database, $port);
// Check for connection errors
if ($mysqli->connect_error) {
die("Connection failed: " . $mysqli->connect_error);
}
return $mysqli;
}
function getTrackerData(string $trackerName) {
return $this->_executeQuery(TikiWikiDB::SQL_TRACKER_VALUES, $trackerName);
}
function _executeQuery(string $query, ...$params): array
{
// Prepare the statement
$stmt = $this->conn->prepare($query);
if ($stmt === false) {
throw new Exception("Query preparation failed: " . $this->conn->error);
}
// Bind parameters if there are any
if (!empty($params)) {
// Create a types string based on the types of the passed parameters
$types = '';
foreach ($params as $param) {
if (is_int($param)) {
$types .= 'i'; // Integer
} elseif (is_float($param)) {
$types .= 'd'; // Double
} elseif (is_string($param)) {
$types .= 's'; // String
} else {
$types .= 'b'; // Blob or other types
}
}
// Bind the parameters to the statement
$stmt->bind_param($types, ...$params);
}
// Execute the statement
if (!$stmt->execute()) {
throw new Exception("Query execution failed: " . $this->conn->error);
}
// Get the result set
$result = $stmt->get_result();
if ($result === false) {
throw new Exception("Getting result set failed: " . $this->conn->error);
}
// Fetch all rows as an associative array
$rows = $result->fetch_all(MYSQLI_ASSOC);
// Close the statement
$stmt->close();
return $rows;
}
}
\ No newline at end of file
{
"require": {
"pear/console_commandline": "^1.2",
"ext-mysqli": "*"
},
"autoload": {
"classmap": ["app/"]
}
}
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "791fb8a349f8118ae3945e43dcfdfe16",
"packages": [
{
"name": "pear/console_commandline",
"version": "v1.2.6",
"source": {
"type": "git",
"url": "https://github.com/pear/Console_CommandLine.git",
"reference": "611c5bff2e47ec5a184748cb5fedc2869098ff28"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pear/Console_CommandLine/zipball/611c5bff2e47ec5a184748cb5fedc2869098ff28",
"reference": "611c5bff2e47ec5a184748cb5fedc2869098ff28",
"shasum": ""
},
"require": {
"ext-dom": "*",
"ext-xml": "*",
"pear/pear_exception": "^1.0.0",
"php": ">=5.3.0"
},
"require-dev": {
"phpunit/phpunit": "*"
},
"type": "library",
"autoload": {
"psr-0": {
"Console": "./"
},
"exclude-from-classmap": [
"tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"include-path": [
""
],
"license": [
"MIT"
],
"authors": [
{
"name": "Richard Quadling",
"email": "rquadling@gmail.com"
},
{
"name": "David Jean Louis",
"email": "izimobil@gmail.com"
}
],
"description": "A full featured command line options and arguments parser.",
"homepage": "https://github.com/pear/Console_CommandLine",
"keywords": [
"console"
],
"support": {
"issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=Console_CommandLine",
"source": "https://github.com/pear/Console_CommandLine"
},
"time": "2023-04-02T18:49:53+00:00"
},
{
"name": "pear/pear_exception",
"version": "v1.0.2",
"source": {
"type": "git",
"url": "https://github.com/pear/PEAR_Exception.git",
"reference": "b14fbe2ddb0b9f94f5b24cf08783d599f776fff0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pear/PEAR_Exception/zipball/b14fbe2ddb0b9f94f5b24cf08783d599f776fff0",
"reference": "b14fbe2ddb0b9f94f5b24cf08783d599f776fff0",
"shasum": ""
},
"require": {
"php": ">=5.2.0"
},
"require-dev": {
"phpunit/phpunit": "<9"
},
"type": "class",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"classmap": [
"PEAR/"
]
},
"notification-url": "https://packagist.org/downloads/",
"include-path": [
"."
],
"license": [
"BSD-2-Clause"
],
"authors": [
{
"name": "Helgi Thormar",
"email": "dufuz@php.net"
},
{
"name": "Greg Beaver",
"email": "cellog@php.net"
}
],
"description": "The PEAR Exception base class.",
"homepage": "https://github.com/pear/PEAR_Exception",
"keywords": [
"exception"
],
"support": {
"issues": "http://pear.php.net/bugs/search.php?cmd=display&package_name[]=PEAR_Exception",
"source": "https://github.com/pear/PEAR_Exception"
},
"time": "2021-03-21T15:43:46+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.2.0"
}
{
"domains": {
"teste" : {
"trackers": {
"vehicleList": "Vehicle List",
"vehicleMaintenancePlan": "Vehicle Maintenance Plan",
"vehicleMaintenanceReport": "Vehicle Maintenance Report",
"vehicleMaintenanceReportErrorCodes": "Vehicle Failure"
}
}
}
}
\ No newline at end of file
<?php
namespace Ingress;
require __DIR__ . '/vendor/autoload.php';
use Console_CommandLine;
use Console_CommandLine_Exception;
use Ingress\Services\CommandRegister;
$parser = new Console_CommandLine();
$parser->description = 'AutoDL data ingress tool.';
$parser->version = '0.1.0';
# Register available commands
CommandRegister::registerCommand("TikiWiki\ImportCommand", $parser);
# Process command line
try {
CommandRegister::process($parser->parse());
} catch (Console_CommandLine_Exception $e) {
$parser->displayError($e->getMessage());
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment