Compare commits

...

61 Commits
2.3.6 ... 2.3.8

Author SHA1 Message Date
9bbafdaad4 Release wallabag 2.3.8 2019-05-14 11:24:07 +02:00
227a1a27f1 Merge pull request #3966 from wallabag/prepare-2.3.8
Prepare 2.3.8 release
2019-05-14 11:14:37 +02:00
cc181629a0 Prepare 2.3.8 release 2019-05-14 10:16:46 +02:00
eb06edba0c Merge pull request #3964 from wallabag/fix/intl
Fix Intl Locale issue
2019-05-14 09:36:46 +02:00
b50ecd0c8a Fix Intl Locale issue
Some issue appeared after the release of PHP 7.2.17 about Intl Memory
Leak / infinite loop.
To fix it we should upgrade to Symfony 3.4 (which is done in wallabag
2.4) but for the 2.3 branch, we'll use a temporary fix for the Locale
issue.
2019-05-13 14:04:33 +02:00
a73cb8a689 Merge pull request #3922 from burkemw3/patch-5
Remove preview picture from share view page for #1875
2019-05-13 06:40:16 +02:00
295b714426 Merge pull request #3943 from wallabag/img-referrer
Enable no-referrer on img tags, enable strict-origin-when-cross-origin by default
2019-05-12 23:44:33 +02:00
19822ecb31 Remove preview picture from share view page for #1875
Essentially, same as commit 038fccd for single entry views. From that commit:
> Showing the preview picture usually leads to showing a duplicate
> image, and frequently leads to showing duplicate images directly
> adjacent to each other.
2019-05-12 12:32:22 -04:00
9ae5bd9e10 assets: regenerate material.css
Signed-off-by: Kevin Decherf <kevin@kdecherf.com>
2019-05-10 23:08:23 +02:00
2dbb5b2307 Enable no-referrer on img tags, enable strict-origin-when-cross-origin by default
Fixes #3889

Signed-off-by: Kevin Decherf <kevin@kdecherf.com>
2019-05-10 23:07:26 +02:00
570113208b Merge pull request #3942 from wallabag/issue-3838
material: add metadata to list view
2019-05-09 15:45:07 +03:00
4b5b228650 material: add metadata to list view
Add reading time and creation date to rows of list view.
Refactor styles using a sass mixin.

Fixes #3838

Signed-off-by: Kevin Decherf <kevin@kdecherf.com>
2019-05-01 15:47:48 +02:00
ea54c2adb1 Merge pull request #3937 from wallabag/fix/credential-subdomain
Add ability to match many domains for credentials
2019-04-27 10:58:26 +02:00
35359bd3c6 Adding more tests to cover different scenario 2019-04-24 15:28:15 +02:00
ff8f338dc2 FIx unrelated failing test 2019-04-23 22:48:04 +02:00
f45496336f Add ability to match many domains for credentials
Instead of fetching one domain, we use the same method as in site config (to retrieve the matching file) and handle api.example.org, example.org, .org (yes the last one isn’t useful).
If one of these match, we got it and use it.
2019-04-23 22:39:31 +02:00
bfd69c74e5 Merge pull request #3909 from wallabag/fix/html-not-defined
Fix PHP warning
2019-03-18 09:26:33 +01:00
8ab5dcc467 Merge pull request #3908 from wallabag/epub-issue-3642
epub: fix exception when articles have the same title
2019-03-18 09:26:16 +01:00
893f107fa1 Merge pull request #3860 from baurmatt/fix/posix_compatibility
Make dev/install/update script posix compatible
2019-03-18 09:25:00 +01:00
8ca858ee73 Fix PHP warning
Looks like sometimes (usually from import) the `html` key isn’t available.
2019-03-18 06:23:41 +01:00
41d476d7e7 epub: fix exception when articles have the same title
This commit fixes an exception occuring when exporting as epub several
articles with the same title. The chapter filename is now derived from
title and url.

Fixes #3642

Signed-off-by: Kevin Decherf <kevin@kdecherf.com>
2019-03-17 23:36:10 +01:00
7c553a6017 Properly source require.sh
Fixes #3571.
2019-03-12 15:44:38 +01:00
a48ff25d4c Merge pull request #3901 from wallabag/fix-pr-3893
material: fix left padding on non-entry pages introduced by #3893
2019-03-09 12:19:31 +01:00
cf0010cf4a material: fix left padding on non-entry pages introduced by #3893
Signed-off-by: Kevin Decherf <kevin@kdecherf.com>
2019-03-09 00:27:50 +01:00
13d2fe6d2e Merge pull request #3897 from wallabag/2.3.8-dev
Jump to 2.3.8-dev
2019-03-04 15:23:06 +01:00
3d7a1f4caf Jump to 2.3.8-dev 2019-03-04 13:49:23 +01:00
36fd8e5fde Merge pull request #3895 from wallabag/prepare-2.3.7
Prepare 2.3.7 release
2019-03-04 12:06:22 +01:00
f2aa373054 Prepare 2.3.7 release 2019-03-04 09:32:26 +01:00
4ae4fa7b89 Merge pull request #3894 from wallabag/issue-3851
material: hide creation date from card actions on specific sizes
2019-03-03 20:22:30 +01:00
6640a922d1 material: update prod assets
Signed-off-by: Kevin Decherf <kevin@kdecherf.com>
2019-03-03 19:24:34 +01:00
246cc9ac93 material: add media queries to hide creation date from card actions
Hide the creation date from card actions on specific sizes when there's
not enough space for all parts.

Fixes #3851

Signed-off-by: Kevin Decherf <kevin@kdecherf.com>
2019-03-03 19:22:32 +01:00
f1f1efb5de material: wrap card actions, remove class hiding of creation date
Signed-off-by: Kevin Decherf <kevin@kdecherf.com>
2019-03-03 19:22:32 +01:00
806635f7d5 Merge pull request #3893 from wallabag/issue-3877
material: fix left padding of content on medium screens
2019-03-03 19:22:03 +01:00
05232afe32 material: fix left padding of content on medium screens
Fixes #3877

Signed-off-by: Kevin Decherf <kevin@kdecherf.com>
2019-03-02 23:46:00 +01:00
fb7dedf36c material: move a media query from cards to dedicated scss file
Signed-off-by: Kevin Decherf <kevin@kdecherf.com>
2019-03-02 22:48:43 +01:00
1e9c710fdd Merge pull request #3885 from mart-e/script-ignore-root
Allow optional --ignore-root-warning
2019-03-01 20:22:22 +01:00
d5154ee2ae Merge pull request #3886 from wallabag/issue-3602
epub export: fix missing cover image, only for exports of one article
2019-02-25 14:03:41 +01:00
4de99d1ab1 Merge pull request #3887 from wallabag/issue-3711
Add support of expect parameter to change return object when deleting entry
2019-02-25 10:56:07 +01:00
12a97c3522 tests: fix broken session clients for rest entry deletion tests
Signed-off-by: Kevin Decherf <kevin@kdecherf.com>
2019-02-20 15:57:56 +01:00
508302042f EntryRestController: add support of expect parameter to delete action
The expect parameter enables an application to request the whole entry
or only the id when requesting its deletion.

`expects` defaults to `entry` to prevent any API breakage.

Fixes #3711

