Skip to content

Commit

Permalink
embedded relations loading, embedded projects loading when the main p…
Browse files Browse the repository at this point in the history
…roject is cached
  • Loading branch information
mind84 committed Feb 1, 2024
1 parent 783f371 commit 7efff39
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 13 deletions.
30 changes: 23 additions & 7 deletions lizmap/modules/lizmap/lib/Project/Project.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,8 @@ public function __construct($key, Repository $rep, App\AppContextInterface $appC
}
}
$rewriteCache = false;
// embedded layers
$embeddedProjects = array();
foreach ($data['qgis']['layers'] as $index => $layer) {
if (array_key_exists('embedded', $layer)
&& $layer['embedded'] == '1'
Expand All @@ -172,16 +174,30 @@ public function __construct($key, Repository $rep, App\AppContextInterface $appC
|| $layer['qgsmtime'] < filemtime($layer['file'])
)
) {
$qgsProj = new QgisProject($layer['file'], $services, $this->appContext);
$newLayer = $qgsProj->getLayerDefinition($layer['id']);
$newLayer['qgsmtime'] = filemtime($layer['file']);
$newLayer['file'] = $layer['file'];
$newLayer['embedded'] = 1;
$newLayer['projectPath'] = $layer['projectPath'];
$data['qgis']['layers'][$index] = $newLayer;
if (!array_key_exists($layer['file'], $embeddedProjects)) {
$embeddedProjects[$layer['file']] = array();
}
// populate array of embedded layers
$embeddedProjects[$layer['file']][$index] = $layer;
$rewriteCache = true;
}
}

// loop through the embedded projects if any, to get the embedded layers definition
foreach ($embeddedProjects as $projectPath => $embeddedLayers) {
if (is_array($embeddedLayers)) {
$embeddedProject = new QgisProject($projectPath, $this->services, $this->appContext);
foreach ($embeddedLayers as $index => $embeddedLayer) {
$newLayer = $embeddedProject->getLayerDefinition($embeddedLayer['id']);
$newLayer['qgsmtime'] = filemtime($embeddedLayer['file']);
$newLayer['file'] = $embeddedLayer['file'];
$newLayer['embedded'] = 1;
$newLayer['projectPath'] = $embeddedLayer['projectPath'];
$data['qgis']['layers'][$index] = $newLayer;
}
}
}

if ($rewriteCache) {
$this->cacheHandler->storeProjectData($data);
}
Expand Down
30 changes: 24 additions & 6 deletions lizmap/modules/lizmap/lib/Project/QgisProject.php
Original file line number Diff line number Diff line change
Expand Up @@ -581,15 +581,28 @@ public function xpathQuery($query)
*
* @deprecated
*
* @param mixed $layerId
* @param mixed $layerId
* @param null|array $embeddedRelationsProjects reference to associative array path(key) - QgisProject instance (value)
*
* @return \SimpleXMLElement[]
*/
public function getXmlLayer($layerId)
public function getXmlLayer($layerId, &$embeddedRelationsProjects = null)
{
$layer = $this->getLayerDefinition($layerId);
if ($layer && array_key_exists('embedded', $layer) && $layer['embedded'] == 1) {
$qgsProj = new QgisProject(realpath(dirname($this->path).DIRECTORY_SEPARATOR.$layer['projectPath']), $this->services, $this->appContext);
// avoid reloading the same qgis project multiple times while reading relations by checking embeddedRelationsProjects param
// If this array is null or does not contains the corresponding qgis project, then the function if forced to load a new qgis project
if ($embeddedRelationsProjects && array_key_exists($layer['projectPath'], $embeddedRelationsProjects)) {
// use QgisProject instance already created
$qgsProj = $embeddedRelationsProjects[$layer['projectPath']];
} else {
// create new QgisProject instance
$qgsProj = new QgisProject(realpath(dirname($this->path).DIRECTORY_SEPARATOR.$layer['projectPath']), $this->services, $this->appContext);
// update the array, if exists
if ($embeddedRelationsProjects) {
$embeddedRelationsProjects[$layer['projectPath']] = $qgsProj;
}
}

return $qgsProj->getXml()->xpath("//maplayer[id='{$layerId}']");
}
Expand Down Expand Up @@ -1336,11 +1349,15 @@ protected function readRelations($xml)
$pivotGather = array();
$pivot = array();
if ($xmlRelations) {
// Store qgisProjects references in a key=>value array and pass it by reference along the methods that loads and validates relations.
// This avoid to reload the same QgisProject instance multiple times, if there are many "embedded relations" referencing the same (embedded) qgis project
$embeddedRelationsProjects = array();

/** @var \SimpleXMLElement $relation */
foreach ($xmlRelations[0] as $relation) {
$relationObj = $relation->attributes();

$relationField = $this->readRelationField($relation);
$relationField = $this->readRelationField($relation, $embeddedRelationsProjects);
if ($relationField === null) {
// no corresponding layer
continue;
Expand Down Expand Up @@ -1384,12 +1401,13 @@ protected function readRelations($xml)

/**
* @param \SimpleXMLElement $relationXml
* @param null|array $embeddedRelationsProjects
*/
protected function readRelationField($relationXml)
protected function readRelationField($relationXml, &$embeddedRelationsProjects = null)
{
$referencedLayerId = $relationXml->attributes()->referencedLayer;

$_referencedLayerXml = $this->getXmlLayer($referencedLayerId);
$_referencedLayerXml = $this->getXmlLayer($referencedLayerId, $embeddedRelationsProjects);
if (count($_referencedLayerXml) == 0) {
return null;
}
Expand Down

0 comments on commit 7efff39

Please sign in to comment.