Compare commits

...

15 commits

Author SHA1 Message Date
Markus Klein 9eb9d3c7ec [TASK] Make SkillSet API a public service 2023-07-07 13:05:31 +02:00
Markus Klein f37a57e46e [FEATURE] Add value picker for skill set selection in content element 2023-07-07 12:55:18 +02:00
Weissheiten Wien 41beb0310a
Merge pull request #16 from SkillDisplay/Weissheiten-patch-1
Update README.rst
2023-07-07 12:24:55 +02:00
Weissheiten Wien 48142a8786
Update README.rst 2023-07-07 12:24:13 +02:00
Julian Zangl e2b7c980e5
Merge pull request #15 from SkillDisplay/skill-grouping-vh
Skill grouping vh
2023-07-07 12:23:06 +02:00
Markus Klein 15ddcb4158 [FEATURE] Add optional caching for skill set data retrieval 2023-07-07 12:19:02 +02:00
julianzangl 0f0b7e3145 [BUGFIX] formatting issues 2023-07-07 12:16:23 +02:00
julianzangl eb432ddf94 [BUGFIX] changed return types of initializeArguments functions 2023-07-07 12:12:53 +02:00
Weissheiten Wien 80dcd33175
Update README.rst
Update readme to match new functionalities
2023-07-07 12:11:34 +02:00
julianzangl 9076aa0067 [BUGFIX] if condition is always true 2023-07-07 12:08:28 +02:00
julianzangl 60931303c0 [TASK] added ViewHelper for grouping skills by their domainTag 2023-07-07 12:02:21 +02:00
Markus Klein ffde64c04b [TASK] Use types from SD PHP API 2023-07-07 09:43:28 +02:00
Markus Klein 901b7ab2be [FEATURE] VH to group skills by domain 2023-07-07 09:28:43 +02:00
Markus Klein 08a1830e75 [TASK] Fetch more details for skills in sets 2023-07-07 09:04:58 +02:00
Markus Klein 573e1baedd [BUGFIX] Allow multi-value skillset selection 2023-07-07 09:04:40 +02:00
13 changed files with 273 additions and 29 deletions

View file

@ -0,0 +1,55 @@
<?php
declare(strict_types=1);
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
namespace SkillDisplay\SkilldisplayContent\FormDataProvider;
use SkillDisplay\PHPToolKit\Api\SkillSet;
use TYPO3\CMS\Backend\Form\FormDataProviderInterface;
/**
* Inject available skill sets a valuepicker form
*/
class ValuePickerItemDataProvider implements FormDataProviderInterface
{
private SkillSet $skillSetApi;
public function __construct(SkillSet $skillSetApi)
{
$this->skillSetApi = $skillSetApi;
}
/**
* Add sys_domains into $result data array
*
* @param array $result Initialized result array
* @return array Result filled with more data
*/
public function addData(array $result): array
{
if ($result['tableName'] === 'tt_content' && isset($result['processedTca']['columns']['skilldisplay_skillset'])) {
$skillSets = $this->skillSetApi->getAll();
foreach ($skillSets as $skillSet) {
$result['processedTca']['columns']['skilldisplay_skillset']['config']['valuePicker']['items'][] =
[
$skillSet->getName(),
$skillSet->getId(),
];
}
}
return $result;
}
}

View file

@ -25,6 +25,8 @@ namespace SkillDisplay\SkilldisplayContent\Frontend\DataProcessing;
use Exception;
use SkillDisplay\PHPToolKit\Api\SkillSet;
use TYPO3\CMS\Core\Cache\CacheManager;
use TYPO3\CMS\Core\Cache\Frontend\VariableFrontend;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer;
use TYPO3\CMS\Frontend\ContentObject\DataProcessorInterface;
@ -45,23 +47,43 @@ class SkillSets implements DataProcessorInterface
array $processorConfiguration,
array $processedData
) {
$as = $cObj->stdWrapValue('as', $processorConfiguration, 'skillSets');
$skillSetsIdsRaw = (string)$cObj->stdWrapValue('skillSets', $processorConfiguration);
$skillSetIds = GeneralUtility::intExplode(
',',
(string)$cObj->stdWrapValue('skillSets', $processorConfiguration),
$skillSetsIdsRaw,
true
);
$skillSets = [];
$enableCache = $processorConfiguration['cache'] ?? false;
if ($enableCache) {
$cacheKey = md5($skillSetsIdsRaw) . $as;
/** @var VariableFrontend $cache */
$cache = GeneralUtility::makeInstance(CacheManager::class)->getCache('sdcontent');
if ($cache->has($cacheKey)) {
$data = $cache->get($cacheKey);
} else {
$data = $this->generateData($skillSetIds);
$cache->set($cacheKey, $data);
}
} else {
$data = $this->generateData($skillSetIds);
}
$processedData[$as] = $data;
return $processedData;
}
protected function generateData(array $skillSetIds): array
{
$skillSets = [];
foreach ($skillSetIds as $skillSetId) {
try {
$skillSets[] = $this->skillSetApi->getById($skillSetId);
$skillSets[] = $this->skillSetApi->getById($skillSetId, true);
} catch (Exception $e) {
continue;
}
}
$processedData[$as] = $skillSets;
return $processedData;
return $skillSets;
}
}

