Skip to content
This repository has been archived by the owner on Jan 1, 2023. It is now read-only.

Commit

Permalink
Merge branch '2.0.0' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
nesk committed Nov 30, 2020
2 parents b14d511 + e972abd commit 5389f44
Show file tree
Hide file tree
Showing 43 changed files with 1,242 additions and 114 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
php-version: [7.1, 7.2, 7.3]
php-version: [7.3, 7.4, 8.0]
composer-flags: [null, --prefer-lowest]
steps:
- uses: actions/checkout@v2
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/.build/
/node_modules/
/vendor/
.phpunit.result.cache
composer.lock
package-lock.json
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
**Note:** PuPHPeteer is heavily based on [Rialto](https://github.com/nesk/rialto). For a complete overview of the changes, you might want to check out [Rialto's changelog](https://github.com/nesk/rialto/blob/master/CHANGELOG.md) too.

## [Unreleased]
_In progress…_
### Added
- Support Puppeteer v5.5
- Support PHP 8
- Add documentation on all resources to provide autocompletion in IDEs

### Removed
- Drop support for PHP 7.1 and 7.2

## [1.6.0] - 2019-07-01
### Added
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ $browser->close();

## Requirements and installation

This package requires PHP >= 7.1 and Node >= 8.
This package requires PHP >= 7.3 and Node >= 8.

Install it with these two command lines:

Expand Down
12 changes: 12 additions & 0 deletions bin/console
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env php
<?php

require_once __DIR__.'/../vendor/autoload.php';

use Symfony\Component\Console\Application;
use Nesk\Puphpeteer\Command\GenerateDocumentationCommand;

(new Application())
->add(new GenerateDocumentationCommand)
->getApplication()
->run();
6 changes: 3 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@
}
],
"require": {
"php": ">=7.1",
"php": ">=7.3",
"nesk/rialto": "^1.2.0",
"psr/log": "^1.0",
"vierbergenlars/php-semver": "^3.0.2"
},
"require-dev": {
"monolog/monolog": "^1.23",
"phpunit/phpunit": "^6.5|^7.0",
"monolog/monolog": "^2.0",
"phpunit/phpunit": "^9.0",
"symfony/process": "^4.0|^5.0"
},
"autoload": {
Expand Down
9 changes: 7 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@
"license": "MIT",
"repository": "github:nesk/puphpeteer",
"engines": {
"node": ">=8.0.0"
"node": ">=9.0.0"
},
"dependencies": {
"@nesk/rialto": "^1.2.1",
"puppeteer": "~1.18.0"
"puppeteer": "~5.5.0"
},
"devDependencies": {
"@types/yargs": "^15.0.10",
"typescript": "^4.1.2",
"yargs": "^16.1.1"
}
}
21 changes: 5 additions & 16 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -1,20 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/6.5/phpunit.xsd"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd"
bootstrap="vendor/autoload.php"
forceCoversAnnotation="true"
beStrictAboutCoversAnnotation="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
colors="true"
verbose="true">
<testsuite name="default">
<directory suffix="Test.php">tests</directory>
</testsuite>

<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<directory suffix=".php">src</directory>
</whitelist>
</filter>
colors="true">
<testsuite name="default">
<directory suffix="Test.php">tests</directory>
</testsuite>
</phpunit>
178 changes: 178 additions & 0 deletions src/Command/GenerateDocumentationCommand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
<?php

namespace Nesk\Puphpeteer\Command;

use Nesk\Puphpeteer\Puppeteer;
use Symfony\Component\Process\Process;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

