Skip to content

Commit

Permalink
refactor(bazar): dynamically add extra fields, simplify necessary fields
Browse files Browse the repository at this point in the history
  • Loading branch information
seballot committed Jan 19, 2025
1 parent b4c9fdd commit cdaae17
Show file tree
Hide file tree
Showing 13 changed files with 226 additions and 107 deletions.
27 changes: 26 additions & 1 deletion docs/en/dev.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ In order to optimize the request, dynamic bazalist loads by default only the min
```twig
{% extends "@bazar/entries/index-dynamic.twig" %}
{% set necessary_fields = ['bf_titre', 'bf_description'] %}
{% set necessary_fields = ['bf_description'] %}
{% block display_entries %}
<div v-for="entry in entriesToDisplay">
Expand All @@ -100,6 +100,31 @@ In order to optimize the request, dynamic bazalist loads by default only the min
{% endblock %}
```

| **Default Data Sent** |
| -------------------------------- |
| `id_fiche` |
| `bf_titre` |
| `url` |
| Alls fields needed for searching |
| Alls fields needed for filtering |
| Alls fields needed for sorting |

| **Available Fields** |
| ----------------------------------------------------------------- |
| Alls fields configured in your form. For example `bf_description` |

| **Available Metadata Fields** |
| ----------------------------- |
| `owner` |
| `url` |
| `date_creation_fiche` |
| `date_maj_fiche` |
| `comments` |
| `comments_count` |
| `reactions` |
| `reactions_count` |
| `triples` |

##### Override existing template

Existing yeswiki templates contains block declaration so you can easily override specific parts, for example
Expand Down
8 changes: 8 additions & 0 deletions includes/services/CommentService.php
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,14 @@ public function getCommentList($tag, $first = true, $comments = null)
return $this->wiki->render('@core/comment-list.twig', $com);
}

public function getCommentsCount($tag)
{
return $this->dbService->count("
SELECT * FROM {$this->dbService->prefixTable('pages')}
WHERE comment_on = '{$this->dbService->escape($tag)}' AND latest = 'Y'
");
}

private function setUserData(array $comment, string $key, array &$data)
{
if (in_array($key, ['user', 'owner'], true) && !empty($comment[$key])) {
Expand Down
9 changes: 9 additions & 0 deletions includes/services/ReactionManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,15 @@ public function getReactions($pageTag = '', $ids = [], $user = '', $singleEntry
return $res;
}

public function getReactionsCount($tag)
{
$type = self::TYPE_URI;
return $this->dbService->count("
SELECT * FROM {$this->dbService->prefixTable('triples')}
WHERE resource = '{$this->dbService->escape($tag)}' AND property = '{$type}'
");
}

public function getActionParameters($page, $idReaction = null)
{
if ($this->entryManager->isEntry($page)) {
Expand Down
12 changes: 12 additions & 0 deletions tools/bazar/actions/BazarListeAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use YesWiki\Bazar\Controller\EntryController;
use YesWiki\Bazar\Exception\ParsingMultipleException;
use YesWiki\Bazar\Service\BazarListService;
use YesWiki\Bazar\Service\EntryExtraFieldsService;
use YesWiki\Bazar\Service\EntryManager;
use YesWiki\Core\Controller\AuthController;
use YesWiki\Core\Exception\TemplateNotFound;
Expand Down Expand Up @@ -288,6 +289,17 @@ public function run()
$GLOBALS['_BAZAR_']['nbbazarliste']++;
$this->arguments['nbbazarliste'] = $GLOBALS['_BAZAR_']['nbbazarliste'];

// add extra informations (comments, reactions, metadatas)
$entryFieldsService = $this->getService(EntryExtraFieldsService::class);
if ($this->arguments['extrafields'] === true) {
foreach ($entries as $i => $entry) {
$entryFieldsService->setEntryId($entry['id_fiche']);
foreach (EntryExtraFieldsService::EXTRA_FIELDS as $field) {
$entries[$i][$field] = $entryFieldsService->get($field);
}
}
}

// TODO put in all bazar templates
$this->wiki->AddJavascriptFile('tools/bazar/presentation/javascripts/bazar.js');

Expand Down
92 changes: 55 additions & 37 deletions tools/bazar/controllers/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
use YesWiki\Bazar\Service\BazarListService;
use YesWiki\Bazar\Service\EntryExtraFieldsService;
use YesWiki\Bazar\Service\EntryManager;
use YesWiki\Bazar\Service\FormManager;
use YesWiki\Bazar\Service\SemanticTransformer;
Expand Down Expand Up @@ -235,14 +236,12 @@ public function createSemanticEntry($formId)
public function getBazarListData()
{
$bazarListService = $this->getService(BazarListService::class);

/* ------------------------------------ */
/* Format Params */
/* ------------------------------------ */
$externalIds = $_GET['externalIds'] ?? null;
$externalModeActivated = (is_array($externalIds) && isset($_GET['externalModeActivated'])) ? in_array($_GET['externalModeActivated'], [1, true, '1', 'true'], true) : false;
$forms = $bazarListService->getForms([
'externalModeActivated' => $externalModeActivated,
'externalIds' => $externalIds,
'refresh' => isset($_GET['refresh']) ? in_array($_GET['refresh'], [1, true, '1', 'true'], true) : false,
]);

$formattedGet = array_map(function ($value) {
return ($value === 'true') ? true : (($value === 'false') ? false : $value);
}, $_GET);
Expand All @@ -259,6 +258,17 @@ public function getBazarListData()
$formattedGet['searchfields'] = $searchfields;
$formattedGet['externalModeActivated'] = $externalModeActivated;

/* ------------------------------------ */
/* Get Data */
/* ------------------------------------ */
// All forms
$forms = $bazarListService->getForms([
'externalModeActivated' => $externalModeActivated,
'externalIds' => $externalIds,
'refresh' => isset($_GET['refresh']) ? in_array($_GET['refresh'], [1, true, '1', 'true'], true) : false,
]);

// Entries
$entries = $bazarListService->getEntries(
$formattedGet + [
'user' => null,
Expand All @@ -272,62 +282,70 @@ public function getBazarListData()
],
$forms
);

// Filters
$filters = $bazarListService->getFilters($formattedGet, $entries, $forms);

/* ------------------------------------ */
/* Transform Data */
/* ------------------------------------ */

// Associated Forms
$formIds = array_unique(array_map(function ($entry) {
return $entry['id_typeannonce'];
}, $entries));
$usedForms = array_filter($forms, function ($form) use ($formIds) {
return in_array($form['bn_id_nature'], $formIds);
});
$usedForms = array_map(function ($f) {
return $f['prepared'];
}, $usedForms);

// Basic fields
$fieldList = ['id_fiche', 'bf_titre', 'date_maj_fiche', 'date_creation_fiche'];
$fieldList = ['id_fiche', 'bf_titre', 'url'];
// If no id, we need idtypeannonce (== formId) to filter
if (!isset($_GET['id'])) {
$fieldList[] = 'id_typeannonce';
}
// fields for colo / icon
// fields for color / icon
$fieldList = array_merge($fieldList, [$_GET['colorfield'] ?? null, $_GET['iconfield'] ?? null]);
// Fields for filters
foreach ($filters as $filter) {
$fieldList[] = $filter['propName'];
}
// Fields used to search
foreach ($searchfields as $field) {
$fieldList[] = $field;
}
$fieldList = array_merge($fieldList, $searchfields);
// Fields used to sort
$fieldList = array_merge($fieldList, $_GET['sortfields'] ?? []);
// Fields used by template
foreach ($_GET['displayfields'] ?? [] as $field) {
$fieldList[] = $field;
}
// Fields for external urls
if ($formattedGet['externalModeActivated']) {
$fieldList[] = 'url';
}
$fieldList = array_merge($fieldList, $_GET['displayfields'] ?? []);
// extra fields required by template
$fieldList = array_merge($fieldList, $_GET['necessary_fields'] ?? []);
$fieldList = array_values(array_unique(array_filter($fieldList))); // array_values to have incremental keys
// Fields for filters
foreach ($filters as $filter) {
$fieldList[] = $filter['propName'];
}

// filter blank values, remove duplicates, array_values to have incremental keys
$fieldList = array_values(array_unique(array_filter($fieldList)));

$formIds = array_map(function ($entry) {
return $entry['id_typeannonce'];
}, $entries);
$formIds = array_unique($formIds);
// Reduce the size of the data sent by transforming entries object into array
// we use the $fieldMapping to transform back the data when receiving data in the front end
$entries = array_map(function ($entry) use ($fieldList) {
$entryFieldsService = $this->getService(EntryExtraFieldsService::class);
$entries = array_map(function ($entry) use ($fieldList, $entryFieldsService) {
$entryFieldsService->setEntryId($entry['id_fiche']);
$result = [];
foreach ($fieldList as $field) {
// Format subtitle (why?)
if (!empty($entry[$field]) && !empty($_GET['displayfields']['subtitle']) && $_GET['displayfields']['subtitle'] == $field) {
$entry[$field] = $this->wiki->Format($entry[$field]);
}
// handle specific fields like comments, reactions
if (empty($entry[$field])) {
$entry[$field] = $entryFieldsService->get($field);
}
$result[] = $entry[$field] ?? null;
}
if ($_GET['extrafields'] === "true") {
$result['extrafields'] = $this->getService(EntryManager::class)->getExtraFields($entry['id_fiche']);
}

return $result;
}, $entries);
$usedForms = array_filter($forms, function ($form) use ($formIds) {
return in_array($form['bn_id_nature'], $formIds);
});
$usedForms = array_map(function ($f) {
return $f['prepared'];
}, $usedForms);


return new ApiResponse(
[
Expand Down
11 changes: 2 additions & 9 deletions tools/bazar/services/BazarListService.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public function getForms($options): array
// External mode activated ?
if (($options['externalModeActivated'] ?? false) === true) {
return $this->externalBazarService
->getFormsForBazarListe($options['externalIds'], $options['refresh']);
->getFormsForBazarListe($options['externalIds'], $options['refresh']);
} else {
return $this->formManager->getAll();
}
Expand Down Expand Up @@ -97,7 +97,7 @@ public function getEntries($options, $forms = null): array
} else {
$entries = $this->entryManager->search(
[
"regexp" => $options["regexp"]??"0",
"regexp" => $options["regexp"] ?? "0",
'queries' => $options['query'] ?? '',
'formsIds' => $options['idtypeannonce'] ?? [],
'keywords' => $_REQUEST['q'] ?? '',
Expand All @@ -111,13 +111,6 @@ public function getEntries($options, $forms = null): array
}
$entries = $this->replaceDefaultImage($options, $forms, $entries);

// add extra informations (comments, reactions, metadatas)
if ($options['extrafields'] === true) {
foreach ($entries as $i => $entry) {
$entries[$i]['extrafields'] = $this->entryManager->getExtraFields($entry['id_fiche']);
}
}

// filter entries on datefilter parameter
if (!empty($options['datefilter'])) {
$entries = $this->entryController->filterEntriesOnDate($entries, $options['datefilter']);
Expand Down
84 changes: 84 additions & 0 deletions tools/bazar/services/EntryExtraFieldsService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

namespace YesWiki\Bazar\Service;

use YesWiki\Core\Service\CommentService;
use YesWiki\Core\Service\ReactionManager;
use YesWiki\Core\Service\TripleStore;
use YesWiki\Wiki;

// Get more data about an entry
class EntryExtraFieldsService
{
public const EXTRA_FIELDS = ['comments', 'comments_count', 'reactions', 'reactions_count', 'triples'];

protected $wiki;
protected $entryId;

public function __construct(Wiki $wiki)
{
$this->wiki = $wiki;
}

public function setEntryId($entryId)
{
$this->entryId = $entryId;
}

// get('comments'), get('nb_comments')
public function get($prop)
{
$methodName = 'get' . $this->snakeToPascal($prop);
if (method_exists($this, $methodName)) {
return $this->$methodName();
}
return null;
}

private function snakeToPascal(string $string): string
{
return str_replace(' ', '', ucwords(str_replace('_', ' ', $string)));
}

public function getReactions()
{
return $this->wiki->services->get(ReactionManager::class)->getReactions($this->entryId, [], '', true);
}

public function getReactionsCount()
{
$reactions = $this->wiki->services->get(ReactionManager::class)->getReactions($this->entryId, [], '', true);
// The format of getReactions is not easy to use in a template, so we transform it
// bf_my_reaction: { like: { label: "I like", icon: "..", count: 5 }, dislike: { ... } }
$result = [];
foreach ($reactions as $field => $data) {
$fieldResult = [];
foreach ($data["parameters"]["labels"] as $reactionId => $label) {
$fieldResult[$reactionId] = ["label" => $label, "image" => null, "count" => 0];
}
foreach ($data["parameters"]["images"] as $reactionId => $image) {
$fieldResult[$reactionId]["image"] = $image;
}
foreach ($data["nb_reactions"] as $reactionId => $count) {
$fieldResult[$reactionId]["count"] = $count;
}
$result[$field] = $fieldResult;
}
return $result;
}

public function getComments()
{
return $this->wiki->services->get(CommentService::class)->loadCommentsRecursive($this->entryId);
}

public function getCommentsCount()
{
return $this->wiki->services->get(CommentService::class)->getCommentsCount($this->entryId);
}

public function getTriples()
{
return $this->wiki->services->get(TripleStore::class)->getMatching($this->entryId, null, null, '=');
}
}
Loading

0 comments on commit cdaae17

Please sign in to comment.