Skip to content
Snippets Groups Projects
smartdatacontext.php 10.4 KiB
Newer Older
<?php

namespace SmartDataContext\Persistence;

use Exception;
use MongoDB\Database;
use MongoDB\Collection;
use SmartDataContext\Domain\SmartDataContext;

class SmartDataContextCrud {
    
    private Database $connection;
    private static array $collections = [];

    function __construct(Database $dbconn) {
        $this->connection = $dbconn;
        SmartDataContextCrud::$collections = [];
    }

    function create($domain, $t0, $t1, $content, $features, $smartDataSources, $smartDataUnits):array {
        if (! array_key_exists('identifier', $features)) {
            $features['identifier'] = $this->build_identifier($content);
        }

        $id = UniqueID::generateID();

        $this->getCollection($domain)->insertOne([
                "id" => $id,
                "t0" => $t0,
                "t1" => $t1,
                "content" => $content,
                "features" => $features,
                "smartDataSources" => $smartDataSources,
                "smartDataUnits" => $smartDataUnits
            ]
        );

        return array("success" => true, "contents" => array("smartDataContextId" => $id));
    }   


    private function getCollection($domain): Collection {
        if (in_array($domain, SmartDataContextCrud::$collections)) {
            return $this->connection->{$domain};
        } else {
            $cols = $this->connection->listCollectionNames(["name" => $domain]);
            $cols->next();
            if (! $cols->valid()) {
                $this->createCollection($domain);
            } else {
                SmartDataContextCrud::$collections[] = $domain;
            }
            return $this->connection->{$domain};
        }
    }

    private function createCollection($domain) {
        $this->connection->createCollection($domain);
        $this->connection->selectCollection($domain)->createIndex(["id" => 1]);
        $this->connection->selectCollection($domain)->createIndex(["features" => 1]);
        $this->connection->selectCollection($domain)->createIndex(["tags" => 1]);
        $this->connection->selectCollection($domain)->createIndex(["smartDataSources" => 1]);
        $this->connection->selectCollection($domain)->createIndex(["smartDataUnits" => 1]);
        $this->connection->selectCollection($domain)->createIndex(["t0" => 1, "t1" => 1, "smartDataUnits" => 1]);
        $this->connection->selectCollection($domain)->createIndex(["t0" => 1, "t1" => 1, "smartDataSources" => 1]);
    }

    private function build_identifier($content) {
        return sha1(json_encode($content));
    }

    public function get($domain, $id):mixed {
        $smartdatacontext = $this->getCollection($domain)->findOne(["id" => $id]);
        if (! isset($smartdatacontext)) {
            return ["success" => false, "errors" => ["not found"]];
        } else {
            return ["success" => true, "contents" => json_decode(json_encode($smartdatacontext), true)];
        }
    }

    public function associate(mixed $domain, mixed $id, mixed $smartDataSources, mixed $smartDataUnits)
    {
        $errors = array_merge(SmartDataContext::ValidateSmartDataSources($smartDataSources),
            SmartDataContext::ValidateSmartDataUnits($smartDataUnits));

        if ($errors) {
            return ["success" => false, "errors" => $errors];
        }

        $smartdatacontext = json_decode(json_encode($this->getCollection($domain)->findOne(["id" => $id])), true);

        if ($smartdatacontext) {
            $smartDataUnitsToAdd = [];
            foreach ($smartDataUnits as $smartDataUnit) {
                if (! in_array($smartDataUnit, $smartdatacontext['smartDataUnits'])) {
                    $smartDataUnitsToAdd[] = $smartDataUnit;
                }
            }

            $smartDataSourcesToAdd = [];
            foreach ($smartDataSources as $smartDataSource) {
                if (! in_array($smartDataSource, $smartdatacontext['smartDataSources'])) {
                    $smartDataSourcesToAdd[] = $smartDataSource;
                }
            }

            $updateData = [
                '$push' => [
                    'smartDataSources' => [
                        '$each' => $smartDataSourcesToAdd
                    ],
                    'smartDataUnits' => [
                        '$each' => $smartDataUnitsToAdd
                    ]
                ]
            ];

            $this->getCollection($domain)->updateOne(["id" => $id], $updateData);
            return ["success" => true, "result" => json_decode(json_encode($this->getCollection($domain)->findOne(["id" => $id])), true)];
        } else {
            return ["success" => false, "errors" => ["smartdatacontext id not found"]];
        }
    }

