From: Jeremy Benoist Date: Wed, 26 Jun 2019 20:31:47 +0000 (+0200) Subject: Add ability to import/export tagging rules X-Git-Url: https://git.immae.eu/?p=github%2Fwallabag%2Fwallabag.git;a=commitdiff_plain;h=34be2d5de44ade2a78be73decc0b90a2c1bca720 Add ability to import/export tagging rules - Add missing translations - Add some tests - Add `/api/taggingrule/export` API endpoint - Add baggy theme - Add error message when importing tagging rules failed - Also fix all translations (I think we are good now) --- diff --git a/.gitignore b/.gitignore index 49ff72c6..553b0e94 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ web/uploads/ # Build /app/build /build +/coverage # Composer PHAR /composer.phar diff --git a/src/Wallabag/ApiBundle/Controller/TaggingRuleRestController.php b/src/Wallabag/ApiBundle/Controller/TaggingRuleRestController.php new file mode 100644 index 00000000..2496298a --- /dev/null +++ b/src/Wallabag/ApiBundle/Controller/TaggingRuleRestController.php @@ -0,0 +1,39 @@ +validateAuthentication(); + + $data = SerializerBuilder::create()->build()->serialize( + $this->getUser()->getConfig()->getTaggingRules(), + 'json', + SerializationContext::create()->setGroups(['export_tagging_rule']) + ); + + return Response::create( + $data, + 200, + [ + 'Content-type' => 'application/json', + 'Content-Disposition' => 'attachment; filename="tagging_rules_' . $this->getUser()->getUsername() . '.json"', + 'Content-Transfer-Encoding' => 'UTF-8', + ] + ); + } +} diff --git a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml index 06e62c37..98efeeb1 100644 --- a/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml +++ b/src/Wallabag/ApiBundle/Resources/config/routing_rest.yml @@ -13,6 +13,11 @@ tag: resource: "WallabagApiBundle:TagRest" name_prefix: api_ +tagging_rule: + type: rest + resource: "WallabagApiBundle:TaggingRuleRest" + name_prefix: api_ + annotation: type: rest resource: "WallabagApiBundle:AnnotationRest" diff --git a/src/Wallabag/CoreBundle/Controller/ConfigController.php b/src/Wallabag/CoreBundle/Controller/ConfigController.php index cea41303..0db90ba4 100644 --- a/src/Wallabag/CoreBundle/Controller/ConfigController.php +++ b/src/Wallabag/CoreBundle/Controller/ConfigController.php @@ -2,11 +2,14 @@ namespace Wallabag\CoreBundle\Controller; +use JMS\Serializer\SerializationContext; +use JMS\Serializer\SerializerBuilder; use PragmaRX\Recovery\Recovery as BackupCodes; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\Routing\Annotation\Route; use Symfony\Component\Validator\Constraints\Locale as LocaleConstraint; @@ -15,6 +18,7 @@ use Wallabag\CoreBundle\Entity\TaggingRule; use Wallabag\CoreBundle\Form\Type\ChangePasswordType; use Wallabag\CoreBundle\Form\Type\ConfigType; use Wallabag\CoreBundle\Form\Type\FeedType; +use Wallabag\CoreBundle\Form\Type\TaggingRuleImportType; use Wallabag\CoreBundle\Form\Type\TaggingRuleType; use Wallabag\CoreBundle\Form\Type\UserInformationType; use Wallabag\CoreBundle\Tools\Utils; @@ -140,6 +144,37 @@ class ConfigController extends Controller return $this->redirect($this->generateUrl('config') . '#set5'); } + // handle tagging rules import + $taggingRulesImportform = $this->createForm(TaggingRuleImportType::class); + $taggingRulesImportform->handleRequest($request); + + if ($taggingRulesImportform->isSubmitted() && $taggingRulesImportform->isValid()) { + $message = 'flashes.config.notice.tagging_rules_not_imported'; + $file = $taggingRulesImportform->get('file')->getData(); + + if (null !== $file && $file->isValid() && \in_array($file->getClientMimeType(), ['application/json', 'application/octet-stream'], true)) { + $content = json_decode(file_get_contents($file->getPathname()), true); + + if (\is_array($content)) { + foreach ($content as $rule) { + $taggingRule = new TaggingRule(); + $taggingRule->setRule($rule['rule']); + $taggingRule->setTags($rule['tags']); + $taggingRule->setConfig($config); + $em->persist($taggingRule); + } + + $em->flush(); + + $message = 'flashes.config.notice.tagging_rules_imported'; + } + } + + $this->addFlash('notice', $message); + + return $this->redirect($this->generateUrl('config') . '#set5'); + } + return $this->render('WallabagCoreBundle:Config:index.html.twig', [ 'form' => [ 'config' => $configForm->createView(), @@ -147,6 +182,7 @@ class ConfigController extends Controller 'pwd' => $pwdForm->createView(), 'user' => $userForm->createView(), 'new_tagging_rule' => $newTaggingRule->createView(), + 'import_tagging_rule' => $taggingRulesImportform->createView(), ], 'feed' => [ 'username' => $user->getUsername(), @@ -492,6 +528,32 @@ class ConfigController extends Controller return $this->redirect($request->headers->get('referer', $this->generateUrl('homepage'))); } + /** + * Export tagging rules for the logged in user. + * + * @Route("/tagging-rule/export", name="export_tagging_rule") + * + * @return Response + */ + public function exportTaggingRulesAction() + { + $data = SerializerBuilder::create()->build()->serialize( + $this->getUser()->getConfig()->getTaggingRules(), + 'json', + SerializationContext::create()->setGroups(['export_tagging_rule']) + ); + + return Response::create( + $data, + 200, + [ + 'Content-type' => 'application/json', + 'Content-Disposition' => 'attachment; filename="tagging_rules_' . $this->getUser()->getUsername() . '.json"', + 'Content-Transfer-Encoding' => 'UTF-8', + ] + ); + } + /** * Remove all tags for given tags and a given user and cleanup orphan tags. * diff --git a/src/Wallabag/CoreBundle/Entity/TaggingRule.php b/src/Wallabag/CoreBundle/Entity/TaggingRule.php index c1be3165..eac53fa3 100644 --- a/src/Wallabag/CoreBundle/Entity/TaggingRule.php +++ b/src/Wallabag/CoreBundle/Entity/TaggingRule.php @@ -3,12 +3,16 @@ namespace Wallabag\CoreBundle\Entity; use Doctrine\ORM\Mapping as ORM; +use JMS\Serializer\Annotation\Exclude; +use JMS\Serializer\Annotation\Groups; +use JMS\Serializer\Annotation\XmlRoot; use Symfony\Bridge\RulerZ\Validator\Constraints as RulerZAssert; use Symfony\Component\Validator\Constraints as Assert; /** * Tagging rule. * + * @XmlRoot("tagging_rule") * @ORM\Entity(repositoryClass="Wallabag\CoreBundle\Repository\TaggingRuleRepository") * @ORM\Table(name="`tagging_rule`") * @ORM\Entity @@ -34,6 +38,8 @@ class TaggingRule * allowed_operators={">", "<", ">=", "<=", "=", "is", "!=", "and", "not", "or", "matches", "notmatches"} * ) * @ORM\Column(name="rule", type="string", nullable=false) + * + * @Groups({"export_tagging_rule"}) */ private $rule; @@ -42,10 +48,14 @@ class TaggingRule * * @Assert\NotBlank() * @ORM\Column(name="tags", type="simple_array", nullable=false) + * + * @Groups({"export_tagging_rule"}) */ private $tags = []; /** + * @Exclude + * * @ORM\ManyToOne(targetEntity="Wallabag\CoreBundle\Entity\Config", inversedBy="taggingRules") */ private $config; diff --git a/src/Wallabag/CoreBundle/Form/Type/TaggingRuleImportType.php b/src/Wallabag/CoreBundle/Form/Type/TaggingRuleImportType.php new file mode 100644 index 00000000..c6a8c0b8 --- /dev/null +++ b/src/Wallabag/CoreBundle/Form/Type/TaggingRuleImportType.php @@ -0,0 +1,29 @@ +add('file', FileType::class, [ + 'label' => 'config.form_rules.file_label', + 'required' => true, + ]) + ->add('import', SubmitType::class, [ + 'label' => 'config.form_rules.import_submit', + ]) + ; + } + + public function getBlockPrefix() + { + return 'upload_tagging_rule_file'; + } +} diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml index 5c4ca29c..fab05835 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.da.yml @@ -140,6 +140,15 @@ config: # edit_rule_label: 'edit' # rule_label: 'Rule' # tags_label: 'Tags' + # card: + # new_tagging_rule: Create a tagging rule + # import_tagging_rules: Import tagging rules + # import_tagging_rules_detail: You have to select the JSON file you previously exported. + # export_tagging_rules: Export tagging rules + # export_tagging_rules_detail: This will download a JSON file that you can use to import tagging rules elsewhere or to backup them. + # file_label: JSON file + # import_submit: Import + # export: Export # faq: # title: 'FAQ' # tagging_rules_definition_title: 'What does « tagging rules » mean?' @@ -602,6 +611,9 @@ flashes: # tags_reset: Tags reset # entries_reset: Entries reset # archived_reset: Archived entries deleted + # otp_enabled: Two-factor authentication enabled + # tagging_rules_imported: Tagging rules imported + # tagging_rules_not_imported: Error while importing tagging rules entry: notice: # entry_already_saved: 'Entry already saved on %date%' diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml index a21bd0f1..6ba464d0 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.de.yml @@ -140,6 +140,15 @@ config: edit_rule_label: 'bearbeiten' rule_label: 'Regel' tags_label: 'Tags' + # card: + # new_tagging_rule: Create a tagging rule + # import_tagging_rules: Import tagging rules + # import_tagging_rules_detail: You have to select the JSON file you previously exported. + # export_tagging_rules: Export tagging rules + # export_tagging_rules_detail: This will download a JSON file that you can use to import tagging rules elsewhere or to backup them. + # file_label: JSON file + # import_submit: Import + # export: Export faq: title: 'FAQ' tagging_rules_definition_title: 'Was bedeuten die "Tagging-Regeln"?' @@ -172,6 +181,15 @@ config: and: 'Eine Regel UND eine andere' matches: 'Testet, ob eine Variable auf eine Suche zutrifft (Groß- und Kleinschreibung wird nicht berücksichtigt).
Beispiel: title matches "Fußball"' notmatches: 'Testet, ob ein Titel nicht auf eine Suche zutrifft (Groß- und Kleinschreibung wird nicht berücksichtigt).
Beispiel: title notmatches "Fußball"' + otp: + # page_title: Two-factor authentication + # app: + # two_factor_code_description_1: You just enabled the OTP two factor authentication, open your OTP app and use that code to get a one time password. It'll disapear after a page reload. + # two_factor_code_description_2: 'You can scan that QR Code with your app:' + # two_factor_code_description_3: 'Also, save these backup codes in a safe place, you can use them in case you lose access to your OTP app:' + # two_factor_code_description_4: 'Test an OTP code from your configured app:' + # cancel: Cancel + # enable: Enable entry: default_title: 'Titel des Eintrags' @@ -593,6 +611,9 @@ flashes: tags_reset: Tags zurücksetzen entries_reset: Einträge zurücksetzen archived_reset: Archiverte Einträge zurücksetzen + # otp_enabled: Two-factor authentication enabled + # tagging_rules_imported: Tagging rules imported + # tagging_rules_not_imported: Error while importing tagging rules entry: notice: entry_already_saved: 'Eintrag bereits am %date% gespeichert' diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml index 2f310246..a7c32f11 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.en.yml @@ -140,6 +140,15 @@ config: edit_rule_label: 'edit' rule_label: 'Rule' tags_label: 'Tags' + card: + new_tagging_rule: Create a tagging rule + import_tagging_rules: Import tagging rules + import_tagging_rules_detail: You have to select the JSON file you previously exported. + export_tagging_rules: Export tagging rules + export_tagging_rules_detail: This will download a JSON file that you can use to import tagging rules elsewhere or to backup them. + file_label: JSON file + import_submit: Import + export: Export faq: title: 'FAQ' tagging_rules_definition_title: 'What does « tagging rules » mean?' @@ -603,6 +612,8 @@ flashes: entries_reset: Entries reset archived_reset: Archived entries deleted otp_enabled: Two-factor authentication enabled + tagging_rules_imported: Tagging rules imported + tagging_rules_not_imported: Error while importing tagging rules entry: notice: entry_already_saved: 'Entry already saved on %date%' diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml index c194041a..093c5857 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.es.yml @@ -140,6 +140,15 @@ config: edit_rule_label: 'editar' rule_label: 'Regla' tags_label: 'Etiquetas' + # card: + # new_tagging_rule: Create a tagging rule + # import_tagging_rules: Import tagging rules + # import_tagging_rules_detail: You have to select the JSON file you previously exported. + # export_tagging_rules: Export tagging rules + # export_tagging_rules_detail: This will download a JSON file that you can use to import tagging rules elsewhere or to backup them. + # file_label: JSON file + # import_submit: Import + # export: Export faq: title: 'Preguntas frecuentes' tagging_rules_definition_title: '¿Qué significa « reglas de etiquetado automático »?' @@ -602,6 +611,9 @@ flashes: tags_reset: Etiquetas reiniciadas entries_reset: Artículos reiniciados # archived_reset: Archived entries deleted + # otp_enabled: Two-factor authentication enabled + # tagging_rules_imported: Tagging rules imported + # tagging_rules_not_imported: Error while importing tagging rules entry: notice: entry_already_saved: 'Artículo ya guardado el %fecha%' diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml index 9aef7dde..00caa0ac 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fa.yml @@ -140,6 +140,15 @@ config: # edit_rule_label: 'edit' rule_label: 'قانون' tags_label: 'برچسب‌ها' + # card: + # new_tagging_rule: Create a tagging rule + # import_tagging_rules: Import tagging rules + # import_tagging_rules_detail: You have to select the JSON file you previously exported. + # export_tagging_rules: Export tagging rules + # export_tagging_rules_detail: This will download a JSON file that you can use to import tagging rules elsewhere or to backup them. + # file_label: JSON file + # import_submit: Import + # export: Export faq: title: 'پرسش‌های متداول' tagging_rules_definition_title: 'برچسب‌گذاری خودکار یعنی چه؟' @@ -602,6 +611,9 @@ flashes: # tags_reset: Tags reset # entries_reset: Entries reset # archived_reset: Archived entries deleted + # otp_enabled: Two-factor authentication enabled + # tagging_rules_imported: Tagging rules imported + # tagging_rules_not_imported: Error while importing tagging rules entry: notice: entry_already_saved: 'این مقاله در تاریخ %date% ذخیره شده بود' diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml index 9848ed9a..ca66acde 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.fr.yml @@ -140,6 +140,15 @@ config: edit_rule_label: "éditer" rule_label: "Règle" tags_label: "Tags" + card: + new_tagging_rule: Créer une règle + import_tagging_rules: Importer des règles + import_tagging_rules_detail: Vous devez sélectionné un fichier JSON que vous avez précédemment exporté. + export_tagging_rules: Exporter les règles + export_tagging_rules_detail: Un fichier JSON sera téléchargé et vous pourrez l'utiliser pour ré-importer les règles ou comme sauvegarde. + file_label: Fichier JSON + import_submit: Importer + export: Export faq: title: "FAQ" tagging_rules_definition_title: "Que signifient les règles de tag automatiques ?" @@ -604,6 +613,8 @@ flashes: entries_reset: "Articles supprimés" archived_reset: "Articles archivés supprimés" otp_enabled: "Authentification à double-facteur activée" + tagging_rules_imported: Règles bien importées + tagging_rules_not_imported: Impossible d'importer les règles entry: notice: entry_already_saved: "Article déjà sauvegardé le %date%" diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml index efbf062b..85720ef8 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.it.yml @@ -105,6 +105,7 @@ config: # login_label: 'Login (can not be changed)' name_label: 'Nome' email_label: 'E-mail' + two_factor: # emailTwoFactor_label: 'Using email (receive a code by email)' # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' # table_method: Method @@ -139,6 +140,15 @@ config: edit_rule_label: 'modifica' rule_label: 'Regola' tags_label: 'Etichetta' + # card: + # new_tagging_rule: Create a tagging rule + # import_tagging_rules: Import tagging rules + # import_tagging_rules_detail: You have to select the JSON file you previously exported. + # export_tagging_rules: Export tagging rules + # export_tagging_rules_detail: This will download a JSON file that you can use to import tagging rules elsewhere or to backup them. + # file_label: JSON file + # import_submit: Import + # export: Export faq: title: 'FAQ' tagging_rules_definition_title: 'Cosa significa « regole di etichettatura » ?' @@ -601,6 +611,9 @@ flashes: tags_reset: Reset etichette entries_reset: Reset articoli # archived_reset: Archived entries deleted + # otp_enabled: Two-factor authentication enabled + # tagging_rules_imported: Tagging rules imported + # tagging_rules_not_imported: Error while importing tagging rules entry: notice: entry_already_saved: 'Contenuto già salvato in data %date%' diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml index 86ce4644..18d1173b 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.oc.yml @@ -105,6 +105,7 @@ config: # login_label: 'Login (can not be changed)' name_label: 'Nom' email_label: 'Adreça de corrièl' + two_factor: # emailTwoFactor_label: 'Using email (receive a code by email)' # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' # table_method: Method @@ -139,6 +140,15 @@ config: edit_rule_label: 'modificar' rule_label: 'Règla' tags_label: 'Etiquetas' + # card: + # new_tagging_rule: Create a tagging rule + # import_tagging_rules: Import tagging rules + # import_tagging_rules_detail: You have to select the JSON file you previously exported. + # export_tagging_rules: Export tagging rules + # export_tagging_rules_detail: This will download a JSON file that you can use to import tagging rules elsewhere or to backup them. + # file_label: JSON file + # import_submit: Import + # export: Export faq: title: 'FAQ' tagging_rules_definition_title: "Qué significa las règlas d'etiquetas automaticas ?" @@ -601,6 +611,9 @@ flashes: tags_reset: Etiquetas levadas entries_reset: Articles levats archived_reset: Articles archivat suprimits + # otp_enabled: Two-factor authentication enabled + # tagging_rules_imported: Tagging rules imported + # tagging_rules_not_imported: Error while importing tagging rules entry: notice: entry_already_saved: 'Article ja salvagardat lo %date%' diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml index 9ebe0236..6528a562 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pl.yml @@ -105,6 +105,7 @@ config: # login_label: 'Login (can not be changed)' name_label: 'Nazwa' email_label: 'Adres email' + two_factor: # emailTwoFactor_label: 'Using email (receive a code by email)' # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' # table_method: Method @@ -139,6 +140,15 @@ config: edit_rule_label: 'edytuj' rule_label: 'Reguła' tags_label: 'Tagi' + # card: + # new_tagging_rule: Create a tagging rule + # import_tagging_rules: Import tagging rules + # import_tagging_rules_detail: You have to select the JSON file you previously exported. + # export_tagging_rules: Export tagging rules + # export_tagging_rules_detail: This will download a JSON file that you can use to import tagging rules elsewhere or to backup them. + # file_label: JSON file + # import_submit: Import + # export: Export faq: title: 'FAQ' tagging_rules_definition_title: 'Co oznaczają « reguły tagowania » ?' @@ -601,6 +611,9 @@ flashes: tags_reset: Zresetuj tagi entries_reset: Zresetuj wpisy archived_reset: Zarchiwizowane wpisy usunięte + # otp_enabled: Two-factor authentication enabled + # tagging_rules_imported: Tagging rules imported + # tagging_rules_not_imported: Error while importing tagging rules entry: notice: entry_already_saved: 'Wpis już został dodany %date%' diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml index d310e016..3f1c7a68 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.pt.yml @@ -105,6 +105,7 @@ config: # login_label: 'Login (can not be changed)' name_label: 'Nome' email_label: 'E-mail' + two_factor: # emailTwoFactor_label: 'Using email (receive a code by email)' # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' # table_method: Method @@ -139,6 +140,15 @@ config: edit_rule_label: 'editar' rule_label: 'Regras' tags_label: 'Tags' + # card: + # new_tagging_rule: Create a tagging rule + # import_tagging_rules: Import tagging rules + # import_tagging_rules_detail: You have to select the JSON file you previously exported. + # export_tagging_rules: Export tagging rules + # export_tagging_rules_detail: This will download a JSON file that you can use to import tagging rules elsewhere or to backup them. + # file_label: JSON file + # import_submit: Import + # export: Export faq: title: 'FAQ' tagging_rules_definition_title: 'O que as « regras de tags » significam?' @@ -601,6 +611,9 @@ flashes: # tags_reset: Tags reset # entries_reset: Entries reset # archived_reset: Archived entries deleted + # otp_enabled: Two-factor authentication enabled + # tagging_rules_imported: Tagging rules imported + # tagging_rules_not_imported: Error while importing tagging rules entry: notice: entry_already_saved: 'Entrada já foi salva em %date%' diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml index c11ff0b8..d82e9377 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.ro.yml @@ -105,6 +105,7 @@ config: # login_label: 'Login (can not be changed)' name_label: 'Nume' email_label: 'E-mail' + two_factor: # emailTwoFactor_label: 'Using email (receive a code by email)' # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' # table_method: Method @@ -139,6 +140,15 @@ config: # edit_rule_label: 'edit' # rule_label: 'Rule' # tags_label: 'Tags' + # card: + # new_tagging_rule: Create a tagging rule + # import_tagging_rules: Import tagging rules + # import_tagging_rules_detail: You have to select the JSON file you previously exported. + # export_tagging_rules: Export tagging rules + # export_tagging_rules_detail: This will download a JSON file that you can use to import tagging rules elsewhere or to backup them. + # file_label: JSON file + # import_submit: Import + # export: Export # faq: # title: 'FAQ' # tagging_rules_definition_title: 'What does « tagging rules » mean?' @@ -429,9 +439,9 @@ tag: rename: # placeholder: 'You can update tag name.' -# export: -# footer_template: '

