mirror of
https://github.com/wallabag/wallabag.git
synced 2024-12-23 08:06:33 +00:00
commit
a7f1921f7d
26 changed files with 1888 additions and 34 deletions
|
@ -29,6 +29,7 @@ class AppKernel extends Kernel
|
|||
new FOS\OAuthServerBundle\FOSOAuthServerBundle(),
|
||||
new Wallabag\UserBundle\WallabagUserBundle(),
|
||||
new Scheb\TwoFactorBundle\SchebTwoFactorBundle(),
|
||||
new KPhoen\RulerZBundle\KPhoenRulerZBundle(),
|
||||
);
|
||||
|
||||
if (in_array($this->getEnvironment(), array('dev', 'test'))) {
|
||||
|
|
|
@ -189,3 +189,7 @@ scheb_two_factor:
|
|||
sender_email: %twofactor_sender%
|
||||
digits: 6
|
||||
template: WallabagUserBundle:Authentication:form.html.twig
|
||||
|
||||
kphoen_rulerz:
|
||||
executors:
|
||||
doctrine: true
|
||||
|
|
|
@ -57,7 +57,8 @@
|
|||
"friendsofsymfony/oauth-server-bundle": "^1.4@dev",
|
||||
"scheb/two-factor-bundle": "~1.4",
|
||||
"grandt/phpepub": "~4.0",
|
||||
"wallabag/php-mobi": "~1.0.0"
|
||||
"wallabag/php-mobi": "~1.0.0",
|
||||
"kphoen/rulerz-bundle": "~0.10"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/doctrine-fixtures-bundle": "~2.2.0",
|
||||
|
|
774
composer.lock
generated
774
composer.lock
generated
|
@ -4,7 +4,8 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "a9ec461e17166dcda1563dd55f6ff861",
|
||||
"hash": "fed9468f6c830b0f81899daad7670af7",
|
||||
"content-hash": "394f8a6ca5162f2d2756dbbee0ff5aae",
|
||||
"packages": [
|
||||
{
|
||||
"name": "doctrine/annotations",
|
||||
|
@ -1484,6 +1485,610 @@
|
|||
],
|
||||
"time": "2014-10-12 19:18:40"
|
||||
},
|
||||
{
|
||||
"name": "hoa/compiler",
|
||||
"version": "2.15.10.29",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/hoaproject/Compiler.git",
|
||||
"reference": "ec0849fd3c1472fbcd86c3c961981f0cfe1f8d39"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/hoaproject/Compiler/zipball/ec0849fd3c1472fbcd86c3c961981f0cfe1f8d39",
|
||||
"reference": "ec0849fd3c1472fbcd86c3c961981f0cfe1f8d39",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"hoa/core": "~2.0",
|
||||
"hoa/file": "~0.0",
|
||||
"hoa/iterator": "~1.0",
|
||||
"hoa/math": "~0.0",
|
||||
"hoa/regex": "~0.0",
|
||||
"hoa/visitor": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"hoa/json": "~1.0",
|
||||
"hoa/test": "~1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Hoa\\Compiler\\": "."
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ivan Enderlin",
|
||||
"email": "ivan.enderlin@hoa-project.net"
|
||||
},
|
||||
{
|
||||
"name": "Hoa community",
|
||||
"homepage": "http://hoa-project.net/"
|
||||
}
|
||||
],
|
||||
"description": "The Hoa\\Compiler library.",
|
||||
"homepage": "http://hoa-project.net/",
|
||||
"keywords": [
|
||||
"algebraic",
|
||||
"ast",
|
||||
"compiler",
|
||||
"context-free",
|
||||
"coverage",
|
||||
"exhaustive",
|
||||
"grammar",
|
||||
"isotropic",
|
||||
"language",
|
||||
"lexer",
|
||||
"library",
|
||||
"ll1",
|
||||
"llk",
|
||||
"parser",
|
||||
"pp",
|
||||
"random",
|
||||
"regular",
|
||||
"rule",
|
||||
"sampler",
|
||||
"syntax",
|
||||
"token",
|
||||
"trace",
|
||||
"uniform"
|
||||
],
|
||||
"time": "2015-10-29 21:35:12"
|
||||
},
|
||||
{
|
||||
"name": "hoa/core",
|
||||
"version": "2.15.11.09",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/hoaproject/Core.git",
|
||||
"reference": "5538b1e90e2c66c90df5cc45e03fb85d047be900"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/hoaproject/Core/zipball/5538b1e90e2c66c90df5cc45e03fb85d047be900",
|
||||
"reference": "5538b1e90e2c66c90df5cc45e03fb85d047be900",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-spl": "*",
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"hoa/test": "~1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-mbstring": "ext/mbstring must be present (or a third implementation).",
|
||||
"hoa/cli": "To use the `hoa` script."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Hoa\\Core\\": "."
|
||||
},
|
||||
"files": [
|
||||
"Core.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ivan Enderlin",
|
||||
"email": "ivan.enderlin@hoa-project.net"
|
||||
},
|
||||
{
|
||||
"name": "Hoa community",
|
||||
"homepage": "http://hoa-project.net/"
|
||||
}
|
||||
],
|
||||
"description": "The Hoa\\Core library.",
|
||||
"homepage": "http://hoa-project.net/",
|
||||
"keywords": [
|
||||
"consistency",
|
||||
"core",
|
||||
"data",
|
||||
"event",
|
||||
"library",
|
||||
"listener",
|
||||
"parameter",
|
||||
"protocol"
|
||||
],
|
||||
"time": "2015-11-09 06:51:06"
|
||||
},
|
||||
{
|
||||
"name": "hoa/file",
|
||||
"version": "0.15.11.09",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/hoaproject/File.git",
|
||||
"reference": "f46fe552ff79cb6c93a2ff9c25cfbc134fbd57ee"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/hoaproject/File/zipball/f46fe552ff79cb6c93a2ff9c25cfbc134fbd57ee",
|
||||
"reference": "f46fe552ff79cb6c93a2ff9c25cfbc134fbd57ee",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"hoa/core": "~2.0",
|
||||
"hoa/iterator": "~1.0",
|
||||
"hoa/stream": "~0.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"hoa/test": "~1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Hoa\\File\\": "."
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ivan Enderlin",
|
||||
"email": "ivan.enderlin@hoa-project.net"
|
||||
},
|
||||
{
|
||||
"name": "Hoa community",
|
||||
"homepage": "http://hoa-project.net/"
|
||||
}
|
||||
],
|
||||
"description": "The Hoa\\File library.",
|
||||
"homepage": "http://hoa-project.net/",
|
||||
"keywords": [
|
||||
"Socket",
|
||||
"directory",
|
||||
"file",
|
||||
"finder",
|
||||
"library",
|
||||
"link",
|
||||
"temporary"
|
||||
],
|
||||
"time": "2015-11-09 06:55:20"
|
||||
},
|
||||
{
|
||||
"name": "hoa/iterator",
|
||||
"version": "1.15.10.29",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/hoaproject/Iterator.git",
|
||||
"reference": "a64ed9fd62579a34e4450134d6d1abdf77d54435"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/hoaproject/Iterator/zipball/a64ed9fd62579a34e4450134d6d1abdf77d54435",
|
||||
"reference": "a64ed9fd62579a34e4450134d6d1abdf77d54435",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"hoa/core": "~2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"hoa/test": "~1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Hoa\\Iterator\\": "."
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ivan Enderlin",
|
||||
"email": "ivan.enderlin@hoa-project.net"
|
||||
},
|
||||
{
|
||||
"name": "Hoa community",
|
||||
"homepage": "http://hoa-project.net/"
|
||||
}
|
||||
],
|
||||
"description": "The Hoa\\Iterator library.",
|
||||
"homepage": "http://hoa-project.net/",
|
||||
"keywords": [
|
||||
"iterator",
|
||||
"library"
|
||||
],
|
||||
"time": "2015-10-29 21:37:16"
|
||||
},
|
||||
{
|
||||
"name": "hoa/math",
|
||||
"version": "0.15.10.26",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/hoaproject/Math.git",
|
||||
"reference": "62631c65d9a4f1b8bb4c4a3d6cdff0e8971d684e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/hoaproject/Math/zipball/62631c65d9a4f1b8bb4c4a3d6cdff0e8971d684e",
|
||||
"reference": "62631c65d9a4f1b8bb4c4a3d6cdff0e8971d684e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"hoa/compiler": "~2.0",
|
||||
"hoa/core": "~2.0",
|
||||
"hoa/iterator": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"hoa/test": "~1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Hoa\\Math\\": "."
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ivan Enderlin",
|
||||
"email": "ivan.enderlin@hoa-project.net"
|
||||
},
|
||||
{
|
||||
"name": "Hoa community",
|
||||
"homepage": "http://hoa-project.net/"
|
||||
}
|
||||
],
|
||||
"description": "The Hoa\\Math library.",
|
||||
"homepage": "http://hoa-project.net/",
|
||||
"keywords": [
|
||||
"arrangement",
|
||||
"combination",
|
||||
"combinatorics",
|
||||
"counting",
|
||||
"library",
|
||||
"math",
|
||||
"permutation",
|
||||
"sampler",
|
||||
"set"
|
||||
],
|
||||
"time": "2015-10-26 15:22:52"
|
||||
},
|
||||
{
|
||||
"name": "hoa/regex",
|
||||
"version": "0.15.08.13",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/hoaproject/Regex.git",
|
||||
"reference": "2ef8a77ef3885ca202fcd9c31a8e54c44cd04232"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/hoaproject/Regex/zipball/2ef8a77ef3885ca202fcd9c31a8e54c44cd04232",
|
||||
"reference": "2ef8a77ef3885ca202fcd9c31a8e54c44cd04232",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"hoa/core": "~2.0",
|
||||
"hoa/math": "~0.0",
|
||||
"hoa/ustring": "~3.0",
|
||||
"hoa/visitor": "~1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Hoa\\Regex\\": "."
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ivan Enderlin",
|
||||
"email": "ivan.enderlin@hoa-project.net"
|
||||
},
|
||||
{
|
||||
"name": "Hoa community",
|
||||
"homepage": "http://hoa-project.net/"
|
||||
}
|
||||
],
|
||||
"description": "The Hoa\\Regex library.",
|
||||
"homepage": "http://hoa-project.net/",
|
||||
"keywords": [
|
||||
"compiler",
|
||||
"library",
|
||||
"regex"
|
||||
],
|
||||
"time": "2015-08-13 06:48:47"
|
||||
},
|
||||
{
|
||||
"name": "hoa/ruler",
|
||||
"version": "1.15.11.09",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/hoaproject/Ruler.git",
|
||||
"reference": "9afc9ae032d40b6dc10bff85c9126cf516953925"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/hoaproject/Ruler/zipball/9afc9ae032d40b6dc10bff85c9126cf516953925",
|
||||
"reference": "9afc9ae032d40b6dc10bff85c9126cf516953925",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"hoa/compiler": "~2.0",
|
||||
"hoa/core": "~2.0",
|
||||
"hoa/file": "~0.0",
|
||||
"hoa/visitor": "~1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"hoa/test": "~1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Hoa\\Ruler\\": "."
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ivan Enderlin",
|
||||
"email": "ivan.enderlin@hoa-project.net"
|
||||
},
|
||||
{
|
||||
"name": "Hoa community",
|
||||
"homepage": "http://hoa-project.net/"
|
||||
}
|
||||
],
|
||||
"description": "The Hoa\\Ruler library.",
|
||||
"homepage": "http://hoa-project.net/",
|
||||
"keywords": [
|
||||
"library",
|
||||
"ruler"
|
||||
],
|
||||
"time": "2015-11-09 06:58:52"
|
||||
},
|
||||
{
|
||||
"name": "hoa/stream",
|
||||
"version": "0.15.10.26",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/hoaproject/Stream.git",
|
||||
"reference": "011ab91d942f1d7096deade4c8a10fe57d51c5b3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/hoaproject/Stream/zipball/011ab91d942f1d7096deade4c8a10fe57d51c5b3",
|
||||
"reference": "011ab91d942f1d7096deade4c8a10fe57d51c5b3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"hoa/core": "~2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Hoa\\Stream\\": "."
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ivan Enderlin",
|
||||
"email": "ivan.enderlin@hoa-project.net"
|
||||
},
|
||||
{
|
||||
"name": "Hoa community",
|
||||
"homepage": "http://hoa-project.net/"
|
||||
}
|
||||
],
|
||||
"description": "The Hoa\\Stream library.",
|
||||
"homepage": "http://hoa-project.net/",
|
||||
"keywords": [
|
||||
"Context",
|
||||
"bucket",
|
||||
"composite",
|
||||
"filter",
|
||||
"in",
|
||||
"library",
|
||||
"out",
|
||||
"protocol",
|
||||
"stream",
|
||||
"wrapper"
|
||||
],
|
||||
"time": "2015-10-22 06:30:43"
|
||||
},
|
||||
{
|
||||
"name": "hoa/ustring",
|
||||
"version": "3.15.11.09",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/hoaproject/Ustring.git",
|
||||
"reference": "8506be4910212b1a2beb9014763a8a4fbd871001"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/hoaproject/Ustring/zipball/8506be4910212b1a2beb9014763a8a4fbd871001",
|
||||
"reference": "8506be4910212b1a2beb9014763a8a4fbd871001",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"hoa/core": "~2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"hoa/test": "~1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-iconv": "ext/iconv must be present (or a third implementation) to use Hoa\\Ustring::transcode().",
|
||||
"ext-intl": "To get a better Hoa\\Ustring::toAscii() and Hoa\\Ustring::compareTo()."
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Hoa\\Ustring\\": "."
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ivan Enderlin",
|
||||
"email": "ivan.enderlin@hoa-project.net"
|
||||
},
|
||||
{
|
||||
"name": "Hoa community",
|
||||
"homepage": "http://hoa-project.net/"
|
||||
}
|
||||
],
|
||||
"description": "The Hoa\\Ustring library.",
|
||||
"homepage": "http://hoa-project.net/",
|
||||
"keywords": [
|
||||
"library",
|
||||
"search",
|
||||
"string",
|
||||
"unicode"
|
||||
],
|
||||
"time": "2015-11-09 06:44:33"
|
||||
},
|
||||
{
|
||||
"name": "hoa/visitor",
|
||||
"version": "1.15.08.17",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/hoaproject/Visitor.git",
|
||||
"reference": "e30bfff741f71979f6476a41548e34afe8053c67"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/hoaproject/Visitor/zipball/e30bfff741f71979f6476a41548e34afe8053c67",
|
||||
"reference": "e30bfff741f71979f6476a41548e34afe8053c67",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"hoa/core": "~2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"hoa/test": "~1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Hoa\\Visitor\\": "."
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Ivan Enderlin",
|
||||
"email": "ivan.enderlin@hoa-project.net"
|
||||
},
|
||||
{
|
||||
"name": "Hoa community",
|
||||
"homepage": "http://hoa-project.net/"
|
||||
}
|
||||
],
|
||||
"description": "The Hoa\\Visitor library.",
|
||||
"homepage": "http://hoa-project.net/",
|
||||
"keywords": [
|
||||
"library",
|
||||
"structure",
|
||||
"visit",
|
||||
"visitor"
|
||||
],
|
||||
"time": "2015-08-17 06:30:58"
|
||||
},
|
||||
{
|
||||
"name": "htmlawed/htmlawed",
|
||||
"version": "1.1.19",
|
||||
|
@ -1532,21 +2137,21 @@
|
|||
},
|
||||
{
|
||||
"name": "incenteev/composer-parameter-handler",
|
||||
"version": "v2.1.1",
|
||||
"version": "v2.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Incenteev/ParameterHandler.git",
|
||||
"reference": "84a205fe80a46101607bafbc423019527893ddd0"
|
||||
"reference": "d7ce7f06136109e81d1cb9d57066c4d4a99cf1cc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Incenteev/ParameterHandler/zipball/84a205fe80a46101607bafbc423019527893ddd0",
|
||||
"reference": "84a205fe80a46101607bafbc423019527893ddd0",
|
||||
"url": "https://api.github.com/repos/Incenteev/ParameterHandler/zipball/d7ce7f06136109e81d1cb9d57066c4d4a99cf1cc",
|
||||
"reference": "d7ce7f06136109e81d1cb9d57066c4d4a99cf1cc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3",
|
||||
"symfony/yaml": "~2.0"
|
||||
"symfony/yaml": "~2.3|~3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"composer/composer": "1.0.*@dev",
|
||||
|
@ -1579,7 +2184,7 @@
|
|||
"keywords": [
|
||||
"parameters management"
|
||||
],
|
||||
"time": "2015-06-03 08:27:03"
|
||||
"time": "2015-11-10 17:04:01"
|
||||
},
|
||||
{
|
||||
"name": "j0k3r/graby",
|
||||
|
@ -1671,20 +2276,19 @@
|
|||
},
|
||||
{
|
||||
"name": "j0k3r/php-readability",
|
||||
"version": "v1.0.8",
|
||||
"version": "v1.0.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/j0k3r/php-readability.git",
|
||||
"reference": "f71c3a419623f821c245e0a003edfbf2c67f278e"
|
||||
"reference": "41d7440c6e6130bacd50808342fe566e28f536fb"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/j0k3r/php-readability/zipball/f71c3a419623f821c245e0a003edfbf2c67f278e",
|
||||
"reference": "f71c3a419623f821c245e0a003edfbf2c67f278e",
|
||||
"url": "https://api.github.com/repos/j0k3r/php-readability/zipball/41d7440c6e6130bacd50808342fe566e28f536fb",
|
||||
"reference": "41d7440c6e6130bacd50808342fe566e28f536fb",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-tidy": ">=1.2",
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"type": "library",
|
||||
|
@ -1730,7 +2334,7 @@
|
|||
"extraction",
|
||||
"html"
|
||||
],
|
||||
"time": "2015-09-23 19:09:38"
|
||||
"time": "2015-11-10 08:55:29"
|
||||
},
|
||||
{
|
||||
"name": "j0k3r/safecurl",
|
||||
|
@ -2057,6 +2661,124 @@
|
|||
],
|
||||
"time": "2013-12-05 14:36:11"
|
||||
},
|
||||
{
|
||||
"name": "kphoen/rulerz",
|
||||
"version": "0.14.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/K-Phoen/rulerz.git",
|
||||
"reference": "608649b148ffdf3437600cc0f450d59b0579148d"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/K-Phoen/rulerz/zipball/608649b148ffdf3437600cc0f450d59b0579148d",
|
||||
"reference": "608649b148ffdf3437600cc0f450d59b0579148d",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"hoa/ruler": "~1.0",
|
||||
"php": ">=5.4",
|
||||
"symfony/property-access": "~2.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"behat/behat": "~3.0",
|
||||
"coduo/phpspec-data-provider-extension": "~1.0,!=1.0.2",
|
||||
"doctrine/orm": "~2.4",
|
||||
"elasticsearch/elasticsearch": "~1.0",
|
||||
"illuminate/database": "~5.0",
|
||||
"mikey179/vfsstream": "~1.4",
|
||||
"phpspec/phpspec": "~2.0",
|
||||
"pomm-project/cli": "~2.0@dev",
|
||||
"pomm-project/foundation": "~2.0@dev",
|
||||
"pomm-project/model-manager": "~2.0.@dev",
|
||||
"ruflin/elastica": "~1.0",
|
||||
"vlucas/phpdotenv": "~2.1"
|
||||
},
|
||||
"suggest": {
|
||||
"doctrine/orm": "To execute rules as Doctrine queries",
|
||||
"elasticsearch/elasticsearch": "To execute rules as Elasticsearch queries",
|
||||
"kphoen/rulerz-spec-builder": "If you want a specification builder",
|
||||
"pomm-project/model-manager": "To execute rules as Pomm queries"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"RulerZ\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Kévin Gomez",
|
||||
"email": "contact@kevingomez.fr"
|
||||
}
|
||||
],
|
||||
"description": "Powerful implementation of the Specification pattern",
|
||||
"homepage": "https://github.com/K-Phoen/RulerZ",
|
||||
"keywords": [
|
||||
"doctrine",
|
||||
"specification"
|
||||
],
|
||||
"time": "2015-10-31 20:54:37"
|
||||
},
|
||||
{
|
||||
"name": "kphoen/rulerz-bundle",
|
||||
"version": "0.11.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/K-Phoen/RulerZBundle.git",
|
||||
"reference": "dcaaed69d8252fa1e3a25802f8cf697947570778"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/K-Phoen/RulerZBundle/zipball/dcaaed69d8252fa1e3a25802f8cf697947570778",
|
||||
"reference": "dcaaed69d8252fa1e3a25802f8cf697947570778",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"kphoen/rulerz": "~0.1, >=0.13.0",
|
||||
"symfony/framework-bundle": "~2.3|~3.0",
|
||||
"symfony/validator": "~2.3|~3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"matthiasnoback/symfony-dependency-injection-test": "~0.7",
|
||||
"mikey179/vfsstream": "~1.0",
|
||||
"phpunit/phpunit": "~4.8"
|
||||
},
|
||||
"type": "symfony-bundle",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"KPhoen\\RulerZBundle\\": ""
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Kévin Gomez",
|
||||
"email": "contact@kevingomez.fr"
|
||||
}
|
||||
],
|
||||
"description": "Symfony2 Bundle for RulerZ",
|
||||
"homepage": "https://github.com/K-Phoen/RulerZBundle",
|
||||
"keywords": [
|
||||
"doctrine",
|
||||
"ruler",
|
||||
"rulerz",
|
||||
"specification"
|
||||
],
|
||||
"time": "2015-11-13 13:00:14"
|
||||
},
|
||||
{
|
||||
"name": "kriswallsmith/assetic",
|
||||
"version": "v1.3.1",
|
||||
|
@ -3014,25 +3736,25 @@
|
|||
},
|
||||
{
|
||||
"name": "sensio/framework-extra-bundle",
|
||||
"version": "v3.0.10",
|
||||
"version": "v3.0.11",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sensiolabs/SensioFrameworkExtraBundle.git",
|
||||
"reference": "18fc2063c4d6569cdca47a39fbac32342eb65f3c"
|
||||
"reference": "a79e205737b58d557c05caef6dfa8f94d8084bca"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sensiolabs/SensioFrameworkExtraBundle/zipball/18fc2063c4d6569cdca47a39fbac32342eb65f3c",
|
||||
"reference": "18fc2063c4d6569cdca47a39fbac32342eb65f3c",
|
||||
"url": "https://api.github.com/repos/sensiolabs/SensioFrameworkExtraBundle/zipball/a79e205737b58d557c05caef6dfa8f94d8084bca",
|
||||
"reference": "a79e205737b58d557c05caef6dfa8f94d8084bca",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/common": "~2.2",
|
||||
"symfony/framework-bundle": "~2.3"
|
||||
"symfony/framework-bundle": "~2.3|~3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/expression-language": "~2.4",
|
||||
"symfony/security-bundle": "~2.4"
|
||||
"symfony/expression-language": "~2.4|~3.0",
|
||||
"symfony/security-bundle": "~2.4|~3.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/expression-language": "",
|
||||
|
@ -3065,7 +3787,7 @@
|
|||
"annotations",
|
||||
"controllers"
|
||||
],
|
||||
"time": "2015-08-03 11:59:27"
|
||||
"time": "2015-10-28 15:47:04"
|
||||
},
|
||||
{
|
||||
"name": "sensiolabs/security-checker",
|
||||
|
@ -4516,16 +5238,16 @@
|
|||
},
|
||||
{
|
||||
"name": "phpunit/phpunit",
|
||||
"version": "4.8.16",
|
||||
"version": "4.8.18",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/sebastianbergmann/phpunit.git",
|
||||
"reference": "625f8c345606ed0f3a141dfb88f4116f0e22978e"
|
||||
"reference": "fa33d4ad96481b91df343d83e8c8aabed6b1dfd3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/625f8c345606ed0f3a141dfb88f4116f0e22978e",
|
||||
"reference": "625f8c345606ed0f3a141dfb88f4116f0e22978e",
|
||||
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fa33d4ad96481b91df343d83e8c8aabed6b1dfd3",
|
||||
"reference": "fa33d4ad96481b91df343d83e8c8aabed6b1dfd3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -4584,7 +5306,7 @@
|
|||
"testing",
|
||||
"xunit"
|
||||
],
|
||||
"time": "2015-10-23 06:48:33"
|
||||
"time": "2015-11-11 11:32:49"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/phpunit-mock-objects",
|
||||
|
|
66
src/Wallabag/CoreBundle/Command/TagAllCommand.php
Normal file
66
src/Wallabag/CoreBundle/Command/TagAllCommand.php
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Command;
|
||||
|
||||
use Doctrine\ORM\NoResultException;
|
||||
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class TagAllCommand extends ContainerAwareCommand
|
||||
{
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setName('wallabag:tag:all')
|
||||
->setDescription('Tag all entries using the tagging rules.')
|
||||
->addArgument(
|
||||
'username',
|
||||
InputArgument::REQUIRED,
|
||||
'User to tag entries for.'
|
||||
)
|
||||
;
|
||||
}
|
||||
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
try {
|
||||
$user = $this->getUser($input->getArgument('username'));
|
||||
} catch (NoResultException $e) {
|
||||
$output->writeln(sprintf('<error>User %s not found.</error>', $input->getArgument('username')));
|
||||
|
||||
return 1;
|
||||
}
|
||||
$tagger = $this->getContainer()->get('wallabag_core.rule_based_tagger');
|
||||
|
||||
$output->write(sprintf('Tagging entries for user « <info>%s</info> »... ', $user->getUserName()));
|
||||
|
||||
$entries = $tagger->tagAllForUser($user);
|
||||
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
foreach ($entries as $entry) {
|
||||
$em->persist($entry);
|
||||
}
|
||||
$em->flush();
|
||||
|
||||
$output->writeln('<info>Done.</info>');
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a user from its username.
|
||||
*
|
||||
* @param string $username
|
||||
*
|
||||
* @return \Wallabag\UserBundle\Entity\User
|
||||
*/
|
||||
private function getUser($username)
|
||||
{
|
||||
return $this->getDoctrine()->getRepository('WallabagUserBundle:User')->findOneByUserName($username);
|
||||
}
|
||||
|
||||
private function getDoctrine()
|
||||
{
|
||||
return $this->getContainer()->get('doctrine');
|
||||
}
|
||||
}
|
|
@ -7,9 +7,11 @@ use Symfony\Bundle\FrameworkBundle\Controller\Controller;
|
|||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Wallabag\CoreBundle\Entity\Config;
|
||||
use Wallabag\CoreBundle\Entity\TaggingRule;
|
||||
use Wallabag\UserBundle\Entity\User;
|
||||
use Wallabag\CoreBundle\Form\Type\ChangePasswordType;
|
||||
use Wallabag\CoreBundle\Form\Type\UserInformationType;
|
||||
use Wallabag\CoreBundle\Form\Type\TaggingRuleType;
|
||||
use Wallabag\CoreBundle\Form\Type\NewUserType;
|
||||
use Wallabag\CoreBundle\Form\Type\RssType;
|
||||
use Wallabag\CoreBundle\Tools\Utils;
|
||||
|
@ -98,6 +100,24 @@ class ConfigController extends Controller
|
|||
return $this->redirect($this->generateUrl('config'));
|
||||
}
|
||||
|
||||
// handle tagging rule
|
||||
$taggingRule = new TaggingRule();
|
||||
$newTaggingRule = $this->createForm(new TaggingRuleType(), $taggingRule, array('action' => $this->generateUrl('config').'#set5'));
|
||||
$newTaggingRule->handleRequest($request);
|
||||
|
||||
if ($newTaggingRule->isValid()) {
|
||||
$taggingRule->setConfig($config);
|
||||
$em->persist($taggingRule);
|
||||
$em->flush();
|
||||
|
||||
$this->get('session')->getFlashBag()->add(
|
||||
'notice',
|
||||
'Tagging rules updated'
|
||||
);
|
||||
|
||||
return $this->redirect($this->generateUrl('config'));
|
||||
}
|
||||
|
||||
// handle adding new user
|
||||
$newUser = $userManager->createUser();
|
||||
// enable created user by default
|
||||
|
@ -136,6 +156,7 @@ class ConfigController extends Controller
|
|||
'pwd' => $pwdForm->createView(),
|
||||
'user' => $userForm->createView(),
|
||||
'new_user' => $newUserForm->createView(),
|
||||
'new_tagging_rule' => $newTaggingRule->createView(),
|
||||
),
|
||||
'rss' => array(
|
||||
'username' => $user->getUsername(),
|
||||
|
@ -167,6 +188,33 @@ class ConfigController extends Controller
|
|||
return $request->headers->get('referer') ? $this->redirect($request->headers->get('referer')) : $this->redirectToRoute('config');
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a tagging rule and redirect to the config homepage.
|
||||
*
|
||||
* @param TaggingRule $rule
|
||||
*
|
||||
* @Route("/tagging-rule/delete/{id}", requirements={"id" = "\d+"}, name="delete_tagging_rule")
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse
|
||||
*/
|
||||
public function deleteTaggingRule(TaggingRule $rule)
|
||||
{
|
||||
if ($this->getUser()->getId() != $rule->getConfig()->getUser()->getId()) {
|
||||
throw $this->createAccessDeniedException('You can not access this tagging ryle.');
|
||||
}
|
||||
|
||||
$em = $this->getDoctrine()->getManager();
|
||||
$em->remove($rule);
|
||||
$em->flush();
|
||||
|
||||
$this->get('session')->getFlashBag()->add(
|
||||
'notice',
|
||||
'Tagging rule deleted'
|
||||
);
|
||||
|
||||
return $this->redirect($this->generateUrl('config'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve config for the current user.
|
||||
* If no config were found, create a new one.
|
||||
|
|
|
@ -6,6 +6,7 @@ use Doctrine\Common\DataFixtures\AbstractFixture;
|
|||
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Wallabag\CoreBundle\Entity\Config;
|
||||
use Wallabag\CoreBundle\Entity\TaggingRule;
|
||||
|
||||
class LoadConfigData extends AbstractFixture implements OrderedFixtureInterface
|
||||
{
|
||||
|
@ -15,6 +16,13 @@ class LoadConfigData extends AbstractFixture implements OrderedFixtureInterface
|
|||
public function load(ObjectManager $manager)
|
||||
{
|
||||
$adminConfig = new Config($this->getReference('admin-user'));
|
||||
$taggingRule = new TaggingRule();
|
||||
|
||||
$taggingRule->setConfig($adminConfig);
|
||||
$taggingRule->setRule('title matches "wallabag"');
|
||||
$taggingRule->setTags(['wallabag']);
|
||||
$manager->persist($taggingRule);
|
||||
|
||||
$adminConfig->setTheme('material');
|
||||
$adminConfig->setItemsPerPage(30);
|
||||
$adminConfig->setLanguage('en_US');
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Wallabag\CoreBundle\Entity;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
|
||||
|
@ -76,12 +77,19 @@ class Config
|
|||
*/
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="Wallabag\CoreBundle\Entity\TaggingRule", mappedBy="config", cascade={"remove"})
|
||||
* @ORM\OrderBy({"id" = "ASC"})
|
||||
*/
|
||||
private $taggingRules;
|
||||
|
||||
/*
|
||||
* @param User $user
|
||||
*/
|
||||
public function __construct(\Wallabag\UserBundle\Entity\User $user)
|
||||
{
|
||||
$this->user = $user;
|
||||
$this->taggingRules = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -237,4 +245,24 @@ class Config
|
|||
{
|
||||
return $this->rssLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param TaggingRule $rule
|
||||
*
|
||||
* @return Config
|
||||
*/
|
||||
public function addTaggingRule(TaggingRule $rule)
|
||||
{
|
||||
$this->taggingRules[] = $rule;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ArrayCollection<TaggingRule>
|
||||
*/
|
||||
public function getTaggingRules()
|
||||
{
|
||||
return $this->taggingRules;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -458,6 +458,10 @@ class Entry
|
|||
*/
|
||||
public function addTag(Tag $tag)
|
||||
{
|
||||
if ($this->tags->contains($tag)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->tags[] = $tag;
|
||||
$tag->addEntry($this);
|
||||
}
|
||||
|
|
133
src/Wallabag/CoreBundle/Entity/TaggingRule.php
Normal file
133
src/Wallabag/CoreBundle/Entity/TaggingRule.php
Normal file
|
@ -0,0 +1,133 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Entity;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Symfony\Component\Validator\Constraints as Assert;
|
||||
use KPhoen\RulerZBundle\Validator\Constraints as RulerZAssert;
|
||||
|
||||
/**
|
||||
* Tagging rule.
|
||||
*
|
||||
* @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\TaggingRuleRepository")
|
||||
* @ORM\Table
|
||||
* @ORM\Entity
|
||||
*/
|
||||
class TaggingRule
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*
|
||||
* @ORM\Column(name="id", type="integer")
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue(strategy="AUTO")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*
|
||||
* @Assert\NotBlank()
|
||||
* @RulerZAssert\ValidRule(
|
||||
* allowed_variables={"title", "url", "isArchived", "isStared", "content", "language", "mimetype", "readingTime", "domainName"},
|
||||
* allowed_operators={">", "<", ">=", "<=", "=", "is", "!=", "and", "not", "or", "matches"}
|
||||
* )
|
||||
* @ORM\Column(name="rule", type="string", nullable=false)
|
||||
*/
|
||||
private $rule;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*
|
||||
* @Assert\NotBlank()
|
||||
* @ORM\Column(name="tags", type="simple_array", nullable=false)
|
||||
*/
|
||||
private $tags = [];
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="Wallabag\CoreBundle\Entity\Config", inversedBy="taggingRules")
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* Get id.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set rule.
|
||||
*
|
||||
* @param string $rule
|
||||
*
|
||||
* @return TaggingRule
|
||||
*/
|
||||
public function setRule($rule)
|
||||
{
|
||||
$this->rule = $rule;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get rule.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getRule()
|
||||
{
|
||||
return $this->rule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set tags.
|
||||
*
|
||||
* @param array<string> $tags
|
||||
*
|
||||
* @return TaggingRule
|
||||
*/
|
||||
public function setTags(array $tags)
|
||||
{
|
||||
$this->tags = $tags;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tags.
|
||||
*
|
||||
* @return array<string>
|
||||
*/
|
||||
public function getTags()
|
||||
{
|
||||
return $this->tags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set config.
|
||||
*
|
||||
* @param Config $config
|
||||
*
|
||||
* @return TaggingRule
|
||||
*/
|
||||
public function setConfig(Config $config)
|
||||
{
|
||||
$this->config = $config;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get config.
|
||||
*
|
||||
* @return Config
|
||||
*/
|
||||
public function getConfig()
|
||||
{
|
||||
return $this->config;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Form\DataTransformer;
|
||||
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Symfony\Component\Form\DataTransformerInterface;
|
||||
use Symfony\Component\Form\Exception\TransformationFailedException;
|
||||
|
||||
/**
|
||||
* Transforms a comma-separated list to a proper PHP array.
|
||||
* Example: the string "foo, bar" will become the array ["foo", "bar"]
|
||||
*/
|
||||
class StringToListTransformer implements DataTransformerInterface
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $separator;
|
||||
|
||||
/**
|
||||
* @param string $separator The separator used in the list.
|
||||
*/
|
||||
public function __construct($separator = ',')
|
||||
{
|
||||
$this->separator = $separator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a list to a string.
|
||||
*
|
||||
* @param array|null $list
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function transform($list)
|
||||
{
|
||||
if (null === $list) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return implode($this->separator, $list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a string to a list.
|
||||
*
|
||||
* @param string $string
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function reverseTransform($string)
|
||||
{
|
||||
if ($string === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return array_values(array_filter(array_map('trim', explode($this->separator, $string))));
|
||||
}
|
||||
}
|
38
src/Wallabag/CoreBundle/Form/Type/TaggingRuleType.php
Normal file
38
src/Wallabag/CoreBundle/Form/Type/TaggingRuleType.php
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Form\Type;
|
||||
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
use Wallabag\CoreBundle\Form\DataTransformer\StringToListTransformer;
|
||||
|
||||
class TaggingRuleType extends AbstractType
|
||||
{
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
->add('rule', 'text', array('required' => true))
|
||||
->add('save', 'submit')
|
||||
;
|
||||
|
||||
$tagsField = $builder
|
||||
->create('tags', 'text')
|
||||
->addModelTransformer(new StringToListTransformer(','));
|
||||
|
||||
$builder->add($tagsField);
|
||||
}
|
||||
|
||||
public function configureOptions(OptionsResolver $resolver)
|
||||
{
|
||||
$resolver->setDefaults(array(
|
||||
'data_class' => 'Wallabag\CoreBundle\Entity\TaggingRule',
|
||||
));
|
||||
}
|
||||
|
||||
public function getName()
|
||||
{
|
||||
return 'tagging_rule';
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
namespace Wallabag\CoreBundle\Helper;
|
||||
|
||||
use Graby\Graby;
|
||||
use Psr\Log\LoggerInterface as Logger;
|
||||
use Wallabag\CoreBundle\Entity\Entry;
|
||||
use Wallabag\CoreBundle\Tools\Utils;
|
||||
|
||||
|
@ -13,10 +14,14 @@ use Wallabag\CoreBundle\Tools\Utils;
|
|||
class ContentProxy
|
||||
{
|
||||
protected $graby;
|
||||
protected $tagger;
|
||||
protected $logger;
|
||||
|
||||
public function __construct(Graby $graby)
|
||||
public function __construct(Graby $graby, RuleBasedTagger $tagger, Logger $logger)
|
||||
{
|
||||
$this->graby = $graby;
|
||||
$this->graby = $graby;
|
||||
$this->tagger = $tagger;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,6 +64,15 @@ class ContentProxy
|
|||
$entry->setPreviewPicture($content['open_graph']['og_image']);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->tagger->tag($entry);
|
||||
} catch (\Exception $e) {
|
||||
$this->logger->error('Error while trying to automatically tag an entry.', array(
|
||||
'entry_url' => $url,
|
||||
'error_msg' => $e->getMessage(),
|
||||
));
|
||||
}
|
||||
|
||||
return $entry;
|
||||
}
|
||||
}
|
||||
|
|
108
src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php
Normal file
108
src/Wallabag/CoreBundle/Helper/RuleBasedTagger.php
Normal file
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Helper;
|
||||
|
||||
use RulerZ\RulerZ;
|
||||
|
||||
use Wallabag\CoreBundle\Entity\Entry;
|
||||
use Wallabag\CoreBundle\Entity\Tag;
|
||||
use Wallabag\CoreBundle\Repository\EntryRepository;
|
||||
use Wallabag\CoreBundle\Repository\TagRepository;
|
||||
use Wallabag\UserBundle\Entity\User;
|
||||
|
||||
class RuleBasedTagger
|
||||
{
|
||||
private $rulerz;
|
||||
private $tagRepository;
|
||||
private $entryRepository;
|
||||
|
||||
public function __construct(RulerZ $rulerz, TagRepository $tagRepository, EntryRepository $entryRepository)
|
||||
{
|
||||
$this->rulerz = $rulerz;
|
||||
$this->tagRepository = $tagRepository;
|
||||
$this->entryRepository = $entryRepository;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add tags from rules defined by the user.
|
||||
*
|
||||
* @param Entry $entry Entry to tag.
|
||||
*/
|
||||
public function tag(Entry $entry)
|
||||
{
|
||||
$rules = $this->getRulesForUser($entry->getUser());
|
||||
|
||||
foreach ($rules as $rule) {
|
||||
if (!$this->rulerz->satisfies($entry, $rule->getRule())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($rule->getTags() as $label) {
|
||||
$tag = $this->getTag($entry->getUser(), $label);
|
||||
|
||||
$entry->addTag($tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply all the tagging rules defined by a user on its entries.
|
||||
*
|
||||
* @param User $user
|
||||
*
|
||||
* @return array<Entry> A list of modified entries.
|
||||
*/
|
||||
public function tagAllForUser(User $user)
|
||||
{
|
||||
$rules = $this->getRulesForUser($user);
|
||||
$entries = array();
|
||||
|
||||
foreach ($rules as $rule) {
|
||||
$qb = $this->entryRepository->getBuilderForAllByUser($user->getId());
|
||||
$entries = $this->rulerz->filter($qb, $rule->getRule());
|
||||
|
||||
foreach ($entries as $entry) {
|
||||
foreach ($rule->getTags() as $label) {
|
||||
$tag = $this->getTag($user, $label);
|
||||
|
||||
$entry->addTag($tag);
|
||||
$entries[] = $entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a tag for a user.
|
||||
*
|
||||
* @param User $user
|
||||
* @param string $label The tag's label.
|
||||
*
|
||||
* @return Tag
|
||||
*/
|
||||
private function getTag(User $user, $label)
|
||||
{
|
||||
$tag = $this->tagRepository->findOneByLabelAndUserId($label, $user->getId());
|
||||
|
||||
if (!$tag) {
|
||||
$tag = new Tag($user);
|
||||
$tag->setLabel($label);
|
||||
}
|
||||
|
||||
return $tag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the tagging rules for a given user.
|
||||
*
|
||||
* @param User $user
|
||||
*
|
||||
* @return array<TaggingRule>
|
||||
*/
|
||||
private function getRulesForUser(User $user)
|
||||
{
|
||||
return $user->getConfig()->getTaggingRules();
|
||||
}
|
||||
}
|
25
src/Wallabag/CoreBundle/Operator/Doctrine/Matches.php
Normal file
25
src/Wallabag/CoreBundle/Operator/Doctrine/Matches.php
Normal file
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Operator\Doctrine;
|
||||
|
||||
/**
|
||||
* Provides a "matches" operator used for tagging rules.
|
||||
*
|
||||
* It asserts that a given pattern is contained in a subject, in a
|
||||
* case-insensitive way.
|
||||
*
|
||||
* This operator will be used to compile tagging rules in DQL, usable
|
||||
* by Doctrine ORM.
|
||||
* It's registered in RulerZ using a service (wallabag.operator.doctrine.matches);
|
||||
*/
|
||||
class Matches
|
||||
{
|
||||
public function __invoke($subject, $pattern)
|
||||
{
|
||||
if ($pattern[0] === "'") {
|
||||
$pattern = sprintf("'%%%s%%'", substr($pattern, 1, -1));
|
||||
}
|
||||
|
||||
return sprintf('UPPER(%s) LIKE UPPER(%s)', $subject, $pattern);
|
||||
}
|
||||
}
|
21
src/Wallabag/CoreBundle/Operator/PHP/Matches.php
Normal file
21
src/Wallabag/CoreBundle/Operator/PHP/Matches.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Operator\PHP;
|
||||
|
||||
/**
|
||||
* Provides a "matches" operator used for tagging rules.
|
||||
*
|
||||
* It asserts that a given pattern is contained in a subject, in a
|
||||
* case-insensitive way.
|
||||
*
|
||||
* This operator will be used to compile tagging rules in PHP, usable
|
||||
* directly on Entry objects for instance.
|
||||
* It's registered in RulerZ using a service (wallabag.operator.array.matches);
|
||||
*/
|
||||
class Matches
|
||||
{
|
||||
public function __invoke($subject, $pattern)
|
||||
{
|
||||
return stripos($subject, $pattern) !== false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Repository;
|
||||
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
|
||||
class TaggingRuleRepository extends EntityRepository
|
||||
{
|
||||
}
|
|
@ -53,6 +53,27 @@ services:
|
|||
class: Wallabag\CoreBundle\Helper\ContentProxy
|
||||
arguments:
|
||||
- @wallabag_core.graby
|
||||
- @wallabag_core.rule_based_tagger
|
||||
- @logger
|
||||
|
||||
wallabag_core.rule_based_tagger:
|
||||
class: Wallabag\CoreBundle\Helper\RuleBasedTagger
|
||||
arguments:
|
||||
- @rulerz
|
||||
- @wallabag_core.tag_repository
|
||||
- @wallabag_core.entry_repository
|
||||
|
||||
wallabag_core.entry_repository:
|
||||
class: Wallabag\CoreBundle\Repository\EntryRepository
|
||||
factory: [ @doctrine.orm.default_entity_manager, getRepository ]
|
||||
arguments:
|
||||
- WallabagCoreBundle:Entry
|
||||
|
||||
wallabag_core.tag_repository:
|
||||
class: Wallabag\CoreBundle\Repository\TagRepository
|
||||
factory: [ @doctrine.orm.default_entity_manager, getRepository ]
|
||||
arguments:
|
||||
- WallabagCoreBundle:Tag
|
||||
|
||||
wallabag_core.registration_confirmed:
|
||||
class: Wallabag\CoreBundle\EventListener\RegistrationConfirmedListener
|
||||
|
@ -70,3 +91,13 @@ services:
|
|||
arguments:
|
||||
- %wallabag_url%
|
||||
- src/Wallabag/CoreBundle/Resources/views/themes/_global/public/img/appicon/apple-touch-icon-152.png
|
||||
|
||||
wallabag.operator.array.matches:
|
||||
class: Wallabag\CoreBundle\Operator\PHP\Matches
|
||||
tags:
|
||||
- { name: rulerz.operator, executor: rulerz.executor.array, operator: matches }
|
||||
|
||||
wallabag.operator.doctrine.matches:
|
||||
class: Wallabag\CoreBundle\Operator\Doctrine\Matches
|
||||
tags:
|
||||
- { name: rulerz.operator, executor: rulerz.executor.doctrine, operator: matches, inline: true }
|
||||
|
|
|
@ -145,6 +145,39 @@
|
|||
{{ form_rest(form.pwd) }}
|
||||
</form>
|
||||
|
||||
<h2>{% trans %}Tagging rules{% endtrans %}</h2>
|
||||
|
||||
<ul>
|
||||
{% for tagging_rule in app.user.config.taggingRules %}
|
||||
<li>
|
||||
if « {{ tagging_rule.rule }} » then tag as « {{ tagging_rule.tags|join(', ') }} »
|
||||
<a href="{{ path('delete_tagging_rule', {id: tagging_rule.id}) }}" title="{% trans %}Delete{% endtrans %}" class="tool delete icon-trash icon"></a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
<form action="{{ path('config') }}" method="post" {{ form_enctype(form.new_tagging_rule) }}>
|
||||
{{ form_errors(form.new_tagging_rule) }}
|
||||
|
||||
<fieldset class="w500p inline">
|
||||
<div class="row">
|
||||
{{ form_label(form.new_tagging_rule.rule) }}
|
||||
{{ form_errors(form.new_tagging_rule.rule) }}
|
||||
{{ form_widget(form.new_tagging_rule.rule) }}
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<fieldset class="w500p inline">
|
||||
<div class="row">
|
||||
{{ form_label(form.new_tagging_rule.tags) }}
|
||||
{{ form_errors(form.new_tagging_rule.tags) }}
|
||||
{{ form_widget(form.new_tagging_rule.tags) }}
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
{{ form_rest(form.new_tagging_rule) }}
|
||||
</form>
|
||||
|
||||
{% if is_granted('ROLE_SUPER_ADMIN') %}
|
||||
<h2>{% trans %}Add a user{% endtrans %}</h2>
|
||||
|
||||
|
|
|
@ -15,8 +15,9 @@
|
|||
<li class="tab col s3"><a href="#set2">{% trans %}RSS{% endtrans %}</a></li>
|
||||
<li class="tab col s3"><a href="#set3">{% trans %}User information{% endtrans %}</a></li>
|
||||
<li class="tab col s3"><a href="#set4">{% trans %}Password{% endtrans %}</a></li>
|
||||
<li class="tab col s3"><a href="#set5">{% trans %}Tagging rules{% endtrans %}</a></li>
|
||||
{% if is_granted('ROLE_SUPER_ADMIN') %}
|
||||
<li class="tab col s3"><a href="#set5">{% trans %}Add a user{% endtrans %}</a></li>
|
||||
<li class="tab col s3"><a href="#set6">{% trans %}Add a user{% endtrans %}</a></li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -183,8 +184,155 @@
|
|||
</form>
|
||||
</div>
|
||||
|
||||
{% if is_granted('ROLE_SUPER_ADMIN') %}
|
||||
<div id="set5" class="col s12">
|
||||
<div class="row">
|
||||
<div class="input-field col s12">
|
||||
<ul>
|
||||
{% for tagging_rule in app.user.config.taggingRules %}
|
||||
<li>
|
||||
if « {{ tagging_rule.rule }} » then tag as « {{ tagging_rule.tags|join(', ') }} »
|
||||
<a href="{{ path('delete_tagging_rule', {id: tagging_rule.id}) }}" title="{% trans %}Delete{% endtrans %}">
|
||||
<i class="tool grey-text delete mdi-action-delete"></i>
|
||||
</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{ form_start(form.new_tagging_rule) }}
|
||||
{{ form_errors(form.new_tagging_rule) }}
|
||||
|
||||
<div class="row">
|
||||
<div class="input-field col s12">
|
||||
{{ form_label(form.new_tagging_rule.rule) }}
|
||||
{{ form_errors(form.new_tagging_rule.rule) }}
|
||||
{{ form_widget(form.new_tagging_rule.rule) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="input-field col s12">
|
||||
{{ form_label(form.new_tagging_rule.tags) }}
|
||||
{{ form_errors(form.new_tagging_rule.tags) }}
|
||||
{{ form_widget(form.new_tagging_rule.tags) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hidden">{{ form_rest(form.new_tagging_rule) }}</div>
|
||||
<button class="btn waves-effect waves-light" type="submit" name="action">
|
||||
{% trans %}Save{% endtrans %}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="row">
|
||||
<div class="input-field col s12">
|
||||
<h4>{% trans %}FAQ{% endtrans %}</h4>
|
||||
|
||||
<h5>{% trans %}What does « tagging rules » mean?{% endtrans %}</h5>
|
||||
<p class="help">
|
||||
{% trans %}
|
||||
They are rules used by Wallabag to automatically tag new entries.<br />
|
||||
Each time a new entry is added, all the tagging rules will be used to add
|
||||
the tags you configured, thus saving you the trouble to manually classify
|
||||
your entries.
|
||||
{% endtrans %}
|
||||
</p>
|
||||
|
||||
<h5>{% trans %}How do I use them?{% endtrans %}</h5>
|
||||
<p class="help">
|
||||
{% trans %}
|
||||
Let assume you want to tag new entries as « <i>short reading</i> » when the reading time is inferior to 3 minutes.<br />
|
||||
In that case, you should put « readingTime <= 3 » in the <i>Rule</i> field and « <i>short reading</i> » in the <i>Tags</i>
|
||||
field.<br />
|
||||
Several tags can added simultaneously by separating them by a comma: « <i>short reading, must read</i> »<br />
|
||||
Complex rules can be written by using predefined operators: if « <i>readingTime >= 5 AND domainName = "github.com"</i> » then tag as « <i>long reading, github </i> »
|
||||
{% endtrans %}
|
||||
</p>
|
||||
|
||||
<h5>{% trans %}Which variables and operators can I use to write rules?{% endtrans %}</h5>
|
||||
<p class="help">
|
||||
{% trans %}The following variables and operators can be used to create tagging rules:{% endtrans %}
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{% trans %}Variable{% endtrans %}</th>
|
||||
<th>{% trans %}Meaning{% endtrans %}</th>
|
||||
<th>{% trans %}Operator{% endtrans %}</th>
|
||||
<th>{% trans %}Meaning{% endtrans %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>title</td>
|
||||
<td>{% trans %}Title of the entry{% endtrans %}</td>
|
||||
<td><=</td>
|
||||
<td>{% trans %}Less than…{% endtrans %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>url</td>
|
||||
<td>{% trans %}URL of the entry{% endtrans %}</td>
|
||||
<td><</td>
|
||||
<td>{% trans %}Strictly less than…{% endtrans %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>isArchived</td>
|
||||
<td>{% trans %}Whether the entry is archived or not{% endtrans %}</td>
|
||||
<td>=></td>
|
||||
<td>{% trans %}Greater than…{% endtrans %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>isStared</td>
|
||||
<td>{% trans %}Whether the entry is starred or not{% endtrans %}</td>
|
||||
<td>></td>
|
||||
<td>{% trans %}Strictly greater than…{% endtrans %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>content</td>
|
||||
<td>{% trans %}The entry's content{% endtrans %}</td>
|
||||
<td>=</td>
|
||||
<td>{% trans %}Equal to…{% endtrans %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>language</td>
|
||||
<td>{% trans %}The entry's language{% endtrans %}</td>
|
||||
<td>!=</td>
|
||||
<td>{% trans %}Not equal to…{% endtrans %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>mimetype</td>
|
||||
<td>{% trans %}The entry's mime-type{% endtrans %}</td>
|
||||
<td>OR</td>
|
||||
<td>{% trans %}One rule or another{% endtrans %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>readingTime</td>
|
||||
<td>{% trans %}The estimated entry's reading time, in minutes{% endtrans %}</td>
|
||||
<td>AND</td>
|
||||
<td>{% trans %}One rule and another{% endtrans %}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>domainName</td>
|
||||
<td>{% trans %}The domain name of the entry{% endtrans %}</td>
|
||||
<td>matches</td>
|
||||
<td>
|
||||
{% trans %}
|
||||
Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />
|
||||
Example: <code>title matches "football"</code>
|
||||
{% endtrans %}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if is_granted('ROLE_SUPER_ADMIN') %}
|
||||
<div id="set6" class="col s12">
|
||||
{{ form_start(form.new_user) }}
|
||||
{{ form_errors(form.new_user) }}
|
||||
|
||||
|
|
|
@ -479,4 +479,59 @@ class ConfigControllerTest extends WallabagCoreTestCase
|
|||
$this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(array('_text')));
|
||||
$this->assertContains($expectedMessage, $alert[0]);
|
||||
}
|
||||
|
||||
public function testTaggingRuleCreation()
|
||||
{
|
||||
$this->logInAs('admin');
|
||||
$client = $this->getClient();
|
||||
|
||||
$crawler = $client->request('GET', '/config');
|
||||
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
|
||||
$form = $crawler->filter('button[id=tagging_rule_save]')->form();
|
||||
|
||||
$data = array(
|
||||
'tagging_rule[rule]' => 'readingTime <= 3',
|
||||
'tagging_rule[tags]' => 'short reading',
|
||||
);
|
||||
|
||||
$client->submit($form, $data);
|
||||
|
||||
$this->assertEquals(302, $client->getResponse()->getStatusCode());
|
||||
|
||||
$crawler = $client->followRedirect();
|
||||
|
||||
$this->assertGreaterThan(1, $alert = $crawler->filter('div.messages.success')->extract(array('_text')));
|
||||
$this->assertContains('Tagging rules updated', $alert[0]);
|
||||
|
||||
$deleteLink = $crawler->filter('.delete')->last()->link();
|
||||
|
||||
$crawler = $client->click($deleteLink);
|
||||
$this->assertEquals(302, $client->getResponse()->getStatusCode());
|
||||
|
||||
$crawler = $client->followRedirect();
|
||||
$this->assertGreaterThan(1, $alert = $crawler->filter('div.messages.success')->extract(array('_text')));
|
||||
$this->assertContains('Tagging rule deleted', $alert[0]);
|
||||
}
|
||||
|
||||
public function dataForTaggingRuleFailed()
|
||||
{
|
||||
return array(
|
||||
array(
|
||||
array(
|
||||
'rss_config[rule]' => 'unknownVar <= 3',
|
||||
'rss_config[tags]' => 'cool tag',
|
||||
),
|
||||
'The variable « unknownVar » does not exist.',
|
||||
),
|
||||
array(
|
||||
array(
|
||||
'rss_config[rule]' => 'length(domainName) <= 42',
|
||||
'rss_config[tags]' => 'cool tag',
|
||||
),
|
||||
'The operator « length » does not exist.',
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,6 +102,44 @@ class EntryControllerTest extends WallabagCoreTestCase
|
|||
$this->assertContains('Google', $alert[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* This test will require an internet connection.
|
||||
*/
|
||||
public function testPostNewThatWillBeTaggued()
|
||||
{
|
||||
$this->logInAs('admin');
|
||||
$client = $this->getClient();
|
||||
|
||||
$crawler = $client->request('GET', '/new');
|
||||
|
||||
$this->assertEquals(200, $client->getResponse()->getStatusCode());
|
||||
|
||||
$form = $crawler->filter('button[type=submit]')->form();
|
||||
|
||||
$data = array(
|
||||
'entry[url]' => $url = 'https://github.com/wallabag/wallabag',
|
||||
);
|
||||
|
||||
$client->submit($form, $data);
|
||||
|
||||
$this->assertEquals(302, $client->getResponse()->getStatusCode());
|
||||
|
||||
$crawler = $client->followRedirect();
|
||||
|
||||
$em = $client->getContainer()
|
||||
->get('doctrine.orm.entity_manager');
|
||||
$entry = $em
|
||||
->getRepository('WallabagCoreBundle:Entry')
|
||||
->findOneByUrl($url);
|
||||
$tags = $entry->getTags();
|
||||
|
||||
$this->assertCount(1, $tags);
|
||||
$this->assertEquals('wallabag', $tags[0]->getLabel());
|
||||
|
||||
$em->remove($entry);
|
||||
$em->flush();
|
||||
}
|
||||
|
||||
public function testArchive()
|
||||
{
|
||||
$this->logInAs('admin');
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Tests\Form\DataTransformer;
|
||||
|
||||
use Wallabag\CoreBundle\Form\DataTransformer\StringToListTransformer;
|
||||
|
||||
class StringToListTransformerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
/**
|
||||
* @dataProvider transformProvider
|
||||
*/
|
||||
public function testTransformWithValidData($inputData, $expectedResult)
|
||||
{
|
||||
$transformer = new StringToListTransformer();
|
||||
|
||||
$this->assertSame($expectedResult, $transformer->transform($inputData));
|
||||
}
|
||||
|
||||
public function transformProvider()
|
||||
{
|
||||
return array(
|
||||
array( null, '' ),
|
||||
array( array(), '' ),
|
||||
array( array('single value'), 'single value' ),
|
||||
array( array('first value', 'second value'), 'first value,second value' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider reverseTransformProvider
|
||||
*/
|
||||
public function testReverseTransformWithValidData($inputData, $expectedResult)
|
||||
{
|
||||
$transformer = new StringToListTransformer();
|
||||
|
||||
$this->assertSame($expectedResult, $transformer->reverseTransform($inputData));
|
||||
}
|
||||
|
||||
public function reverseTransformProvider()
|
||||
{
|
||||
return array(
|
||||
array( null, null ),
|
||||
array( '', array() ),
|
||||
array( 'single value', array('single value') ),
|
||||
array( 'first value,second value', array('first value', 'second value') ),
|
||||
array( 'first value, second value', array('first value', 'second value') ),
|
||||
array( 'first value, , second value', array('first value', 'second value') ),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
namespace Wallabag\CoreBundle\Tests\Helper;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
|
||||
use Psr\Log\NullLogger;
|
||||
|
||||
use Wallabag\CoreBundle\Entity\Entry;
|
||||
use Wallabag\UserBundle\Entity\User;
|
||||
use Wallabag\CoreBundle\Helper\ContentProxy;
|
||||
|
@ -10,6 +13,10 @@ class ContentProxyTest extends \PHPUnit_Framework_TestCase
|
|||
{
|
||||
public function testWithEmptyContent()
|
||||
{
|
||||
$tagger = $this->getTaggerMock();
|
||||
$tagger->expects($this->once())
|
||||
->method('tag');
|
||||
|
||||
$graby = $this->getMockBuilder('Graby\Graby')
|
||||
->setMethods(array('fetchContent'))
|
||||
->disableOriginalConstructor()
|
||||
|
@ -25,7 +32,7 @@ class ContentProxyTest extends \PHPUnit_Framework_TestCase
|
|||
'language' => '',
|
||||
));
|
||||
|
||||
$proxy = new ContentProxy($graby);
|
||||
$proxy = new ContentProxy($graby, $tagger, $this->getLogger());
|
||||
$entry = $proxy->updateEntry(new Entry(new User()), 'http://0.0.0.0');
|
||||
|
||||
$this->assertEquals('http://0.0.0.0', $entry->getUrl());
|
||||
|
@ -40,6 +47,10 @@ class ContentProxyTest extends \PHPUnit_Framework_TestCase
|
|||
|
||||
public function testWithEmptyContentButOG()
|
||||
{
|
||||
$tagger = $this->getTaggerMock();
|
||||
$tagger->expects($this->once())
|
||||
->method('tag');
|
||||
|
||||
$graby = $this->getMockBuilder('Graby\Graby')
|
||||
->setMethods(array('fetchContent'))
|
||||
->disableOriginalConstructor()
|
||||
|
@ -59,7 +70,7 @@ class ContentProxyTest extends \PHPUnit_Framework_TestCase
|
|||
),
|
||||
));
|
||||
|
||||
$proxy = new ContentProxy($graby);
|
||||
$proxy = new ContentProxy($graby, $tagger, $this->getLogger());
|
||||
$entry = $proxy->updateEntry(new Entry(new User()), 'http://domain.io');
|
||||
|
||||
$this->assertEquals('http://domain.io', $entry->getUrl());
|
||||
|
@ -74,6 +85,10 @@ class ContentProxyTest extends \PHPUnit_Framework_TestCase
|
|||
|
||||
public function testWithContent()
|
||||
{
|
||||
$tagger = $this->getTaggerMock();
|
||||
$tagger->expects($this->once())
|
||||
->method('tag');
|
||||
|
||||
$graby = $this->getMockBuilder('Graby\Graby')
|
||||
->setMethods(array('fetchContent'))
|
||||
->disableOriginalConstructor()
|
||||
|
@ -94,7 +109,7 @@ class ContentProxyTest extends \PHPUnit_Framework_TestCase
|
|||
),
|
||||
));
|
||||
|
||||
$proxy = new ContentProxy($graby);
|
||||
$proxy = new ContentProxy($graby, $tagger, $this->getLogger());
|
||||
$entry = $proxy->updateEntry(new Entry(new User()), 'http://0.0.0.0');
|
||||
|
||||
$this->assertEquals('http://1.1.1.1', $entry->getUrl());
|
||||
|
@ -106,4 +121,17 @@ class ContentProxyTest extends \PHPUnit_Framework_TestCase
|
|||
$this->assertEquals(4.0, $entry->getReadingTime());
|
||||
$this->assertEquals('1.1.1.1', $entry->getDomainName());
|
||||
}
|
||||
|
||||
private function getTaggerMock()
|
||||
{
|
||||
return $this->getMockBuilder('Wallabag\CoreBundle\Helper\RuleBasedTagger')
|
||||
->setMethods(array('tag'))
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
}
|
||||
|
||||
private function getLogger()
|
||||
{
|
||||
return new NullLogger();
|
||||
}
|
||||
}
|
||||
|
|
167
src/Wallabag/CoreBundle/Tests/Helper/RuleBasedTaggerTest.php
Normal file
167
src/Wallabag/CoreBundle/Tests/Helper/RuleBasedTaggerTest.php
Normal file
|
@ -0,0 +1,167 @@
|
|||
<?php
|
||||
|
||||
namespace Wallabag\CoreBundle\Tests\Helper;
|
||||
|
||||
use Wallabag\CoreBundle\Entity\Config;
|
||||
use Wallabag\CoreBundle\Entity\Entry;
|
||||
use Wallabag\CoreBundle\Entity\Tag;
|
||||
use Wallabag\CoreBundle\Entity\TaggingRule;
|
||||
use Wallabag\UserBundle\Entity\User;
|
||||
use Wallabag\CoreBundle\Helper\RuleBasedTagger;
|
||||
|
||||
class RuleBasedTaggerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
private $rulerz;
|
||||
private $tagRepository;
|
||||
private $entryRepository;
|
||||
private $tagger;
|
||||
|
||||
public function setUp()
|
||||
{
|
||||
$this->rulerz = $this->getRulerZMock();
|
||||
$this->tagRepository = $this->getTagRepositoryMock();
|
||||
$this->entryRepository = $this->getEntryRepositoryMock();
|
||||
|
||||
$this->tagger = new RuleBasedTagger($this->rulerz, $this->tagRepository, $this->entryRepository);
|
||||
}
|
||||
|
||||
public function testTagWithNoRule()
|
||||
{
|
||||
$entry = new Entry($this->getUser());
|
||||
|
||||
$this->tagger->tag($entry);
|
||||
|
||||
$this->assertTrue($entry->getTags()->isEmpty());
|
||||
}
|
||||
|
||||
public function testTagWithNoMatchingRule()
|
||||
{
|
||||
$taggingRule = $this->getTaggingRule('rule as string', array('foo', 'bar'));
|
||||
$user = $this->getUser([$taggingRule]);
|
||||
$entry = new Entry($user);
|
||||
|
||||
$this->rulerz
|
||||
->expects($this->once())
|
||||
->method('satisfies')
|
||||
->with($entry, 'rule as string')
|
||||
->willReturn(false);
|
||||
|
||||
$this->tagger->tag($entry);
|
||||
|
||||
$this->assertTrue($entry->getTags()->isEmpty());
|
||||
}
|
||||
|
||||
public function testTagWithAMatchingRule()
|
||||
{
|
||||
$taggingRule = $this->getTaggingRule('rule as string', array('foo', 'bar'));
|
||||
$user = $this->getUser([$taggingRule]);
|
||||
$entry = new Entry($user);
|
||||
|
||||
$this->rulerz
|
||||
->expects($this->once())
|
||||
->method('satisfies')
|
||||
->with($entry, 'rule as string')
|
||||
->willReturn(true);
|
||||
|
||||
$this->tagger->tag($entry);
|
||||
|
||||
$this->assertFalse($entry->getTags()->isEmpty());
|
||||
|
||||
$tags = $entry->getTags();
|
||||
$this->assertSame('foo', $tags[0]->getLabel());
|
||||
$this->assertSame($user, $tags[0]->getUser());
|
||||
$this->assertSame('bar', $tags[1]->getLabel());
|
||||
$this->assertSame($user, $tags[1]->getUser());
|
||||
}
|
||||
|
||||
public function testTagWithAMixOfMatchingRules()
|
||||
{
|
||||
$taggingRule = $this->getTaggingRule('bla bla', array('hey'));
|
||||
$otherTaggingRule = $this->getTaggingRule('rule as string', array('foo'));
|
||||
|
||||
$user = $this->getUser([$taggingRule, $otherTaggingRule]);
|
||||
$entry = new Entry($user);
|
||||
|
||||
$this->rulerz
|
||||
->method('satisfies')
|
||||
->will($this->onConsecutiveCalls(false, true));
|
||||
|
||||
$this->tagger->tag($entry);
|
||||
|
||||
$this->assertFalse($entry->getTags()->isEmpty());
|
||||
|
||||
$tags = $entry->getTags();
|
||||
$this->assertSame('foo', $tags[0]->getLabel());
|
||||
$this->assertSame($user, $tags[0]->getUser());
|
||||
}
|
||||
|
||||
public function testWhenTheTagExists()
|
||||
{
|
||||
$taggingRule = $this->getTaggingRule('rule as string', array('foo'));
|
||||
$user = $this->getUser([$taggingRule]);
|
||||
$entry = new Entry($user);
|
||||
$tag = new Tag($user);
|
||||
|
||||
$this->rulerz
|
||||
->expects($this->once())
|
||||
->method('satisfies')
|
||||
->with($entry, 'rule as string')
|
||||
->willReturn(true);
|
||||
|
||||
$this->tagRepository
|
||||
->expects($this->once())
|
||||
->method('findOneByLabelAndUserId')
|
||||
->willReturn($tag);
|
||||
|
||||
$this->tagger->tag($entry);
|
||||
|
||||
$this->assertFalse($entry->getTags()->isEmpty());
|
||||
|
||||
$tags = $entry->getTags();
|
||||
$this->assertSame($tag, $tags[0]);
|
||||
}
|
||||
|
||||
private function getUser(array $taggingRules = [])
|
||||
{
|
||||
$user = new User();
|
||||
$config = new Config($user);
|
||||
|
||||
$user->setConfig($config);
|
||||
|
||||
foreach ($taggingRules as $rule) {
|
||||
$config->addTaggingRule($rule);
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
private function getTaggingRule($rule, array $tags)
|
||||
{
|
||||
$taggingRule = new TaggingRule();
|
||||
$taggingRule->setRule($rule);
|
||||
$taggingRule->setTags($tags);
|
||||
|
||||
return $taggingRule;
|
||||
}
|
||||
|
||||
private function getRulerZMock()
|
||||
{
|
||||
return $this->getMockBuilder('RulerZ\RulerZ')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
}
|
||||
|
||||
private function getTagRepositoryMock()
|
||||
{
|
||||
return $this->getMockBuilder('Wallabag\CoreBundle\Repository\TagRepository')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
}
|
||||
|
||||
private function getEntryRepositoryMock()
|
||||
{
|
||||
return $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
}
|
||||
}
|
|
@ -23,4 +23,19 @@ class UserRepository extends EntityRepository
|
|||
->getQuery()
|
||||
->getOneOrNullResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a user by its username.
|
||||
*
|
||||
* @param string $username
|
||||
*
|
||||
* @return User
|
||||
*/
|
||||
public function findOneByUserName($username)
|
||||
{
|
||||
return $this->createQueryBuilder('u')
|
||||
->andWhere('u.username = :username')->setParameter('username', $username)
|
||||
->getQuery()
|
||||
->getSingleResult();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue