Skip to content

Commit

Permalink
Merge pull request #20 from mirko-pagliai/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
mirko-pagliai authored Sep 11, 2019
2 parents e80aaa9 + 47f5d6e commit a025418
Show file tree
Hide file tree
Showing 11 changed files with 96 additions and 78 deletions.
24 changes: 16 additions & 8 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,33 @@ matrix:
fast_finish: true

include:
- php: 5.6
env: dependencies=lowest
- php: 7.0
env: dependencies=lowest
- php: 7.1
env: dependencies=lowest
- php: 7.2
env: dependencies=lowest
- php: 7.3
env: dependencies=lowest
- php: 7.0
env: PHPCS=1

- php: 7.0
env: COVERAGE=1

- php: 7.0
env: CAKEPHP_VERSION="3.7.*"

install:
- composer self-update
- composer self-update -q
- composer install --prefer-dist --no-interaction
- if [[ ! -z "$CAKEPHP_VERSION" ]]; then composer require --update-with-dependencies cakephp/cakephp:${CAKEPHP_VERSION}; fi

- if [ "$dependencies" = "lowest" ]; then composer update --prefer-lowest -n; fi;
- composer show -i

script:
- rm tests/examples/responses/*
- if [[ $PHPCS != '1' && $COVERAGE != '1' ]]; then vendor/bin/phpunit; fi
- if [[ $PHPCS = 1 ]]; then vendor/bin/phpcs --standard=phpcs.xml.dist; fi
- if [[ $COVERAGE = 1 ]]; then vendor/bin/phpunit --coverage-clover=clover.xml; fi

after_success:
- if [[ $COVERAGE = 1 ]]; then bash <(curl -s https://codecov.io/bash); fi

Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# 1.x branch
## 1.0 branch
### 1.0.7
* added tests for lower dependencies;
* no longer uses `File` and `Folder` classes;
* little fixes.

### 1.0.6
* `LinkScanner::import()` can no longer be called statically;
* little fixes;
Expand Down
11 changes: 6 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
[![Build Status](https://api.travis-ci.org/mirko-pagliai/cakephp-link-scanner.svg?branch=master)](https://travis-ci.org/mirko-pagliai/cakephp-link-scanner)
[![Build status](https://ci.appveyor.com/api/projects/status/hqk7fxtad6r75wk3?svg=true)](https://ci.appveyor.com/project/mirko-pagliai/cakephp-link-scanner)
[![codecov](https://codecov.io/gh/mirko-pagliai/cakephp-link-scanner/branch/master/graph/badge.svg)](https://codecov.io/gh/mirko-pagliai/cakephp-link-scanner)
[![CodeFactor](https://www.codefactor.io/repository/github/mirko-pagliai/cakephp-link-scanner/badge/cakephp4)](https://www.codefactor.io/repository/github/mirko-pagliai/cakephp-link-scanner/overview/cakephp4)

*LinkScanner* is a CakePHP plugin for recursively scanning links: starting from
a full base url, it performs GET requests, checks the status codes, inspects the
Expand Down Expand Up @@ -42,15 +43,15 @@ to indicate the full base url which to start the scan every time.

## How to use
Please, refer to the wiki:
- [How to use the LinkScanner utility](//github.com/mirko-pagliai/cakephp-link-scanner/wiki/How-to-use-the-LinkScanner-utility)
- [How to use the LinkScannerCommand](//github.com/mirko-pagliai/cakephp-link-scanner/wiki/How-to-use-the-LinkScannerCommand)
- [Examples for ResultScan](//github.com/mirko-pagliai/cakephp-link-scanner/wiki/Examples-for-ResultScan)
* [How to use the LinkScanner utility](//github.com/mirko-pagliai/cakephp-link-scanner/wiki/How-to-use-the-LinkScanner-utility)
* [How to use the LinkScannerCommand](//github.com/mirko-pagliai/cakephp-link-scanner/wiki/How-to-use-the-LinkScannerCommand)
* [Examples for ResultScan](//github.com/mirko-pagliai/cakephp-link-scanner/wiki/Examples-for-ResultScan)

In addition, you can refer to our [API](//mirko-pagliai.github.io/cakephp-link-scanner).

## To do list
* allow the use of a configuration file for the shell;
* allow to export results as html and/or xml.
* allow the use of a configuration file for the shell;
* allow to export results as html and/or xml.

## Versioning
For transparency and insight into our release cycle and to maintain backward
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ init:

install:
- cd c:\
- curl -fsS -o php.zip https://windows.php.net/downloads/releases/php-7.2.20-nts-Win32-VC15-x86.zip
- curl -fsS -o php.zip https://windows.php.net/downloads/releases/php-7.2.22-nts-Win32-VC15-x86.zip
- 7z x php.zip -oc:\php > nul
- cd c:\php
- copy php.ini-production php.ini
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@
"require": {
"php": ">=5.5.9",
"cakephp/cakephp": "^3.7.1",
"mirko-pagliai/me-tools": "^2.18",
"mirko-pagliai/me-tools": "^2.18.9",
"mirko-pagliai/php-tools": "^1.2.6"
},
"require-dev": {
"cakephp/cakephp-codesniffer": "^3.0",
"phpunit/phpunit": "^5.7|^6.0"
"phpunit/phpunit": "^5.7.14|^6.0"
},
"autoload": {
"psr-4": {
Expand Down
29 changes: 13 additions & 16 deletions src/Event/LinkScannerCommandEventListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -216,33 +216,30 @@ public function scanStarted(Event $event, $startTime, $fullBaseUrl)
$this->io->hr();

$cache = Cache::getConfig('LinkScanner');
list($method, $message) = ['info', __d('link-scanner', 'The cache is disabled')];
if (!$this->args->getOption('no-cache') && Cache::enabled() && !empty($cache['duration'])) {
$this->io->success(__d(
'link-scanner',
'The cache is enabled and its duration is `{0}`',
$cache['duration']
));
} else {
$this->io->info(__d('link-scanner', 'The cache is disabled'));
$method = 'success';
$message = __d('link-scanner', 'The cache is enabled and its duration is `{0}`', $cache['duration']);
}
call_user_func([$this->io, $method], $message);

$message = __d('link-scanner', 'Force mode is not enabled');
if ($this->args->getOption('force')) {
$this->io->info(__d('link-scanner', 'Force mode is enabled'));
} else {
$this->io->info(__d('link-scanner', 'Force mode is not enabled'));
$message = __d('link-scanner', 'Force mode is enabled');
}
$this->io->info($message);

$message = __d('link-scanner', 'Scanning of external links is not enabled');
if ($event->getSubject()->getConfig('externalLinks')) {
$this->io->info(__d('link-scanner', 'Scanning of external links is enabled'));
} else {
$this->io->info(__d('link-scanner', 'Scanning of external links is not enabled'));
$message = __d('link-scanner', 'Scanning of external links is enabled');
}
$this->io->info($message);

$message = __d('link-scanner', 'Redirects will not be followed');
if ($event->getSubject()->getConfig('followRedirects')) {
$this->io->info(__d('link-scanner', 'Redirects will be followed'));
} else {
$this->io->info(__d('link-scanner', 'Redirects will not be followed'));
$message = __d('link-scanner', 'Redirects will be followed');
}
$this->io->info($message);

$maxDepth = $event->getSubject()->getConfig('maxDepth');
if (is_positive($maxDepth)) {
Expand Down
15 changes: 9 additions & 6 deletions src/TestSuite/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,21 @@ protected function getClientReturnsSampleResponse()
$Client->method('get')->will($this->returnCallback(function ($url) {
$responseFile = TESTS . 'examples' . DS . 'responses' . DS . 'google_response';
$bodyFile = TESTS . 'examples' . DS . 'responses' . DS . 'google_body';
$getResponse = function () use ($url) {
return (new Client(['redirect' => true]))->get($url);
};

if (is_readable($responseFile)) {
$response = @unserialize(file_get_contents($responseFile));
} else {
$response = (new Client(['redirect' => true]))->get($url);
$getResponse = function () use ($responseFile) {
return @unserialize(file_get_contents($responseFile));
};
}
is_readable($responseFile) ? null : file_put_contents($responseFile, serialize($response));
is_readable($responseFile) ? null : file_put_contents($responseFile, serialize($getResponse()));

$body = is_readable($bodyFile) ? @unserialize(file_get_contents($bodyFile)) : (string)$response->getBody();
$body = is_readable($bodyFile) ? @unserialize(file_get_contents($bodyFile)) : (string)$getResponse()->getBody();
is_readable($bodyFile) ? null : file_put_contents($bodyFile, serialize($body));

return $this->getResponseWithBody($body, $response);
return $this->getResponseWithBody($body, $getResponse());
}));

return $Client;
Expand Down
32 changes: 21 additions & 11 deletions src/Utility/LinkScanner.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@
use Cake\Core\InstanceConfigTrait;
use Cake\Event\EventDispatcherTrait;
use Cake\Event\EventList;
use Cake\Filesystem\File;
use Cake\Filesystem\Folder;
use Cake\Http\Client;
use Cake\Http\Client\Response;
use Exception;
Expand All @@ -28,6 +26,7 @@
use LinkScanner\ScanEntity;
use RuntimeException;
use Serializable;
use Symfony\Component\Filesystem\Filesystem;
use Tools\BodyParser;
use Zend\Diactoros\Stream;

Expand Down Expand Up @@ -146,7 +145,20 @@ protected function _createLockFile()
$this->lockFile
), RuntimeException::class);

return $this->getConfig('lockFile') ? new File($this->lockFile, true) !== false : true;
return $this->getConfig('lockFile') ? create_file($this->lockFile) !== false : true;
}

/**
* Internal method to get the absolute path for a filename
* @param string $filename Filename
* @return string
* @since 1.0.7
*/
protected function _getAbsolutePath($filename)
{
$isAbsolute = (new Filesystem())->isAbsolutePath($filename);

return $isAbsolute ? $filename : add_slash_term($this->getConfig('target')) . $filename;
}