    public function unassociate(mixed $domain, mixed $id, mixed $smartDataSources, mixed $smartDataUnits)
    {
        $errors = array_merge(SmartDataContext::ValidateSmartDataSources($smartDataSources),
            SmartDataContext::ValidateSmartDataUnits($smartDataUnits));

        if ($errors) {
            return ["success" => false, "errors" => $errors];
        }

        $smartdatacontext = json_decode(json_encode($this->getCollection($domain)->findOne(["id" => $id])), true);

        if ($smartdatacontext) {
            $smartDataUnitsToRemove = [];
            foreach ($smartDataUnits as $smartDataUnit) {
                if (in_array($smartDataUnit, $smartdatacontext['smartDataUnits'])) {
                    $smartDataUnitsToRemove[] = $smartDataUnit;
                }
            }

            $smartDataSourcesToRemove = [];
            foreach ($smartDataSources as $smartDataSource) {
                if (in_array($smartDataSource, $smartdatacontext['smartDataSources'])) {
                    $smartDataSourcesToRemove[] = $smartDataSource;
                }
            }

            if ($smartDataSourcesToRemove && $smartDataUnitsToRemove) {
                $updateData = [
                    '$pull' => [
                        'smartDataSources' => ['$in' => $smartDataSourcesToRemove],
                        'smartDataUnits' => ['$in' => $smartDataUnitsToRemove]
                    ]
                ];
            } else if ($smartDataSourcesToRemove) {
                $updateData = [
                    '$pull' => [
                        'smartDataSources' => ['$in' => $smartDataSourcesToRemove]
                    ]
                ];
            } else if ($smartDataUnitsToRemove) {
                $updateData = [
                    '$pull' => [
                        'smartDataUnits' => ['$in' => $smartDataUnitsToRemove]
                    ]
                ];
            } else {
                return ["success" => true, "result" => json_decode(json_encode($this->getCollection($domain)->findOne(["id" => $id])), true)];
            }

            $this->getCollection($domain)->updateOne(["id" => $id], $updateData);
            return ["success" => true, "result" => json_decode(json_encode($this->getCollection($domain)->findOne(["id" => $id])), true)];
        } else {
            return ["success" => false, "errors" => ["smartdatacontext id not found"]];
        }
    }

    public function query(string $domain, mixed $query)
    {
        try {
            $contentsMongo = $this->getCollection($domain)->find($query);
            $contents = [];
            foreach ($contentsMongo as $contentMongo) {
                $contents[] = json_decode(json_encode($contentMongo), true);
            }
            return ["success" => true, "contents" => $contents];
        } catch (Exception $exception) {
            return ["success" => false, "errors" => [$exception->getMessage()]];
        }
    }

    public function update($domain, $id, array $updateData): array {
        // Find the document in the MongoDB collection using the id field value
        $collection = $this->getCollection($domain);
        $document = $collection->findOne(["id" => $id]);

        // Check if the document exists
        if ($document === null) {
            return ["success" => false, "errors" => ["SmartDataContext with id $id not found"]];
        }

        // Update the document's properties using the associative array received
        $updateFields = [];
        foreach ($updateData as $key => $value) {
            $updateFields[$key] = $value;
        }

        // Prepare the update query
        $updateQuery = ['$set' => $updateFields];

        // Update the document in the MongoDB collection
        try {
            $collection->updateOne(["id" => $id], $updateQuery);
            $updatedDocument = $collection->findOne(["id" => $id]);
            return ["success" => true, "contents" => json_decode(json_encode($updatedDocument), false)];
        } catch (Exception $e) {
            return ["success" => false, "errors" => [$e->getMessage()]];
        }
    }

    public function addUnstructuredData(mixed $domain, mixed $smartdatacontextid, ?string $objectid, $contentype, $filename)
    {
        $smartdatacontext = json_decode(json_encode($this->getCollection($domain)->findOne(["id" => $smartdatacontextid])), true);

        if ($smartdatacontext) {
            $updateData = [
                '$push' => [
                    'unstructuredData' => [
                            "id" => $objectid,
                            "mimetype" => $contentype,
                            "filename" => $filename
                    ]
                ]
            ];

            $this->getCollection($domain)->updateOne(["id" => $smartdatacontextid], $updateData);
            return ["success" => true, "result" => json_decode(json_encode($this->getCollection($domain)->findOne(["id" => $smartdatacontextid])), true)];
        } else {
            return ["success" => false, "errors" => ["smartDataContext id not found"]];
        }
    }


    public function removeUnstructuredData(mixed $domain, mixed $smartdatacontextid, string $objectid)
    {
        $smartdatacontext = json_decode(json_encode($this->getCollection($domain)->findOne(["id" => $smartdatacontextid])), true);

        if ($smartdatacontext) {
            $updateData = [
                '$pull' => [
                    'unstructuredData' => ['id' => $objectid]
                ]
            ];

            $this->getCollection($domain)->updateOne(["id" => $smartdatacontextid], $updateData);
            return ["success" => true, "result" => json_decode(json_encode($this->getCollection($domain)->findOne(["id" => $smartdatacontextid])), true)];
        } else {
            return ["success" => false, "errors" => ["smartDataContext id not found"]];
        }
    }