View file

@ -0,0 +1,107 @@
<?php
declare(strict_types=1);
namespace SkillDisplay\SkilldisplayContent\ViewHelpers;
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
use Closure;
use SkillDisplay\PHPToolKit\Entity\Skill;
use SkillDisplay\PHPToolKit\Entity\SkillSet;
use TYPO3Fluid\Fluid\Core\Rendering\RenderingContextInterface;
use TYPO3Fluid\Fluid\Core\ViewHelper\AbstractViewHelper;
use TYPO3Fluid\Fluid\Core\ViewHelper\Traits\CompileWithRenderStatic;
/**
* Usage:
*
* <sd:skillGrouping skillSet="{skillSet}" as="domainGroup">
* {domainGroup.title}<br />
* <f:for each="{domainGroup.skills}" as="skill">
* {skill.name}<br />
* </f:for>
* </sd:skillGrouping>
*/
class SkillGroupingViewHelper extends AbstractViewHelper
{
use CompileWithRenderStatic;
protected $escapeOutput = false;
public function initializeArguments(): void
{
$this->registerArgument('skills', 'array', 'An array of skills to group', false, []);
$this->registerArgument('skillSet', SkillSet::class, 'The skills of this skill set will be grouped');
$this->registerArgument('as', 'string', 'The name of the iteration variable', true);
}
public static function renderStatic(
array $arguments,
Closure $renderChildrenClosure,
RenderingContextInterface $renderingContext
) {
/** @var Skill[] $skills */
$skills = $arguments['skills'];
/** @var SkillSet|null $skillSet */
$skillSet = $arguments['skillSet'];
$as = $arguments['as'];
if ($skillSet) {
$groups = self::group($skillSet->getSkills());
} else {
$groups = self::group($skills);
}
$templateVariableContainer = $renderingContext->getVariableProvider();
$output = '';
foreach ($groups as $group) {
$templateVariableContainer->add($as, $group);
$output .= $renderChildrenClosure();
$templateVariableContainer->remove($as);
}
return $output;
}
/**
* @param Skill[] $skills
* @return array
*/
protected static function group(array $skills): array
{
$domainTags = [];
foreach ($skills as $skill) {
$domainTags[] = isset($skill->toArray()['domainTag']) ? $skill->toArray()['domainTag']['title'] : "none";
}
$domainTags = array_unique($domainTags);
$result = [];
foreach ($domainTags as $domainTag) {
$result[] = [
'title' => $domainTag,
'skills' => array_filter($skills, function (Skill $skill) use ($domainTag) {
if (!isset($skill->toArray()['domainTag'])) {
return $domainTag === "none";
}
return $skill->toArray()['domainTag']['title'] === $domainTag;
})
];
}
return $result;
}
}

View file

