diff --git a/config/services.xml b/config/services.xml
index 3f40e1f6..39e9acf9 100644
--- a/config/services.xml
+++ b/config/services.xml
@@ -87,25 +87,6 @@
-
-
-
-
-
-
- Doctrine\Website\Model\BlogPost
-
-
-
-
-
-
-
-
-
- Doctrine\Website\Model\BlogPost
-
-
Doctrine\Website\Model\BlogPost
@@ -140,22 +121,8 @@
-
-
-
-
-
- Doctrine\Website\Model\Project
-
-
-
-
-
-
-
-
-
- Doctrine\Website\Model\Project
+
+ Doctrine\Website\Model\Project
@@ -210,5 +172,12 @@
+
+
+
+
+
+
diff --git a/config/services/orm.xml b/config/services/orm.xml
index 02518a4b..23df7380 100644
--- a/config/services/orm.xml
+++ b/config/services/orm.xml
@@ -8,6 +8,8 @@
lib/Model
+ lib/Git
+ lib/Docs/RST
@@ -24,6 +26,6 @@
-
+
diff --git a/lib/DataBuilder/ProjectDataBuilder.php b/lib/DataBuilder/ProjectDataBuilder.php
deleted file mode 100644
index 1839d5bf..00000000
--- a/lib/DataBuilder/ProjectDataBuilder.php
+++ /dev/null
@@ -1,245 +0,0 @@
- 100])]
-final readonly class ProjectDataBuilder implements DataBuilder
-{
- public const DATA_FILE = 'projects';
-
- private const DEFAULTS = [
- 'active' => true,
- 'archived' => false,
- 'integration' => false,
- ];
-
- public function __construct(
- private ProjectDataRepository $projectDataRepository,
- private ProjectGitSyncer $projectGitSyncer,
- private ProjectDataReader $projectDataReader,
- private ProjectVersionsReader $projectVersionsReader,
- private RSTLanguagesDetector $rstLanguagesDetector,
- private GetProjectPackagistData $getProjectPackagistData,
- private string $projectsDir,
- ) {
- }
-
- public function getName(): string
- {
- return self::DATA_FILE;
- }
-
- public function build(): WebsiteData
- {
- $repositoryNames = $this->projectDataRepository->getProjectRepositoryNames();
-
- $projects = array_map(function (string $repositoryName): array {
- return $this->buildProjectData($repositoryName);
- }, $repositoryNames);
-
- return new WebsiteData(self::DATA_FILE, $projects);
- }
-
- /** @return mixed[] */
- private function buildProjectData(string $repositoryName): array
- {
- // checkout master branch
- $this->projectGitSyncer->checkoutDefaultBranch($repositoryName);
-
- $projectData = array_replace(
- self::DEFAULTS,
- $this->projectDataReader->read($repositoryName),
- );
-
- $projectData['versions'] = $this->buildProjectVersions(
- $repositoryName,
- $projectData,
- );
-
- $projectData['packagistData'] = $this->getProjectPackagistData->__invoke(
- $projectData['composerPackageName'],
- );
-
- return $projectData;
- }
-
- /**
- * @param mixed[] $projectData
- *
- * @return mixed[]
- */
- private function buildProjectVersions(string $repositoryName, array $projectData): array
- {
- $projectVersions = $this->readProjectVersionsFromGit($repositoryName);
-
- $this->applyConfiguredProjectVersions($projectVersions, $projectData);
-
- $this->sortProjectVersions($projectVersions);
-
- $this->prepareProjectVersions(
- $repositoryName,
- $projectVersions,
- $projectData,
- );
-
- return $projectVersions;
- }
-
- /** @return mixed[] */
- private function readProjectVersionsFromGit(string $repositoryName): array
- {
- $repositoryPath = $this->projectsDir . '/' . $repositoryName;
-
- $projectVersions = $this->projectVersionsReader->readProjectVersions($repositoryPath);
-
- // fix this, we shouldn't have null branch names at this point. Fix it further upstream
- return array_filter($projectVersions, static function (array $projectVersion): bool {
- return count($projectVersion['tags']) > 0;
- });
- }
-
- /**
- * @param mixed[] $projectVersions
- * @param mixed[] $projectData
- *
- * @return mixed[]
- */
- private function applyConfiguredProjectVersions(
- array &$projectVersions,
- array $projectData,
- ): array {
- foreach ($projectVersions as $key => $projectVersion) {
- $configured = false;
-
- foreach ($projectData['versions'] as $k => $version) {
- if ($this->containsSameProjectVersion($projectVersion, $version)) {
- $version['tags'] = $projectVersion['tags'];
-
- $version['branchName'] = $projectVersion['branchName'];
-
- $projectVersions[$key] = $version;
-
- unset($projectData['versions'][$k]);
-
- $configured = true;
-
- break;
- }
- }
-
- if ($configured !== false) {
- continue;
- }
-
- $projectVersions[$key]['maintained'] = false;
- }
-
- foreach ($projectData['versions'] as $projectVersion) {
- $projectVersions[] = $projectVersion;
- }
-
- return $projectVersions;
- }
-
- /**
- * @param mixed[] $a
- * @param mixed[] $b
- */
- private function containsSameProjectVersion(array $a, array $b): bool
- {
- if ($a['name'] === $b['name']) {
- return true;
- }
-
- if (! isset($b['branchName'])) {
- return false;
- }
-
- return $a['branchName'] === $b['branchName'];
- }
-
- /**
- * @param mixed[] $projectVersions
- * @param mixed[] $projectData
- *
- * @return mixed[]
- */
- private function prepareProjectVersions(
- string $repositoryName,
- array &$projectVersions,
- array $projectData,
- ): array {
- $docsRepositoryName = $projectData['docsRepositoryName'] ?? $projectData['repositoryName'];
-
- $docsDir = $this->projectsDir . '/' . $docsRepositoryName . $projectData['docsPath'];
-
- foreach ($projectVersions as $key => $projectVersion) {
- if (! isset($projectVersion['branchName'])) {
- $this->projectGitSyncer->checkoutTag(
- $docsRepositoryName,
- end($projectVersion['tags'])->getName(),
- );
- } else {
- $this->projectGitSyncer->checkoutBranch(
- $docsRepositoryName,
- $projectVersion['branchName'],
- );
- }
-
- $docsLanguages = array_map(static function (RSTLanguage $language): array {
- return [
- 'code' => $language->getCode(),
- 'path' => $language->getPath(),
- ];
- }, $this->rstLanguagesDetector->detectLanguages($docsDir));
-
- $projectVersions[$key]['hasDocs'] = count($docsLanguages) > 0;
- $projectVersions[$key]['docsLanguages'] = $docsLanguages;
-
- if (! isset($projectVersion['tags'])) {
- continue;
- }
-
- $projectVersions[$key]['tags'] = array_map(static function (Tag $tag): array {
- return [
- 'name' => $tag->getName(),
- 'date' => $tag->getDate()->format('Y-m-d H:i:s'),
- ];
- }, $projectVersion['tags']);
- }
-
- // switch back to master
- $this->projectGitSyncer->checkoutDefaultBranch($repositoryName);
-
- return $projectVersions;
- }
-
- /** @param mixed[] $projectVersions */
- private function sortProjectVersions(array &$projectVersions): void
- {
- // sort by name so newest versions are first
- usort($projectVersions, static function (array $a, array $b): int {
- return strnatcmp($b['name'], $a['name']);
- });
- }
-}
diff --git a/lib/DataSources/DbPrefill/Projects.php b/lib/DataSources/DbPrefill/Projects.php
new file mode 100644
index 00000000..1a5e11b3
--- /dev/null
+++ b/lib/DataSources/DbPrefill/Projects.php
@@ -0,0 +1,120 @@
+dataSource->getSourceRows() as $sourceRow) {
+ $this->buildAndSaveProject($sourceRow);
+ }
+ }
+
+ /** @param mixed[] $projectData */
+ private function buildAndSaveProject(array $projectData): void
+ {
+ $active = (bool) ($projectData['active'] ?? true);
+ $archived = (bool) ($projectData['archived'] ?? false);
+ $name = (string) ($projectData['name'] ?? '');
+ $shortName = (string) ($projectData['shortName'] ?? $name);
+ $slug = (string) ($projectData['slug'] ?? '');
+ $docsSlug = (string) ($projectData['docsSlug'] ?? $slug);
+ $composerPackageName = (string) ($projectData['composerPackageName'] ?? '');
+ $repositoryName = (string) ($projectData['repositoryName'] ?? '');
+ $integration = (bool) ($projectData['integration'] ?? false);
+ $integrationFor = (string) ($projectData['integrationFor'] ?? '');
+ $docsRepositoryName = (string) ($projectData['docsRepositoryName'] ?? $repositoryName);
+ $docsPath = (string) ($projectData['docsPath'] ?? '/docs');
+ $codePath = (string) ($projectData['codePath'] ?? '/lib');
+ $description = (string) ($projectData['description'] ?? '');
+ $keywords = $projectData['keywords'] ?? [];
+
+ $versions = new ArrayCollection();
+ foreach ($projectData['versions'] ?? [] as $version) {
+ $projectVersion = new ProjectVersion($version);
+
+ foreach ($version['tags'] ?? [] as $tag) {
+ $tag = new Tag($tag['name'], new DateTimeImmutable($tag['date']));
+ $projectVersion->addTag($tag);
+ }
+
+ $tagVersion = $projectVersion->getLatestTag()?->getName();
+ if (isset($projectData['versionsGreaterThan']) && $tagVersion !== null && version_compare($projectData['versionsGreaterThan'], $tagVersion, '>')) {
+ continue;
+ }
+
+ foreach ($version['docsLanguages'] ?? [] as $language) {
+ $rstLanguage = new RSTLanguage($language['code'], $language['path']);
+ $projectVersion->addDocsLanguage($rstLanguage);
+ }
+
+ $this->entityManager->persist($projectVersion);
+
+ $versions->add($projectVersion);
+ }
+
+ $projectIntegrationType = null;
+ if ($integration) {
+ $projectIntegrationType = new ProjectIntegrationType(...$projectData['integrationType']);
+
+ $this->entityManager->persist($projectIntegrationType);
+ }
+
+ $projectStats = new ProjectStats(
+ (int) ($projectData['packagistData']['package']['github_stars'] ?? 0),
+ (int) ($projectData['packagistData']['package']['github_watchers'] ?? 0),
+ (int) ($projectData['packagistData']['package']['github_forks'] ?? 0),
+ (int) ($projectData['packagistData']['package']['github_open_issues'] ?? 0),
+ (int) ($projectData['packagistData']['package']['dependents'] ?? 0),
+ (int) ($projectData['packagistData']['package']['suggesters'] ?? 0),
+ (int) ($projectData['packagistData']['package']['downloads']['total'] ?? 0),
+ (int) ($projectData['packagistData']['package']['downloads']['monthly'] ?? 0),
+ (int) ($projectData['packagistData']['package']['downloads']['daily'] ?? 0),
+ );
+ $this->entityManager->persist($projectStats);
+
+ $project = new Project(
+ $projectStats,
+ $active,
+ $archived,
+ $name,
+ $shortName,
+ $slug,
+ $docsSlug,
+ $composerPackageName,
+ $repositoryName,
+ $integrationFor,
+ $docsRepositoryName,
+ $docsPath,
+ $codePath,
+ $description,
+ $projectIntegrationType,
+ $integration,
+ $keywords,
+ $versions,
+ );
+
+ $this->entityManager->persist($project);
+ $this->entityManager->flush();
+ }
+}
diff --git a/lib/DataSources/Projects.php b/lib/DataSources/Projects.php
index de5b0bd4..37c189ae 100644
--- a/lib/DataSources/Projects.php
+++ b/lib/DataSources/Projects.php
@@ -4,21 +4,232 @@
namespace Doctrine\Website\DataSources;
-use Doctrine\Website\DataBuilder\ProjectDataBuilder;
-use Doctrine\Website\DataBuilder\WebsiteDataReader;
+use Doctrine\Website\Docs\RST\RSTLanguage;
+use Doctrine\Website\Docs\RST\RSTLanguagesDetector;
+use Doctrine\Website\Git\Tag;
+use Doctrine\Website\Projects\GetProjectPackagistData;
+use Doctrine\Website\Projects\ProjectDataReader;
+use Doctrine\Website\Projects\ProjectDataRepository;
+use Doctrine\Website\Projects\ProjectGitSyncer;
+use Doctrine\Website\Projects\ProjectVersionsReader;
+
+use function array_filter;
+use function array_map;
+use function array_replace;
+use function count;
+use function end;
+use function strnatcmp;
+use function usort;
final readonly class Projects implements DataSource
{
+ private const DEFAULTS = [
+ 'active' => true,
+ 'archived' => false,
+ 'integration' => false,
+ ];
+
public function __construct(
- private WebsiteDataReader $dataReader,
+ private ProjectDataRepository $projectDataRepository,
+ private ProjectGitSyncer $projectGitSyncer,
+ private ProjectDataReader $projectDataReader,
+ private ProjectVersionsReader $projectVersionsReader,
+ private RSTLanguagesDetector $rstLanguagesDetector,
+ private GetProjectPackagistData $getProjectPackagistData,
+ private string $projectsDir,
) {
}
/** @return mixed[][] */
public function getSourceRows(): array
{
- return $this->dataReader
- ->read(ProjectDataBuilder::DATA_FILE)
- ->getData();
+ $repositoryNames = $this->projectDataRepository->getProjectRepositoryNames();
+
+ return array_map(function (string $repositoryName): array {
+ return $this->buildProjectData($repositoryName);
+ }, $repositoryNames);
+ }
+
+ /** @return mixed[] */
+ private function buildProjectData(string $repositoryName): array
+ {
+ // checkout master branch
+ $this->projectGitSyncer->checkoutDefaultBranch($repositoryName);
+
+ $projectData = array_replace(
+ self::DEFAULTS,
+ $this->projectDataReader->read($repositoryName),
+ );
+
+ $projectData['versions'] = $this->buildProjectVersions(
+ $repositoryName,
+ $projectData,
+ );
+
+ $projectData['packagistData'] = $this->getProjectPackagistData->__invoke(
+ $projectData['composerPackageName'],
+ );
+
+ return $projectData;
+ }
+
+ /**
+ * @param mixed[] $projectData
+ *
+ * @return mixed[]
+ */
+ private function buildProjectVersions(string $repositoryName, array $projectData): array
+ {
+ $projectVersions = $this->readProjectVersionsFromGit($repositoryName);
+
+ $this->applyConfiguredProjectVersions($projectVersions, $projectData);
+
+ $this->sortProjectVersions($projectVersions);
+
+ $this->prepareProjectVersions(
+ $repositoryName,
+ $projectVersions,
+ $projectData,
+ );
+
+ return $projectVersions;
+ }
+
+ /** @return mixed[] */
+ private function readProjectVersionsFromGit(string $repositoryName): array
+ {
+ $repositoryPath = $this->projectsDir . '/' . $repositoryName;
+
+ $projectVersions = $this->projectVersionsReader->readProjectVersions($repositoryPath);
+
+ // fix this, we shouldn't have null branch names at this point. Fix it further upstream
+ return array_filter($projectVersions, static function (array $projectVersion): bool {
+ return count($projectVersion['tags']) > 0;
+ });
+ }
+
+ /**
+ * @param mixed[] $projectVersions
+ * @param mixed[] $projectData
+ *
+ * @return mixed[]
+ */
+ private function applyConfiguredProjectVersions(
+ array &$projectVersions,
+ array $projectData,
+ ): array {
+ foreach ($projectVersions as $key => $projectVersion) {
+ $configured = false;
+
+ foreach ($projectData['versions'] as $k => $version) {
+ if ($this->containsSameProjectVersion($projectVersion, $version)) {
+ $version['tags'] = $projectVersion['tags'];
+
+ $version['branchName'] = $projectVersion['branchName'];
+
+ $projectVersions[$key] = $version;
+
+ unset($projectData['versions'][$k]);
+
+ $configured = true;
+
+ break;
+ }
+ }
+
+ if ($configured !== false) {
+ continue;
+ }
+
+ $projectVersions[$key]['maintained'] = false;
+ }
+
+ foreach ($projectData['versions'] as $projectVersion) {
+ $projectVersions[] = $projectVersion;
+ }
+
+ return $projectVersions;
+ }
+
+ /**
+ * @param mixed[] $a
+ * @param mixed[] $b
+ */
+ private function containsSameProjectVersion(array $a, array $b): bool
+ {
+ if ($a['name'] === $b['name']) {
+ return true;
+ }
+
+ if (! isset($b['branchName'])) {
+ return false;
+ }
+
+ return $a['branchName'] === $b['branchName'];
+ }
+
+ /**
+ * @param mixed[] $projectVersions
+ * @param mixed[] $projectData
+ *
+ * @return mixed[]
+ */
+ private function prepareProjectVersions(
+ string $repositoryName,
+ array &$projectVersions,
+ array $projectData,
+ ): array {
+ $docsRepositoryName = $projectData['docsRepositoryName'] ?? $projectData['repositoryName'];
+
+ $docsDir = $this->projectsDir . '/' . $docsRepositoryName . $projectData['docsPath'];
+
+ foreach ($projectVersions as $key => $projectVersion) {
+ if (! isset($projectVersion['branchName'])) {
+ $this->projectGitSyncer->checkoutTag(
+ $docsRepositoryName,
+ end($projectVersion['tags'])->getName(),
+ );
+ } else {
+ $this->projectGitSyncer->checkoutBranch(
+ $docsRepositoryName,
+ $projectVersion['branchName'],
+ );
+ }
+
+ $docsLanguages = array_map(static function (RSTLanguage $language): array {
+ return [
+ 'code' => $language->getCode(),
+ 'path' => $language->getPath(),
+ ];
+ }, $this->rstLanguagesDetector->detectLanguages($docsDir));
+
+ $projectVersions[$key]['hasDocs'] = count($docsLanguages) > 0;
+ $projectVersions[$key]['docsLanguages'] = $docsLanguages;
+
+ if (! isset($projectVersion['tags'])) {
+ continue;
+ }
+
+ $projectVersions[$key]['tags'] = array_map(static function (Tag $tag): array {
+ return [
+ 'name' => $tag->getName(),
+ 'date' => $tag->getDate()->format('Y-m-d H:i:s'),
+ ];
+ }, $projectVersion['tags']);
+ }
+
+ // switch back to master
+ $this->projectGitSyncer->checkoutDefaultBranch($repositoryName);
+
+ return $projectVersions;
+ }
+
+ /** @param mixed[] $projectVersions */
+ private function sortProjectVersions(array &$projectVersions): void
+ {
+ // sort by name so newest versions are first
+ usort($projectVersions, static function (array $a, array $b): int {
+ return strnatcmp($b['name'], $a['name']);
+ });
}
}
diff --git a/lib/Docs/RST/RSTLanguage.php b/lib/Docs/RST/RSTLanguage.php
index 2e9e514b..c625a897 100644
--- a/lib/Docs/RST/RSTLanguage.php
+++ b/lib/Docs/RST/RSTLanguage.php
@@ -4,11 +4,25 @@
namespace Doctrine\Website\Docs\RST;
-final readonly class RSTLanguage
+use Doctrine\ORM\Mapping as ORM;
+use Doctrine\Website\Model\ProjectVersion;
+
+#[ORM\Entity]
+final class RSTLanguage
{
+ #[ORM\Id]
+ #[ORM\GeneratedValue]
+ #[ORM\Column(type: 'integer')]
+ private int|null $id = null;
+
+ #[ORM\ManyToOne(targetEntity: ProjectVersion::class, inversedBy: 'docsLanguages')]
+ private ProjectVersion $projectVersion;
+
public function __construct(
- private string $code,
- private string $path,
+ #[ORM\Column(type: 'string')]
+ private readonly string $code,
+ #[ORM\Column(type: 'string')]
+ private readonly string $path,
) {
}
@@ -21,4 +35,14 @@ public function getPath(): string
{
return $this->path;
}
+
+ public function setProjectVersion(ProjectVersion $version): void
+ {
+ $this->projectVersion = $version;
+ }
+
+ public function getProjectVersion(): ProjectVersion
+ {
+ return $this->projectVersion;
+ }
}
diff --git a/lib/Git/Tag.php b/lib/Git/Tag.php
index 9f47aa48..785fbf44 100644
--- a/lib/Git/Tag.php
+++ b/lib/Git/Tag.php
@@ -5,13 +5,16 @@
namespace Doctrine\Website\Git;
use DateTimeImmutable;
+use Doctrine\ORM\Mapping as ORM;
+use Doctrine\Website\Model\ProjectVersion;
use function ltrim;
use function stripos;
use function strpos;
use function strtoupper;
-final readonly class Tag
+#[ORM\Entity]
+final class Tag
{
private const ALPHA = 'alpha';
private const BETA = 'beta';
@@ -27,9 +30,19 @@
private const COMPOSER_EPOCH = '2011-09-25';
+ #[ORM\Id]
+ #[ORM\GeneratedValue]
+ #[ORM\Column(type: 'integer')]
+ private int|null $id = null;
+
+ #[ORM\ManyToOne(targetEntity: ProjectVersion::class, inversedBy: 'tags')]
+ private ProjectVersion $projectVersion;
+
public function __construct(
- private string $name,
- private DateTimeImmutable $date,
+ #[ORM\Column(type: 'string')]
+ private readonly string $name,
+ #[ORM\Column(type: 'datetime_immutable')]
+ private readonly DateTimeImmutable $date,
) {
}
@@ -87,4 +100,14 @@ public function getStability(): string
return self::STABLE;
}
+
+ public function setProjectVersion(ProjectVersion $version): void
+ {
+ $this->projectVersion = $version;
+ }
+
+ public function getProjectVersion(): ProjectVersion
+ {
+ return $this->projectVersion;
+ }
}
diff --git a/lib/Hydrators/ProjectHydrator.php b/lib/Hydrators/ProjectHydrator.php
deleted file mode 100644
index 39e9d376..00000000
--- a/lib/Hydrators/ProjectHydrator.php
+++ /dev/null
@@ -1,99 +0,0 @@
-
- */
-final class ProjectHydrator extends ModelHydrator
-{
- /** @return class-string */
- protected function getClassName(): string
- {
- return Project::class;
- }
-
- /** @param mixed[] $data */
- protected function doHydrate(array $data): void
- {
- $this->active = (bool) ($data['active'] ?? true);
- $this->archived = (bool) ($data['archived'] ?? false);
- $this->name = (string) ($data['name'] ?? '');
- $this->shortName = (string) ($data['shortName'] ?? $this->name);
- $this->slug = (string) ($data['slug'] ?? '');
- $this->docsSlug = (string) ($data['docsSlug'] ?? $this->slug);
- $this->composerPackageName = (string) ($data['composerPackageName'] ?? '');
- $this->repositoryName = (string) ($data['repositoryName'] ?? '');
- $this->isIntegration = (bool) ($data['integration'] ?? false);
- $this->integrationFor = (string) ($data['integrationFor'] ?? '');
- $this->docsRepositoryName = (string) ($data['docsRepositoryName'] ?? $this->repositoryName);
- $this->docsPath = (string) ($data['docsPath'] ?? '/docs');
- $this->codePath = (string) ($data['codePath'] ?? '/lib');
- $this->description = (string) ($data['description'] ?? '');
- $this->keywords = $data['keywords'] ?? [];
-
- if (! isset($data['versions'])) {
- return;
- }
-
- $versions = [];
-
- foreach ($data['versions'] as $version) {
- $projectVersion = $version instanceof ProjectVersion
- ? $version
- : new ProjectVersion($version);
-
- $tagVersion = $projectVersion->getLatestTag()?->getName();
- if (isset($data['versionsGreaterThan']) && $tagVersion !== null && version_compare($data['versionsGreaterThan'], $tagVersion, '>')) {
- continue;
- }
-
- $versions[] = $projectVersion;
- }
-
- $this->versions = $versions;
-
- if ($this->isIntegration) {
- $this->projectIntegrationType = new ProjectIntegrationType($data['integrationType']);
- }
-
- $this->projectStats = new ProjectStats(
- (int) ($data['packagistData']['package']['github_stars'] ?? 0),
- (int) ($data['packagistData']['package']['github_watchers'] ?? 0),
- (int) ($data['packagistData']['package']['github_forks'] ?? 0),
- (int) ($data['packagistData']['package']['github_open_issues'] ?? 0),
- (int) ($data['packagistData']['package']['dependents'] ?? 0),
- (int) ($data['packagistData']['package']['suggesters'] ?? 0),
- (int) ($data['packagistData']['package']['downloads']['total'] ?? 0),
- (int) ($data['packagistData']['package']['downloads']['monthly'] ?? 0),
- (int) ($data['packagistData']['package']['downloads']['daily'] ?? 0),
- );
- }
-}
diff --git a/lib/Model/Project.php b/lib/Model/Project.php
index 1ccf2997..58d0d06a 100644
--- a/lib/Model/Project.php
+++ b/lib/Model/Project.php
@@ -5,57 +5,66 @@
namespace Doctrine\Website\Model;
use Closure;
-use Doctrine\SkeletonMapper\Mapping\ClassMetadataInterface;
-use Doctrine\SkeletonMapper\Mapping\LoadMetadataInterface;
+use Doctrine\Common\Collections\Collection;
+use Doctrine\ORM\Mapping as ORM;
+use Doctrine\Website\Repositories\ProjectRepository;
use InvalidArgumentException;
use function array_filter;
use function array_values;
use function sprintf;
-class Project implements LoadMetadataInterface
+#[ORM\Entity(repositoryClass: ProjectRepository::class)]
+class Project
{
- private ProjectIntegrationType|null $projectIntegrationType = null;
-
- private ProjectStats $projectStats;
-
- private bool $active;
-
- private bool $archived;
-
- private string $name;
-
- private string $shortName;
-
- private string $slug;
-
- private string $docsSlug;
-
- private string $composerPackageName;
-
- private string $repositoryName;
-
- private bool $isIntegration = false;
-
- private string $integrationFor;
-
- private string $docsRepositoryName;
-
- private string $docsPath;
-
- private string $codePath;
-
- private string $description;
-
- /** @var string[] */
- private array $keywords = [];
-
- /** @var ProjectVersion[] */
- private array $versions = [];
-
- public static function loadMetadata(ClassMetadataInterface $metadata): void
- {
- $metadata->setIdentifier(['slug']);
+ /**
+ * @param Collection $versions
+ * @param string[] $keywords
+ */
+ public function __construct(
+ #[ORM\OneToOne(targetEntity: ProjectStats::class, fetch: 'EAGER', orphanRemoval: true)]
+ #[ORM\JoinColumn(name: 'projectStats', referencedColumnName: 'id')]
+ private ProjectStats $projectStats,
+ #[ORM\Column(type: 'boolean')]
+ private bool $active,
+ #[ORM\Column(type: 'boolean')]
+ private bool $archived,
+ #[ORM\Column(type: 'string')]
+ private string $name,
+ #[ORM\Column(type: 'string')]
+ private string $shortName,
+ #[ORM\Id]
+ #[ORM\Column(type: 'string')]
+ private string $slug,
+ #[ORM\Column(type: 'string')]
+ private string $docsSlug,
+ #[ORM\Column(type: 'string')]
+ private string $composerPackageName,
+ #[ORM\Column(type: 'string')]
+ private string $repositoryName,
+ #[ORM\Column(type: 'string')]
+ private string $integrationFor,
+ #[ORM\Column(type: 'string')]
+ private string $docsRepositoryName,
+ #[ORM\Column(type: 'string')]
+ private string $docsPath,
+ #[ORM\Column(type: 'string')]
+ private string $codePath,
+ #[ORM\Column(type: 'string')]
+ private string $description,
+ #[ORM\OneToOne(targetEntity: ProjectIntegrationType::class, fetch: 'EAGER', orphanRemoval: true)]
+ #[ORM\JoinColumn(name: 'projectIntegrationType', referencedColumnName: 'id', nullable: true)]
+ private ProjectIntegrationType|null $projectIntegrationType,
+ #[ORM\Column(type: 'boolean')]
+ private bool $integration,
+ #[ORM\Column(type: 'simple_array')]
+ private array $keywords,
+ #[ORM\OneToMany(targetEntity: ProjectVersion::class, fetch: 'EAGER', mappedBy: 'project', orphanRemoval: true)]
+ private Collection $versions,
+ ) {
+ foreach ($this->versions as $version) {
+ $version->setProject($this);
+ }
}
public function getProjectIntegrationType(): ProjectIntegrationType|null
@@ -110,7 +119,7 @@ public function getRepositoryName(): string
public function isIntegration(): bool
{
- return $this->isIntegration;
+ return $this->integration;
}
public function getIntegrationFor(): string
@@ -151,11 +160,13 @@ public function getKeywords(): array
*/
public function getVersions(Closure|null $filter = null): array
{
+ $versions = $this->versions->getValues();
+
if ($filter !== null) {
- return array_values(array_filter($this->versions, $filter));
+ return array_values(array_filter($versions, $filter));
}
- return $this->versions;
+ return $versions;
}
/** @return ProjectVersion[] */
diff --git a/lib/Model/ProjectIntegrationType.php b/lib/Model/ProjectIntegrationType.php
index 8472095f..25021d7a 100644
--- a/lib/Model/ProjectIntegrationType.php
+++ b/lib/Model/ProjectIntegrationType.php
@@ -4,20 +4,24 @@
namespace Doctrine\Website\Model;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ORM\Entity]
class ProjectIntegrationType
{
- private string $name;
-
- private string $url;
-
- private string $icon;
-
- /** @param mixed[] $projectIntegrationType */
- public function __construct(array $projectIntegrationType)
- {
- $this->name = (string) ($projectIntegrationType['name'] ?? '');
- $this->url = (string) ($projectIntegrationType['url'] ?? '');
- $this->icon = (string) ($projectIntegrationType['icon'] ?? '');
+ #[ORM\Id]
+ #[ORM\GeneratedValue]
+ #[ORM\Column(type: 'integer')]
+ private int|null $id = null;
+
+ public function __construct(
+ #[ORM\Column(type: 'string')]
+ private string $name = '',
+ #[ORM\Column(type: 'string')]
+ private string $url = '',
+ #[ORM\Column(type: 'string')]
+ private string $icon = '',
+ ) {
}
public function getName(): string
diff --git a/lib/Model/ProjectStats.php b/lib/Model/ProjectStats.php
index b8a5a9e3..73154d42 100644
--- a/lib/Model/ProjectStats.php
+++ b/lib/Model/ProjectStats.php
@@ -4,17 +4,34 @@
namespace Doctrine\Website\Model;
+use Doctrine\ORM\Mapping as ORM;
+
+#[ORM\Entity]
final class ProjectStats
{
+ #[ORM\Id]
+ #[ORM\GeneratedValue]
+ #[ORM\Column(type: 'integer')]
+ private int|null $id = null;
+
public function __construct(
+ #[ORM\Column(type: 'integer')]
private int $githubStars = 0,
+ #[ORM\Column(type: 'integer')]
private int $githubWatchers = 0,
+ #[ORM\Column(type: 'integer')]
private int $githubForks = 0,
+ #[ORM\Column(type: 'integer')]
private int $githubOpenIssues = 0,
+ #[ORM\Column(type: 'integer')]
private int $dependents = 0,
+ #[ORM\Column(type: 'integer')]
private int $suggesters = 0,
+ #[ORM\Column(type: 'integer')]
private int $totalDownloads = 0,
+ #[ORM\Column(type: 'integer')]
private int $monthlyDownloads = 0,
+ #[ORM\Column(type: 'integer')]
private int $dailyDownloads = 0,
) {
}
diff --git a/lib/Model/ProjectVersion.php b/lib/Model/ProjectVersion.php
index bd57a741..9a82fdd8 100644
--- a/lib/Model/ProjectVersion.php
+++ b/lib/Model/ProjectVersion.php
@@ -4,45 +4,65 @@
namespace Doctrine\Website\Model;
-use DateTimeImmutable;
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\Common\Collections\Collection;
+use Doctrine\ORM\Mapping as ORM;
use Doctrine\Website\Docs\RST\RSTLanguage;
use Doctrine\Website\Git\Tag;
use InvalidArgumentException;
-use function array_map;
use function array_merge;
use function count;
-use function end;
use function sprintf;
+#[ORM\Entity]
class ProjectVersion
{
private const UPCOMING = 'upcoming';
private const STABLE = 'stable';
private const UNMAINTAINED = 'unmaintained';
+ #[ORM\Id]
+ #[ORM\GeneratedValue]
+ #[ORM\Column(type: 'integer')]
+ private int|null $id = null;
+
+ #[ORM\ManyToOne(targetEntity: Project::class, inversedBy: 'versions')]
+ #[ORM\JoinColumn(referencedColumnName: 'slug')]
+ private Project $project;
+
+ #[ORM\Column(type: 'string')]
private string $name;
+ #[ORM\Column(type: 'string', nullable: true)]
private string|null $branchName;
+ #[ORM\Column(type: 'string')]
private string $slug;
- private bool $current = false;
+ #[ORM\Column(type: 'boolean')]
+ private bool $current;
- private bool $maintained = true;
+ #[ORM\Column(type: 'boolean')]
+ private bool $maintained;
- private bool $upcoming = false;
+ #[ORM\Column(type: 'boolean')]
+ private bool $upcoming;
- private bool $hasDocs = true;
+ #[ORM\Column(type: 'boolean')]
+ private bool $hasDocs;
- /** @var RSTLanguage[] */
- private array $docsLanguages = [];
+ /** @var Collection */
+ #[ORM\OneToMany(targetEntity: RSTLanguage::class, fetch: 'EAGER', mappedBy: 'projectVersion', orphanRemoval: true, cascade: ['persist'])]
+ private Collection $docsLanguages;
/** @var string[] */
+ #[ORM\Column(type: 'simple_array', nullable: true)]
private array $aliases;
- /** @var Tag[] */
- private array $tags;
+ /** @var Collection */
+ #[ORM\OneToMany(targetEntity: Tag::class, fetch: 'EAGER', mappedBy: 'projectVersion', orphanRemoval: true, cascade: ['persist'])]
+ private Collection $tags;
/** @param mixed[] $version */
public function __construct(array $version)
@@ -54,16 +74,10 @@ public function __construct(array $version)
$this->maintained = (bool) ($version['maintained'] ?? true);
$this->upcoming = (bool) ($version['upcoming'] ?? false);
$this->hasDocs = (bool) ($version['hasDocs'] ?? true);
+ $this->aliases = $version['aliases'] ?? [];
- $this->docsLanguages = array_map(static function (array $language): RSTLanguage {
- return new RSTLanguage($language['code'], $language['path']);
- }, $version['docsLanguages'] ?? []);
-
- $this->tags = array_map(static function (array $tag): Tag {
- return new Tag($tag['name'], new DateTimeImmutable($tag['date']));
- }, $version['tags'] ?? []);
-
- $this->aliases = $version['aliases'] ?? [];
+ $this->docsLanguages = new ArrayCollection();
+ $this->tags = new ArrayCollection();
if (! $this->current) {
return;
@@ -124,10 +138,16 @@ public function hasDocs(): bool
return $this->hasDocs;
}
+ public function addDocsLanguage(RSTLanguage $docsLanguage): void
+ {
+ $docsLanguage->setProjectVersion($this);
+ $this->docsLanguages->add($docsLanguage);
+ }
+
/** @return RSTLanguage[] */
public function getDocsLanguages(): array
{
- return $this->docsLanguages;
+ return $this->docsLanguages->getValues();
}
/** @return string[] */
@@ -136,10 +156,16 @@ public function getAliases(): array
return $this->aliases;
}
+ public function addTag(Tag $tag): void
+ {
+ $tag->setProjectVersion($this);
+ $this->tags->add($tag);
+ }
+
/** @return Tag[] */
public function getTags(): array
{
- return $this->tags;
+ return $this->tags->getValues();
}
public function getTag(string $slug): Tag
@@ -155,12 +181,12 @@ public function getTag(string $slug): Tag
public function getFirstTag(): Tag|null
{
- return $this->tags[0] ?? null;
+ return $this->tags->first() ?: null;
}
public function getLatestTag(): Tag|null
{
- $latestTag = end($this->tags);
+ $latestTag = $this->tags->last();
if ($latestTag === false) {
return null;
@@ -214,4 +240,14 @@ public function getStabilityColor(string|null $stability = null): string
return $map[$stability] ?? 'secondary';
}
+
+ public function setProject(Project $project): void
+ {
+ $this->project = $project;
+ }
+
+ public function getProject(): Project
+ {
+ return $this->project;
+ }
}
diff --git a/lib/Repositories/ProjectRepository.php b/lib/Repositories/ProjectRepository.php
index 4c065f86..3c6d0f42 100644
--- a/lib/Repositories/ProjectRepository.php
+++ b/lib/Repositories/ProjectRepository.php
@@ -4,7 +4,7 @@
namespace Doctrine\Website\Repositories;
-use Doctrine\SkeletonMapper\ObjectRepository\BasicObjectRepository;
+use Doctrine\ORM\EntityRepository;
use Doctrine\Website\Model\Project;
use InvalidArgumentException;
@@ -12,19 +12,10 @@
/**
* @template T of Project
- * @template-extends BasicObjectRepository
+ * @template-extends EntityRepository
*/
-class ProjectRepository extends BasicObjectRepository
+class ProjectRepository extends EntityRepository
{
- /** @return Project[] */
- public function findAll(): array
- {
- /** @var Project[] $projects */
- $projects = parent::findAll();
-
- return $projects;
- }
-
public function findOneBySlug(string $slug): Project
{
$project = $this->findOneBy(['slug' => $slug]);
diff --git a/lib/WebsiteBuilder.php b/lib/WebsiteBuilder.php
index f8683f35..3c4fd62d 100644
--- a/lib/WebsiteBuilder.php
+++ b/lib/WebsiteBuilder.php
@@ -43,7 +43,6 @@ public function __construct(
private readonly SourceFileRepository $sourceFileRepository,
private readonly SourceFilesBuilder $sourceFilesBuilder,
private readonly string $rootDir,
- private readonly string $cacheDir,
private readonly string $webpackBuildDir,
) {
}
@@ -72,8 +71,6 @@ public function build(
$this->createProjectVersionAliases($buildDir);
- $this->copyWebsiteBuildData($output, $buildDir);
-
$output->writeln(' - done');
}
@@ -149,20 +146,6 @@ private function createProjectVersionAliases(string $buildDir): void
}
}
- private function copyWebsiteBuildData(OutputInterface $output, string $buildDir): void
- {
- $from = $this->cacheDir . '/data';
- $to = $buildDir . '/website-data';
-
- $output->writeln(sprintf(
- ' - copying website build data from %s to %s.',
- $from,
- $to,
- ));
-
- $this->filesystem->mirror($from, $to);
- }
-
private function createDocsProjectVersionAlias(
string $buildDir,
Project $project,
diff --git a/phpstan.neon.dist b/phpstan.neon.dist
index 2c10f7fe..6cac6405 100644
--- a/phpstan.neon.dist
+++ b/phpstan.neon.dist
@@ -13,7 +13,7 @@ parameters:
message: "#While loop condition is always true#"
path: "lib/Commands/BuildWebsiteCommand.php"
count: 1
- - # Refactor class and remove this error
+ - # Will be removed once hydrators are completely gone
message: "#is never written, only read#"
path: "lib/Model/*.php"
- # Temporary final classes in tests are covered by nunomaduro/mock-final-classes until the refactorings start
@@ -23,5 +23,6 @@ parameters:
message: "#contains unresolvable type#"
path: "tests/"
-
- message: "#Parameter \\#4 \\$metadataFactory#"
- path: "tests/Hydrators/Hydrators.php"
+ message: "#::\\$id is never read, only written#"
+ - # Will be removed once hydrators are completely gone
+ message: "/Parameter #4 \\$metadataFactory/"
diff --git a/tests/DataBuilder/ProjectDataBuilderTest.php b/tests/DataBuilder/ProjectDataBuilderTest.php
deleted file mode 100644
index 6a5d9d7f..00000000
--- a/tests/DataBuilder/ProjectDataBuilderTest.php
+++ /dev/null
@@ -1,212 +0,0 @@
-projectDataRepository->expects(self::once())
- ->method('getProjectRepositoryNames')
- ->willReturn(['orm']);
-
- $this->projectGitSyncer->expects(self::any())
- ->method('checkoutDefaultBranch')
- ->with('orm');
-
- $this->projectDataReader->expects(self::once())
- ->method('read')
- ->with('orm')
- ->willReturn([
- 'composerPackageName' => 'doctrine/orm',
- 'repositoryName' => 'orm',
- 'docsPath' => '/docs',
- 'versions' => [
- [
- 'name' => '1.0',
- 'branchName' => null,
- ],
- [
- 'name' => '1.1',
- 'branchName' => '1.1',
- ],
- ['name' => '1.2'],
- ],
- ]);
-
- $this->projectVersionsReader->expects(self::once())
- ->method('readProjectVersions')
- ->with('/path/to/projects/orm')
- ->willReturn([
- [
- 'name' => '1.0',
- 'branchName' => null,
- 'tags' => [
- new Tag('1.0.0', new DateTimeImmutable('2019-09-01')),
- new Tag('1.0.1', new DateTimeImmutable('2019-09-02')),
- ],
- ],
- [
- 'name' => '1.1',
- 'branchName' => '1.1',
- 'tags' => [
- new Tag('1.1.0', new DateTimeImmutable('2019-09-03')),
- new Tag('1.1.1', new DateTimeImmutable('2019-09-04')),
- ],
- ],
- [
- 'name' => '1.2',
- 'branchName' => null,
- 'tags' => [
- new Tag('1.2.0', new DateTimeImmutable('2019-09-05')),
- ],
- ],
- ]);
-
- $this->projectGitSyncer->expects(self::once())
- ->method('checkoutBranch')
- ->with('orm', '1.1');
-
- $this->rstLanguagesDetector->expects(self::exactly(3))
- ->method('detectLanguages')
- ->with('/path/to/projects/orm/docs')
- ->willReturnOnConsecutiveCalls(
- [
- new RSTLanguage('en', '/path/to/en'),
- ],
- [],
- [],
- );
-
- $this->projectGitSyncer->expects(self::exactly(2))
- ->method('checkoutTag')
- ->willReturnMap([
- ['orm', '1.0.1', null],
- ['orm', '1.2.0', null],
- ]);
-
- $this->getProjectPackagistData->expects(self::once())
- ->method('__invoke')
- ->with('doctrine/orm')
- ->willReturn(['package' => []]);
-
- $data = $this->projectDataBuilder->build()->getData();
-
- $expected = [
- [
- 'active' => true,
- 'archived' => false,
- 'integration' => false,
- 'composerPackageName' => 'doctrine/orm',
- 'repositoryName' => 'orm',
- 'docsPath' => '/docs',
- 'versions' => [
- [
- 'name' => '1.2',
- 'tags' => [
- [
- 'name' => '1.2.0',
- 'date' => '2019-09-05 00:00:00',
- ],
- ],
- 'branchName' => null,
- 'hasDocs' => true,
- 'docsLanguages' => [
- [
- 'code' => 'en',
- 'path' => '/path/to/en',
- ],
- ],
- ],
- [
- 'name' => '1.1',
- 'branchName' => '1.1',
- 'tags' => [
- [
- 'name' => '1.1.0',
- 'date' => '2019-09-03 00:00:00',
- ],
- [
- 'name' => '1.1.1',
- 'date' => '2019-09-04 00:00:00',
- ],
- ],
- 'hasDocs' => false,
- 'docsLanguages' => [],
- ],
- [
- 'name' => '1.0',
- 'branchName' => null,
- 'tags' => [
- [
- 'name' => '1.0.0',
- 'date' => '2019-09-01 00:00:00',
- ],
- [
- 'name' => '1.0.1',
- 'date' => '2019-09-02 00:00:00',
- ],
- ],
- 'hasDocs' => false,
- 'docsLanguages' => [],
- ],
- ],
- 'packagistData' => ['package' => []],
- ],
- ];
-
- self::assertSame($expected, $data);
- }
-
- protected function setUp(): void
- {
- $this->projectDataRepository = $this->createMock(ProjectDataRepository::class);
- $this->projectGitSyncer = $this->createMock(ProjectGitSyncer::class);
- $this->projectDataReader = $this->createMock(ProjectDataReader::class);
- $this->projectVersionsReader = $this->createMock(ProjectVersionsReader::class);
- $this->rstLanguagesDetector = $this->createMock(RSTLanguagesDetector::class);
- $this->getProjectPackagistData = $this->createMock(GetProjectPackagistData::class);
- $this->projectsDir = '/path/to/projects';
-
- $this->projectDataBuilder = new ProjectDataBuilder(
- $this->projectDataRepository,
- $this->projectGitSyncer,
- $this->projectDataReader,
- $this->projectVersionsReader,
- $this->rstLanguagesDetector,
- $this->getProjectPackagistData,
- $this->projectsDir,
- );
- }
-}
diff --git a/tests/DataSources/DbPrefill/ProjectsTest.php b/tests/DataSources/DbPrefill/ProjectsTest.php
new file mode 100644
index 00000000..bdda7f12
--- /dev/null
+++ b/tests/DataSources/DbPrefill/ProjectsTest.php
@@ -0,0 +1,148 @@
+getEntityManager();
+ $repository = $entityManager->getRepository(Project::class);
+ $project = $repository->find('testproject');
+
+ assert($project instanceof Project);
+
+ $entityManager->remove($project);
+ $entityManager->flush();
+ }
+
+ public function testPopulate(): void
+ {
+ $projectFixture = __DIR__ . '/fixtures/projects.json';
+ $fixture = json_decode((string) file_get_contents($projectFixture), true);
+
+ $entityManager = $this->getEntityManager();
+
+ $dataSource = $this->createMock(DataSource::class);
+ $dataSource->method('getSourceRows')->willReturn($fixture);
+
+ $dbFill = new Projects($dataSource, $entityManager);
+ $dbFill->populate();
+
+ $this->assertProjectIsComplete($entityManager);
+ }
+
+ private function assertProjectIsComplete(EntityManagerInterface $entityManager): void
+ {
+ $entityManager->clear();
+
+ $repository = $entityManager->getRepository(Project::class);
+ $project = $repository->find('testproject');
+
+ assert($project instanceof Project);
+
+ self::assertSame('Testproject', $project->getName());
+ self::assertSame('testproject', $project->getSlug());
+ self::assertSame('Testproject', $project->getShortName());
+ self::assertTrue($project->isActive());
+ self::assertFalse($project->isArchived());
+ self::assertSame('doctrine-testproject', $project->getDocsSlug());
+ self::assertSame('testproject', $project->getDocsRepositoryName());
+ self::assertSame('/docs', $project->getDocsPath());
+ self::assertSame('/lib', $project->getCodePath());
+ self::assertSame('doctrine/testproject', $project->getComposerPackageName());
+ self::assertSame('testproject', $project->getRepositoryName());
+ self::assertFalse($project->isIntegration());
+ self::assertSame('', $project->getIntegrationFor());
+ self::assertSame('It\'s a testproject', $project->getDescription());
+ self::assertSame(['testproject', 'docblock', 'parser'], $project->getKeywords());
+ $this->assertProjectStats($project->getProjectStats());
+
+ $versions = $project->getVersions();
+ self::assertCount(1, $versions);
+ $this->assertVersion($versions[0]);
+ }
+
+ private function assertVersion(ProjectVersion $version): void
+ {
+ self::assertSame('2.0', $version->getName());
+ self::assertSame('2.0.x', $version->getBranchName());
+ self::assertSame('2.0', $version->getSlug());
+ self::assertTrue($version->isCurrent());
+ self::assertTrue($version->isMaintained());
+ self::assertTrue($version->hasDocs());
+ self::assertSame(['foo', 'current', 'stable'], $version->getAliases());
+
+ self::assertCount(1, $version->getTags());
+ $this->assertTag($version->getTag('2.0.0'));
+
+ $docsLanguages = $version->getDocsLanguages();
+ self::assertCount(1, $docsLanguages);
+ $this->assertDocsLanguage($docsLanguages[0]);
+ }
+
+ private function assertTag(Tag $tag): void
+ {
+ self::assertSame('2.0.0', $tag->getName());
+ self::assertSame('2.0.0', $tag->getDisplayName());
+ self::assertSame('2.0.0', $tag->getSlug());
+ self::assertSame(1671492263, $tag->getDate()->getTimestamp());
+ }
+
+ private function assertDocsLanguage(RSTLanguage $docsLanguage): void
+ {
+ self::assertSame('en', $docsLanguage->getCode());
+ self::assertSame('projects/testproject/docs/en', $docsLanguage->getPath());
+ }
+
+ private function assertProjectStats(ProjectStats $projectStats): void
+ {
+ self::assertSame(6729, $projectStats->getGithubStars());
+ self::assertSame(41, $projectStats->getGithubWatchers());
+ self::assertSame(236, $projectStats->getGithubForks());
+ self::assertSame(30, $projectStats->getGithubOpenIssues());
+ self::assertSame(2349, $projectStats->getDependents());
+ self::assertSame(74, $projectStats->getSuggesters());
+ self::assertSame(426454499, $projectStats->getTotalDownloads());
+ self::assertSame(6487217, $projectStats->getMonthlyDownloads());
+ self::assertSame(260080, $projectStats->getDailyDownloads());
+ }
+
+ private function getEntityManager(): EntityManagerInterface
+ {
+ $entityManager = $this->getContainer()->get(EntityManagerInterface::class);
+ assert($entityManager instanceof EntityManagerInterface);
+
+ return $entityManager;
+ }
+}
diff --git a/tests/DataSources/DbPrefill/fixtures/projects.json b/tests/DataSources/DbPrefill/fixtures/projects.json
new file mode 100644
index 00000000..2f4616d0
--- /dev/null
+++ b/tests/DataSources/DbPrefill/fixtures/projects.json
@@ -0,0 +1,201 @@
+[
+ {
+ "active": true,
+ "archived": false,
+ "integration": false,
+ "name": "Testproject",
+ "repositoryName": "testproject",
+ "docsPath": "/docs",
+ "codePath": "/lib",
+ "slug": "testproject",
+ "versionsGreaterThan": "1.0.1",
+ "versions": [
+ {
+ "name": "2.0",
+ "branchName": "2.0.x",
+ "aliases": [
+ "foo"
+ ],
+ "current": true,
+ "maintained": true,
+ "tags": [
+ {
+ "name": "2.0.0",
+ "date": "2022-12-19 18:24:23"
+ }
+ ],
+ "hasDocs": true,
+ "docsLanguages": [
+ {
+ "code": "en",
+ "path": "projects/testproject/docs/en"
+ }
+ ]
+ },
+ {
+ "name": "1.0",
+ "slug": "1.0",
+ "branchName": null,
+ "tags": [
+ {
+ "name": "v1.0",
+ "date": "2013-01-12 20:26:03"
+ }
+ ],
+ "maintained": false,
+ "hasDocs": false,
+ "docsLanguages": []
+ }
+ ],
+ "composerPackageName": "doctrine/testproject",
+ "description": "It's a testproject",
+ "keywords": [
+ "testproject",
+ "docblock",
+ "parser"
+ ],
+ "docsSlug": "doctrine-testproject",
+ "packagistData": {
+ "package": {
+ "name": "doctrine/testproject",
+ "description": "It's a testproject",
+ "time": "2013-01-12T19:24:37+00:00",
+ "maintainers": [
+ {
+ "name": "beberlei",
+ "avatar_url": "https://www.gravatar.com/avatar/75f5fb3ddda052e46f1daed314ae69ab?d=identicon"
+ }
+ ],
+ "versions": {
+ "2.0.0": {
+ "name": "doctrine/testproject",
+ "description": "It's a testproject",
+ "keywords": [
+ "testproject",
+ "parser",
+ "docblock"
+ ],
+ "homepage": "https://www.doctrine-project.org/projects/testproject.html",
+ "version": "2.0.0",
+ "version_normalized": "2.0.0.0",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "John Doe",
+ "email": "john@doe.dev",
+ "role": "Creator"
+ }
+ ],
+ "source": {
+ "url": "https://github.com/doctrine/testproject.git",
+ "type": "git",
+ "reference": "d02c9f3742044e17d5fa8d28d8402a2d95c33302"
+ },
+ "dist": {
+ "url": "https://api.github.com/repos/doctrine/testproject/zipball/d02c9f3742044e17d5fa8d28d8402a2d95c33302",
+ "type": "zip",
+ "shasum": "",
+ "reference": "d02c9f3742044e17d5fa8d28d8402a2d95c33302"
+ },
+ "type": "library",
+ "support": {
+ "issues": "https://github.com/doctrine/testproject/issues",
+ "source": "https://github.com/doctrine/testproject/tree/2.0.0"
+ },
+ "funding": [],
+ "time": "2022-12-19T18:17:20+00:00",
+ "autoload": {
+ "psr-4": {
+ "Doctrine\\Common\\Testproject\\": "lib/Doctrine/Common/Testproject"
+ }
+ },
+ "require": {
+ "php": "^7.2 || ^8.0",
+ "ext-tokenizer": "*",
+ "doctrine/lexer": "^2 || ^3",
+ "psr/cache": "^1 || ^2 || ^3"
+ },
+ "require-dev": {
+ "doctrine/cache": "^2.0",
+ "doctrine/coding-standard": "^10",
+ "phpstan/phpstan": "^1.8.0",
+ "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
+ "symfony/cache": "^5.4 || ^6",
+ "vimeo/psalm": "^4.10"
+ },
+ "suggest": {
+ "php": "PHP 8.0 or higher comes with attributes, a native replacement for testproject"
+ }
+ },
+ "v1.0": {
+ "name": "doctrine/testproject",
+ "description": "It's a testproject",
+ "keywords": [
+ "testproject",
+ "parser",
+ "docblock"
+ ],
+ "homepage": "http://www.doctrine-project.org",
+ "version": "v1.0",
+ "version_normalized": "1.0.0.0",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "John Doe",
+ "email": "john@doe.dev",
+ "role": "Creator"
+ }
+ ],
+ "source": {
+ "url": "https://github.com/doctrine/testproject.git",
+ "type": "git",
+ "reference": "fae359b3efd908e407a0105ff8956b5c94ddca8e"
+ },
+ "dist": {
+ "url": "https://api.github.com/repos/doctrine/testproject/zipball/fae359b3efd908e407a0105ff8956b5c94ddca8e",
+ "type": "zip",
+ "shasum": "",
+ "reference": "fae359b3efd908e407a0105ff8956b5c94ddca8e"
+ },
+ "type": "library",
+ "support": {
+ "source": "https://github.com/doctrine/testproject/tree/v1.0"
+ },
+ "time": "2013-01-12T19:23:32+00:00",
+ "autoload": {
+ "psr-0": {
+ "Doctrine\\Common\\Testproject\\": "lib/"
+ }
+ },
+ "require": {
+ "php": ">=5.3.2",
+ "doctrine/lexer": "1.*"
+ },
+ "require-dev": {
+ "doctrine/cache": "1.*"
+ }
+ }
+ },
+ "type": "library",
+ "repository": "https://github.com/doctrine/testproject",
+ "github_stars": 6729,
+ "github_watchers": 41,
+ "github_forks": 236,
+ "github_open_issues": 30,
+ "language": "PHP",
+ "dependents": 2349,
+ "suggesters": 74,
+ "downloads": {
+ "total": 426454499,
+ "monthly": 6487217,
+ "daily": 260080
+ },
+ "favers": 6768
+ }
+ }
+ }
+]
diff --git a/tests/DataSources/ProjectsTest.php b/tests/DataSources/ProjectsTest.php
index 00ed1928..b2b11572 100644
--- a/tests/DataSources/ProjectsTest.php
+++ b/tests/DataSources/ProjectsTest.php
@@ -4,56 +4,209 @@
namespace Doctrine\Website\Tests\DataSources;
-use Doctrine\Website\DataBuilder\ProjectDataBuilder;
-use Doctrine\Website\DataBuilder\WebsiteData;
-use Doctrine\Website\DataBuilder\WebsiteDataReader;
+use DateTimeImmutable;
use Doctrine\Website\DataSources\Projects;
+use Doctrine\Website\Docs\RST\RSTLanguage;
+use Doctrine\Website\Docs\RST\RSTLanguagesDetector;
+use Doctrine\Website\Git\Tag;
+use Doctrine\Website\Projects\GetProjectPackagistData;
+use Doctrine\Website\Projects\ProjectDataReader;
+use Doctrine\Website\Projects\ProjectDataRepository;
+use Doctrine\Website\Projects\ProjectGitSyncer;
+use Doctrine\Website\Projects\ProjectVersionsReader;
use Doctrine\Website\Tests\TestCase;
use PHPUnit\Framework\MockObject\MockObject;
class ProjectsTest extends TestCase
{
- private WebsiteDataReader&MockObject $dataReader;
+ private ProjectDataRepository&MockObject $projectDataRepository;
- private Projects $projects;
+ private ProjectGitSyncer&MockObject $projectGitSyncer;
- protected function setUp(): void
- {
- $this->dataReader = $this->createMock(WebsiteDataReader::class);
+ private ProjectDataReader&MockObject $projectDataReader;
- $this->projects = new Projects(
- $this->dataReader,
- );
- }
+ private ProjectVersionsReader&MockObject $projectVersionsReader;
+
+ private RSTLanguagesDetector&MockObject $rstLanguagesDetector;
+
+ private GetProjectPackagistData&MockObject $getProjectPackagistData;
+
+ private string $projectsDir;
- public function testGetSourceRows(): void
+ private Projects $dataSource;
+
+ public function testBuild(): void
{
+ $this->projectDataRepository->expects(self::once())
+ ->method('getProjectRepositoryNames')
+ ->willReturn(['orm']);
+
+ $this->projectGitSyncer->expects(self::exactly(2))
+ ->method('checkoutDefaultBranch')
+ ->with('orm');
+
+ $this->projectDataReader->expects(self::once())
+ ->method('read')
+ ->with('orm')
+ ->willReturn([
+ 'composerPackageName' => 'doctrine/orm',
+ 'repositoryName' => 'orm',
+ 'docsPath' => '/docs',
+ 'versions' => [
+ [
+ 'name' => '1.0',
+ 'branchName' => null,
+ ],
+ [
+ 'name' => '1.1',
+ 'branchName' => '1.1',
+ ],
+ ['name' => '1.2'],
+ ],
+ ]);
+
+ $this->projectVersionsReader->expects(self::once())
+ ->method('readProjectVersions')
+ ->with('/path/to/projects/orm')
+ ->willReturn([
+ [
+ 'name' => '1.0',
+ 'branchName' => null,
+ 'tags' => [
+ new Tag('1.0.0', new DateTimeImmutable('2019-09-01')),
+ new Tag('1.0.1', new DateTimeImmutable('2019-09-02')),
+ ],
+ ],
+ [
+ 'name' => '1.1',
+ 'branchName' => '1.1',
+ 'tags' => [
+ new Tag('1.1.0', new DateTimeImmutable('2019-09-03')),
+ new Tag('1.1.1', new DateTimeImmutable('2019-09-04')),
+ ],
+ ],
+ [
+ 'name' => '1.2',
+ 'branchName' => null,
+ 'tags' => [
+ new Tag('1.2.0', new DateTimeImmutable('2019-09-05')),
+ ],
+ ],
+ ]);
+
+ $this->projectGitSyncer->expects(self::once())
+ ->method('checkoutBranch')
+ ->with('orm', '1.1');
+
+ $this->rstLanguagesDetector->expects(self::exactly(3))
+ ->method('detectLanguages')
+ ->with('/path/to/projects/orm/docs')
+ ->willReturnOnConsecutiveCalls(
+ [
+ new RSTLanguage('en', '/path/to/en'),
+ ],
+ [],
+ [],
+ );
+
+ $this->projectGitSyncer->expects(self::exactly(2))
+ ->method('checkoutTag')
+ ->willReturnMap([
+ ['orm', '1.0.1', null],
+ ['orm', '1.2.0', null],
+ ]);
+
+ $this->getProjectPackagistData->expects(self::once())
+ ->method('__invoke')
+ ->with('doctrine/orm')
+ ->willReturn(['package' => []]);
+
+ $data = $this->dataSource->getSourceRows();
+
$expected = [
[
'active' => true,
'archived' => false,
'integration' => false,
- 'name' => 'Object Relational Mapper',
- 'repositoryName' => 'doctrine2',
- 'versions' => [],
- ],
- [
- 'active' => true,
- 'archived' => false,
- 'integration' => false,
- 'name' => 'Database Abstraction Layer',
- 'repositoryName' => 'dbal',
- 'versions' => [],
+ 'composerPackageName' => 'doctrine/orm',
+ 'repositoryName' => 'orm',
+ 'docsPath' => '/docs',
+ 'versions' => [
+ [
+ 'name' => '1.2',
+ 'tags' => [
+ [
+ 'name' => '1.2.0',
+ 'date' => '2019-09-05 00:00:00',
+ ],
+ ],
+ 'branchName' => null,
+ 'hasDocs' => true,
+ 'docsLanguages' => [
+ [
+ 'code' => 'en',
+ 'path' => '/path/to/en',
+ ],
+ ],
+ ],
+ [
+ 'name' => '1.1',
+ 'branchName' => '1.1',
+ 'tags' => [
+ [
+ 'name' => '1.1.0',
+ 'date' => '2019-09-03 00:00:00',
+ ],
+ [
+ 'name' => '1.1.1',
+ 'date' => '2019-09-04 00:00:00',
+ ],
+ ],
+ 'hasDocs' => false,
+ 'docsLanguages' => [],
+ ],
+ [
+ 'name' => '1.0',
+ 'branchName' => null,
+ 'tags' => [
+ [
+ 'name' => '1.0.0',
+ 'date' => '2019-09-01 00:00:00',
+ ],
+ [
+ 'name' => '1.0.1',
+ 'date' => '2019-09-02 00:00:00',
+ ],
+ ],
+ 'hasDocs' => false,
+ 'docsLanguages' => [],
+ ],
+ ],
+ 'packagistData' => ['package' => []],
],
];
- $this->dataReader->expects(self::once())
- ->method('read')
- ->with(ProjectDataBuilder::DATA_FILE)
- ->willReturn(new WebsiteData('test', $expected));
+ self::assertSame($expected, $data);
+ }
- $projectRows = $this->projects->getSourceRows();
+ protected function setUp(): void
+ {
+ $this->projectDataRepository = $this->createMock(ProjectDataRepository::class);
+ $this->projectGitSyncer = $this->createMock(ProjectGitSyncer::class);
+ $this->projectDataReader = $this->createMock(ProjectDataReader::class);
+ $this->projectVersionsReader = $this->createMock(ProjectVersionsReader::class);
+ $this->rstLanguagesDetector = $this->createMock(RSTLanguagesDetector::class);
+ $this->getProjectPackagistData = $this->createMock(GetProjectPackagistData::class);
+ $this->projectsDir = '/path/to/projects';
- self::assertSame($expected, $projectRows);
+ $this->dataSource = new Projects(
+ $this->projectDataRepository,
+ $this->projectGitSyncer,
+ $this->projectDataReader,
+ $this->projectVersionsReader,
+ $this->rstLanguagesDetector,
+ $this->getProjectPackagistData,
+ $this->projectsDir,
+ );
}
}
diff --git a/tests/Docs/BuildDocsTest.php b/tests/Docs/BuildDocsTest.php
index 5078d65c..59bdf03e 100644
--- a/tests/Docs/BuildDocsTest.php
+++ b/tests/Docs/BuildDocsTest.php
@@ -4,9 +4,12 @@
namespace Doctrine\Website\Tests\Docs;
+use DateTimeImmutable;
use Doctrine\Website\Docs\BuildDocs;
use Doctrine\Website\Docs\RST\RSTBuilder;
+use Doctrine\Website\Docs\RST\RSTLanguage;
use Doctrine\Website\Docs\SearchIndexer;
+use Doctrine\Website\Git\Tag;
use Doctrine\Website\Model\Project;
use Doctrine\Website\Model\ProjectVersion;
use Doctrine\Website\Projects\ProjectGitSyncer;
@@ -48,15 +51,8 @@ public function testBuildWithBranchCheckout(): void
{
$output = $this->createMock(OutputInterface::class);
- $version = new ProjectVersion([
- 'branchName' => '1.0',
- 'docsLanguages' => [
- [
- 'code' => 'en',
- 'path' => '/en',
- ],
- ],
- ]);
+ $version = new ProjectVersion(['branchName' => '1.0']);
+ $version->addDocsLanguage(new RSTLanguage('en', '/en'));
$repositoryName = 'test-project';
@@ -111,6 +107,8 @@ public function testBuildWithTagCheckout(): void
],
],
]);
+ $version->addDocsLanguage(new RSTLanguage('en', '/en'));
+ $version->addTag(new Tag('1.0.1', new DateTimeImmutable('2000-01-01')));
$repositoryName = 'test-project';
@@ -152,14 +150,8 @@ public function testBuildWithInvalidProjectVersion(): void
{
$output = $this->createMock(OutputInterface::class);
- $version = new ProjectVersion([
- 'docsLanguages' => [
- [
- 'code' => 'en',
- 'path' => '/en',
- ],
- ],
- ]);
+ $version = new ProjectVersion([]);
+ $version->addDocsLanguage(new RSTLanguage('en', '/en'));
$repositoryName = 'test-project';
diff --git a/tests/FunctionalTest.php b/tests/FunctionalTest.php
index 24988c6c..31496075 100644
--- a/tests/FunctionalTest.php
+++ b/tests/FunctionalTest.php
@@ -35,7 +35,7 @@ protected function setUp(): void
return;
}
- self::markTestSkipped('This test requires ./bin/console build-website to have been ran.');
+ self::markTestSkipped('This test requires ./bin/console build-website to have been run.');
}
public function testProjectVersionsAndTags(): void
diff --git a/tests/Hydrators/ProjectHydratorTest.php b/tests/Hydrators/ProjectHydratorTest.php
deleted file mode 100644
index c1192443..00000000
--- a/tests/Hydrators/ProjectHydratorTest.php
+++ /dev/null
@@ -1,182 +0,0 @@
-createHydrator(ProjectHydrator::class);
- $propertyValues = [
- 'active' => false,
- 'archived' => true,
- 'name' => 'name',
- 'shortName' => 'shortName',
- 'slug' => 'slug',
- 'docsSlug' => 'docsSlug',
- 'composerPackageName' => 'composerPackageName',
- 'repositoryName' => 'repositoryName',
- 'integration' => true,
- 'integrationFor' => 'integrationFor',
- 'docsRepositoryName' => 'docsRepositoryName',
- 'docsPath' => 'docsPath',
- 'codePath' => 'codePath',
- 'description' => 'description',
- 'keywords' => ['keywords'],
- 'versions' => [
- ['name' => 'v1'],
- new ProjectVersion(['name' => 'v2']),
- ],
- 'integrationType' => [],
- 'packagistData' => [
- 'package' => [
- 'github_stars' => 1,
- 'github_watchers' => 2,
- 'github_forks' => 3,
- 'github_open_issues' => 4,
- 'dependents' => 5,
- 'suggesters' => 6,
- 'downloads' => [
- 'total' => 7,
- 'monthly' => 8,
- 'daily' => 9,
- ],
- ],
- ],
- ];
-
- $expected = new Project();
- $this->populate($expected, [
- 'active' => false,
- 'archived' => true,
- 'name' => 'name',
- 'shortName' => 'shortName',
- 'slug' => 'slug',
- 'docsSlug' => 'docsSlug',
- 'composerPackageName' => 'composerPackageName',
- 'repositoryName' => 'repositoryName',
- 'isIntegration' => true,
- 'integrationFor' => 'integrationFor',
- 'docsRepositoryName' => 'docsRepositoryName',
- 'docsPath' => 'docsPath',
- 'codePath' => 'codePath',
- 'description' => 'description',
- 'keywords' => ['keywords'],
- 'versions' => [
- new ProjectVersion(['name' => 'v1']),
- new ProjectVersion(['name' => 'v2']),
- ],
- 'projectIntegrationType' => new ProjectIntegrationType([]),
- 'projectStats' => new ProjectStats(1, 2, 3, 4, 5, 6, 7, 8, 9),
- ]);
-
- $project = new Project();
-
- $hydrator->hydrate($project, $propertyValues);
-
- self::assertEquals($expected, $project);
- }
-
- public function testHydrateDefaultValues(): void
- {
- $hydrator = $this->createHydrator(ProjectHydrator::class);
- $propertyValues = [
- 'name' => 'name',
- 'slug' => 'slug',
- 'repositoryName' => 'repositoryName',
- 'versions' => [],
- ];
-
- $expected = new Project();
- $this->populate($expected, [
- 'active' => true,
- 'archived' => false,
- 'name' => 'name',
- 'shortName' => 'name',
- 'slug' => 'slug',
- 'docsSlug' => 'slug',
- 'composerPackageName' => '',
- 'repositoryName' => 'repositoryName',
- 'isIntegration' => false,
- 'integrationFor' => '',
- 'docsRepositoryName' => 'repositoryName',
- 'docsPath' => '/docs',
- 'codePath' => '/lib',
- 'description' => '',
- 'keywords' => [],
- 'versions' => [],
- 'projectIntegrationType' => null,
- 'projectStats' => new ProjectStats(0, 0, 0, 0, 0, 0, 0, 0, 0),
- ]);
-
- $project = new Project();
-
- $hydrator->hydrate($project, $propertyValues);
-
- self::assertEquals($expected, $project);
- }
-
- public function testHydrateNoVersions(): void
- {
- $hydrator = $this->createHydrator(ProjectHydrator::class);
- $propertyValues = [
- 'name' => 'name',
- 'slug' => 'slug',
- 'repositoryName' => 'repositoryName',
- ];
-
- $expected = new Project();
- $this->populate($expected, [
- 'active' => true,
- 'archived' => false,
- 'name' => 'name',
- 'shortName' => 'name',
- 'slug' => 'slug',
- 'docsSlug' => 'slug',
- 'composerPackageName' => '',
- 'repositoryName' => 'repositoryName',
- 'isIntegration' => false,
- 'integrationFor' => '',
- 'docsRepositoryName' => 'repositoryName',
- 'docsPath' => '/docs',
- 'codePath' => '/lib',
- 'description' => '',
- ]);
-
- $project = new Project();
-
- $hydrator->hydrate($project, $propertyValues);
-
- self::assertEquals($expected, $project);
- }
-
- public function testHydrateWithFilter(): void
- {
- $hydrator = $this->createHydrator(ProjectHydrator::class);
- $propertyValues = [
- 'name' => 'name',
- 'slug' => 'slug',
- 'repositoryName' => 'repositoryName',
- 'versionsGreaterThan' => '1.99.0',
- 'versions' => [
- ['name' => '1.0.0', 'tags' => [['name' => '1.0.0', 'date' => '2024-10-10']]],
- new ProjectVersion(['name' => '2.0.0', 'tags' => [['name' => '2.0.0', 'date' => '2024-10-10']]]),
- ],
- ];
-
- $project = new Project();
-
- $hydrator->hydrate($project, $propertyValues);
-
- self::assertCount(1, $project->getVersions());
- self::assertEquals('2.0.0', $project->getVersions()[0]->getLatestTag()?->getName());
- }
-}
diff --git a/tests/Projects/GetTotalDownloadsTest.php b/tests/Projects/GetTotalDownloadsTest.php
index 2a3a7b7c..a486cce8 100644
--- a/tests/Projects/GetTotalDownloadsTest.php
+++ b/tests/Projects/GetTotalDownloadsTest.php
@@ -4,6 +4,7 @@
namespace Doctrine\Website\Tests\Projects;
+use Doctrine\Website\Model\ProjectStats;
use Doctrine\Website\Projects\GetTotalDownloads;
use Doctrine\Website\Repositories\ProjectRepository;
use Doctrine\Website\Tests\TestCase;
@@ -29,12 +30,7 @@ public function testGetTotalDownloadsTest(): void
private function createProjectData(int $totalDownloads): array
{
return [
- 'packagistData' => [
- 'package' => [
- 'downloads' => ['total' => $totalDownloads],
- ],
- ],
- 'versions' => [],
+ 'projectStats' => new ProjectStats(totalDownloads: $totalDownloads),
];
}
}
diff --git a/tests/Projects/ProjectTest.php b/tests/Projects/ProjectTest.php
index 7cee9ca7..b91250db 100644
--- a/tests/Projects/ProjectTest.php
+++ b/tests/Projects/ProjectTest.php
@@ -4,6 +4,7 @@
namespace Doctrine\Website\Tests\Projects;
+use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Website\Model\Project;
use Doctrine\Website\Model\ProjectVersion;
use Doctrine\Website\Tests\TestCase;
@@ -25,29 +26,29 @@ protected function setUp(): void
'composerPackageName' => 'doctrine/test-project',
'repositoryName' => 'test-project',
'docsRepositoryName' => 'test-project',
- 'docsDir' => '/docs',
+ 'docsPath' => '/docs',
'codePath' => '/src',
'description' => 'Test description.',
'keywords' => ['keyword1', 'keyword2'],
- 'versions' => [
- [
+ 'versions' => new ArrayCollection([
+ new ProjectVersion([
'name' => 'master',
'branchName' => 'master',
'slug' => 'latest',
- ],
- [
+ ]),
+ new ProjectVersion([
'name' => '2.0',
'branchName' => '2.0',
'slug' => '2.0',
'current' => true,
- ],
- [
+ ]),
+ new ProjectVersion([
'name' => '1.0',
'branchName' => '1.0',
'slug' => '1.0',
'maintained' => false,
- ],
- ],
+ ]),
+ ]),
]);
}
diff --git a/tests/Projects/ProjectVersionTest.php b/tests/Projects/ProjectVersionTest.php
index 3bb06a2b..755b22c8 100644
--- a/tests/Projects/ProjectVersionTest.php
+++ b/tests/Projects/ProjectVersionTest.php
@@ -4,6 +4,8 @@
namespace Doctrine\Website\Tests\Projects;
+use DateTimeImmutable;
+use Doctrine\Website\Git\Tag;
use Doctrine\Website\Model\ProjectVersion;
use Doctrine\Website\Tests\TestCase;
@@ -85,14 +87,8 @@ public function testHasTags(): void
self::assertFalse($projectVersion->hasTags());
- $projectVersion = new ProjectVersion([
- 'tags' => [
- [
- 'name' => '1.0',
- 'date' => '2000-01-01',
- ],
- ],
- ]);
+ $projectVersion = new ProjectVersion([]);
+ $projectVersion->addTag(new Tag('1.0', new DateTimeImmutable('2000-01-01')));
self::assertTrue($projectVersion->hasTags());
}
diff --git a/tests/Requests/ProjectVersionRequestsTest.php b/tests/Requests/ProjectVersionRequestsTest.php
index e939cf6a..e39bbda5 100644
--- a/tests/Requests/ProjectVersionRequestsTest.php
+++ b/tests/Requests/ProjectVersionRequestsTest.php
@@ -4,7 +4,9 @@
namespace Doctrine\Website\Tests\Requests;
+use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\StaticWebsiteGenerator\Request\ArrayRequestCollection;
+use Doctrine\Website\Model\ProjectVersion;
use Doctrine\Website\Repositories\ProjectRepository;
use Doctrine\Website\Requests\ProjectVersionRequests;
use Doctrine\Website\Tests\TestCase;
@@ -13,12 +15,12 @@ class ProjectVersionRequestsTest extends TestCase
{
public function testGetProjectVersions(): void
{
- $partner = $this->createModel(ProjectRepository::class, [
+ $partner = $this->createProject([
'slug' => 'project',
- 'versions' => [
- ['slug' => 'v1'],
- ['slug' => 'v2'],
- ],
+ 'versions' => new ArrayCollection([
+ new ProjectVersion(['slug' => 'v1']),
+ new ProjectVersion(['slug' => 'v2']),
+ ]),
]);
$projectRepository = $this->createMock(ProjectRepository::class);
$projectRepository->expects(self::once())
diff --git a/tests/TestCase.php b/tests/TestCase.php
index a70b0f14..50199c1e 100644
--- a/tests/TestCase.php
+++ b/tests/TestCase.php
@@ -4,13 +4,16 @@
namespace Doctrine\Website\Tests;
+use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\SkeletonMapper\ObjectRepository\ObjectRepositoryInterface;
use Doctrine\Website\Application;
use Doctrine\Website\Model\Project;
-use Doctrine\Website\Repositories\ProjectRepository;
+use Doctrine\Website\Model\ProjectStats;
use PHPUnit\Framework\TestCase as BaseTestCase;
use Symfony\Component\DependencyInjection\ContainerBuilder;
+use function array_merge;
+
abstract class TestCase extends BaseTestCase
{
private static ContainerBuilder|null $container = null;
@@ -40,9 +43,29 @@ protected function createModel(string $repositoryClassName, array $data): object
/** @param mixed[] $data */
protected function createProject(array $data): Project
{
- $project = $this->createModel(ProjectRepository::class, $data);
- self::assertInstanceOf(Project::class, $project);
+ $default = [
+ 'projectStats' => new ProjectStats(),
+ 'active' => true,
+ 'archived' => false,
+ 'name' => '',
+ 'shortName' => '',
+ 'slug' => '',
+ 'docsSlug' => '',
+ 'composerPackageName' => '',
+ 'repositoryName' => '',
+ 'integrationFor' => '',
+ 'docsRepositoryName' => '',
+ 'docsPath' => '',
+ 'codePath' => '',
+ 'description' => '',
+ 'projectIntegrationType' => null,
+ 'integration' => true,
+ 'keywords' => [],
+ 'versions' => new ArrayCollection(),
+ ];
+
+ $data = array_merge($default, $data);
- return $project;
+ return new Project(...$data);
}
}
diff --git a/tests/Twig/MainExtensionTest.php b/tests/Twig/MainExtensionTest.php
index 91d3255f..75abf8e1 100644
--- a/tests/Twig/MainExtensionTest.php
+++ b/tests/Twig/MainExtensionTest.php
@@ -4,6 +4,7 @@
namespace Doctrine\Website\Tests\Twig;
+use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Website\Assets\AssetIntegrityGenerator;
use Doctrine\Website\Model\ProjectVersion;
use Doctrine\Website\Tests\TestCase;
@@ -51,12 +52,12 @@ public function testGetSearchBoxPlaceholder(): void
$project = $this->createProject([
'shortName' => 'ORM',
- 'versions' => [
- [
+ 'versions' => new ArrayCollection([
+ new ProjectVersion([
'slug' => 'latest',
'name' => '1.0',
- ],
- ],
+ ]),
+ ]),
]);
$projectVersion = new ProjectVersion(['name' => '1.0']);
diff --git a/tests/WebsiteBuilderTest.php b/tests/WebsiteBuilderTest.php
index c912e055..9e314f3b 100644
--- a/tests/WebsiteBuilderTest.php
+++ b/tests/WebsiteBuilderTest.php
@@ -29,8 +29,6 @@ class WebsiteBuilderTest extends TestCase
private string $rootDir;
- private string $cacheDir;
-
private string $webpackBuildDir;
private WebsiteBuilder&MockObject $websiteBuilder;
@@ -43,7 +41,6 @@ protected function setUp(): void
$this->sourceFileRepository = $this->createMock(SourceFileRepository::class);
$this->sourceFilesBuilder = $this->createMock(SourceFilesBuilder::class);
$this->rootDir = '/data/doctrine-website-build-staging';
- $this->cacheDir = '/data/doctrine-website-build-staging/cache';
$this->webpackBuildDir = '/data/doctrine-website-build-staging/.webpack-build';
$this->websiteBuilder = $this->getMockBuilder(WebsiteBuilder::class)
@@ -54,7 +51,6 @@ protected function setUp(): void
$this->sourceFileRepository,
$this->sourceFilesBuilder,
$this->rootDir,
- $this->cacheDir,
$this->webpackBuildDir,
])
->onlyMethods(['filePutContents'])
@@ -92,6 +88,5 @@ public function testBuild(): void
$this->websiteBuilder->build($output, $buildDir, $env);
self::assertSame($buildDir . '/frontend', $mirrored[$this->webpackBuildDir]);
- self::assertSame($buildDir . '/website-data', $mirrored[$this->cacheDir . '/data']);
}
}