/**
Expand Down Expand Up @@ -371,6 +383,7 @@ public function unserialize($serialized)
* @return string
* @see serialize()
* @throws \RuntimeException
* @uses _getAbsolutePath()
* @uses $ResultScan
* @uses $hostname
* @uses $startTime
Expand All @@ -383,11 +396,8 @@ public function export($filename = null)
RuntimeException::class
);

$filename = $filename ?: sprintf('results_%s_%s', $this->hostname, $this->startTime);
if (!Folder::isAbsolute($filename)) {
$filename = add_slash_term($this->getConfig('target')) . $filename;
}
(new File($filename, true))->write(serialize($this));
$filename = $this->_getAbsolutePath($filename ?: sprintf('results_%s_%s', $this->hostname, $this->startTime));
create_file($filename, serialize($this));
$this->dispatchEvent('LinkScanner.resultsExported', [$filename]);

return $filename;
Expand All @@ -403,14 +413,14 @@ public function export($filename = null)
* been exported.
* @param string $filename Filename from which to import
* @return \LinkScanner\Utility\LinkScanner
* @uses _getAbsolutePath()
* @throws \RuntimeException
*/
public function import($filename)
{
$filename = $this->_getAbsolutePath($filename);

try {
if (!Folder::isAbsolute($filename)) {
$filename = add_slash_term($this->getConfig('target')) . $filename;
}
$instance = unserialize(file_get_contents($filename));
} catch (Exception $e) {
$message = preg_replace('/^file_get_contents\([\/\w\d:\-\\\\]+\): /', null, $e->getMessage());
Expand Down
7 changes: 4 additions & 3 deletions tests/TestCase/Command/LinkScannerCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ public function testScan()
$this->Command->run(['--verbose'], $this->io);
$this->assertErrorContains('404');
}

/**
* Test for `scan()` method, with cache enabled
* @test
Expand Down Expand Up @@ -192,12 +193,12 @@ public function testScanParams()
$expectedConfig['fullBaseUrl'] = $this->fullBaseUrl;
$this->assertEquals($expectedConfig, $this->LinkScanner->getConfig());

$lineDifferentFullBaseUrl = function ($line) {
$differentLines = function ($line) {
$pattern = sprintf('/^Checking https?:\/\/%s/', preg_quote(get_hostname_from_url($this->fullBaseUrl)));

return substr($line, 0, strlen('Checking')) === 'Checking' && !preg_match($pattern, $line);
};
$this->assertEmpty(array_filter($this->_out->messages(), $lineDifferentFullBaseUrl));
$this->assertEmpty(array_filter($this->_out->messages(), $differentLines));
$this->assertOutputContains('Scanning of external links is not enabled');

//Re-enables external links
Expand All @@ -206,7 +207,7 @@ public function testScanParams()
$this->Command->run($params, $this->io);
$expectedConfig['externalLinks'] = true;
$this->assertEquals($expectedConfig, $this->LinkScanner->getConfig());
$this->assertNotEmpty(array_filter($this->_out->messages(), $lineDifferentFullBaseUrl));
$this->assertNotEmpty(array_filter($this->_out->messages(), $differentLines));

foreach ([
'example' => $this->LinkScanner->getConfig('target') . DS . 'example',
Expand Down
43 changes: 18 additions & 25 deletions tests/TestCase/Utility/LinkScannerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,6 @@ public function testGetResponse()
if ($response->isOk()) {
$this->assertNotEmpty($responseFromCache);
$this->assertInstanceof(Response::class, $responseFromCache);
} else {
$this->assertEmpty($responseFromCache);
}
}

Expand Down Expand Up @@ -174,8 +172,8 @@ public function testExport()
null => $this->LinkScanner->getConfig('target') . DS . 'results_' . $this->LinkScanner->hostname . '_' . $this->LinkScanner->startTime,
'example' => $this->LinkScanner->getConfig('target') . DS . 'example',
TMP . 'example' => TMP . 'example',
] as $filenameWhereToExport => $expectedFilename) {
$result = $this->LinkScanner->export($filenameWhereToExport);
] as $filename => $expectedFilename) {
$result = $this->LinkScanner->export($filename);
$this->assertFileExists($result);
$this->assertEquals($expectedFilename, $result);
$this->assertEventFired('LinkScanner.resultsExported', $this->EventManager);
Expand Down Expand Up @@ -221,13 +219,13 @@ public function testImport()

//Gets properties from both client, fixes properties of the `Client`
// instances and performs the comparison
$expectedClientProperties = $this->getProperties($this->LinkScanner->Client);
$resultClientProperties = $this->getProperties($result->Client);
$expectedProperties = $this->getProperties($this->LinkScanner->Client);
$resultProperties = $this->getProperties($result->Client);
foreach (['_adapter', '__phpunit_invocationMocker', '__phpunit_originalObject', '__phpunit_configurable'] as $key) {
unset($expectedClientProperties[$key], $resultClientProperties[$key]);
unset($expectedProperties[$key], $resultProperties[$key]);
}
$expectedProperties = ['Client' => $expectedClientProperties] + $this->getProperties($this->LinkScanner);
$resultProperties = ['Client' => $resultClientProperties] + $this->getProperties($result);
$expectedProperties = ['Client' => $expectedProperties] + $this->getProperties($this->LinkScanner);
$resultProperties = ['Client' => $resultProperties] + $this->getProperties($result);
$this->assertEquals($expectedProperties, $resultProperties);

//With a no existing file
Expand Down Expand Up @@ -302,12 +300,7 @@ public function testScan()
$hostname = get_hostname_from_url($this->fullBaseUrl);

foreach ($LinkScanner->ResultScan as $item) {
if (!$item->external) {
$this->assertRegexp(sprintf('/^https?:\/\/%s/', preg_quote($hostname)), $item->url);
} else {
$this->assertTextStartsNotWith('http://' . $hostname, $item->url);
$this->assertTextStartsNotWith('https://' . $hostname, $item->url);
}
$this->assertRegexp(sprintf('/^https?:\/\/%s/', preg_quote($hostname)), $item->url);
$this->assertContains($item->code, [200, 500]);
$this->assertStringStartsWith('text/html', $item->type);
}
Expand Down Expand Up @@ -373,7 +366,7 @@ public function testScanFromTests()
$this->assertEquals($expectedDebug, $this->debug);

//Results contain both internal and external urls
$expectedInternaLinks = [
$expectedInternal = [
'http://localhost',
'http://localhost/pages/first_page',
'http://localhost/favicon.ico',
Expand All @@ -384,11 +377,11 @@ public function testScanFromTests()
'http://localhost/pages/redirect',
'http://localhost/pages/sameredirect',
];
$expectedExternalLinks = ['http://google.it'];
$expectedExternal = ['http://google.it'];
$internalLinks = $LinkScanner->ResultScan->match(['external' => false])->extract('url');
$externalLinks = $LinkScanner->ResultScan->match(['external' => true])->extract('url');
$this->assertEquals($expectedInternaLinks, $internalLinks->toList());
$this->assertEquals($expectedExternalLinks, $externalLinks->toList());
$this->assertEquals($expectedInternal, $internalLinks->toList());
$this->assertEquals($expectedExternal, $externalLinks->toList());

$this->debug = [];

Expand Down Expand Up @@ -419,13 +412,13 @@ public function testScanFromTests()
$LinkScanner->setConfig('followRedirects', true)->scan();
$this->assertEquals($expectedDebug, $this->debug);

array_pop($expectedInternaLinks);
array_pop($expectedInternaLinks);
$expectedInternaLinks[] = 'http://localhost/pages/third_page';
array_pop($expectedInternal);
array_pop($expectedInternal);
$expectedInternal[] = 'http://localhost/pages/third_page';
$internalLinks = $LinkScanner->ResultScan->match(['external' => false])->extract('url');
$externalLinks = $LinkScanner->ResultScan->match(['external' => true])->extract('url');
$this->assertEquals($expectedInternaLinks, $internalLinks->toList());
$this->assertEquals($expectedExternalLinks, $externalLinks->toList());
$this->assertEquals($expectedInternal, $internalLinks->toList());
$this->assertEquals($expectedExternal, $externalLinks->toList());

$LinkScanner = $this->getLinkScannerClientReturnsFromTests($params);
$LinkScanner->setConfig('maxDepth', 1)->scan();
Expand Down Expand Up @@ -459,6 +452,6 @@ public function testScanResponseNotOk()
$EventManager = $this->getEventManager($LinkScanner);
$LinkScanner->scan();

$this->assertEventFired('LinkScanner.' . 'responseNotOk', $EventManager);
$this->assertEventFired('LinkScanner.responseNotOk', $EventManager);
}
}
2 changes: 1 addition & 1 deletion version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.0.6
1.0.7

0 comments on commit a025418

Please sign in to comment.