Commit 02d936d7 by bernard

Initial commit

parents
.DS_*
config.yml
composer.lock
vendor/
tests/tmp/
.idea
\ No newline at end of file
### Installation :
Go to extensions dir
Add this to composer.json in repositories part
```
{
"type": "composer",
"url": "https://packages.lab.appolo.fr/"
},
```
Run
> composer require appolo/bolt-extension-custom-queries
Add new field in content type like this :
```
list:
type: textarea
class: customQuery
group: customQuery
```
And add in the template where you want the filter result :
```
{{ record.list|queriesResults }}
```
\ No newline at end of file
{
"name": "appolo/bolt-extension-custom-queries",
"description": "",
"type": "bolt-extension",
"keywords": [
],
"version": "0.1.0",
"require": {
"bolt/bolt": "^3.0"
},
"require-dev": {
"phpunit/phpunit": "^4.7"
},
"license": "MIT",
"authors": [
{
"name": "Appolo",
"email": "contact@appolo.fr"
}
],
"minimum-stability": "dev",
"prefer-stable": true,
"autoload": {
"psr-4": {
"Bolt\\Extension\\Appolo\\CustomQueries\\": "src"
}
},
"autoload-dev": {
"psr-4": {
"Bolt\\Extension\\Appolo\\CustomQueries\\Tests\\": "tests",
"Bolt\\Tests\\": "vendor/bolt/bolt/tests/phpunit/unit/"
}
},
"extra": {
"bolt-assets": "web",
"bolt-class": "Bolt\\Extension\\Appolo\\CustomQueries\\CustomQueriesExtension"
}
}
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="tests/bootstrap.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false">
<testsuites>
<testsuite name="unit">
<directory>tests</directory>
</testsuite>
</testsuites>
<listeners>
<listener file="vendor/bolt/bolt/tests/phpunit/BoltListener.php" class="Bolt\Tests\BoltListener">
<arguments>
<!-- Configuration files. Can be either .yml or .yml.dist files -->
<!-- Locations can be relative to TEST_ROOT directory, the Bolt directory, or an absolute path -->
<array>
<element key="config">
<string>vendor/bolt/bolt/app/config/config.yml.dist</string>
</element>
<element key="contenttypes">
<string>vendor/bolt/bolt/app/config/contenttypes.yml.dist</string>
</element>
<element key="menu">
<string>vendor/bolt/bolt/app/config/menu.yml.dist</string>
</element>
<element key="permissions">
<string>vendor/bolt/bolt/app/config/permissions.yml.dist</string>
</element>
<element key="routing">
<string>vendor/bolt/bolt/app/config/routing.yml.dist</string>
</element>
<element key="taxonomy">
<string>vendor/bolt/bolt/app/config/taxonomy.yml.dist</string>
</element>
</array>
<!-- Theme directory. Can be relative to TEST_ROOT directory, the Bolt directory, or an absolute path -->
<array>
<element key="theme">
<string>theme/base-2014</string>
</element>
</array>
<!-- The Bolt SQLite database, leave empty to use the one bundled with Bolt's repository -->
<!-- Location can be relative to TEST_ROOT directory, the Bolt directory, or an absolute path -->
<array>
<element key="boltdb">
<string>vendor/bolt/bolt/tests/phpunit/unit/resources/db/bolt.db</string>
</element>
</array>
<!-- Reset the cache and test temporary directories -->
<boolean>true</boolean>
<!-- Create timer output in app/cache/phpunit-test-timer.txt -->
<boolean>true</boolean>
</arguments>
</listener>
</listeners>
</phpunit>
<?php
namespace Bolt\Extension\Appolo\CustomQueries\Controller\Backend;
use Bolt\Application;
use Bolt\Controller\Backend\BackendBase;
use Silex\ControllerCollection;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
class CustomQueriesController extends BackendBase {
/**
* @var Application
*/
private $application;
/**
* ConnectionController constructor.
* @param Application $application
* @internal param array $config
*/
public function __construct(Application $application)
{
$this->application = $application;
}
/**
* @param ControllerCollection $c
* @return ControllerCollection
*/
protected function addRoutes(ControllerCollection $c)
{
$c->match('/config', 'getConfig')
->bind('getConfig')
;
return $c;
}
/**
* @param Request $request
* @return JsonResponse
*/
public function getConfig(Request $request)
{
return new JsonResponse($this->application['config']->get('contenttypes'));
}
}
<?php
namespace Bolt\Extension\Appolo\CustomQueries;
use Bolt\Asset\File\JavaScript;
use Bolt\Asset\File\Stylesheet;
use Bolt\Controller\Zone;
use Bolt\Extension\Appolo\CustomQueries\Controller\Backend\CustomQueriesController;
use Bolt\Extension\SimpleExtension;
/**
* CustomQueries extension class.
*
* @author Your Name <you@example.com>
*/
class CustomQueriesExtension extends SimpleExtension
{
/**
* {@inheritdoc}
*/
protected function registerTwigFilters()
{
return [
'queriesResults' => ['getQueriesResults', ['is_safe' => ['html']]],
];
}
/**
* {@inheritdoc}
*/
protected function registerAssets()
{
return [
JavaScript::create()
->setFileName('js/app.js')
->setLate(true)
->setPriority(5)
->setZone(Zone::BACKEND),
Stylesheet::create()
->setFileName('css/app.css')
->setLate(true)
->setPriority(5)
->setZone(Zone::BACKEND)
];
}
/**
* Register Controller
* {@inheritdoc}
*/
protected function registerBackendControllers()
{
return [
'/custom-queries' => new CustomQueriesController($this->getContainer()),
];
}
/**
* Register twig paths for application
*/
protected function registerTwigPaths()
{
return ['templates'];
}
/**
* @return false|mixed
*/
public function getQueriesResults($input)
{
if($input == '') {
return '';
}
$json = json_decode($input, true);
if(!$json || empty($json)) {
return '';
}
$records = [];
$storage = $this->getContainer()['storage'];
foreach ($json as $contentType => $fields) {
$query = $this->_buildQuery($contentType, $fields);
if(!empty($query))
{
$rows = $this->getContainer()['db']->fetchAll($query);
$ids = array_map(function($rows) {
return $rows['id'];
}, $rows);
$contents = $storage->getContent($contentType, ['id' => implode(' || ', $ids), 'paging' => true, 'limit' => 99999]);
if(is_array($contents)) {
$records = array_merge($records, $contents);
} else {
$records = array_merge($records, [$contents]);
}
}
}
return $this->getContainer()['twig']->render("custom_queries.twig", ['records' => $records]);
}
/**
* @param array $fields
* @return string
*/
protected function _buildQuery($contentType, array $fields = []) {
if(!$contentType) {
return '';
}
$storage = $this->getContainer()['storage'];
$tableName = $storage->getContenttypeTablename($contentType);
if(!$tableName) {
return '';
}
$query = 'SELECT id FROM '.$tableName;
$where = $this->_buildWhere($fields);
if($where) {
$query .= $where;
}
return $query;
}
/**
* @param array $fields
* @return bool
*/
protected function _buildWhere(array $fields = []) {
$where = false;
foreach ($fields as $field => $value) {
if(!empty($value) && (!empty($value['include']) || !empty($value['exclude']))) {
$joinField = 'AND';
if(empty($value['joinFields']) || $value['joinFields'] == 'or') {
$joinField = 'OR';
}
if(!$where) {
$where = ' WHERE ';
} else {
$where .= ' AND ';
}
if(!empty($value['include'])) {
$where .= '(';
foreach ($value['include'] as $val) {
list($operator, $val) = $this->_getOperatorInclude($val);
$where .= $field.' '.$operator.' '.$val.' '.$joinField.' ';
}
$where = rtrim($where, ' '.$joinField.' ');
$where .= ')';
}
if(!empty($value['exclude'])) {
$where .= ' AND (';
foreach ($value['exclude'] as $val) {
list($operator, $val) = $this->_getOperatorExclude($val);
$where .= $field.' '.$operator.' '.$val.' AND ';
}
$where = rtrim($where, ' AND ');
$where .= ')';
}
}
}
return $where;
}
/**
* @param $value
* @return array
*/
protected function _getOperatorInclude($value) {
// Set the correct operator for the where clause
$operator = "=";
$first = substr($value, 0, 1);
if (substr($value, 0, 2) == "<=") {
$operator = "<=";
$value = substr($value, 2);
} elseif (substr($value, 0, 2) == ">=") {
$operator = ">=";
$value = substr($value, 2);
} elseif ($first == "<") {
$operator = "<";
$value = substr($value, 1);
} elseif ($first == ">") {
$operator = ">";
$value = substr($value, 1);
} elseif ($first == "%" || substr($value, -1) == "%") {
$operator = "LIKE";
}
$value = "'".$value."'";
return [$operator, $value];
}
/**
* @param $value
* @return array
*/
protected function _getOperatorExclude($value) {
// Set the correct operator for the where clause
$operator = "!=";
$first = substr($value, 0, 1);
if (substr($value, 0, 2) == "<=") {
$operator = "<=";
$value = substr($value, 2);
} elseif (substr($value, 0, 2) == ">=") {
$operator = ">=";
$value = substr($value, 2);
} elseif ($first == "<") {
$operator = "<";
$value = substr($value, 1);
} elseif ($first == ">") {
$operator = ">";
$value = substr($value, 1);
} elseif ($first == "%" || substr($value, -1) == "%") {
$operator = "NOT LIKE";
}
$value = "'".$value."'";
return [$operator, $value];
}
}
{% if records is defined %}
<ul>
{% for record in records %}
<li><a href="{{ record.link }}">{{ record.title }}</a></li>
{% endfor %}
</ul>
{% endif %}
\ No newline at end of file
.m-t-15 {
margin-top: 15px;
}
.border-none {
border: none !important;
}
.chooseField {
height: 26px !important;
}
.addContentTypeContainer {
margin-bottom: 30px;
}
.listContentTypeContainer .dashboardlisting tr {
background-color: transparent !important;
}
.listContentTypeContainer div.buic-listing table.listing tbody.striping_odd tr:nth-of-type(odd) {
background: #f2f4f3 !important;
}
.listContentTypeContainer .panel-heading .title {
font-size: 20px;
text-transform: uppercase;
font-weight: bold;
}
.switch {
position: relative;
width: 56px;
height: 26px;
border: 1px solid #5e9e11;
color: #5e9e11;
border-radius: 3px;
background-color: #e0e0e0;
float: right;
}
.quality {
position: relative;
display: inline-block;
width: 50%;
height: 100%;
line-height: 40px;
}
.quality:first-child label {
line-height: 26px;
}
.quality:last-child label {
line-height: 26px;
}
.quality label {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
cursor: pointer;
font-style: italic;
text-align: center;
transition: transform 0.4s, color 0.4s, background-color 0.4s;
}
.quality input[type="radio"] {
appearance: none;
width: 0;
height: 0;
opacity: 0;
}
.quality input[type="radio"]:focus {
outline: 0;
outline-offset: 0;
}
.quality input[type="radio"]:checked ~ label {
background-color: #5e9e11;
color: #ffffff;
}
.quality input[type="radio"]:active ~ label {
transform: scale(1.05);
}
This diff is collapsed. Click to expand it.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment