mirror of
https://github.com/shlinkio/shlink.git
synced 2025-04-02 06:45:33 +03:00
Improved how existing imported short URLs are checked by tracking its original short code
This commit is contained in:
parent
786e4f642b
commit
7c343f42c1
7 changed files with 49 additions and 21 deletions
|
@ -53,7 +53,7 @@
|
||||||
"shlinkio/shlink-common": "^3.2.0",
|
"shlinkio/shlink-common": "^3.2.0",
|
||||||
"shlinkio/shlink-config": "^1.0",
|
"shlinkio/shlink-config": "^1.0",
|
||||||
"shlinkio/shlink-event-dispatcher": "^1.4",
|
"shlinkio/shlink-event-dispatcher": "^1.4",
|
||||||
"shlinkio/shlink-importer": "^2.0",
|
"shlinkio/shlink-importer": "^2.0.1",
|
||||||
"shlinkio/shlink-installer": "^5.1.0",
|
"shlinkio/shlink-installer": "^5.1.0",
|
||||||
"shlinkio/shlink-ip-geolocation": "^1.5",
|
"shlinkio/shlink-ip-geolocation": "^1.5",
|
||||||
"symfony/console": "^5.1",
|
"symfony/console": "^5.1",
|
||||||
|
|
|
@ -21,6 +21,15 @@ final class Version20201023090929 extends AbstractMigration
|
||||||
'length' => 255,
|
'length' => 255,
|
||||||
'notnull' => false,
|
'notnull' => false,
|
||||||
]);
|
]);
|
||||||
|
$shortUrls->addColumn('import_original_short_code', Types::STRING, [
|
||||||
|
'length' => 255,
|
||||||
|
'notnull' => false,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$shortUrls->addUniqueIndex(
|
||||||
|
[self::IMPORT_SOURCE_COLUMN, 'import_original_short_code', 'domain_id'],
|
||||||
|
'unique_imports',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down(Schema $schema): void
|
public function down(Schema $schema): void
|
||||||
|
@ -29,5 +38,7 @@ final class Version20201023090929 extends AbstractMigration
|
||||||
$this->skipIf(! $shortUrls->hasColumn(self::IMPORT_SOURCE_COLUMN));
|
$this->skipIf(! $shortUrls->hasColumn(self::IMPORT_SOURCE_COLUMN));
|
||||||
|
|
||||||
$shortUrls->dropColumn(self::IMPORT_SOURCE_COLUMN);
|
$shortUrls->dropColumn(self::IMPORT_SOURCE_COLUMN);
|
||||||
|
$shortUrls->dropColumn('import_original_short_code');
|
||||||
|
$shortUrls->dropIndex('unique_imports');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,11 @@ return static function (ClassMetadata $metadata, array $emConfig): void {
|
||||||
->nullable()
|
->nullable()
|
||||||
->build();
|
->build();
|
||||||
|
|
||||||
|
$builder->createField('importOriginalShortCode', Types::STRING)
|
||||||
|
->columnName('import_original_short_code')
|
||||||
|
->nullable()
|
||||||
|
->build();
|
||||||
|
|
||||||
$builder->createOneToMany('visits', Entity\Visit::class)
|
$builder->createOneToMany('visits', Entity\Visit::class)
|
||||||
->mappedBy('shortUrl')
|
->mappedBy('shortUrl')
|
||||||
->fetchExtraLazy()
|
->fetchExtraLazy()
|
||||||
|
|
|
@ -36,6 +36,7 @@ class ShortUrl extends AbstractEntity
|
||||||
private bool $customSlugWasProvided;
|
private bool $customSlugWasProvided;
|
||||||
private int $shortCodeLength;
|
private int $shortCodeLength;
|
||||||
private ?string $importSource = null;
|
private ?string $importSource = null;
|
||||||
|
private ?string $importOriginalShortCode = null;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
string $longUrl,
|
string $longUrl,
|
||||||
|
@ -72,6 +73,7 @@ class ShortUrl extends AbstractEntity
|
||||||
|
|
||||||
$instance = new self($url->longUrl(), ShortUrlMeta::fromRawData($meta), $domainResolver);
|
$instance = new self($url->longUrl(), ShortUrlMeta::fromRawData($meta), $domainResolver);
|
||||||
$instance->importSource = $url->source();
|
$instance->importSource = $url->source();
|
||||||
|
$instance->importOriginalShortCode = $url->shortCode();
|
||||||
$instance->dateCreated = Chronos::instance($url->createdAt());
|
$instance->dateCreated = Chronos::instance($url->createdAt());
|
||||||
|
|
||||||
return $instance;
|
return $instance;
|
||||||
|
|
|
@ -50,7 +50,7 @@ class ImportedLinksProcessor implements ImportedLinksProcessorInterface
|
||||||
$longUrl = $url->longUrl();
|
$longUrl = $url->longUrl();
|
||||||
|
|
||||||
// Skip already imported URLs
|
// Skip already imported URLs
|
||||||
if ($shortUrlRepo->importedUrlExists($url, $importShortCodes)) {
|
if ($shortUrlRepo->importedUrlExists($url)) {
|
||||||
$io->text(sprintf('%s: <comment>Skipped</comment>', $longUrl));
|
$io->text(sprintf('%s: <comment>Skipped</comment>', $longUrl));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ class ImportedLinksProcessor implements ImportedLinksProcessorInterface
|
||||||
$shortUrl = ShortUrl::fromImport($url, $importShortCodes, $this->domainResolver);
|
$shortUrl = ShortUrl::fromImport($url, $importShortCodes, $this->domainResolver);
|
||||||
$shortUrl->setTags($this->tagNamesToEntities($this->em, $url->tags()));
|
$shortUrl->setTags($this->tagNamesToEntities($this->em, $url->tags()));
|
||||||
|
|
||||||
if (! $this->handleShortcodeUniqueness($url, $shortUrl, $io, $importShortCodes)) {
|
if (! $this->handleShortCodeUniqueness($url, $shortUrl, $io, $importShortCodes)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ class ImportedLinksProcessor implements ImportedLinksProcessorInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function handleShortcodeUniqueness(
|
private function handleShortCodeUniqueness(
|
||||||
ImportedShlinkUrl $url,
|
ImportedShlinkUrl $url,
|
||||||
ShortUrl $shortUrl,
|
ShortUrl $shortUrl,
|
||||||
StyleInterface $io,
|
StyleInterface $io,
|
||||||
|
@ -90,6 +90,6 @@ class ImportedLinksProcessor implements ImportedLinksProcessorInterface
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this->handleShortcodeUniqueness($url, $shortUrl, $io, false);
|
return $this->handleShortCodeUniqueness($url, $shortUrl, $io, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,13 +190,7 @@ DQL;
|
||||||
->setParameter('slug', $slug)
|
->setParameter('slug', $slug)
|
||||||
->setMaxResults(1);
|
->setMaxResults(1);
|
||||||
|
|
||||||
if ($domain !== null) {
|
$this->whereDomainIs($qb, $domain);
|
||||||
$qb->join('s.domain', 'd')
|
|
||||||
->andWhere($qb->expr()->eq('d.authority', ':authority'))
|
|
||||||
->setParameter('authority', $domain);
|
|
||||||
} else {
|
|
||||||
$qb->andWhere($qb->expr()->isNull('s.domain'));
|
|
||||||
}
|
|
||||||
|
|
||||||
return $qb;
|
return $qb;
|
||||||
}
|
}
|
||||||
|
@ -256,15 +250,31 @@ DQL;
|
||||||
return $qb->getQuery()->getOneOrNullResult();
|
return $qb->getQuery()->getOneOrNullResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function importedUrlExists(ImportedShlinkUrl $url, bool $importShortCodes): bool
|
public function importedUrlExists(ImportedShlinkUrl $url): bool
|
||||||
{
|
{
|
||||||
$findConditions = ['importSource' => $url->source()];
|
$qb = $this->getEntityManager()->createQueryBuilder();
|
||||||
if ($importShortCodes) {
|
$qb->select('COUNT(DISTINCT s.id)')
|
||||||
$findConditions['shortCode'] = $url->shortCode();
|
->from(ShortUrl::class, 's')
|
||||||
} else {
|
->andWhere($qb->expr()->eq('s.importOriginalShortCode', ':shortCode'))
|
||||||
$findConditions['longUrl'] = $url->longUrl();
|
->setParameter('shortCode', $url->shortCode())
|
||||||
}
|
->andWhere($qb->expr()->eq('s.importSource', ':importSource'))
|
||||||
|
->setParameter('importSource', $url->source())
|
||||||
|
->setMaxResults(1);
|
||||||
|
|
||||||
return $this->count($findConditions) > 0;
|
$this->whereDomainIs($qb, $url->domain());
|
||||||
|
|
||||||
|
$result = (int) $qb->getQuery()->getSingleScalarResult();
|
||||||
|
return $result > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function whereDomainIs(QueryBuilder $qb, ?string $domain): void
|
||||||
|
{
|
||||||
|
if ($domain !== null) {
|
||||||
|
$qb->join('s.domain', 'd')
|
||||||
|
->andWhere($qb->expr()->eq('d.authority', ':authority'))
|
||||||
|
->setParameter('authority', $domain);
|
||||||
|
} else {
|
||||||
|
$qb->andWhere($qb->expr()->isNull('s.domain'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,5 +32,5 @@ interface ShortUrlRepositoryInterface extends ObjectRepository
|
||||||
|
|
||||||
public function findOneMatching(string $url, array $tags, ShortUrlMeta $meta): ?ShortUrl;
|
public function findOneMatching(string $url, array $tags, ShortUrlMeta $meta): ?ShortUrl;
|
||||||
|
|
||||||
public function importedUrlExists(ImportedShlinkUrl $url, bool $importShortCodes): bool;
|
public function importedUrlExists(ImportedShlinkUrl $url): bool;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue