Merging upstream/master

This commit is contained in:
Mike Mollick
2018-10-26 23:42:22 -04:00
parent dc72a375f0
commit ea083c8601
409 changed files with 1211 additions and 3629 deletions

View File

@@ -17,4 +17,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -15,8 +15,8 @@
"algolia/algoliasearch-client-php": "^1.27",
"cache/doctrine-adapter": "^1.0",
"doctrine/inflector": "^1.3",
"doctrine/rst-parser": "dev-master",
"doctrine/skeleton-mapper": "dev-master",
"doctrine/skeleton-mapper": "^0.0.1",
"doctrine/static-website-generator": "^0.0.1",
"erusev/parsedown": "^1.7",
"knplabs/github-api": "^2.10",
"php-http/guzzle6-adapter": "^1.1",

728
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -2,11 +2,11 @@ parameters:
doctrine.website.algolia.app_id: 'YVYTFT9XMW'
doctrine.website.algolia.admin_api_key: '1234'
doctrine.website.projects_path: '%doctrine.website.root_dir%/projects'
doctrine.website.docs_path: '%doctrine.website.root_dir%/docs'
doctrine.website.source_path: '%doctrine.website.root_dir%/source'
doctrine.website.webpack_build_path: '%doctrine.website.root_dir%/.webpack-build'
doctrine.website.templates_path: '%doctrine.website.root_dir%/templates'
doctrine.website.webpack_build_dir: '%doctrine.website.root_dir%/.webpack-build'
doctrine.website.projects_dir: '%doctrine.website.root_dir%/projects'
doctrine.website.docs_dir: '%doctrine.website.root_dir%/docs'
doctrine.website.source_dir: '%doctrine.website.root_dir%/source'
doctrine.website.templates_dir: '%doctrine.website.root_dir%/templates'
doctrine.website.title: Doctrine
doctrine.website.subtitle: PHP Database Tools

View File

@@ -1,4 +1,4 @@
parameters:
doctrine.website.algolia.admin_api_key: 'abcd'
doctrine.website.projects_path: '%doctrine.website.root_dir%/projects'
doctrine.website.projects_dir: '%doctrine.website.root_dir%/projects'
doctrine.website.github.http_token: 'abcd'

142
config/routes.yml Normal file
View File

@@ -0,0 +1,142 @@
parameters:
doctrine.website.routes:
homepage:
path: /index.html
controller: Doctrine\Website\Controllers\HomepageController::index
defaults:
title: Home
menuSlug: home
atom:
path: /atom.xml
controller: Doctrine\Website\Controllers\AtomController::index
robots:
path: /robots.txt
sitemap:
path: /sitemap.xml
controller: Doctrine\Website\Controllers\SitemapController::index
rst_examples:
path: /rst-examples.html
defaults:
title: RST Example
blog:
path: /blog/index.html
controller: Doctrine\Website\Controllers\BlogController::index
defaults:
title: Blog
menuSlug: blog
blog_archive:
path: /blog/archive.html
controller: Doctrine\Website\Controllers\BlogController::archive
defaults:
title: Blog Archive
menuSlug: blog
blog_post:
path: /{year}/{month}/{day}/{slug}.html
controller: Doctrine\Website\Controllers\BlogController::view
defaults:
menuSlug: blog
layout: blog-post
community:
path: /community/index.html
defaults:
title: Community
menuSlug: community
team_maintainers:
path: /team/maintainers.html
controller: Doctrine\Website\Controllers\TeamController::maintainers
defaults:
title: Doctrine Maintaiers
menuSlug: team
team_contributors:
path: /team/contributors.html
controller: Doctrine\Website\Controllers\TeamController::contributors
defaults:
title: Doctrine Contributors
menuSlug: team
team_contributor:
path: /team/{github}.html
controller: Doctrine\Website\Controllers\TeamController::contributor
provider: Doctrine\Website\Requests\ContributorRequests::getContributors
contribute:
path: /contribute/index.html
defaults:
title: Contribute
menuSlug: development
contribute_maintainer:
path: /contribute/maintainer/index.html
defaults:
title: Contribute to Website
menuSlug: development
contribute_website:
path: /contribute/website/index.html
defaults:
title: Contribute to Website
menuSlug: development
policies:
path: /policies.html
defaults:
title: Policies
menuSlug: development
policies_deprecation:
path: /policies/deprecation.html
defaults:
title: Deprecation Policy
menuSlug: development
policies_releases:
path: /policies/releases.html
defaults:
title: Release Policy
menuSlug: development
policies_security:
path: /policies/security.html
defaults:
title: Security Policy
menuSlug: development
projects:
path: /projects.html
controller: Doctrine\Website\Controllers\ProjectController::index
defaults:
title: Projects
menuSlug: projects
project:
path: /projects/{slug}.html
controller: Doctrine\Website\Controllers\ProjectController::view
defaults:
menuSlug: projects
layout: project
project_docs_section:
path: /projects/{docsSlug}/{language}/{docsVersion}/{section}.html
controller: Doctrine\Website\Controllers\DocumentationController::view
defaults:
layout: documentation
indexed: true
menuSlug: projects
docsPage: true
requirements:
section: .+
project_api_docs_page:
path: /api/{slug}}/{docsVersion}/{page}.html
requirements:
section: .+

View File