@ -36,7 +36,7 @@ abstract class VerificationViewHelper extends AbstractViewHelper
protected $escapeOutput = false;
public function initializeArguments()
public function initializeArguments(): void
{
$this->registerArgument('skill', 'integer', 'ID of the Skill.');
$this->registerArgument('skillSet', 'integer', 'ID of the SkillSet.');

View file

@ -21,10 +21,12 @@ services:
alias: '@skilldisplay.settings'
SkillDisplay\PHPToolKit\Api\Skill:
public: true
arguments:
$settings: '@skilldisplay.settings'
SkillDisplay\PHPToolKit\Api\SkillSet:
public: true
arguments:
$settings: '@skilldisplay.settings'

View file

@ -30,6 +30,11 @@
'type' => 'input',
'eval' => 'required',
'size' => 10,
'valuePicker' => [
'mode' => 'append',
// filled by ValuePickerItemDataProvider
'items' => [],
],
],
],
'skilldisplay_campaign' => [

View file

@ -0,0 +1 @@
SkilldisplayContent.skillSet.cache = 0

View file

@ -17,6 +17,7 @@ tt_content.skilldisplay_skillset {
dataProcessing {
10 = SkillDisplay\SkilldisplayContent\Frontend\DataProcessing\SkillSets
10 {
cache = {$SkilldisplayContent.skillSet.cache}
skillSets.field = skilldisplay_skillset
}
}

View file

@ -1,10 +1,21 @@
=========================================
TYPO3 Extension to integrate SkillDisplay
=========================================
=======================================================================
Display Skills & SkillSets from SkillDisplay as TYPO3 Content Elements
========================================================================
This TYPO3 extension integrates SkillDisplay into TYPO3 installations.
This TYPO3 extension allows to show SkillDisplay Skills & SkillSets in TYPO3 installations.
Right now it provides the following features:
Scenarios
* Show job requirements based on official certification and expert definitions on your website
* Visualize the curriculum of a training your agency provides
* Display the requirements for official certification (on official pages or your intranet websites)
You can list the skills as content elements one by one, or use SkillSets for grouping purposes (see scenarios above).
All public SkillSets available on the SkillDisplay platform (e.g.: Certification curriculums, etc.) are automatically available for use in this extension.
To use custom SkillSets you either need a business account on the official SkillDisplay platform, or host the Open Source SkillDisplay Core Extension on your own TYPO3 instance.
Right now this extension provides the following features:
* Content element to render one or more skills.
@ -18,6 +29,8 @@ Right now it provides the following features:
* ViewHelper to generate verification URL.
* ViewHelper to group skills by domain tag
Installation
============
@ -46,6 +59,10 @@ Or copy the files from `/Resources/Private/Templates/ContentElements/` to your e
Configuration
=============
It is possible to cache the API results for Skill Sets with this TypoScript constant::
SkilldisplayContent.skillSet.cache = 1
You may include default CSS for the templates in your TypoScript::
page.includeCSS.skilldisplay = EXT:skilldisplay_content/Resources/Public/Css/Styles.css
@ -59,5 +76,4 @@ Both can be adjusted via custom TypoScript and TSconfig.
Usage
=====
Add content elements to the pages and insert the ID of skills as comma separated
list, or the ID of a single skill set.
Add content elements to the pages and insert the ID of skills as comma separated list, or select one of the available skillsets. (The list includes all public SkillSets on the official SkillDisplay platform. Using custom SkillDisplay instances based on the Open Source extension is possible, check the skilldisplay/php-api package for more information)

View file

@ -1,14 +1,25 @@
<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
xmlns:sd="http://typo3.org/ns/SkillDisplay/SkilldisplayContent/ViewHelpers"
data-namespace-typo3-fluid="true">
<f:for each="{skillSets}" as="skillSet">
{f:render(partial: 'VerificationBox', arguments: {
title: skillSet.name,
count: '{skillSet.skills -> f:count()}',
detailUrl: 'https://my.skilldisplay.eu/skillset/{skillSet.id}',
brandLogoUrl: skillSet.brand.logoPublicUrl,
verificationUrl: '{sd:verification.url(skillSet: skillSet.id, campaign: data.skilldisplay_campaign)}',
description: skillSet.description
})}
xmlns:sd="http://typo3.org/ns/SkillDisplay/SkilldisplayContent/ViewHelpers"
data-namespace-typo3-fluid="true">
<f:for each="{skillSets}" as="skillSet">
<sd:skillGrouping skillSet="{skillSet}" as="domainGroup">
<b>{domainGroup.title}</b><br/>
<f:for each="{domainGroup.skills}" as="skill">
{skill.title}<br/>
</f:for>
</sd:skillGrouping>
</f:for>
<hr>
<f:for each="{skillSets}" as="skillSet">
{f:render(partial: 'VerificationBox', arguments: {
title: skillSet.name,
count: '{skillSet.skills -> f:count()}',
detailUrl: 'https://my.skilldisplay.eu/skillset/{skillSet.id}',
brandLogoUrl: skillSet.brand.logoPublicUrl,
verificationUrl: '{sd:verification.url(skillSet: skillSet.id, campaign: data.skilldisplay_campaign)}',
description: skillSet.description
})}
</f:for>
</html>

View file

@ -27,7 +27,7 @@
},
"require": {
"php": "^7.4 || ^8.1 || ^8.2",
"skilldisplay/phptoolkit": "^2.0.1",
"skilldisplay/phptoolkit": "^2.1",
"typo3/cms-backend": "^11.5 || ^12.4",
"typo3/cms-frontend": "^11.5 || ^12.4"
},

View file

@ -25,4 +25,28 @@
// todo v11?
$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['cms/layout/class.tx_cms_layout.php']['tt_content_drawItem'][$extKey] =
\SkillDisplay\SkilldisplayContent\Backend\Preview::class;
// Inject skillsets into valuepicker form
$GLOBALS['TYPO3_CONF_VARS']['SYS']['formEngine']['formDataGroup']['tcaDatabaseRecord']
[\SkillDisplay\SkilldisplayContent\FormDataProvider\ValuePickerItemDataProvider::class] = [
'depends' => [
\TYPO3\CMS\Backend\Form\FormDataProvider\TcaInputPlaceholders::class,
],
];
$caches = [
'sdcontent',
];
foreach ($caches as $cacheName) {
$GLOBALS['TYPO3_CONF_VARS']['SYS']['caching']['cacheConfigurations'][$cacheName] = [
'frontend' => \TYPO3\CMS\Core\Cache\Frontend\VariableFrontend::class,
'backend' => \TYPO3\CMS\Core\Cache\Backend\SimpleFileBackend::class,
'options' => [
'defaultLifetime' => 2592000, // 30 days
],
'groups' => ['lowlevel']
];
}
})('skilldisplay_content');

View file

@ -1,6 +1,6 @@
CREATE TABLE tt_content
(
skilldisplay_skills TEXT,
skilldisplay_skillset int(11) unsigned DEFAULT '0' NOT NULL,
skilldisplay_campaign varchar(200) DEFAULT '' NOT NULL
skilldisplay_skills varchar(200) DEFAULT '' NOT NULL,
skilldisplay_skillset varchar(200) DEFAULT '' NOT NULL,
skilldisplay_campaign varchar(200) DEFAULT '' NOT NULL
);