Compare commits

..

1 Commits
2.3.5 ... 2.3.3

Author SHA1 Message Date
92cb8acae9 Release wallabag 2.3.3 2018-06-19 09:45:19 +02:00
118 changed files with 2463 additions and 4615 deletions

View File

@ -8,15 +8,9 @@
| Documentation | yes/no | Documentation | yes/no
| Translation | yes/no | Translation | yes/no
| CHANGELOG.md | yes/no | CHANGELOG.md | yes/no
| Fixed tickets | #...
| License | MIT | License | MIT
<!--
Please list the issues your PR fixes using special keywords, see
https://help.github.com/articles/closing-issues-using-keywords/
Fixes #…
-->
<!-- <!--
- Please fill in this template according to the PR you're about to submit. - Please fill in this template according to the PR you're about to submit.
- Replace this comment by a description of what your PR is solving. - Replace this comment by a description of what your PR is solving.

View File

@ -26,18 +26,3 @@ tools:
checks: checks:
php: php:
code_rating: true code_rating: true
# use the new PHP analysis engine
# https://scrutinizer-ci.com/docs/tools/php/php-analyzer/guides/migrate_to_new_php_analysis
build:
nodes:
analysis:
tests:
override:
- php-scrutinizer-run
dependencies:
override:
- npm install -g 'yarn'
- yarn install --force
- COMPOSER_MEMORY_LIMIT=-1 composer install -o --no-interaction --no-progress --prefer-dist

View File

@ -1,14 +1,17 @@
language: php language: php
services: services:
- rabbitmq - rabbitmq
- redis - redis
# faster builds on docker-container setup
sudo: false
# used for HHVM # used for HHVM
addons: addons:
apt: apt:
packages: packages:
- tidy - tidy
# cache vendor dirs # cache vendor dirs
cache: cache:
@ -41,6 +44,7 @@ matrix:
- php: 7.0 - php: 7.0
env: CS_FIXER=run VALIDATE_TRANSLATION_FILE=run ASSETS=build DB=sqlite env: CS_FIXER=run VALIDATE_TRANSLATION_FILE=run ASSETS=build DB=sqlite
allow_failures: allow_failures:
- php: 7.2
- php: nightly - php: nightly
# exclude v1 branches # exclude v1 branches
@ -48,14 +52,6 @@ branches:
except: except:
- legacy - legacy
before_install:
- if [[ $TRAVIS_REPO_SLUG = wallabag/wallabag ]]; then cp .composer-auth.json ~/.composer/auth.json; fi;
install:
- if [[ $ASSETS = build ]]; then source ~/.nvm/nvm.sh && nvm install 6.10; fi;
- if [[ $ASSETS = build ]]; then npm install -g yarn@latest; fi;
- if [[ $ASSETS = build ]]; then yarn install; fi;
before_script: before_script:
- PHP=$TRAVIS_PHP_VERSION - PHP=$TRAVIS_PHP_VERSION
- if [[ ! $PHP = hhvm* ]]; then echo "memory_limit=-1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; fi; - if [[ ! $PHP = hhvm* ]]; then echo "memory_limit=-1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; fi;
@ -63,17 +59,17 @@ before_script:
- if [[ ! $PHP = hhvm* ]]; then phpenv config-rm xdebug.ini || echo "xdebug not available"; fi - if [[ ! $PHP = hhvm* ]]; then phpenv config-rm xdebug.ini || echo "xdebug not available"; fi
- composer self-update --no-progress - composer self-update --no-progress
- if [[ $DB = pgsql ]]; then psql -c 'create database wallabag_test;' -U postgres; fi; - if [[ $DB = pgsql ]]; then psql -c 'create database wallabag_test;' -U postgres; fi;
# increase swap to avoid "proc_open(): fork failed - Cannot allocate memory"
# this should be removed when no more PHP 5 build will be defined install:
- sudo swapon -s - if [[ $ASSETS = build ]]; then source ~/.nvm/nvm.sh && nvm install 6.10; fi;
- sudo fallocate -l 4G /swapfile - if [[ $ASSETS = build ]]; then npm install -g yarn@latest; fi;
- sudo chmod 600 /swapfile - if [[ $ASSETS = build ]]; then yarn install; fi;
- sudo mkswap /swapfile
- sudo swapon /swapfile before_install:
- sudo swapon -s - if [[ $TRAVIS_REPO_SLUG = wallabag/wallabag ]]; then cp .composer-auth.json ~/.composer/auth.json; fi;
script: script:
- travis_wait bash composer update -o --no-interaction --no-progress --prefer-dist - travis_wait composer update --no-interaction --no-progress
- echo "travis_fold:start:prepare" - echo "travis_fold:start:prepare"
- make prepare DB=$DB - make prepare DB=$DB
- echo "travis_fold:end:prepare" - echo "travis_fold:end:prepare"

View File