final class GenerateDocumentationCommand extends Command
{
private const DOC_FILE_NAME = 'doc-generator';
private const BUILD_DIR = __DIR__.'/../../.build';
private const NODE_MODULES_DIR = __DIR__.'/../../node_modules';
private const RESOURCES_DIR = __DIR__.'/../Resources';
private const RESOURCES_NAMESPACE = 'Nesk\\Puphpeteer\\Resources';

protected static $defaultName = 'doc:generate';

protected function configure(): void
{
$this->addOption(
'puppeteerPath',
null,
InputOption::VALUE_OPTIONAL,
'The path where Puppeteer is installed.',
self::NODE_MODULES_DIR.'/puppeteer'
);
}

/**
* Builds the documentation generator from TypeScript to JavaScript.
*/
private static function buildDocumentationGenerator(): void
{
$process = new Process([
self::NODE_MODULES_DIR.'/.bin/tsc',
'--outDir',
self::BUILD_DIR,
__DIR__.'/../../src/'.self::DOC_FILE_NAME.'.ts',
]);
$process->run();
}

/**
* Gets the documentation from the TypeScript documentation generator.
*/
private static function getDocumentation(string $puppeteerPath, array $resourceNames): array
{
self::buildDocumentationGenerator();

$commonFiles = \glob("$puppeteerPath/lib/esm/puppeteer/common/*.d.ts");
$nodeFiles = \glob("$puppeteerPath/lib/esm/puppeteer/node/*.d.ts");

$process = new Process(
\array_merge(
['node', self::BUILD_DIR.'/'.self::DOC_FILE_NAME.'.js', 'php'],
$commonFiles,
$nodeFiles,
['--resources-namespace', self::RESOURCES_NAMESPACE, '--resources'],
$resourceNames
)
);
$process->mustRun();

return \json_decode($process->getOutput(), true);
}

private static function getResourceNames(): array
{
return array_map(function (string $filePath): string {
return explode('.', \basename($filePath))[0];
}, \glob(self::RESOURCES_DIR.'/*'));
}

private static function generatePhpDocWithDocumentation(array $classDocumentation): ?string
{
$properties = array_map(function (string $property): string {
return "\n * @property $property";
}, $classDocumentation['properties']);
$properties = \implode('', $properties);

$getters = array_map(function (string $getter): string {
return "\n * @property-read $getter";
}, $classDocumentation['getters']);
$getters = \implode('', $getters);

$methods = array_map(function (string $method): string {
return "\n * @method $method";
}, $classDocumentation['methods']);
$methods = \implode('', $methods);

if (\strlen($properties) > 0 || \strlen($getters) > 0 || \strlen($methods) > 0) {
return "/**$properties$getters$methods\n */";
}

return null;
}

/**
* Writes the doc comment in the PHP class.
*/
private static function writePhpDoc(string $className, string $phpDoc): void
{
$reflectionClass = new \ReflectionClass($className);

if (! $reflectionClass) {
return;
}

$fileName = $reflectionClass->getFileName();

$contents = file_get_contents($fileName);

// If there already is a doc comment, replace it.
if ($doc = $reflectionClass->getDocComment()) {
$newContents = str_replace($doc, $phpDoc, $contents);
} else {
$startLine = $reflectionClass->getStartLine();

$lines = explode("\n", $contents);

$before = array_slice($lines, 0, $startLine - 1);
$after = array_slice($lines, $startLine - 1);

$newContents = implode("\n", array_merge($before, explode("\n", $phpDoc), $after));
}

file_put_contents($fileName, $newContents);
}

/**
* Executes the current command.
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);

$resourceNames = self::getResourceNames();
$documentation = self::getDocumentation($input->getOption('puppeteerPath'), $resourceNames);

foreach ($resourceNames as $resourceName) {
$classDocumentation = $documentation[$resourceName] ?? null;

if ($classDocumentation !== null) {
$phpDoc = self::generatePhpDocWithDocumentation($classDocumentation);
if ($phpDoc !== null) {
$resourceClass = self::RESOURCES_NAMESPACE.'\\'.$resourceName;
self::writePhpDoc($resourceClass, $phpDoc);
}
}
}

// Handle the specific Puppeteer class
$classDocumentation = $documentation['Puppeteer'] ?? null;
if ($classDocumentation !== null) {
$phpDoc = self::generatePhpDocWithDocumentation($classDocumentation);
if ($phpDoc !== null) {
self::writePhpDoc(Puppeteer::class, $phpDoc);
}
}

$missingResources = \array_diff(\array_keys($documentation), $resourceNames);
foreach ($missingResources as $resource) {
$io->warning("The $resource class in Puppeteer doesn't have any equivalent in PuPHPeteer.");
}

$inexistantResources = \array_diff($resourceNames, \array_keys($documentation));
foreach ($inexistantResources as $resource) {
$io->error("The $resource resource doesn't have any equivalent in Puppeteer.");
}

return 0;
}
}
9 changes: 9 additions & 0 deletions src/Puppeteer.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@
use Nesk\Rialto\AbstractEntryPoint;
use vierbergenlars\SemVer\{version, expression, SemVerException};

/**
* @property-read mixed devices
* @property-read mixed errors
* @method \Nesk\Puphpeteer\Resources\Browser connect(array<string, mixed> $options)
* @method void registerCustomQueryHandler(string $name, mixed $queryHandler)
* @method void unregisterCustomQueryHandler(string $name)
* @method string[] customQueryHandlerNames()
* @method void clearCustomQueryHandlers()
*/
class Puppeteer extends AbstractEntryPoint
{
/**
Expand Down
3 changes: 3 additions & 0 deletions src/Resources/Accessibility.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@

use Nesk\Rialto\Data\BasicResource;

/**
* @method mixed snapshot(array<string, mixed> $options = null)
*/
class Accessibility extends BasicResource
{
//
Expand Down
21 changes: 18 additions & 3 deletions src/Resources/Browser.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,24 @@

namespace Nesk\Puphpeteer\Resources;

use Nesk\Rialto\Data\BasicResource;

class Browser extends BasicResource
/**
* @method mixed|null process()
* @method \Nesk\Puphpeteer\Resources\BrowserContext createIncognitoBrowserContext()
* @method \Nesk\Puphpeteer\Resources\BrowserContext[] browserContexts()
* @method \Nesk\Puphpeteer\Resources\BrowserContext defaultBrowserContext()
* @method string wsEndpoint()
* @method \Nesk\Puphpeteer\Resources\Page newPage()
* @method \Nesk\Puphpeteer\Resources\Target[] targets()
* @method \Nesk\Puphpeteer\Resources\Target target()
* @method \Nesk\Puphpeteer\Resources\Target waitForTarget(callable(\Nesk\Puphpeteer\Resources\Target $x): bool $predicate, array<string, mixed> $options = null)
* @method \Nesk\Puphpeteer\Resources\Page[] pages()
* @method string version()
* @method string userAgent()
* @method void close()
* @method void disconnect()
* @method bool isConnected()
*/
class Browser extends EventEmitter
{
//
}
15 changes: 12 additions & 3 deletions src/Resources/BrowserContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,18 @@

namespace Nesk\Puphpeteer\Resources;

use Nesk\Rialto\Data\BasicResource;

class BrowserContext extends BasicResource
/**
* @method \Nesk\Puphpeteer\Resources\Target[] targets()
* @method \Nesk\Puphpeteer\Resources\Target waitForTarget(callable(\Nesk\Puphpeteer\Resources\Target $x): bool $predicate, array{ timeout: float } $options = null)
* @method \Nesk\Puphpeteer\Resources\Page[] pages()
* @method bool isIncognito()
* @method void overridePermissions(string $origin, string[] $permissions)
* @method void clearPermissionOverrides()
* @method \Nesk\Puphpeteer\Resources\Page newPage()
* @method \Nesk\Puphpeteer\Resources\Browser browser()
* @method void close()
*/
class BrowserContext extends EventEmitter
{
//
}
10 changes: 10 additions & 0 deletions src/Resources/BrowserFetcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@

use Nesk\Rialto\Data\BasicResource;

/**
* @method mixed platform()
* @method mixed product()
* @method string host()
* @method bool canDownload(string $revision)
* @method mixed download(string $revision, callable(float $x, float $y): void $progressCallback = null)
* @method string[] localRevisions()
* @method void remove(string $revision)
* @method mixed revisionInfo(string $revision)
*/
class BrowserFetcher extends BasicResource
{
//
Expand Down
Loading

0 comments on commit 5389f44

Please sign in to comment.