Produced by wallabag with %method%

Please open an issue if you have trouble with the display of this E-Book on your device.

' -# unknown: 'Unknown' +export: + # footer_template: '

Produced by wallabag with %method%

Please open an issue if you have trouble with the display of this E-Book on your device.

' + # unknown: 'Unknown' import: # page_title: 'Import' @@ -601,6 +611,9 @@ flashes: # tags_reset: Tags reset # entries_reset: Entries reset # archived_reset: Archived entries deleted + # otp_enabled: Two-factor authentication enabled + # tagging_rules_imported: Tagging rules imported + # tagging_rules_not_imported: Error while importing tagging rules entry: notice: # entry_already_saved: 'Entry already saved on %date%' diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.ru.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.ru.yml index 9fe75369..23d31333 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.ru.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.ru.yml @@ -80,6 +80,7 @@ config: redirect_current_page: 'На текущую страницу' pocket_consumer_key_label: "Ключ от Pocket для импорта контента" android_configuration: "Настройте Ваше Android приложение" + # android_instruction: "Touch here to prefill your Android application" help_theme: "wallabag настраиваемый, здесь Вы можете выбрать тему." help_items_per_page: "Вы можете выбрать количество отображаемых записей на странице." help_reading_speed: "wallabag посчитает сколько времени занимает чтение каждой записи. Вы можете определить здесь, как быстро вы читаете. wallabag пересчитает время чтения для каждой записи." @@ -97,12 +98,14 @@ config: unread: 'непрочитанные' starred: 'помеченные' archive: 'архивные' + # all: 'All' feed_limit: 'Количество записей в фиде' form_user: # two_factor_description: "Enabling two factor authentication means you'll receive an email with a code OR need to use an OTP app (like Google Authenticator, Authy or FreeOTP) to get a one time code on every new untrusted connection. You can't choose both option." # login_label: 'Login (can not be changed)' name_label: 'Имя' email_label: 'Email' + two_factor: # emailTwoFactor_label: 'Using email (receive a code by email)' # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' # table_method: Method @@ -123,6 +126,7 @@ config: annotations: "Удалить все аннотации" tags: "Удалить все теги" entries: "Удалить все записи" + # archived: Remove ALL archived entries confirm: "Вы уверены? (Данные будут БЕЗВОЗВРАТНО удалены, эти действия необратимы)" form_password: description: "Здесь Вы можете поменять своя пароль. Ваш пароль должен быть длиннее 8 символов." @@ -136,6 +140,15 @@ config: edit_rule_label: 'изменить' rule_label: 'Правило' tags_label: 'теги' + # card: + # new_tagging_rule: Create a tagging rule + # import_tagging_rules: Import tagging rules + # import_tagging_rules_detail: You have to select the JSON file you previously exported. + # export_tagging_rules: Export tagging rules + # export_tagging_rules_detail: This will download a JSON file that you can use to import tagging rules elsewhere or to backup them. + # file_label: JSON file + # import_submit: Import + # export: Export faq: title: 'FAQ' tagging_rules_definition_title: 'Что значит "правило тегирования"?' @@ -167,6 +180,7 @@ config: or: 'Одно правило ИЛИ другое' and: 'Одно правило И другое' matches: 'Тесты, в которых тема соответствует поиску (без учета регистра). Пример: title matches "футбол" ' + # notmatches: 'Tests that a subject doesn''t match match a search (case-insensitive).
Example: title notmatches "football"' otp: # page_title: Two-factor authentication # app: @@ -187,6 +201,7 @@ entry: filtered_tags: 'Отфильтрованные по тегу:' filtered_search: 'Отфильтрованные по поиску:' untagged: 'Записи без тегов' + # all: 'All entries' list: number_on_the_page: '{0} Записей не обнаружено.|{1} Одна запись.|]1,Inf[ Найдено %count% записей.' reading_time: 'расчетное время чтения' @@ -208,6 +223,8 @@ entry: unread_label: 'Непрочитанная' preview_picture_label: 'Есть картинка предварительного просмотра' preview_picture_help: 'Картинка предварительного просмотра' + # is_public_label: 'Has a public link' + # is_public_help: 'Public link' language_label: 'Язык' http_status_label: 'статус HTTP' reading_time: @@ -246,6 +263,8 @@ entry: original_article: 'оригинал' annotations_on_the_entry: '{0} Нет аннотации|{1} Одна аннотация|]1,Inf[ %count% аннотаций' created_at: 'Дата создания' + # published_at: 'Publication date' + # published_by: 'Published by' # provided_by: 'Provided by' new: page_title: 'Сохранить новую запись' @@ -259,10 +278,12 @@ entry: title_label: 'Название' url_label: 'Ссылка' # origin_url_label: 'Origin url (from where you found that entry)' - is_public_label: 'Публичная' save_label: 'Сохранить' public: shared_by_wallabag: "Запись была опубликована wallabag" + confirm: + # delete: "Are you sure you want to remove that article?" + # delete_tag: "Are you sure you want to remove that tag from that article?" metadata: # reading_time: "Estimated reading time" # reading_time_minutes_short: "%readingTime% min" @@ -418,9 +439,9 @@ tag: rename: # placeholder: 'You can update tag name.' -# export: -# footer_template: '

Produced by wallabag with %method%

Please open an issue if you have trouble with the display of this E-Book on your device.

' -# unknown: 'Unknown' +export: + # footer_template: '

Produced by wallabag with %method%

Please open an issue if you have trouble with the display of this E-Book on your device.

' + # unknown: 'Unknown' import: page_title: 'Импорт' @@ -548,6 +569,28 @@ user: delete: "Удалить" delete_confirm: "Вы уверены?" back_to_list: "Назад к списку" + search: + # placeholder: Filter by login or email + +site_credential: + # page_title: Site credentials management + # new_site_credential: Create a credential + # edit_site_credential: Edit an existing credential + # description: "Here you can manage all credentials for sites which required them (create, edit and delete), like a paywall, an authentication, etc." + # list: + # actions: Actions + # edit_action: Edit + # yes: Yes + # no: No + # create_new_one: Create a new credential + # form: + # username_label: 'Login' + # host_label: 'Host (subdomain.example.org, .example.org, etc.)' + # password_label: 'Password' + # save: Save + # delete: Delete + # delete_confirm: Are you sure? + # back_to_list: Back to list error: page_title: "Произошла ошибка" @@ -567,6 +610,10 @@ flashes: annotations_reset: "Аннотации сброшены" tags_reset: "Теги сброшены" entries_reset: "Записи сброшены" + # archived_reset: Archived entries deleted + # otp_enabled: Two-factor authentication enabled + # tagging_rules_imported: Tagging rules imported + # tagging_rules_not_imported: Error while importing tagging rules entry: notice: entry_already_saved: 'Запись была сохранена ранее %date%' @@ -603,3 +650,8 @@ flashes: added: 'Пользователь "%username%" добавлен' updated: 'Пользователь "%username%" обновлен' deleted: 'Пользователь "%username%" удален' + site_credential: + notice: + # added: 'Site credential for "%host%" added' + # updated: 'Site credential for "%host%" updated' + # deleted: 'Site credential for "%host%" deleted' diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.th.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.th.yml index 672dcbf0..d7f47904 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.th.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.th.yml @@ -105,6 +105,7 @@ config: # login_label: 'Login (can not be changed)' name_label: 'ชื่อ' email_label: 'อีเมล' + two_factor: # emailTwoFactor_label: 'Using email (receive a code by email)' # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' # table_method: Method @@ -139,6 +140,15 @@ config: edit_rule_label: 'ปรับแก้' rule_label: 'ข้อบังคับ' tags_label: 'แท็ก' + # card: + # new_tagging_rule: Create a tagging rule + # import_tagging_rules: Import tagging rules + # import_tagging_rules_detail: You have to select the JSON file you previously exported. + # export_tagging_rules: Export tagging rules + # export_tagging_rules_detail: This will download a JSON file that you can use to import tagging rules elsewhere or to backup them. + # file_label: JSON file + # import_submit: Import + # export: Export faq: title: 'FAQ' tagging_rules_definition_title: 'ข้อบังคับการแท็กคืออะไร?' @@ -255,6 +265,7 @@ entry: created_at: 'วันที่สร้าง' published_at: 'วันที่ประกาศ' published_by: 'ประกาศโดย' + # provided_by: 'Provided by' new: page_title: 'บันทึกรายการใหม่' placeholder: 'http://website.com' @@ -266,6 +277,7 @@ entry: page_title: 'แก้ไขรายการ' title_label: 'หัวข้อ' url_label: 'Url' + # origin_url_label: 'Origin url (from where you found that entry)' save_label: 'บันทึก' public: shared_by_wallabag: "บทความนี้จะมีการแชร์โดย %username% กับ wallabag" @@ -599,6 +611,9 @@ flashes: tags_reset: รีเซ็ตแท็ก entries_reset: รีเซ็ตรายการ archived_reset: การลบเอกสารของรายการ + # otp_enabled: Two-factor authentication enabled + # tagging_rules_imported: Tagging rules imported + # tagging_rules_not_imported: Error while importing tagging rules entry: notice: entry_already_saved: 'รายการพร้อมบันทึกที่ %date%' diff --git a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml index c2ad854d..a444cadb 100644 --- a/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml +++ b/src/Wallabag/CoreBundle/Resources/translations/messages.tr.yml @@ -105,6 +105,7 @@ config: # login_label: 'Login (can not be changed)' name_label: 'İsim' email_label: 'E-posta' + two_factor: # emailTwoFactor_label: 'Using email (receive a code by email)' # googleTwoFactor_label: 'Using an OTP app (open the app, like Google Authenticator, Authy or FreeOTP, to get a one time code)' # table_method: Method @@ -139,6 +140,15 @@ config: # edit_rule_label: 'edit' rule_label: 'Kural' tags_label: 'Etiketler' + # card: + # new_tagging_rule: Create a tagging rule + # import_tagging_rules: Import tagging rules + # import_tagging_rules_detail: You have to select the JSON file you previously exported. + # export_tagging_rules: Export tagging rules + # export_tagging_rules_detail: This will download a JSON file that you can use to import tagging rules elsewhere or to backup them. + # file_label: JSON file + # import_submit: Import + # export: Export faq: title: 'S.S.S.' tagging_rules_definition_title: '« etiketleme kuralları » ne anlama geliyor?' @@ -213,6 +223,8 @@ entry: unread_label: 'Okunmayan' preview_picture_label: 'Resim önizlemesi varsa' preview_picture_help: 'Resim önizlemesi' + # is_public_label: 'Has a public link' + # is_public_help: 'Public link' language_label: 'Dil' # http_status_label: 'HTTP status' reading_time: @@ -427,9 +439,9 @@ tag: rename: # placeholder: 'You can update tag name.' -# export: -# footer_template: '

Produced by wallabag with %method%

Please open an issue if you have trouble with the display of this E-Book on your device.

' -# unknown: 'Unknown' +export: + # footer_template: '

Produced by wallabag with %method%

Please open an issue if you have trouble with the display of this E-Book on your device.

' + # unknown: 'Unknown' import: page_title: 'İçe Aktar' @@ -560,6 +572,26 @@ user: search: # placeholder: Filter by username or email +site_credential: + # page_title: Site credentials management + # new_site_credential: Create a credential + # edit_site_credential: Edit an existing credential + # description: "Here you can manage all credentials for sites which required them (create, edit and delete), like a paywall, an authentication, etc." + # list: + # actions: Actions + # edit_action: Edit + # yes: Yes + # no: No + # create_new_one: Create a new credential + # form: + # username_label: 'Login' + # host_label: 'Host (subdomain.example.org, .example.org, etc.)' + # password_label: 'Password' + # save: Save + # delete: Delete + # delete_confirm: Are you sure? + # back_to_list: Back to list + error: # page_title: An error occurred @@ -571,13 +603,17 @@ flashes: password_not_updated_demo: "In demonstration mode, you can't change password for this user." user_updated: 'Bilgiler güncellendi' feed_updated: 'RSS bilgiler güncellendi' - tagging_rules_updated: 'Tagging rules updated' - tagging_rules_deleted: 'Tagging rule deleted' - feed_token_updated: 'RSS token updated' + # 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 # archived_reset: Archived entries deleted + # otp_enabled: Two-factor authentication enabled + # tagging_rules_imported: Tagging rules imported + # tagging_rules_not_imported: Error while importing tagging rules entry: notice: entry_already_saved: 'Entry already saved on %date%' diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig index eba4539f..f719bea2 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/baggy/Config/index.html.twig @@ -291,6 +291,34 @@ {{ form_rest(form.new_tagging_rule) }} + +
+

{{ 'config.form_rules.card.import_tagging_rules'|trans }}

+

{{ 'config.form_rules.card.import_tagging_rules_detail'|trans }}

+
+ + {{ form_start(form.import_tagging_rule) }} + {{ form_errors(form.import_tagging_rule) }} + +
+
+ {{ form_label(form.import_tagging_rule.file) }} + {{ form_errors(form.import_tagging_rule.file) }} + {{ form_widget(form.import_tagging_rule.file) }} +
+
+ + {{ form_rest(form.import_tagging_rule) }} + + + {% if app.user.config.taggingRules is not empty %} +
+

{{ 'config.form_rules.card.export_tagging_rules'|trans }}

+

{{ 'config.form_rules.card.export_tagging_rules_detail'|trans }}

+

{{ 'config.form_rules.export'|trans }}

+
+ {% endif %} +

{{ 'config.form_rules.faq.title'|trans }}

diff --git a/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig b/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig index 990546e8..d8e9694d 100644 --- a/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig +++ b/src/Wallabag/CoreBundle/Resources/views/themes/material/Config/index.html.twig @@ -307,28 +307,77 @@
{% endif %} - {{ form_start(form.new_tagging_rule) }} - {{ form_errors(form.new_tagging_rule) }} - -
-
- {{ form_label(form.new_tagging_rule.rule) }} - {{ form_errors(form.new_tagging_rule.rule) }} - {{ form_widget(form.new_tagging_rule.rule) }} +
    +
  • +
    +
    + {{ 'config.form_rules.card.new_tagging_rule'|trans }} + + {{ form_start(form.new_tagging_rule) }} + {{ form_errors(form.new_tagging_rule) }} + +
    +
    + {{ form_label(form.new_tagging_rule.rule) }} + {{ form_errors(form.new_tagging_rule.rule) }} + {{ form_widget(form.new_tagging_rule.rule) }} +
    +
    + +
    +
    + {{ form_label(form.new_tagging_rule.tags) }} + {{ form_errors(form.new_tagging_rule.tags) }} + {{ form_widget(form.new_tagging_rule.tags) }} +
    +
    + + {{ form_widget(form.new_tagging_rule.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }} + {{ form_rest(form.new_tagging_rule) }} + +
    -
- -
-
- {{ form_label(form.new_tagging_rule.tags) }} - {{ form_errors(form.new_tagging_rule.tags) }} - {{ form_widget(form.new_tagging_rule.tags) }} + +
  • +
    +
    + {{ 'config.form_rules.card.import_tagging_rules'|trans }} +

    {{ 'config.form_rules.card.import_tagging_rules_detail'|trans }}

    + {{ form_start(form.import_tagging_rule) }} + {{ form_errors(form.import_tagging_rule) }} +
    +
    + {{ form_errors(form.import_tagging_rule.file) }} +
    + {{ form.import_tagging_rule.file.vars.label|trans }} + {{ form_widget(form.import_tagging_rule.file) }} +
    +
    + +
    +
    +
    + + {{ form_widget(form.import_tagging_rule.import, { 'attr': {'class': 'btn waves-effect waves-light'} }) }} + + {{ form_rest(form.import_tagging_rule) }} + +
    -
  • - - {{ form_widget(form.new_tagging_rule.save, {'attr': {'class': 'btn waves-effect waves-light'}}) }} - {{ form_rest(form.new_tagging_rule) }} - + + {% if app.user.config.taggingRules is not empty %} +
  • +
    +
    + {{ 'config.form_rules.card.export_tagging_rules'|trans }} +

    {{ 'config.form_rules.card.export_tagging_rules_detail'|trans }}

    +
    +

    {{ 'config.form_rules.export'|trans }}

    +
    +
    +
  • + {% endif %} +
    diff --git a/tests/Wallabag/ApiBundle/Controller/TaggingRuleRestControllerTest.php b/tests/Wallabag/ApiBundle/Controller/TaggingRuleRestControllerTest.php new file mode 100644 index 00000000..b6477256 --- /dev/null +++ b/tests/Wallabag/ApiBundle/Controller/TaggingRuleRestControllerTest.php @@ -0,0 +1,15 @@ +client->request('GET', '/api/taggingrule/export'); + $this->assertSame(200, $this->client->getResponse()->getStatusCode()); + $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type')); + } +} diff --git a/tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php b/tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php index b9e0bed2..d8b5f383 100644 --- a/tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php +++ b/tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php @@ -2,6 +2,7 @@ namespace Tests\Wallabag\CoreBundle\Controller; +use Symfony\Component\HttpFoundation\File\UploadedFile; use Tests\Wallabag\CoreBundle\WallabagCoreTestCase; use Wallabag\AnnotationBundle\Entity\Annotation; use Wallabag\CoreBundle\Entity\Config; @@ -1097,4 +1098,67 @@ class ConfigControllerTest extends WallabagCoreTestCase $this->assertFalse($user->isGoogleTwoFactor()); $this->assertEmpty($user->getBackupCodes()); } + + public function testExportTaggingRule() + { + $this->logInAs('admin'); + $client = $this->getClient(); + + ob_start(); + $crawler = $client->request('GET', '/tagging-rule/export'); + ob_end_clean(); + + $this->assertSame(200, $client->getResponse()->getStatusCode()); + + $headers = $client->getResponse()->headers; + $this->assertSame('application/json', $headers->get('content-type')); + $this->assertSame('attachment; filename="tagging_rules_admin.json"', $headers->get('content-disposition')); + $this->assertSame('UTF-8', $headers->get('content-transfer-encoding')); + + $content = json_decode($client->getResponse()->getContent(), true); + + $this->assertCount(4, $content); + $this->assertSame('content matches "spurs"', $content[0]['rule']); + $this->assertSame('sport', $content[0]['tags'][0]); + } + + public function testImportTagginfRuleBadFile() + { + $this->logInAs('admin'); + $client = $this->getClient(); + + $crawler = $client->request('GET', '/config'); + $form = $crawler->filter('form[name=upload_tagging_rule_file] > button[type=submit]')->form(); + + $data = [ + 'upload_tagging_rule_file[file]' => '', + ]; + + $client->submit($form, $data); + + $this->assertSame(302, $client->getResponse()->getStatusCode()); + } + + public function testImportTagginfRuleFile() + { + $this->logInAs('admin'); + $client = $this->getClient(); + + $crawler = $client->request('GET', '/config'); + $form = $crawler->filter('form[name=upload_tagging_rule_file] > button[type=submit]')->form(); + + $file = new UploadedFile(__DIR__ . '/../fixtures/tagging_rules_admin.json', 'tagging_rules_admin.json'); + + $data = [ + 'upload_tagging_rule_file[file]' => $file, + ]; + + $client->submit($form, $data); + $this->assertSame(302, $client->getResponse()->getStatusCode()); + + $user = $client->getContainer()->get('fos_user.user_manager.test')->findUserBy(['username' => 'admin']); + $taggingRules = $user->getConfig()->getTaggingRules()->toArray(); + $this->assertCount(5, $taggingRules); + $this->assertSame('title matches "football"', $taggingRules[4]->getRule()); + } } diff --git a/tests/Wallabag/CoreBundle/fixtures/tagging_rules_admin.json b/tests/Wallabag/CoreBundle/fixtures/tagging_rules_admin.json new file mode 100644 index 00000000..a54824e2 --- /dev/null +++ b/tests/Wallabag/CoreBundle/fixtures/tagging_rules_admin.json @@ -0,0 +1,4 @@ +[{ + "rule": "title matches \"football\"", + "tags": ["football"] +}]