Signed-off-by: Kevin Decherf <kevin@kdecherf.com>
2019-02-20 15:57:50 +01:00
9a7a0e1e6b epub export: fix missing cover image, only for exports of one article
Fixes #3602

Signed-off-by: Kevin Decherf <kevin@kdecherf.com>
2019-02-18 00:16:05 +01:00
4e0ed3368d tests: create entry for testDeleteEntry, fix missing id
When using the entity manager to retrieve an already stored entry, the
id disapears from $entry after the first delete call. This leads to
testing a nonexistent endpoint (api/entries/.json) during the second
delete call.

This change now creates an entry specifically for the test.

Signed-off-by: Kevin Decherf <kevin@kdecherf.com>
2019-02-17 15:25:21 +01:00
c01bda038e Allow optional --ignore-root-warning
Now both
./install prod --ignore-root-warning
./install --ignore-root-warning prod

will work

$1 was both used for the environment and the root flag

Fixes wallabag/wallabag#3884
2019-02-14 16:42:57 +05:30
b1992b340e Merge pull request #3882 from wallabag/fix/cors
Fix CORS for API
2019-02-13 15:05:57 +01:00
44560c7767 CS 2019-02-13 14:06:57 +01:00
0182cdaec4 CS 2019-02-11 11:57:52 +01:00
a9f61d3dbb CORS repare for api 2019-02-11 11:57:52 +01:00
47e4784110 Merge pull request #3869 from itsthejb/fix-2factor-email-image
Fix broken 2 factor auth logo image
2019-02-01 12:58:31 +01:00
7e04bd4ca4 Fix broken 2 factor auth logo image 2019-01-31 22:14:53 +01:00
755753e3ef Merge pull request #3819 from stan3/pocket-import
Fix read & starred status in Pocket import
2019-01-28 11:34:37 +01:00
8d082488e9 Improve checks & add tests 2019-01-28 06:03:16 +01:00
a2e60dd393 status and favourite are actually strings in the import so use == 2019-01-27 18:39:26 +01:00
b992522d85 Merge pull request #3861 from wallabag/fix/siteconfig-email
Add dedicated email for site config issue
2019-01-18 13:20:38 +01:00
293730656d Add dedicated email for site config issue
Instead of sending an email to the devs, it now creates an issue on GitHub using a zap from zapier.
2019-01-18 11:15:23 +01:00
6b32cf0c73 Merge pull request #3853 from techexo/patch-2
Update composer.json to add php-tidy (ext-tidy)
2019-01-17 12:09:07 +01:00
1ec44a346b Update composer.json to add php-tidy (ext-tidy)
Should fix https://github.com/wallabag/wallabag/issues/3844 for milestone https://github.com/wallabag/wallabag/milestone/63.
2019-01-16 21:54:38 +01:00
f6b9e883c0 Merge pull request #3841 from wallabag/fix/bad-order-api
Fix bad order parameter in the API
2019-01-14 22:24:40 +01:00
78e3fafa3f Avoid error when a bad order parameter is given
Only allowed parameter are asc & desc
2019-01-14 17:01:21 +01:00
a5e9a98aa3 Come back to stable version
Previous one was used because some PHPUnit version where deleted and tests can't be run anymore.
2019-01-14 17:00:32 +01:00
f083836cc4 Merge pull request #3837 from wallabag/2.3.7-dev
Jump to 2.3.7-dev
2019-01-12 11:19:19 +01:00
314f647238 Jump to 2.3.7-dev 2019-01-11 22:17:48 +01:00
51 changed files with 8247 additions and 159 deletions

View File

@ -73,7 +73,7 @@ before_script:
- sudo swapon -s
script:
- travis_wait bash composer install -o --no-interaction --no-progress --prefer-dist
- travis_wait bash composer update -o --no-interaction --no-progress --prefer-dist
- echo "travis_fold:start:prepare"
- make prepare DB=$DB
- echo "travis_fold:end:prepare"

View File

