private function getTable($tableName)
{
- return $this->container->getParameter('database_table_prefix') . $tableName;
+ return $this->container->getParameter('database_table_prefix').$tableName;
}
/**
*/
public function up(Schema $schema)
{
- if ($this->connection->getDatabasePlatform()->getName() == 'postgresql') {
- $this->addSql('ALTER TABLE "'.$this->getTable('entry').'" ADD uuid UUID DEFAULT NULL');
- } else {
- $this->addSql('ALTER TABLE "'.$this->getTable('entry').'" ADD uuid LONGTEXT DEFAULT NULL');
- }
+ $entryTable = $schema->getTable($this->getTable('entry'));
- $this->addSql("INSERT INTO \"".$this->getTable('craue_config_setting')."\" (name, value, section) VALUES ('share_public', '1', 'entry')");
+ $this->skipIf($entryTable->hasColumn('uuid'), 'It seems that you already played this migration.');
+
+ $entryTable->addColumn('uuid', 'guid', [
+ 'notnull' => false,
+ ]);
+ $this->addSql('INSERT INTO '.$this->getTable('craue_config_setting')." (name, value, section) VALUES ('share_public', '1', 'entry')");
}
/**
*/
public function down(Schema $schema)
{
- $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'sqlite', 'This down migration can\'t be executed on SQLite databases, because SQLite don\'t support DROP COLUMN.');
+ $entryTable = $schema->getTable($this->getTable('entry'));
+ $entryTable->dropColumn('uuid');
- $this->addSql('ALTER TABLE "'.$this->getTable('entry').'" DROP uuid');
- $this->addSql("DELETE FROM \"".$this->getTable('craue_config_setting')."\" WHERE name = 'share_public'");
+ $this->addSql('DELETE FROM '.$this->getTable('craue_config_setting')." WHERE name = 'share_public'");
}
}
private function getTable($tableName)
{
- return $this->container->getParameter('database_table_prefix') . $tableName;
+ return $this->container->getParameter('database_table_prefix').$tableName;
}
/**
*/
public function up(Schema $schema)
{
- switch ($this->connection->getDatabasePlatform()->getName()) {
- case 'sqlite':
- $this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD name longtext DEFAULT NULL');
- break;
-
- case 'mysql':
- $this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD name longtext COLLATE \'utf8_unicode_ci\' DEFAULT NULL');
- break;
-
- case 'postgresql':
- $this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD name text DEFAULT NULL');
- }
+ $clientsTable = $schema->getTable($this->getTable('oauth2_clients'));
+ $this->skipIf($clientsTable->hasColumn('name'), 'It seems that you already played this migration.');
+
+ $clientsTable->addColumn('name', 'blob');
}
/**
*/
public function down(Schema $schema)
{
- $this->abortIf($this->connection->getDatabasePlatform()->getName() == 'sqlite', 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
-
- $this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' DROP COLUMN name');
+ $clientsTable = $schema->getTable($this->getTable('oauth2_clients'));
+ $clientsTable->dropColumn('name');
}
}
private function getTable($tableName)
{
- return $this->container->getParameter('database_table_prefix') . $tableName;
+ return $this->container->getParameter('database_table_prefix').$tableName;
}
/**
*/
public function up(Schema $schema)
{
- $this->addSql('INSERT INTO "'.$this->getTable('craue_config_setting').'" (name, value, section) VALUES (\'import_with_redis\', \'0\', \'import\')');
- $this->addSql('INSERT INTO "'.$this->getTable('craue_config_setting').'" (name, value, section) VALUES (\'import_with_rabbitmq\', \'0\', \'import\')');
+ $this->addSql('INSERT INTO '.$this->getTable('craue_config_setting')." (name, value, section) VALUES ('import_with_redis', 0, 'import')");
+ $this->addSql('INSERT INTO '.$this->getTable('craue_config_setting')." (name, value, section) VALUES ('import_with_rabbitmq', 0, 'import')");
}
/**
*/
public function down(Schema $schema)
{
+ $this->addSql('DELETE FROM '.$this->getTable('craue_config_setting')." WHERE name = 'import_with_redis';");
+ $this->addSql('DELETE FROM '.$this->getTable('craue_config_setting')." WHERE name = 'import_with_rabbitmq';");
}
}
private function getTable($tableName)
{
- return $this->container->getParameter('database_table_prefix') . $tableName;
+ return $this->container->getParameter('database_table_prefix').$tableName;
}
/**
*/
public function up(Schema $schema)
{
- $this->addSql('ALTER TABLE "'.$this->getTable('config').'" ADD pocket_consumer_key VARCHAR(255) DEFAULT NULL');
- $this->addSql("DELETE FROM \"".$this->getTable('craue_config_setting')."\" WHERE name = 'pocket_consumer_key';");
+ $configTable = $schema->getTable($this->getTable('config'));
+
+ $this->skipIf($configTable->hasColumn('pocket_consumer_key'), 'It seems that you already played this migration.');
+
+ $configTable->addColumn('pocket_consumer_key', 'string');
+ $this->addSql('DELETE FROM '.$this->getTable('craue_config_setting')." WHERE name = 'pocket_consumer_key';");
}
/**
*/
public function down(Schema $schema)
{
- $this->abortIf($this->connection->getDatabasePlatform()->getName() == 'sqlite', 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
-
- $this->addSql('ALTER TABLE "'.$this->getTable('config').'" DROP pocket_consumer_key');
- $this->addSql("INSERT INTO \"".$this->getTable('craue_config_setting')."\" (name, value, section) VALUES ('pocket_consumer_key', NULL, 'import')");
+ $configTable = $schema->getTable($this->getTable('config'));
+ $configTable->dropColumn('pocket_consumer_key');
+ $this->addSql('INSERT INTO '.$this->getTable('craue_config_setting')." (name, value, section) VALUES ('pocket_consumer_key', NULL, 'import')");
}
}
private function getTable($tableName)
{
- return $this->container->getParameter('database_table_prefix') . $tableName;
+ return $this->container->getParameter('database_table_prefix').$tableName;
}
/**
private function getTable($tableName)
{
- return $this->container->getParameter('database_table_prefix') . $tableName;
+ return $this->container->getParameter('database_table_prefix').$tableName;
}
/**
$this->addSql('ALTER TABLE '.$this->getTable('tag').' CHANGE `label` `label` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
$this->addSql('ALTER TABLE '.$this->getTable('user').' CHANGE `name` `name` longtext CHARACTER SET utf8 COLLATE utf8_unicode_ci;');
-
}
}
private function getTable($tableName)
{
- return $this->container->getParameter('database_table_prefix') . $tableName;
+ return $this->container->getParameter('database_table_prefix').$tableName;
}
/**
*/
public function up(Schema $schema)
{
- $this->skipIf($this->connection->getDatabasePlatform()->getName() == 'sqlite', 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
+ $clientsTable = $schema->getTable($this->getTable('oauth2_clients'));
- $this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD user_id INT(11) DEFAULT NULL');
- $this->addSql('ALTER TABLE '.$this->getTable('oauth2_clients').' ADD CONSTRAINT FK_clients_user_clients FOREIGN KEY (user_id) REFERENCES '.$this->getTable('user').' (id) ON DELETE CASCADE');
+ $this->skipIf($clientsTable->hasColumn('user_id'), 'It seems that you already played this migration.');
+
+ $clientsTable->addColumn('user_id', 'integer');
+
+ $clientsTable->addForeignKeyConstraint(
+ $this->getTable('user'),
+ ['user_id'],
+ ['id'],
+ ['onDelete' => 'CASCADE']
+ );
}
/**
*/
public function down(Schema $schema)
{
-
}
}
private function getTable($tableName)
{
- return $this->container->getParameter('database_table_prefix') . $tableName;
+ return $this->container->getParameter('database_table_prefix').$tableName;
}
/**
*/
public function up(Schema $schema)
{
- $this->addSql("INSERT INTO \"".$this->getTable('craue_config_setting')."\" (name, value, section) VALUES ('download_images_enabled', 0, 'misc')");
+ $this->addSql('INSERT INTO "'.$this->getTable('craue_config_setting')."\" (name, value, section) VALUES ('download_images_enabled', 0, 'misc')");
}
/**
*/
public function down(Schema $schema)
{
- $this->abortIf($this->connection->getDatabasePlatform()->getName() == 'sqlite', 'Migration can only be executed safely on \'mysql\' or \'postgresql\'.');
-
- $this->addSql("DELETE FROM \"".$this->getTable('craue_config_setting')."\" WHERE name = 'download_images_enabled';");
+ $this->addSql('DELETE FROM "'.$this->getTable('craue_config_setting')."\" WHERE name = 'download_images_enabled';");
}
}
*/
private $container;
+ private $indexName = 'IDX_entry_created_at';
+
public function setContainer(ContainerInterface $container = null)
{
$this->container = $container;
private function getTable($tableName)
{
- return $this->container->getParameter('database_table_prefix') . $tableName;
+ return $this->container->getParameter('database_table_prefix').$tableName;
}
/**
*/
public function up(Schema $schema)
{
- switch ($this->connection->getDatabasePlatform()->getName()) {
- case 'sqlite':
- $this->addSql('CREATE INDEX `created_at` ON `'.$this->getTable('entry').'` (`created_at` DESC)');
- break;
-
- case 'mysql':
- $this->addSql('ALTER TABLE '.$this->getTable('entry').' ADD INDEX created_at (created_at);');
- break;
-
- case 'postgresql':
- $this->addSql('CREATE INDEX created_at ON '.$this->getTable('entry').' (created_at DESC)');
- }
+ $entryTable = $schema->getTable($this->getTable('entry'));
+ $this->skipIf($entryTable->hasIndex($this->indexName), 'It seems that you already played this migration.');
+
+ $entryTable->addIndex(['created_at'], $this->indexName);
}
/**
*/
public function down(Schema $schema)
{
+ $entryTable = $schema->getTable($this->getTable('entry'));
+ $this->skipIf(false === $entryTable->hasIndex($this->indexName), 'It seems that you already played this migration.');
+ $entryTable->dropIndex($this->indexName);
}
}
private function getTable($tableName)
{
- return $this->container->getParameter('database_table_prefix') . $tableName;
+ return $this->container->getParameter('database_table_prefix').$tableName;
}
/**
*/
public function up(Schema $schema)
{
- $this->addSql('ALTER TABLE '.$this->getTable('config').' ADD action_mark_as_read INT DEFAULT 0');
+ $configTable = $schema->getTable($this->getTable('config'));
+
+ $this->skipIf($configTable->hasColumn('action_mark_as_read'), 'It seems that you already played this migration.');
+
+ $configTable->addColumn('action_mark_as_read', 'integer', [
+ 'default' => 0,
+ ]);
}
/**
*/
public function down(Schema $schema)
{
- $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'sqlite', 'This down migration can\'t be executed on SQLite databases, because SQLite don\'t support DROP COLUMN.');
-
- $this->addSql('ALTER TABLE '.$this->getTable('config').' DROP action_mark_as_read');
+ $configTable = $schema->getTable($this->getTable('config'));
+ $userTable->dropColumn('action_mark_as_read');
}
}
private function getTable($tableName)
{
- return $this->container->getParameter('database_table_prefix') . $tableName;
+ return $this->container->getParameter('database_table_prefix').$tableName;
}
/**
*/
public function up(Schema $schema)
{
- $this->addSql("INSERT INTO ".$this->getTable('craue_config_setting')." (name, value, section) VALUES ('share_unmark', 0, 'entry')");
- $this->addSql("INSERT INTO ".$this->getTable('craue_config_setting')." (name, value, section) VALUES ('unmark_url', 'https://unmark.it', 'entry')");
+ $this->addSql('INSERT INTO '.$this->getTable('craue_config_setting')." (name, value, section) VALUES ('share_unmark', 0, 'entry')");
+ $this->addSql('INSERT INTO '.$this->getTable('craue_config_setting')." (name, value, section) VALUES ('unmark_url', 'https://unmark.it', 'entry')");
}
/**
*/
public function down(Schema $schema)
{
- $this->addSql("DELETE FROM ".$this->getTable('craue_config_setting')." WHERE name = 'share_unmark';");
- $this->addSql("DELETE FROM ".$this->getTable('craue_config_setting')." WHERE name = 'unmark_url';");
+ $this->addSql('DELETE FROM '.$this->getTable('craue_config_setting')." WHERE name = 'share_unmark';");
+ $this->addSql('DELETE FROM '.$this->getTable('craue_config_setting')." WHERE name = 'unmark_url';");
}
}
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
- * Add http_status in `entry_table`
+ * Add http_status in `entry_table`.
*/
class Version20161118134328 extends AbstractMigration implements ContainerAwareInterface
{
private function getTable($tableName)
{
- return $this->container->getParameter('database_table_prefix') . $tableName;
+ return $this->container->getParameter('database_table_prefix').$tableName;
}
/**
*/
public function up(Schema $schema)
{
- $this->addSql('ALTER TABLE '.$this->getTable('entry').' ADD http_status VARCHAR(3) DEFAULT NULL');
+ $entryTable = $schema->getTable($this->getTable('entry'));
+
+ $this->skipIf($entryTable->hasColumn('http_status'), 'It seems that you already played this migration.');
+
+ $entryTable->addColumn('http_status', 'string', [
+ 'length' => 3,
+ 'notnull' => false,
+ ]);
}
/**
*/
public function down(Schema $schema)
{
- $this->abortIf($this->connection->getDatabasePlatform()->getName() != 'sqlite', 'This down migration can\'t be executed on SQLite databases, because SQLite don\'t support DROP COLUMN.');
-
- $this->addSql('ALTER TABLE '.$this->getTable('entry').' DROP http_status');
+ $userTable = $schema->getTable($this->getTable('entry'));
+ $userTable->dropColumn('http_status');
}
}
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
- * Add the restricted_access internal setting for articles with paywall
+ * Add the restricted_access internal setting for articles with paywall.
*/
class Version20161122144743 extends AbstractMigration implements ContainerAwareInterface
{
private function getTable($tableName)
{
- return $this->container->getParameter('database_table_prefix') . $tableName;
+ return $this->container->getParameter('database_table_prefix').$tableName;
}
/**
*/
public function up(Schema $schema)
{
- $this->addSql("INSERT INTO ".$this->getTable('craue_config_setting')." (name, value, section) VALUES ('restricted_access', 0, 'entry')");
+ $this->addSql('INSERT INTO '.$this->getTable('craue_config_setting')." (name, value, section) VALUES ('restricted_access', 0, 'entry')");
}
/**
*/
public function down(Schema $schema)
{
- $this->addSql("DELETE FROM ".$this->getTable('craue_config_setting')." WHERE name = 'restricted_access';");
+ $this->addSql('DELETE FROM '.$this->getTable('craue_config_setting')." WHERE name = 'restricted_access';");
}
}
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
- * Methods and properties removed from `FOS\UserBundle\Model\User`
+ * Methods and properties removed from `FOS\UserBundle\Model\User`.
*
* - `$expired`
* - `$credentialsExpired`
private function getTable($tableName)
{
- return $this->container->getParameter('database_table_prefix') . $tableName;
+ return $this->container->getParameter('database_table_prefix').$tableName;
}
/**
*/
public function up(Schema $schema)
{
- $this->abortIf($this->connection->getDatabasePlatform()->getName() === 'sqlite', 'This up migration can\'t be executed on SQLite databases, because SQLite don\'t support DROP COLUMN.');
+ $userTable = $schema->getTable($this->getTable('user'));
- $this->addSql('ALTER TABLE '.$this->getTable('user').' DROP expired');
- $this->addSql('ALTER TABLE '.$this->getTable('user').' DROP credentials_expired');
+ $this->skipIf(false === $userTable->hasColumn('expired') || false === $userTable->hasColumn('credentials_expired'), 'It seems that you already played this migration.');
+
+ $userTable->dropColumn('expired');
+ $userTable->dropColumn('credentials_expired');
}
/**
*/
public function down(Schema $schema)
{
- $this->addSql('ALTER TABLE '.$this->getTable('user').' ADD expired tinyint(1) NULL DEFAULT 0');
- $this->addSql('ALTER TABLE '.$this->getTable('user').' ADD credentials_expired tinyint(1) NULL DEFAULT 0');
+ $userTable = $schema->getTable($this->getTable('user'));
+ $userTable->addColumn('expired', 'smallint');
+ $userTable->addColumn('credentials_expired', 'smallint');
}
}
$configTable = $schema->getTable($this->getTable('config'));
$this->skipIf($configTable->hasColumn('list_mode'), 'It seems that you already played this migration.');
- $configTable->addColumn('list_mode', 'integer');
+ $configTable->addColumn('list_mode', 'integer', ['notnull' => false]);
}
/**
rss_limit: 50
reading_speed: 1
cache_lifetime: 10
+ action_mark_as_read: 1
+ list_mode: 1
fetching_error_message: |
wallabag can't retrieve contents for this article. Please <a href="http://doc.wallabag.org/en/master/user/errors_during_fetching.html#how-can-i-help-to-fix-that">troubleshoot this issue</a>.
bin/console wallabag:import:redis-worker -e=prod firefox -vv >> /path/to/wallabag/var/logs/redis-firefox.log
# für den Chrome-Import
- bin/console wallabag:import:redis-worker -e=prod instapaper -vv >> /path/to/wallabag/var/logs/redis-chrome.log
+ bin/console wallabag:import:redis-worker -e=prod chrome -vv >> /path/to/wallabag/var/logs/redis-chrome.log
Wenn du den Import nur für einige Artikel nutzen willst, kannst du die Nummer festlegen (hier: 12) und der Consumer wird nach dem zwölften Artikel aufhören:
.. code:: bash
- bin/console wallabag:import:redis-worker -e=prod pocket -vv --maxIterations=12
\ No newline at end of file
+ bin/console wallabag:import:redis-worker -e=prod pocket -vv --maxIterations=12
bin/console wallabag:import:redis-worker -e=prod firefox -vv >> /path/to/wallabag/var/logs/redis-firefox.log
# for Chrome import
- bin/console wallabag:import:redis-worker -e=prod instapaper -vv >> /path/to/wallabag/var/logs/redis-chrome.log
+ bin/console wallabag:import:redis-worker -e=prod chrome -vv >> /path/to/wallabag/var/logs/redis-chrome.log
If you want to launch the import only for some messages and not all, you can specify this number (here 12) and the worker will stop right after the 12th message :
bin/console wallabag:import:redis-worker -e=prod firefox -vv >> /path/to/wallabag/var/logs/redis-firefox.log
# for Chrome import
- bin/console wallabag:import:redis-worker -e=prod instapaper -vv >> /path/to/wallabag/var/logs/redis-chrome.log
+ bin/console wallabag:import:redis-worker -e=prod chrome -vv >> /path/to/wallabag/var/logs/redis-chrome.log
Si vous souhaitez démarrer l'import pour quelques messages uniquement, vous pouvez spécifier cette valeur en paramètre (ici 12) et le client va s'arrêter après le 12ème message :
$adminConfig->setLanguage('en');
$adminConfig->setPocketConsumerKey('xxxxx');
$adminConfig->setActionMarkAsRead(0);
+ $adminConfig->setListMode(0);
$manager->persist($adminConfig);
$bobConfig->setLanguage('fr');
$bobConfig->setPocketConsumerKey(null);
$bobConfig->setActionMarkAsRead(1);
+ $bobConfig->setListMode(1);
$manager->persist($bobConfig);
$emptyConfig->setLanguage('en');
$emptyConfig->setPocketConsumerKey(null);
$emptyConfig->setActionMarkAsRead(0);
+ $emptyConfig->setListMode(0);
$manager->persist($emptyConfig);
->end()
->scalarNode('fetching_error_message')
->end()
+ ->scalarNode('action_mark_as_read')
+ ->defaultValue(1)
+ ->end()
+ ->scalarNode('list_mode')
+ ->defaultValue(1)
+ ->end()
->end()
;
$container->setParameter('wallabag_core.version', $config['version']);
$container->setParameter('wallabag_core.paypal_url', $config['paypal_url']);
$container->setParameter('wallabag_core.cache_lifetime', $config['cache_lifetime']);
+ $container->setParameter('wallabag_core.action_mark_as_read', $config['action_mark_as_read']);
+ $container->setParameter('wallabag_core.list_mode', $config['list_mode']);
$container->setParameter('wallabag_core.fetching_error_message', $config['fetching_error_message']);
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config'));
* @var string
*
* @Assert\NotBlank()
+ * @Assert\Length(max=255)
* @RulerZAssert\ValidRule(
* allowed_variables={"title", "url", "isArchived", "isStared", "content", "language", "mimetype", "readingTime", "domainName"},
* allowed_operators={">", "<", ">=", "<=", "=", "is", "!=", "and", "not", "or", "matches"}
protected $logger;
protected $tagRepository;
protected $mimeGuesser;
+ protected $fetchingErrorMessage;
- public function __construct(Graby $graby, RuleBasedTagger $tagger, TagRepository $tagRepository, LoggerInterface $logger)
+ public function __construct(Graby $graby, RuleBasedTagger $tagger, TagRepository $tagRepository, LoggerInterface $logger, $fetchingErrorMessage)
{
$this->graby = $graby;
$this->tagger = $tagger;
$this->logger = $logger;
$this->tagRepository = $tagRepository;
$this->mimeGuesser = new MimeTypeExtensionGuesser();
+ $this->fetchingErrorMessage = $fetchingErrorMessage;
}
/**
{
// do we have to fetch the content or the provided one is ok?
if (empty($content) || false === $this->validateContent($content)) {
- $content = $this->graby->fetchContent($url);
+ $fetchedContent = $this->graby->fetchContent($url);
+
+ // 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
+ if (empty($content) || $fetchedContent['html'] !== $this->fetchingErrorMessage) {
+ $content = $fetchedContent;
+ }
}
$title = $content['title'];
$html = $content['html'];
if (false === $html) {
- $html = '<p>Unable to retrieve readable content.</p>';
+ $html = $this->fetchingErrorMessage;
if (isset($content['open_graph']['og_description'])) {
$html .= '<p><i>But we found a short description: </i></p>';
$entry->setContent($html);
$entry->setHttpStatus(isset($content['status']) ? $content['status'] : '');
- $entry->setLanguage($content['language']);
- $entry->setMimetype($content['content_type']);
+ $entry->setLanguage(isset($content['language']) ? $content['language'] : '');
+ $entry->setMimetype(isset($content['content_type']) ? $content['content_type'] : '');
$entry->setReadingTime(Utils::getReadingTime($html));
$domainName = parse_url($entry->getUrl(), PHP_URL_HOST);
}
// if content is an image define as a preview too
- if (in_array($this->mimeGuesser->guess($content['content_type']), ['jpeg', 'jpg', 'gif', 'png'], true)) {
+ if (isset($content['content_type']) && in_array($this->mimeGuesser->guess($content['content_type']), ['jpeg', 'jpg', 'gif', 'png'], true)) {
$entry->setPreviewPicture($content['url']);
}
{
// if folder doesn't exist, attempt to create one and store the folder name in property $folder
if (!file_exists($this->baseFolder)) {
- mkdir($this->baseFolder, 0777, true);
+ mkdir($this->baseFolder, 0755, true);
}
}
private function getBuilderByUser($userId)
{
return $this->createQueryBuilder('e')
- ->leftJoin('e.user', 'u')
- ->andWhere('u.id = :userId')->setParameter('userId', $userId)
+ ->andWhere('e.user = :userId')->setParameter('userId', $userId)
->orderBy('e.createdAt', 'desc')
;
}
parameters:
addons_url:
firefox: https://addons.mozilla.org/firefox/addon/wallabag-v2/
- chrome: https://chrome.google.com/webstore/detail/wallabagit/peehlcgckcnclnjlndmoddifcicdnabm
+ chrome: https://chrome.google.com/webstore/detail/wallabagger/gbmgphmejlcoihgedabhgjdkcahacjlj
+ opera: https://addons.opera.com/en/extensions/details/wallabagger/?display=en
f_droid: https://f-droid.org/app/fr.gaulupeau.apps.InThePoche
google_play: https://play.google.com/store/apps/details?id=fr.gaulupeau.apps.InThePoche
- ios: https://itunes.apple.com/app/wallabag/id828331015?mt=8
+ ios: https://itunes.apple.com/app/wallabag-2/id1170800946?mt=8
windows: https://www.microsoft.com/store/apps/wallabag/9nblggh11646
- "@wallabag_core.rule_based_tagger"
- "@wallabag_core.tag_repository"
- "@logger"
+ - '%wallabag_core.fetching_error_message%'
wallabag_core.rule_based_tagger:
class: Wallabag\CoreBundle\Helper\RuleBasedTagger
browser_addons:
firefox: 'Standardudvidelse til Firefox'
chrome: 'Chrome-udvidelse'
+ opera: 'Opera-udvidelse'
mobile_apps:
android:
via_f_droid: 'via F-Droid'
browser_addons:
firefox: 'Firefox-Erweiterung'
chrome: 'Chrome-Erweiterung'
+ opera: 'Opera-Erweiterung'
mobile_apps:
android:
via_f_droid: 'via F-Droid'
form:
description: 'Thanks to this form'
browser_addons:
- firefox: 'Standard Firefox Add-On'
- chrome: 'Chrome Extension'
+ firefox: 'Firefox addon'
+ chrome: 'Chrome addon'
+ opera: 'Opera addon'
mobile_apps:
android:
via_f_droid: 'via F-Droid'
browser_addons:
firefox: 'Extensión Firefox'
chrome: 'Extensión Chrome'
+ opera: 'Extensión Opera'
mobile_apps:
android:
via_f_droid: 'via F-Droid'
browser_addons:
firefox: 'افزونهٔ فایرفاکس'
chrome: 'افزونهٔ کروم'
+ # opera: 'Opera addon'
mobile_apps:
android:
via_f_droid: 'از راه F-Droid'
browser_addons:
firefox: "Extension Firefox"
chrome: "Extension Chrome"
+ opera: "Extension Opera"
mobile_apps:
android:
via_f_droid: "via F-Droid"
browser_addons:
firefox: 'Add-On di Firefox'
chrome: 'Estensione di Chrome'
+ opera: 'Estensione di Opera'
mobile_apps:
android:
via_f_droid: 'via F-Droid'
browser_addons:
firefox: 'Extension Firefox'
chrome: 'Extension Chrome'
+ opera: 'Extension Opera'
mobile_apps:
android:
via_f_droid: 'via F-Droid'
browser_addons:
firefox: 'Standardowe rozszerzenie dla Firefox'
chrome: 'Rozszerzenie dla Chrome'
+ opera: 'Rozszerzenie dla Opera'
mobile_apps:
android:
via_f_droid: 'w F-Droid'
browser_addons:
firefox: 'Extensão padrão do Firefox'
chrome: 'Extensão do Chrome'
+ opera: 'Extensão do Opera'
mobile_apps:
android:
via_f_droid: 'via F-Droid'
browser_addons:
firefox: 'Add-On standard de Firefox'
chrome: 'Extensie Chrome'
+ opera: 'Extensie Opera'
mobile_apps:
android:
via_f_droid: 'prin F-Droid'
browser_addons:
firefox: 'Standart Firefox Eklentisi'
chrome: 'Chrome Eklentisi'
+ opera: 'Opera Eklentisi'
mobile_apps:
android:
# via_f_droid: 'via F-Droid'
<ul>
<li><a href="{{ addonsUrl.firefox }}" target="_blank">{{ 'howto.browser_addons.firefox'|trans }}</a></li>
<li><a href="{{ addonsUrl.chrome }}" target="_blank">{{ 'howto.browser_addons.chrome'|trans }}</a></li>
+ <li><a href="{{ addonsUrl.opera }}" target="_blank">{{ 'howto.browser_addons.opera'|trans }}</a></li>
</ul>
</div>
</tbody>
</table>
</div>
-
+
</div>
</div>
</div>
<article>
{{ entry.content | raw }}
</article>
+
+ <div class="fixed-action-btn horizontal click-to-toggle hide-on-large-only">
+ <a class="btn-floating btn-large">
+ <i class="material-icons">menu</i>
+ </a>
+ <ul>
+ <li><a class="btn-floating" href="{{ path('archive_entry', { 'id': entry.id }) }}"><i class="material-icons">done</i></a></li>
+ <li><a class="btn-floating" href="{{ path('star_entry', { 'id': entry.id }) }}"><i class="material-icons">star_outline</i></a></li>
+ <li><a class="btn-floating" href="{{ path('delete_entry', { 'id': entry.id }) }}"><i class="material-icons">delete</i></a></li>
+ </ul>
+ </div>
</div>
<script id="annotationroutes" type="application/json">
Materialize.toast('{{ flashMessage|trans }}', 4000);
</script>
{% endfor %}
-
- {{ render(controller("WallabagImportBundle:Import:checkQueue")) }}
{% endblock %}
{% block menu %}
$worker = new QueueWorker(
$this->getContainer()->get('wallabag_import.queue.redis.'.$serviceName),
$this->getContainer()->get('wallabag_import.consumer.redis.'.$serviceName),
- $input->getOption('maxIterations')
+ (int) $input->getOption('maxIterations')
);
$worker->start();
{
$data = [
'title' => $entry['name'],
- 'html' => '',
+ 'html' => false,
'url' => $entry['url'],
- 'is_archived' => $this->markAsRead,
+ 'is_archived' => (int) $this->markAsRead,
+ 'is_starred' => false,
'tags' => '',
'created_at' => substr($entry['date_added'], 0, 10),
];
{
$data = [
'title' => $entry['title'],
- 'html' => '',
+ 'html' => false,
'url' => $entry['uri'],
- 'is_archived' => $this->markAsRead,
+ 'is_archived' => (int) $this->markAsRead,
+ 'is_starred' => false,
'tags' => '',
'created_at' => substr($entry['dateAdded'], 0, 10),
];
'status' => $data[3],
'is_archived' => $data[3] === 'Archive' || $data[3] === 'Starred',
'is_starred' => $data[3] === 'Starred',
- 'content_type' => '',
- 'language' => '',
+ 'html' => false,
];
}
fclose($handle);
$data = [
'title' => $importedEntry['description'],
'url' => $importedEntry['href'],
- 'content_type' => '',
- 'language' => '',
'is_archived' => ('no' === $importedEntry['toread']) || $this->markAsRead,
'is_starred' => false,
'created_at' => $importedEntry['time'],
$data = [
'title' => $importedEntry['article__title'],
'url' => $importedEntry['article__url'],
- 'content_type' => '',
- 'language' => '',
'is_archived' => $importedEntry['archive'] || $this->markAsRead,
'is_starred' => $importedEntry['favorite'],
'created_at' => $importedEntry['date_added'],
+ 'html' => false,
];
$entry = new Entry($this->user);
'title' => $entry['title'],
'html' => $entry['content'],
'url' => $entry['url'],
- 'content_type' => '',
- 'language' => '',
'is_archived' => $entry['is_read'] || $this->markAsRead,
'is_starred' => $entry['is_fav'],
'tags' => '',
return [
'html' => $entry['content'],
'content_type' => $entry['mimetype'],
- 'is_archived' => ($entry['is_archived'] || $this->markAsRead),
+ 'is_archived' => (int) ($entry['is_archived'] || $this->markAsRead),
+ 'is_starred' => false,
] + $entry;
}
{% block title %}{{ 'import.page_title'|trans }}{% endblock %}
+{% block messages %}
+ {{ render(controller("WallabagImportBundle:Import:checkQueue")) }}
+
+ {{ parent() }}
+{% endblock %}
+
{% block content %}
<div class="row">
<div class="col s12">
private $rssLimit;
private $language;
private $readingSpeed;
+ private $actionMarkAsRead;
+ private $listMode;
- public function __construct(EntityManager $em, $theme, $itemsOnPage, $rssLimit, $language, $readingSpeed)
+ public function __construct(EntityManager $em, $theme, $itemsOnPage, $rssLimit, $language, $readingSpeed, $actionMarkAsRead, $listMode)
{
$this->em = $em;
$this->theme = $theme;
$this->rssLimit = $rssLimit;
$this->language = $language;
$this->readingSpeed = $readingSpeed;
+ $this->actionMarkAsRead = $actionMarkAsRead;
+ $this->listMode = $listMode;
}
public static function getSubscribedEvents()
$config->setRssLimit($this->rssLimit);
$config->setLanguage($this->language);
$config->setReadingSpeed($this->readingSpeed);
+ $config->setActionMarkAsRead($this->actionMarkAsRead);
+ $config->setListMode($this->listMode);
$this->em->persist($config);
$this->em->flush();
- "%wallabag_core.rss_limit%"
- "%wallabag_core.language%"
- "%wallabag_core.reading_speed%"
+ - "%wallabag_core.action_mark_as_read%"
+ - "%wallabag_core.list_mode%"
tags:
- { name: kernel.event_subscriber }
--- /dev/null
+# Two factor mail
+auth_code:
+ on: 'an'
+ mailer:
+ subject: 'wallabag Authentifizierungcode'
+ body:
+ hello: "Hi %user%,"
+ first_para: "da du die Zwei-Faktor-Authentifizierung in deinem wallabag Konto aktiviert hast, und du dich gerade von einem neuen Gerät (Computer, Handy, etc.) anmeldest, senden wir dir einen Code, um deinen Zugriff zu prüfen."
+ second_para: "Hier ist der Code:"
+ support: "Bitte zögere nicht, Kontakt mit uns aufzunehmen falls du ein Problem hast:"
+ signature: "Das wallabag Team"
auth_code:
on: 'on'
mailer:
- subject: 'Wallabag authentication Code'
+ subject: 'wallabag authentication code'
body:
hello: "Hi %user%,"
first_para: "Since you enable two factor authentication on your wallabag account and you just logged in from a new device (computer, phone, etc.), we send you a code to validate your connection."
<table cellpadding="0" cellspacing="0" border="0" align="center" id="card">
<tr>
- <td style="padding: 20px;" width="96px" valign="top"><img class="image_fix" src="{{ asset('bundles/wallabagcore/themes/material/img/logo-other_themes.png') }}" alt="logo" title="{{ wallabag_url }}" style="width: 96px; height: 96px;" /></td>
+ <td style="padding: 20px;" width="96px" valign="top"><img class="image_fix" src="{{ absolute_url(asset('bundles/wallabagcore/themes/_global/img/logo-other_themes.png')) }}" alt="logo" title="{{ wallabag_url }}" style="width: 96px; height: 96px;" /></td>
<td style="padding: 20px; padding-left: 0;" valign="top" id="cell_desc">
<h1>wallabag</h1>
<h5>{{ "auth_code.on"|trans({}, 'wallabag_user') }} {{ wallabag_url }}</h5>
}
}
+ public function testTaggingRuleTooLong()
+ {
+ $this->logInAs('admin');
+ $client = $this->getClient();
+
+ $crawler = $client->request('GET', '/config');
+
+ $this->assertEquals(200, $client->getResponse()->getStatusCode());
+
+ $form = $crawler->filter('button[id=tagging_rule_save]')->form();
+
+ $crawler = $client->submit($form, [
+ 'tagging_rule[rule]' => str_repeat('title', 60),
+ 'tagging_rule[tags]' => 'cool tag',
+ ]);
+
+ $this->assertEquals(200, $client->getResponse()->getStatusCode());
+
+ $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
+
+ $this->assertContains('255 characters', $body[0]);
+ }
+
public function testDeletingTaggingRuleFromAnOtherUser()
{
$this->logInAs('bob');
class ContentProxyTest extends \PHPUnit_Framework_TestCase
{
+ private $fetchingErrorMessage = 'wallabag can\'t retrieve contents for this article. Please <a href="http://doc.wallabag.org/en/master/user/errors_during_fetching.html#how-can-i-help-to-fix-that">troubleshoot this issue</a>.';
+
public function testWithBadUrl()
{
$tagger = $this->getTaggerMock();
'language' => '',
]);
- $proxy = new ContentProxy($graby, $tagger, $this->getTagRepositoryMock(), $this->getLogger());
+ $proxy = new ContentProxy($graby, $tagger, $this->getTagRepositoryMock(), $this->getLogger(), $this->fetchingErrorMessage);
$entry = $proxy->updateEntry(new Entry(new User()), 'http://user@:80');
$this->assertEquals('http://user@:80', $entry->getUrl());
$this->assertEmpty($entry->getTitle());
- $this->assertEquals('<p>Unable to retrieve readable content.</p>', $entry->getContent());
+ $this->assertEquals($this->fetchingErrorMessage, $entry->getContent());
$this->assertEmpty($entry->getPreviewPicture());
$this->assertEmpty($entry->getMimetype());
$this->assertEmpty($entry->getLanguage());
'language' => '',
]);
- $proxy = new ContentProxy($graby, $tagger, $this->getTagRepositoryMock(), $this->getLogger());
+ $proxy = new ContentProxy($graby, $tagger, $this->getTagRepositoryMock(), $this->getLogger(), $this->fetchingErrorMessage);
$entry = $proxy->updateEntry(new Entry(new User()), 'http://0.0.0.0');
$this->assertEquals('http://0.0.0.0', $entry->getUrl());
$this->assertEmpty($entry->getTitle());
- $this->assertEquals('<p>Unable to retrieve readable content.</p>', $entry->getContent());
+ $this->assertEquals($this->fetchingErrorMessage, $entry->getContent());
$this->assertEmpty($entry->getPreviewPicture());
$this->assertEmpty($entry->getMimetype());
$this->assertEmpty($entry->getLanguage());
],
]);
- $proxy = new ContentProxy($graby, $tagger, $this->getTagRepositoryMock(), $this->getLogger());
+ $proxy = new ContentProxy($graby, $tagger, $this->getTagRepositoryMock(), $this->getLogger(), $this->fetchingErrorMessage);
$entry = $proxy->updateEntry(new Entry(new User()), 'http://domain.io');
$this->assertEquals('http://domain.io', $entry->getUrl());
$this->assertEquals('my title', $entry->getTitle());
- $this->assertEquals('<p>Unable to retrieve readable content.</p><p><i>But we found a short description: </i></p>desc', $entry->getContent());
+ $this->assertEquals($this->fetchingErrorMessage . '<p><i>But we found a short description: </i></p>desc', $entry->getContent());
$this->assertEmpty($entry->getPreviewPicture());
$this->assertEmpty($entry->getLanguage());
$this->assertEmpty($entry->getHttpStatus());
],
]);
- $proxy = new ContentProxy($graby, $tagger, $this->getTagRepositoryMock(), $this->getLogger());
+ $proxy = new ContentProxy($graby, $tagger, $this->getTagRepositoryMock(), $this->getLogger(), $this->fetchingErrorMessage);
$entry = $proxy->updateEntry(new Entry(new User()), 'http://0.0.0.0');
$this->assertEquals('http://1.1.1.1', $entry->getUrl());
$graby = $this->getMockBuilder('Graby\Graby')->getMock();
- $proxy = new ContentProxy($graby, $tagger, $this->getTagRepositoryMock(), $this->getLogger());
+ $proxy = new ContentProxy($graby, $tagger, $this->getTagRepositoryMock(), $this->getLogger(), $this->fetchingErrorMessage);
$entry = $proxy->updateEntry(new Entry(new User()), 'http://0.0.0.0', [
'html' => str_repeat('this is my content', 325),
'title' => 'this is my title',
->will($this->throwException(new \Exception()));
$tagRepo = $this->getTagRepositoryMock();
- $proxy = new ContentProxy($graby, $tagger, $tagRepo, $this->getLogger());
+ $proxy = new ContentProxy($graby, $tagger, $tagRepo, $this->getLogger(), $this->fetchingErrorMessage);
$entry = $proxy->updateEntry(new Entry(new User()), 'http://0.0.0.0', [
'html' => str_repeat('this is my content', 325),
->getMock();
$tagRepo = $this->getTagRepositoryMock();
- $proxy = new ContentProxy($graby, $this->getTaggerMock(), $tagRepo, $this->getLogger());
+ $proxy = new ContentProxy($graby, $this->getTaggerMock(), $tagRepo, $this->getLogger(), $this->fetchingErrorMessage);
$entry = new Entry(new User());
->getMock();
$tagRepo = $this->getTagRepositoryMock();
- $proxy = new ContentProxy($graby, $this->getTaggerMock(), $tagRepo, $this->getLogger());
+ $proxy = new ContentProxy($graby, $this->getTaggerMock(), $tagRepo, $this->getLogger(), $this->fetchingErrorMessage);
$entry = new Entry(new User());
->getMock();
$tagRepo = $this->getTagRepositoryMock();
- $proxy = new ContentProxy($graby, $this->getTaggerMock(), $tagRepo, $this->getLogger());
+ $proxy = new ContentProxy($graby, $this->getTaggerMock(), $tagRepo, $this->getLogger(), $this->fetchingErrorMessage);
$entry = new Entry(new User());
->getMock();
$tagRepo = $this->getTagRepositoryMock();
- $proxy = new ContentProxy($graby, $this->getTaggerMock(), $tagRepo, $this->getLogger());
+ $proxy = new ContentProxy($graby, $this->getTaggerMock(), $tagRepo, $this->getLogger(), $this->fetchingErrorMessage);
$entry = new Entry(new User());
->getMock();
$tagRepo = $this->getTagRepositoryMock();
- $proxy = new ContentProxy($graby, $this->getTaggerMock(), $tagRepo, $this->getLogger());
+ $proxy = new ContentProxy($graby, $this->getTaggerMock(), $tagRepo, $this->getLogger(), $this->fetchingErrorMessage);
$tagEntity = new Tag();
$tagEntity->setLabel('tag1');
$tagRepo->expects($this->never())
->method('__call');
- $proxy = new ContentProxy($graby, $this->getTaggerMock(), $tagRepo, $this->getLogger());
+ $proxy = new ContentProxy($graby, $this->getTaggerMock(), $tagRepo, $this->getLogger(), $this->fetchingErrorMessage);
$tagEntity = new Tag();
$tagEntity->setLabel('tag1');
->get('doctrine.orm.entity_manager')
->getRepository('WallabagCoreBundle:Entry')
->findByUrlAndUserId(
- 'http://www.framablog.org/index.php/post/2014/02/05/Framabag-service-libre-gratuit-interview-developpeur',
+ 'https://framablog.org/2014/02/05/framabag-service-libre-gratuit-interview-developpeur/',
$this->getLoggedInUserId()
);
$this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
$this->assertContains('flashes.import.notice.summary', $body[0]);
- $this->assertEmpty($content->getMimetype(), 'Mimetype for http://www.framablog.org is ok');
- $this->assertEmpty($content->getPreviewPicture(), 'Preview picture for http://www.framablog.org is ok');
- $this->assertEmpty($content->getLanguage(), 'Language for http://www.framablog.org is ok');
+ $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://www.framablog.org is ok');
+ $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.framablog.org is ok');
+ $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.framablog.org is ok');
$this->assertEquals(1, count($content->getTags()));
$this->assertInstanceOf(\DateTime::class, $content->getCreatedAt());
}
20,
50,
'fr',
+ 1,
+ 1,
1
);