Skip to content

Commit c1280c8

Browse files
committed
Simple class to file
1 parent 5db41f5 commit c1280c8

File tree

6 files changed

+184
-67
lines changed

6 files changed

+184
-67
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php
2+
3+
namespace Phpactor\ClassFileConverter\Adapter\Simple;
4+
5+
/**
6+
* Return the class name from a file.
7+
*
8+
* Based on http://stackoverflow.com/questions/7153000/get-class-name-from-file
9+
*/
10+
class ClassScanner
11+
{
12+
public function getClassNameFromFile($file)
13+
{
14+
$fp = fopen($file, 'r');
15+
16+
$class = $namespace = $buffer = '';
17+
$i = 0;
18+
19+
while (!$class) {
20+
if (feof($fp)) {
21+
break;
22+
}
23+
24+
// Read entire lines to prevent keyword truncation
25+
for ($line = 0; $line <= 20; $line++) {
26+
$buffer .= fgets($fp);
27+
}
28+
$tokens = @token_get_all($buffer);
29+
30+
if (strpos($buffer, '{') === false) {
31+
continue;
32+
}
33+
34+
for (; $i < count($tokens); $i++) {
35+
if ($tokens[$i][0] === \T_NAMESPACE) {
36+
for ($j = $i + 1; $j < count($tokens); $j++) {
37+
if ($tokens[$j][0] === T_STRING) {
38+
$namespace .= '\\' . $tokens[$j][1];
39+
} elseif ($tokens[$j] === '{' || $tokens[$j] === ';') {
40+
break;
41+
}
42+
}
43+
}
44+
45+
if ($tokens[$i][0] === \T_CLASS) {
46+
for ($j = $i + 1; $j < count($tokens); $j++) {
47+
if ($tokens[$j][0] === \T_STRING) {
48+
$class = $tokens[$i + 2][1];
49+
break 2;
50+
}
51+
}
52+
}
53+
}
54+
}
55+
56+
if (!trim($class)) {
57+
return;
58+
}
59+
60+
fclose($fp);
61+
62+
return ltrim($namespace . '\\' . $class, '\\');
63+
}
64+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
namespace Phpactor\ClassFileConverter\Adapter\Simple;
4+
5+
use Phpactor\ClassFileConverter\Domain\ClassToFile;
6+
use Phpactor\ClassFileConverter\Domain\FilePathCandidates;
7+
use Phpactor\ClassFileConverter\Domain\ClassName;
8+
use Phpactor\ClassFileConverter\Domain\FilePath;
9+
10+
class SimpleClassToFile implements ClassToFile
11+
{
12+
/**
13+
* @var string
14+
*/
15+
private $cwd;
16+
17+
/**
18+
* @var ClassScanner
19+
*/
20+
private $classScanner;
21+
22+
public function __construct(string $cwd)
23+
{
24+
$this->cwd = $cwd;
25+
$this->classScanner = new ClassScanner();
26+
}
27+
28+
public function classToFileCandidates(ClassName $className): FilePathCandidates
29+
{
30+
$candidates = [];
31+
foreach (glob(sprintf(
32+
'%s/**/%s.php',
33+
$this->cwd,
34+
$className->name()
35+
)) as $phpFile) {
36+
if (ClassName::fromString(
37+
$this->classScanner->getClassNameFromFile($phpFile)
38+
) == $className) {
39+
$candidates[] = FilePath::fromString($phpFile);
40+
}
41+
}
42+
43+
return FilePathCandidates::fromFilePaths($candidates);
44+
}
45+
}

lib/Adapter/Simple/SimpleFileToClass.php

Lines changed: 12 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -6,81 +6,30 @@
66
use Phpactor\ClassFileConverter\Domain\ClassNameCandidates;
77
use Phpactor\ClassFileConverter\Domain\FilePath;
88
use Phpactor\ClassFileConverter\Domain\ClassName;
9+
use Phpactor\ClassFileConverter\Adapter\Simple\ClassScanner;
910

1011
class SimpleFileToClass implements FileToClass
1112
{
13+
/**
14+
* @var ClassScanner
15+
*/
16+
private $classScanner;
17+
18+
public function __construct()
19+
{
20+
$this->classScanner = new ClassScanner();
21+
}
22+
1223
public function fileToClassCandidates(FilePath $filePath): ClassNameCandidates
1324
{
1425
$classNames = [];
1526

16-
$className = $this->getClassNameFromFile($filePath->__toString());
27+
$className = $this->classScanner->getClassNameFromFile($filePath->__toString());
1728

1829
if ($className) {
1930
$classNames[] = ClassName::fromString($className);
2031
}
2132

2233
return ClassNameCandidates::fromClassNames($classNames);
2334
}
24-
25-
/**
26-
* Return the class name from a file.
27-
*
28-
* Taken from http://stackoverflow.com/questions/7153000/get-class-name-from-file
29-
*
30-
* @param string $file
31-
*
32-
* @return string
33-
*/
34-
private function getClassNameFromFile($file)
35-
{
36-
$fp = fopen($file, 'r');
37-
38-
$class = $namespace = $buffer = '';
39-
$i = 0;
40-
41-
while (!$class) {
42-
if (feof($fp)) {
43-
break;
44-
}
45-
46-
// Read entire lines to prevent keyword truncation
47-
for ($line = 0; $line <= 20; $line++) {
48-
$buffer .= fgets($fp);
49-
}
50-
$tokens = @token_get_all($buffer);
51-
52-
if (strpos($buffer, '{') === false) {
53-
continue;
54-
}
55-
56-
for (; $i < count($tokens); $i++) {
57-
if ($tokens[$i][0] === T_NAMESPACE) {
58-
for ($j = $i + 1; $j < count($tokens); $j++) {
59-
if ($tokens[$j][0] === T_STRING) {
60-
$namespace .= '\\' . $tokens[$j][1];
61-
} elseif ($tokens[$j] === '{' || $tokens[$j] === ';') {
62-
break;
63-
}
64-
}
65-
}
66-
67-
if ($tokens[$i][0] === T_CLASS) {
68-
for ($j = $i + 1; $j < count($tokens); $j++) {
69-
if ($tokens[$j][0] === T_STRING) {
70-
$class = $tokens[$i + 2][1];
71-
break 2;
72-
}
73-
}
74-
}
75-
}
76-
}
77-
78-
if (!trim($class)) {
79-
return;
80-
}
81-
82-
fclose($fp);
83-
84-
return ltrim($namespace . '\\' . $class, '\\');
85-
}
8635
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
namespace Phpactor\ClassFileConverter\Tests\Integration\Simple;
4+
5+
use Phpactor\ClassFileConverter\Tests\Integration\IntegrationTestCase;
6+
use Symfony\Component\Filesystem\Filesystem;
7+
use Phpactor\ClassFileConverter\Adapter\Simple\SimpleClassToFile;
8+
use Phpactor\ClassFileConverter\Domain\FilePath;
9+
use Phpactor\ClassFileConverter\Domain\ClassNameCandidates;
10+
use Phpactor\ClassFileConverter\Domain\ClassName;
11+
use Phpactor\ClassFileConverter\Domain\FilePathCandidates;
12+
13+
class SimpleClassToFileTest extends SimpleTestCase
14+
{
15+
/**
16+
* @var SimpleClassToFile
17+
*/
18+
private $classToFile;
19+
20+
public function setUp()
21+
{
22+
$this->initWorkspace();
23+
$this->copyProject();
24+
$this->classToFile = new SimpleClassToFile($this->workspacePath());
25+
}
26+
27+
public function testClassToFile()
28+
{
29+
$candidates = $this->classToFile->classToFileCandidates(ClassName::fromString('Acme\\Foobar'));
30+
31+
$this->assertEquals(FilePathCandidates::fromFilePaths([
32+
FilePath::fromString(__DIR__ . '/../workspace/lib/Foobar.php')
33+
]), $candidates);
34+
}
35+
36+
public function testClassToNoCandidates()
37+
{
38+
$candidates = $this->classToFile->classToFileCandidates(ClassName::fromString('Zog\\Foobar'));
39+
$this->assertEquals(FilePathCandidates::fromFilePaths([]), $candidates);
40+
}
41+
}

tests/Integration/Simple/SimpleFileToClassTest.php

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
use Phpactor\ClassFileConverter\Domain\ClassNameCandidates;
1010
use Phpactor\ClassFileConverter\Domain\ClassName;
1111

12-
class SimpleFileToClassTest extends IntegrationTestCase
12+
class SimpleFileToClassTest extends SimpleTestCase
1313
{
1414
/**
1515
* @var SimpleFileToClass
@@ -19,9 +19,7 @@ class SimpleFileToClassTest extends IntegrationTestCase
1919
public function setUp()
2020
{
2121
$this->initWorkspace();
22-
$projectPath = __DIR__.'/project';
23-
$filesystem = new Filesystem();
24-
$filesystem->mirror($projectPath, $this->workspacePath());
22+
$this->copyProject();
2523
$this->fileToClass = new SimpleFileToClass();
2624
}
2725

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
3+
namespace Phpactor\ClassFileConverter\Tests\Integration\Simple;
4+
5+
use Phpactor\ClassFileConverter\Tests\Integration\IntegrationTestCase;
6+
use Symfony\Component\Filesystem\Filesystem;
7+
use Phpactor\ClassFileConverter\Adapter\Simple\SimpleFileToClass;
8+
use Phpactor\ClassFileConverter\Domain\FilePath;
9+
use Phpactor\ClassFileConverter\Domain\ClassNameCandidates;
10+
use Phpactor\ClassFileConverter\Domain\ClassName;
11+
12+
class SimpleTestCase extends IntegrationTestCase
13+
{
14+
protected function copyProject()
15+
{
16+
$projectPath = __DIR__.'/project';
17+
$filesystem = new Filesystem();
18+
$filesystem->mirror($projectPath, $this->workspacePath());
19+
}
20+
}

0 commit comments

Comments
 (0)