Skip to content

Commit a4ae110

Browse files
committed
Initial commit
0 parents  commit a4ae110

File tree

10 files changed

+454
-0
lines changed

10 files changed

+454
-0
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.DS_*
2+
config.yml
3+
composer.lock
4+
vendor/
5+
tests/tmp/
6+

README.md

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# Social Hub Extension
2+
3+
Helper functions for the Social Hub website.
4+
5+
# Is Useful Extension
6+
7+
This is a simple extension that adds the feature to add a "Is this page useful? Yes No"
8+
to your pages. It has two modes:
9+
10+
- `link`: If a user clicks 'No', it will go to that page.
11+
- `boltforms`: If a user clicks 'No', it will expand a form (requires `bolt/boltforms`).
12+
13+
For `link` mode, you can get the `url` parameter from the query string.
14+
15+
For `boltforms` mode, you need to add a form named `feedback` and set `ajax` to
16+
`true`. An example form as follows:
17+
18+
```
19+
feedback:
20+
submission:
21+
ajax: true
22+
notification:
23+
enabled: true
24+
# debug: true
25+
# debug_address:
26+
# debug_smtp: true
27+
subject: Feedback
28+
from_name: no-reply@example.com
29+
from_email: no-reply@example.com
30+
to_name: Example
31+
to_email: info@example.com
32+
feedback:
33+
success: Success
34+
error: Error
35+
fields:
36+
message:
37+
type: textarea
38+
options:
39+
required: false
40+
label: Feedback
41+
attr:
42+
placeholder: How should we improve this page?
43+
class: message
44+
url:
45+
type: hidden
46+
options:
47+
label: URL
48+
required: false
49+
attr:
50+
class: hidden
51+
submit:
52+
type: submit
53+
options:
54+
label: Send
55+
attr:
56+
class: button primary
57+
```
58+
59+
In your template add:
60+
61+
```
62+
{{ include('@is_useful/_is_useful.twig') }}
63+
```
64+
65+
Or copy the twig file to your theme, customize it and include that file.
66+
67+
<!--
68+
Inspired from GOV.UK, e.g. https://www.gov.uk/service-manual/measuring-success/measuring-user-satisfaction
69+
-->

composer.json

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"name": "twokings/socialhub",
3+
"description": "Social Hub helper functions",
4+
"type": "bolt-extension",
5+
"keywords": [
6+
"useful",
7+
"feedback"
8+
],
9+
"require": {
10+
"bolt/bolt": "^3.0"
11+
},
12+
"license": "MIT",
13+
"authors": [
14+
{
15+
"name": "Xiao-Hu Tai",
16+
"email": "xiao@twokings.nl"
17+
}
18+
],
19+
"minimum-stability": "dev",
20+
"prefer-stable": true,
21+
"autoload": {
22+
"psr-4": {
23+
"Bolt\\Extension\\TwoKings\\SocialHub\\": "src"
24+
}
25+
},
26+
"extra": {
27+
"bolt-assets": "web",
28+
"bolt-class": "Bolt\\Extension\\TwoKings\\SocialHub\\SocialHubExtension",
29+
"bolt-icon": "bolt-icon.png",
30+
},
31+
"suggest": {
32+
"bolt/boltforms": "A form generator for Bolt CMS"
33+
}
34+
}

config/config.yml.dist

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Pick one of two options.
2+
3+
# ------------------------------------------------------------------------------
4+
# Option 1: Link
5+
# ------------------------------------------------------------------------------
6+
7+
type: link
8+
link: '/contact'
9+
10+
# ------------------------------------------------------------------------------
11+
# Option 2: Boltforms
12+
# ------------------------------------------------------------------------------
13+
14+
# type: boltforms
15+
# formname: feedback
16+
17+
# ------------------------------------------------------------------------------
18+
# General
19+
# ------------------------------------------------------------------------------
20+
21+
label:
22+
question: Is this page useful?
23+
yes: Yes
24+
yes_detail: this page is useful
25+
no: No
26+
no_detail: this page is not useful
27+
thanks: Thanks for your feedback
28+
close: Close form
29+
30+
# visuallyhidden: Classes for visually hidden elements; these elements can be
31+
# read/interpreted by screen readers and other assisitive
32+
# technologies. Common class names are 'sr-only', 'at-only',
33+
# and 'visually-hidden'.
34+
css:
35+
wrapper : 'is-useful-wrapper' # do not change if you use default js/css
36+
expand : 'expand' # do not change if you use default js/css
37+
visuallyhidden : 'visually-hidden'
38+
39+
add_js: true
40+
add_css: true