@@ -7,19 +7,53 @@
<defaults autowire="true" autoconfigure="true" public="false">
<bind key="$rootDir">%doctrine.website.root_dir%</bind>
<bind key="$env">%doctrine.website.env%</bind>
<bind key="$projectsPath">%doctrine.website.projects_path%</bind>
<bind key="$docsPath">%doctrine.website.docs_path%</bind>
<bind key="$sourcePath">%doctrine.website.source_path%</bind>
<bind key="$projectsDir">%doctrine.website.projects_dir%</bind>
<bind key="$docsDir">%doctrine.website.docs_dir%</bind>
<bind key="$sourceDir">%doctrine.website.source_dir%</bind>
<bind key="$projectsData">%doctrine.website.projects_data%</bind>
<bind key="$webpackBuildPath">%doctrine.website.webpack_build_path%</bind>
<bind key="$webpackBuildDir">%doctrine.website.webpack_build_dir%</bind>
<bind key="$teamMembers">%doctrine.website.team_members%</bind>
<bind key="$templatesPath">%doctrine.website.templates_path%</bind>
<bind key="$templatesDir">%doctrine.website.templates_dir%</bind>
<bind key="$doctrineUsers">%doctrine.website.doctrine_users%</bind>
<bind key="$projectIntegrationTypes">%doctrine.website.project_integration.types%</bind>
<bind key="$routes">%doctrine.website.routes%</bind>
</defaults>
<prototype namespace="Doctrine\Website\" resource="../lib/*" />
<prototype namespace="Doctrine\StaticWebsiteGenerator\" resource="../vendor/doctrine/static-website-generator/lib/*" />
<service id="Doctrine\StaticWebsiteGenerator\SourceFile\Converters\MarkdownConverter">
<argument type="service" id="Parsedown" />
</service>
<service id="Doctrine\StaticWebsiteGenerator\SourceFile\Converters\ReStructuredTextConverter">
<argument type="service" id="Doctrine\RST\Parser" />
</service>
<service id="Doctrine\StaticWebsiteGenerator\SourceFile\SourceFileBuilder">
<argument type="service" id="Doctrine\StaticWebsiteGenerator\SourceFile\SourceFileRenderer" />
<argument type="service" id="Symfony\Component\Filesystem\Filesystem" />
<argument type="collection">
<argument type="service" id="Doctrine\StaticWebsiteGenerator\SourceFile\Converters\MarkdownConverter" />
<argument type="service" id="Doctrine\StaticWebsiteGenerator\SourceFile\Converters\ReStructuredTextConverter" />
</argument>
<argument type="collection">
<argument>/\/api\//</argument>
</argument>
</service>
<service id="Doctrine\StaticWebsiteGenerator\Twig\StringTwigRenderer" autowire="false">
<argument>%doctrine.website.templates_dir%</argument>
<argument type="collection">
<argument type="service" id="Doctrine\Website\Twig\MainExtension" />
<argument type="service" id="Doctrine\Website\Twig\ProjectExtension" />
<argument type="service" id="Doctrine\StaticWebsiteGenerator\Twig\RoutingExtension" />
</argument>
</service>
<service id="Doctrine\StaticWebsiteGenerator\Twig\TwigRenderer" alias="Doctrine\StaticWebsiteGenerator\Twig\StringTwigRenderer" />
<service id="Doctrine\Website\Application" autowire="true" public="true" />
<service id="Doctrine\Website\Projects\ProjectDataRepository" autowire="true" />
@@ -33,6 +67,13 @@
<argument type="service" id="Doctrine\Website\RST\Kernel" />
</service>
<service id="Doctrine\StaticWebsiteGenerator\SourceFile\SourceFileRepository">
<argument type="collection">
<argument type="service" id="Doctrine\StaticWebsiteGenerator\SourceFile\SourceFileFilesystemReader" />
<argument type="service" id="Doctrine\StaticWebsiteGenerator\SourceFile\SourceFileRouteReader" />
</argument>
</service>
<service id="Doctrine\RST\HTML\Kernel" autowire="true" />
<service id="Github\Client">
<call method="authenticate">
@@ -52,11 +93,12 @@
<service id="Parsedown" class="Parsedown" autowire="true" />
<service id="Symfony\Component\Console\Application" autowire="true" />
<service id="Symfony\Component\Filesystem\Filesystem" autowire="true" />
<service id="Symfony\Component\HttpKernel\Controller\ArgumentResolver" autowire="true" />
<service id="Doctrine\Common\Cache\FilesystemCache" autowire="false">
<argument>%doctrine.website.cache_dir%</argument>
</service>
<service id="Doctrine\Website\Controller\ControllerProvider">
<service id="Doctrine\StaticWebsiteGenerator\Controller\ControllerProvider">
<argument type="collection">
<argument type="service" id="Doctrine\Website\Controllers\AtomController" />
<argument type="service" id="Doctrine\Website\Controllers\BlogController" />
@@ -68,12 +110,18 @@
</argument>
</service>
<service id="Doctrine\StaticWebsiteGenerator\Request\RequestCollectionProvider">
<argument type="collection">
<argument type="service" id="Doctrine\Website\Requests\ContributorRequests" />
</argument>
</service>
<service id="AlgoliaSearch\Client">
<argument>%doctrine.website.algolia.app_id%</argument>
<argument>%doctrine.website.algolia.admin_api_key%</argument>
</service>
<service id="Doctrine\Website\Site">
<service id="Doctrine\StaticWebsiteGenerator\Site">
<argument>%doctrine.website.title%</argument>
<argument>%doctrine.website.subtitle%</argument>
<argument>%doctrine.website.url%</argument>
@@ -121,7 +169,7 @@
<service id="Doctrine\Website\Repositories\BlogPostRepository" autowire="false">
<argument type="service" id="Doctrine\SkeletonMapper\ObjectManager" />
<argument type="service">
<service class="Doctrine\Website\DataSource\DataSourceObjectDataRepository" autowire="false">
<service class="Doctrine\SkeletonMapper\DataSource\DataSourceObjectDataRepository" autowire="false">
<argument type="service" id="Doctrine\SkeletonMapper\ObjectManager" />
<argument type="service" id="Doctrine\Website\DataSources\BlogPosts" />
<argument>Doctrine\Website\Model\BlogPost</argument>
@@ -140,7 +188,7 @@
<service id="Doctrine\Website\Repositories\ContributorRepository" autowire="false">
<argument type="service" id="Doctrine\SkeletonMapper\ObjectManager" />
<argument type="service">
<service class="Doctrine\Website\DataSource\DataSourceObjectDataRepository" autowire="false">
<service class="Doctrine\SkeletonMapper\DataSource\DataSourceObjectDataRepository" autowire="false">
<argument type="service" id="Doctrine\SkeletonMapper\ObjectManager" />
<argument type="service" id="Doctrine\Website\DataSources\Contributors" />
<argument>Doctrine\Website\Model\Contributor</argument>
@@ -159,7 +207,7 @@
<service id="Doctrine\Website\Repositories\DoctrineUserRepository" autowire="false" public="true">
<argument type="service" id="Doctrine\SkeletonMapper\ObjectManager" />
<argument type="service">
<service class="Doctrine\Website\DataSource\DataSourceObjectDataRepository" autowire="false">
<service class="Doctrine\SkeletonMapper\DataSource\DataSourceObjectDataRepository" autowire="false">
<argument type="service" id="Doctrine\SkeletonMapper\ObjectManager" />
<argument type="service" id="Doctrine\Website\DataSources\DoctrineUsers" />
<argument>Doctrine\Website\Model\DoctrineUser</argument>
@@ -178,7 +226,7 @@
<service id="Doctrine\Website\Repositories\ProjectRepository" autowire="false" public="true">
<argument type="service" id="Doctrine\SkeletonMapper\ObjectManager" />
<argument type="service">
<service class="Doctrine\Website\DataSource\DataSourceObjectDataRepository" autowire="false">
<service class="Doctrine\SkeletonMapper\DataSource\DataSourceObjectDataRepository" autowire="false">
<argument type="service" id="Doctrine\SkeletonMapper\ObjectManager" />
<argument type="service" id="Doctrine\Website\DataSources\Projects" />
<argument>Doctrine\Website\Model\Project</argument>
@@ -197,7 +245,7 @@
<service id="Doctrine\Website\Repositories\ProjectContributorRepository" autowire="false" public="true">
<argument type="service" id="Doctrine\SkeletonMapper\ObjectManager" />
<argument type="service">
<service class="Doctrine\Website\DataSource\DataSourceObjectDataRepository" autowire="false">
<service class="Doctrine\SkeletonMapper\DataSource\DataSourceObjectDataRepository" autowire="false">
<argument type="service" id="Doctrine\SkeletonMapper\ObjectManager" />
<argument type="service" id="Doctrine\Website\DataSources\ProjectContributors" />
<argument>Doctrine\Website\Model\ProjectContributor</argument>
@@ -216,7 +264,7 @@
<service id="Doctrine\Website\Repositories\SitemapPageRepository" autowire="false">
<argument type="service" id="Doctrine\SkeletonMapper\ObjectManager" />
<argument type="service">
<service class="Doctrine\Website\DataSource\DataSourceObjectDataRepository" autowire="false">
<service class="Doctrine\SkeletonMapper\DataSource\DataSourceObjectDataRepository" autowire="false">
<argument type="service" id="Doctrine\SkeletonMapper\ObjectManager" />
<argument type="service" id="Doctrine\Website\DataSources\SitemapPages" />
<argument>Doctrine\Website\Model\SitemapPage</argument>
@@ -235,7 +283,7 @@
<service id="Doctrine\Website\Repositories\TeamMemberRepository" autowire="false">
<argument type="service" id="Doctrine\SkeletonMapper\ObjectManager" />
<argument type="service">
<service class="Doctrine\Website\DataSource\DataSourceObjectDataRepository" autowire="false">
<service class="Doctrine\SkeletonMapper\DataSource\DataSourceObjectDataRepository" autowire="false">
<argument type="service" id="Doctrine\SkeletonMapper\ObjectManager" />
<argument type="service" id="Doctrine\Website\DataSources\TeamMembers" />
<argument>Doctrine\Website\Model\TeamMember</argument>

View File

@@ -11,6 +11,7 @@ use Doctrine\Website\Commands\DeployCommand;
use Symfony\Component\Config\FileLocator;
use Symfony\Component\Console\Application as BaseApplication;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
@@ -52,6 +53,15 @@ class Application
public function run(InputInterface $input) : int
{
$inputOption = new InputOption(
'env',
'e',
InputOption::VALUE_REQUIRED,
'The environment.',
'dev'
);
$this->application->getDefinition()->addOption($inputOption);
$this->application->add($this->buildDocsCommand);
$this->application->add($this->buildWebsiteCommand);
$this->application->add($this->clearBuildCacheCommand);
@@ -75,6 +85,7 @@ class Application
$loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../config'));
$loader->load('projects.yml');
$loader->load('team_members.yml');
$loader->load('routes.yml');
$loader->load(sprintf('config_%s.yml', $env));

View File

@@ -13,24 +13,24 @@ use function realpath;
class AssetIntegrityGenerator
{
/** @var string */
private $sourcePath;
private $sourceDir;
/** @var string */
private $webpackBuildPath;
private $webpackBuildDir;
/** @var string[] */
private $cache = [];
public function __construct(string $sourcePath, string $webpackBuildPath)
public function __construct(string $sourceDir, string $webpackBuildDir)
{
$this->sourcePath = $sourcePath;
$this->webpackBuildPath = $webpackBuildPath;
$this->sourceDir = $sourceDir;
$this->webpackBuildDir = $webpackBuildDir;
}
public function getAssetIntegrity(string $path, string $rootPath = null) : string
{
if (! isset($this->cache[$path])) {
$contents = $this->getFileContents($path, $rootPath ?? $this->sourcePath);
$contents = $this->getFileContents($path, $rootPath ?? $this->sourceDir);
$this->cache[$path] = $this->buildAssetIntegrityString($contents);
}
@@ -40,7 +40,7 @@ class AssetIntegrityGenerator
public function getWebpackAssetIntegrity(string $path) : string
{
return $this->getAssetIntegrity($path, $this->webpackBuildPath);
return $this->getAssetIntegrity($path, $this->webpackBuildDir);
}
private function getFileContents(string $path, string $rootPath) : string

View File

@@ -1,133 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Website\Builder;
use DateTimeImmutable;
use function count;
use function explode;
use function in_array;
use function sprintf;
use function strpos;
use function strtotime;
class SourceFile
{
private const TWIG_EXTENSIONS = ['html', 'md', 'rst', 'xml', 'txt'];
private const NEEDS_LAYOUT_EXTENSIONS = ['html', 'md', 'rst'];
private const MARKDOWN_EXTENSION = 'md';
private const RESTRUCTURED_TEXT_EXTENSION = 'rst';
/** @var string */
private $extension;
/** @var string */
private $sourcePath;
/** @var string */
private $writePath;
/** @var string */
private $contents;
/** @var SourceFileParameters */
private $parameters;
public function __construct(
string $extension,
string $sourcePath,
string $writePath,
string $contents,
SourceFileParameters $parameters
) {
$this->extension = $extension;
$this->sourcePath = $sourcePath;
$this->writePath = $writePath;
$this->contents = $contents;
$this->parameters = $parameters;
}
public function getSourcePath() : string
{
return $this->sourcePath;
}
public function getWritePath() : string
{
return $this->writePath;
}
public function getUrl() : string
{
return (string) $this->parameters->getParameter('url');
}
public function getDate() : DateTimeImmutable
{
$e = explode('/', $this->getUrl());
if (count($e) < 4) {
return new DateTimeImmutable();
}
$date = strtotime(sprintf('%s/%s/%s', $e[1], $e[2], $e[3]));
if ($date === false) {
return new DateTimeImmutable();
}
return (new DateTimeImmutable())->setTimestamp($date);
}
public function getExtension() : string
{
return $this->extension;
}
public function isMarkdown() : bool
{
return $this->getExtension() === self::MARKDOWN_EXTENSION;
}
public function isRestructuredText() : bool
{
return $this->getExtension() === self::RESTRUCTURED_TEXT_EXTENSION;
}
public function isTwig() : bool
{
return in_array($this->getExtension(), self::TWIG_EXTENSIONS, true) && $this->isApiDocs() === false;
}
public function isLayoutNeeded() : bool
{
return in_array($this->getExtension(), self::NEEDS_LAYOUT_EXTENSIONS, true);
}
public function isApiDocs() : bool
{
return strpos($this->getUrl(), '/api/') === 0;
}
public function getContents() : string
{
return $this->contents;
}
public function getParameters() : SourceFileParameters
{
return $this->parameters;
}
/**
* @return mixed
*/
public function getParameter(string $key)
{
return $this->parameters->getParameter($key);
}
}

View File

@@ -1,65 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Website\Builder;
use Doctrine\RST\Parser as RSTParser;
use Parsedown;
use Symfony\Component\Filesystem\Filesystem;
class SourceFileBuilder
{
/** @var SourceFileRenderer */
private $sourceFileRenderer;
/** @var Filesystem */
private $filesystem;
/** @var Parsedown */
private $parsedown;
/** @var RSTParser */
private $rstParser;
public function __construct(
SourceFileRenderer $sourceFileRenderer,
Filesystem $filesystem,
Parsedown $parsedown,
RSTParser $rstParser
) {
$this->sourceFileRenderer = $sourceFileRenderer;
$this->filesystem = $filesystem;
$this->parsedown = $parsedown;
$this->rstParser = $rstParser;
}
public function buildFile(SourceFile $sourceFile, string $buildDir) : void
{
$parsedFile = $this->parseFile($sourceFile);
if ($sourceFile->isTwig()) {
$parsedFile = $this->sourceFileRenderer->render(
$sourceFile,
$parsedFile
);
}
$this->filesystem->dumpFile($sourceFile->getWritePath(), $parsedFile);
}
private function parseFile(SourceFile $sourceFile) : string
{
$contents = $sourceFile->getContents();
if ($sourceFile->isMarkdown()) {
return $this->parsedown->text($contents);
}
if ($sourceFile->isRestructuredText()) {
return $this->rstParser->parse($contents)->render();
}
return $contents;
}
}

View File

@@ -1,35 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Website\Builder;
class SourceFileParameters
{
/** @var mixed[] */
private $parameters = [];
/**
* @param mixed[] $parameters
*/
public function __construct(array $parameters)
{
$this->parameters = $parameters;
}
/**
* @return mixed[]
*/
public function getAll() : array
{
return $this->parameters;
}
/**
* @return mixed
*/
public function getParameter(string $key)
{
return $this->parameters[$key] ?? null;
}
}

View File

@@ -1,86 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Website\Builder;
use Doctrine\Website\Controller\ControllerExecutor;
use Doctrine\Website\Site;
use Doctrine\Website\Twig\TwigRenderer;
use function preg_match_all;
use function str_replace;
class SourceFileRenderer
{
/** @var ControllerExecutor */
private $controllerExecutor;
/** @var TwigRenderer */
private $twigRenderer;
/** @var Site */
private $site;
/** @var string */
private $sourcePath;
public function __construct(
ControllerExecutor $controllerExecutor,
TwigRenderer $twigRenderer,
Site $site,
string $sourcePath
) {
$this->controllerExecutor = $controllerExecutor;
$this->twigRenderer = $twigRenderer;
$this->site = $site;
$this->sourcePath = $sourcePath;
}
public function render(SourceFile $sourceFile, string $contents) : string
{
$template = $this->prepareTemplate($sourceFile, $contents);
$pageParameters = $this->preparePageParameters($sourceFile);
$parameters = [
'page' => $pageParameters,
'site' => $this->site,
];
if (isset($parameters['page']['controller'])) {
$controllerParameters = $this->controllerExecutor->execute($sourceFile);
$parameters += $controllerParameters;
}
return $this->twigRenderer->render($template, $parameters);
}
/**
* @return mixed[]
*/
private function preparePageParameters(SourceFile $sourceFile) : array
{
return $sourceFile->getParameters()->getAll() + [
'date' => $sourceFile->getDate(),
'sourceFile' => str_replace($this->sourcePath, '/source', $sourceFile->getSourcePath()),
];
}
private function prepareTemplate(SourceFile $sourceFile, string $contents) : string
{
if ($sourceFile->isLayoutNeeded()) {
if ($contents !== '') {
$regex = '/{%\s+block\s+(\w+)\s+%}(.*?){%\s+endblock\s+%}/si';
if (preg_match_all($regex, $contents, $matches) === 0) {
$contents = '{% block content %}' . $contents . '{% endblock %}';
}
}
$contents = '{% extends "layouts/' . $sourceFile->getParameter('layout') . '.html.twig" %}' . $contents;
}
return $contents;
}
}

View File

@@ -1,135 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Website\Builder;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Yaml\Yaml;
use function assert;
use function end;
use function explode;
use function file_get_contents;
use function in_array;
use function is_string;
use function preg_match;
use function preg_replace;
use function str_replace;
use function strrpos;
use function substr;
class SourceFileRepository
{
/** @var string */
private $rootDir;
public function __construct(string $rootDir)
{
$this->rootDir = $rootDir;
}
/**
* @return SourceFile[]
*/
public function getFiles(string $buildDir, string $inPath = 'source') : array
{
$finder = new Finder();
$finder
->in($this->rootDir . '/' . $inPath)
->files();
$files = [];
foreach ($finder as $splFileInfo) {
$path = $splFileInfo->getRealPath();
assert(is_string($path));
$contents = file_get_contents($path);
assert(is_string($contents));
$extension = $this->getExtension($path);
$writePath = $this->getWritePath($buildDir, $path, $extension);
$sourceFileParameters = $this->createSourceFileParameters(
$buildDir,
$writePath,
$contents
);
$writePath = $buildDir . $sourceFileParameters->getParameter('url');
$contents = $this->stripFileParameters($contents);
$files[] = new SourceFile(
$extension,
$path,
$writePath,
$contents,
$sourceFileParameters
);
}
return $files;
}
private function getWritePath(string $buildDir, string $path, string $extension) : string
{
$writePath = $buildDir . str_replace($this->rootDir . '/source', '', $path);
if (in_array($extension, ['md', 'rst'], true)) {
$writePath = substr($writePath, 0, (int) strrpos($writePath, '.')) . '.html';
}
return $writePath;
}
private function getExtension(string $path) : string
{
$e = explode('.', $path);
return end($e);
}
private function stripFileParameters(string $contents) : string
{
return preg_replace('/^\s*(?:---[\s]*[\r\n]+)(.*?)(?:---[\s]*[\r\n]+)(.*?)$/s', '$2', $contents);
}
private function createSourceFileParameters(
string $buildDir,
string $writePath,
string $string
) : SourceFileParameters {
$parameters = [];
if (preg_match('/^\s*(?:---[\s]*[\r\n]+)(.*?)(?:---[\s]*[\r\n]+)(.*?)$/s', $string, $matches) > 0) {
if (preg_match('/^(\s*[-]+\s*|\s*)$/', $matches[1]) === 0) {
$parameters = Yaml::parse($matches[1], 1);
}
}
if (! isset($parameters['layout'])) {
$parameters['layout'] = 'default';
}
$parameters['url'] = $this->getUrl($buildDir, $writePath, $parameters);
return new SourceFileParameters($parameters);
}
/**
* @param mixed[] $parameters
*/
private function getUrl(string $buildDir, string $writePath, array $parameters) : string
{
$permalink = $parameters['permalink'] ?? '';
if ($permalink !== '' && $permalink !== 'none') {
return $permalink;
}
return str_replace($buildDir, '', $writePath);
}
}

View File

@@ -9,6 +9,9 @@ use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use function assert;
use function is_bool;
use function is_string;
class BuildDocsCommand extends Command
{
@@ -31,13 +34,15 @@ class BuildDocsCommand extends Command
'project',
null,
InputOption::VALUE_REQUIRED,
'The project to build the docs for.'
'The project to build the docs for.',
''
)
->addOption(
'v',
null,
InputOption::VALUE_REQUIRED,
'The project version to build the docs for.'
'The project version to build the docs for.',
''
)
->addOption(
'api',
@@ -56,22 +61,25 @@ class BuildDocsCommand extends Command
null,
InputOption::VALUE_NONE,
'Sync git repositories before building.'
)
->addOption(
'env',
'e',
InputOption::VALUE_REQUIRED,
'The environment.'
);
}
protected function execute(InputInterface $input, OutputInterface $output) : int
{
$projectToBuild = (string) $input->getOption('project');
$versionToBuild = (string) $input->getOption('v');
$buildApiDocs = (bool) $input->getOption('api');
$buildSearchIndexes = (bool) $input->getOption('search');
$syncGit = (bool) $input->getOption('sync-git');
$projectToBuild = $input->getOption('project');
assert(is_string($projectToBuild));
$versionToBuild = $input->getOption('v');
assert(is_string($versionToBuild));
$buildApiDocs = $input->getOption('api');
assert(is_bool($buildApiDocs));
$buildSearchIndexes = $input->getOption('search');
assert(is_bool($buildSearchIndexes));
$syncGit = $input->getOption('sync-git');
assert(is_bool($syncGit));
$this->buildDocs->build(
$output,

View File

@@ -11,9 +11,12 @@ use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use function assert;
use function in_array;
use function ini_set;
use function is_bool;
use function is_dir;
use function is_string;
use function mkdir;
use function realpath;
use function sprintf;
@@ -57,12 +60,6 @@ class BuildWebsiteCommand extends Command
null,
InputOption::VALUE_NONE,
'Publish the build to GitHub Pages.'
)
->addOption(
'env',
'e',
InputOption::VALUE_REQUIRED,
'The environment.'
);
}
@@ -70,13 +67,15 @@ class BuildWebsiteCommand extends Command
{
ini_set('memory_limit', '1024M');
$publish = (bool) $input->getOption('publish');
$publish = $input->getOption('publish');
assert(is_bool($publish));
if ($publish && ! in_array($this->env, WebsiteBuilder::PUBLISHABLE_ENVS, true)) {
throw new InvalidArgumentException(sprintf('You cannot publish the "%s" environment.', $this->env));
}
$buildDir = $input->getArgument('build-dir');
assert(is_string($buildDir));
if (! is_dir($buildDir)) {
mkdir($buildDir, 0777, true);

View File

@@ -11,7 +11,9 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Filesystem\Filesystem;
use function array_filter;
use function assert;
use function glob;
use function is_string;
use function sprintf;
class ClearBuildCacheCommand extends Command
@@ -54,6 +56,7 @@ class ClearBuildCacheCommand extends Command
protected function execute(InputInterface $input, OutputInterface $output) : int
{
$buildDir = $input->getArgument('build-dir');
assert(is_string($buildDir));
// clear build directory
$remove = [$buildDir];

View File

@@ -7,7 +7,6 @@ namespace Doctrine\Website\Commands;
use Doctrine\Website\Deployer;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class DeployCommand extends Command
@@ -26,13 +25,7 @@ class DeployCommand extends Command
{
$this
->setName('deploy')
->setDescription('Deploy the Doctrine website.')
->addOption(
'env',
'e',
InputOption::VALUE_REQUIRED,
'The environment.'
);
->setDescription('Deploy the Doctrine website.');
}
protected function execute(InputInterface $input, OutputInterface $output) : int

View File

@@ -1,45 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Website\Controller;
use Doctrine\Website\Builder\SourceFile;
use ReflectionClass;
use RuntimeException;
use function sprintf;
class ControllerExecutor
{
/** @var ControllerProvider */
private $controllerProvider;
public function __construct(ControllerProvider $controllerProvider)
{
$this->controllerProvider = $controllerProvider;
}
/**
* @return mixed[]
*/
public function execute(SourceFile $sourceFile) : array
{
[$className, $methodName] = $sourceFile->getParameter('controller');
$controller = $this->controllerProvider->getController($className);
$reflectionMethod = (new ReflectionClass($controller))->getMethod($methodName);
$controllerResult = $reflectionMethod->invokeArgs($controller, [$sourceFile]);
if (! $controllerResult instanceof ControllerResult) {
throw new RuntimeException(sprintf(
'Controller %s did not return a %s instance.',
$className,
ControllerResult::class
));
}
return $controllerResult->getResult();
}
}

View File

@@ -1,37 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Website\Controller;
use InvalidArgumentException;
use function get_class;
use function sprintf;
class ControllerProvider
{
/** @var object[] */
private $controllers;
/**
* @param object[] $controllers
*/
public function __construct(array $controllers)
{
foreach ($controllers as $controller) {
$this->controllers[get_class($controller)] = $controller;
}
}
/**
* @return object
*/
public function getController(string $className)
{
if (! isset($this->controllers[$className])) {
throw new InvalidArgumentException(sprintf('Could not find controller class %s', $className));
}
return $this->controllers[$className];
}
}

View File

@@ -1,27 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Website\Controller;
class ControllerResult
{
/** @var mixed[] */
private $result;
/**
* @param mixed[] $result
*/
public function __construct(array $result)
{
$this->result = $result;
}
/**
* @return mixed[]
*/
public function getResult() : array
{
return $this->result;
}
}

View File

@@ -4,8 +4,7 @@ declare(strict_types=1);
namespace Doctrine\Website\Controllers;
use Doctrine\Website\Builder\SourceFile;
use Doctrine\Website\Controller\ControllerResult;
use Doctrine\StaticWebsiteGenerator\Controller\Response;
use Doctrine\Website\Repositories\BlogPostRepository;
class AtomController
@@ -18,9 +17,9 @@ class AtomController
$this->blogPostRepository = $blogPostRepository;
}
public function index(SourceFile $sourceFile) : ControllerResult
public function index() : Response
{
return new ControllerResult([
return new Response([
'blogPosts' => $this->blogPostRepository->findPaginated(),
]);
}

View File

@@ -4,8 +4,7 @@ declare(strict_types=1);
namespace Doctrine\Website\Controllers;
use Doctrine\Website\Builder\SourceFile;
use Doctrine\Website\Controller\ControllerResult;
use Doctrine\StaticWebsiteGenerator\Controller\Response;
use Doctrine\Website\Repositories\BlogPostRepository;
class BlogController
@@ -18,24 +17,24 @@ class BlogController
$this->blogPostRepository = $blogPostRepository;
}
public function index(SourceFile $sourceFile) : ControllerResult
public function index() : Response
{
return new ControllerResult([
return new Response([
'blogPosts' => $this->blogPostRepository->findPaginated(),
]);
}
public function archive(SourceFile $sourceFile) : ControllerResult
public function archive() : Response
{
return new ControllerResult([
return new Response([
'blogPosts' => $this->blogPostRepository->findAll(),
]);
}
public function view(SourceFile $sourceFile) : ControllerResult
public function view(string $slug) : Response
{
return new ControllerResult([
'blogPost' => $this->blogPostRepository->find($sourceFile->getParameter('url')),
return new Response([
'blogPost' => $this->blogPostRepository->find($slug),
]);
}
}

View File

@@ -4,8 +4,7 @@ declare(strict_types=1);
namespace Doctrine\Website\Controllers;
use Doctrine\Website\Builder\SourceFile;
use Doctrine\Website\Controller\ControllerResult;
use Doctrine\StaticWebsiteGenerator\Controller\Response;
use Doctrine\Website\Repositories\ProjectRepository;
class DocumentationController
@@ -18,13 +17,13 @@ class DocumentationController
$this->projectRepository = $projectRepository;
}
public function view(SourceFile $sourceFile) : ControllerResult
public function view(string $docsSlug, string $docsVersion) : Response
{
$project = $this->projectRepository->findOneByDocsSlug($sourceFile->getParameter('docsSlug'));
$project = $this->projectRepository->findOneByDocsSlug($docsSlug);
return new ControllerResult([
return new Response([
'project' => $project,
'projectVersion' => $project->getVersion($sourceFile->getParameter('docsVersion')),
'projectVersion' => $project->getVersion($docsVersion),
]);
}
}

View File

@@ -4,8 +4,7 @@ declare(strict_types=1);
namespace Doctrine\Website\Controllers;
use Doctrine\Website\Builder\SourceFile;
use Doctrine\Website\Controller\ControllerResult;
use Doctrine\StaticWebsiteGenerator\Controller\Response;
use Doctrine\Website\Repositories\BlogPostRepository;
use Doctrine\Website\Repositories\DoctrineUserRepository;
use Doctrine\Website\Repositories\ProjectRepository;
@@ -31,13 +30,13 @@ class HomepageController
$this->doctrineUserRepository = $doctrineUserRepository;
}
public function index(SourceFile $sourceFile) : ControllerResult
public function index() : Response
{
$blogPosts = $this->blogPostRepository->findPaginated(1, 10);
$primaryProjects = $this->projectRepository->findPrimaryProjects();
$doctrineUsers = $this->doctrineUserRepository->findAll();
return new ControllerResult([
return new Response([
'blogPosts' => $blogPosts,
'primaryProjects' => $primaryProjects,
'doctrineUsers' => $doctrineUsers,

View File

@@ -4,8 +4,7 @@ declare(strict_types=1);
namespace Doctrine\Website\Controllers;
use Doctrine\Website\Builder\SourceFile;
use Doctrine\Website\Controller\ControllerResult;
use Doctrine\StaticWebsiteGenerator\Controller\Response;
use Doctrine\Website\Repositories\ProjectContributorRepository;
use Doctrine\Website\Repositories\ProjectRepository;
@@ -25,9 +24,9 @@ class ProjectController
$this->projectContributorRepository = $projectContributorRepository;
}
public function index(SourceFile $sourceFile) : ControllerResult
public function index() : Response
{
return new ControllerResult([
return new Response([
'primaryProjects' => $this->projectRepository->findPrimaryProjects(),
'inactiveProjects' => $this->projectRepository->findInactiveProjects(),
'archivedProjects' => $this->projectRepository->findArchivedProjects(),
@@ -35,11 +34,11 @@ class ProjectController
]);
}
public function view(SourceFile $sourceFile) : ControllerResult
public function view(string $docsSlug) : Response
{
$project = $this->projectRepository->findOneByDocsSlug($sourceFile->getParameter('docsSlug'));
$project = $this->projectRepository->findOneByDocsSlug($docsSlug);
return new ControllerResult([
return new Response([
'project' => $project,
'integrationProjects' => $this->projectRepository->findProjectIntegrations($project),
'maintainers' => $this->projectContributorRepository->findMaintainersByProject($project),

View File

@@ -4,8 +4,7 @@ declare(strict_types=1);
namespace Doctrine\Website\Controllers;
use Doctrine\Website\Builder\SourceFile;
use Doctrine\Website\Controller\ControllerResult;
use Doctrine\StaticWebsiteGenerator\Controller\Response;
use Doctrine\Website\Repositories\SitemapPageRepository;
class SitemapController
@@ -18,8 +17,8 @@ class SitemapController
$this->sitemapPageRepository = $sitemapPageRepository;
}
public function index(SourceFile $sourceFile) : ControllerResult
public function index() : Response
{
return new ControllerResult(['pages' => $this->sitemapPageRepository->findAll()]);
return new Response(['pages' => $this->sitemapPageRepository->findAll()]);
}
}

View File

@@ -4,8 +4,7 @@ declare(strict_types=1);
namespace Doctrine\Website\Controllers;
use Doctrine\Website\Builder\SourceFile;
use Doctrine\Website\Controller\ControllerResult;
use Doctrine\StaticWebsiteGenerator\Controller\Response;
use Doctrine\Website\Repositories\ContributorRepository;
class TeamController
@@ -18,17 +17,27 @@ class TeamController
$this->contributorRepository = $contributorRepository;
}
public function maintainers(SourceFile $sourceFile) : ControllerResult
public function maintainers() : Response
{
return new ControllerResult([
return new Response([
'contributors' => $this->contributorRepository->findMaintainers(),
]);
}
public function contributors(SourceFile $sourceFile) : ControllerResult
public function contributors() : Response
{
return new ControllerResult([
return new Response([
'contributors' => $this->contributorRepository->findContributors(),
]);
}
public function contributor(string $github) : Response
{
$contributor = $this->contributorRepository->findOneByGithub($github);
return new Response(
['contributor' => $contributor],
'/team/member.html.twig'
);
}
}

View File

@@ -1,73 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Website\DataSource;
use function in_array;
class CriteriaMatcher
{
/** @var mixed[] */
private $criteria;
/** @var mixed[] */
private $row;
/**
* @param mixed[] $criteria
* @param mixed[] $row
*/
public function __construct(array $criteria, array $row)
{
$this->criteria = $criteria;
$this->row = $row;
}
public function matches() : bool
{
$matches = true;
foreach ($this->criteria as $key => $value) {
if ($this->criteriaElementMatches($key, $value)) {
continue;
}
$matches = false;
}
return $matches;
}
/**
* @param mixed $value
*/
private function criteriaElementMatches(string $key, $value) : bool
{
if (isset($value['$contains'])) {
if ($this->contains($key, $value)) {
return true;
}
} elseif ($this->equals($key, $value)) {
return true;
}
return false;
}
/**
* @param mixed[] $value
*/
private function contains(string $key, array $value) : bool
{
return isset($this->row[$key]) && in_array($value['$contains'], $this->row[$key], true);
}
/**
* @param mixed $value
*/
private function equals(string $key, $value) : bool
{
return isset($this->row[$key]) && $this->row[$key] === $value;
}
}

View File

@@ -1,13 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Website\DataSource;
interface DataSource
{
/**
* @return mixed[][]
*/
public function getSourceRows() : array;
}

View File

@@ -1,139 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Website\DataSource;
use Doctrine\SkeletonMapper\DataRepository\BasicObjectDataRepository;
use Doctrine\SkeletonMapper\ObjectManagerInterface;
use function array_slice;
use function count;
use function usort;
class DataSourceObjectDataRepository extends BasicObjectDataRepository
{
/** @var DataSource */
private $dataSource;
/** @var mixed[][]|null */
private $sourceRows;
public function __construct(
ObjectManagerInterface $objectManager,
DataSource $dataSource,
string $className
) {
parent::__construct($objectManager, $className);
$this->dataSource = $dataSource;
}
/**
* @return mixed[][]
*/
public function findAll() : array
{
return $this->getSourceRows();
}
/**
* @param mixed[] $criteria
* @param mixed[] $orderBy
*
* @return mixed[][]
*/
public function findBy(
array $criteria,
?array $orderBy = null,
?int $limit = null,
?int $offset = null
) : array {
$rows = [];
foreach ($this->getSourceRows() as $row) {
if (! $this->matches($criteria, $row)) {
continue;
}
$rows[] = $row;
}
if ($orderBy !== null && $orderBy !== []) {
$rows = $this->sort($rows, $orderBy);
}
if ($limit !== null || $offset !== null) {
return $this->slice($rows, $limit, $offset);
}
return $rows;
}
/**
* @param mixed[] $criteria
*
* @return mixed[]|null
*/
public function findOneBy(array $criteria) : ?array
{
foreach ($this->getSourceRows() as $row) {
if ($this->matches($criteria, $row)) {
return $row;
}
}
return null;
}
/**
* @param mixed[] $criteria
* @param mixed[] $row
*/
private function matches(array $criteria, array $row) : bool
{
return (new CriteriaMatcher($criteria, $row))->matches();
}
/**
* @param mixed[][] $rows
* @param string[] $orderBy
*
* @return mixed[][] $rows
*/
private function sort(array $rows, array $orderBy) : array
{
usort($rows, new Sorter($orderBy));
return $rows;
}
/**
* @param mixed[][] $rows
*
* @return mixed[][] $rows
*/
private function slice(array $rows, ?int $limit, ?int $offset) : array
{
if ($limit === null) {
$limit = count($rows);
}
if ($offset === null) {
$offset = 0;
}
return array_slice($rows, $offset, $limit);
}
/**
* @return mixed[][]
*/
private function getSourceRows() : array
{
if ($this->sourceRows === null) {
$this->sourceRows = $this->dataSource->getSourceRows();
}
return $this->sourceRows;
}
}

View File

@@ -1,106 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Website\DataSource;
use InvalidArgumentException;
use function count;
use function is_string;
use function sprintf;
use function strtolower;
class Sorter
{
private const ORDER_ASC = 'asc';
private const ORDER_DESC = 'desc';
/** @var int */
private $level = 0;
/** @var string[] */
private $fields;
/** @var int[] */
private $orders;
/**
* @param string[] $orderBy
*/
public function __construct(array $orderBy)
{
if ($orderBy === []) {
throw new InvalidArgumentException('The Sorter class does not accept an empty $orderBy');
}
foreach ($orderBy as $field => $order) {
$this->fields[] = $field;
$this->orders[] = $this->getOrder($order);
}
}
/**
* @param mixed[] $a
* @param mixed[] $b
*/
public function __invoke(array $a, array $b) : int
{
$returnVal = 0;
$comparisonField = $this->fields[$this->level];
$order = $this->orders[$this->level];
$aComparisonField = $this->getComparisonField($a, $comparisonField);
$bComparisonField = $this->getComparisonField($b, $comparisonField);
$comparisonResult = $aComparisonField <=> $bComparisonField;
if ($comparisonResult !== 0) {
$returnVal = $comparisonResult;
} else {
if ($this->level < count($this->fields) - 1) {
$this->level++;
return $this->__invoke($a, $b);
}
}
$returnVal *= $order;
$this->level = 0;
return $returnVal;
}
private function getOrder(string $order) : int
{
$lowercaseOrder = strtolower($order);
if ($lowercaseOrder === self::ORDER_ASC) {
return 1;
}
if ($lowercaseOrder === self::ORDER_DESC) {
return -1;
}
throw new InvalidArgumentException(sprintf(
'$order value of %s is not accepted. Only a value of asc or desc is allowed.',
$order
));
}
/**
* @param mixed[] $item
*
* @return mixed
*/
private function getComparisonField(array $item, string $field)
{
if (! isset($item[$field])) {
throw new InvalidArgumentException(sprintf('Unable to find comparison field %s', $field));
}
$value = $item[$field];
return is_string($value) ? strtolower($value) : $value;
}
}

View File

@@ -4,18 +4,17 @@ declare(strict_types=1);
namespace Doctrine\Website\DataSources;
use Doctrine\Website\Builder\SourceFileRepository;
use Doctrine\Website\DataSource\DataSource;
use function array_reverse;
use Doctrine\SkeletonMapper\DataSource\DataSource;
use Doctrine\StaticWebsiteGenerator\SourceFile\SourceFileFilesystemReader;
class BlogPosts implements DataSource
{
/** @var SourceFileRepository */
private $sourceFileRepository;
/** @var SourceFileFilesystemReader */
private $sourceFileFilesystemReader;
public function __construct(SourceFileRepository $sourceFileRepository)
public function __construct(SourceFileFilesystemReader $sourceFileFilesystemReader)
{
$this->sourceFileRepository = $sourceFileRepository;
$this->sourceFileFilesystemReader = $sourceFileFilesystemReader;
}
/**
@@ -23,15 +22,15 @@ class BlogPosts implements DataSource
*/
public function getSourceRows() : array
{
$sourceFiles = $this->sourceFileRepository->getFiles('', 'source/blog');
$reversedSourceFiles = array_reverse($sourceFiles);
$sourceFiles = $this->sourceFileFilesystemReader
->getSourceFiles()->in('/blog/');
$blogPostRows = [];
foreach ($reversedSourceFiles as $sourceFile) {
foreach ($sourceFiles as $sourceFile) {
$blogPostRows[] = [
'url' => $sourceFile->getParameter('url'),
'slug' => $sourceFile->getParameter('slug'),
'title' => $sourceFile->getParameter('title'),
'authorName' => (string) $sourceFile->getParameter('authorName'),
'authorEmail' => (string) $sourceFile->getParameter('authorEmail'),

View File

@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Doctrine\Website\DataSources;
use Doctrine\Website\DataSource\DataSource;
use Doctrine\SkeletonMapper\DataSource\DataSource;
use Doctrine\Website\Repositories\ProjectContributorRepository;
class Contributors implements DataSource

View File

@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Doctrine\Website\DataSources;
use Doctrine\Website\DataSource\DataSource;
use Doctrine\SkeletonMapper\DataSource\DataSource;
class DoctrineUsers implements DataSource
{

View File

@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Doctrine\Website\DataSources;
use Doctrine\Website\DataSource\DataSource;
use Doctrine\SkeletonMapper\DataSource\DataSource;
use Doctrine\Website\Github\GithubProjectContributors;
use Doctrine\Website\Repositories\ProjectRepository;
use Doctrine\Website\Repositories\TeamMemberRepository;
@@ -51,7 +51,13 @@ class ProjectContributors implements DataSource
$numDeletions += $week['d'];
}
$teamMember = $this->teamMemberRepository->findOneByGithub($contributor['author']['login']);
if (! isset($contributor['author']['login'])) {
continue;
}
$teamMember = $this->teamMemberRepository->findOneByGithub(
$contributor['author']['login']
);
$isMaintainer = $teamMember !== null
? $teamMember->isProjectMaintainer($project)

View File

@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Doctrine\Website\DataSources;
use Doctrine\Website\DataSource\DataSource;
use Doctrine\SkeletonMapper\DataSource\DataSource;
use Doctrine\Website\Projects\ProjectDataReader;
use function array_replace;

View File

@@ -5,24 +5,17 @@ declare(strict_types=1);
namespace Doctrine\Website\DataSources;
use DateTimeImmutable;
use Doctrine\Website\DataSource\DataSource;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use function array_merge;
use function assert;
use function file_exists;
use function filemtime;
use function is_int;
use function str_replace;
use Doctrine\SkeletonMapper\DataSource\DataSource;
use Doctrine\StaticWebsiteGenerator\SourceFile\SourceFileRepository;
class SitemapPages implements DataSource
{
/** @var string */
private $sourcePath;
/** @var SourceFileRepository */
private $sourceFileRepository;
public function __construct(string $sourcePath)
public function __construct(SourceFileRepository $sourceFileRepository)
{
$this->sourcePath = $sourcePath;
$this->sourceFileRepository = $sourceFileRepository;
}
/**
@@ -30,51 +23,15 @@ class SitemapPages implements DataSource
*/
public function getSourceRows() : array
{
return array_merge(
[
[
'url' => '/',
'date' => new DateTimeImmutable(),
],
],
$this->getSitemapPagesDataFromFiles('projects'),
$this->getSitemapPagesDataFromFiles('api')
);
}
$sitemapPages = [];
/**
* @return mixed[][]
*/
private function getSitemapPagesDataFromFiles(string $path) : array
{
$path = $this->sourcePath . '/' . $path;
if (! file_exists($path)) {
return [];
}
$it = new RecursiveDirectoryIterator(
$path,
RecursiveDirectoryIterator::SKIP_DOTS | RecursiveDirectoryIterator::CURRENT_AS_PATHNAME
);
$it = new RecursiveIteratorIterator($it);
$urls = [];
foreach ($it as $file) {
$url = str_replace($this->sourcePath, '', $file);
$timestamp = filemtime($file);
assert(is_int($timestamp));
$date = (new DateTimeImmutable())->setTimestamp($timestamp);
$urls[] = [
'url' => $url,
'date' => $date,
foreach ($this->sourceFileRepository->getSourceFiles() as $sourceFile) {
$sitemapPages[] = [
'url' => $sourceFile->getUrl(),
'date' => new DateTimeImmutable(),
];
}
return $urls;
return $sitemapPages;
}
}

View File

@@ -4,7 +4,7 @@ declare(strict_types=1);
namespace Doctrine\Website\DataSources;
use Doctrine\Website\DataSource\DataSource;
use Doctrine\SkeletonMapper\DataSource\DataSource;
class TeamMembers implements DataSource
{

View File

@@ -17,19 +17,19 @@ class APIBuilder
private $processFactory;
/** @var string */
private $projectsPath;
private $projectsDir;
/** @var string */
private $sourcePath;
private $sourceDir;
public function __construct(
ProcessFactory $processFactory,
string $projectsPath,
string $sourcePath
string $projectsDir,
string $sourceDir
) {
$this->processFactory = $processFactory;
$this->projectsPath = $projectsPath;
$this->sourcePath = $sourcePath;
$this->projectsDir = $projectsDir;
$this->sourceDir = $sourceDir;
}
public function buildAPIDocs(
@@ -49,9 +49,9 @@ return new Sami\Sami('%s', [
]);
CONFIG;
$codeDir = $this->projectsPath . '/' . $project->getRepositoryName() . $project->getCodePath();
$buildDir = $this->sourcePath . '/api/' . $project->getSlug() . '/' . $version->getSlug();
$cacheDir = $this->projectsPath . '/' . $project->getRepositoryName() . '/cache';
$codeDir = $this->projectsDir . '/' . $project->getRepositoryName() . $project->getCodePath();
$buildDir = $this->sourceDir . '/api/' . $project->getSlug() . '/' . $version->getSlug();
$cacheDir = $this->projectsDir . '/' . $project->getRepositoryName() . '/cache';
$renderedConfigContent = sprintf(
$configContent,
@@ -59,12 +59,12 @@ CONFIG;
$buildDir,
$cacheDir,
'doctrine/' . $project->getRepositoryName(),
$this->projectsPath . '/' . $project->getRepositoryName(),
$this->projectsDir . '/' . $project->getRepositoryName(),
$version->getBranchName()
);
$configPath = $this->projectsPath . '/' . $project->getRepositoryName() . '/sami.php';
$samiPharPath = $this->sourcePath . '/../sami.phar';
$configPath = $this->projectsDir . '/' . $project->getRepositoryName() . '/sami.php';
$samiPharPath = $this->sourceDir . '/../sami.phar';
$this->filePutContents($configPath, $renderedConfigContent);

View File

@@ -28,10 +28,10 @@ class RSTBuilder
private $filesystem;
/** @var string */
private $sourcePath;
private $sourceDir;
/** @var string */
private $docsPath;
private $docsDir;
public function __construct(
RSTFileRepository $rstFileRepository,
@@ -39,16 +39,16 @@ class RSTBuilder
Builder $builder,
RSTPostBuildProcessor $rstPostBuildProcessor,
Filesystem $filesystem,
string $sourcePath,
string $docsPath
string $sourceDir,
string $docsDir
) {
$this->rstFileRepository = $rstFileRepository;
$this->rstCopier = $rstCopier;
$this->builder = $builder;
$this->rstPostBuildProcessor = $rstPostBuildProcessor;
$this->filesystem = $filesystem;
$this->sourcePath = $sourcePath;
$this->docsPath = $docsPath;
$this->sourceDir = $sourceDir;
$this->docsDir = $docsDir;
}
/**
@@ -56,7 +56,7 @@ class RSTBuilder
*/
public function buildRSTDocs(Project $project, ProjectVersion $version, RSTLanguage $language) : array
{
// copy the docs from the project to a central location in $docsPath
// copy the docs from the project to a central location in $docsDir
$this->rstCopier->copyRst($project, $version);
// build the rst and prepare html for ./bin/console build-website
@@ -70,7 +70,7 @@ class RSTBuilder
private function buildRst(Project $project, ProjectVersion $version, RSTLanguage $language) : void
{
$outputPath = $project->getProjectVersionDocsOutputPath($this->sourcePath, $version, $language->getCode());
$outputPath = $project->getProjectVersionDocsOutputPath($this->sourceDir, $version, $language->getCode());
// clear the files in the output path first
$this->filesystem->remove($this->rstFileRepository->findFiles($outputPath));
@@ -78,10 +78,10 @@ class RSTBuilder
// we have to get a fresh builder due to how the RST parser works
$this->builder = $this->builder->recreate();
// build the docs from the files in $docsPath and write them to $outputPath
// which is contained inside the $sourcePath
// build the docs from the files in $docsDir and write them to $outputPath
// which is contained inside the $sourceDir
$this->builder->build(
$project->getProjectVersionDocsPath($this->docsPath, $version, $language->getCode()),
$project->getProjectVersionDocsPath($this->docsDir, $version, $language->getCode()),
$outputPath,
false
);

View File

@@ -56,18 +56,18 @@ SIDEBAR;
private $filesystem;
/** @var string */
private $docsPath;
private $docsDir;
public function __construct(
RSTFileRepository $rstFileRepository,
RSTLanguagesDetector $rstLanguagesDetector,
Filesystem $filesystem,
string $docsPath
string $docsDir
) {
$this->rstFileRepository = $rstFileRepository;
$this->rstLanguagesDetector = $rstLanguagesDetector;
$this->filesystem = $filesystem;
$this->docsPath = $docsPath;
$this->docsDir = $docsDir;
}
public function copyRst(Project $project, ProjectVersion $version) : void
@@ -75,7 +75,7 @@ SIDEBAR;
$languages = $this->rstLanguagesDetector->detectLanguages($project, $version);
foreach ($languages as $language) {
$outputPath = $project->getProjectVersionDocsPath($this->docsPath, $version, $language->getCode());
$outputPath = $project->getProjectVersionDocsPath($this->docsDir, $version, $language->getCode());
// clear existing files before copying the rst over
$this->filesystem->remove($this->rstFileRepository->findFiles($outputPath));
@@ -131,7 +131,7 @@ SIDEBAR;
// append the source file name to the content so we can parse it back out
// for use in the build process
return $content . sprintf('{{ SOURCE_FILE:%s }}', $sourceFile);
return $content . sprintf('{{ DOCS_SOURCE_PATH:%s }}', $sourceFile);
}
private function fixRSTSyntax(Project $project, string $content) : string
@@ -172,11 +172,11 @@ SIDEBAR;
return $content;
}
private function getSidebarRST(string $docsPath) : string
private function getSidebarRST(string $docsDir) : string
{
// check if we have an explicit sidebar file to use
// otherwise just use the default autogenerated sidebar
$sidebarPath = $docsPath . '/sidebar.rst';
$sidebarPath = $docsDir . '/sidebar.rst';
return file_exists($sidebarPath)
? $this->rstFileRepository->getFileContents($sidebarPath)

View File

@@ -21,11 +21,11 @@ class RSTLanguagesDetector
public const ENGLISH_LANGUAGE_CODE = 'en';
/** @var string */
private $projectsPath;
private $projectsDir;
public function __construct(string $projectsPath)
public function __construct(string $projectsDir)
{
$this->projectsPath = $projectsPath;
$this->projectsDir = $projectsDir;
}
/**
@@ -35,11 +35,11 @@ class RSTLanguagesDetector
{
$finder = new Finder();
$docsPath = $project->getAbsoluteDocsPath($this->projectsPath);
$docsDir = $project->getAbsoluteDocsPath($this->projectsDir);
$finder
->directories()
->in($docsPath);
->in($docsDir);
$files = array_values(array_map(static function (SplFileInfo $file) {
return $file->getRealPath();
@@ -59,7 +59,7 @@ class RSTLanguagesDetector
continue;
}
$languagePath = $project->getAbsoluteDocsPath($this->projectsPath) . '/' . $languageCode;
$languagePath = $project->getAbsoluteDocsPath($this->projectsDir) . '/' . $languageCode;
$languages[] = new RSTLanguage(
$languageCode,
@@ -71,7 +71,7 @@ class RSTLanguagesDetector
}
return [
new RSTLanguage(self::ENGLISH_LANGUAGE_CODE, $project->getAbsoluteDocsPath($this->projectsPath)),
new RSTLanguage(self::ENGLISH_LANGUAGE_CODE, $project->getAbsoluteDocsPath($this->projectsDir)),
];
}
}

View File

@@ -17,18 +17,9 @@ class RSTPostBuildProcessor
{
public const PARAMETERS_TEMPLATE = <<<TEMPLATE
---
layout: "documentation"
indexed: true
title: "%s"
menuSlug: "projects"
docsSlug: "%s"
docsPage: true
docsIndex: %s
docsVersion: "%s"
sourceFile: "%s"
lanuage: "%s"
permalink: "none"
controller: ['Doctrine\Website\Controllers\DocumentationController', 'view']
docsSourcePath: "%s"
---
%s
TEMPLATE;
@@ -40,22 +31,22 @@ TEMPLATE;
private $filesystem;
/** @var string */
private $sourcePath;
private $sourceDir;
public function __construct(
RSTFileRepository $rstFileRepository,
Filesystem $filesystem,
string $sourcePath
string $sourceDir
) {
$this->rstFileRepository = $rstFileRepository;
$this->filesystem = $filesystem;
$this->sourcePath = $sourcePath;
$this->sourceDir = $sourceDir;
}
public function postRstBuild(Project $project, ProjectVersion $version, RSTLanguage $language) : void
{
$projectVersionDocsOutputPath = $project->getProjectVersionDocsOutputPath(
$this->sourcePath,
$this->sourceDir,
$version,
$language->getCode()
);
@@ -110,11 +101,11 @@ TEMPLATE;
string $contents
) : string {
// parse out the source file that generated this file
preg_match('/<p>{{ SOURCE_FILE:(.*) }}<\/p>/', $contents, $match);
preg_match('/<p>{{ DOCS_SOURCE_PATH:(.*) }}<\/p>/', $contents, $match);
$sourceFile = $match[1];
$docsSourcePath = $match[1];
// get rid of the special SOURCE_FILE: syntax in the contents
// get rid of the special DOCS_SOURCE_PATH: syntax in the contents
$contents = str_replace($match[0], '', $contents);
$title = $this->extractTitle($contents);
@@ -124,11 +115,8 @@ TEMPLATE;
return sprintf(
self::PARAMETERS_TEMPLATE,
$title,
$project->getDocsSlug(),
strpos($file, 'index.html') !== false ? 'true' : 'false',
$version->getSlug(),
$sourceFile,
$language->getCode(),
$docsSourcePath,
$contents
);
}

View File

@@ -102,7 +102,7 @@ class SearchIndexer
foreach ($nodes as $node) {
$value = (string) $node->getValue();
if (strpos($value, '{{ SOURCE_FILE') !== false) {
if (strpos($value, '{{ DOCS_SOURCE_PATH') !== false) {
continue;
}

View File

@@ -15,6 +15,9 @@ class BlogPost implements HydratableInterface, LoadMetadataInterface
/** @var string */
private $url;
/** @var string */
private $slug;
/** @var string */
private $title;
@@ -32,6 +35,7 @@ class BlogPost implements HydratableInterface, LoadMetadataInterface
public function __construct(
string $url,
string $slug,
string $title,
string $authorName,
string $authorEmail,
@@ -39,6 +43,7 @@ class BlogPost implements HydratableInterface, LoadMetadataInterface
DateTimeImmutable $date
) {
$this->url = $url;
$this->slug = $slug;
$this->title = $title;
$this->authorName = $authorName;
$this->authorEmail = $authorEmail;
@@ -48,7 +53,7 @@ class BlogPost implements HydratableInterface, LoadMetadataInterface
public static function loadMetadata(ClassMetadataInterface $metadata) : void
{
$metadata->setIdentifier(['url']);
$metadata->setIdentifier(['slug']);
}
/**
@@ -57,6 +62,7 @@ class BlogPost implements HydratableInterface, LoadMetadataInterface
public function hydrate(array $project, ObjectManagerInterface $objectManager) : void
{
$this->url = (string) $project['url'] ?? '';
$this->slug = (string) $project['slug'] ?? '';
$this->title = (string) $project['title'] ?? '';
$this->authorName = (string) $project['authorName'] ?? '';
$this->authorEmail = (string) $project['authorEmail'] ?? '';
@@ -69,6 +75,11 @@ class BlogPost implements HydratableInterface, LoadMetadataInterface
return $this->url;
}
public function getSlug() : string
{
return $this->slug;
}
public function getTitle() : string
{
return $this->title;

View File

@@ -273,19 +273,19 @@ class Project implements HydratableInterface, LoadMetadataInterface
})[0] ?? ($this->versions[0] ?? null);
}
public function getProjectDocsRepositoryPath(string $projectsPath) : string
public function getProjectDocsRepositoryPath(string $projectsDir) : string
{
return $projectsPath . '/' . $this->getDocsRepositoryName();
return $projectsDir . '/' . $this->getDocsRepositoryName();
}
public function getProjectRepositoryPath(string $projectsPath) : string
public function getProjectRepositoryPath(string $projectsDir) : string
{
return $projectsPath . '/' . $this->getRepositoryName();
return $projectsDir . '/' . $this->getRepositoryName();
}
public function getAbsoluteDocsPath(string $projectsPath) : string
public function getAbsoluteDocsPath(string $projectsDir) : string
{
return $this->getProjectDocsRepositoryPath($projectsPath) . $this->getDocsPath();
return $this->getProjectDocsRepositoryPath($projectsDir) . $this->getDocsPath();
}
public function getProjectVersionDocsPath(string $docsPath, ProjectVersion $version, string $language) : string

View File

@@ -25,7 +25,7 @@ class ProjectDataReader
private const COMPOSER_JSON_FILE_NAME = 'composer.json';
/** @var string */
private $projectsPath;
private $projectsDir;
/** @var mixed[] */
private $projectsData;
@@ -38,11 +38,11 @@ class ProjectDataReader
* @param mixed[] $projectIntegrationTypes
*/
public function __construct(
string $projectsPath,
string $projectsDir,
array $projectsData,
array $projectIntegrationTypes
) {
$this->projectsPath = $projectsPath;
$this->projectsDir = $projectsDir;
$this->projectsData = $projectsData;
$this->projectIntegrationTypes = $projectIntegrationTypes;
}
@@ -142,7 +142,7 @@ class ProjectDataReader
private function detectPath(string $repositoryName, array $pathsToCheck, ?string $default) : ?string
{
foreach ($pathsToCheck as $path) {
$check = $this->projectsPath . '/' . $repositoryName . $path;
$check = $this->projectsDir . '/' . $repositoryName . $path;
if (is_dir($check)) {
return $path;
@@ -181,7 +181,7 @@ class ProjectDataReader
*/
private function readJsonFile(string $repositoryName, string $fileName) : array
{
$filePath = $this->projectsPath . '/' . $repositoryName . '/' . $fileName;
$filePath = $this->projectsDir . '/' . $repositoryName . '/' . $fileName;
if (! file_exists($filePath)) {
return [];

View File

@@ -16,22 +16,22 @@ class ProjectGitSyncer
private $processFactory;
/** @var string */
private $projectsPath;
private $projectsDir;
public function __construct(ProcessFactory $processFactory, string $projectsPath)
public function __construct(ProcessFactory $processFactory, string $projectsDir)
{
$this->processFactory = $processFactory;
$this->projectsPath = $projectsPath;
$this->projectsDir = $projectsDir;
}
public function isRepositoryInitialized(string $repositoryName) : bool
{
return is_dir($this->projectsPath . '/' . $repositoryName);
return is_dir($this->projectsDir . '/' . $repositoryName);
}
public function initRepository(string $repositoryName) : void
{
$repositoryPath = $this->projectsPath . '/' . $repositoryName;
$repositoryPath = $this->projectsDir . '/' . $repositoryName;
if (is_dir($repositoryPath)) {
return;
@@ -51,13 +51,13 @@ class ProjectGitSyncer
// handle when docs are in a different repository then the code
if ($project->getDocsRepositoryName() !== $project->getRepositoryName()) {
$this->syncRepository(
$project->getProjectRepositoryPath($this->projectsPath)
$project->getProjectRepositoryPath($this->projectsDir)
);
}
// sync docs repository
$this->syncRepository(
$project->getProjectDocsRepositoryPath($this->projectsPath)
$project->getProjectDocsRepositoryPath($this->projectsDir)
);
}
@@ -74,10 +74,10 @@ class ProjectGitSyncer
private function checkoutBranch(Project $project, string $branchName) : void
{
if ($project->getDocsRepositoryName() !== $project->getRepositoryName()) {
$this->doCheckoutBranch($project->getProjectRepositoryPath($this->projectsPath), $branchName);
$this->doCheckoutBranch($project->getProjectRepositoryPath($this->projectsDir), $branchName);
}
$this->doCheckoutBranch($project->getProjectDocsRepositoryPath($this->projectsPath), $branchName);
$this->doCheckoutBranch($project->getProjectDocsRepositoryPath($this->projectsDir), $branchName);
}
private function doCheckoutBranch(string $directory, string $branchName) : void

View File

@@ -5,11 +5,13 @@ declare(strict_types=1);
namespace Doctrine\Website\RST;
use Doctrine\RST\Builder;
use Doctrine\RST\Configuration;
use Doctrine\RST\Directive;
use Doctrine\RST\Document;
use Doctrine\RST\Factory;
use Doctrine\RST\Environment as BaseEnvironment;
use Doctrine\RST\HTML\Kernel as HtmlKernel;
use Doctrine\RST\Kernel as BaseKernel;
use Doctrine\RST\NodeFactory;
use Doctrine\RST\Reference;
use function array_merge;
@@ -19,7 +21,7 @@ class Kernel extends BaseKernel
private $baseKernel;
/** @var Directive[] */
private $directives;
protected $directives;
/**
* @param Directive[] $directives
@@ -29,7 +31,7 @@ class Kernel extends BaseKernel
$this->baseKernel = $baseKernel;
$this->directives = $directives;
parent::__construct($directives);
parent::__construct(null, $directives);
}
public function getName() : string
@@ -40,9 +42,14 @@ class Kernel extends BaseKernel
/**
* @return Directive[]
*/
public function getDirectives() : array
public function createDirectives() : array
{
return array_merge($this->baseKernel->getDirectives(), $this->directives);
return array_merge($this->baseKernel->createDirectives(), $this->directives);
}
public function createEnvironment(?Configuration $configuration = null) : BaseEnvironment
{
return $this->baseKernel->createEnvironment($configuration);
}
public function getFileExtension() : string
@@ -50,11 +57,6 @@ class Kernel extends BaseKernel
return $this->baseKernel->getFileExtension();
}
public function getFactory() : Factory
{
return $this->baseKernel->getFactory();
}
/**
* @return Reference[]
*/
@@ -72,4 +74,9 @@ class Kernel extends BaseKernel
{
$this->baseKernel->initBuilder($builder);
}
protected function createNodeFactory() : NodeFactory
{
return $this->baseKernel->createNodeFactory();
}
}

View File

@@ -9,6 +9,11 @@ use Doctrine\Website\Model\Contributor;
class ContributorRepository extends BasicObjectRepository
{
public function findOneByGithub(string $github) : Contributor
{
return $this->findOneBy(['github' => $github]);
}
/**
* @return Contributor[]
*/

View File

@@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace Doctrine\Website\Requests;
use Doctrine\StaticWebsiteGenerator\Request\ArrayRequestCollection;
use Doctrine\StaticWebsiteGenerator\Request\RequestCollection;
use Doctrine\Website\Model\Contributor;
use Doctrine\Website\Repositories\ContributorRepository;
class ContributorRequests
{
/** @var ContributorRepository */
private $contributorRepository;
public function __construct(ContributorRepository $contributorRepository)
{
$this->contributorRepository = $contributorRepository;
}
public function getContributors() : RequestCollection
{
/** @var Contributor[] $contributors */
$contributors = $this->contributorRepository->findAll();
$requests = [];
foreach ($contributors as $contributor) {
$requests[] = [
'github' => $contributor->getGithub(),
];
}
return new ArrayRequestCollection($requests);
}
}

View File

@@ -1,88 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Website;
class Site
{
/** @var string */
private $title;
/** @var string */
private $subtitle;
/** @var string */
private $url;
/** @var string[] */
private $keywords;
/** @var string */
private $description;
/** @var string */
private $env;
/** @var string */
private $googleAnalyticsTrackingId;
/**
* @param string[] $keywords
*/
public function __construct(
string $title,
string $subtitle,
string $url,
array $keywords,
string $description,
string $env,
string $googleAnalyticsTrackingId
) {
$this->title = $title;
$this->subtitle = $subtitle;
$this->url = $url;
$this->keywords = $keywords;
$this->description = $description;
$this->env = $env;
$this->googleAnalyticsTrackingId = $googleAnalyticsTrackingId;
}
public function getTitle() : string
{
return $this->title;
}
public function getSubtitle() : string
{
return $this->subtitle;
}
public function getUrl() : string
{
return $this->url;
}
/**
* @return string[]
*/
public function getKeywords() : array
{
return $this->keywords;
}
public function getDescription() : string
{
return $this->description;
}
public function getEnv() : string
{
return $this->env;
}
public function googleAnalyticsTrackingId() : string
{
return $this->googleAnalyticsTrackingId;
}
}

View File

@@ -26,17 +26,17 @@ class MainExtension extends Twig_Extension
private $assetIntegrityGenerator;
/** @var string */
private $sourcePath;
private $sourceDir;
/** @var string */
private $webpackBuildPath;
private $webpackBuildDir;
public function __construct(Parsedown $parsedown, AssetIntegrityGenerator $assetIntegrityGenerator, string $sourcePath, string $webpackBuildPath)
public function __construct(Parsedown $parsedown, AssetIntegrityGenerator $assetIntegrityGenerator, string $sourceDir, string $webpackBuildDir)
{
$this->parsedown = $parsedown;
$this->assetIntegrityGenerator = $assetIntegrityGenerator;
$this->sourcePath = $sourcePath;
$this->webpackBuildPath = $webpackBuildPath;
$this->sourceDir = $sourceDir;
$this->webpackBuildDir = $webpackBuildDir;
}
/**
@@ -82,12 +82,12 @@ class MainExtension extends Twig_Extension
public function getAssetUrl(string $path, string $siteUrl, string $rootPath = null) : string
{
return $siteUrl . $path . '?' . $this->getAssetCacheBuster($path, $rootPath ?? $this->sourcePath);
return $siteUrl . $path . '?' . $this->getAssetCacheBuster($path, $rootPath ?? $this->sourceDir);
}
public function getWebpackAssetUrl(string $path, string $siteUrl) : string
{
return $this->getAssetUrl($path, $siteUrl, $this->webpackBuildPath);
return $this->getAssetUrl($path, $siteUrl, $this->webpackBuildDir);
}
private function getAssetCacheBuster(string $path, string $rootPath) : string

View File

@@ -19,12 +19,12 @@ class ProjectExtension extends Twig_Extension
private $projectRepository;
/** @var string */
private $sourcePath;
private $sourceDir;
public function __construct(ProjectRepository $projectRepository, string $sourcePath)
public function __construct(ProjectRepository $projectRepository, string $sourceDir)
{
$this->projectRepository = $projectRepository;
$this->sourcePath = $sourcePath;
$this->sourceDir = $sourceDir;
}
/**
@@ -52,7 +52,7 @@ class ProjectExtension extends Twig_Extension
$otherVersionUrl = str_replace($currentVersion, $projectVersion->getSlug(), $url);
}
$otherVersionFile = $this->sourcePath . $otherVersionUrl;
$otherVersionFile = $this->sourceDir . $otherVersionUrl;
if (! $this->fileExists($otherVersionFile)) {
return null;

View File

@@ -1,53 +0,0 @@
<?php
declare(strict_types=1);
namespace Doctrine\Website\Twig;
use Twig\Environment;
use Twig\Loader\ArrayLoader;
use Twig\Loader\ChainLoader;
use Twig\Loader\FilesystemLoader;
class TwigRenderer
{
/** @var MainExtension */
private $mainExtension;
/** @var ProjectExtension */
private $projectExtension;
/** @var string */
private $templatesPath;
public function __construct(
MainExtension $mainExtension,
ProjectExtension $projectExtension,
string $templatesPath
) {
$this->mainExtension = $mainExtension;
$this->projectExtension = $projectExtension;
$this->templatesPath = $templatesPath;
}
/**
* @param mixed[] $parameters
*/
public function render(string $twig, array $parameters) : string
{
$name = $parameters['page']['url'];
$loader = new ArrayLoader([$name => $twig]);
$chainLoader = new ChainLoader([
$loader,
new FilesystemLoader($this->templatesPath),
]);
$twig = new Environment($chainLoader, ['strict_variables' => true]);
$twig->addExtension($this->mainExtension);
$twig->addExtension($this->projectExtension);
return $twig->render($name, $parameters);
}
}

View File

@@ -4,15 +4,14 @@ declare(strict_types=1);
namespace Doctrine\Website;
use Doctrine\Website\Builder\SourceFileBuilder;
use Doctrine\Website\Builder\SourceFileRepository;
use Doctrine\StaticWebsiteGenerator\SourceFile\SourceFileRepository;
use Doctrine\StaticWebsiteGenerator\SourceFile\SourceFilesBuilder;
use Doctrine\Website\Model\Project;
use Doctrine\Website\Model\ProjectVersion;
use Doctrine\Website\Repositories\ProjectRepository;
use RuntimeException;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Filesystem\Filesystem;
use Throwable;
use function chdir;
use function file_exists;
use function file_put_contents;
@@ -47,26 +46,26 @@ class WebsiteBuilder
/** @var SourceFileRepository */
private $sourceFileRepository;
/** @var SourceFileBuilder */
private $sourceFileBuilder;
/** @var SourceFilesBuilder */
private $sourceFilesBuilder;
/** @var string */
private $webpackBuildPath;
private $webpackBuildDir;
public function __construct(
ProcessFactory $processFactory,
ProjectRepository $projectRepository,
Filesystem $filesystem,
SourceFileRepository $sourceFileRepository,
SourceFileBuilder $sourceFileBuilder,
string $webpackBuildPath
SourceFilesBuilder $sourceFilesBuilder,
string $webpackBuildDir
) {
$this->processFactory = $processFactory;
$this->projectRepository = $projectRepository;
$this->filesystem = $filesystem;
$this->sourceFileRepository = $sourceFileRepository;
$this->sourceFileBuilder = $sourceFileBuilder;
$this->webpackBuildPath = $webpackBuildPath;
$this->processFactory = $processFactory;
$this->projectRepository = $projectRepository;
$this->filesystem = $filesystem;
$this->sourceFileRepository = $sourceFileRepository;
$this->sourceFilesBuilder = $sourceFilesBuilder;
$this->webpackBuildDir = $webpackBuildDir;
}
public function build(
@@ -124,35 +123,27 @@ class WebsiteBuilder
// Move webpack assets into build directory
$this->buildWebpackAssets($buildDir, $isPublishableEnv);
foreach ($this->sourceFileRepository->getFiles($buildDir) as $file) {
try {
$this->sourceFileBuilder->buildFile($file, $buildDir);
} catch (Throwable $e) {
throw new RuntimeException(sprintf(
'Failed building file "%s" with error "%s',
$file->getWritePath(),
$e->getMessage() . "\n\n" . $e->getTraceAsString()
));
}
}
$this->sourceFilesBuilder->buildSourceFiles(
$this->sourceFileRepository->getSourceFiles($buildDir)
);
}
private function buildWebpackAssets(string $buildDir, bool $isPublishableEnv) : void
{
$this->filesystem->remove(glob($this->webpackBuildPath . '/*'));
$this->filesystem->remove(glob($this->webpackBuildDir . '/*'));
$this->processFactory->run(sprintf('cd %s && npm run %s',
$buildDir, $isPublishableEnv ? 'build' : 'dev'));
// Copy built assets if this is a publishable build
if ($isPublishableEnv) {
$this->filesystem->mirror($this->webpackBuildPath, $buildDir);
$this->filesystem->mirror($this->webpackBuildDir, $buildDir);
return;
}
// Symlink files to allow files to auto update using webpack --watch
$this->filesystem->mkdir($buildDir);
$this->filesystem->symlink($this->webpackBuildPath . '/css', $buildDir . '/css', true);
$this->filesystem->symlink($this->webpackBuildPath . '/js', $buildDir . '/js', true);
$this->filesystem->symlink($this->webpackBuildDir . '/css', $buildDir . '/css', true);
$this->filesystem->symlink($this->webpackBuildDir . '/js', $buildDir . '/js', true);
}
private function createProjectVersionAliases(string $buildDir) : void

View File

@@ -1,9 +1,5 @@
---
layout: default
title: Blog Archive
menuSlug: blog
permalink: /blog/archive.html
controller: ['Doctrine\Website\Controllers\BlogController', 'archive']
---
<h1>Blog Archive</h1>

View File

@@ -1,8 +1,3 @@
---
permalink: /atom.xml
controller: ['Doctrine\Website\Controllers\AtomController', 'index']
---
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[{{ site.title }}]]></title>

View File

@@ -1,9 +1,5 @@
---
layout: default
title: Blog
menuSlug: blog
permalink: /blog/index.html
controller: ['Doctrine\Website\Controllers\BlogController', 'index']
---
{% for blogPost in blogPosts %}

View File

@@ -1,8 +1,5 @@
---
title: "New Website"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "New Coverage Report"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "Beta 2"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "Beta 2 Released"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: [release]

View File

@@ -1,8 +1,5 @@
---
title: "URL Changes"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "New Design"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "Project Status"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "Cleaning up the mess"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: guilhermeblanco
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "A few updates for 2008"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "Using Doctrine with CodeIgniter"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "Doctrine all grown up"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "Doctrine 0.9.1 / 0.10.1 Released"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: [release]

View File

@@ -1,8 +1,5 @@
---
title: "Doctrine ORM Sandbox"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "0.10.2 Released"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: [release]

View File

@@ -1,8 +1,5 @@
---
title: "My First Project Doctrine Tutorial"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "Doctrine Cheat Sheet"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "4,000th svn commit/revision"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "0.10.3 Released"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: [release]

View File

@@ -1,8 +1,5 @@
---
title: "0.10.4 Released - 46 Closed Tickets"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: [release]

View File

@@ -1,8 +1,5 @@
---
title: "Using Doctrine with Zend Framework"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "APRIL FOOLS! Doctrine goes PECL"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "Doctrine frequently asked questions"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "0.11.0 Release Candidate 1"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: [release]

View File

@@ -1,8 +1,5 @@
---
title: "0.11.0 Release Candidate 2"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: [release]

View File

@@ -1,8 +1,5 @@
---
title: "Wow! 1000 tickets"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "Website upgraded to symfony 1.1 and Doctrine 0.11"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "Road to Doctrine 1.0"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "0.11.0-RC3 Released"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: [release]

View File

@@ -1,8 +1,5 @@
---
title: "One more 0.11 Release Candidate"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: [release]

View File

@@ -1,8 +1,5 @@
---
title: "Php.net style API documentation lookups"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "Getting started with Doctrine and symfony 1.1"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "Doctrine in your language"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "Introducing the Doctrine Cookbook"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "0.11.0 Stable Released"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: [release]

View File

@@ -1,8 +1,5 @@
---
title: "1000th Ticket Closed"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "Introducing the Doctrine Forum"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "Doctrine 1.0 and symfony 1.2"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "Doctrine 0.11.1 and 1.0"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "Doctrine gets its first employee"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

View File

@@ -1,8 +1,5 @@
---
title: "Plug and Play Schema Information With Templates"
menuSlug: blog
layout: blog-post
controller: ['Doctrine\Website\Controllers\BlogController', 'view']
authorName: jwage
authorEmail:
categories: []

Some files were not shown because too many files have changed in this diff Show More