@ -1,55 +1,5 @@
# Changelog # Changelog
## [2.3.5](https://github.com/wallabag/wallabag/tree/2.3.5)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.3.4...2.3.5)
### Fixes
- Jump to 2.3.5-dev and update release process [#3778](https://github.com/wallabag/wallabag/pull/3778)
- Remove preview picture from single entry view page [#3765](https://github.com/wallabag/wallabag/pull/3765)
- Fix Android app login issue [#3784](https://github.com/wallabag/wallabag/pull/3784)
- material: fix missing thumbnail on list view [#3782](https://github.com/wallabag/wallabag/pull/3782)
- material: decrease size of tags on list view [#3783](https://github.com/wallabag/wallabag/pull/3783)
- build: upgrade yarn dependencies, update prod assets [#3781](https://github.com/wallabag/wallabag/pull/3781)
- No more dev for guzzle-site-authenticator [#3810](https://github.com/wallabag/wallabag/pull/3810)
## [2.3.4](https://github.com/wallabag/wallabag/tree/2.3.4)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.3.3...2.3.4)
### Fixes
- Fix image downloading on null image path [#3684](https://github.com/wallabag/wallabag/pull/3684)
- Remove remaining deprecation notices [#3686](https://github.com/wallabag/wallabag/pull/3686)
- Fix mobile viewport on big iframe and video elements [#3683](https://github.com/wallabag/wallabag/pull/3683)
- Autofocus the username field on the login page [#3691](https://github.com/wallabag/wallabag/pull/3691)
- Feature/svg logo [#3692](https://github.com/wallabag/wallabag/pull/3692)
- Fixes a typo [#3702](https://github.com/wallabag/wallabag/pull/3702)
- Update release script [#3705](https://github.com/wallabag/wallabag/pull/3705)
- Removing failing test from Travis [#3707](https://github.com/wallabag/wallabag/pull/3707)
- Replace SO url by lemonde.fr to avoid random failing test [#3685](https://github.com/wallabag/wallabag/pull/3685)
- php-cs-fixer: native_function_invocation [#3716](https://github.com/wallabag/wallabag/pull/3716)
- PHP 7.2 shouldn't fail [#3717](https://github.com/wallabag/wallabag/pull/3717)
- Liberation goes https [#3726](https://github.com/wallabag/wallabag/pull/3726)
- Bugfix: Sanitize the title of a saved webpage from invalid UTF-8 characters. [#3725](https://github.com/wallabag/wallabag/pull/3725)
- Fix dockerfile php72 [#3734](https://github.com/wallabag/wallabag/pull/3734)
- Fix sort parameters [#3719](https://github.com/wallabag/wallabag/pull/3719)
- Add note on GitHub PR template to auto-close issues [#3763](https://github.com/wallabag/wallabag/pull/3763)
- Fix link to wallabag requirements in documentation [#3766](https://github.com/wallabag/wallabag/pull/3766)
- Update translation when marking as read [#3772](https://github.com/wallabag/wallabag/pull/3772)
- Makefile fixes for non GNU systems [#3706](https://github.com/wallabag/wallabag/pull/3706)
- Card no preview replaced by wallabag logo [#3774](https://github.com/wallabag/wallabag/pull/3774)
### Changes
- Propose YunoHost badge for installing [#3678](https://github.com/wallabag/wallabag/pull/3678)
- More robust srcset image attribute handling [#3690](https://github.com/wallabag/wallabag/pull/3690)
- Rename getBuilderByUser and refactor query for untagged entries [#3712](https://github.com/wallabag/wallabag/pull/3712)
- Show tags on non-image gallery preview card [#3743](https://github.com/wallabag/wallabag/pull/3743)
- add manifest.json for android pwa [#3606](https://github.com/wallabag/wallabag/pull/3606)
- Add placeholder image to card-based gallery entries page [#3745](https://github.com/wallabag/wallabag/pull/3745)
- Abort running install and update script if root [#3733](https://github.com/wallabag/wallabag/pull/3733)
- Swap entry url with origin url if graby provides an updated one [#3553](https://github.com/wallabag/wallabag/pull/3553)
## [2.3.3](https://github.com/wallabag/wallabag/tree/2.3.3) ## [2.3.3](https://github.com/wallabag/wallabag/tree/2.3.3)
[Full Changelog](https://github.com/wallabag/wallabag/compare/2.3.2...2.3.3) [Full Changelog](https://github.com/wallabag/wallabag/compare/2.3.2...2.3.3)

View File

@ -1,53 +0,0 @@
SHELL=bash
TMP_FOLDER=/tmp
RELEASE_FOLDER=wllbg-release
ENV ?= prod
help: ## Display this help menu
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
clean: ## Clear the application cache
rm -rf var/cache/*
install: ## Install wallabag with the latest version
@./scripts/install.sh $(ENV)
update: ## Update the wallabag installation to the latest version
@./scripts/update.sh $(ENV)
dev: ## Install the latest dev version
@./scripts/dev.sh
run: ## Run the wallabag built-in server
@php bin/console server:run --env=dev
build: ## Run webpack
@npm run build:$(ENV)
prepare: clean ## Prepare database for testsuite
ifdef DB
cp app/config/tests/parameters_test.$(DB).yml app/config/parameters_test.yml
endif
-php bin/console doctrine:database:drop --force --env=test
php bin/console doctrine:database:create --env=test
php bin/console doctrine:migrations:migrate --no-interaction --env=test
fixtures: ## Load fixtures into database
php bin/console doctrine:fixtures:load --no-interaction --env=test
test: prepare fixtures ## Launch wallabag testsuite
bin/simple-phpunit -v
release: ## Create a package. Need a VERSION parameter (eg: `make release VERSION=master`).
ifndef VERSION
$(error VERSION is not set)
endif
@./scripts/release.sh $(VERSION) $(TMP_FOLDER) $(RELEASE_FOLDER) $(ENV)
deploy: ## Deploy wallabag
@bundle exec cap staging deploy
.PHONY: help clean prepare install fixtures update build test release deploy run dev
.DEFAULT_GOAL := install

54
Makefile Normal file → Executable file
View File

@ -1,2 +1,52 @@
.DEFAULT: TMP_FOLDER=/tmp
gmake $@ RELEASE_FOLDER=wllbg-release
ENV ?= prod
help: ## Display this help menu
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
clean: ## Clear the application cache
rm -rf var/cache/*
install: ## Install wallabag with the latest version
@sh scripts/install.sh $(ENV)
update: ## Update the wallabag installation to the latest version
@sh scripts/update.sh $(ENV)
dev: ## Install the latest dev version
@sh scripts/dev.sh
run: ## Run the wallabag built-in server
@php bin/console server:run --env=dev
build: ## Run webpack
@npm run build:$(ENV)
prepare: clean ## Prepare database for testsuite
ifdef DB
cp app/config/tests/parameters_test.$(DB).yml app/config/parameters_test.yml
endif
-php bin/console doctrine:database:drop --force --env=test
php bin/console doctrine:database:create --env=test
php bin/console doctrine:migrations:migrate --no-interaction --env=test
fixtures: ## Load fixtures into database
php bin/console doctrine:fixtures:load --no-interaction --env=test
test: prepare fixtures ## Launch wallabag testsuite
bin/simple-phpunit -v
release: ## Create a package. Need a VERSION parameter (eg: `make release VERSION=master`).
ifndef VERSION
$(error VERSION is not set)
endif
@sh scripts/release.sh $(VERSION) $(TMP_FOLDER) $(RELEASE_FOLDER) $(ENV)
deploy: ## Deploy wallabag
@bundle exec cap staging deploy
.PHONY: help clean prepare install fixtures update build test release deploy run dev
.DEFAULT_GOAL := install

View File

@ -13,7 +13,7 @@ If you do not have your own server, consider [the wallabag.it hosting solution](
![wallabag logo](https://raw.githubusercontent.com/wallabag/logo/master/_default/typo-horizontal/png/sm/logo-typo-horizontal-black-no-bg-no-border-sm.png) ![wallabag logo](https://raw.githubusercontent.com/wallabag/logo/master/_default/typo-horizontal/png/sm/logo-typo-horizontal-black-no-bg-no-border-sm.png)
# Install wallabag # Install wallabag
Please read [the documentation to see the wallabag requirements](https://doc.wallabag.org/en/admin/installation/requirements.html). Please read [the documentation to see the wallabag requirements](http://doc.wallabag.org/en/master/user/installation.html#requirements).
Then you can install wallabag by executing the following commands: Then you can install wallabag by executing the following commands:
@ -24,11 +24,6 @@ cd wallabag && make install
Now, [configure a virtual host](https://doc.wallabag.org/en/admin/installation/virtualhosts.html) to use your wallabag. Now, [configure a virtual host](https://doc.wallabag.org/en/admin/installation/virtualhosts.html) to use your wallabag.
# Run on YunoHost
[![Install Wallabag with YunoHost](https://install-app.yunohost.org/install-with-yunohost.png)](https://install-app.yunohost.org/?app=wallabag2)
Wallabag app for [YunoHost](https://yunohost.org). See [here](https://github.com/YunoHost-Apps/wallabag2_ynh)
# License # License
Copyright © 2013-2018 Nicolas Lœuillet <nicolas@loeuillet.org> Copyright © 2013-2018 Nicolas Lœuillet <nicolas@loeuillet.org>
This work is free. You can redistribute it and/or modify it under the This work is free. You can redistribute it and/or modify it under the

View File

@ -4,17 +4,14 @@ A release is mostly a git tag of http://github.com/wallabag/wallabag, following
### Steps to release ### Steps to release
During this documentation, we assume the release is `$LAST_WALLABAG_RELEASE` (like 2.3.4). During this documentation, we assume the release is `$LAST_WALLABAG_RELEASE`.
#### Prepare the release #### Files to edit
- Update these files with new information - `app/config/wallabag.yml` (`wallabag_core.version`)
- `app/config/wallabag.yml` (`wallabag_core.version`) - `CHANGELOG.md`
- `CHANGELOG.md`
- Create a PR named "Prepare $LAST_WALLABAG_RELEASE release".
- Wait for test to be ok, merge it.
#### Create a new release on GitHub #### Create release on GitHub
- Run these commands to create the tag: - Run these commands to create the tag:
@ -29,8 +26,8 @@ SYMFONY_ENV=prod composer up --no-dev
```diff ```diff
script: script:
- - travis_wait bash composer install -o --no-interaction --no-progress --prefer-dist - - travis_wait bash composer install -o --no-interaction --no-progress --prefer-dist
+ - travis_wait bash composer update -o --no-interaction --no-progress --prefer-dist + - travis_wait composer update --no-interaction --no-progress
``` ```
- Then continue with these commands: - Then continue with these commands:
@ -45,14 +42,15 @@ git push origin release-$LAST_WALLABAG_RELEASE
- Run these command to create the package: - Run these command to create the package:
``` ```
make release VERSION=$LAST_WALLABAG_RELEASE make release master /tmp wllbg-release prod
``` ```
- [Create the new release on GitHub](https://github.com/wallabag/wallabag/releases/new) by targetting the `release-$LAST_WALLABAG_RELEASE` branch. You have to upload the package (generated previously). - [Create the new release on GitHub](https://github.com/wallabag/wallabag/releases/new). You have to upload on this page the package.
- Close the previously created pull request (**DO NOT MERGE IT**) and delete the `release-$LAST_WALLABAG_RELEASE` branch. - Delete the `release-$LAST_WALLABAG_RELEASE` branch and close the pull request (**DO NOT MERGE IT**).
- Update the URL shortener (used on `wllbg.org` to generate links like `https://wllbg.org/latest-v2-package` or `http://wllbg.org/latest-v2`) - Update the URL shortener (used on `wllbg.org` to generate links like `https://wllbg.org/latest-v2-package` or `http://wllbg.org/latest-v2`)
- Update [the downloads page](https://github.com/wallabag/wallabag.org/blob/master/content/pages/download.md) on the website (MD5 sum, release date)
- Update Dockerfile https://github.com/wallabag/docker (and create a new tag) - Update Dockerfile https://github.com/wallabag/docker (and create a new tag)
- Update wallabag.org website (downloads, MD5 sum, releases and new blog post) - Update wallabag.org website (downloads, releases and new blog post)
- Put the next patch version suffixed with `-dev` in `app/config/config.yml` (`wallabag_core.version`) - Put the next patch version suffixed with `-dev` in `app/config/config.yml` (`wallabag_core.version`)
- Drink a :beer:! - Drink a :beer:!

View File

@ -55,7 +55,7 @@ class Version20170719231144 extends WallabagMigration
} }
// Just in case... // Just in case...
if (\count($ids) > 0) { if (count($ids) > 0) {
// Merge tags // Merge tags
$this->addSql(' $this->addSql('
UPDATE ' . $this->getTable('entry_tag') . ' UPDATE ' . $this->getTable('entry_tag') . '

View File

@ -27,7 +27,7 @@ export: "export"
import: "import" import: "import"
misc: "misc" misc: "misc"
modify_settings: "apply" modify_settings: "apply"
piwik_host: Host of your website in Piwik (without http:// or https://) piwik_host: Host of your website in Piwik (without http:// ou https://)
piwik_site_id: ID of your website in Piwik piwik_site_id: ID of your website in Piwik
piwik_enabled: Enable Piwik piwik_enabled: Enable Piwik
demo_mode_enabled: "Enable demo mode? (Only used for the public wallabag demo)" demo_mode_enabled: "Enable demo mode? (Only used for the public wallabag demo)"
@ -37,4 +37,4 @@ download_images_enabled: Download images locally
restricted_access: Enable authentication for paywalled websites restricted_access: Enable authentication for paywalled websites
api_user_registration: Enable user to be registered using the API api_user_registration: Enable user to be registered using the API
store_article_headers: Enable if wallabag stores HTTP headers for each article store_article_headers: Enable if wallabag stores HTTP headers for each article
shaarli_share_origin_url: Enable sharing origin url to Shaarli, if the service is enabled shaarli_share_origin_url: Enable sharing origin url to Shaarli, if the service is enabled

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200"><path fill="none" d="M0 0h200v200H0z"/><path d="M75.899 72.438c1.597-.981 10.207-5.556 24.098.178 14.289 5.897 23.154.776 24.253.079-3.454-5.678-7.562-10.62-12.104-13.943.303-.083.612-.167.939-.263 6.023-1.742 7.553-6.842 7.875-11.21.364-4.954.616-5.03 1.692-9.487 1.032-4.281-.119-5.137-1.181-4.273-.572.465-5.552 1.616-8.505 3.919-4.768 3.72-7.707 10.794-9.039 14.706-.025.06-.205.604-.265.792-.621 1.498-1.857 1.494-1.857 1.494v.001c-.6-.065-1.202-.1-1.809-.1-.54 0-1.079.029-1.616.081-.012.002-.019 0-.031.001-1.581.233-2.45-1.697-2.632-2.157-1.847-5.304-6.816-15.763-17.984-18.577 0 0-2.028-1.554-1.41 1.074.588 2.511 1.804 5.049 1.534 8.741-.124 1.704-1.181 10.442 6.85 14.99.763.432 1.441.795 2.051 1.101-4.042 3.235-7.716 7.74-10.859 12.853zM128.626 152.353c-9.842-6.098-13.153-8.242-12.946-10.575 0 0 .002-.379.099-.957.239-1.236.995-3.348 3.407-4.552.079-.039.146-.084.208-.129 7.668-4.45 13.27-11.614 15.246-20.56-1.99 4.941-16.735 8.78-34.645 8.78-17.903 0-32.651-3.839-34.641-8.78.442 2.008 1.073 3.923 1.864 5.742.666 3.745 1.562 12.563-2.673 20.282-3.731 6.8-22.15 16.069-49.485 10.748 0 0-1.096-.766-1.428-.136-.491.932 1.517 1.685 3.583 2.229 19.031 5.04 47.756 2.989 56.777-4.443 4.116-3.388 5.704-7.953 6.107-12.865l.003.008s.11-1.287 1.719-.32c.461.277 2.125 1.36 2.39 2.585.232 1.743.248 3.883-.652 5.382-1.287 2.144-1.301 2.452.393 3.662 1.04.742 5.287 3.864 11.198 7.415.015.01.023.019.038.027 1.25.753 2.987 2.597 2.987 2.597 2.662 3.079 8.452 9.275 10.972 8.108 1.19-.551-.051-3.032-.051-3.032s1.98 2.571 3.043 1.694c.809-.668-.473-3.229-.473-3.229s1.729 1.499 2.757.944c1.258-.679-.187-4.614-10.079-10.627-9.896-6.018-12.578-6.94-12.814-9.626 0 0-.004-.135.004-.366.077-.593.414-1.847 1.852-1.712 2.141.346 4.348.531 6.608.531 2.587 0 5.107-.237 7.536-.69l.001.003s.127-.025.164-.031c.284-.036.838-.018.84.671-.09.873-.331 1.751-.845 2.519-1.447 2.168-.972 2.466.54 3.859.933.859 5.211 4.622 11.07 8.264.012.009.017.016.031.023 1.249.752 3.41 2.816 3.41 2.816v-.001c2.428 2.466 6.894 6.596 9.327 6.347 1.646-.168.306-3.002.306-3.002s2.078 2.006 3.099 1.416c1.142-.659-.474-2.755-.474-2.755s1.338.708 2.283.473c.948-.236 1.185-2.644-8.656-8.737z"/><path d="M117.631 83.452c-1.181 0-2.161.355-2.912 1.057-.76.71-1.144 1.531-1.144 2.438v16.056c0 2.154-.382 3.742-1.135 4.721-.728.946-1.892 1.406-3.556 1.406-1.703 0-2.863-.457-3.549-1.396-.716-.979-1.078-2.571-1.078-4.731V86.884c0-1.098-.5-1.996-1.448-2.596-1.289-.812-2.57-1.105-4.129-.587-.476.159-.924.366-1.333.615-.435.265-.802.597-1.093.985-.322.432-.486.901-.486 1.396v16.307c0 2.158-.363 3.75-1.079 4.73-.688.939-1.849 1.396-3.548 1.396-1.705 0-2.877-.459-3.584-1.401-.734-.979-1.107-2.57-1.107-4.726V86.947c0-.908-.384-1.728-1.145-2.438-.751-.702-1.751-1.057-2.973-1.057-1.258 0-2.296.352-3.085 1.045-.811.71-1.222 1.535-1.222 2.45v15.806c0 1.988.194 3.869.575 5.588.393 1.758 1.077 3.3 2.035 4.586.968 1.299 2.282 2.323 3.906 3.05 1.607.716 3.617 1.079 5.975 1.079 2.457 0 4.515-.455 6.115-1.354 1.342-.754 2.473-1.744 3.371-2.951.866 1.207 1.971 2.197 3.294 2.95 1.58.899 3.669 1.354 6.211 1.354 2.357 0 4.359-.364 5.947-1.081 1.601-.726 2.902-1.751 3.872-3.048.96-1.29 1.645-2.833 2.034-4.586.381-1.719.575-3.6.575-5.588V86.947c0-.911-.398-1.733-1.184-2.445-.767-.697-1.818-1.05-3.12-1.05z"/></svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 9.2 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -221,12 +221,6 @@ ol li:last-child {
padding-bottom: 0; padding-bottom: 0;
} }
iframe,
video {
max-width: 100%;
height: auto;
}
mark { mark {
padding: 0 0.2em; padding: 0 0.2em;
} }

View File

@ -116,6 +116,13 @@ main {
height: 13.5em; height: 13.5em;
} }
.card-image .preview,
.card-fullimage .preview {
height: 14em;
background: no-repeat 50%/cover;
display: block;
}
&.sw { &.sw {
max-width: 370px; max-width: 370px;
margin-left: auto; margin-left: auto;
@ -130,19 +137,6 @@ a.original:not(.waves-effect) {
display: block; display: block;
} }
.card .card-image .preview,
.card .card-fullimage .preview,
.card-stacked .preview {
height: 100%;
background: no-repeat 50%/cover;
background-color: #efefef;
display: block;
&--default {
background-size: contain;
}
}
.card-entry-labels li, .card-entry-labels li,
.card-tag-labels li { .card-tag-labels li {
margin: 10px 10px 10px auto; margin: 10px 10px 10px auto;
@ -211,21 +205,24 @@ a.original:not(.waves-effect) {
text-align: right; text-align: right;
} }
.card-preview { .preview {
max-width: 100px; max-width: 100px;
max-height: 50px; height: auto;
margin-right: 10px; margin-right: 10px;
flex: 1; flex: 1;
img {
max-width: 100%;
max-height: 100%;
}
} }
div.metadata { div.metadata {
.chip { .chip {
background-color: $blueAccentColor; background-color: $blueAccentColor;
padding: 0 7px; padding: 0 15px 0 10px;
margin: auto 2px; margin: auto 2px;
border-radius: 6px; border-radius: 6px;
line-height: 22px;
height: 22px;
a, a,
i { i {

View File

@ -24,10 +24,6 @@ main,
height: 100%; height: 100%;
} }
.typo-logo {
max-width: 150px;
}
#main { #main {
flex: 1 0 auto; flex: 1 0 auto;

View File

@ -26,6 +26,7 @@ framework:
engines: ['twig'] engines: ['twig']
default_locale: "%locale%" default_locale: "%locale%"
trusted_hosts: ~ trusted_hosts: ~
trusted_proxies: ~
session: session:
# handler_id set to null will use default session handler from php.ini # handler_id set to null will use default session handler from php.ini
handler_id: session.handler.native_file handler_id: session.handler.native_file

View File

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

View File

@ -83,7 +83,7 @@
"javibravo/simpleue": "^2.0", "javibravo/simpleue": "^2.0",
"symfony/dom-crawler": "^3.3.13", "symfony/dom-crawler": "^3.3.13",
"friendsofsymfony/jsrouting-bundle": "^1.6.3", "friendsofsymfony/jsrouting-bundle": "^1.6.3",
"bdunogier/guzzle-site-authenticator": "^1.0.0", "bdunogier/guzzle-site-authenticator": "^1.0.0@dev",
"defuse/php-encryption": "^2.1", "defuse/php-encryption": "^2.1",
"html2text/html2text": "^4.1" "html2text/html2text": "^4.1"
}, },
@ -91,7 +91,7 @@
"doctrine/doctrine-fixtures-bundle": "~2.2", "doctrine/doctrine-fixtures-bundle": "~2.2",
"doctrine/data-fixtures": "~1.1", "doctrine/data-fixtures": "~1.1",
"sensio/generator-bundle": "^3.0", "sensio/generator-bundle": "^3.0",
"symfony/phpunit-bridge": "3.4.x-dev", "symfony/phpunit-bridge": "^3.3",
"friendsofphp/php-cs-fixer": "~2.0", "friendsofphp/php-cs-fixer": "~2.0",
"m6web/redis-mock": "^2.0", "m6web/redis-mock": "^2.0",
"dama/doctrine-test-bundle": "^4.0" "dama/doctrine-test-bundle": "^4.0"

642
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -4,10 +4,10 @@ FROM php:fpm
ARG timezone='Europe/Paris' ARG timezone='Europe/Paris'
RUN apt-get update && apt-get install -y \ RUN apt-get update && apt-get install -y \
libmcrypt-dev libicu-dev libpq-dev libxml2-dev libpng-dev libjpeg-dev \ libmcrypt-dev libicu-dev libpq-dev libxml2-dev libpng12-dev libjpeg-dev \
&& /usr/local/bin/docker-php-ext-configure gd --with-jpeg-dir=/usr/include \ && /usr/local/bin/docker-php-ext-configure gd --with-jpeg-dir=/usr/include \
&& docker-php-ext-install \ && docker-php-ext-install \
iconv mbstring intl pdo pdo_mysql pdo_pgsql gd iconv mcrypt mbstring intl pdo pdo_mysql pdo_pgsql gd
RUN echo "date.timezone="$timezone > /usr/local/etc/php/conf.d/date_timezone.ini RUN echo "date.timezone="$timezone > /usr/local/etc/php/conf.d/date_timezone.ini

View File

@ -1,13 +1,13 @@
{ {
"name": "wallabag", "name": "wallabag",
"version": "2.3.3", "version": "2.2.2",
"description": "wallabag is a self hostable application for saving web pages", "description": "wallabag is a self hostable application for saving web pages",
"private": true, "private": true,
"directories": { "directories": {
"doc": "docs" "doc": "docs"
}, },
"engines": { "engines": {
"node": ">=6.10" "node": ">4.8"
}, },
"repository": { "repository": {
"type": "git", "type": "git",

0
scripts/dev.sh Executable file → Normal file
View File

14
scripts/install.sh Executable file → Normal file
View File

@ -2,20 +2,6 @@
# You can execute this file to install wallabag # You can execute this file to install wallabag
# eg: `sh install.sh prod` # eg: `sh install.sh prod`
IGNORE_ROOT_ARG="--ignore-root-warning"
IGNORE_ROOT=0
if [ "$1" == "$IGNORE_ROOT_ARG" ]; then
IGNORE_ROOT=1
fi
# Abort running this script if root
if [ "$IGNORE_ROOT" -eq 0 ] && [ "$EUID" == "0" ]; then
echo "Do not run this script as root!" >&2
echo "Use $IGNORE_ROOT_ARG to ignore this error." >&2
exit 1
fi
COMPOSER_COMMAND='composer' COMPOSER_COMMAND='composer'
DIR="${BASH_SOURCE}" DIR="${BASH_SOURCE}"

14
scripts/release.sh Executable file → Normal file
View File

@ -1,6 +1,6 @@
#! /usr/bin/env bash #! /usr/bin/env bash
# You can execute this file to create a new package for wallabag # You can execute this file to create a new package for wallabag
# eg: `sh release.sh 2.3.3 /tmp wllbg-release prod` # eg: `sh release.sh master /tmp wllbg-release prod`
VERSION=$1 VERSION=$1
TMP_FOLDER=$2 TMP_FOLDER=$2
@ -9,12 +9,12 @@ ENV=$4
rm -rf $TMP_FOLDER/$RELEASE_FOLDER rm -rf $TMP_FOLDER/$RELEASE_FOLDER
mkdir $TMP_FOLDER/$RELEASE_FOLDER mkdir $TMP_FOLDER/$RELEASE_FOLDER
git clone git@github.com:wallabag/wallabag.git -b release-$VERSION $TMP_FOLDER/$RELEASE_FOLDER/$VERSION git clone git@github.com:wallabag/wallabag.git -b $VERSION $TMP_FOLDER/$RELEASE_FOLDER/$VERSION
cd $TMP_FOLDER/$RELEASE_FOLDER/$VERSION && SYMFONY_ENV=$ENV COMPOSER_MEMORY_LIMIT=-1 composer up -n --no-dev cd $TMP_FOLDER/$RELEASE_FOLDER/$VERSION && SYMFONY_ENV=$ENV composer up -n --no-dev
cd $TMP_FOLDER/$RELEASE_FOLDER/$VERSION && php bin/console wallabag:install --env=$ENV -n cd $TMP_FOLDER/$RELEASE_FOLDER/$VERSION && php bin/console wallabag:install --env=$ENV
cd $TMP_FOLDER/$RELEASE_FOLDER/$VERSION && php bin/console assets:install --env=$ENV --symlink --relative cd $TMP_FOLDER/$RELEASE_FOLDER/$VERSION && php bin/console assets:install --env=$ENV --symlink --relative
cd $TMP_FOLDER/$RELEASE_FOLDER && tar czf wallabag-$VERSION.tar.gz --exclude="var/cache/*" --exclude="var/logs/*" --exclude="var/sessions/*" --exclude=".git" $VERSION cd $TMP_FOLDER/$RELEASE_FOLDER && tar czf wallabag-$VERSION.tar.gz --exclude="var/cache/*" --exclude="var/logs/*" --exclude="var/sessions/*" --exclude=".git" $VERSION
echo "MD5 checksum of the package for wallabag $VERSION" echo "MD5 checksum of the package for wallabag $VERSION"
md5 $TMP_FOLDER/$RELEASE_FOLDER/wallabag-release-$VERSION.tar.gz md5 $TMP_FOLDER/$RELEASE_FOLDER/wallabag-$VERSION.tar.gz
echo "Package to upload to the release server:" scp $TMP_FOLDER/$RELEASE_FOLDER/wallabag-$VERSION.tar.gz framasoft_bag@78.46.248.87:/var/www/framabag.org/web
echo $TMP_FOLDER/$RELEASE_FOLDER/wallabag-release-$VERSION.tar.gz rm -rf $TMP_FOLDER/$RELEASE_FOLDER

0
scripts/require.sh Executable file → Normal file
View File

14
scripts/update.sh Executable file → Normal file
View File

@ -2,20 +2,6 @@
# You can execute this file to update wallabag # You can execute this file to update wallabag
# eg: `sh update.sh prod` # eg: `sh update.sh prod`
IGNORE_ROOT_ARG="--ignore-root-warning"
IGNORE_ROOT=0
if [ "$1" == "$IGNORE_ROOT_ARG" ]; then
IGNORE_ROOT=1
fi
# Abort running this script if root
if [ "$IGNORE_ROOT" -eq 0 ] && [ "$EUID" == "0" ]; then
echo "Do not run this script as root!" >&2
echo "Use $IGNORE_ROOT_ARG to ignore this error." >&2
exit 1
fi
set -e set -e
set -u set -u

View File

@ -28,7 +28,7 @@ class WallabagAnnotationController extends FOSRestController
->getDoctrine() ->getDoctrine()
->getRepository('WallabagAnnotationBundle:Annotation') ->getRepository('WallabagAnnotationBundle:Annotation')
->findAnnotationsByPageId($entry->getId(), $this->getUser()->getId()); ->findAnnotationsByPageId($entry->getId(), $this->getUser()->getId());
$total = \count($annotationRows); $total = count($annotationRows);
$annotations = ['total' => $total, 'rows' => $annotationRows]; $annotations = ['total' => $total, 'rows' => $annotationRows];
$json = $this->get('jms_serializer')->serialize($annotations, 'json'); $json = $this->get('jms_serializer')->serialize($annotations, 'json');

View File

@ -21,7 +21,7 @@ class AnnotationRepository extends EntityRepository
public function getBuilderForAllByUser($userId) public function getBuilderForAllByUser($userId)
{ {
return $this return $this
->getSortedQueryBuilderByUser($userId) ->getBuilderByUser($userId)
; ;
} }
@ -133,7 +133,7 @@ class AnnotationRepository extends EntityRepository
* *
* @return QueryBuilder * @return QueryBuilder
*/ */
private function getSortedQueryBuilderByUser($userId) private function getBuilderByUser($userId)
{ {
return $this->createQueryBuilder('a') return $this->createQueryBuilder('a')
->leftJoin('a.user', 'u') ->leftJoin('a.user', 'u')

View File

@ -102,7 +102,7 @@ class EntryRestController extends WallabagRestController
$order = $request->query->get('order', 'desc'); $order = $request->query->get('order', 'desc');
$page = (int) $request->query->get('page', 1); $page = (int) $request->query->get('page', 1);
$perPage = (int) $request->query->get('perPage', 30); $perPage = (int) $request->query->get('perPage', 30);
$tags = \is_array($request->query->get('tags')) ? '' : (string) $request->query->get('tags', ''); $tags = is_array($request->query->get('tags')) ? '' : (string) $request->query->get('tags', '');
$since = $request->query->get('since', 0); $since = $request->query->get('since', 0);
/** @var \Pagerfanta\Pagerfanta $pager */ /** @var \Pagerfanta\Pagerfanta $pager */
@ -253,7 +253,7 @@ class EntryRestController extends WallabagRestController
$limit = $this->container->getParameter('wallabag_core.api_limit_mass_actions'); $limit = $this->container->getParameter('wallabag_core.api_limit_mass_actions');
if (\count($urls) > $limit) { if (count($urls) > $limit) {
throw new HttpException(400, 'API limit reached'); throw new HttpException(400, 'API limit reached');
} }
@ -347,7 +347,7 @@ class EntryRestController extends WallabagRestController
'open_graph' => [ 'open_graph' => [
'og_image' => !empty($data['picture']) ? $data['picture'] : $entry->getPreviewPicture(), 'og_image' => !empty($data['picture']) ? $data['picture'] : $entry->getPreviewPicture(),
], ],
'authors' => \is_string($data['authors']) ? explode(',', $data['authors']) : $entry->getPublishedBy(), 'authors' => is_string($data['authors']) ? explode(',', $data['authors']) : $entry->getPublishedBy(),
] ]
); );
} catch (\Exception $e) { } catch (\Exception $e) {
@ -461,7 +461,7 @@ class EntryRestController extends WallabagRestController
$contentProxy->updateLanguage($entry, $data['language']); $contentProxy->updateLanguage($entry, $data['language']);
} }
if (!empty($data['authors']) && \is_string($data['authors'])) { if (!empty($data['authors']) && is_string($data['authors'])) {
$entry->setPublishedBy(explode(',', $data['authors'])); $entry->setPublishedBy(explode(',', $data['authors']));
} }

View File

@ -138,14 +138,14 @@ class TagRestController extends WallabagRestController
*/ */
private function cleanOrphanTag($tags) private function cleanOrphanTag($tags)
{ {
if (!\is_array($tags)) { if (!is_array($tags)) {
$tags = [$tags]; $tags = [$tags];
} }
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
foreach ($tags as $tag) { foreach ($tags as $tag) {
if (0 === \count($tag->getEntries())) { if (0 === count($tag->getEntries())) {
$em->remove($tag); $em->remove($tag);
} }
} }

View File

@ -51,7 +51,7 @@ class CleanDuplicatesCommand extends ContainerAwareCommand
} else { } else {
$users = $this->getContainer()->get('wallabag_user.user_repository')->findAll(); $users = $this->getContainer()->get('wallabag_user.user_repository')->findAll();
$this->io->text(sprintf('Cleaning through <info>%d</info> user accounts', \count($users))); $this->io->text(sprintf('Cleaning through <info>%d</info> user accounts', count($users)));
foreach ($users as $user) { foreach ($users as $user) {
$this->io->text(sprintf('Processing user <info>%s</info>', $user->getUsername())); $this->io->text(sprintf('Processing user <info>%s</info>', $user->getUsername()));
@ -79,7 +79,7 @@ class CleanDuplicatesCommand extends ContainerAwareCommand
$url = $this->similarUrl($entry['url']); $url = $this->similarUrl($entry['url']);
/* @var $entry Entry */ /* @var $entry Entry */
if (\in_array($url, $urls, true)) { if (in_array($url, $urls, true)) {
++$duplicatesCount; ++$duplicatesCount;
$em->remove($repo->find($entry['id'])); $em->remove($repo->find($entry['id']));
@ -96,8 +96,8 @@ class CleanDuplicatesCommand extends ContainerAwareCommand
private function similarUrl($url) private function similarUrl($url)
{ {
if (\in_array(substr($url, -1), ['/', '#'], true)) { // get rid of "/" and "#" and the end of urls if (in_array(substr($url, -1), ['/', '#'], true)) { // get rid of "/" and "#" and the end of urls
return substr($url, 0, \strlen($url)); return substr($url, 0, strlen($url));
} }
return $url; return $url;

View File

@ -47,7 +47,7 @@ class ExportCommand extends ContainerAwareCommand
->getQuery() ->getQuery()
->getResult(); ->getResult();
$io->text(sprintf('Exporting <info>%d</info> entrie(s) for user <info>%s</info>...', \count($entries), $user->getUserName())); $io->text(sprintf('Exporting <info>%d</info> entrie(s) for user <info>%s</info>...', count($entries), $user->getUserName()));
$filePath = $input->getArgument('filepath'); $filePath = $input->getArgument('filepath');

View File

@ -81,7 +81,7 @@ class InstallCommand extends ContainerAwareCommand
$status = '<info>OK!</info>'; $status = '<info>OK!</info>';
$help = ''; $help = '';
if (!\extension_loaded($this->getContainer()->getParameter('database_driver'))) { if (!extension_loaded($this->getContainer()->getParameter('database_driver'))) {
$fulfilled = false; $fulfilled = false;
$status = '<error>ERROR!</error>'; $status = '<error>ERROR!</error>';
$help = 'Database driver "' . $this->getContainer()->getParameter('database_driver') . '" is not installed.'; $help = 'Database driver "' . $this->getContainer()->getParameter('database_driver') . '" is not installed.';
@ -146,7 +146,7 @@ class InstallCommand extends ContainerAwareCommand
$status = '<info>OK!</info>'; $status = '<info>OK!</info>';
$help = ''; $help = '';
if (!\function_exists($functionRequired)) { if (!function_exists($functionRequired)) {
$fulfilled = false; $fulfilled = false;
$status = '<error>ERROR!</error>'; $status = '<error>ERROR!</error>';
$help = 'You need the ' . $functionRequired . ' function activated'; $help = 'You need the ' . $functionRequired . ' function activated';
@ -371,7 +371,7 @@ class InstallCommand extends ContainerAwareCommand
} }
try { try {
return \in_array($databaseName, $schemaManager->listDatabases(), true); return in_array($databaseName, $schemaManager->listDatabases(), true);
} catch (\Doctrine\DBAL\Exception\DriverException $e) { } catch (\Doctrine\DBAL\Exception\DriverException $e) {
// it means we weren't able to get database list, assume the database doesn't exist // it means we weren't able to get database list, assume the database doesn't exist
@ -389,6 +389,6 @@ class InstallCommand extends ContainerAwareCommand
{ {
$schemaManager = $this->getContainer()->get('doctrine')->getManager()->getConnection()->getSchemaManager(); $schemaManager = $this->getContainer()->get('doctrine')->getManager()->getConnection()->getSchemaManager();
return \count($schemaManager->listTableNames()) > 0 ? true : false; return count($schemaManager->listTableNames()) > 0 ? true : false;
} }
} }

View File

@ -50,7 +50,7 @@ class ListUserCommand extends ContainerAwareCommand
$io->success( $io->success(
sprintf( sprintf(
'%s/%s%s user(s) displayed.', '%s/%s%s user(s) displayed.',
\count($users), count($users),
$nbUsers, $nbUsers,
null === $input->getArgument('search') ? '' : ' (filtered)' null === $input->getArgument('search') ? '' : ' (filtered)'
) )

View File

@ -43,7 +43,7 @@ class ReloadEntryCommand extends ContainerAwareCommand
$entryRepository = $this->getContainer()->get('wallabag_core.entry_repository'); $entryRepository = $this->getContainer()->get('wallabag_core.entry_repository');
$entryIds = $entryRepository->findAllEntriesIdByUserId($userId); $entryIds = $entryRepository->findAllEntriesIdByUserId($userId);
$nbEntries = \count($entryIds); $nbEntries = count($entryIds);
if (!$nbEntries) { if (!$nbEntries) {
$io->success('No entry to reload.'); $io->success('No entry to reload.');

View File

@ -348,7 +348,7 @@ class ConfigController extends Controller
$em = $this->getDoctrine()->getManager(); $em = $this->getDoctrine()->getManager();
foreach ($tags as $tag) { foreach ($tags as $tag) {
if (0 === \count($tag->getEntries())) { if (0 === count($tag->getEntries())) {
$em->remove($tag); $em->remove($tag);
} }
} }

View File

@ -65,7 +65,7 @@ class TagController extends Controller
$em->flush(); $em->flush();
// remove orphan tag in case no entries are associated to it // remove orphan tag in case no entries are associated to it
if (0 === \count($tag->getEntries())) { if (0 === count($tag->getEntries())) {
$em->remove($tag); $em->remove($tag);
$em->flush(); $em->flush();
} }

View File

@ -33,7 +33,7 @@ class EntryFilterType extends AbstractType
$this->user = $tokenStorage->getToken() ? $tokenStorage->getToken()->getUser() : null; $this->user = $tokenStorage->getToken() ? $tokenStorage->getToken()->getUser() : null;
if (null === $this->user || !\is_object($this->user)) { if (null === $this->user || !is_object($this->user)) {
return; return;
} }
} }
@ -96,7 +96,7 @@ class EntryFilterType extends AbstractType
->add('domainName', TextFilterType::class, [ ->add('domainName', TextFilterType::class, [
'apply_filter' => function (QueryInterface $filterQuery, $field, $values) { 'apply_filter' => function (QueryInterface $filterQuery, $field, $values) {
$value = $values['value']; $value = $values['value'];
if (\strlen($value) <= 2 || empty($value)) { if (strlen($value) <= 2 || empty($value)) {
return; return;
} }
$expression = $filterQuery->getExpr()->like($field, $filterQuery->getExpr()->lower($filterQuery->getExpr()->literal('%' . $value . '%'))); $expression = $filterQuery->getExpr()->like($field, $filterQuery->getExpr()->lower($filterQuery->getExpr()->literal('%' . $value . '%')));

View File

@ -107,7 +107,7 @@ class GrabySiteConfigBuilder implements SiteConfigBuilder
*/ */
protected function processExtraFields($extraFieldsStrings) protected function processExtraFields($extraFieldsStrings)
{ {
if (!\is_array($extraFieldsStrings)) { if (!is_array($extraFieldsStrings)) {
return []; return [];
} }

View File

@ -53,7 +53,6 @@ class ContentProxy
if ((empty($content) || false === $this->validateContent($content)) && false === $disableContentUpdate) { if ((empty($content) || false === $this->validateContent($content)) && false === $disableContentUpdate) {
$fetchedContent = $this->graby->fetchContent($url); $fetchedContent = $this->graby->fetchContent($url);
$fetchedContent['title'] = $this->sanitizeContentTitle($fetchedContent['title'], $fetchedContent['content_type']);
// when content is imported, we have information in $content // when content is imported, we have information in $content
// in case fetching content goes bad, we'll keep the imported information instead of overriding them // in case fetching content goes bad, we'll keep the imported information instead of overriding them
@ -66,13 +65,6 @@ class ContentProxy
// so we'll be able to refetch it in the future // so we'll be able to refetch it in the future
$content['url'] = !empty($content['url']) ? $content['url'] : $url; $content['url'] = !empty($content['url']) ? $content['url'] : $url;
// In one case (at least in tests), url is empty here
// so we set it using $url provided in the updateEntry call.
// Not sure what are the other possible cases where this property is empty
if (empty($entry->getUrl()) && !empty($url)) {
$entry->setUrl($url);
}
$this->stockEntry($entry, $content); $this->stockEntry($entry, $content);
} }
@ -93,7 +85,7 @@ class ContentProxy
(new LocaleConstraint()) (new LocaleConstraint())
); );
if (0 === \count($errors)) { if (0 === count($errors)) {
$entry->setLanguage($value); $entry->setLanguage($value);
return; return;
@ -115,7 +107,7 @@ class ContentProxy
(new UrlConstraint()) (new UrlConstraint())
); );
if (0 === \count($errors)) { if (0 === count($errors)) {
$entry->setPreviewPicture($value); $entry->setPreviewPicture($value);
return; return;
@ -184,59 +176,6 @@ class ContentProxy
$entry->setTitle($path); $entry->setTitle($path);
} }
/**
* Try to sanitize the title of the fetched content from wrong character encodings and invalid UTF-8 character.
*
* @param $title
* @param $contentType
*
* @return string
*/
private function sanitizeContentTitle($title, $contentType)
{
if ('application/pdf' === $contentType) {
$title = $this->convertPdfEncodingToUTF8($title);
}
return $this->sanitizeUTF8Text($title);
}
/**
* If the title from the fetched content comes from a PDF, then its very possible that the character encoding is not
* UTF-8. This methods tries to identify the character encoding and translate the title to UTF-8.
*
* @param $title
*
* @return string (maybe contains invalid UTF-8 character)
*/
private function convertPdfEncodingToUTF8($title)
{
// first try UTF-8 because its easier to detect its present/absence
foreach (['UTF-8', 'UTF-16BE', 'WINDOWS-1252'] as $encoding) {
if (mb_check_encoding($title, $encoding)) {
return mb_convert_encoding($title, 'UTF-8', $encoding);
}
}
return $title;
}
/**
* Remove invalid UTF-8 characters from the given string.
*
* @param string $rawText
*
* @return string
*/
private function sanitizeUTF8Text($rawText)
{
if (mb_check_encoding($rawText, 'UTF-8')) {
return $rawText;
}
return iconv('UTF-8', 'UTF-8//IGNORE', $rawText);
}
/** /**
* Stock entry with fetched or imported content. * Stock entry with fetched or imported content.
* Will fall back to OpenGraph data if available. * Will fall back to OpenGraph data if available.
@ -246,7 +185,7 @@ class ContentProxy
*/ */
private function stockEntry(Entry $entry, array $content) private function stockEntry(Entry $entry, array $content)
{ {
$this->updateOriginUrl($entry, $content['url']); $entry->setUrl($content['url']);
$this->setEntryDomainName($entry); $this->setEntryDomainName($entry);
@ -273,7 +212,7 @@ class ContentProxy
$entry->setHttpStatus($content['status']); $entry->setHttpStatus($content['status']);
} }
if (!empty($content['authors']) && \is_array($content['authors'])) { if (!empty($content['authors']) && is_array($content['authors'])) {
$entry->setPublishedBy($content['authors']); $entry->setPublishedBy($content['authors']);
} }
@ -294,7 +233,7 @@ class ContentProxy
} }
// if content is an image, define it as a preview too // if content is an image, define it as a preview too
if (!empty($content['content_type']) && \in_array($this->mimeGuesser->guess($content['content_type']), ['jpeg', 'jpg', 'gif', 'png'], true)) { if (!empty($content['content_type']) && in_array($this->mimeGuesser->guess($content['content_type']), ['jpeg', 'jpg', 'gif', 'png'], true)) {
$this->updatePreviewPicture($entry, $content['url']); $this->updatePreviewPicture($entry, $content['url']);
} }
@ -312,115 +251,6 @@ class ContentProxy
} }
} }
/**
* Update the origin_url field when a redirection occurs
* This field is set if it is empty and new url does not match ignore list.
*
* @param Entry $entry
* @param string $url
*/
private function updateOriginUrl(Entry $entry, $url)
{
if (empty($url) || $entry->getUrl() === $url) {
return false;
}
$parsed_entry_url = parse_url($entry->getUrl());
$parsed_content_url = parse_url($url);
/**
* The following part computes the list of part changes between two
* parse_url arrays.
*
* As array_diff_assoc only computes changes to go from the left array
* to the right one, we make two differents arrays to have both
* directions. We merge these two arrays and sort keys before passing
* the result to the switch.
*
* The resulting array gives us all changing parts between the two
* urls: scheme, host, path, query and/or fragment.
*/
$diff_ec = array_diff_assoc($parsed_entry_url, $parsed_content_url);
$diff_ce = array_diff_assoc($parsed_content_url, $parsed_entry_url);
$diff = array_merge($diff_ec, $diff_ce);
$diff_keys = array_keys($diff);
sort($diff_keys);
if ($this->ignoreUrl($entry->getUrl())) {
$entry->setUrl($url);
return false;
}
/**
* This switch case lets us apply different behaviors according to
* changing parts of urls.
*
* As $diff_keys is an array, we provide arrays as cases. ['path'] means
* 'only the path is different between the two urls' whereas
* ['fragment', 'query'] means 'only fragment and query string parts are
* different between the two urls'.
*
* Note that values in $diff_keys are sorted.
*/
switch ($diff_keys) {
case ['path']:
if (($parsed_entry_url['path'] . '/' === $parsed_content_url['path']) // diff is trailing slash, we only replace the url of the entry
|| ($url === urldecode($entry->getUrl()))) { // we update entry url if new url is a decoded version of it, see EntryRepository#findByUrlAndUserId
$entry->setUrl($url);
}
break;
case ['scheme']:
$entry->setUrl($url);
break;
case ['fragment']:
// noop
break;
default:
if (empty($entry->getOriginUrl())) {
$entry->setOriginUrl($entry->getUrl());
}
$entry->setUrl($url);
break;
}
}
/**
* Check entry url against an ignore list to replace with content url.
*
* XXX: move the ignore list in the database to let users handle it
*
* @param string $url url to test
*
* @return bool true if url matches ignore list otherwise false
*/
private function ignoreUrl($url)
{
$ignored_hosts = ['feedproxy.google.com', 'feeds.reuters.com'];
$ignored_patterns = ['https?://www\.lemonde\.fr/tiny.*'];
$parsed_url = parse_url($url);
$filtered = array_filter($ignored_hosts, function ($var) use ($parsed_url) {
return $var === $parsed_url['host'];
});
if ([] !== $filtered) {
return true;
}
$filtered = array_filter($ignored_patterns, function ($var) use ($url) {
return preg_match("`$var`i", $url);
});
if ([] !== $filtered) {
return true;
}
return false;
}
/** /**
* Validate that the given content has at least a title, an html and a url. * Validate that the given content has at least a title, an html and a url.
* *

View File

@ -81,6 +81,6 @@ class CryptoProxy
*/ */
private function mask($value) private function mask($value)
{ {
return \strlen($value) > 0 ? $value[0] . '*****' . $value[\strlen($value) - 1] : 'Empty value'; return strlen($value) > 0 ? $value[0] . '*****' . $value[strlen($value) - 1] : 'Empty value';
} }
} }

View File

@ -85,10 +85,6 @@ class DownloadImages
*/ */
public function processSingleImage($entryId, $imagePath, $url, $relativePath = null) public function processSingleImage($entryId, $imagePath, $url, $relativePath = null)
{ {
if (null === $imagePath) {
return false;
}
if (null === $relativePath) { if (null === $relativePath) {
$relativePath = $this->getRelativePath($entryId); $relativePath = $this->getRelativePath($entryId);
} }
@ -185,7 +181,7 @@ class DownloadImages
* *
* @return array An array of urls * @return array An array of urls
*/ */
private function getSrcsetUrls(Crawler $imagesCrawler) protected function getSrcsetUrls(Crawler $imagesCrawler)
{ {
$urls = []; $urls = [];
$iterator = $imagesCrawler $iterator = $imagesCrawler
@ -193,14 +189,9 @@ class DownloadImages
while ($iterator->valid()) { while ($iterator->valid()) {
$srcsetAttribute = $iterator->current()->getAttribute('srcset'); $srcsetAttribute = $iterator->current()->getAttribute('srcset');
if ('' !== $srcsetAttribute) { if ('' !== $srcsetAttribute) {
// Couldn't start with " OR ' OR a white space $srcset = array_map('trim', explode(',', $srcsetAttribute));
// Could be one or more white space
// Must be one or more digits followed by w OR x
$pattern = "/(?:[^\"'\s]+\s*(?:\d+[wx])+)/";
preg_match_all($pattern, $srcsetAttribute, $matches);
$srcset = \call_user_func_array('array_merge', $matches);
$srcsetUrls = array_map(function ($src) { $srcsetUrls = array_map(function ($src) {
return trim(explode(' ', $src, 2)[0]); return explode(' ', $src)[0];
}, $srcset); }, $srcset);
$urls = array_merge($srcsetUrls, $urls); $urls = array_merge($srcsetUrls, $urls);
} }
@ -308,7 +299,7 @@ class DownloadImages
$this->logger->debug('DownloadImages: Checking extension (alternative)', ['ext' => $ext]); $this->logger->debug('DownloadImages: Checking extension (alternative)', ['ext' => $ext]);
} }
if (!\in_array($ext, ['jpeg', 'jpg', 'gif', 'png'], true)) { if (!in_array($ext, ['jpeg', 'jpg', 'gif', 'png'], true)) {
$this->logger->error('DownloadImages: Processed image with not allowed extension. Skipping: ' . $imagePath); $this->logger->error('DownloadImages: Processed image with not allowed extension. Skipping: ' . $imagePath);
return false; return false;

View File

@ -45,7 +45,7 @@ class EntriesExport
*/ */
public function setEntries($entries) public function setEntries($entries)
{ {
if (!\is_array($entries)) { if (!is_array($entries)) {
$this->language = $entries->getLanguage(); $this->language = $entries->getLanguage();
$entries = [$entries]; $entries = [$entries];
} }
@ -325,7 +325,7 @@ class EntriesExport
{ {
$delimiter = ';'; $delimiter = ';';
$enclosure = '"'; $enclosure = '"';
$handle = fopen('php://memory', 'b+r'); $handle = fopen('php://memory', 'rb+');
fputcsv($handle, ['Title', 'URL', 'Content', 'Tags', 'MIME Type', 'Language', 'Creation date'], $delimiter, $enclosure); fputcsv($handle, ['Title', 'URL', 'Content', 'Tags', 'MIME Type', 'Language', 'Creation date'], $delimiter, $enclosure);

View File

@ -31,7 +31,7 @@ class PreparePagerForEntries
$user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null; $user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null;
} }
if (null === $user || !\is_object($user)) { if (null === $user || !is_object($user)) {
return; return;
} }

View File

@ -31,7 +31,7 @@ class Redirect
{ {
$user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null; $user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null;
if (null === $user || !\is_object($user)) { if (null === $user || !is_object($user)) {
return $url; return $url;
} }

View File

@ -32,7 +32,7 @@ class TagsAssigner
{ {
$tagsEntities = []; $tagsEntities = [];
if (!\is_array($tags)) { if (!is_array($tags)) {
$tags = explode(',', $tags); $tags = explode(',', $tags);
} }
@ -48,7 +48,7 @@ class TagsAssigner
$label = trim(mb_convert_case($label, MB_CASE_LOWER)); $label = trim(mb_convert_case($label, MB_CASE_LOWER));
// avoid empty tag // avoid empty tag
if (0 === \strlen($label)) { if (0 === strlen($label)) {
continue; continue;
} }

View File

@ -36,7 +36,7 @@ class UsernameRssTokenConverter implements ParamConverterInterface
{ {
// If there is no manager, this means that only Doctrine DBAL is configured // If there is no manager, this means that only Doctrine DBAL is configured
// In this case we can do nothing and just return // In this case we can do nothing and just return
if (null === $this->registry || !\count($this->registry->getManagers())) { if (null === $this->registry || !count($this->registry->getManagers())) {
return false; return false;
} }

View File

@ -21,7 +21,7 @@ class EntryRepository extends EntityRepository
public function getBuilderForAllByUser($userId) public function getBuilderForAllByUser($userId)
{ {
return $this return $this
->getSortedQueryBuilderByUser($userId) ->getBuilderByUser($userId)
; ;
} }
@ -35,7 +35,7 @@ class EntryRepository extends EntityRepository
public function getBuilderForUnreadByUser($userId) public function getBuilderForUnreadByUser($userId)
{ {
return $this return $this
->getSortedQueryBuilderByUser($userId) ->getBuilderByUser($userId)
->andWhere('e.isArchived = false') ->andWhere('e.isArchived = false')
; ;
} }
@ -50,7 +50,7 @@ class EntryRepository extends EntityRepository
public function getBuilderForArchiveByUser($userId) public function getBuilderForArchiveByUser($userId)
{ {
return $this return $this
->getSortedQueryBuilderByUser($userId) ->getBuilderByUser($userId)
->andWhere('e.isArchived = true') ->andWhere('e.isArchived = true')
; ;
} }
@ -65,7 +65,7 @@ class EntryRepository extends EntityRepository
public function getBuilderForStarredByUser($userId) public function getBuilderForStarredByUser($userId)
{ {
return $this return $this
->getSortedQueryBuilderByUser($userId, 'starredAt', 'desc') ->getBuilderByUser($userId, 'starredAt', 'desc')
->andWhere('e.isStarred = true') ->andWhere('e.isStarred = true')
; ;
} }
@ -82,7 +82,7 @@ class EntryRepository extends EntityRepository
public function getBuilderForSearchByUser($userId, $term, $currentRoute) public function getBuilderForSearchByUser($userId, $term, $currentRoute)
{ {
$qb = $this $qb = $this
->getSortedQueryBuilderByUser($userId); ->getBuilderByUser($userId);
if ('starred' === $currentRoute) { if ('starred' === $currentRoute) {
$qb->andWhere('e.isStarred = true'); $qb->andWhere('e.isStarred = true');
@ -102,7 +102,7 @@ class EntryRepository extends EntityRepository
} }
/** /**
* Retrieve a sorted list of untagged entries for a user. * Retrieves untagged entries for a user.
* *
* @param int $userId * @param int $userId
* *
@ -111,21 +111,8 @@ class EntryRepository extends EntityRepository
public function getBuilderForUntaggedByUser($userId) public function getBuilderForUntaggedByUser($userId)
{ {
return $this return $this
->sortQueryBuilder($this->getRawBuilderForUntaggedByUser($userId)); ->getBuilderByUser($userId)
} ->andWhere('size(e.tags) = 0');
/**
* Retrieve untagged entries for a user.
*
* @param int $userId
*
* @return QueryBuilder
*/
public function getRawBuilderForUntaggedByUser($userId)
{
return $this->getQueryBuilderByUser($userId)
->leftJoin('e.tags', 't')
->andWhere('t.id is null');
} }
/** /**
@ -164,7 +151,7 @@ class EntryRepository extends EntityRepository
$qb->andWhere('e.updatedAt > :since')->setParameter('since', new \DateTime(date('Y-m-d H:i:s', $since))); $qb->andWhere('e.updatedAt > :since')->setParameter('since', new \DateTime(date('Y-m-d H:i:s', $since)));
} }
if (\is_string($tags) && '' !== $tags) { if (is_string($tags) && '' !== $tags) {
foreach (explode(',', $tags) as $i => $tag) { foreach (explode(',', $tags) as $i => $tag) {
$entryAlias = 'e' . $i; $entryAlias = 'e' . $i;
$tagAlias = 't' . $i; $tagAlias = 't' . $i;
@ -273,7 +260,7 @@ class EntryRepository extends EntityRepository
*/ */
public function removeTag($userId, Tag $tag) public function removeTag($userId, Tag $tag)
{ {
$entries = $this->getSortedQueryBuilderByUser($userId) $entries = $this->getBuilderByUser($userId)
->innerJoin('e.tags', 't') ->innerJoin('e.tags', 't')
->andWhere('t.id = :tagId')->setParameter('tagId', $tag->getId()) ->andWhere('t.id = :tagId')->setParameter('tagId', $tag->getId())
->getQuery() ->getQuery()
@ -309,7 +296,7 @@ class EntryRepository extends EntityRepository
*/ */
public function findAllByTagId($userId, $tagId) public function findAllByTagId($userId, $tagId)
{ {
return $this->getSortedQueryBuilderByUser($userId) return $this->getBuilderByUser($userId)
->innerJoin('e.tags', 't') ->innerJoin('e.tags', 't')
->andWhere('t.id = :tagId')->setParameter('tagId', $tagId) ->andWhere('t.id = :tagId')->setParameter('tagId', $tagId)
->getQuery() ->getQuery()
@ -333,7 +320,7 @@ class EntryRepository extends EntityRepository
->getQuery() ->getQuery()
->getResult(); ->getResult();
if (\count($res)) { if (count($res)) {
return current($res); return current($res);
} }
@ -427,20 +414,7 @@ class EntryRepository extends EntityRepository
} }
/** /**
* Return a query builder to be used by other getBuilderFor* method. * Return a query builder to used by other getBuilderFor* method.
*
* @param int $userId
*
* @return QueryBuilder
*/
private function getQueryBuilderByUser($userId)
{
return $this->createQueryBuilder('e')
->andWhere('e.user = :userId')->setParameter('userId', $userId);
}
/**
* Return a sorted query builder to be used by other getBuilderFor* method.
* *
* @param int $userId * @param int $userId
* @param string $sortBy * @param string $sortBy
@ -448,23 +422,10 @@ class EntryRepository extends EntityRepository
* *
* @return QueryBuilder * @return QueryBuilder
*/ */
private function getSortedQueryBuilderByUser($userId, $sortBy = 'createdAt', $direction = 'desc') private function getBuilderByUser($userId, $sortBy = 'createdAt', $direction = 'desc')
{ {
return $this->sortQueryBuilder($this->getQueryBuilderByUser($userId), $sortBy, $direction); return $this->createQueryBuilder('e')
} ->andWhere('e.user = :userId')->setParameter('userId', $userId)
/**
* Return the given QueryBuilder with an orderBy() call.
*
* @param QueryBuilder $qb
* @param string $sortBy
* @param string $direction
*
* @return QueryBuilder
*/
private function sortQueryBuilder(QueryBuilder $qb, $sortBy = 'createdAt', $direction = 'desc')
{
return $qb
->orderBy(sprintf('e.%s', $sortBy), $direction); ->orderBy(sprintf('e.%s', $sortBy), $direction);
} }
} }

View File

@ -30,7 +30,7 @@ class TagRepository extends EntityRepository
$query->setResultCacheLifetime($cacheLifeTime); $query->setResultCacheLifetime($cacheLifeTime);
} }
return \count($query->getArrayResult()); return count($query->getArrayResult());
} }
/** /**

View File

@ -157,8 +157,8 @@ config:
# not_equal_to: 'Not equal to...' # not_equal_to: 'Not equal to...'
# or: 'One rule OR another' # or: 'One rule OR another'
# and: 'One rule AND another' # and: 'One rule AND another'
# matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' # matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
# notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
entry: entry:
# default_title: 'Title of the entry' # default_title: 'Title of the entry'

View File

@ -72,9 +72,9 @@ config:
300_word: 'I read ~300 words per minute' 300_word: 'I read ~300 words per minute'
400_word: 'I read ~400 words per minute' 400_word: 'I read ~400 words per minute'
action_mark_as_read: action_mark_as_read:
label: 'What to do after removing, starring or marking as read an article?' label: 'Where do you want to be redirected to after marking an article as read?'
redirect_homepage: 'Go to the homepage' redirect_homepage: 'To the homepage'
redirect_current_page: 'Stay on the current page' redirect_current_page: 'To the current page'
pocket_consumer_key_label: Consumer key for Pocket to import contents pocket_consumer_key_label: Consumer key for Pocket to import contents
android_configuration: Configure your Android application android_configuration: Configure your Android application
android_instruction: "Touch here to prefill your Android application" android_instruction: "Touch here to prefill your Android application"
@ -116,7 +116,7 @@ config:
archived: Remove ALL archived entries archived: Remove ALL archived entries
confirm: Are you really sure? (THIS CAN'T BE UNDONE) confirm: Are you really sure? (THIS CAN'T BE UNDONE)
form_password: form_password:
description: "You can change your password here. Your new password should be at least 8 characters long." description: "You can change your password here. Your new password should by at least 8 characters long."
old_password_label: 'Current password' old_password_label: 'Current password'
new_password_label: 'New password' new_password_label: 'New password'
repeat_new_password_label: 'Repeat new password' repeat_new_password_label: 'Repeat new password'
@ -157,8 +157,8 @@ config:
not_equal_to: 'Not equal to...' not_equal_to: 'Not equal to...'
or: 'One rule OR another' or: 'One rule OR another'
and: 'One rule AND another' and: 'One rule AND another'
matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
entry: entry:
default_title: 'Title of the entry' default_title: 'Title of the entry'

View File

@ -158,7 +158,7 @@ config:
or: 'Una regla U otra' or: 'Una regla U otra'
and: 'Una regla Y la otra' and: 'Una regla Y la otra'
matches: 'Prueba si un <i>sujeto</i> corresponde a una <i>búsqueda</i> (insensible a mayusculas).<br />Ejemplo : <code>title matches "fútbol"</code>' matches: 'Prueba si un <i>sujeto</i> corresponde a una <i>búsqueda</i> (insensible a mayusculas).<br />Ejemplo : <code>title matches "fútbol"</code>'
# notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
entry: entry:
default_title: 'Título del artículo' default_title: 'Título del artículo'

View File

@ -157,8 +157,8 @@ config:
# not_equal_to: 'Not equal to...' # not_equal_to: 'Not equal to...'
# or: 'One rule OR another' # or: 'One rule OR another'
# and: 'One rule AND another' # and: 'One rule AND another'
# matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' # matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
# notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
entry: entry:
# default_title: 'Title of the entry' # default_title: 'Title of the entry'

View File

@ -72,9 +72,9 @@ config:
300_word: "Je lis environ 300 mots par minute" 300_word: "Je lis environ 300 mots par minute"
400_word: "Je lis environ 400 mots par minute" 400_word: "Je lis environ 400 mots par minute"
action_mark_as_read: action_mark_as_read:
label: "Que faire lorsqu'un article est supprimé, marqué comme lu ou marqué comme favoris ?" label: "Où souhaitez-vous être redirigé après avoir marqué un article comme lu ?"
redirect_homepage: "Retourner à la page daccueil" redirect_homepage: "À la page daccueil"
redirect_current_page: "Rester sur la page actuelle" redirect_current_page: "À la page courante"
pocket_consumer_key_label: "Clé dauthentification Pocket pour importer les données" pocket_consumer_key_label: "Clé dauthentification Pocket pour importer les données"
android_configuration: "Configurez votre application Android" android_configuration: "Configurez votre application Android"
android_instruction: "Appuyez ici pour préremplir votre application Android" android_instruction: "Appuyez ici pour préremplir votre application Android"

View File

@ -158,7 +158,7 @@ config:
or: "Una regola O un'altra" or: "Una regola O un'altra"
and: "Una regola E un'altra" and: "Una regola E un'altra"
matches: 'Verifica che un <i>oggetto</i> risulti in una <i>ricerca</i> (case-insensitive).<br />Esempio: <code>titolo contiene "football"</code>' matches: 'Verifica che un <i>oggetto</i> risulti in una <i>ricerca</i> (case-insensitive).<br />Esempio: <code>titolo contiene "football"</code>'
# notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
entry: entry:
default_title: "Titolo del contenuto" default_title: "Titolo del contenuto"

View File

@ -158,7 +158,7 @@ config:
or: 'Uma regra OU outra' or: 'Uma regra OU outra'
and: 'Uma regra E outra' and: 'Uma regra E outra'
matches: 'Testa que um <i>assunto</i> corresponde a uma <i>pesquisa</i> (maiúscula ou minúscula).<br />Exemplo: <code>título corresponde a "futebol"</code>' matches: 'Testa que um <i>assunto</i> corresponde a uma <i>pesquisa</i> (maiúscula ou minúscula).<br />Exemplo: <code>título corresponde a "futebol"</code>'
# notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
entry: entry:
default_title: 'Título da entrada' default_title: 'Título da entrada'

View File

@ -157,8 +157,8 @@ config:
# not_equal_to: 'Not equal to...' # not_equal_to: 'Not equal to...'
# or: 'One rule OR another' # or: 'One rule OR another'
# and: 'One rule AND another' # and: 'One rule AND another'
# matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' # matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
# notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
entry: entry:
# default_title: 'Title of the entry' # default_title: 'Title of the entry'

View File

@ -157,8 +157,8 @@ config:
not_equal_to: 'Eşit değildir…' not_equal_to: 'Eşit değildir…'
or: 'Bir kural veya birbaşkası' or: 'Bir kural veya birbaşkası'
and: 'Bir kural ve diğeri' and: 'Bir kural ve diğeri'
# matches: 'Tests that a <i>subject</i> matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>' # matches: 'Tests that a <i>subject</i> is matches a <i>search</i> (case-insensitive).<br />Example: <code>title matches "football"</code>'
# notmatches: 'Tests that a <i>subject</i> doesn''t match match a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>' # notmatches: 'Tests that a <i>subject</i> is not matches a <i>search</i> (case-insensitive).<br />Example: <code>title notmatches "football"</code>'
entry: entry:
default_title: 'Makalenin başlığı' default_title: 'Makalenin başlığı'

View File

@ -38,8 +38,6 @@
<link rel="shortcut icon" type="image/x-icon" href="{{ asset('wallassets/themes/_global/img/appicon/favicon.ico') }}"> <link rel="shortcut icon" type="image/x-icon" href="{{ asset('wallassets/themes/_global/img/appicon/favicon.ico') }}">
<link rel="manifest" href="{{ asset('manifest.json') }}">
{% block css %} {% block css %}
{% endblock %} {% endblock %}
{% block scripts %} {% block scripts %}

View File

@ -57,7 +57,7 @@
</div> </div>
<ul class="tools links"> <ul class="tools links">
<li><a href="{{ entry.url|e }}" target="_blank" rel="noopener" title="{{ 'entry.list.original_article'|trans }} : {{ entry.title|e }}"><span>{{ entry.domainName|removeWww }}</span></a></li> <li><a href="{{ entry.url|e }}" target="_blank" title="{{ 'entry.list.original_article'|trans }} : {{ entry.title|e }}"><span>{{ entry.domainName|removeWww }}</span></a></li>
<li><a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool icon {% if entry.isArchived == 0 %}archive-off{% else %}archive{% endif %}" href="{{ path('archive_entry', { 'id': entry.id }) }}"><i class="material-icons md-24 vertical-align-middle">check</i><span>{{ 'entry.list.toogle_as_read'|trans }}</span></a></li> <li><a title="{{ 'entry.list.toogle_as_read'|trans }}" class="tool icon {% if entry.isArchived == 0 %}archive-off{% else %}archive{% endif %}" href="{{ path('archive_entry', { 'id': entry.id }) }}"><i class="material-icons md-24 vertical-align-middle">check</i><span>{{ 'entry.list.toogle_as_read'|trans }}</span></a></li>
<li><a title="{{ 'entry.list.toogle_as_star'|trans }}" class="tool icon {% if entry.isStarred == 0 %}fav-off{% else %}fav{% endif %}" href="{{ path('star_entry', { 'id': entry.id }) }}"><i class="material-icons md-24 vertical-align-middle">star_rate</i><span>{{ 'entry.list.toogle_as_star'|trans }}</span></a></li> <li><a title="{{ 'entry.list.toogle_as_star'|trans }}" class="tool icon {% if entry.isStarred == 0 %}fav-off{% else %}fav{% endif %}" href="{{ path('star_entry', { 'id': entry.id }) }}"><i class="material-icons md-24 vertical-align-middle">star_rate</i><span>{{ 'entry.list.toogle_as_star'|trans }}</span></a></li>
<li><a title="{{ 'entry.list.delete'|trans }}" class="tool icon" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" href="{{ path('delete_entry', { 'id': entry.id }) }}"><i class="material-icons md-24 vertical-align-middle">delete</i><span>{{ 'entry.list.delete'|trans }}</span></a></li> <li><a title="{{ 'entry.list.delete'|trans }}" class="tool icon" onclick="return confirm('{{ 'entry.confirm.delete'|trans|escape('js') }}')" href="{{ path('delete_entry', { 'id': entry.id }) }}"><i class="material-icons md-24 vertical-align-middle">delete</i><span>{{ 'entry.list.delete'|trans }}</span></a></li>

View File

@ -11,7 +11,7 @@
<div id="article_toolbar"> <div id="article_toolbar">
<ul class="links"> <ul class="links">
<li class="topPosF"><a href="#top" title="{{ 'entry.view.left_menu.back_to_top'|trans }}" class="tool top icon icon-arrow-up-thick"><span>{{ 'entry.view.left_menu.set_as_read'|trans }}</span></a></li> <li class="topPosF"><a href="#top" title="{{ 'entry.view.left_menu.back_to_top'|trans }}" class="tool top icon icon-arrow-up-thick"><span>{{ 'entry.view.left_menu.set_as_read'|trans }}</span></a></li>
<li><a href="{{ entry.url|e }}" target="_blank" rel="noopener" title="{{ 'entry.view.original_article'|trans }} : {{ entry.title|e }}" class="tool link icon icon-link original"><span>{{ entry.domainName|removeWww }}</span></a></li> <li><a href="{{ entry.url|e }}" target="_blank" title="{{ 'entry.view.original_article'|trans }} : {{ entry.title|e }}" class="tool link icon icon-link original"><span>{{ entry.domainName|removeWww }}</span></a></li>
<li><a title="{{ 'entry.view.left_menu.re_fetch_content'|trans }}" class="tool icon icon-reload" href="{{ path('reload_entry', { 'id': entry.id }) }}"><span>{{ 'entry.view.left_menu.re_fetch_content'|trans }}</span></a></li> <li><a title="{{ 'entry.view.left_menu.re_fetch_content'|trans }}" class="tool icon icon-reload" href="{{ path('reload_entry', { 'id': entry.id }) }}"><span>{{ 'entry.view.left_menu.re_fetch_content'|trans }}</span></a></li>
{% set markAsReadLabel = 'entry.view.left_menu.set_as_unread' %} {% set markAsReadLabel = 'entry.view.left_menu.set_as_unread' %}
@ -27,13 +27,13 @@
<li><a href="{{ path('share', {'id': entry.id }) }}" target="_blank" class="tool icon icon-eye" title="{{ 'entry.view.left_menu.public_link'|trans }}"><span>{{ 'entry.view.left_menu.public_link'|trans }}</span></a></li> <li><a href="{{ path('share', {'id': entry.id }) }}" target="_blank" class="tool icon icon-eye" title="{{ 'entry.view.left_menu.public_link'|trans }}"><span>{{ 'entry.view.left_menu.public_link'|trans }}</span></a></li>
<li><a href="{{ path('delete_share', {'id': entry.id }) }}" class="tool icon icon-no-eye" title="{{ 'entry.view.left_menu.delete_public_link'|trans }}"><span>{{ 'entry.view.left_menu.delete_public_link'|trans }}</span></a></li> <li><a href="{{ path('delete_share', {'id': entry.id }) }}" class="tool icon icon-no-eye" title="{{ 'entry.view.left_menu.delete_public_link'|trans }}"><span>{{ 'entry.view.left_menu.delete_public_link'|trans }}</span></a></li>
{% endif %} {% endif %}
{% if craue_setting('share_twitter') %}<li><a href="https://twitter.com/home?status={{entry.title|url_encode}}%20{{ entry.url|url_encode }}%20via%20@wallabagapp" target="_blank" rel="noopener" class="tool twitter icon icon-twitter" title="Tweet"><span>Tweet</span></a></li>{% endif %} {% if craue_setting('share_twitter') %}<li><a href="https://twitter.com/home?status={{entry.title|url_encode}}%20{{ entry.url|url_encode }}%20via%20@wallabagapp" target="_blank" class="tool twitter icon icon-twitter" title="Tweet"><span>Tweet</span></a></li>{% endif %}
{% if craue_setting('share_mail') %}<li><a href="mailto:?subject={{ entry.title|url_encode }}&amp;body={{ entry.url|url_encode }}%20via%20@wallabagapp" class="tool email icon icon-mail" title="Email"><span>Email</span></a></li>{% endif %} {% if craue_setting('share_mail') %}<li><a href="mailto:?subject={{ entry.title|url_encode }}&amp;body={{ entry.url|url_encode }}%20via%20@wallabagapp" class="tool email icon icon-mail" title="Email"><span>Email</span></a></li>{% endif %}
{% if craue_setting('share_shaarli') %}<li><a href="{{ craue_setting('shaarli_url') }}/index.php?post={{ entry.url|url_encode }}&amp;title={{ entry.title|url_encode }}&amp;tags={{ entry.tags|join(',')|url_encode }}{% if craue_setting('shaarli_share_origin_url') %}&amp;original_url={{ entry.originUrl|url_encode }}{% endif %}" target="_blank" rel="noopener" class="tool icon-image icon-image--shaarli" title="shaarli"><span>shaarli</span></a></li>{% endif %} {% if craue_setting('share_shaarli') %}<li><a href="{{ craue_setting('shaarli_url') }}/index.php?post={{ entry.url|url_encode }}&amp;title={{ entry.title|url_encode }}&amp;tags={{ entry.tags|join(',')|url_encode }}{% if craue_setting('shaarli_share_origin_url') %}&amp;original_url={{ entry.originUrl|url_encode }}{% endif %}" target="_blank" class="tool icon-image icon-image--shaarli" title="shaarli"><span>shaarli</span></a></li>{% endif %}
{% if craue_setting('share_scuttle') %}<li><a href="{{ craue_setting('scuttle_url') }}/bookmarks.php?action=add&amp;address={{ entry.url|url_encode }}&amp;title={{ entry.title|url_encode }}&amp;tags={{ entry.tags|join(',')|url_encode }}" target="_blank" rel="noopener" class="tool icon-image icon-image--scuttle" title="scuttle"><span>scuttle</span></a></li>{% endif %} {% if craue_setting('share_scuttle') %}<li><a href="{{ craue_setting('scuttle_url') }}/bookmarks.php?action=add&amp;address={{ entry.url|url_encode }}&amp;title={{ entry.title|url_encode }}&amp;tags={{ entry.tags|join(',')|url_encode }}" target="_blank" class="tool icon-image icon-image--scuttle" title="scuttle"><span>scuttle</span></a></li>{% endif %}
{% if craue_setting('share_diaspora') %}<li><a href="{{ craue_setting('diaspora_url') }}/bookmarklet?url={{ entry.url|url_encode }}&title={{ entry.title|url_encode }}&notes=&v=1&noui=1&jump=doclose" target="_blank" rel="noopener" class="tool diaspora icon-image icon-image--diaspora" title="diaspora"><span>diaspora</span></a></li>{% endif %} {% if craue_setting('share_diaspora') %}<li><a href="{{ craue_setting('diaspora_url') }}/bookmarklet?url={{ entry.url|url_encode }}&title={{ entry.title|url_encode }}&notes=&v=1&noui=1&jump=doclose" target="_blank" class="tool diaspora icon-image icon-image--diaspora" title="diaspora"><span>diaspora</span></a></li>{% endif %}
{% if craue_setting('share_unmark') %}<li><a href="{{ craue_setting('unmark_url') }}/mark/add?url={{ entry.url|url_encode }}&amp;title={{entry.title|url_encode}}&amp;v=6" target="_blank" rel="noopener" class="tool unmark icon-image icon-image--unmark" title="unmark"><span>unmark.it</span></a></li>{% endif %} {% if craue_setting('share_unmark') %}<li><a href="{{ craue_setting('unmark_url') }}/mark/add?url={{ entry.url|url_encode }}&amp;title={{entry.title|url_encode}}&amp;v=6" target="_blank" class="tool unmark icon-image icon-image--unmark" title="unmark"><span>unmark.it</span></a></li>{% endif %}
{% if craue_setting('carrot') %}<li><a href="https://secure.carrot.org/GiveAndGetBack.do?url={{ entry.url|url_encode }}&title={{ entry.title|url_encode }}" class="tool carrot icon-image icon-image--carrot" target="_blank" rel="noopener" title="carrot"><span>Carrot</span></a></li>{% endif %} {% if craue_setting('carrot') %}<li><a href="https://secure.carrot.org/GiveAndGetBack.do?url={{ entry.url|url_encode }}&title={{ entry.title|url_encode }}" class="tool carrot icon-image icon-image--carrot" target="_blank" title="carrot"><span>Carrot</span></a></li>{% endif %}
{% if craue_setting('show_printlink') %}<li><a title="{{ 'entry.view.left_menu.print'|trans }}" class="tool icon icon-print" href="javascript: window.print();"><span>{{ 'entry.view.left_menu.print'|trans }}</span></a></li>{% endif %} {% if craue_setting('show_printlink') %}<li><a title="{{ 'entry.view.left_menu.print'|trans }}" class="tool icon icon-print" href="javascript: window.print();"><span>{{ 'entry.view.left_menu.print'|trans }}</span></a></li>{% endif %}
{% 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_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_mobi') %}<li><a href="{{ path('export_entry', { 'id': entry.id, 'format': 'mobi' }) }}" title="Generate Mobi file">MOBI</a></li>{% endif %}
@ -74,7 +74,7 @@
{% if entry.originUrl is not empty %} {% if entry.originUrl is not empty %}
<i class="material-icons" title="{{ 'entry.view.provided_by'|trans }}">launch</i> <i class="material-icons" title="{{ 'entry.view.provided_by'|trans }}">launch</i>
<a href="{{ entry.originUrl|e }}" target="_blank" rel="noopener" class="tool"> <a href="{{ entry.originUrl|e }}" target="_blank" class="tool">
{{ entry.originUrl|striptags|removeSchemeAndWww|truncate(32) }} {{ entry.originUrl|striptags|removeSchemeAndWww|truncate(32) }}
</a> </a>
{% endif %} {% endif %}
@ -96,6 +96,9 @@
</div> </div>
</aside> </aside>
</div> </div>
{% if entry.previewPicture is not null %}
<div><img class="preview" src="{{ entry.previewPicture }}" alt="{{ entry.title|e|raw }}" /></div>
{% endif %}
<article> <article>
{{ entry.content | raw }} {{ entry.content | raw }}
</article> </article>

View File

@ -7,7 +7,7 @@
<meta property="og:title" content="{{ entry.title|e|raw }}" /> <meta property="og:title" content="{{ entry.title|e|raw }}" />
<meta property="og:type" content="article" /> <meta property="og:type" content="article" />
<meta property="og:url" content="{{ app.request.uri }}" /> <meta property="og:url" content="{{ app.request.uri }}" />
{% set picturePath = app.request.schemeAndHttpHost ~ asset('wallassets/themes/_global/img/logo-wallabag.svg') %} {% set picturePath = app.request.schemeAndHttpHost ~ asset('wallassets/themes/_global/img/logo-other_themes.png') %}
{% if entry.previewPicture is not null %} {% if entry.previewPicture is not null %}
{% set picturePath = entry.previewPicture %} {% set picturePath = entry.previewPicture %}
{% endif %} {% endif %}
@ -27,7 +27,7 @@
<body> <body>
<header class="block"> <header class="block">
<h1>{{ entry.title|e|raw }}</h1> <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> <a href="{{ entry.url|e }}" target="_blank" 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> <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 %} {% if entry.previewPicture is not null %}
<img class="preview" src="{{ entry.previewPicture }}" alt="{{ entry.title|striptags|e('html_attr') }}" /> <img class="preview" src="{{ entry.previewPicture }}" alt="{{ entry.title|striptags|e('html_attr') }}" />

View File

@ -28,18 +28,18 @@
<div class="col s12"> <div class="col s12">
<h5>{{ 'howto.top_menu.browser_addons'|trans }}</h5> <h5>{{ 'howto.top_menu.browser_addons'|trans }}</h5>
<ul> <ul>
<li><a href="{{ addonsUrl.firefox }}" target="_blank" rel="noopener">{{ 'howto.browser_addons.firefox'|trans }}</a></li> <li><a href="{{ addonsUrl.firefox }}" target="_blank">{{ 'howto.browser_addons.firefox'|trans }}</a></li>
<li><a href="{{ addonsUrl.chrome }}" target="_blank" rel="noopener">{{ 'howto.browser_addons.chrome'|trans }}</a></li> <li><a href="{{ addonsUrl.chrome }}" target="_blank">{{ 'howto.browser_addons.chrome'|trans }}</a></li>
<li><a href="{{ addonsUrl.opera }}" target="_blank" rel="noopener">{{ 'howto.browser_addons.opera'|trans }}</a></li> <li><a href="{{ addonsUrl.opera }}" target="_blank">{{ 'howto.browser_addons.opera'|trans }}</a></li>
</ul> </ul>
</div> </div>
<div class="col s12"> <div class="col s12">
<h5>{{ 'howto.top_menu.mobile_apps'|trans }}</h5> <h5>{{ 'howto.top_menu.mobile_apps'|trans }}</h5>
<ul> <ul>
<li>Android: <a href="{{ addonsUrl.f_droid }}" target="_blank" rel="noopener">{{ 'howto.mobile_apps.android.via_f_droid'|trans }}</a> / <a href="{{ addonsUrl.google_play }}" target="_blank" rel="noopener">{{ 'howto.mobile_apps.android.via_google_play'|trans }}</a></li> <li>Android: <a href="{{ addonsUrl.f_droid }}" target="_blank">{{ 'howto.mobile_apps.android.via_f_droid'|trans }}</a> / <a href="{{ addonsUrl.google_play }}" target="_blank">{{ 'howto.mobile_apps.android.via_google_play'|trans }}</a></li>
<li>iOS: <a href="{{ addonsUrl.ios }}" target="_blank">{{ 'howto.mobile_apps.ios'|trans }}</a></li> <li>iOS: <a href="{{ addonsUrl.ios }}" target="_blank">{{ 'howto.mobile_apps.ios'|trans }}</a></li>
<li>Windows Phone: <a href="{{ addonsUrl.windows }}" target="_blank" rel="noopener">{{ 'howto.mobile_apps.windows'|trans }}</a></li> <li>Windows Phone: <a href="{{ addonsUrl.windows }}" target="_blank">{{ 'howto.mobile_apps.windows'|trans }}</a></li>
</ul> </ul>
</div> </div>

View File

@ -1,9 +1,10 @@
<div class="card-stacked"> <div class="card-stacked">
<div class="card-preview"> <div class="preview">
<a href="{{ path('view', { 'id': entry.id }) }}"> {% if entry.previewPicture is not null %}
{% set previewClassModifier = entry.previewPicture ? '' : ' preview--default' %} <a href="{{ path('view', { 'id': entry.id }) }}">
<span class="preview{{ previewClassModifier }}" style="background-image: url({{ entry.previewPicture | default(asset('wallassets/themes/_global/img/logo-square.svg')) }})"></span> <img src="{{ entry.previewPicture }}" />
</a> </a>
{% endif %}
</div> </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, 'withTags': true, 'subClass': 'metadata'} only %}
<ul class="tools-list hide-on-small-only"> <ul class="tools-list hide-on-small-only">

View File

@ -0,0 +1,7 @@
<div class="card">
<div class="card-body">
{% include "@WallabagCore/themes/material/Entry/Card/_content.html.twig" with {'entry': entry} only %}
</div>
{% include "@WallabagCore/themes/material/Entry/_card_actions.html.twig" with {'entry': entry} only %}
</div>

View File

@ -7,8 +7,7 @@
{% endfor %} {% endfor %}
</ul> </ul>
<a href="{{ path('view', { 'id': entry.id }) }}"> <a href="{{ path('view', { 'id': entry.id }) }}">
{% set previewClassModifier = entry.previewPicture ? '' : ' preview--default' %} <span class="preview" style="background-image: url({{ entry.previewPicture }})"></span>
<span class="preview{{ previewClassModifier }}" style="background-image: url({{ entry.previewPicture | default(asset('wallassets/themes/_global/img/logo-square.svg')) }})"></span>
</a> </a>
</div> </div>
{% include "@WallabagCore/themes/material/Entry/Card/_content.html.twig" with {'entry': entry, 'withPreview': true} only %} {% include "@WallabagCore/themes/material/Entry/Card/_content.html.twig" with {'entry': entry, 'withPreview': true} only %}

View File

@ -39,9 +39,11 @@
<li id="entry-{{ entry.id|e }}" class="col {% if listMode == 0 %}l3 m6{% else %}collection-item{% endif %} s12"> <li id="entry-{{ entry.id|e }}" class="col {% if listMode == 0 %}l3 m6{% else %}collection-item{% endif %} s12">
{% if listMode == 1 %} {% if listMode == 1 %}
{% include "@WallabagCore/themes/material/Entry/_card_list.html.twig" with {'entry': entry} only %} {% include "@WallabagCore/themes/material/Entry/_card_list.html.twig" with {'entry': entry} only %}
{% elseif entry.previewPicture is null %}
{% include "@WallabagCore/themes/material/Entry/_card_no_preview.html.twig" with {'entry': entry} only %}
{% elseif not entry.previewPicture is null and entry.mimetype starts with 'image/' %} {% elseif not entry.previewPicture is null and entry.mimetype starts with 'image/' %}
{% include "@WallabagCore/themes/material/Entry/_card_full_image.html.twig" with {'entry': entry} only %} {% include "@WallabagCore/themes/material/Entry/_card_full_image.html.twig" with {'entry': entry} only %}
{% else %} {% elseif not entry.previewPicture is null %}
{% include "@WallabagCore/themes/material/Entry/_card_preview.html.twig" with {'entry': entry} only %} {% include "@WallabagCore/themes/material/Entry/_card_preview.html.twig" with {'entry': entry} only %}
{% endif %} {% endif %}
</li> </li>

View File

@ -46,7 +46,7 @@
</li> </li>
<li class="bold border-bottom hide-on-med-and-down"> <li class="bold border-bottom hide-on-med-and-down">
<a class="waves-effect collapsible-header original" href="{{ entry.url|e }}" target="_blank" rel="noopener"> <a class="waves-effect collapsible-header original" href="{{ entry.url|e }}" target="_blank">
<i class="material-icons small">link</i> <i class="material-icons small">link</i>
<span>{{ 'entry.view.left_menu.view_original_article'|trans }}</span> <span>{{ 'entry.view.left_menu.view_original_article'|trans }}</span>
</a> </a>
@ -127,42 +127,42 @@
{% endif %} {% endif %}
{% if craue_setting('share_twitter') %} {% if craue_setting('share_twitter') %}
<li> <li>
<a href="https://twitter.com/home?status={{entry.title|striptags|url_encode}}%20{{ entry.url|url_encode }}%20via%20@wallabagapp" target="_blank" rel="noopener" class="tool icon-twitter" title="twitter"> <a href="https://twitter.com/home?status={{entry.title|striptags|url_encode}}%20{{ entry.url|url_encode }}%20via%20@wallabagapp" target="_blank" class="tool icon-twitter" title="twitter">
<span>twitter</span> <span>twitter</span>
</a> </a>
</li> </li>
{% endif %} {% endif %}
{% if craue_setting('share_shaarli') %} {% if craue_setting('share_shaarli') %}
<li> <li>
<a href="{{ craue_setting('shaarli_url') }}/index.php?post={{ entry.url|url_encode }}&amp;title={{ entry.title|striptags|url_encode }}&amp;tags={{ entry.tags|join(',')|striptags|url_encode }}{% if craue_setting('shaarli_share_origin_url') %}&amp;original_url={{ entry.originUrl|url_encode }}{% endif %}" target="_blank" rel="noopener" title="shaarli" class="tool icon-image shaarli"> <a href="{{ craue_setting('shaarli_url') }}/index.php?post={{ entry.url|url_encode }}&amp;title={{ entry.title|striptags|url_encode }}&amp;tags={{ entry.tags|join(',')|striptags|url_encode }}{% if craue_setting('shaarli_share_origin_url') %}&amp;original_url={{ entry.originUrl|url_encode }}{% endif %}" target="_blank" title="shaarli" class="tool icon-image shaarli">
<span>shaarli</span> <span>shaarli</span>
</a> </a>
</li> </li>
{% endif %} {% endif %}
{% if craue_setting('share_scuttle') %} {% if craue_setting('share_scuttle') %}
<li> <li>
<a href="{{ craue_setting('scuttle_url') }}/bookmarks.php?action=add&amp;address={{ entry.url|url_encode }}&amp;title={{ entry.title|striptags|url_encode }}&amp;tags={{ entry.tags|join(',')|striptags|url_encode }}" target="_blank" rel="noopener" title="scuttle" class="tool icon-image scuttle"> <a href="{{ craue_setting('scuttle_url') }}/bookmarks.php?action=add&amp;address={{ entry.url|url_encode }}&amp;title={{ entry.title|striptags|url_encode }}&amp;tags={{ entry.tags|join(',')|striptags|url_encode }}" target="_blank" title="scuttle" class="tool icon-image scuttle">
<span>scuttle</span> <span>scuttle</span>
</a> </a>
</li> </li>
{% endif %} {% endif %}
{% if craue_setting('share_diaspora') %} {% if craue_setting('share_diaspora') %}
<li> <li>
<a href="{{ craue_setting('diaspora_url') }}/bookmarklet?url={{ entry.url|url_encode }}&amp;title={{ entry.title|striptags|url_encode }}&amp;notes=&amp;v=1&amp;noui=1&amp;jump=doclose" target="_blank" rel="noopener" class="tool icon-image diaspora" title="diaspora"> <a href="{{ craue_setting('diaspora_url') }}/bookmarklet?url={{ entry.url|url_encode }}&amp;title={{ entry.title|striptags|url_encode }}&amp;notes=&amp;v=1&amp;noui=1&amp;jump=doclose" target="_blank" class="tool icon-image diaspora" title="diaspora">
<span>diaspora*</span> <span>diaspora*</span>
</a> </a>
</li> </li>
{% endif %} {% endif %}
{% if craue_setting('share_unmark') %} {% if craue_setting('share_unmark') %}
<li> <li>
<a href="{{ craue_setting('unmark_url') }}/mark/add?url={{ entry.url|url_encode }}&amp;title={{entry.title|striptags|url_encode}}&amp;v=6" target="_blank" rel="noopener" class="tool icon-image unmark" title="unmark"> <a href="{{ craue_setting('unmark_url') }}/mark/add?url={{ entry.url|url_encode }}&amp;title={{entry.title|striptags|url_encode}}&amp;v=6" target="_blank" class="tool icon-image unmark" title="unmark">
<span>unmark.it</span> <span>unmark.it</span>
</a> </a>
</li> </li>
{% endif %} {% endif %}
{% if craue_setting('carrot') %} {% if craue_setting('carrot') %}
<li> <li>
<a href="https://secure.carrot.org/GiveAndGetBack.do?url={{ entry.url|url_encode }}&amp;title={{ entry.title|striptags|url_encode }}" target="_blank" rel="noopener" title="carrot" class="tool icon-image carrot"> <a href="https://secure.carrot.org/GiveAndGetBack.do?url={{ entry.url|url_encode }}&amp;title={{ entry.title|striptags|url_encode }}" target="_blank" title="carrot" class="tool icon-image carrot">
<span>Carrot</span> <span>Carrot</span>
</a> </a>
</li> </li>
@ -251,7 +251,7 @@
{% endif %} {% endif %}
<li> <li>
<i class="material-icons link">link</i> <i class="material-icons link">link</i>
<a href="{{ entry.url|e }}" target="_blank" rel="noopener" title="{{ 'entry.view.original_article'|trans }} : {{ entry.title|striptags }}" class="tool"> <a href="{{ entry.url|e }}" target="_blank" title="{{ 'entry.view.original_article'|trans }} : {{ entry.title|striptags }}" class="tool">
{{ entry.domainName|removeWww }} {{ entry.domainName|removeWww }}
</a> </a>
</li> </li>
@ -262,7 +262,7 @@
{% if entry.originUrl is not empty %} {% if entry.originUrl is not empty %}
<li> <li>
<i class="material-icons" title="{{ 'entry.view.provided_by'|trans }}">launch</i> <i class="material-icons" title="{{ 'entry.view.provided_by'|trans }}">launch</i>
<a href="{{ entry.originUrl|e }}" target="_blank" rel="noopener" class="tool"> <a href="{{ entry.originUrl|e }}" target="_blank" class="tool">
{{ entry.originUrl|striptags|removeSchemeAndWww|truncate(32) }} {{ entry.originUrl|striptags|removeSchemeAndWww|truncate(32) }}
</a> </a>
</li> </li>
@ -275,6 +275,10 @@
{{ render(controller( "WallabagCoreBundle:Tag:addTagForm", { 'id': entry.id } )) }} {{ render(controller( "WallabagCoreBundle:Tag:addTagForm", { 'id': entry.id } )) }}
</div> </div>
{% if entry.previewPicture is not null %}
<div><img class="preview" src="{{ entry.previewPicture }}" alt="{{ entry.title|striptags|default('entry.default_title'|trans)|raw }}" /></div>
{% endif %}
</aside> </aside>
<article> <article>
{{ entry.content | raw }} {{ entry.content | raw }}

View File

@ -11,7 +11,7 @@
<main class="valign-wrapper"> <main class="valign-wrapper">
<div class="valign row"> <div class="valign row">
<div class="card sw"> <div class="card sw">
<div class="center"><img src="{{ asset('wallassets/themes/_global/img/logo-wallabag.svg') }}" alt="wallabag logo" class="typo-logo" /></div> <div class="center"><img src="{{ asset('wallassets/themes/_global/img/logo-other_themes.png') }}" alt="wallabag logo" /></div>
<div class="card-content"> <div class="card-content">
<div class="row"> <div class="row">
<h5>{{ status_code }}: {{ status_text }}</h5> <h5>{{ status_code }}: {{ status_text }}</h5>

View File

@ -29,7 +29,7 @@
{% block logo %} {% block logo %}
<li class="logo border-bottom"> <li class="logo border-bottom">
<a title="{{ 'menu.left.back_to_unread'|trans }}" href="{{ path('unread') }}"> <a title="{{ 'menu.left.back_to_unread'|trans }}" href="{{ path('unread') }}">
<img src="{{ asset('wallassets/themes/_global/img/logo-square.svg') }}" alt="wallabag logo" /> <img src="{{ asset('wallassets/themes/_global/img/logo-square.png') }}" alt="wallabag logo" />
</a> </a>
</li> </li>
{% endblock %} {% endblock %}
@ -143,7 +143,7 @@
</div> </div>
<div class="col s12 l4"> <div class="col s12 l4">
<p class="footer-text"> <p class="footer-text">
{{ 'footer.wallabag.powered_by'|trans }} <a target="_blank" rel="noopener" href="https://wallabag.org" class="grey-text text-lighten-4">wallabag</a> {{ 'footer.wallabag.powered_by'|trans }} <a target="_blank" href="https://wallabag.org" class="grey-text text-lighten-4">wallabag</a>
<a class="grey-text text-lighten-4" href="{{ path('about') }}">{{ 'footer.wallabag.about'|trans|lower }}</a> <a class="grey-text text-lighten-4" href="{{ path('about') }}">{{ 'footer.wallabag.about'|trans|lower }}</a>
</p> </p>
</div> </div>

View File

@ -29,6 +29,6 @@ class Utils
*/ */
public static function getReadingTime($text) public static function getReadingTime($text)
{ {
return floor(\count(preg_split('~[^\p{L}\p{N}\']+~u', strip_tags($text))) / 200); return floor(count(preg_split('~[^\p{L}\p{N}\']+~u', strip_tags($text))) / 200);
} }
} }

View File

@ -64,7 +64,7 @@ class WallabagExtension extends \Twig_Extension implements \Twig_Extension_Globa
{ {
$user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null; $user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null;
if (null === $user || !\is_object($user)) { if (null === $user || !is_object($user)) {
return 0; return 0;
} }
@ -96,7 +96,7 @@ class WallabagExtension extends \Twig_Extension implements \Twig_Extension_Globa
$query->useResultCache(true); $query->useResultCache(true);
$query->setResultCacheLifetime($this->lifeTime); $query->setResultCacheLifetime($this->lifeTime);
return \count($query->getArrayResult()); return count($query->getArrayResult());
} }
/** /**
@ -108,7 +108,7 @@ class WallabagExtension extends \Twig_Extension implements \Twig_Extension_Globa
{ {
$user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null; $user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null;
if (null === $user || !\is_object($user)) { if (null === $user || !is_object($user)) {
return 0; return 0;
} }
@ -124,7 +124,7 @@ class WallabagExtension extends \Twig_Extension implements \Twig_Extension_Globa
{ {
$user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null; $user = $this->tokenStorage->getToken() ? $this->tokenStorage->getToken()->getUser() : null;
if (null === $user || !\is_object($user)) { if (null === $user || !is_object($user)) {
return 0; return 0;
} }
@ -137,7 +137,7 @@ class WallabagExtension extends \Twig_Extension implements \Twig_Extension_Globa
$query->useResultCache(true); $query->useResultCache(true);
$query->setResultCacheLifetime($this->lifeTime); $query->setResultCacheLifetime($this->lifeTime);
$nbArchives = \count($query->getArrayResult()); $nbArchives = count($query->getArrayResult());
$interval = $user->getCreatedAt()->diff(new \DateTime('now')); $interval = $user->getCreatedAt()->diff(new \DateTime('now'));
$nbDays = (int) $interval->format('%a') ?: 1; $nbDays = (int) $interval->format('%a') ?: 1;

View File

@ -43,7 +43,7 @@ class ImportCommand extends ContainerAwareCommand
$user = $em->getRepository('WallabagUserBundle:User')->findOneByUsername($input->getArgument('username')); $user = $em->getRepository('WallabagUserBundle:User')->findOneByUsername($input->getArgument('username'));
} }
if (!\is_object($user)) { if (!is_object($user)) {
throw new Exception(sprintf('User "%s" not found', $input->getArgument('username'))); throw new Exception(sprintf('User "%s" not found', $input->getArgument('username')));
} }

View File

@ -30,7 +30,7 @@ abstract class BrowserController extends Controller
$markAsRead = $form->get('mark_as_read')->getData(); $markAsRead = $form->get('mark_as_read')->getData();
$name = $this->getUser()->getId() . '.json'; $name = $this->getUser()->getId() . '.json';
if (null !== $file && \in_array($file->getClientMimeType(), $this->getParameter('wallabag_import.allow_mimetypes'), true) && $file->move($this->getParameter('wallabag_import.resource_dir'), $name)) { if (null !== $file && in_array($file->getClientMimeType(), $this->getParameter('wallabag_import.allow_mimetypes'), true) && $file->move($this->getParameter('wallabag_import.resource_dir'), $name)) {
$res = $wallabag $res = $wallabag
->setFilepath($this->getParameter('wallabag_import.resource_dir') . '/' . $name) ->setFilepath($this->getParameter('wallabag_import.resource_dir') . '/' . $name)
->setMarkAsRead($markAsRead) ->setMarkAsRead($markAsRead)

View File

@ -31,7 +31,7 @@ class InstapaperController extends Controller
$markAsRead = $form->get('mark_as_read')->getData(); $markAsRead = $form->get('mark_as_read')->getData();
$name = 'instapaper_' . $this->getUser()->getId() . '.csv'; $name = 'instapaper_' . $this->getUser()->getId() . '.csv';
if (null !== $file && \in_array($file->getClientMimeType(), $this->getParameter('wallabag_import.allow_mimetypes'), true) && $file->move($this->getParameter('wallabag_import.resource_dir'), $name)) { if (null !== $file && in_array($file->getClientMimeType(), $this->getParameter('wallabag_import.allow_mimetypes'), true) && $file->move($this->getParameter('wallabag_import.resource_dir'), $name)) {
$res = $instapaper $res = $instapaper
->setFilepath($this->getParameter('wallabag_import.resource_dir') . '/' . $name) ->setFilepath($this->getParameter('wallabag_import.resource_dir') . '/' . $name)
->setMarkAsRead($markAsRead) ->setMarkAsRead($markAsRead)

View File

@ -31,7 +31,7 @@ class PinboardController extends Controller
$markAsRead = $form->get('mark_as_read')->getData(); $markAsRead = $form->get('mark_as_read')->getData();
$name = 'pinboard_' . $this->getUser()->getId() . '.json'; $name = 'pinboard_' . $this->getUser()->getId() . '.json';
if (null !== $file && \in_array($file->getClientMimeType(), $this->getParameter('wallabag_import.allow_mimetypes'), true) && $file->move($this->getParameter('wallabag_import.resource_dir'), $name)) { if (null !== $file && in_array($file->getClientMimeType(), $this->getParameter('wallabag_import.allow_mimetypes'), true) && $file->move($this->getParameter('wallabag_import.resource_dir'), $name)) {
$res = $pinboard $res = $pinboard
->setFilepath($this->getParameter('wallabag_import.resource_dir') . '/' . $name) ->setFilepath($this->getParameter('wallabag_import.resource_dir') . '/' . $name)
->setMarkAsRead($markAsRead) ->setMarkAsRead($markAsRead)

View File

@ -31,7 +31,7 @@ class ReadabilityController extends Controller
$markAsRead = $form->get('mark_as_read')->getData(); $markAsRead = $form->get('mark_as_read')->getData();
$name = 'readability_' . $this->getUser()->getId() . '.json'; $name = 'readability_' . $this->getUser()->getId() . '.json';
if (null !== $file && \in_array($file->getClientMimeType(), $this->getParameter('wallabag_import.allow_mimetypes'), true) && $file->move($this->getParameter('wallabag_import.resource_dir'), $name)) { if (null !== $file && in_array($file->getClientMimeType(), $this->getParameter('wallabag_import.allow_mimetypes'), true) && $file->move($this->getParameter('wallabag_import.resource_dir'), $name)) {
$res = $readability $res = $readability
->setFilepath($this->getParameter('wallabag_import.resource_dir') . '/' . $name) ->setFilepath($this->getParameter('wallabag_import.resource_dir') . '/' . $name)
->setMarkAsRead($markAsRead) ->setMarkAsRead($markAsRead)

View File

@ -33,7 +33,7 @@ abstract class WallabagController extends Controller
$markAsRead = $form->get('mark_as_read')->getData(); $markAsRead = $form->get('mark_as_read')->getData();
$name = $this->getUser()->getId() . '.json'; $name = $this->getUser()->getId() . '.json';
if (null !== $file && \in_array($file->getClientMimeType(), $this->getParameter('wallabag_import.allow_mimetypes'), true) && $file->move($this->getParameter('wallabag_import.resource_dir'), $name)) { if (null !== $file && in_array($file->getClientMimeType(), $this->getParameter('wallabag_import.allow_mimetypes'), true) && $file->move($this->getParameter('wallabag_import.resource_dir'), $name)) {
$res = $wallabag $res = $wallabag
->setFilepath($this->getParameter('wallabag_import.resource_dir') . '/' . $name) ->setFilepath($this->getParameter('wallabag_import.resource_dir') . '/' . $name)
->setMarkAsRead($markAsRead) ->setMarkAsRead($markAsRead)

View File

@ -77,7 +77,7 @@ abstract class BrowserImport extends AbstractImport
*/ */
public function parseEntry(array $importedEntry) 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) { if ($this->producer) {
$this->parseEntriesForProducer($importedEntry); $this->parseEntriesForProducer($importedEntry);

View File

@ -62,7 +62,7 @@ class InstapaperImport extends AbstractImport
} }
$entries = []; $entries = [];
$handle = fopen($this->filepath, 'rb'); $handle = fopen($this->filepath, 'r');
while (false !== ($data = fgetcsv($handle, 10240))) { while (false !== ($data = fgetcsv($handle, 10240))) {
if ('URL' === $data[0]) { if ('URL' === $data[0]) {
continue; continue;
@ -72,7 +72,7 @@ class InstapaperImport extends AbstractImport
// BUT it can also be the status (since status = folder in Instapaper) // BUT it can also be the status (since status = folder in Instapaper)
// and we don't want archive, unread & starred to become a tag // and we don't want archive, unread & starred to become a tag
$tags = null; $tags = null;
if (false === \in_array($data[3], ['Archive', 'Unread', 'Starred'], true)) { if (false === in_array($data[3], ['Archive', 'Unread', 'Starred'], true)) {
$tags = [$data[3]]; $tags = [$data[3]];
} }

View File

@ -149,7 +149,7 @@ class PocketImport extends AbstractImport
// - first call get 5k offset 0 // - first call get 5k offset 0
// - second call get 5k offset 5k // - second call get 5k offset 5k
// - and so on // - and so on
if (self::NB_ELEMENTS === \count($entries['list'])) { if (self::NB_ELEMENTS === count($entries['list'])) {
++$run; ++$run;
return $this->import(self::NB_ELEMENTS * $run); return $this->import(self::NB_ELEMENTS * $run);

View File

@ -56,7 +56,7 @@ class WallabagV1Import extends WallabagImport
// In case of a bad fetch in v1, replace title and content with v2 error strings // In case of a bad fetch in v1, replace title and content with v2 error strings
// If fetching fails again, they will get this instead of the v1 strings // If fetching fails again, they will get this instead of the v1 strings
if (\in_array($entry['title'], $this->untitled, true)) { if (in_array($entry['title'], $this->untitled, true)) {
$data['title'] = $this->fetchingErrorMessageTitle; $data['title'] = $this->fetchingErrorMessageTitle;
$data['html'] = $this->fetchingErrorMessage; $data['html'] = $this->fetchingErrorMessage;
} }

View File

@ -16,7 +16,7 @@
<div class="input-field col s12"> <div class="input-field col s12">
<label for="username">{{ 'security.login.username'|trans }}</label> <label for="username">{{ 'security.login.username'|trans }}</label>
<input type="text" id="username" name="_username" value="{{ last_username }}" autofocus /> <input type="text" id="username" name="_username" value="{{ last_username }}" />
</div> </div>
<div class="input-field col s12"> <div class="input-field col s12">

View File

@ -11,7 +11,7 @@
<main class="valign-wrapper"> <main class="valign-wrapper">
<div class="valign row"> <div class="valign row">
<div class="card sw"> <div class="card sw">
<div class="center"><img src="{{ asset('wallassets/themes/_global/img/logo-wallabag.svg') }}" class="typo-logo" alt="wallabag logo" /></div> <div class="center"><img src="{{ asset('wallassets/themes/_global/img/logo-other_themes.png') }}" alt="wallabag logo" /></div>
{% block fos_user_content %} {% block fos_user_content %}
{% endblock fos_user_content %} {% endblock fos_user_content %}
</div> </div>

View File

@ -28,7 +28,7 @@ class DeveloperControllerTest extends WallabagCoreTestCase
$this->assertSame(200, $client->getResponse()->getStatusCode()); $this->assertSame(200, $client->getResponse()->getStatusCode());
$newNbClients = $em->getRepository('WallabagApiBundle:Client')->findAll(); $newNbClients = $em->getRepository('WallabagApiBundle:Client')->findAll();
$this->assertGreaterThan(\count($nbClients), \count($newNbClients)); $this->assertGreaterThan(count($nbClients), count($newNbClients));
$this->assertGreaterThan(1, $alert = $crawler->filter('.settings ul li strong')->extract(['_text'])); $this->assertGreaterThan(1, $alert = $crawler->filter('.settings ul li strong')->extract(['_text']));
$this->assertContains('My app', $alert[0]); $this->assertContains('My app', $alert[0]);
@ -65,7 +65,7 @@ class DeveloperControllerTest extends WallabagCoreTestCase
$crawler = $client->request('GET', '/developer'); $crawler = $client->request('GET', '/developer');
$this->assertSame(200, $client->getResponse()->getStatusCode()); $this->assertSame(200, $client->getResponse()->getStatusCode());
$this->assertSame(\count($nbClients), $crawler->filter('ul[class=collapsible] li')->count()); $this->assertSame(count($nbClients), $crawler->filter('ul[class=collapsible] li')->count());
} }
public function testDeveloperHowto() public function testDeveloperHowto()

View File

@ -28,7 +28,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
$this->assertSame($entry->getTitle(), $content['title']); $this->assertSame($entry->getTitle(), $content['title']);
$this->assertSame($entry->getUrl(), $content['url']); $this->assertSame($entry->getUrl(), $content['url']);
$this->assertCount(\count($entry->getTags()), $content['tags']); $this->assertCount(count($entry->getTags()), $content['tags']);
$this->assertSame($entry->getUserName(), $content['user_name']); $this->assertSame($entry->getUserName(), $content['user_name']);
$this->assertSame($entry->getUserEmail(), $content['user_email']); $this->assertSame($entry->getUserEmail(), $content['user_email']);
$this->assertSame($entry->getUserId(), $content['user_id']); $this->assertSame($entry->getUserId(), $content['user_id']);
@ -127,7 +127,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
$content = json_decode($this->client->getResponse()->getContent(), true); $content = json_decode($this->client->getResponse()->getContent(), true);
$this->assertGreaterThanOrEqual(1, \count($content)); $this->assertGreaterThanOrEqual(1, count($content));
$this->assertNotEmpty($content['_embedded']['items']); $this->assertNotEmpty($content['_embedded']['items']);
$this->assertGreaterThanOrEqual(1, $content['total']); $this->assertGreaterThanOrEqual(1, $content['total']);
$this->assertSame(1, $content['page']); $this->assertSame(1, $content['page']);
@ -154,7 +154,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
$content = json_decode($this->client->getResponse()->getContent(), true); $content = json_decode($this->client->getResponse()->getContent(), true);
$this->assertGreaterThanOrEqual(1, \count($content)); $this->assertGreaterThanOrEqual(1, count($content));
$this->assertArrayHasKey('items', $content['_embedded']); $this->assertArrayHasKey('items', $content['_embedded']);
$this->assertGreaterThanOrEqual(0, $content['total']); $this->assertGreaterThanOrEqual(0, $content['total']);
$this->assertSame(1, $content['page']); $this->assertSame(1, $content['page']);
@ -206,7 +206,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
$content = json_decode($this->client->getResponse()->getContent(), true); $content = json_decode($this->client->getResponse()->getContent(), true);
$this->assertGreaterThanOrEqual(1, \count($content)); $this->assertGreaterThanOrEqual(1, count($content));
$this->assertArrayHasKey('items', $content['_embedded']); $this->assertArrayHasKey('items', $content['_embedded']);
$this->assertGreaterThanOrEqual(1, $content['total']); $this->assertGreaterThanOrEqual(1, $content['total']);
$this->assertSame(1, $content['page']); $this->assertSame(1, $content['page']);
@ -250,7 +250,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
$content = json_decode($this->client->getResponse()->getContent(), true); $content = json_decode($this->client->getResponse()->getContent(), true);
$this->assertGreaterThanOrEqual(1, \count($content)); $this->assertGreaterThanOrEqual(1, count($content));
$this->assertNotEmpty($content['_embedded']['items']); $this->assertNotEmpty($content['_embedded']['items']);
$this->assertGreaterThanOrEqual(1, $content['total']); $this->assertGreaterThanOrEqual(1, $content['total']);
$this->assertSame(1, $content['page']); $this->assertSame(1, $content['page']);
@ -278,7 +278,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
$content = json_decode($this->client->getResponse()->getContent(), true); $content = json_decode($this->client->getResponse()->getContent(), true);
$this->assertGreaterThanOrEqual(1, \count($content)); $this->assertGreaterThanOrEqual(1, count($content));
$this->assertNotEmpty($content['_embedded']['items']); $this->assertNotEmpty($content['_embedded']['items']);
$this->assertGreaterThanOrEqual(1, $content['total']); $this->assertGreaterThanOrEqual(1, $content['total']);
$this->assertSame(1, $content['page']); $this->assertSame(1, $content['page']);
@ -305,7 +305,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
$content = json_decode($this->client->getResponse()->getContent(), true); $content = json_decode($this->client->getResponse()->getContent(), true);
$this->assertGreaterThanOrEqual(1, \count($content)); $this->assertGreaterThanOrEqual(1, count($content));
$this->assertNotEmpty($content['_embedded']['items']); $this->assertNotEmpty($content['_embedded']['items']);
$this->assertGreaterThanOrEqual(1, $content['total']); $this->assertGreaterThanOrEqual(1, $content['total']);
$this->assertSame(1, $content['page']); $this->assertSame(1, $content['page']);
@ -342,7 +342,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
$content = json_decode($this->client->getResponse()->getContent(), true); $content = json_decode($this->client->getResponse()->getContent(), true);
$this->assertGreaterThanOrEqual(1, \count($content)); $this->assertGreaterThanOrEqual(1, count($content));
$this->assertNotEmpty($content['_embedded']['items']); $this->assertNotEmpty($content['_embedded']['items']);
$this->assertGreaterThanOrEqual(1, $content['total']); $this->assertGreaterThanOrEqual(1, $content['total']);
$this->assertSame(1, $content['page']); $this->assertSame(1, $content['page']);
@ -370,7 +370,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
$content = json_decode($this->client->getResponse()->getContent(), true); $content = json_decode($this->client->getResponse()->getContent(), true);
$this->assertGreaterThanOrEqual(1, \count($content)); $this->assertGreaterThanOrEqual(1, count($content));
$this->assertEmpty($content['_embedded']['items']); $this->assertEmpty($content['_embedded']['items']);
$this->assertSame(0, $content['total']); $this->assertSame(0, $content['total']);
$this->assertSame(1, $content['page']); $this->assertSame(1, $content['page']);
@ -608,7 +608,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
$this->assertSame($entry->getId(), $content['id']); $this->assertSame($entry->getId(), $content['id']);
$this->assertSame($entry->getUrl(), $content['url']); $this->assertSame($entry->getUrl(), $content['url']);
$this->assertSame('New awesome title', $content['title']); $this->assertSame('New awesome title', $content['title']);
$this->assertGreaterThanOrEqual(1, \count($content['tags']), 'We force only one tag'); $this->assertGreaterThanOrEqual(1, count($content['tags']), 'We force only one tag');
$this->assertSame(1, $content['user_id']); $this->assertSame(1, $content['user_id']);
$this->assertSame('de_AT', $content['language']); $this->assertSame('de_AT', $content['language']);
$this->assertSame('http://preview.io/picture.jpg', $content['preview_picture']); $this->assertSame('http://preview.io/picture.jpg', $content['preview_picture']);
@ -647,7 +647,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
$this->assertSame($entry->getId(), $content['id']); $this->assertSame($entry->getId(), $content['id']);
$this->assertSame($entry->getUrl(), $content['url']); $this->assertSame($entry->getUrl(), $content['url']);
$this->assertGreaterThanOrEqual(1, \count($content['tags']), 'We force only one tag'); $this->assertGreaterThanOrEqual(1, count($content['tags']), 'We force only one tag');
$this->assertEmpty($content['published_by'], 'Authors were not saved because of an array instead of a string'); $this->assertEmpty($content['published_by'], 'Authors were not saved because of an array instead of a string');
$this->assertSame($previousContent, $content['content'], 'Ensure content has not moved'); $this->assertSame($previousContent, $content['content'], 'Ensure content has not moved');
$this->assertSame($previousLanguage, $content['language'], 'Ensure language has not moved'); $this->assertSame($previousLanguage, $content['language'], 'Ensure language has not moved');
@ -772,7 +772,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
$this->markTestSkipped('No content found in db.'); $this->markTestSkipped('No content found in db.');
} }
$nbTags = \count($entry->getTags()); $nbTags = count($entry->getTags());
$newTags = 'tag1,tag2,tag3'; $newTags = 'tag1,tag2,tag3';
@ -783,7 +783,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
$content = json_decode($this->client->getResponse()->getContent(), true); $content = json_decode($this->client->getResponse()->getContent(), true);
$this->assertArrayHasKey('tags', $content); $this->assertArrayHasKey('tags', $content);
$this->assertSame($nbTags + 3, \count($content['tags'])); $this->assertSame($nbTags + 3, count($content['tags']));
$entryDB = $this->client->getContainer() $entryDB = $this->client->getContainer()
->get('doctrine.orm.entity_manager') ->get('doctrine.orm.entity_manager')
@ -813,7 +813,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
} }
// hydrate the tags relations // hydrate the tags relations
$nbTags = \count($entry->getTags()); $nbTags = count($entry->getTags());
$tag = $entry->getTags()[0]; $tag = $entry->getTags()[0];
$this->client->request('DELETE', '/api/entries/' . $entry->getId() . '/tags/' . $tag->getId() . '.json'); $this->client->request('DELETE', '/api/entries/' . $entry->getId() . '/tags/' . $tag->getId() . '.json');
@ -823,7 +823,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
$content = json_decode($this->client->getResponse()->getContent(), true); $content = json_decode($this->client->getResponse()->getContent(), true);
$this->assertArrayHasKey('tags', $content); $this->assertArrayHasKey('tags', $content);
$this->assertSame($nbTags - 1, \count($content['tags'])); $this->assertSame($nbTags - 1, count($content['tags']));
} }
public function testSaveIsArchivedAfterPost() public function testSaveIsArchivedAfterPost()

View File

@ -166,14 +166,15 @@ class EntryControllerTest extends WallabagCoreTestCase
$this->assertSame($this->url, $content->getUrl()); $this->assertSame($this->url, $content->getUrl());
$this->assertContains('Google', $content->getTitle()); $this->assertContains('Google', $content->getTitle());
$this->assertSame('fr', $content->getLanguage()); $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()); $this->assertSame('Morgane Tual', $author[0]);
$this->assertArrayHasKey('x-varnish1', $content->getHeaders());
$client->getContainer()->get('craue_config')->set('store_article_headers', 0); $client->getContainer()->get('craue_config')->set('store_article_headers', 0);
} }
public function testPostWithMultipleAuthors() public function testPostWithMultipleAuthors()
{ {
$url = 'https://www.liberation.fr/planete/2017/04/05/donald-trump-et-xi-jinping-tentative-de-flirt-en-floride_1560768'; $url = 'http://www.liberation.fr/planete/2017/04/05/donald-trump-et-xi-jinping-tentative-de-flirt-en-floride_1560768';
$this->logInAs('admin'); $this->logInAs('admin');
$client = $this->getClient(); $client = $this->getClient();
@ -196,7 +197,6 @@ class EntryControllerTest extends WallabagCoreTestCase
->getRepository('WallabagCoreBundle:Entry') ->getRepository('WallabagCoreBundle:Entry')
->findByUrlAndUserId($url, $this->getLoggedInUserId()); ->findByUrlAndUserId($url, $this->getLoggedInUserId());
$this->assertInstanceOf('Wallabag\CoreBundle\Entity\Entry', $content);
$authors = $content->getPublishedBy(); $authors = $content->getPublishedBy();
$this->assertSame('2017-04-05 19:26:13', $content->getPublishedAt()->format('Y-m-d H:i:s')); $this->assertSame('2017-04-05 19:26:13', $content->getPublishedAt()->format('Y-m-d H:i:s'));
$this->assertSame('fr', $content->getLanguage()); $this->assertSame('fr', $content->getLanguage());
@ -524,7 +524,7 @@ class EntryControllerTest extends WallabagCoreTestCase
$this->assertGreaterThan(1, $title = $crawler->filter('div[id=article] h1')->extract(['_text'])); $this->assertGreaterThan(1, $title = $crawler->filter('div[id=article] h1')->extract(['_text']));
$this->assertContains('My updated title hehe :)', $title[0]); $this->assertContains('My updated title hehe :)', $title[0]);
$this->assertSame(1, \count($stats = $crawler->filter('div[class=tools] ul[class=stats] li a[class=tool]')->extract(['_text']))); $this->assertSame(1, count($stats = $crawler->filter('div[class=tools] ul[class=stats] li a[class=tool]')->extract(['_text'])));
$this->assertNotContains('example.io', trim($stats[0])); $this->assertNotContains('example.io', trim($stats[0]));
} }
@ -1325,12 +1325,16 @@ class EntryControllerTest extends WallabagCoreTestCase
'http://www.hao123.com/shequ?__noscript__-=1', 'http://www.hao123.com/shequ?__noscript__-=1',
'zh_CN', 'zh_CN',
], ],
'ru' => [ 'de_AT' => [
'https://www.kp.ru/daily/26879.7/3921982/', 'https://buy.garmin.com/de-AT/AT/catalog/product/compareResult.ep?compareProduct=112885&compareProduct=36728',
'ru', 'de_AT',
],
'ru_RU' => [
'http://netler.ru/ikt/windows-error-reporting.htm',
'ru_RU',
], ],
'pt_BR' => [ 'pt_BR' => [
'https://politica.estadao.com.br/noticias/eleicoes,campanha-catatonica,70002491983', 'http://precodoscombustiveis.com.br/postos/cidade/4121/pr/maringa',
'pt_BR', 'pt_BR',
], ],
'fucked_list_of_languages' => [ 'fucked_list_of_languages' => [

View File

@ -180,7 +180,7 @@ class ExportControllerTest extends WallabagCoreTestCase
$this->assertGreaterThan(1, $csv); $this->assertGreaterThan(1, $csv);
// +1 for title line // +1 for title line
$this->assertSame(\count($contentInDB) + 1, \count($csv)); $this->assertSame(count($contentInDB) + 1, count($csv));
$this->assertSame('Title;URL;Content;Tags;"MIME Type";Language;"Creation date"', $csv[0]); $this->assertSame('Title;URL;Content;Tags;"MIME Type";Language;"Creation date"', $csv[0]);
$this->assertContains($contentInDB[0]['title'], $csv[1]); $this->assertContains($contentInDB[0]['title'], $csv[1]);
$this->assertContains($contentInDB[0]['url'], $csv[1]); $this->assertContains($contentInDB[0]['url'], $csv[1]);
@ -272,7 +272,7 @@ class ExportControllerTest extends WallabagCoreTestCase
$content = new \SimpleXMLElement($client->getResponse()->getContent()); $content = new \SimpleXMLElement($client->getResponse()->getContent());
$this->assertGreaterThan(0, $content->count()); $this->assertGreaterThan(0, $content->count());
$this->assertSame(\count($contentInDB), $content->count()); $this->assertSame(count($contentInDB), $content->count());
$this->assertNotEmpty('id', (string) $content->entry[0]->id); $this->assertNotEmpty('id', (string) $content->entry[0]->id);
$this->assertNotEmpty('title', (string) $content->entry[0]->title); $this->assertNotEmpty('title', (string) $content->entry[0]->title);
$this->assertNotEmpty('url', (string) $content->entry[0]->url); $this->assertNotEmpty('url', (string) $content->entry[0]->url);

View File

@ -98,7 +98,7 @@ class TagControllerTest extends WallabagCoreTestCase
$tags[$key] = $tag->getLabel(); $tags[$key] = $tag->getLabel();
} }
$this->assertGreaterThanOrEqual(2, \count($tags)); $this->assertGreaterThanOrEqual(2, count($tags));
$this->assertNotFalse(array_search('foo2', $tags, true), 'Tag foo2 is assigned to the entry'); $this->assertNotFalse(array_search('foo2', $tags, true), 'Tag foo2 is assigned to the entry');
$this->assertNotFalse(array_search('bar2', $tags, true), 'Tag bar2 is assigned to the entry'); $this->assertNotFalse(array_search('bar2', $tags, true), 'Tag bar2 is assigned to the entry');
} }

View File

@ -531,377 +531,6 @@ class ContentProxyTest extends TestCase
$this->assertSame('1.1.1.1', $entry->getDomainName()); $this->assertSame('1.1.1.1', $entry->getDomainName());
} }
public function testWebsiteWithValidUTF8Title_doNothing()
{
// You can use https://www.online-toolz.com/tools/text-hex-convertor.php to convert UTF-8 text <=> hex
// See http://graphemica.com for more info about the characters
// '😻z' (U+1F63B or F09F98BB; U+2124 or E284A4; U+007A or 7A) in hexadecimal and UTF-8
$actualTitle = $this->hexToStr('F09F98BB' . 'E284A4' . '7A');
$tagger = $this->getTaggerMock();
$tagger->expects($this->once())
->method('tag');
$graby = $this->getMockBuilder('Graby\Graby')
->setMethods(['fetchContent'])
->disableOriginalConstructor()
->getMock();
$graby->expects($this->any())
->method('fetchContent')
->willReturn([
'html' => false,
'title' => $actualTitle,
'url' => '',
'content_type' => 'text/html',
'language' => '',
]);
$proxy = new ContentProxy($graby, $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
$entry = new Entry(new User());
$proxy->updateEntry($entry, 'http://0.0.0.0');
// '😻z' (U+1F63B or F09F98BB; U+2124 or E284A4; U+007A or 7A) in hexadecimal and UTF-8
$expectedTitle = 'F09F98BB' . 'E284A4' . '7A';
$this->assertSame($expectedTitle, $this->strToHex($entry->getTitle()));
}
public function testWebsiteWithInvalidUTF8Title_removeInvalidCharacter()
{
// See http://graphemica.com for more info about the characters
// 'a€b' (61;80;62) in hexadecimal and WINDOWS-1252 - but 80 is a invalid UTF-8 character.
// The correct UTF-8 € character (U+20AC) is E282AC
$actualTitle = $this->hexToStr('61' . '80' . '62');
$tagger = $this->getTaggerMock();
$tagger->expects($this->once())
->method('tag');
$graby = $this->getMockBuilder('Graby\Graby')
->setMethods(['fetchContent'])
->disableOriginalConstructor()
->getMock();
$graby->expects($this->any())
->method('fetchContent')
->willReturn([
'html' => false,
'title' => $actualTitle,
'url' => '',
'content_type' => 'text/html',
'language' => '',
]);
$proxy = new ContentProxy($graby, $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
$entry = new Entry(new User());
$proxy->updateEntry($entry, 'http://0.0.0.0');
// 'ab' (61;62) because all invalid UTF-8 character (like 80) are removed
$expectedTitle = '61' . '62';
$this->assertSame($expectedTitle, $this->strToHex($entry->getTitle()));
}
public function testPdfWithUTF16BETitle_convertToUTF8()
{
// See http://graphemica.com for more info about the characters
// '😻' (U+1F63B;D83DDE3B) in hexadecimal and as UTF16BE
$actualTitle = $this->hexToStr('D83DDE3B');
$tagger = $this->getTaggerMock();
$tagger->expects($this->once())
->method('tag');
$graby = $this->getMockBuilder('Graby\Graby')
->setMethods(['fetchContent'])
->disableOriginalConstructor()
->getMock();
$graby->expects($this->any())
->method('fetchContent')
->willReturn([
'html' => false,
'title' => $actualTitle,
'url' => '',
'content_type' => 'application/pdf',
'language' => '',
]);
$proxy = new ContentProxy($graby, $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
$entry = new Entry(new User());
$proxy->updateEntry($entry, 'http://0.0.0.0');
// '😻' (U+1F63B or F09F98BB) in hexadecimal and UTF-8
$expectedTitle = 'F09F98BB';
$this->assertSame($expectedTitle, $this->strToHex($entry->getTitle()));
}
public function testPdfWithUTF8Title_doNothing()
{
// See http://graphemica.com for more info about the characters
// '😻' (U+1F63B;D83DDE3B) in hexadecimal and as UTF8
$actualTitle = $this->hexToStr('F09F98BB');
$tagger = $this->getTaggerMock();
$tagger->expects($this->once())
->method('tag');
$graby = $this->getMockBuilder('Graby\Graby')
->setMethods(['fetchContent'])
->disableOriginalConstructor()
->getMock();
$graby->expects($this->any())
->method('fetchContent')
->willReturn([
'html' => false,
'title' => $actualTitle,
'url' => '',
'content_type' => 'application/pdf',
'language' => '',
]);
$proxy = new ContentProxy($graby, $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
$entry = new Entry(new User());
$proxy->updateEntry($entry, 'http://0.0.0.0');
// '😻' (U+1F63B or F09F98BB) in hexadecimal and UTF-8
$expectedTitle = 'F09F98BB';
$this->assertSame($expectedTitle, $this->strToHex($entry->getTitle()));
}
public function testPdfWithWINDOWS1252Title_convertToUTF8()
{
// See http://graphemica.com for more info about the characters
// '€' (80) in hexadecimal and WINDOWS-1252
$actualTitle = $this->hexToStr('80');
$tagger = $this->getTaggerMock();
$tagger->expects($this->once())
->method('tag');
$graby = $this->getMockBuilder('Graby\Graby')
->setMethods(['fetchContent'])
->disableOriginalConstructor()
->getMock();
$graby->expects($this->any())
->method('fetchContent')
->willReturn([
'html' => false,
'title' => $actualTitle,
'url' => '',
'content_type' => 'application/pdf',
'language' => '',
]);
$proxy = new ContentProxy($graby, $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
$entry = new Entry(new User());
$proxy->updateEntry($entry, 'http://0.0.0.0');
// '€' (U+20AC or E282AC) in hexadecimal and UTF-8
$expectedTitle = 'E282AC';
$this->assertSame($expectedTitle, $this->strToHex($entry->getTitle()));
}
public function testPdfWithInvalidCharacterInTitle_removeInvalidCharacter()
{
// See http://graphemica.com for more info about the characters
// '😻<F09F98BB>z' (U+1F63B or F09F98BB; U+2124 or E284A4; invalid character 81; U+007A or 7A) in hexadecimal and UTF-8
// 0x81 is not a valid character for UTF16, UTF8 and WINDOWS-1252
$actualTitle = $this->hexToStr('F09F98BB' . 'E284A4' . '81' . '7A');
$tagger = $this->getTaggerMock();
$tagger->expects($this->once())
->method('tag');
$graby = $this->getMockBuilder('Graby\Graby')
->setMethods(['fetchContent'])
->disableOriginalConstructor()
->getMock();
$graby->expects($this->any())
->method('fetchContent')
->willReturn([
'html' => false,
'title' => $actualTitle,
'url' => '',
'content_type' => 'application/pdf',
'language' => '',
]);
$proxy = new ContentProxy($graby, $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
$entry = new Entry(new User());
$proxy->updateEntry($entry, 'http://0.0.0.0');
// '😻z' (U+1F63B or F09F98BB; U+2124 or E284A4; U+007A or 7A) in hexadecimal and UTF-8
// the 0x81 (represented by <20>) is invalid for UTF16, UTF8 and WINDOWS-1252 and is removed
$expectedTitle = 'F09F98BB' . 'E284A4' . '7A';
$this->assertSame($expectedTitle, $this->strToHex($entry->getTitle()));
}
/**
* Data provider for testWithChangedUrl.
*
* Arrays contain the following values:
* $entry_url
* $origin_url
* $content_url
* $expected_entry_url
* $expected_origin_url
* $expected_domain
*/
public function dataForChangedUrl()
{
return [
'normal' => [
'http://0.0.0.0',
null,
'http://1.1.1.1',
'http://1.1.1.1',
'http://0.0.0.0',
'1.1.1.1',
],
'origin already set' => [
'http://0.0.0.0',
'http://hello',
'http://1.1.1.1',
'http://1.1.1.1',
'http://hello',
'1.1.1.1',
],
'trailing slash' => [
'https://example.com/hello-world',
null,
'https://example.com/hello-world/',
'https://example.com/hello-world/',
null,
'example.com',
],
'query string in fetched content' => [
'https://example.org/hello',
null,
'https://example.org/hello?world=1',
'https://example.org/hello?world=1',
'https://example.org/hello',
'example.org',
],
'fragment in fetched content' => [
'https://example.org/hello',
null,
'https://example.org/hello#world',
'https://example.org/hello',
null,
'example.org',
],
'fragment and query string in fetched content' => [
'https://example.org/hello',
null,
'https://example.org/hello?foo#world',
'https://example.org/hello?foo#world',
'https://example.org/hello',
'example.org',
],
'different path and query string in fetch content' => [
'https://example.org/hello',
null,
'https://example.org/world?foo',
'https://example.org/world?foo',
'https://example.org/hello',
'example.org',
],
'feedproxy ignore list test' => [
'http://feedproxy.google.com/~r/Wallabag/~3/helloworld',
null,
'https://example.org/hello-wallabag',
'https://example.org/hello-wallabag',
null,
'example.org',
],
'feedproxy ignore list test with origin url already set' => [
'http://feedproxy.google.com/~r/Wallabag/~3/helloworld',
'https://example.org/this-is-source',
'https://example.org/hello-wallabag',
'https://example.org/hello-wallabag',
'https://example.org/this-is-source',
'example.org',
],
'lemonde ignore pattern test' => [
'http://www.lemonde.fr/tiny/url',
null,
'http://example.com/hello-world',
'http://example.com/hello-world',
null,
'example.com',
],
];
}
/**
* @dataProvider dataForChangedUrl
*/
public function testWithChangedUrl($entry_url, $origin_url, $content_url, $expected_entry_url, $expected_origin_url, $expected_domain)
{
$tagger = $this->getTaggerMock();
$tagger->expects($this->once())
->method('tag');
$proxy = new ContentProxy((new Graby()), $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage, true);
$entry = new Entry(new User());
$entry->setOriginUrl($origin_url);
$proxy->updateEntry(
$entry,
$entry_url,
[
'html' => false,
'title' => '',
'url' => $content_url,
'content_type' => '',
'language' => '',
],
true
);
$this->assertSame($expected_entry_url, $entry->getUrl());
$this->assertSame($expected_domain, $entry->getDomainName());
$this->assertSame($expected_origin_url, $entry->getOriginUrl());
}
/**
* https://stackoverflow.com/a/18506801.
*
* @param $string
*
* @return string
*/
private function strToHex($string)
{
$hex = '';
for ($i = 0; $i < \strlen($string); ++$i) {
$ord = \ord($string[$i]);
$hexCode = dechex($ord);
$hex .= substr('0' . $hexCode, -2);
}
return strtoupper($hex);
}
/**
* https://stackoverflow.com/a/18506801.
*
* @param $hex
*
* @return string
*/
private function hexToStr($hex)
{
$string = '';
for ($i = 0; $i < \strlen($hex) - 1; $i += 2) {
$string .= \chr(hexdec($hex[$i] . $hex[$i + 1]));
}
return $string;
}
private function getTaggerMock() private function getTaggerMock()
{ {
return $this->getMockBuilder(RuleBasedTagger::class) return $this->getMockBuilder(RuleBasedTagger::class)

View File

@ -204,52 +204,4 @@ class DownloadImagesTest extends TestCase
$this->assertNotContains('http://piketty.blog.lemonde.fr/', $res, 'Image srcset attribute were not replaced'); $this->assertNotContains('http://piketty.blog.lemonde.fr/', $res, 'Image srcset attribute were not replaced');
} }
public function testProcessImageWithTrickySrcset()
{
$client = new Client();
$mock = new Mock([
new Response(200, ['content-type' => 'image/jpeg'], Stream::factory(file_get_contents(__DIR__ . '/../fixtures/image-no-content-type.jpg'))),
new Response(200, ['content-type' => 'image/jpeg'], Stream::factory(file_get_contents(__DIR__ . '/../fixtures/image-no-content-type.jpg'))),
new Response(200, ['content-type' => 'image/jpeg'], Stream::factory(file_get_contents(__DIR__ . '/../fixtures/image-no-content-type.jpg'))),
]);
$client->getEmitter()->attach($mock);
$logHandler = new TestHandler();
$logger = new Logger('test', [$logHandler]);
$download = new DownloadImages($client, sys_get_temp_dir() . '/wallabag_test', 'http://wallabag.io/', $logger);
$res = $download->processHtml(123, '<figure id="post-257260" class="align-none media-257260"><img src="https://cdn.css-tricks.com/wp-content/uploads/2017/08/the-critical-request.png" srcset="https://res.cloudinary.com/css-tricks/image/upload/c_scale,w_1000,f_auto,q_auto/v1501594717/the-critical-request_bqdfaa.png 1000w, https://res.cloudinary.com/css-tricks/image/upload/c_scale,w_200,f_auto,q_auto/v1501594717/the-critical-request_bqdfaa.png 200w" sizes="(min-width: 1850px) calc( (100vw - 555px) / 3 )
(min-width: 1251px) calc( (100vw - 530px) / 2 )
(min-width: 1086px) calc(100vw - 480px)
(min-width: 626px) calc(100vw - 335px)
calc(100vw - 30px)" alt="" /></figure>', 'https://css-tricks.com/the-critical-request/');
$this->assertNotContains('f_auto,q_auto', $res, 'Image srcset attribute were not replaced');
}
public function testProcessImageWithNullPath()
{
$client = new Client();
$mock = new Mock([
new Response(200, ['content-type' => null], Stream::factory(file_get_contents(__DIR__ . '/../fixtures/image-no-content-type.jpg'))),
]);
$client->getEmitter()->attach($mock);
$logHandler = new TestHandler();
$logger = new Logger('test', [$logHandler]);
$download = new DownloadImages($client, sys_get_temp_dir() . '/wallabag_test', 'http://wallabag.io/', $logger);
$res = $download->processSingleImage(
123,
null,
'https://framablog.org/2018/06/30/engagement-atypique/'
);
$this->assertFalse($res);
}
} }

View File

@ -121,7 +121,7 @@ class ChromeControllerTest extends WallabagCoreTestCase
$this->assertInstanceOf('Wallabag\CoreBundle\Entity\Entry', $content); $this->assertInstanceOf('Wallabag\CoreBundle\Entity\Entry', $content);
$this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.usinenouvelle.com is ok'); $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.usinenouvelle.com is ok');
$this->assertNotEmpty($content->getLanguage(), 'Language for http://www.usinenouvelle.com is ok'); $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.usinenouvelle.com is ok');
$this->assertSame(1, \count($content->getTags())); $this->assertSame(1, count($content->getTags()));
$createdAt = $content->getCreatedAt(); $createdAt = $content->getCreatedAt();
$this->assertSame('2011', $createdAt->format('Y')); $this->assertSame('2011', $createdAt->format('Y'));

View File

@ -122,20 +122,20 @@ class FirefoxControllerTest extends WallabagCoreTestCase
$this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://lexpansion.lexpress.fr is ok'); $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://lexpansion.lexpress.fr is ok');
$this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://lexpansion.lexpress.fr is ok'); $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://lexpansion.lexpress.fr is ok');
$this->assertNotEmpty($content->getLanguage(), 'Language for http://lexpansion.lexpress.fr is ok'); $this->assertNotEmpty($content->getLanguage(), 'Language for http://lexpansion.lexpress.fr is ok');
$this->assertSame(3, \count($content->getTags())); $this->assertSame(3, count($content->getTags()));
$content = $client->getContainer() $content = $client->getContainer()
->get('doctrine.orm.entity_manager') ->get('doctrine.orm.entity_manager')
->getRepository('WallabagCoreBundle:Entry') ->getRepository('WallabagCoreBundle:Entry')
->findByUrlAndUserId( ->findByUrlAndUserId(
'https://www.lemonde.fr/disparitions/article/2018/07/05/le-journaliste-et-cineaste-claude-lanzmann-est-mort_5326313_3382.html', 'https://stackoverflow.com/questions/15017163/parser-for-exported-bookmarks-html-file-of-google-chrome-and-mozilla-in-java',
$this->getLoggedInUserId() $this->getLoggedInUserId()
); );
$this->assertInstanceOf('Wallabag\CoreBundle\Entity\Entry', $content); $this->assertInstanceOf('Wallabag\CoreBundle\Entity\Entry', $content);
$this->assertNotEmpty($content->getMimetype(), 'Mimetype for https://www.lemonde.fr is ok'); $this->assertNotEmpty($content->getMimetype(), 'Mimetype for https://stackoverflow.com is ok');
$this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for https://www.lemonde.fr is ok'); $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for https://stackoverflow.com is ok');
$this->assertNotEmpty($content->getLanguage(), 'Language for https://www.lemonde.fr is ok'); $this->assertEmpty($content->getLanguage(), 'Language for https://stackoverflow.com is ok');
$createdAt = $content->getCreatedAt(); $createdAt = $content->getCreatedAt();
$this->assertSame('2013', $createdAt->format('Y')); $this->assertSame('2013', $createdAt->format('Y'));

View File

@ -114,17 +114,15 @@ class InstapaperControllerTest extends WallabagCoreTestCase
->get('doctrine.orm.entity_manager') ->get('doctrine.orm.entity_manager')
->getRepository('WallabagCoreBundle:Entry') ->getRepository('WallabagCoreBundle:Entry')
->findByUrlAndUserId( ->findByUrlAndUserId(
'https://www.liberation.fr/societe/2012/12/06/baumettes-un-tour-en-cellule_865551', 'http://www.liberation.fr/societe/2012/12/06/baumettes-un-tour-en-cellule_865551',
$this->getLoggedInUserId() $this->getLoggedInUserId()
); );
$this->assertInstanceOf('Wallabag\CoreBundle\Entity\Entry', $content); $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://www.liberation.fr is ok');
$this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.liberation.fr is ok');
$this->assertNotEmpty($content->getMimetype(), 'Mimetype for https://www.liberation.fr is ok'); $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.liberation.fr is ok');
$this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for https://www.liberation.fr is ok');
$this->assertNotEmpty($content->getLanguage(), 'Language for https://www.liberation.fr is ok');
$this->assertContains('foot', $content->getTags(), 'It includes the "foot" tag'); $this->assertContains('foot', $content->getTags(), 'It includes the "foot" tag');
$this->assertSame(1, \count($content->getTags())); $this->assertSame(1, count($content->getTags()));
$this->assertInstanceOf(\DateTime::class, $content->getCreatedAt()); $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt());
$content = $client->getContainer() $content = $client->getContainer()
@ -138,7 +136,7 @@ class InstapaperControllerTest extends WallabagCoreTestCase
$this->assertContains('foot', $content->getTags()); $this->assertContains('foot', $content->getTags());
$this->assertContains('test_tag', $content->getTags()); $this->assertContains('test_tag', $content->getTags());
$this->assertSame(2, \count($content->getTags())); $this->assertSame(2, count($content->getTags()));
} }
public function testImportInstapaperWithFileAndMarkAllAsRead() public function testImportInstapaperWithFileAndMarkAllAsRead()

View File

@ -127,7 +127,7 @@ class PinboardControllerTest extends WallabagCoreTestCase
$this->assertContains('foot', $tags, 'It includes the "foot" tag'); $this->assertContains('foot', $tags, 'It includes the "foot" tag');
$this->assertContains('varnish', $tags, 'It includes the "varnish" tag'); $this->assertContains('varnish', $tags, 'It includes the "varnish" tag');
$this->assertContains('php', $tags, 'It includes the "php" tag'); $this->assertContains('php', $tags, 'It includes the "php" tag');
$this->assertSame(3, \count($tags)); $this->assertSame(3, count($tags));
$this->assertInstanceOf(\DateTime::class, $content->getCreatedAt()); $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt());
$this->assertSame('2016-10-26', $content->getCreatedAt()->format('Y-m-d')); $this->assertSame('2016-10-26', $content->getCreatedAt()->format('Y-m-d'));

View File

@ -125,7 +125,7 @@ class ReadabilityControllerTest extends WallabagCoreTestCase
$tags = $content->getTags(); $tags = $content->getTags();
$this->assertContains('foot', $tags, 'It includes the "foot" tag'); $this->assertContains('foot', $tags, 'It includes the "foot" tag');
$this->assertSame(1, \count($tags)); $this->assertSame(1, count($tags));
$this->assertInstanceOf(\DateTime::class, $content->getCreatedAt()); $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt());
$this->assertSame('2016-09-08', $content->getCreatedAt()->format('Y-m-d')); $this->assertSame('2016-09-08', $content->getCreatedAt()->format('Y-m-d'));

View File

@ -127,7 +127,7 @@ class WallabagV1ControllerTest extends WallabagCoreTestCase
$tags = $content->getTags(); $tags = $content->getTags();
$this->assertContains('foot', $tags, 'It includes the "foot" tag'); $this->assertContains('foot', $tags, 'It includes the "foot" tag');
$this->assertContains('framabag', $tags, 'It includes the "framabag" tag'); $this->assertContains('framabag', $tags, 'It includes the "framabag" tag');
$this->assertSame(2, \count($tags)); $this->assertSame(2, count($tags));
$this->assertInstanceOf(\DateTime::class, $content->getCreatedAt()); $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt());
} }

View File

@ -115,20 +115,20 @@ class WallabagV2ControllerTest extends WallabagCoreTestCase
->get('doctrine.orm.entity_manager') ->get('doctrine.orm.entity_manager')
->getRepository('WallabagCoreBundle:Entry') ->getRepository('WallabagCoreBundle:Entry')
->findByUrlAndUserId( ->findByUrlAndUserId(
'https://www.liberation.fr/planete/2015/10/26/refugies-l-ue-va-creer-100-000-places-d-accueil-dans-les-balkans_1408867', 'http://www.liberation.fr/planete/2015/10/26/refugies-l-ue-va-creer-100-000-places-d-accueil-dans-les-balkans_1408867',
$this->getLoggedInUserId() $this->getLoggedInUserId()
); );
$this->assertInstanceOf('Wallabag\CoreBundle\Entity\Entry', $content); $this->assertInstanceOf('Wallabag\CoreBundle\Entity\Entry', $content);
// empty because it wasn't re-imported // empty because it wasn't re-imported
$this->assertEmpty($content->getMimetype(), 'Mimetype for https://www.liberation.fr is empty'); $this->assertEmpty($content->getMimetype(), 'Mimetype for http://www.liberation.fr is empty');
$this->assertEmpty($content->getPreviewPicture(), 'Preview picture for https://www.liberation.fr is empty'); $this->assertEmpty($content->getPreviewPicture(), 'Preview picture for http://www.liberation.fr is empty');
$this->assertEmpty($content->getLanguage(), 'Language for https://www.liberation.fr is empty'); $this->assertEmpty($content->getLanguage(), 'Language for http://www.liberation.fr is empty');
$tags = $content->getTags(); $tags = $content->getTags();
$this->assertContains('foot', $tags, 'It includes the "foot" tag'); $this->assertContains('foot', $tags, 'It includes the "foot" tag');
$this->assertSame(1, \count($tags)); $this->assertSame(1, count($tags));
$content = $client->getContainer() $content = $client->getContainer()
->get('doctrine.orm.entity_manager') ->get('doctrine.orm.entity_manager')
@ -147,7 +147,7 @@ class WallabagV2ControllerTest extends WallabagCoreTestCase
$this->assertContains('foot', $tags, 'It includes the "foot" tag'); $this->assertContains('foot', $tags, 'It includes the "foot" tag');
$this->assertContains('mediapart', $tags, 'It includes the "mediapart" tag'); $this->assertContains('mediapart', $tags, 'It includes the "mediapart" tag');
$this->assertContains('blog', $tags, 'It includes the "blog" tag'); $this->assertContains('blog', $tags, 'It includes the "blog" tag');
$this->assertSame(3, \count($tags)); $this->assertSame(3, count($tags));
$this->assertInstanceOf(\DateTime::class, $content->getCreatedAt()); $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt());
$this->assertSame('2016-09-08', $content->getCreatedAt()->format('Y-m-d')); $this->assertSame('2016-09-08', $content->getCreatedAt()->format('Y-m-d'));

Some files were not shown because too many files have changed in this diff Show More