src/Config/Config.php

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
<?php
2+
3+
namespace Bolt\Extension\TwoKings\SocialHub\Config;
4+
5+
use Symfony\Component\HttpFoundation\ParameterBag;
6+
7+
/**
8+
* @author Xiao-Hu Tai <xiao@twokings.nl>
9+
*/
10+
class Config extends ParameterBag
11+
{
12+
/**
13+
* {@inheritdoc}
14+
*/
15+
public function __construct($parameters = [])
16+
{
17+
parent::__construct($parameters);
18+
}
19+
20+
/**
21+
* This function is aken from \Bolt\Config class:
22+
* @link https://github.com/bolt/bolt/blob/release/3.2/src/Config.php#L202-L239
23+
*
24+
* Get a config value, using a path. So the third parameter $deep is ignored.
25+
*
26+
* For example:
27+
* $var = $config->get('general/wysiwyg/ck/contentsCss');
28+
*
29+
* @param string $path
30+
* @param string|array|boolean $default
31+
* @param bool $deep
32+
*
33+
* @return mixed
34+
*/
35+
public function get($path, $default = null, $deep = false)
36+
{
37+
$path = explode('/', $path);
38+
39+
// Only do something if we get at least one key.
40+
if (empty($path[0]) || !isset($this->parameters[$path[0]])) {
41+
return false;
42+
}
43+
44+
$part = & $this->parameters;
45+
$value = null;
46+
47+
foreach ($path as $key) {
48+
if (!isset($part[$key])) {
49+
$value = null;
50+
break;
51+
}
52+
53+
$value = $part[$key];
54+
$part = & $part[$key];
55+
}
56+
if ($value !== null) {
57+
return $value;
58+
}
59+
60+
return $default;
61+
}
62+
}

src/IsUsefulTable.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Bolt\Extension\TwoKings\SocialHub;
4+
5+
use Bolt\Storage\Database\Schema\Table\BaseTable;
6+
7+
class IsUsefulTable extends BaseTable
8+
{
9+
/**
10+
* {@inheritdoc}
11+
*/
12+
protected function addColumns()
13+
{
14+
$this->table->addColumn('id', 'integer', ['autoincrement' => true]);
15+
$this->table->addColumn('contenttype', 'string', ['notnull' => false]);
16+
$this->table->addColumn('contentid', 'integer', ['notnull' => false]);
17+
$this->table->addColumn('totals', 'json_array');
18+
$this->table->addColumn('ips', 'json_array');
19+
}
20+
21+
/**
22+
* {@inheritdoc}
23+
*/
24+
protected function addIndexes()
25+
{
26+
// This will create a joint index of both columns
27+
$this->table->addIndex(['contenttype', 'contentid']);
28+
}
29+
30+
/**
31+
* {@inheritdoc}
32+
*/
33+
protected function setPrimaryKey()
34+
{
35+
$this->table->setPrimaryKey(['id']);
36+
}
37+
}

