--- /dev/null
+<?php
+
+declare(strict_types=1);
+
+namespace Application\Migrations;
+
+use Doctrine\DBAL\Schema\Schema;
+use Wallabag\CoreBundle\Doctrine\WallabagMigration;
+
+/**
+ * Convert tab label to utf8mb4_bin (MySQL only).
+ */
+final class Version20190511165128 extends WallabagMigration
+{
+ public function up(Schema $schema): void
+ {
+ $this->skipIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'This migration only apply to MySQL');
+
+ $this->addSql('ALTER TABLE ' . $this->getTable('tag') . ' CHANGE `label` `label` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;');
+ $this->addSql('ALTER TABLE ' . $this->getTable('tag') . ' CHANGE `slug` `slug` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;');
+ }
+
+ public function down(Schema $schema): void
+ {
+ $this->skipIf('mysql' !== $this->connection->getDatabasePlatform()->getName(), 'This migration only apply to MySQL');
+
+ $this->addSql('ALTER TABLE ' . $this->getTable('tag') . ' CHANGE `slug` `slug` VARCHAR(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
+ $this->addSql('ALTER TABLE ' . $this->getTable('tag') . ' CHANGE `label` `label` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;');
+ }
+}
return $this->redirect($this->generateUrl('config') . '#set2');
}
+ /**
+ * @param Request $request
+ *
+ * @Route("/revoke-token", name="revoke_token")
+ *
+ * @return RedirectResponse|JsonResponse
+ */
+ public function revokeTokenAction(Request $request)
+ {
+ $config = $this->getConfig();
+ $config->setFeedToken(null);
+
+ $em = $this->getDoctrine()->getManager();
+ $em->persist($config);
+ $em->flush();
+
+ if ($request->isXmlHttpRequest()) {
+ return new JsonResponse();
+ }
+
+ $this->addFlash(
+ 'notice',
+ 'flashes.config.notice.feed_token_revoked'
+ );
+
+ return $this->redirect($this->generateUrl('config') . '#set2');
+ }
+
/**
* Deletes a tagging rule and redirect to the config homepage.
*
* Tag.
*
* @XmlRoot("tag")
- * @ORM\Table(name="`tag`")
+ * @ORM\Table(
+ * name="`tag`",
+ * options={"collate"="utf8mb4_bin", "charset"="utf8mb4"},
+ * )
* @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\TagRepository")
* @ExclusionPolicy("all")
*/
back_to_unread: 'Tilbage til de ulæste artikler'
# users_management: 'Users management'
# site_credentials: 'Site credentials'
+ # quickstart: "Quickstart"
top:
add_new_entry: 'Tilføj ny artikel'
search: 'Søg'
no_token: 'Intet token'
token_create: 'Opret token'
token_reset: 'Nulstil token'
+ # token_revoke: 'Revoke the token'
feed_links: 'RSS-Links'
feed_link:
unread: 'Ulæst'
# tagging_rules_updated: 'Tagging rules updated'
# tagging_rules_deleted: 'Tagging rule deleted'
# feed_token_updated: 'RSS token updated'
+ # feed_token_revoked: 'RSS token revoked'
# annotations_reset: Annotations reset
# tags_reset: Tags reset
# entries_reset: Entries reset
back_to_unread: 'Zurück zu ungelesenen Artikeln'
users_management: 'Benutzerverwaltung'
site_credentials: 'Zugangsdaten'
+ quickstart: "Schnelleinstieg"
top:
add_new_entry: 'Neuen Artikel hinzufügen'
search: 'Suche'
no_token: 'Kein Token'
token_create: 'Token erstellen'
token_reset: 'Token zurücksetzen'
+ # token_revoke: 'Revoke the token'
feed_links: 'RSS-Links'
feed_link:
unread: 'Ungelesene'
tagging_rules_updated: 'Tagging-Regeln aktualisiert'
tagging_rules_deleted: 'Tagging-Regel gelöscht'
feed_token_updated: 'RSS-Token aktualisiert'
+ # feed_token_revoked: 'RSS token revoked'
annotations_reset: Anmerkungen zurücksetzen
tags_reset: Tags zurücksetzen
entries_reset: Einträge zurücksetzen
back_to_unread: 'Back to unread articles'
users_management: 'Users management'
site_credentials: 'Site credentials'
+ quickstart: "Quickstart"
top:
add_new_entry: 'Add a new entry'
search: 'Search'
no_token: 'No token'
token_create: 'Create your token'
token_reset: 'Regenerate your token'
+ token_revoke: 'Revoke the token'
feed_links: 'Feed links'
feed_link:
unread: 'Unread'
tagging_rules_updated: 'Tagging rules updated'
tagging_rules_deleted: 'Tagging rule deleted'
feed_token_updated: 'Feed token updated'
+ feed_token_revoked: 'RSS token revoked'
annotations_reset: Annotations reset
tags_reset: Tags reset
entries_reset: Entries reset
back_to_unread: 'Volver a los artículos sin leer'
users_management: 'Configuración de usuarios'
# site_credentials: 'Site credentials'
+ quickstart: "Inicio rápido"
top:
add_new_entry: 'Añadir un nuevo artículo'
search: 'Buscar'
no_token: 'Sin token'
token_create: 'Crear token'
token_reset: 'Reiniciar token'
+ # token_revoke: 'Revoke the token'
feed_links: 'URLs de feeds RSS'
feed_link:
unread: 'sin leer'
tagging_rules_updated: 'Regla de etiquetado actualizada'
tagging_rules_deleted: 'Regla de etiquetado eliminada'
feed_token_updated: 'Token RSS actualizado'
+ # feed_token_revoked: 'RSS token revoked'
annotations_reset: Anotaciones reiniciadas
tags_reset: Etiquetas reiniciadas
entries_reset: Artículos reiniciados
back_to_unread: 'بازگشت به خواندهنشدهها'
# users_management: 'Users management'
# site_credentials: 'Site credentials'
+ quickstart: "Quickstart"
top:
add_new_entry: 'افزودن مقالهٔ تازه'
search: 'جستجو'
no_token: 'بدون کد'
token_create: 'کد خود را بسازید'
token_reset: 'بازنشانی کد'
+ # token_revoke: 'Revoke the token'
feed_links: 'پیوند آر-اس-اس'
feed_link:
unread: 'خواندهنشده'
tagging_rules_updated: 'برچسبگذاری خودکار بهروز شد'
tagging_rules_deleted: 'قانون برچسبگذاری پاک شد'
feed_token_updated: 'کد آر-اس-اس بهروز شد'
+ # feed_token_revoked: 'RSS token revoked'
# annotations_reset: Annotations reset
# tags_reset: Tags reset
# entries_reset: Entries reset
back_to_unread: "Retour aux articles non lus"
users_management: "Gestion des utilisateurs"
site_credentials: 'Accès aux sites'
+ quickstart: "Pour bien débuter"
top:
add_new_entry: "Sauvegarder un nouvel article"
search: "Rechercher"
no_token: "Aucun jeton généré"
token_create: "Créez votre jeton"
token_reset: "Réinitialisez votre jeton"
+ token_revoke: 'Supprimer le jeton'
feed_links: "Adresses de vos flux"
feed_link:
unread: "Non lus"
tagging_rules_updated: "Règles mises à jour"
tagging_rules_deleted: "Règle supprimée"
feed_token_updated: "Jeton des flux mis à jour"
+ feed_token_revoked: 'Jeton des flux supprimé'
annotations_reset: "Annotations supprimées"
tags_reset: "Tags supprimés"
entries_reset: "Articles supprimés"
back_to_unread: 'Torna ai contenuti non letti'
users_management: 'Gestione utenti'
site_credentials: 'Credenziali sito'
+ quickstart: "Introduzione"
top:
add_new_entry: 'Aggiungi un nuovo contenuto'
search: 'Cerca'
no_token: 'Nessun token'
token_create: 'Crea il tuo token'
token_reset: 'Rigenera il tuo token'
+ # token_revoke: 'Revoke the token'
feed_links: 'Collegamenti RSS'
feed_link:
unread: 'Non letti'
tagging_rules_updated: 'Regole di etichettatura aggiornate'
tagging_rules_deleted: 'Regola di etichettatura eliminate'
feed_token_updated: 'RSS token aggiornato'
+ # feed_token_revoked: 'RSS token revoked'
annotations_reset: Reset annotazioni
tags_reset: Reset etichette
entries_reset: Reset articoli
back_to_unread: 'Tornar als articles pas legits'
users_management: 'Gestion dels utilizaires'
site_credentials: 'Identificants del site'
+ quickstart: "Per ben començar"
top:
add_new_entry: 'Enregistrar un novèl article'
search: 'Cercar'
no_token: 'Pas cap de geton generat'
token_create: 'Creatz vòstre geton'
token_reset: 'Reïnicializatz vòstre geton'
+ # token_revoke: 'Revoke the token'
feed_links: 'URLs de vòstres fluxes RSS'
feed_link:
unread: 'Pas legits'
tagging_rules_updated: 'Règlas misa a jorn'
tagging_rules_deleted: 'Règla suprimida'
feed_token_updated: 'Geton RSS mes a jorn'
+ # feed_token_revoked: 'RSS token revoked'
annotations_reset: Anotacions levadas
tags_reset: Etiquetas levadas
entries_reset: Articles levats
back_to_unread: 'Powrót do nieprzeczytanych artykułów'
users_management: 'Zarządzanie użytkownikami'
site_credentials: 'Poświadczenia strony'
+ quickstart: "Szybki start"
top:
add_new_entry: 'Dodaj nowy wpis'
search: 'Szukaj'
no_token: 'Brak tokena'
token_create: 'Stwórz tokena'
token_reset: 'Zresetuj swojego tokena'
+ # token_revoke: 'Revoke the token'
feed_links: 'RSS links'
feed_link:
unread: 'Nieprzeczytane'
tagging_rules_updated: 'Reguły tagowania zaktualizowane'
tagging_rules_deleted: 'Reguła tagowania usunięta'
feed_token_updated: 'Token kanału RSS zaktualizowany'
+ # feed_token_revoked: 'RSS token revoked'
annotations_reset: Zresetuj adnotacje
tags_reset: Zresetuj tagi
entries_reset: Zresetuj wpisy
back_to_unread: 'Voltar para os artigos não lidos'
users_management: 'Gestão de Usuários'
# site_credentials: 'Site credentials'
+ quickstart: "Começo Rápido"
top:
add_new_entry: 'Adicionar uma nova entrada'
search: 'Pesquisa'
no_token: 'Nenhum Token'
token_create: 'Criar seu token'
token_reset: 'Gerar novamente seu token'
+ # token_revoke: 'Revoke the token'
feed_links: 'Links RSS'
feed_link:
unread: 'Não lido'
tagging_rules_updated: 'Regras de tags atualizadas'
tagging_rules_deleted: 'Regra de tag apagada'
feed_token_updated: 'Token RSS atualizado'
+ # feed_token_revoked: 'RSS token revoked'
# annotations_reset: Annotations reset
# tags_reset: Tags reset
# entries_reset: Entries reset
back_to_unread: 'Înapoi la articolele necitite'
# users_management: 'Users management'
# site_credentials: 'Site credentials'
+ # quickstart: "Quickstart"
top:
add_new_entry: 'Introdu un nou articol'
search: 'Căutare'
no_token: 'Fără token'
token_create: 'Crează-ți token'
token_reset: 'Resetează-ți token-ul'
+ # token_revoke: 'Revoke the token'
feed_links: 'Link-uri RSS'
feed_link:
unread: 'Unread'
# tagging_rules_updated: 'Tagging rules updated'
# tagging_rules_deleted: 'Tagging rule deleted'
# feed_token_updated: 'RSS token updated'
+ # feed_token_revoked: 'RSS token revoked'
# annotations_reset: Annotations reset
# tags_reset: Tags reset
# entries_reset: Entries reset
save_link: 'Сохранить ссылку'
back_to_unread: 'Назад к непрочитанным записям'
users_management: 'Управление пользователями'
+ site_credentials: 'Site credentials'
+ quickstart: "Быстрый старт"
top:
add_new_entry: 'Добавить новую запись'
search: 'Поиск'
no_token: 'Ключ не задан'
token_create: 'Создать ключ'
token_reset: 'Пересоздать ключ'
+ # token_revoke: 'Revoke the token'
feed_links: 'ссылка на RSS'
feed_link:
unread: 'непрочитанные'
tagging_rules_updated: 'Правила тегировния обновлены'
tagging_rules_deleted: 'Правила тегировния удалены'
feed_token_updated: 'RSS ключ обновлен'
+ # feed_token_revoked: 'RSS token revoked'
annotations_reset: "Аннотации сброшены"
tags_reset: "Теги сброшены"
entries_reset: "Записи сброшены"
back_to_unread: 'กลับไปยังรายการที่ไม่ได้อ่าน'
users_management: 'การจัดการผู้ใช้'
site_credentials: 'การรับรองไซต์'
+ quickstart: "เริ่มแบบด่วน"
top:
add_new_entry: 'เพิ่มรายการใหม่'
search: 'ค้นหา'
no_token: 'ไม่มีเครื่องหมาย'
token_create: 'สร้างเครื่องหมาย'
token_reset: 'ทำเครื่องหมาย'
+ # token_revoke: 'Revoke the token'
feed_links: 'ลิงค์ RSS'
feed_link:
unread: 'ยังไมได้่อ่าน'
tagging_rules_updated: 'อัปเดตการแท็กข้อบังคับ'
tagging_rules_deleted: 'การลบข้อบังคับของแท็ก'
feed_token_updated: 'อัปเดตเครื่องหมาย RSS '
+ # feed_token_revoked: 'RSS token revoked'
annotations_reset: รีเซ็ตหมายเหตุ
tags_reset: รีเซ็ตแท็ก
entries_reset: รีเซ็ตรายการ
back_to_unread: 'Okunmayan makalelere geri dön'
# users_management: 'Users management'
# site_credentials: 'Site credentials'
+ quickstart: "Hızlı başlangıç"
top:
add_new_entry: 'Yeni bir makale ekle'
search: 'Ara'
no_token: 'Belirteç (token) yok'
token_create: 'Yeni belirteç (token) oluştur'
token_reset: 'Belirteci (token) sıfırla'
+ # token_revoke: 'Revoke the token'
feed_links: 'RSS akış bağlantıları'
feed_link:
unread: 'Okunmayan'
{% else %}
<em>{{ 'config.form_feed.no_token'|trans }}</em>
{% endif %}
- –
- <a href="{{ path('generate_token') }}">
- {% if feed.token %}
- {{ 'config.form_feed.token_reset'|trans }}
- {% else %}
- {{ 'config.form_feed.token_create'|trans }}
- {% endif %}
- </a>
+
+ {% if feed.token %}
+ – <a href="{{ path('generate_token') }}">{{ 'config.form_feed.token_reset'|trans }}</a>
+ – <a href="{{ path('revoke_token') }}">{{ 'config.form_feed.token_revoke'|trans }}</a>
+ {% else %}
+ – <a href="{{ path('generate_token') }}">{{ 'config.form_feed.token_create'|trans }}</a>
+ {% endif %}
+
</div>
</fieldset>
<li class="menu howto"><a href="{{ path('howto') }}">{{ 'menu.left.howto'|trans }}</a></li>
<li class="menu developer"><a href="{{ path('developer') }}">{{ 'menu.left.developer'|trans }}</a></li>
<li class="menu about"><a href="{{ path('about') }}">{{ 'footer.wallabag.about'|trans }}</a></li>
+ <li class="menu quickstart"><a href="{{ path('quickstart') }}">{{ 'menu.left.quickstart'|trans }}</a></li>
<li class="menu logout"><a class="icon icon-power" href="{{ path('fos_user_security_logout') }}">{{ 'menu.left.logout'|trans }}</a></li>
</ul>
{% endblock %}
{% else %}
<em>{{ 'config.form_feed.no_token'|trans }}</em>
{% endif %}
- – <a href="{{ path('generate_token') }}">
+
{% if feed.token %}
- {{ 'config.form_feed.token_reset'|trans }}
+ – <a href="{{ path('generate_token') }}">{{ 'config.form_feed.token_reset'|trans }}</a>
+ – <a href="{{ path('revoke_token') }}">{{ 'config.form_feed.token_revoke'|trans }}</a>
{% else %}
- {{ 'config.form_feed.token_create'|trans }}
- {% endif %}</a>
+ – <a href="{{ path('generate_token') }}">{{ 'config.form_feed.token_create'|trans }}</a>
+ {% endif %}
</div>
</div>
</div>
<li class="bold {% if currentRoute == 'howto' %}active{% endif %}">
<a class="waves-effect" href="{{ path('howto') }}">{{ 'menu.left.howto'|trans }}</a>
</li>
+ <li class="bold {% if currentRoute == 'quickstart' %}active{% endif %}">
+ <a class="waves-effect" href="{{ path('quickstart') }}">{{ 'menu.left.quickstart'|trans }}</a>
+ </li>
<li class="bold">
<a class="waves-effect icon icon-power" href="{{ path('fos_user_security_logout') }}">{{ 'menu.left.logout'|trans }}</a>
</li>
$crawler = $client->followRedirect();
$this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
- $this->assertNotContains('config.form_feed.no_token', $body[0]);
+ $this->assertContains('config.form_feed.token_reset', $body[0]);
}
public function testGenerateTokenAjax()
$this->assertArrayHasKey('token', $content);
}
+ public function testRevokeTokenAjax()
+ {
+ $this->logInAs('admin');
+ $client = $this->getClient();
+
+ $client->request(
+ 'GET',
+ '/revoke-token',
+ [],
+ [],
+ ['HTTP_X-Requested-With' => 'XMLHttpRequest']
+ );
+
+ $this->assertSame(200, $client->getResponse()->getStatusCode());
+ }
+
public function testFeedUpdate()
{
$this->logInAs('admin');
$this->assertInstanceOf(Tag::class, $newTag, 'Tag "specific label" exists.');
$this->assertTrue($newTag->hasEntry($freshEntry), 'Tag "specific label" is assigned to the entry.');
}
+
+ public function testAddUnicodeTagLabel()
+ {
+ $this->logInAs('admin');
+ $client = $this->getClient();
+
+ $entry = new Entry($this->getLoggedInUser());
+ $entry->setUrl('http://0.0.0.0/tag-caché');
+ $this->getEntityManager()->persist($entry);
+ $this->getEntityManager()->flush();
+ $this->getEntityManager()->clear();
+
+ $crawler = $client->request('GET', '/view/' . $entry->getId());
+
+ $form = $crawler->filter('form[name=tag]')->form();
+
+ $data = [
+ 'tag[label]' => 'cache',
+ ];
+
+ $client->submit($form, $data);
+
+ $crawler = $client->request('GET', '/view/' . $entry->getId());
+
+ $form = $crawler->filter('form[name=tag]')->form();
+
+ $data = [
+ 'tag[label]' => 'caché',
+ ];
+
+ $client->submit($form, $data);
+
+ $newEntry = $client->getContainer()
+ ->get('doctrine.orm.entity_manager')
+ ->getRepository('WallabagCoreBundle:Entry')
+ ->find($entry->getId());
+
+ $tags = $newEntry->getTags()->toArray();
+ foreach ($tags as $key => $tag) {
+ $tags[$key] = $tag->getLabel();
+ }
+
+ $this->assertGreaterThanOrEqual(2, \count($tags));
+ $this->assertNotFalse(array_search('cache', $tags, true), 'Tag cache is assigned to the entry');
+ $this->assertNotFalse(array_search('caché', $tags, true), 'Tag caché is assigned to the entry');
+ }
}