@ -1,5 +1,39 @@
# Changelog
## [2.3.8](https://github.com/wallabag/wallabag/tree/2.3.8)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.3.7...2.3.8)
### Fixes
- Jump to 2.3.8-dev [#3897](https://github.com/wallabag/wallabag/pull/3897)
- material: fix left padding on non-entry pages [#3901](https://github.com/wallabag/wallabag/pull/3901)
- Make dev/install/update script posix compatible [#3860](https://github.com/wallabag/wallabag/pull/3860)
- epub: fix exception when articles have the same title [#3908](https://github.com/wallabag/wallabag/pull/3908)
- Fix PHP warning [#3909](https://github.com/wallabag/wallabag/pull/3909)
- Add ability to match many domains for credentials [#3937](https://github.com/wallabag/wallabag/pull/3937)
- material: add metadata to list view [#3942](https://github.com/wallabag/wallabag/pull/3942)
- Enable no-referrer on img tags, enable strict-origin-when-cross-origin by default [#3943](https://github.com/wallabag/wallabag/pull/3943)
- Remove preview picture from share view page#3922
- Fix Intl Locale issue [#3964](https://github.com/wallabag/wallabag/pull/3964)
## [2.3.7](https://github.com/wallabag/wallabag/tree/2.3.7)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.3.6...2.3.7)
### Fixes
- Jump to 2.3.7-dev [#3837](https://github.com/wallabag/wallabag/pull/3837)
- Fix bad order parameter in the API [#3841](https://github.com/wallabag/wallabag/pull/3841)
- Update composer.json to add php-tidy (ext-tidy) [#3853](https://github.com/wallabag/wallabag/pull/3853)
- Add dedicated email for site config issue [#3861](https://github.com/wallabag/wallabag/pull/3861)
- Fix read & starred status in Pocket import [#3819](https://github.com/wallabag/wallabag/pull/3819)
- Fix broken 2 factor auth logo image [#3869](https://github.com/wallabag/wallabag/pull/3869)
- Fix CORS for API [#3882](https://github.com/wallabag/wallabag/pull/3882)
- Add support of expect parameter to change return object when deleting entry [#3887](https://github.com/wallabag/wallabag/pull/3887)
- epub export: fix missing cover image, only for exports of one article [#3886](https://github.com/wallabag/wallabag/pull/3886)
- Allow optional --ignore-root-warning [#3885](https://github.com/wallabag/wallabag/pull/3885)
- material: fix left padding of content on medium screens [#3893](https://github.com/wallabag/wallabag/pull/3893)
- material: hide creation date from card actions on specific sizes [#3894](https://github.com/wallabag/wallabag/pull/3894)
## [2.3.6](https://github.com/wallabag/wallabag/tree/2.3.6)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.3.5...2.3.6)

View File

@ -18,6 +18,24 @@ main {
overflow: hidden;
}
@mixin mixin-reading-time {
.reading-time {
display: inline-flex;
vertical-align: middle;
.card-reading-time,
.card-created-at {
display: inline-flex;
}
span {
margin-right: 5px;
}
@content;
}
}
.card {
.card-content .card-title,
.card-reveal .card-title {
@ -98,14 +116,7 @@ main {
margin-right: 5px !important;
}
.reading-time {
display: inline-flex;
vertical-align: middle;
span {
margin-right: 5px;
}
}
@include mixin-reading-time;
}
.card-image {
@ -219,10 +230,18 @@ a.original:not(.waves-effect) {
}
div.metadata {
overflow: hidden;
height: 1.5em;
display: flex;
ul.tags {
margin-left: 4px;
}
.chip {
background-color: $blueAccentColor;
padding: 0 7px;
margin: auto 2px;
margin: auto 1px;
border-radius: 6px;
line-height: 22px;
height: 22px;
@ -239,6 +258,16 @@ a.original:not(.waves-effect) {
padding-left: 8px;
}
}
@include mixin-reading-time {
padding: 0 5px;
flex-wrap: wrap;
margin-left: auto;
i.material-icons {
font-size: 20px;
}
}
}
div.card-content {
@ -272,9 +301,3 @@ a.original:not(.waves-effect) {
.settings .div_tabs {
padding-bottom: 15px;
}
@media only screen and (min-width: 992px) {
.card-tag-labels li {
max-width: 50%;
}
}

View File

@ -12,6 +12,16 @@
.pagination {
margin-left: auto;
}
.card-tag-labels li {
max-width: 50%;
}
}
@media screen and (min-width: 993px) {
body.entry main #content {
padding-left: 70px;
}
}
@media only screen and (max-width: 992px) {
@ -163,4 +173,17 @@
.row .col {
padding: 0;
}
.card-stacked div.metadata .reading-time {
display: none;
}
}
@media screen and (max-width: 310px),
screen and (min-width: 601px) and (max-width: 660px),
screen and (min-width: 993px) and (max-width: 1050px),
screen and (min-width: 1201px) and (max-width: 1250px) {
.card .card-action .reading-time .card-created-at {
display: none;
}
}

View File

@ -147,18 +147,18 @@ nelmio_cors:
paths:
'^/api/':
allow_origin: ['*']
allow_headers: ['X-Custom-Auth']
allow_headers: ['Authorization','content-type']
allow_methods: ['POST', 'PUT', 'PATCH','GET', 'DELETE']
max_age: 3600
'^/oauth/':
allow_origin: ['*']
allow_headers: ['X-Custom-Auth']
allow_headers: ['Authorization','content-type']
allow_methods: ['POST', 'PUT', 'GET', 'DELETE']
max_age: 3600
'^/':
#origin_regex: true
allow_origin: ['^http://localhost:[0-9]+']
allow_headers: ['X-Custom-Auth']
allow_origin: ['*']
allow_headers: ['Authorization','content-type']
allow_methods: ['POST', 'PUT', 'GET', 'DELETE']
max_age: 3600
hosts: ['^api\.']

View File

@ -1,5 +1,5 @@
wallabag_core:
version: 2.3.6
version: 2.3.8
paypal_url: "https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=9UBA65LG3FX9Y&lc=gb"
languages:
en: 'English'

View File

@ -43,6 +43,7 @@
"ext-iconv": "*",
"ext-tokenizer": "*",
"ext-pdo": "*",
"ext-tidy": "*",
"symfony/symfony": "~3.3.13",
"doctrine/orm": "^2.5.12",
"doctrine/doctrine-bundle": "^1.8.0",
@ -85,13 +86,14 @@
"friendsofsymfony/jsrouting-bundle": "^1.6.3",
"bdunogier/guzzle-site-authenticator": "^1.0.0",
"defuse/php-encryption": "^2.1",
"html2text/html2text": "^4.1"
"html2text/html2text": "^4.1",
"sulu/symfony-intl-fix": "^1.0"
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "~2.2",
"doctrine/data-fixtures": "~1.1",
"sensio/generator-bundle": "^3.0",
"symfony/phpunit-bridge": "3.4.x-dev",
"symfony/phpunit-bridge": "^4.2",
"friendsofphp/php-cs-fixer": "~2.0",
"m6web/redis-mock": "^2.0",
"dama/doctrine-test-bundle": "^4.0"
@ -124,7 +126,11 @@
},
"autoload": {
"psr-4": { "Wallabag\\": "src/Wallabag/" },
"classmap": [ "app/AppKernel.php", "app/AppCache.php" ]
"classmap": [ "app/AppKernel.php", "app/AppCache.php" ],
"exclude-from-classmap": [
"vendor/symfony/intl/Locale.php",
"vendor/symfony/symfony/src/Symfony/Component/Intl/Locale.php"
]
},
"autoload-dev": {
"psr-4": { "Tests\\": "tests/" }

7748
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -3,10 +3,14 @@
# eg: `sh dev.sh`
COMPOSER_COMMAND='composer'
REQUIRE_FILE='scripts/require.sh'
DIR="${BASH_SOURCE}"
if [ ! -d "$DIR" ]; then DIR="$PWD/scripts"; fi
. "$DIR/require.sh"
if [ ! -f "$REQUIRE_FILE" ]; then
echo "Cannot find $REQUIRE_FILE"
exit 1
fi
. "$REQUIRE_FILE"
$COMPOSER_COMMAND install
php bin/console wallabag:install

View File

@ -5,9 +5,17 @@
IGNORE_ROOT_ARG="--ignore-root-warning"
IGNORE_ROOT=0
if [ "$1" == "$IGNORE_ROOT_ARG" ]; then
IGNORE_ROOT=1
fi
while :; do
case $1 in
$IGNORE_ROOT_ARG) IGNORE_ROOT=1
;;
*[a-zA-Z]) ENV=$1
;;
*) break
;;
esac
shift
done
# Abort running this script if root
if [ "$IGNORE_ROOT" -eq 0 ] && [ "$EUID" == "0" ]; then
@ -17,12 +25,15 @@ if [ "$IGNORE_ROOT" -eq 0 ] && [ "$EUID" == "0" ]; then
fi
COMPOSER_COMMAND='composer'
REQUIRE_FILE='scripts/require.sh'
DIR="${BASH_SOURCE}"
if [ ! -d "$DIR" ]; then DIR="$PWD/scripts"; fi
. "$DIR/require.sh"
if [ ! -f "$REQUIRE_FILE" ]; then
echo "Cannot find $REQUIRE_FILE"
exit 1
fi
. "$REQUIRE_FILE"
ENV=$1
TAG=$(git describe --tags $(git rev-list --tags --max-count=1))
git checkout $TAG

View File

@ -5,9 +5,17 @@
IGNORE_ROOT_ARG="--ignore-root-warning"
IGNORE_ROOT=0
if [ "$1" == "$IGNORE_ROOT_ARG" ]; then
IGNORE_ROOT=1
fi
while :; do
case $1 in
$IGNORE_ROOT_ARG) IGNORE_ROOT=1
;;
*[a-zA-Z]) ENV=$1
;;
*) break
;;
esac
shift
done
# Abort running this script if root
if [ "$IGNORE_ROOT" -eq 0 ] && [ "$EUID" == "0" ]; then
@ -20,12 +28,14 @@ set -e
set -u
COMPOSER_COMMAND='composer'
REQUIRE_FILE='scripts/require.sh'
DIR="${BASH_SOURCE}"
if [ ! -d "$DIR" ]; then DIR="$PWD/scripts"; fi
. "$DIR/require.sh"
if [ ! -f "$REQUIRE_FILE" ]; then
echo "Cannot find $REQUIRE_FILE"
exit 1
fi
ENV=$1
. "$REQUIRE_FILE"
rm -rf var/cache/*
git fetch origin

View File

@ -9,6 +9,7 @@ use Nelmio\ApiDocBundle\Annotation\ApiDoc;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Wallabag\CoreBundle\Entity\Entry;
@ -98,24 +99,28 @@ class EntryRestController extends WallabagRestController
$isArchived = (null === $request->query->get('archive')) ? null : (bool) $request->query->get('archive');
$isStarred = (null === $request->query->get('starred')) ? null : (bool) $request->query->get('starred');
$isPublic = (null === $request->query->get('public')) ? null : (bool) $request->query->get('public');
$sort = $request->query->get('sort', 'created');
$order = $request->query->get('order', 'desc');
$sort = strtolower($request->query->get('sort', 'created'));
$order = strtolower($request->query->get('order', 'desc'));
$page = (int) $request->query->get('page', 1);
$perPage = (int) $request->query->get('perPage', 30);
$tags = \is_array($request->query->get('tags')) ? '' : (string) $request->query->get('tags', '');
$since = $request->query->get('since', 0);
/** @var \Pagerfanta\Pagerfanta $pager */
$pager = $this->get('wallabag_core.entry_repository')->findEntries(
$this->getUser()->getId(),
$isArchived,
$isStarred,
$isPublic,
$sort,
$order,
$since,
$tags
);
try {
/** @var \Pagerfanta\Pagerfanta $pager */
$pager = $this->get('wallabag_core.entry_repository')->findEntries(
$this->getUser()->getId(),
$isArchived,
$isStarred,
$isPublic,
$sort,
$order,
$since,
$tags
);
} catch (\Exception $e) {
throw new BadRequestHttpException($e->getMessage());
}
$pager->setMaxPerPage($perPage);
$pager->setCurrentPage($page);
@ -565,18 +570,31 @@ class EntryRestController extends WallabagRestController
* @ApiDoc(
* requirements={
* {"name"="entry", "dataType"="integer", "requirement"="\w+", "description"="The entry ID"}
* },
* parameters={
* {"name"="expect", "dataType"="string", "required"=false, "format"="id or entry", "description"="Only returns the id instead of the deleted entry's full entity if 'id' is specified. Default to entry"},
* }
* )
*
* @return JsonResponse
*/
public function deleteEntriesAction(Entry $entry)
public function deleteEntriesAction(Entry $entry, Request $request)
{
$expect = $request->query->get('expect', 'entry');
if (!\in_array($expect, ['id', 'entry'], true)) {
throw new BadRequestHttpException(sprintf("expect: 'id' or 'entry' expected, %s given", $expect));
}
$this->validateAuthentication();
$this->validateUserAccess($entry->getUser()->getId());
// We copy $entry to keep id in returned object
$e = $entry;
$response = $this->sendResponse([
'id' => $entry->getId(),
]);
// We clone $entry to keep id in returned object
if ('entry' === $expect) {
$e = clone $entry;
$response = $this->sendResponse($e);
}
$em = $this->getDoctrine()->getManager();
$em->remove($entry);
@ -585,7 +603,7 @@ class EntryRestController extends WallabagRestController
// entry deleted, dispatch event about it!
$this->get('event_dispatcher')->dispatch(EntryDeletedEvent::NAME, new EntryDeletedEvent($entry));
return $this->sendResponse($e);
return $response;
}
/**

View File

@ -5,19 +5,38 @@ namespace Wallabag\CoreBundle\DataFixtures\ORM;
use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Wallabag\CoreBundle\Entity\SiteCredential;
class LoadSiteCredentialData extends AbstractFixture implements OrderedFixtureInterface
class LoadSiteCredentialData extends AbstractFixture implements OrderedFixtureInterface, ContainerAwareInterface
{
/**
* @var ContainerInterface
*/
private $container;
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
}
/**
* {@inheritdoc}
*/
public function load(ObjectManager $manager)
{
$credential = new SiteCredential($this->getReference('admin-user'));
$credential->setHost('example.com');
$credential->setUsername('foo');
$credential->setPassword('bar');
$credential->setHost('.super.com');
$credential->setUsername($this->container->get('wallabag_core.helper.crypto_proxy')->crypt('.super'));
$credential->setPassword($this->container->get('wallabag_core.helper.crypto_proxy')->crypt('bar'));
$manager->persist($credential);
$credential = new SiteCredential($this->getReference('admin-user'));
$credential->setHost('paywall.example.com');
$credential->setUsername($this->container->get('wallabag_core.helper.crypto_proxy')->crypt('paywall.example'));
$credential->setPassword($this->container->get('wallabag_core.helper.crypto_proxy')->crypt('bar'));
$manager->persist($credential);

View File

@ -108,7 +108,7 @@ class EntryFilterType extends AbstractType
->add('httpStatus', TextFilterType::class, [
'apply_filter' => function (QueryInterface $filterQuery, $field, $values) {
$value = $values['value'];
if (false === array_key_exists($value, Response::$statusTexts)) {
if (false === \array_key_exists($value, Response::$statusTexts)) {
return;
}

View File

@ -62,11 +62,24 @@ class GrabySiteConfigBuilder implements SiteConfigBuilder
$host = substr($host, 4);
}
$credentials = null;
if ($this->currentUser) {
$credentials = $this->credentialRepository->findOneByHostAndUser($host, $this->currentUser->getId());
if (!$this->currentUser) {
$this->logger->debug('Auth: no current user defined.');
return false;
}
$hosts = [$host];
// will try to see for a host without the first subdomain (fr.example.org & .example.org)
$split = explode('.', $host);
if (\count($split) > 1) {
// remove first subdomain
array_shift($split);
$hosts[] = '.' . implode('.', $split);
}
$credentials = $this->credentialRepository->findOneByHostsAndUser($hosts, $this->currentUser->getId());
if (null === $credentials) {
$this->logger->debug('Auth: no credentials available for host.', ['host' => $host]);

View File

@ -47,6 +47,7 @@ class ContentProxy
*/
public function updateEntry(Entry $entry, $url, array $content = [], $disableContentUpdate = false)
{
$this->graby->toggleImgNoReferrer(true);
if (!empty($content['html'])) {
$content['html'] = $this->graby->cleanupHtml($content['html'], $url);
}
@ -256,18 +257,17 @@ class ContentProxy
$entry->setTitle($content['open_graph']['og_title']);
}
$html = $content['html'];
if (false === $html) {
$html = $this->fetchingErrorMessage;
if (empty($content['html'])) {
$content['html'] = $this->fetchingErrorMessage;
if (!empty($content['open_graph']['og_description'])) {
$html .= '<p><i>But we found a short description: </i></p>';
$html .= $content['open_graph']['og_description'];
$content['html'] .= '<p><i>But we found a short description: </i></p>';
$content['html'] .= $content['open_graph']['og_description'];
}
}
$entry->setContent($html);
$entry->setReadingTime(Utils::getReadingTime($html));
$entry->setContent($content['html']);
$entry->setReadingTime(Utils::getReadingTime($content['html']));
if (!empty($content['status'])) {
$entry->setHttpStatus($content['status']);

View File

@ -165,13 +165,6 @@ class EntriesExport
$book->addDublinCoreMetadata(DublinCore::CONTRIBUTOR, 'PHP');
$book->addDublinCoreMetadata(DublinCore::CONTRIBUTOR, 'wallabag');
/*
* Front page
*/
if (file_exists($this->logoPath)) {
$book->setCoverImage('Cover.png', file_get_contents($this->logoPath), 'image/png');
}
$entryIds = [];
$entryCount = \count($this->entries);
$i = 0;
@ -183,10 +176,19 @@ class EntriesExport
// set tags as subjects
foreach ($this->entries as $entry) {
++$i;
/*
* Front page
* Set if there's only one entry in the given set
*/
if (1 === $entryCount && null !== $entry->getPreviewPicture()) {
$book->setCoverImage($entry->getPreviewPicture());
}
foreach ($entry->getTags() as $tag) {
$book->setSubject($tag->getLabel());
}
$filename = sha1($entry->getTitle());
$filename = sha1(sprintf('%s:%s', $entry->getUrl(), $entry->getTitle()));
$publishedBy = $entry->getPublishedBy();
$authors = $this->translator->trans('export.unknown');

View File

@ -23,7 +23,7 @@ class PreparePagerForEntries
* @param AdapterInterface $adapter
* @param User $user If user isn't logged in, we can force it (like for rss)
*
* @return null|Pagerfanta
* @return Pagerfanta|null
*/
public function prepare(AdapterInterface $adapter, User $user = null)
{

View File

@ -142,7 +142,7 @@ class EntryRepository extends EntityRepository
*
* @return Pagerfanta
*/
public function findEntries($userId, $isArchived = null, $isStarred = null, $isPublic = null, $sort = 'created', $order = 'ASC', $since = 0, $tags = '')
public function findEntries($userId, $isArchived = null, $isStarred = null, $isPublic = null, $sort = 'created', $order = 'asc', $since = 0, $tags = '')
{
$qb = $this->createQueryBuilder('e')
->leftJoin('e.tags', 't')
@ -185,6 +185,10 @@ class EntryRepository extends EntityRepository
}
}
if (!\in_array(strtolower($order), ['asc', 'desc'], true)) {
throw new \Exception('Order "' . $order . '" parameter is wrong, allowed: asc or desc');
}
if ('created' === $sort) {
$qb->orderBy('e.id', $order);
} elseif ('updated' === $sort) {

View File

@ -19,16 +19,16 @@ class SiteCredentialRepository extends \Doctrine\ORM\EntityRepository
/**
* Retrieve one username/password for the given host and userId.
*
* @param string $host
* @param int $userId
* @param array $hosts An array of host to look for
* @param int $userId
*
* @return null|array
* @return array|null
*/
public function findOneByHostAndUser($host, $userId)
public function findOneByHostsAndUser($hosts, $userId)
{
$res = $this->createQueryBuilder('s')
->select('s.username', 's.password')
->where('s.host = :hostname')->setParameter('hostname', $host)
->where('s.host IN (:hosts)')->setParameter('hosts', $hosts)
->andWhere('s.user = :userId')->setParameter('userId', $userId)
->setMaxResults(1)
->getQuery()

View File

@ -550,7 +550,7 @@ site_credential:
# create_new_one: Create a new credential
# form:
# username_label: 'Username'
# host_label: 'Host'
# host_label: 'Host (subdomain.example.org, .example.org, etc.)'
# password_label: 'Password'
# save: Save
# delete: Delete

View File

@ -550,7 +550,7 @@ site_credential:
create_new_one: 'Einen neuen Seitenzugang anlegen'
form:
username_label: 'Benutzername'
host_label: 'Host'
host_label: 'Host (subdomain.example.org, .example.org, etc.)'
password_label: 'Passwort'
save: 'Speichern'
delete: 'Löschen'

View File

@ -550,7 +550,7 @@ site_credential:
create_new_one: Create a new credential
form:
username_label: 'Username'
host_label: 'Host'
host_label: 'Host (subdomain.example.org, .example.org, etc.)'
password_label: 'Password'
save: Save
delete: Delete

View File

@ -550,7 +550,7 @@ site_credential:
# create_new_one: Create a new credential
# form:
# username_label: 'Username'
# host_label: 'Host'
# host_label: 'Host (subdomain.example.org, .example.org, etc.)'
# password_label: 'Password'
# save: Save
# delete: Delete

View File

@ -550,7 +550,7 @@ site_credential:
# create_new_one: Create a new credential
# form:
# username_label: 'Username'
# host_label: 'Host'
# host_label: 'Host (subdomain.example.org, .example.org, etc.)'
# password_label: 'Password'
# save: Save
# delete: Delete

View File

@ -550,7 +550,7 @@ site_credential:
create_new_one: Créer un nouvel accès à un site
form:
username_label: 'Identifiant'
host_label: 'Domaine'
host_label: 'Domaine (subdomain.example.org, .example.org, etc.)'
password_label: 'Mot de passe'
save: "Sauvegarder"
delete: "Supprimer"

View File

@ -550,7 +550,7 @@ site_credential:
# create_new_one: Create a new credential
# form:
# username_label: 'Username'
# host_label: 'Host'
# host_label: 'Host (subdomain.example.org, .example.org, etc.)'
# password_label: 'Password'
# save: Save
# delete: Delete

View File

@ -550,7 +550,7 @@ site_credential:
create_new_one: Crear un novèl identificant
form:
username_label: "Nom d'utilizaire"
host_label: 'Òste'
host_label: 'Òste (subdomain.example.org, .example.org, etc.)'
password_label: 'Senhal'
save: 'Enregistrar'
delete: 'Suprimir'

View File

@ -550,7 +550,7 @@ site_credential:
create_new_one: Stwórz nowe poświadczenie
form:
username_label: 'Nazwa użytkownika'
host_label: 'Host'
host_label: 'Host (subdomain.example.org, .example.org, etc.)'
password_label: 'Hasło'
save: Zapisz
delete: Usuń

View File

@ -550,7 +550,7 @@ site_credential:
# create_new_one: Create a new credential
form:
# username_label: 'Username'
# host_label: 'Host'
# host_label: 'Host (subdomain.example.org, .example.org, etc.)'
# password_label: 'Password'
save: 'Salvar'
delete: 'Apagar'

View File

@ -550,7 +550,7 @@ site_credential:
# create_new_one: Create a new credential
# form:
# username_label: 'Username'
# host_label: 'Host'
# host_label: 'Host (subdomain.example.org, .example.org, etc.)'
# password_label: 'Password'
# save: Save
# delete: Delete

View File

@ -548,7 +548,7 @@ site_credential:
create_new_one: สร้างข้อมูลส่วนตัวใหม่
form:
username_label: 'ชื่อผู้ใช้'
host_label: 'โฮส'
host_label: 'โฮส (subdomain.example.org, .example.org, etc.)'
password_label: 'รหัสผ่าน'
save: บันทึก
delete: ลบ

View File

@ -8,6 +8,7 @@
{% block head %}
<meta name="viewport" content="initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="referrer" content="strict-origin-when-cross-origin">
<!--[if IE]>
<meta http-equiv="X-UA-Compatible" content="IE=10">
<![endif]-->

View File

@ -38,7 +38,7 @@
{% if craue_setting('export_epub') %}<li><a href="{{ path('export_entry', { 'id': entry.id, 'format': 'epub' }) }}" title="Generate ePub file">EPUB</a></li>{% endif %}
{% if craue_setting('export_mobi') %}<li><a href="{{ path('export_entry', { 'id': entry.id, 'format': 'mobi' }) }}" title="Generate Mobi file">MOBI</a></li>{% endif %}
{% if craue_setting('export_pdf') %}<li><a href="{{ path('export_entry', { 'id': entry.id, 'format': 'pdf' }) }}" title="Generate PDF file">PDF</a></li>{% endif %}
<li><a href="mailto:hello@wallabag.org?subject=Wrong%20display%20in%20wallabag&amp;body={{ entry.url|url_encode }}" title="{{ 'entry.view.left_menu.problem.label'|trans }}" class="tool bad-display icon icon-delete"><span>{{ 'entry.view.left_menu.problem.label'|trans }}</span></a></li>
<li><a href="mailto:siteconfig@wallabag.org?subject=Wrong%20display%20in%20wallabag&amp;body={{ entry.url|url_encode }}" title="{{ 'entry.view.left_menu.problem.label'|trans }}" class="tool bad-display icon icon-delete"><span>{{ 'entry.view.left_menu.problem.label'|trans }}</span></a></li>
</ul>
</div>

View File

@ -29,9 +29,6 @@
<h1>{{ entry.title|e|raw }}</h1>
<a href="{{ entry.url|e }}" target="_blank" rel="noopener" title="{{ 'entry.view.original_article'|trans }} : {{ entry.title|e|raw }}" class="tool">{{ entry.domainName|removeWww }}</a>
<p class="shared-by">{{ "entry.public.shared_by_wallabag"|trans({'%wallabag_instance%': url('homepage'), '%username%': entry.user.username})|raw }}.</p>
{% if entry.previewPicture is not null %}
<img class="preview" src="{{ entry.previewPicture }}" alt="{{ entry.title|striptags|e('html_attr') }}" />
{% endif %}
</header>
<article class="block">
{{ entry.content | raw }}

View File

@ -8,8 +8,11 @@
<div class="{{ subClass|default('original grey-text') }}">
<a href="{{ entry.url|e }}" target="_blank" title="{{ entry.domainName|removeWww }}" class="tool grey-text">{{ entry.domainName|removeWww }}</a>
{% if withTags is defined %}
{% if withMetadata is defined %}
{% include "@WallabagCore/themes/material/Entry/_tags.html.twig" with {'tags': entry.tags | slice(0, 3), 'entryId': entry.id, 'listClass': ' hide-on-med-and-down'} only %}
<div class="reading-time grey-text">
<div class="card-reading-time">{% include "@WallabagCore/themes/material/Entry/_reading_time.html.twig" with {'entry': entry} only %}</div>
</div>
{% endif %}
</div>
</div>

View File

@ -1,9 +1,11 @@
<div class="card-action">
<span class="reading-time grey-text">
{% include "@WallabagCore/themes/material/Entry/_reading_time.html.twig" with {'entry': entry} only %}
<i class="material-icons hide-on-med-and-down" title="{{ 'entry.view.created_at'|trans }}">today</i>
<span class="hide-on-med-and-down">&nbsp;{{ entry.createdAt|date('Y-m-d') }}</span>
</span>
<div class="reading-time grey-text">
<div class="card-reading-time">{% include "@WallabagCore/themes/material/Entry/_reading_time.html.twig" with {'entry': entry} only %}</div>
<div class="card-created-at">
<i class="material-icons" title="{{ 'entry.view.created_at'|trans }}">today</i>
<span>&nbsp;{{ entry.createdAt|date('Y-m-d') }}</span>
</div>
</div>
<ul class="tools right">
<li>

View File

@ -5,7 +5,7 @@
<span class="preview{{ previewClassModifier }}" style="background-image: url({{ entry.previewPicture | default(asset('wallassets/themes/_global/img/logo-square.svg')) }})"></span>
</a>
</div>
{% include "@WallabagCore/themes/material/Entry/Card/_content.html.twig" with {'entry': entry, 'withTags': true, 'subClass': 'metadata'} only %}
{% include "@WallabagCore/themes/material/Entry/Card/_content.html.twig" with {'entry': entry, 'withMetadata': true, 'subClass': 'metadata'} only %}
<ul class="tools-list hide-on-small-only">
<li>
<a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool grey-text" href="{{ path('archive_entry', { 'id': entry.id }) }}"><i class="material-icons">{% if entry.isArchived == 0 %}done{% else %}unarchive{% endif %}</i></a>

View File

@ -209,7 +209,7 @@
</li>
<li class="bold">
<a class="waves-effect collapsible-header" href="mailto:hello@wallabag.org?subject=Wrong%20display%20in%20wallabag&amp;body={{ entry.url|url_encode }}" title="{{ 'entry.view.left_menu.problem.description'|trans }}">
<a class="waves-effect collapsible-header" href="mailto:siteconfig@wallabag.org?subject=Wrong%20display%20in%20wallabag&amp;body={{ entry.url|url_encode }}" title="{{ 'entry.view.left_menu.problem.description'|trans }}">
<i class="material-icons small">error</i>
<span>{{ 'entry.view.left_menu.problem.label'|trans }}</span>
</a>

View File

@ -77,7 +77,7 @@ abstract class BrowserImport extends AbstractImport
*/
public function parseEntry(array $importedEntry)
{
if ((!array_key_exists('guid', $importedEntry) || (!array_key_exists('id', $importedEntry))) && \is_array(reset($importedEntry))) {
if ((!\array_key_exists('guid', $importedEntry) || (!\array_key_exists('id', $importedEntry))) && \is_array(reset($importedEntry))) {
if ($this->producer) {
$this->parseEntriesForProducer($importedEntry);
@ -89,7 +89,7 @@ abstract class BrowserImport extends AbstractImport
return;
}
if (array_key_exists('children', $importedEntry)) {
if (\array_key_exists('children', $importedEntry)) {
if ($this->producer) {
$this->parseEntriesForProducer($importedEntry['children']);
@ -101,11 +101,11 @@ abstract class BrowserImport extends AbstractImport
return;
}
if (!array_key_exists('uri', $importedEntry) && !array_key_exists('url', $importedEntry)) {
if (!\array_key_exists('uri', $importedEntry) && !\array_key_exists('url', $importedEntry)) {
return;
}
$url = array_key_exists('uri', $importedEntry) ? $importedEntry['uri'] : $importedEntry['url'];
$url = \array_key_exists('uri', $importedEntry) ? $importedEntry['uri'] : $importedEntry['url'];
$existingEntry = $this->em
->getRepository('WallabagCoreBundle:Entry')
@ -126,7 +126,7 @@ abstract class BrowserImport extends AbstractImport
// update entry with content (in case fetching failed, the given entry will be return)
$this->fetchContent($entry, $data['url'], $data);
if (array_key_exists('tags', $data)) {
if (\array_key_exists('tags', $data)) {
$this->tagsAssigner->assignTagsToEntry(
$entry,
$data['tags']

View File

@ -57,7 +57,7 @@ class ChromeImport extends BrowserImport
'created_at' => substr($entry['date_added'], 0, 10),
];
if (array_key_exists('tags', $entry) && '' !== $entry['tags']) {
if (\array_key_exists('tags', $entry) && '' !== $entry['tags']) {
$data['tags'] = $entry['tags'];
}

View File

@ -57,7 +57,7 @@ class FirefoxImport extends BrowserImport
'created_at' => substr($entry['dateAdded'], 0, 10),
];
if (array_key_exists('tags', $entry) && '' !== $entry['tags']) {
if (\array_key_exists('tags', $entry) && '' !== $entry['tags']) {
$data['tags'] = $entry['tags'];
}

View File

@ -206,10 +206,10 @@ class PocketImport extends AbstractImport
$this->fetchContent($entry, $url);
// 0, 1, 2 - 1 if the item is archived - 2 if the item should be deleted
$entry->setArchived(1 === $importedEntry['status'] || $this->markAsRead);
$entry->setArchived(1 === (int) $importedEntry['status'] || $this->markAsRead);
// 0 or 1 - 1 If the item is starred
$entry->setStarred(1 === $importedEntry['favorite']);
// 0 or 1 - 1 if the item is starred
$entry->setStarred(1 === (int) $importedEntry['favorite']);
$title = 'Untitled';
if (isset($importedEntry['resolved_title']) && '' !== $importedEntry['resolved_title']) {

View File

@ -122,7 +122,7 @@ abstract class WallabagImport extends AbstractImport
// update entry with content (in case fetching failed, the given entry will be return)
$this->fetchContent($entry, $data['url'], $data);
if (array_key_exists('tags', $data)) {
if (\array_key_exists('tags', $data)) {
$this->tagsAssigner->assignTagsToEntry(
$entry,
$data['tags'],

View File

@ -61,7 +61,7 @@ class WallabagV1Import extends WallabagImport
$data['html'] = $this->fetchingErrorMessage;
}
if (array_key_exists('tags', $entry) && '' !== $entry['tags']) {
if (\array_key_exists('tags', $entry) && '' !== $entry['tags']) {
$data['tags'] = $entry['tags'];
}

View File

@ -74,7 +74,7 @@
<table cellpadding="0" cellspacing="0" border="0" align="center" id="card">
<tr>
<td style="padding: 20px;" width="96px" valign="top"><img class="image_fix" src="{{ absolute_url(asset('wallassets/themes/_global/img/logo-other_themes.png')) }}" alt="logo" title="{{ wallabag_url }}" style="width: 96px; height: 96px;" /></td>
<td style="padding: 20px;" width="96px" valign="top"><img class="image_fix" src="{{ absolute_url(asset('wallassets/themes/_global/img/logo-square.svg')) }}" alt="logo" title="{{ wallabag_url }}" style="width: 96px; height: 96px;" /></td>
<td style="padding: 20px; padding-left: 0;" valign="top" id="cell_desc">
<h1>wallabag</h1>
<h5>{{ "auth_code.on"|trans({}, 'wallabag_user') }} {{ wallabag_url }}</h5>

View File

@ -242,6 +242,15 @@ class EntryRestControllerTest extends WallabagApiTestCase
$this->assertSame(2, $content['limit']);
}
public function testGetStarredEntriesWithBadSort()
{
$this->client->request('GET', '/api/entries', ['starred' => 1, 'sort' => 'updated', 'order' => 'unknown']);
$this->assertSame(400, $this->client->getResponse()->getStatusCode());
$this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
}
public function testGetStarredEntries()
{
$this->client->request('GET', '/api/entries', ['starred' => 1, 'sort' => 'updated']);
@ -391,29 +400,71 @@ class EntryRestControllerTest extends WallabagApiTestCase
public function testDeleteEntry()
{
$entry = $this->client->getContainer()
->get('doctrine.orm.entity_manager')
->getRepository('WallabagCoreBundle:Entry')
->findOneByUser(1, ['id' => 'asc']);
$em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
$entry = new Entry($em->getReference(User::class, 1));
$entry->setUrl('http://0.0.0.0/test-delete-entry');
$entry->setTitle('Test delete entry');
$em->persist($entry);
$em->flush();
if (!$entry) {
$this->markTestSkipped('No content found in db.');
}
$em->clear();
$this->client->request('DELETE', '/api/entries/' . $entry->getId() . '.json');
$e = [
'title' => $entry->getTitle(),
'url' => $entry->getUrl(),
'id' => $entry->getId(),
];
$this->client->request('DELETE', '/api/entries/' . $e['id'] . '.json');
$this->assertSame(200, $this->client->getResponse()->getStatusCode());
$content = json_decode($this->client->getResponse()->getContent(), true);
$this->assertSame($entry->getTitle(), $content['title']);
$this->assertSame($entry->getUrl(), $content['url']);
$this->assertSame($entry->getId(), $content['id']);
$this->assertSame($e['title'], $content['title']);
$this->assertSame($e['url'], $content['url']);
$this->assertSame($e['id'], $content['id']);
// We'll try to delete this entry again
$this->client->request('DELETE', '/api/entries/' . $entry->getId() . '.json');
$client = $this->createAuthorizedClient();
$client->request('DELETE', '/api/entries/' . $e['id'] . '.json');
$this->assertSame(404, $this->client->getResponse()->getStatusCode());
$this->assertSame(404, $client->getResponse()->getStatusCode());
}
public function testDeleteEntryExpectId()
{
$em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
$entry = new Entry($em->getReference(User::class, 1));
$entry->setUrl('http://0.0.0.0/test-delete-entry-id');
$em->persist($entry);
$em->flush();
$em->clear();
$id = $entry->getId();
$this->client->request('DELETE', '/api/entries/' . $id . '.json?expect=id');
$this->assertSame(200, $this->client->getResponse()->getStatusCode());
$content = json_decode($this->client->getResponse()->getContent(), true);
$this->assertSame($id, $content['id']);
$this->assertArrayNotHasKey('url', $content);
// We'll try to delete this entry again
$client = $this->createAuthorizedClient();
$client->request('DELETE', '/api/entries/' . $id . '.json');
$this->assertSame(404, $client->getResponse()->getStatusCode());
}
public function testDeleteEntryExpectBadRequest()
{
$this->client->request('DELETE', '/api/entries/1.json?expect=badrequest');
$this->assertSame(400, $this->client->getResponse()->getStatusCode());
}
public function testPostEntry()

View File

@ -166,7 +166,7 @@ class EntryControllerTest extends WallabagCoreTestCase
$this->assertSame($this->url, $content->getUrl());
$this->assertContains('Google', $content->getTitle());
$this->assertSame('fr', $content->getLanguage());
$this->assertSame('2016-04-07 19:01:35', $content->getPublishedAt()->format('Y-m-d H:i:s'));
$this->assertSame('2015-03-28 11:43:19', $content->getPublishedAt()->format('Y-m-d H:i:s'));
$this->assertArrayHasKey('x-frame-options', $content->getHeaders());
$client->getContainer()->get('craue_config')->set('store_article_headers', 0);
}

View File

@ -5,26 +5,22 @@ namespace Tests\Wallabag\CoreBundle\GuzzleSiteAuthenticator;
use Graby\SiteConfig\SiteConfig as GrabySiteConfig;
use Monolog\Handler\TestHandler;
use Monolog\Logger;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
use Wallabag\CoreBundle\GuzzleSiteAuthenticator\GrabySiteConfigBuilder;
class GrabySiteConfigBuilderTest extends TestCase
class GrabySiteConfigBuilderTest extends WallabagCoreTestCase
{
/** @var \Wallabag\CoreBundle\GuzzleSiteAuthenticator\GrabySiteConfigBuilder */
protected $builder;
public function testBuildConfigExists()
{
/* @var \Graby\SiteConfig\ConfigBuilder|\PHPUnit_Framework_MockObject_MockObject */
$grabyConfigBuilderMock = $this->getMockBuilder('Graby\SiteConfig\ConfigBuilder')
->disableOriginalConstructor()
->getMock();
$grabySiteConfig = new GrabySiteConfig();
$grabySiteConfig->requires_login = true;
$grabySiteConfig->login_uri = 'http://www.example.com/login';
$grabySiteConfig->login_uri = 'http://api.example.com/login';
$grabySiteConfig->login_username_field = 'login';
$grabySiteConfig->login_password_field = 'password';
$grabySiteConfig->login_extra_fields = ['field=value'];
@ -32,7 +28,7 @@ class GrabySiteConfigBuilderTest extends TestCase
$grabyConfigBuilderMock
->method('buildForHost')
->with('example.com')
->with('api.example.com')
->will($this->returnValue($grabySiteConfig));
$logger = new Logger('foo');
@ -43,8 +39,8 @@ class GrabySiteConfigBuilderTest extends TestCase
->disableOriginalConstructor()
->getMock();
$siteCrentialRepo->expects($this->once())
->method('findOneByHostAndUser')
->with('example.com', 1)
->method('findOneByHostsAndUser')
->with(['api.example.com', '.example.com'], 1)
->willReturn(['username' => 'foo', 'password' => 'bar']);
$user = $this->getMockBuilder('Wallabag\UserBundle\Entity\User')
@ -59,18 +55,18 @@ class GrabySiteConfigBuilderTest extends TestCase
$tokenStorage = new TokenStorage();
$tokenStorage->setToken($token);
$this->builder = new GrabySiteConfigBuilder(
$builder = new GrabySiteConfigBuilder(
$grabyConfigBuilderMock,
$tokenStorage,
$siteCrentialRepo,
$logger
);
$config = $this->builder->buildForHost('www.example.com');
$config = $builder->buildForHost('api.example.com');
$this->assertSame('example.com', $config->getHost());
$this->assertSame('api.example.com', $config->getHost());
$this->assertTrue($config->requiresLogin());
$this->assertSame('http://www.example.com/login', $config->getLoginUri());
$this->assertSame('http://api.example.com/login', $config->getLoginUri());
$this->assertSame('login', $config->getUsernameField());
$this->assertSame('password', $config->getPasswordField());
$this->assertSame(['field' => 'value'], $config->getExtraFields());
@ -85,7 +81,6 @@ class GrabySiteConfigBuilderTest extends TestCase
public function testBuildConfigDoesntExist()
{
/* @var \Graby\SiteConfig\ConfigBuilder|\PHPUnit_Framework_MockObject_MockObject */
$grabyConfigBuilderMock = $this->getMockBuilder('\Graby\SiteConfig\ConfigBuilder')
->disableOriginalConstructor()
->getMock();
@ -103,8 +98,8 @@ class GrabySiteConfigBuilderTest extends TestCase
->disableOriginalConstructor()
->getMock();
$siteCrentialRepo->expects($this->once())
->method('findOneByHostAndUser')
->with('unknown.com', 1)
->method('findOneByHostsAndUser')
->with(['unknown.com', '.com'], 1)
->willReturn(null);
$user = $this->getMockBuilder('Wallabag\UserBundle\Entity\User')
@ -119,14 +114,14 @@ class GrabySiteConfigBuilderTest extends TestCase
$tokenStorage = new TokenStorage();
$tokenStorage->setToken($token);
$this->builder = new GrabySiteConfigBuilder(
$builder = new GrabySiteConfigBuilder(
$grabyConfigBuilderMock,
$tokenStorage,
$siteCrentialRepo,
$logger
);
$config = $this->builder->buildForHost('unknown.com');
$config = $builder->buildForHost('unknown.com');
$this->assertFalse($config);
@ -134,4 +129,121 @@ class GrabySiteConfigBuilderTest extends TestCase
$this->assertCount(1, $records, 'One log was recorded');
}
public function testBuildConfigUserNotDefined()
{
$grabyConfigBuilderMock = $this->getMockBuilder('\Graby\SiteConfig\ConfigBuilder')
->disableOriginalConstructor()
->getMock();
$grabyConfigBuilderMock
->method('buildForHost')
->with('unknown.com')
->will($this->returnValue(new GrabySiteConfig()));
$logger = new Logger('foo');
$handler = new TestHandler();
$logger->pushHandler($handler);
$siteCrentialRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\SiteCredentialRepository')
->disableOriginalConstructor()
->getMock();
$tokenStorage = new TokenStorage();
$builder = new GrabySiteConfigBuilder(
$grabyConfigBuilderMock,
$tokenStorage,
$siteCrentialRepo,
$logger
);
$config = $builder->buildForHost('unknown.com');
$this->assertFalse($config);
}
public function dataProviderCredentials()
{
return [
[
'host' => 'example.com',
],
[
'host' => 'other.example.com',
],
[
'host' => 'paywall.example.com',
'expectedUsername' => 'paywall.example',
'expectedPassword' => 'bar',
],
[
'host' => 'api.super.com',
'expectedUsername' => '.super',
'expectedPassword' => 'bar',
],
[
'host' => '.super.com',
'expectedUsername' => '.super',
'expectedPassword' => 'bar',
],
];
}
/**
* @dataProvider dataProviderCredentials
*/
public function testBuildConfigWithDbAccess($host, $expectedUsername = null, $expectedPassword = null)
{
$grabyConfigBuilderMock = $this->getMockBuilder('Graby\SiteConfig\ConfigBuilder')
->disableOriginalConstructor()
->getMock();
$grabySiteConfig = new GrabySiteConfig();
$grabySiteConfig->requires_login = true;
$grabySiteConfig->login_uri = 'http://api.example.com/login';
$grabySiteConfig->login_username_field = 'login';
$grabySiteConfig->login_password_field = 'password';
$grabySiteConfig->login_extra_fields = ['field=value'];
$grabySiteConfig->not_logged_in_xpath = '//div[@class="need-login"]';
$grabyConfigBuilderMock
->method('buildForHost')
->with($host)
->will($this->returnValue($grabySiteConfig));
$user = $this->getMockBuilder('Wallabag\UserBundle\Entity\User')
->disableOriginalConstructor()
->getMock();
$user->expects($this->once())
->method('getId')
->willReturn(1);
$token = new UsernamePasswordToken($user, 'pass', 'provider');
$tokenStorage = new TokenStorage();
$tokenStorage->setToken($token);
$logger = new Logger('foo');
$handler = new TestHandler();
$logger->pushHandler($handler);
$builder = new GrabySiteConfigBuilder(
$grabyConfigBuilderMock,
$tokenStorage,
$this->getClient()->getContainer()->get('wallabag_core.site_credential_repository'),
$logger
);
$config = $builder->buildForHost($host);
if (null === $expectedUsername && null === $expectedPassword) {
$this->assertFalse($config);
return;
}
$this->assertSame($expectedUsername, $config->getUsername());
$this->assertSame($expectedPassword, $config->getPassword());
}
}

View File

@ -226,6 +226,13 @@ class PocketImportTest extends TestCase
->method('getRepository')
->willReturn($entryRepo);
$this->em
->expects($this->any())
->method('persist')
->with($this->callback(function ($persistedEntry) {
return $persistedEntry->isArchived() && $persistedEntry->isStarred();
}));
$entry = new Entry($this->user);
$this->contentProxy

File diff suppressed because one or more lines are too long