src/SocialHubExtension.php

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
namespace Bolt\Extension\TwoKings\SocialHub;
4+
5+
use Bolt\Asset\File\JavaScript;
6+
use Bolt\Asset\File\Stylesheet;
7+
use Bolt\Controller\Zone;
8+
use Bolt\Extension\DatabaseSchemaTrait;
9+
use Bolt\Extension\SimpleExtension;
10+
use Bolt\Extension\TwoKings\SocialHub\Config\Config;
11+
use Silex\Application;
12+
use Silex\ControllerCollection;
13+
14+
/**
15+
* @author Xiao-Hu Tai <xiao@twokings.nl>
16+
*/
17+
class SocialHubExtension extends SimpleExtension
18+
{
19+
use DatabaseSchemaTrait;
20+
21+
/**
22+
* {@inheritdoc}
23+
*/
24+
protected function registerExtensionTables()
25+
{
26+
return [
27+
'is_useful' => IsUsefulTable::class,
28+
];
29+
}
30+
31+
protected function registerFrontendRoutes(ControllerCollection $collection)
32+
{
33+
// $collection->match('/async/is-useful', [$this, '']);
34+
// Update with a 'yes' or a 'no' and count them in the database
35+
}
36+
37+
/**
38+
* {@inheritdoc}
39+
*/
40+
protected function registerTwigPaths()
41+
{
42+
return [
43+
'templates' => [
44+
'position' => 'prepend',
45+
'namespace' => 'is_useful'
46+
]
47+
];
48+
}
49+
50+
/**
51+
* {@inheritdoc}
52+
*/
53+
protected function registerAssets()
54+
{
55+
$assets = [];
56+
57+
$config = $this->getConfig();
58+
59+
// By default, add JavaScript and CSS files, unless it is explicityly
60+
// set to `false`.
61+
if (!isset($config['add_js']) || $config['add_js'] !== false) {
62+
$assets[] = JavaScript::create()
63+
->setFileName('extensions/vendor/twokings/is-useful/extension.js')
64+
->setLate(true)
65+
->setZone(Zone::FRONTEND)
66+
;
67+
}
68+
69+
if (!isset($config['add_css']) || $config['add_css'] !== false) {
70+
$assets[] = StyleSheet::create()
71+
->setFileName('extensions/vendor/twokings/is-useful/extension.css')
72+
->setLate(true)
73+
->setZone(Zone::FRONTEND)
74+
;
75+
}
76+
77+
return $assets;
78+
}
79+
80+
/**
81+
* {@inheritdoc}
82+
*/
83+
protected function registerServices(Application $app)
84+
{
85+
$this->extendDatabaseSchemaServices();
86+
87+
$app['is_useful.config'] = $app->share(function () { return new Config($this->getConfig()); });
88+
}
89+
}

templates/_is_useful.twig

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{% set config = app['is_useful.config'].all() %}
2+
{% set attributes = '' %}
3+
{% if config.type == 'boltforms' %}
4+
{% set attributes = 'aria-expanded="false"' %}
5+
{% elseif config.type == 'link' %}
6+
{% set attributes = 'href="' ~ config.link ~ '?url=' ~ global.request.getUri()|url_encode ~ '"' %}
7+
{% endif %}
8+
9+
<div
10+
class="{{ config.css.wrapper }}"
11+
data-thanks="{{ config.label.thanks }}"
12+
data-type="{{ config.type }}">
13+
<p>
14+
{{ config.label.question }}
15+
{% spaceless %}
16+
<a class="is-useful">
17+
{{- config.label.yes -}}
18+
<span class="{{ config.css.visuallyhidden }}"> {{ config.label.yes_detail -}}
19+
</span>
20+
</a>
21+
<a class="is-not-useful" {{ attributes|raw }}>
22+
{{- config.label.no -}}
23+
<span class="{{ config.css.visuallyhidden }}"> {{ config.label.no_detail -}}
24+
</span>
25+
</a>
26+
{% endspaceless %}
27+
</p>
28+
{% if config.type == 'boltforms' and config.formname is defined %}
29+
<div class="{{ config.css.expand }}" aria-hidden="true">
30+
<button class="close-button" aria-label="{{ config.label.close }}" type="button">
31+
<span aria-hidden="true">&times;</span>
32+
</button>
33+
{{ boltforms(config.formname, defaults = {
34+
url: global.request.getUri()
35+
}) }}
36+
</div>
37+
{% endif %}
38+
</div>

0 commit comments

Comments
 (0)