├── tests
├── PHPToolsTest
│ └── Namespacer
│ │ ├── _files
│ │ ├── Foo
│ │ │ ├── Bar
│ │ │ │ ├── Bar1.php
│ │ │ │ └── Bar2.php
│ │ │ └── Foo.php
│ │ └── Zend
│ │ │ ├── Filter
│ │ │ ├── Alpha.php
│ │ │ └── Alnum.php
│ │ │ └── Filter.php
│ │ ├── DocblockContentProcessorTest.php
│ │ └── FileNameProcessorTest.php
├── phpunit.xml
└── bootstrap.php
├── README
├── bin
└── php-namespacer.php
└── library
└── PHPTools
├── Namespacer
├── RecursiveFilterIterator.php
├── DocblockContentProcessor.php
├── FileRegistry.php
├── FileNameProcessor.php
├── CLIRunner.php
├── Namespacer.php
└── FileContentProcessor.php
└── SPL
└── SplClassLoader.php
/tests/PHPToolsTest/Namespacer/_files/Foo/Bar/Bar1.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | ./
5 |
6 |
7 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | PHPTools
2 | ========
3 |
4 | Namespacer
5 | ----------
6 |
7 | This tool is to help facilitate the conversion of PHP5 Prefixed code
8 | (ZF or PEAR standards code) to PHP 5.3 Namespaced code.
9 |
10 | .. more info ..
11 |
--------------------------------------------------------------------------------
/tests/bootstrap.php:
--------------------------------------------------------------------------------
1 | register();
--------------------------------------------------------------------------------
/tests/PHPToolsTest/Namespacer/_files/Foo/Foo.php:
--------------------------------------------------------------------------------
1 | register();
16 | \PHPTools\Namespacer\CLIRunner::main();
17 |
--------------------------------------------------------------------------------
/tests/PHPToolsTest/Namespacer/DocblockContentProcessorTest.php:
--------------------------------------------------------------------------------
1 | _fileRegistry = new \PHPTools\Namespacer\FileRegistry;
12 |
13 | $libraryDirectory = realpath(dirname(__FILE__) . '/_files/');
14 |
15 | foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($libraryDirectory)) as $realFilePath => $fileInfo) {
16 | $relativeFilePath = substr($realFilePath, strlen($libraryDirectory)+1);
17 | $fileNameProcessor = new \PHPTools\Namespacer\FileNameProcessor($relativeFilePath, $libraryDirectory);
18 | $this->_fileRegistry->registerFileNameProcessor($fileNameProcessor);
19 | }
20 |
21 | }
22 |
23 | public function teardown()
24 | {
25 | $this->_fileRegistry = null;
26 | }
27 |
28 | public function testTrue()
29 | {
30 | $docblock = <<_fileRegistry);
61 | $this->assertEquals($expected, $dcp->getContents());
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/tests/PHPToolsTest/Namespacer/FileNameProcessorTest.php:
--------------------------------------------------------------------------------
1 | assertEquals('./foo/bar/Zend/Validate/Alpha.php', $fnc->getOriginalFilePath(), 'Original file path not preserved.');
14 | $this->assertEquals('Zend/Validate/Alpha.php', $fnc->getOriginalRelativeFilePath(), 'Original file path not preserved.');
15 | $this->assertEquals('Zend_Validate_Alpha', $fnc->getOriginalClassName(), 'Original class not computed or preserved.');
16 | }
17 |
18 | public function testAbstractNamingWorks()
19 | {
20 | $fnc = new FileNameProcessor('Zend/Validate/Abstract.php', './foo/bar');
21 |
22 | $this->assertEquals('Zend\Validate', $fnc->getNewNamespace(), 'New namespace not computed correctly.');
23 | $this->assertEquals('AbstractValidate', $fnc->getNewClassName(), 'New class name not computed correctly.');
24 | $this->assertEquals('Zend\Validate\AbstractValidate', $fnc->getNewFullyQualifiedName(), 'New FQN not computed correctly.');
25 | $this->assertEquals('Zend/Validate/AbstractValidate.php', $fnc->getNewRelativeFilePath(), 'New file path not computed correctly.');
26 | }
27 |
28 | public function testClassMovedIntoNamespaceWorks()
29 | {
30 | $fnc = new FileNameProcessor('Zend/Filter.php', realpath(dirname(__FILE__) . '/_files/'));
31 |
32 | $this->assertEquals('Zend\Filter', $fnc->getNewNamespace(), 'New namespace not computed correctly.');
33 | $this->assertEquals('Filter', $fnc->getNewClassName(), 'New class name not computed correctly.');
34 | $this->assertEquals('Zend\Filter\Filter', $fnc->getNewFullyQualifiedName(), 'New FQN not computed correctly.');
35 | $this->assertEquals('Zend/Filter/Filter.php', $fnc->getNewRelativeFilePath(), 'New file path not computed correctly.');
36 | }
37 |
38 | }
--------------------------------------------------------------------------------
/library/PHPTools/Namespacer/RecursiveFilterIterator.php:
--------------------------------------------------------------------------------
1 | _filter = str_replace(array('\\', '/'), DIRECTORY_SEPARATOR, $filter);
20 | if ($topDirectory == null) {
21 | $iterator->rewind();
22 | $this->_topDirectory = (string) $iterator->current()->getPath();
23 | } else {
24 | $this->_topDirectory = $topDirectory;
25 | }
26 | parent::__construct($iterator);
27 | }
28 |
29 |
30 | public function accept()
31 | {
32 | $relativeFileName = substr($this->current()->getRealPath(), strlen($this->_topDirectory)+1);
33 |
34 | if ($this->isDot() || preg_match('#(\.svn|_svn|\.git)#', $relativeFileName)) {
35 | return false;
36 | }
37 |
38 | if ($this->isDir()) {
39 | return true;
40 | }
41 |
42 | if (preg_match('#^' . preg_quote($this->_filter) . '#', $relativeFileName)) {
43 | return true;
44 | } else {
45 | return false;
46 | }
47 | }
48 |
49 | /**
50 | * getChildren() - overridden from RecursiveFilterIterator to allow the persistence of
51 | * the $_denyDirectoryPattern and the $_acceptFilePattern when sub iterators of this filter
52 | * are needed to be created.
53 | *
54 | * @return Zend_Tool_Framework_Loader_IncludePathLoader_RecursiveFilterIterator
55 | */
56 | public function getChildren()
57 | {
58 | if (empty($this->ref)) {
59 | $this->ref = new \ReflectionClass($this);
60 | }
61 |
62 | return $this->ref->newInstance(
63 | $this->getInnerIterator()->getChildren(),
64 | $this->_filter,
65 | $this->_topDirectory
66 | );
67 | }
68 |
69 |
70 | }
--------------------------------------------------------------------------------
/library/PHPTools/Namespacer/DocblockContentProcessor.php:
--------------------------------------------------------------------------------
1 | _content = $docblockContent;
20 | $this->_prefixes = $prefixes;
21 | $this->_fileRegistry = $fileRegistry;
22 | $this->_generate();
23 | }
24 |
25 | public function getContents()
26 | {
27 | $content = '';
28 | foreach ($this->_newTokens as $newToken) {
29 | $content .= $newToken[1];
30 | }
31 | return $content;
32 | }
33 |
34 | protected function _generate()
35 | {
36 | $tokens = docblock_tokenize($this->_content);
37 | $context = null;
38 |
39 | $this->_newTokens = array();
40 |
41 | foreach ($tokens as $token) {
42 | $newToken = array();
43 | $tokenName = docblock_token_name($token[0]);
44 | switch ($tokenName) {
45 | case 'DOCBLOCK_TAG':
46 | switch ($token[1]) {
47 | case '@var':
48 | case '@uses':
49 | case '@param':
50 | case '@return':
51 | case '@throws':
52 | $context = 'INSIDE_TYPE_TAG';
53 | break;
54 | }
55 | $this->_newTokens[] = $token;
56 | break;
57 | case 'DOCBLOCK_TEXT':
58 | if ($context == 'INSIDE_TYPE_TAG') {
59 | $matches = array();
60 | $prefixRegex = implode('|', $this->_prefixes);
61 | if (preg_match('#.*(' . $prefixRegex . '_[\\w_]*).*#', $token[1], $matches)) {
62 | $className = $matches[1];
63 | $fileNameProc = $this->_fileRegistry->findByOriginalClassName($className);
64 | if ($fileNameProc) {
65 | $newClassName = '\\' . $fileNameProc->getNewFullyQualifiedName();
66 | $tokenContent = preg_replace('#' . $className . '#', $newClassName, $matches[0]);
67 | $newToken[1] = $tokenContent;
68 | $this->_newTokens[] = $newToken;
69 | } else {
70 | $this->_newTokens[] = $token;
71 | }
72 |
73 | } else {
74 | $this->_newTokens[] = $token;
75 | }
76 | $context = null;
77 | } else {
78 | $this->_newTokens[] = $token;
79 | }
80 | break;
81 | default:
82 | $this->_newTokens[] = $token;
83 | break;
84 | }
85 | }
86 |
87 | }
88 |
89 | }
90 |
--------------------------------------------------------------------------------
/tests/PHPToolsTest/Namespacer/_files/Zend/Filter/Alpha.php:
--------------------------------------------------------------------------------
1 | toArray();
71 | } else if (is_array($allowWhiteSpace)) {
72 | if (array_key_exists('allowwhitespace', $allowWhiteSpace)) {
73 | $allowWhiteSpace = $allowWhiteSpace['allowwhitespace'];
74 | } else {
75 | $allowWhiteSpace = false;
76 | }
77 | }
78 |
79 | $this->allowWhiteSpace = (boolean) $allowWhiteSpace;
80 | if (null === self::$_unicodeEnabled) {
81 | self::$_unicodeEnabled = (@preg_match('/\pL/u', 'a')) ? true : false;
82 | }
83 |
84 | if (null === self::$_meansEnglishAlphabet) {
85 | $this->_locale = new Zend_Locale('auto');
86 | self::$_meansEnglishAlphabet = in_array($this->_locale->getLanguage(),
87 | array('ja', 'ko', 'zh')
88 | );
89 | }
90 |
91 | }
92 |
93 | /**
94 | * Returns the allowWhiteSpace option
95 | *
96 | * @return boolean
97 | */
98 | public function getAllowWhiteSpace()
99 | {
100 | return $this->allowWhiteSpace;
101 | }
102 |
103 | /**
104 | * Sets the allowWhiteSpace option
105 | *
106 | * @param boolean $allowWhiteSpace
107 | * @return Zend_Filter_Alpha Provides a fluent interface
108 | */
109 | public function setAllowWhiteSpace($allowWhiteSpace)
110 | {
111 | $this->allowWhiteSpace = (boolean) $allowWhiteSpace;
112 | return $this;
113 | }
114 |
115 | /**
116 | * Defined by Zend_Filter_Interface
117 | *
118 | * Returns the string $value, removing all but alphabetic characters
119 | *
120 | * @param string $value
121 | * @return string
122 | */
123 | public function filter($value)
124 | {
125 | $whiteSpace = $this->allowWhiteSpace ? '\s' : '';
126 | if (!self::$_unicodeEnabled) {
127 | // POSIX named classes are not supported, use alternative a-zA-Z match
128 | $pattern = '/[^a-zA-Z' . $whiteSpace . ']/';
129 | } else if (self::$_meansEnglishAlphabet) {
130 | //The Alphabet means english alphabet.
131 | $pattern = '/[^a-zA-Z' . $whiteSpace . ']/u';
132 | } else {
133 | //The Alphabet means each language's alphabet.
134 | $pattern = '/[^\p{L}' . $whiteSpace . ']/u';
135 | }
136 |
137 | return preg_replace($pattern, '', (string) $value);
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/tests/PHPToolsTest/Namespacer/_files/Zend/Filter/Alnum.php:
--------------------------------------------------------------------------------
1 | toArray();
71 | } else if (is_array($allowWhiteSpace)) {
72 | if (array_key_exists('allowwhitespace', $allowWhiteSpace)) {
73 | $allowWhiteSpace = $allowWhiteSpace['allowwhitespace'];
74 | } else {
75 | $allowWhiteSpace = false;
76 | }
77 | }
78 |
79 | $this->allowWhiteSpace = (boolean) $allowWhiteSpace;
80 | if (null === self::$_unicodeEnabled) {
81 | self::$_unicodeEnabled = (@preg_match('/\pL/u', 'a')) ? true : false;
82 | }
83 |
84 | if (null === self::$_meansEnglishAlphabet) {
85 | $this->_locale = new Zend_Locale('auto');
86 | self::$_meansEnglishAlphabet = in_array($this->_locale->getLanguage(),
87 | array('ja', 'ko', 'zh')
88 | );
89 | }
90 |
91 | }
92 |
93 | /**
94 | * Returns the allowWhiteSpace option
95 | *
96 | * @return boolean
97 | */
98 | public function getAllowWhiteSpace()
99 | {
100 | return $this->allowWhiteSpace;
101 | }
102 |
103 | /**
104 | * Sets the allowWhiteSpace option
105 | *
106 | * @param boolean $allowWhiteSpace
107 | * @return Zend_Filter_Alnum Provides a fluent interface
108 | */
109 | public function setAllowWhiteSpace($allowWhiteSpace)
110 | {
111 | $this->allowWhiteSpace = (boolean) $allowWhiteSpace;
112 | return $this;
113 | }
114 |
115 | /**
116 | * Defined by Zend_Filter_Interface
117 | *
118 | * Returns the string $value, removing all but alphabetic and digit characters
119 | *
120 | * @param string $value
121 | * @return string
122 | */
123 | public function filter($value)
124 | {
125 | $whiteSpace = $this->allowWhiteSpace ? '\s' : '';
126 | if (!self::$_unicodeEnabled) {
127 | // POSIX named classes are not supported, use alternative a-zA-Z0-9 match
128 | $pattern = '/[^a-zA-Z0-9' . $whiteSpace . ']/';
129 | } else if (self::$_meansEnglishAlphabet) {
130 | //The Alphabet means english alphabet.
131 | $pattern = '/[^a-zA-Z0-9' . $whiteSpace . ']/u';
132 | } else {
133 | //The Alphabet means each language's alphabet.
134 | $pattern = '/[^\p{L}\p{N}' . $whiteSpace . ']/u';
135 | }
136 |
137 | return preg_replace($pattern, '', (string) $value);
138 | }
139 |
140 | public function setArray(ArrayObject $o)
141 | {
142 | $return = Foo::FOO;
143 | return self::FOO;
144 | }
145 | }
146 |
--------------------------------------------------------------------------------
/library/PHPTools/Namespacer/FileRegistry.php:
--------------------------------------------------------------------------------
1 | _fileNameProcessors[$objectId] = $fileNameProcessor;
25 |
26 | $this->_fileNameByOriginalFilePathIndex[$fileNameProcessor->getOriginalFilePath()] = $objectId;
27 | $this->_fileNameByOriginalRelativeFilePathIndex[$fileNameProcessor->getOriginalRelativeFilePath()] = $objectId;
28 | $this->_fileNameByOriginalClassNameIndex[$fileNameProcessor->getOriginalClassName()] = $objectId;
29 | $this->_fileNameByNewFullyQualifiedNameIndex[$fileNameProcessor->getNewFullyQualifiedName()] = $objectId;
30 |
31 | return $this;
32 | }
33 |
34 | public function registerFileContentProcessor(FileContentProcessor $fileContentProcessor)
35 | {
36 | $objectId = spl_object_hash($fileContentProcessor);
37 | $this->_fileContentProcessors[$objectId] = $fileContentProcessor;
38 |
39 | $fileNameProcessorObjectId = spl_object_hash($fileContentProcessor->getFileNameProcessor());
40 | $this->_fileContentProcessorToFileNameProcessorIndex[$objectId] = $fileNameProcessorObjectId;
41 | }
42 |
43 | public function findByOriginalFilePath($originalFilePath)
44 | {
45 | if (array_key_exists($originalFilePath, $this->_fileNameByOriginalFilePathIndex)) {
46 | $objId = $this->_fileNameByOriginalFilePathIndex[$originalFilePath];
47 | if ($objId && array_key_exists($objId, $this->_fileNameProcessors)) {
48 | return $this->_fileNameProcessors[$objId];
49 | }
50 | }
51 | return false;
52 | }
53 |
54 | public function findByOriginalRelativeFilePath($originalRelativeFilePath)
55 | {
56 | if (array_key_exists($originalRelativeFilePath, $this->_fileNameByOriginalRelativeFilePathIndex)) {
57 | $objId = $this->_fileNameByOriginalRelativeFilePathIndex[$originalRelativeFilePath];
58 | if ($objId && array_key_exists($objId, $this->_fileNameProcessors)) {
59 | return $this->_fileNameProcessors[$objId];
60 | }
61 | }
62 | return false;
63 | }
64 |
65 | public function findByOriginalClassName($originalClassName)
66 | {
67 | if (array_key_exists($originalClassName, $this->_fileNameByOriginalClassNameIndex)) {
68 | $objId = $this->_fileNameByOriginalClassNameIndex[$originalClassName];
69 | if ($objId && array_key_exists($objId, $this->_fileNameProcessors)) {
70 | return $this->_fileNameProcessors[$objId];
71 | }
72 | }
73 | return false;
74 | }
75 |
76 | public function findByNewFullyQualifiedName($newFullyQualifiedName)
77 | {
78 | if (array_key_exists($newFullyQualifiedName, $this->_fileNameByNewFullyQualifiedNameIndex)) {
79 | $objId = $this->_fileNameByNewFullyQualifiedNameIndex[$newFullyQualifiedName];
80 | if ($objId && array_key_exists($objId, $this->_fileNameProcessors)) {
81 | return $this->_fileNameProcessors[$objId];
82 | }
83 | }
84 | return false;
85 | }
86 |
87 | public function getFileNameProcessorForContentProcessor(FileContentProcessor $fileContentProcessor)
88 | {
89 | $fcpObjectId = spl_object_hash($fileContentProcessor);
90 |
91 | $objectId = $this->_fileContentProcessorToFileNameProcessorIndex[$fcpObjectId];
92 | return $this->_fileNameProcessors[$objectId];
93 | }
94 |
95 | public function setIterationType($iterationType = self::ITERATE_NAMES)
96 | {
97 | $this->_iterationType = $iterationType;
98 | }
99 |
100 | public function getIterator()
101 | {
102 | switch ($this->_iterationType) {
103 | case self::ITERATE_CONTENTS:
104 | return new \ArrayIterator($this->_fileContentProcessors);
105 | case self::ITERATE_NAMES:
106 | default:
107 | return new \ArrayIterator($this->_fileNameConverters);
108 | }
109 | }
110 |
111 | public function count()
112 | {
113 | return count($this->_fileNameProcessors);
114 | }
115 |
116 | }
117 |
--------------------------------------------------------------------------------
/library/PHPTools/Namespacer/FileNameProcessor.php:
--------------------------------------------------------------------------------
1 | _libraryDirectory = $libraryDirectory;
21 |
22 | if (is_string($relativeFilePath)) {
23 | $this->_originalRelativeFilePath = $relativeFilePath;
24 | $this->_process();
25 | } elseif (is_array($relativeFilePath)) {
26 | $options = $relativeFilePath;
27 | $this->_originalRelativeFilePath = $options['originalRelativeFilePath'];
28 | $this->_originalClassName = $options['originalClassName'];
29 | $this->_newRelativeFilePath = $options['newRelativeFilePath'];
30 | $this->_newNamespace = $options['newNamespace'];
31 | $this->_newClassName = $options['newClassName'];
32 | $this->_newFullyQualifiedName = $options['newFullyQualifiedName'];
33 | }
34 | }
35 |
36 | public function getOriginalFilePath()
37 | {
38 | return rtrim($this->_libraryDirectory, '/\\') . DIRECTORY_SEPARATOR . $this->_originalRelativeFilePath;
39 | }
40 |
41 | public function getOriginalRelativeFilePath()
42 | {
43 | return $this->_originalRelativeFilePath;
44 | }
45 |
46 | public function getOriginalClassName()
47 | {
48 | return $this->_originalClassName;
49 | }
50 |
51 | public function getLibraryDirectory()
52 | {
53 | return $this->_libraryDirectory;
54 | }
55 |
56 | public function getNewRelativeFilePath()
57 | {
58 | return $this->_newRelativeFilePath;
59 | }
60 |
61 | public function getNewFullyQualifiedName()
62 | {
63 | return $this->_newFullyQualifiedName;
64 | }
65 |
66 | public function getNewNamespace()
67 | {
68 | return $this->_newNamespace;
69 | }
70 |
71 | public function getNewClassName()
72 | {
73 | return $this->_newClassName;
74 | }
75 |
76 | protected function _process()
77 | {
78 | // change separators to underscore
79 | $this->_originalClassName = str_replace(array('/', '\\'), '_', $this->_originalRelativeFilePath);
80 | $this->_originalClassName = substr($this->_originalClassName, 0, -4);
81 |
82 | $originalClassParts = explode('_', $this->_originalClassName);
83 | $newClassParts = $originalClassParts;
84 |
85 | // does this class have sub parts?
86 | if (is_dir($this->_libraryDirectory . '/' . implode('/', $newClassParts))) {
87 | $lastSegment = end($newClassParts);
88 | $newClassParts[] = $lastSegment;
89 | }
90 |
91 | $this->_newNamespace = implode('\\', array_slice($newClassParts, 0, count($newClassParts)-1));
92 |
93 | $lastClassPart = end($newClassParts);
94 | $this->_newClassName = $this->_createSafeClassName($lastClassPart);
95 |
96 |
97 | $this->_newFullyQualifiedName = $this->_newNamespace . '\\' . $this->_newClassName;
98 | $this->_newRelativeFilePath = str_replace('\\', '/', $this->_newFullyQualifiedName) . '.php';
99 |
100 | }
101 |
102 | protected function _createSafeClassName($className)
103 | {
104 | if ($className === 'Abstract') {
105 | $className = 'Abstract' . substr($this->_newNamespace, strrpos($this->_newNamespace, '\\') + 1);
106 | } elseif ($className === 'Interface') {
107 | $className = substr($this->_newNamespace, strrpos($this->_newNamespace, '\\') + 1) . 'Interface';
108 | }
109 |
110 | $reservedWords = array(
111 | 'and','array','as','break','case','catch','class','clone',
112 | 'const','continue','declare','default','do','else','elseif',
113 | 'enddeclare','endfor','endforeach','endif','endswitch','endwhile',
114 | 'extends','final','for','foreach','function','global',
115 | 'goto','if','implements','instanceof','namespace',
116 | 'new','or','private','protected','public','static','switch',
117 | 'throw','try','use','var','while','xor'
118 | );
119 |
120 | if (in_array($className, $reservedWords)) {
121 | $className = $className . 'CLASS';
122 | }
123 |
124 | return $className;
125 | }
126 |
127 | public function __toString()
128 | {
129 | return $this->_originalClassName . ' => ' . $this->_newFullyQualifiedName;
130 | }
131 |
132 |
133 | }
--------------------------------------------------------------------------------
/library/PHPTools/SPL/SplClassLoader.php:
--------------------------------------------------------------------------------
1 |
10 | */
11 |
12 | namespace PHPTools\SPL;
13 |
14 | /**
15 | * SplClassLoader implementation that implements the technical interoperability
16 | * standards for PHP 5.3 namespaces and class names.
17 | *
18 | * http://groups.google.com/group/php-standards/web/final-proposal
19 | *
20 | * // Example which loads classes for the Doctrine Common package in the
21 | * // Doctrine\Common namespace.
22 | * $classLoader = new SplClassLoader('Doctrine\Common', '/path/to/doctrine');
23 | * $classLoader->register();
24 | *
25 | * @author Jonathan H. Wage
26 | * @author Roman S. Borschel
27 | * @author Matthew Weier O'Phinney
28 | * @author Kris Wallsmith
29 | * @author Fabien Potencier
30 | */
31 | class SplClassLoader
32 | {
33 | private $_fileExtension = '.php';
34 | private $_namespace;
35 | private $_includePath;
36 | private $_namespaceSeparator = '\\';
37 |
38 | /**
39 | * Creates a new SplClassLoader that loads classes of the
40 | * specified namespace.
41 | *
42 | * @param string $ns The namespace to use.
43 | */
44 | public function __construct($ns = null, $includePath = null)
45 | {
46 | $this->_namespace = $ns;
47 | $this->_includePath = $includePath;
48 | }
49 |
50 | /**
51 | * Sets the namespace separator used by classes in the namespace of this class loader.
52 | *
53 | * @param string $sep The separator to use.
54 | */
55 | public function setNamespaceSeparator($sep)
56 | {
57 | $this->_namespaceSeparator = $sep;
58 | }
59 |
60 | /**
61 | * Gets the namespace seperator used by classes in the namespace of this class loader.
62 | *
63 | * @return void
64 | */
65 | public function getNamespaceSeparator()
66 | {
67 | return $this->_namespaceSeparator;
68 | }
69 |
70 | /**
71 | * Sets the base include path for all class files in the namespace of this class loader.
72 | *
73 | * @param string $includePath
74 | */
75 | public function setIncludePath($includePath)
76 | {
77 | $this->_includePath = $includePath;
78 | }
79 |
80 | /**
81 | * Gets the base include path for all class files in the namespace of this class loader.
82 | *
83 | * @return string $includePath
84 | */
85 | public function getIncludePath()
86 | {
87 | return $this->_includePath;
88 | }
89 |
90 | /**
91 | * Sets the file extension of class files in the namespace of this class loader.
92 | *
93 | * @param string $fileExtension
94 | */
95 | public function setFileExtension($fileExtension)
96 | {
97 | $this->_fileExtension = $fileExtension;
98 | }
99 |
100 | /**
101 | * Gets the file extension of class files in the namespace of this class loader.
102 | *
103 | * @return string $fileExtension
104 | */
105 | public function getFileExtension()
106 | {
107 | return $this->_fileExtension;
108 | }
109 |
110 | /**
111 | * Installs this class loader on the SPL autoload stack.
112 | */
113 | public function register()
114 | {
115 | spl_autoload_register(array($this, 'loadClass'));
116 | }
117 |
118 | /**
119 | * Uninstalls this class loader from the SPL autoloader stack.
120 | */
121 | public function unregister()
122 | {
123 | spl_autoload_unregister(array($this, 'loadClass'));
124 | }
125 |
126 | /**
127 | * Loads the given class or interface.
128 | *
129 | * @param string $className The name of the class to load.
130 | * @return void
131 | */
132 | public function loadClass($className)
133 | {
134 | $className = ltrim($className, $this->_namespaceSeparator);
135 | if (null === $this->_namespace || $this->_namespace.$this->_namespaceSeparator === substr($className, 0, strlen($this->_namespace.$this->_namespaceSeparator))) {
136 | $fileName = '';
137 | $namespace = '';
138 | if (false !== ($lastNsPos = strripos($className, $this->_namespaceSeparator))) {
139 | $namespace = substr($className, 0, $lastNsPos);
140 | $className = substr($className, $lastNsPos + 1);
141 | $fileName = str_replace($this->_namespaceSeparator, DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR;
142 | }
143 | $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . $this->_fileExtension;
144 |
145 | require ($this->_includePath !== null ? $this->_includePath . DIRECTORY_SEPARATOR : '') . $fileName;
146 | }
147 | }
148 |
149 | }
150 |
--------------------------------------------------------------------------------
/library/PHPTools/Namespacer/CLIRunner.php:
--------------------------------------------------------------------------------
1 | run();
17 | }
18 |
19 | public function __construct()
20 | {
21 | if (PHP_SAPI != 'cli') {
22 | throw new \RuntimeException('This class is only available in the CLI PHP Environment');
23 | }
24 | }
25 |
26 | public function run($options = array())
27 | {
28 | $namespacer = new Namespacer();
29 | $this->_parseOptions($namespacer, $options);
30 | }
31 |
32 | protected function _parseOptions(Namespacer $namespacer, array $options = array())
33 | {
34 | if (!$options) {
35 |
36 | $usersOptions = getopt(
37 | 'h::l::d::o::p::s::m::',
38 | array(
39 | 'help::',
40 | 'lib::',
41 | 'library-directory::',
42 | 'dir::',
43 | 'directory-filter::',
44 | 'out::',
45 | 'output-path::',
46 | 'prefix::',
47 | 'prefixes::',
48 | 'stats::',
49 | 'show-statistics::',
50 | 'map::',
51 | 'map-path::'
52 | )
53 | );
54 |
55 | $userToOfficialNames = array(
56 | 'h' => 'help',
57 | 'help' => 'help',
58 | 'l' => 'libraryDirectory',
59 | 'lib' => 'libraryDirectory',
60 | 'library-directory' => 'libraryDirectory',
61 | 'd' => 'directoryFilter',
62 | 'dir' => 'directoryFilter',
63 | 'directory-filter' => 'directoryFilter',
64 | 'o' => 'outputPath',
65 | 'out' => 'outputPath',
66 | 'output-path' => 'outputPath',
67 | 'p' => 'prefixes',
68 | 'prefix' => 'prefixes',
69 | 'prefixes' => 'prefixes',
70 | 's' => 'showStatistics',
71 | 'stats' => 'showStatistics',
72 | 'show-statistics' => 'showStatistics',
73 | 'm' => 'mapPath',
74 | 'map' => 'mapPath',
75 | 'map-path' => 'mapPath'
76 | );
77 |
78 | $options = array();
79 |
80 | foreach ($userToOfficialNames as $userOptionName => $officialName) {
81 | if (isset($usersOptions[$userOptionName])) {
82 | $options[$officialName] = $usersOptions[$userOptionName];
83 | }
84 | }
85 | }
86 |
87 | if (isset($options['help'])) {
88 | $this->_showHelp();
89 | return;
90 | }
91 |
92 | try {
93 | $namespacer->setOptions($options);
94 | $namespacer->convert();
95 | } catch (\Exception $e) {
96 | echo 'Exception caught ' . get_class($e) . ' : ' . $e->getMessage();
97 | exit(1);
98 | }
99 |
100 | }
101 |
102 | protected function _showHelp()
103 | {
104 | echo <<_filters as $filter) {
86 | $valueFiltered = $filter->filter($valueFiltered);
87 | }
88 | return $valueFiltered;
89 | }
90 |
91 | /** REMOVED ORIGINAL CODE, NO PURPOSE IN THIS TEST FILE */
92 |
93 | /**
94 | * @deprecated
95 | * @see Zend_Filter::filterStatic()
96 | *
97 | * @param mixed $value
98 | * @param string $classBaseName
99 | * @param array $args OPTIONAL
100 | * @param array|string $namespaces OPTIONAL
101 | * @return mixed
102 | * @throws Zend_Filter_Exception
103 | */
104 | public static function get($value, $classBaseName, array $args = array(), $namespaces = array())
105 | {
106 | trigger_error(
107 | 'Zend_Filter::get() is deprecated as of 1.9.0; please update your code to utilize Zend_Filter::filterStatic()',
108 | E_USER_NOTICE
109 | );
110 |
111 | return self::filterStatic($value, $classBaseName, $args, $namespaces);
112 | }
113 |
114 | /**
115 | * Returns a value filtered through a specified filter class, without requiring separate
116 | * instantiation of the filter object.
117 | *
118 | * The first argument of this method is a data input value, that you would have filtered.
119 | * The second argument is a string, which corresponds to the basename of the filter class,
120 | * relative to the Zend_Filter namespace. This method automatically loads the class,
121 | * creates an instance, and applies the filter() method to the data input. You can also pass
122 | * an array of constructor arguments, if they are needed for the filter class.
123 | *
124 | * @param mixed $value
125 | * @param string $classBaseName
126 | * @param array $args OPTIONAL
127 | * @param array|string $namespaces OPTIONAL
128 | * @return mixed
129 | * @throws Zend_Filter_Exception
130 | */
131 | public static function filterStatic($value, $classBaseName, array $args = array(), $namespaces = array())
132 | {
133 | $namespaces = array_merge((array) $namespaces, self::$_defaultNamespaces, array('Zend_Filter'));
134 | foreach ($namespaces as $namespace) {
135 | $className = $namespace . '_' . ucfirst($classBaseName);
136 | if (!class_exists($className, false)) {
137 | try {
138 | $file = str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php';
139 | if (Zend_Loader::isReadable($file)) {
140 | Zend_Loader::loadClass($className);
141 | } else {
142 | continue;
143 | }
144 | } catch (Zend_Exception $ze) {
145 | continue;
146 | }
147 | }
148 |
149 | $class = new ReflectionClass($className);
150 | if ($class->implementsInterface('Zend_Filter_Interface')) {
151 | if ($class->hasMethod('__construct')) {
152 | $object = $class->newInstanceArgs($args);
153 | } else {
154 | $object = $class->newInstance();
155 | }
156 | return $object->filter($value);
157 | }
158 | }
159 | throw new Zend_Filter_Exception("Filter class not found from basename '$classBaseName'");
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/library/PHPTools/Namespacer/Namespacer.php:
--------------------------------------------------------------------------------
1 | setOptions($options);
23 | }
24 | $this->_fileRegistry = new FileRegistry();
25 | }
26 |
27 | public function setOptions(Array $options)
28 | {
29 | foreach ($options as $optionName => $optionValue) {
30 | $this->setOption($optionName, $optionValue);
31 | }
32 | }
33 |
34 | public function setOption($optionName, $optionValue = true)
35 | {
36 | switch ($optionName) {
37 | case 'libraryDirectory':
38 | $this->_libraryDirectoryOriginal = $optionValue;
39 | $this->_libraryDirectory = realpath($this->_libraryDirectoryOriginal);
40 | if (!file_exists($this->_libraryDirectory)) {
41 | throw new \InvalidArgumentException('Library directory provided does not exist (' . $this->_libraryDirectory . ')');
42 | }
43 | break;
44 | case 'directoryFilter':
45 | $this->_directoryFilter = $optionValue;
46 | break;
47 | case 'outputPath':
48 | $this->_outputPath = $optionValue;
49 | if (!file_exists(realpath($this->_outputPath))) {
50 | if (!file_exists(realpath(dirname($this->_outputPath)))) {
51 | throw new \InvalidArgumentException('The output path provided does not exist and cannot be created in ' . $this->_outputPath);
52 | }
53 | mkdir($this->_outputPath);
54 | }
55 | break;
56 | case 'mapPath':
57 | $this->_mapPath = $optionValue;
58 | if (!file_exists(realpath($this->_mapPath))) {
59 | if (!file_exists(realpath(dirname($this->_mapPath)))) {
60 | throw new \InvalidArgumentException('The output path provided does not exist and cannot be created in ' . $this->_mapPath);
61 | }
62 | mkdir($this->_mapPath);
63 | }
64 | break;
65 | case 'prefixes':
66 | $this->_prefixes = explode(',', $optionValue);
67 | break;
68 | case 'showStatistics':
69 | $this->_showStatistics = $optionValue;
70 | break;
71 | default:
72 | throw new \InvalidArgumentException('Option ' . $optionName . ' is not supporter by ' . __CLASS__);
73 | }
74 | }
75 |
76 | public function getOptions()
77 | {
78 | return array(
79 | 'libraryDirectory' => $this->_libraryDirectory,
80 | 'directoryFilter' => $this->_directoryFilter,
81 | 'outputPath' => $this->_outputPath,
82 | 'prefixes' => $this->_prefixes,
83 | 'showStatistics' => $this->_showStatistics
84 | );
85 | }
86 |
87 | public function getFileRegistry()
88 | {
89 | return $this->_fileRegistry;
90 | }
91 |
92 | public function convert()
93 | {
94 | if (isset($this->_libraryDirectory)) {
95 | $rdi = $it = new \RecursiveDirectoryIterator($this->_libraryDirectory);
96 |
97 | if (isset($this->_directoryFilter)) {
98 | // use our RecursiveFilterIterator, not SPL's
99 | $it = new RecursiveFilterIterator($rdi, $this->_directoryFilter);
100 | }
101 |
102 | $buildFileMapFromDirectory = true;
103 |
104 | if ($this->_mapPath) {
105 | $mapFilePath = $this->_mapPath . '/PHPNamespacer-MappedClasses.xml';
106 | $mapFileRealPath = realpath($mapFilePath);
107 | if (file_exists($mapFileRealPath)) {
108 | $this->_loadMapFile($mapFileRealPath);
109 | $buildFileMapFromDirectory = false;
110 | } else {
111 | $xmlWriter = new XMLWriter();
112 | $xmlWriter->openURI($mapFilePath);
113 | $xmlWriter->setIndent(true);
114 | $xmlWriter->setIndentString(' ');
115 | $xmlWriter->startDocument('1.0');
116 | $xmlWriter->startElement('mappedClasses');
117 | $xmlWriter->writeAttribute('libraryDirectory', $this->_libraryDirectoryOriginal);
118 | }
119 | }
120 |
121 | if ($buildFileMapFromDirectory) {
122 | foreach (new \RecursiveIteratorIterator($rdi, \RecursiveIteratorIterator::SELF_FIRST) as $realFilePath => $fileInfo) {
123 | $relativeFilePath = substr($realFilePath, strlen($this->_libraryDirectory)+1);
124 | if (preg_match('#(\.svn|_svn|\.git)#', $relativeFilePath) || !preg_match('#\.php$#', $relativeFilePath)) {
125 | continue;
126 | }
127 | $fileNameProcessor = new FileNameProcessor($relativeFilePath, $this->_libraryDirectory);
128 | // add only classes that contain a matching prefix
129 | if (!$this->_prefixes || preg_match('#^' . implode('|', $this->_prefixes) . '#', $fileNameProcessor->getOriginalClassName())) {
130 | $this->_fileRegistry->registerFileNameProcessor($fileNameProcessor);
131 | if (isset($xmlWriter)) {
132 | $xmlWriter->startElement('mappedClass');
133 | $xmlWriter->writeElement('originalRelativeFilePath', $fileNameProcessor->getOriginalRelativeFilePath());
134 | $xmlWriter->writeElement('originalClassName', $fileNameProcessor->getOriginalClassName());
135 | $xmlWriter->writeElement('newRelativeFilePath', $fileNameProcessor->getNewRelativeFilePath());
136 | $xmlWriter->writeElement('newNamespace', $fileNameProcessor->getNewNamespace());
137 | $xmlWriter->writeElement('newClassName', $fileNameProcessor->getNewClassName());
138 | $xmlWriter->writeElement('newFullyQualifiedName', $fileNameProcessor->getNewFullyQualifiedName());
139 | $xmlWriter->endElement();
140 | }
141 | }
142 | }
143 | }
144 |
145 | if (isset($xmlWriter)) {
146 | $xmlWriter->endElement();
147 | $xmlWriter->endDocument();
148 | $xmlWriter->flush();
149 | echo 'Number of classes written to map file: ' . count($this->_fileRegistry) . PHP_EOL;
150 | }
151 |
152 | if ($this->_outputPath) {
153 |
154 | foreach (new \RecursiveIteratorIterator($it, \RecursiveIteratorIterator::SELF_FIRST) as $realFilePath => $fileInfo) {
155 | if ($fileInfo->isFile()) {
156 | $relativeFilePath = substr($realFilePath, strlen($this->_libraryDirectory)+1);
157 | $fileNameProc = $this->_fileRegistry->findByOriginalRelativeFilePath($relativeFilePath);
158 | if ($fileNameProc) {
159 | $fileContentProcessor = new FileContentProcessor($fileNameProc, $this->_prefixes, $this->_fileRegistry);
160 | $this->_fileRegistry->registerFileContentProcessor($fileContentProcessor);
161 | }
162 | }
163 | }
164 |
165 | $this->_fileRegistry->setIterationType(FileRegistry::ITERATE_CONTENTS);
166 | foreach ($this->_fileRegistry as $fileContentProc) {
167 | $fileNameProc = $this->_fileRegistry->getFileNameProcessorForContentProcessor($fileContentProc);
168 |
169 | $base = dirname($fileNameProc->getNewRelativeFilePath());
170 | if (!file_exists($this->_outputPath . '/' . $base)) {
171 | mkdir($this->_outputPath . '/' . $base, 0777, true);
172 | }
173 |
174 | file_put_contents($this->_outputPath . '/' . $fileNameProc->getNewRelativeFilePath(), $fileContentProc->getNewContents());
175 | }
176 | }
177 | } else {
178 | throw new \RuntimeException('Neither a filePath or a libraryDirectory was supplied to the Namespacer.');
179 | }
180 |
181 | }
182 |
183 | protected function _loadMapFile($mapFile)
184 | {
185 | echo 'Loading a map file found at ' . $mapFile . PHP_EOL;
186 | $mappedClassElementNames = array(
187 | 'originalRelativeFilePath',
188 | 'originalClassName',
189 | 'newRelativeFilePath',
190 | 'newNamespace',
191 | 'newClassName',
192 | 'newFullyQualifiedName',
193 | );
194 | $reader = new XMLReader();
195 | $reader->open($mapFile);
196 |
197 | $map = array();
198 | while ($reader->read()) {
199 | if ($reader->name == 'mappedClasses' && $reader->nodeType == XMLReader::ELEMENT) {
200 | $libraryDirectory = $reader->getAttribute('libraryDirectory');
201 | $realLibraryDirectory = realpath($libraryDirectory);
202 | if ($realLibraryDirectory != $this->_libraryDirectory) {
203 | throw new \UnexpectedValueException('The libraryDirectory located in the map file is not the same as the one provided for execution.');
204 | }
205 | continue;
206 | }
207 | if ($reader->name == 'mappedClass' && $reader->nodeType == XMLReader::ELEMENT) {
208 | $mappedClass = array();
209 |
210 | foreach ($reader->expand()->childNodes as $domNode) {
211 | if (in_array($domNode->nodeName, $mappedClassElementNames)) {
212 | $mappedClass[$domNode->nodeName] = $domNode->nodeValue;
213 | }
214 | }
215 |
216 | $fileNameProcessor = new FileNameProcessor($mappedClass, $libraryDirectory);
217 | $this->_fileRegistry->registerFileNameProcessor($fileNameProcessor);
218 | $reader->next();
219 | }
220 | }
221 |
222 | }
223 |
224 | protected function _displayInfo($infoArray)
225 | {
226 | echo ' Class name found: ' . $infoArray['className'] . PHP_EOL;
227 | if (isset($infoArray['consumedClasses'])) {
228 | echo ' Classes consumed:' . PHP_EOL;
229 | foreach ($infoArray['consumedClasses'] as $consumedClass) {
230 | echo ' ' . $consumedClass . PHP_EOL;
231 | }
232 | }
233 | echo PHP_EOL;
234 | }
235 |
236 | }
237 |
--------------------------------------------------------------------------------
/library/PHPTools/Namespacer/FileContentProcessor.php:
--------------------------------------------------------------------------------
1 | _fileNameProcessor = $fileNameProcessor;
27 | $this->_prefixes = $prefixes;
28 | $this->_fileRegistry = $fileRegistry;
29 |
30 | if (extension_loaded('docblock')) {
31 | $this->_canTokenizeDocblocks = true;
32 | }
33 |
34 | $this->_process();
35 | }
36 |
37 | public function getFileNameProcessor()
38 | {
39 | return $this->_fileNameProcessor;
40 | }
41 |
42 | public function getInformation()
43 | {
44 | $info = array();
45 | foreach ($this->_interestingTokens as $tokenType => $tokenInfo) {
46 | switch ($tokenType) {
47 | case 'className':
48 | $info['className'] = $tokenInfo->value;
49 | break;
50 | case 'consumedClass':
51 | $info['consumedClasses'] = array();
52 | foreach ((array) $tokenInfo as $consumedClassToken) {
53 | if (!in_array($consumedClassToken->value, $info['consumedClasses'])) {
54 | $info['consumedClasses'][] = $consumedClassToken->value;
55 | }
56 | }
57 | break;
58 | }
59 | }
60 | return $info;
61 | }
62 |
63 | public function getNewContents()
64 | {
65 | if (!$this->_newTokens) {
66 | $this->convert();
67 | }
68 |
69 | $contents = null;
70 | foreach ($this->_newTokens as $token) {
71 | if (is_array($token)) {
72 | $contents .= $token[1];
73 | } else {
74 | $contents .= $token;
75 | }
76 | }
77 |
78 | return $contents;
79 | }
80 |
81 | protected function _process()
82 | {
83 | $this->_analyze();
84 | $this->_generate();
85 | }
86 |
87 | protected function _analyze()
88 | {
89 | $this->_originalContent = file_get_contents($this->_fileNameProcessor->getOriginalFilePath());
90 | $this->_originalTokens = token_get_all($this->_originalContent);
91 | $this->_staticAnalysis();
92 | // other analysis processes here?
93 | }
94 |
95 | protected function _staticAnalysis()
96 | {
97 | $context = null;
98 |
99 | foreach ($this->_originalTokens as $tokenNumber => $token) {
100 | if (is_array($token)) {
101 | $tokenName = token_name($token[0]);
102 | } else {
103 | $tokenName = 'string:' . $token;
104 | }
105 |
106 | if ($tokenNumber >= 3 && $context == 'INSIDE_OPEN_TAG') {
107 | $context = null;
108 | }
109 |
110 | // mostly for debugging
111 | $surroundingTokens = array();
112 | $surroundingTokens[-2] = (isset($this->_originalTokens[$tokenNumber - 2])) ? $this->_originalTokens[$tokenNumber - 2] : null;
113 | $surroundingTokens[-1] = (isset($this->_originalTokens[$tokenNumber - 1])) ? $this->_originalTokens[$tokenNumber - 1] : null;
114 | $surroundingTokens[1] = (isset($this->_originalTokens[$tokenNumber + 1])) ? $this->_originalTokens[$tokenNumber + 1] : null;
115 | $surroundingTokens[2] = (isset($this->_originalTokens[$tokenNumber + 2])) ? $this->_originalTokens[$tokenNumber + 2] : null;
116 |
117 | switch ($tokenName) {
118 | case 'T_OPEN_TAG':
119 | if ($tokenNumber < 3) {
120 | $context = 'INSIDE_OPEN_TAG';
121 | }
122 | break;
123 | case 'T_DOC_COMMENT':
124 | if ($context == 'INSIDE_OPEN_TAG') {
125 | $this->_registerInterestingToken('topOfFile', $tokenNumber + 1, true);
126 | $context = null;
127 | }
128 | $this->_registerInterestingToken('docblock', $tokenNumber, true);
129 | break;
130 |
131 | case 'T_INTERFACE':
132 | $context = 'INSIDE_CLASS_DECLARATION';
133 | $this->_interestingInformation['isInterface'] = true;
134 | case 'T_CLASS':
135 | $context = 'INSIDE_CLASS_DECLARATION';
136 | break;
137 | case 'T_ABSTRACT':
138 | $this->_interestingInformation['isAbstract'] = true;
139 | break;
140 | case 'T_EXTENDS':
141 | case 'T_IMPLEMENTS':
142 | $context = 'INSIDE_CLASS_SIGNATURE';
143 | break;
144 | case 'T_NEW':
145 | $context = 'INSIDE_NEW_ASSIGNMENT';
146 | break;
147 | case 'T_FUNCTION':
148 | $context = 'INSIDE_FUNCTION_SIGNATURE_START';
149 | break;
150 | case 'T_CATCH':
151 | $context = 'INSIDE_CATCH_STATEMENT';
152 | break;
153 | case 'string:{':
154 | $context = null;
155 | break;
156 | case 'string:(':
157 | if ($context == 'INSIDE_FUNCTION_SIGNATURE_START') {
158 | $context = 'INSIDE_FUNCTION_SIGNATURE';
159 | }
160 | break;
161 | case 'string:)':
162 | if ($context == 'INSIDE_FUNCTION_SIGNATURE') {
163 | $context = null;
164 | }
165 | break;
166 | case 'T_DOUBLE_COLON':
167 | if (!in_array($this->_originalTokens[$tokenNumber-1][1], array('self', 'parent', 'static'))) {
168 | $this->_registerInterestingToken('consumedClass', $tokenNumber - 1);
169 | }
170 | break;
171 | case 'T_INSTANCEOF':
172 | if (!in_array($this->_originalTokens[$tokenNumber+2][1], array('self', 'parent', 'static'))) {
173 | $this->_registerInterestingToken('consumedClass', $tokenNumber + 2);
174 | }
175 |
176 | case 'T_STRING':
177 | switch ($context) {
178 | case 'INSIDE_CLASS_DECLARATION':
179 | $this->_registerInterestingToken('className', $tokenNumber, true);
180 | $context = null;
181 | break;
182 | case 'INSIDE_CLASS_SIGNATURE':
183 | $this->_registerInterestingToken('consumedClass', $tokenNumber);
184 | break;
185 | case 'INSIDE_NEW_ASSIGNMENT':
186 | $this->_registerInterestingToken('consumedClass', $tokenNumber);
187 | $context = null;
188 | break;
189 | case 'INSIDE_FUNCTION_SIGNATURE':
190 | $safeWords = array('true', 'false', 'null', 'self', 'parent', 'static');
191 | $previousToken = $surroundingTokens[-1];
192 | if (in_array($token[1], $safeWords)
193 | || (is_array($previousToken) && $previousToken[1] == '::')) {
194 | break;
195 | }
196 | $this->_registerInterestingToken('consumedClass', $tokenNumber);
197 | break;
198 | case 'INSIDE_CATCH_STATEMENT':
199 | $this->_registerInterestingToken('consumedClass', $tokenNumber);
200 | $context = null;
201 | break;
202 | }
203 |
204 | break;
205 |
206 | }
207 |
208 | }
209 |
210 | }
211 |
212 | protected function _generate()
213 | {
214 |
215 | $namespace = $this->_fileNameProcessor->getNewNamespace();
216 | $className = $this->_fileNameProcessor->getNewClassName();
217 |
218 | $prefixesRegex = implode('|', $this->_prefixes);
219 |
220 | if (!preg_match('#^' . $prefixesRegex . '#', $this->_fileNameProcessor->getOriginalClassName())) {
221 | $this->_newTokens = $this->_originalTokens;
222 | return;
223 | }
224 |
225 | // determine consumed classes
226 | $classCount = array();
227 | if (isset($this->_interestingTokens['consumedClass'])) {
228 | foreach ($this->_interestingTokens['consumedClass'] as $consumedClassToken) {
229 | $origConsumedClassName = $consumedClassToken['value'];
230 | $consumedClassFileNameProc = $this->_fileRegistry->findByOriginalClassName($origConsumedClassName);
231 | if ($consumedClassFileNameProc) {
232 | $currentConsumedClassName = $consumedClassFileNameProc->getNewFullyQualifiedName();
233 | } else {
234 | $currentConsumedClassName = $origConsumedClassName;
235 | }
236 |
237 | if (!isset($classCount[$currentConsumedClassName])) $classCount[$currentConsumedClassName] = 0;
238 | $classCount[$currentConsumedClassName]++;
239 |
240 | }
241 | }
242 |
243 | // compute uses
244 | if ($classCount) {
245 |
246 | $uses['declarations'] = $uses['translations'] = $uses = array();
247 |
248 | foreach ($classCount as $consumedClassName => $numberOfOccurances) {
249 | if ($numberOfOccurances == 1) continue;
250 | if ((strpos($consumedClassName, '\\') !== false) && (strpos($consumedClassName, $namespace) !== 0)) {
251 | $consumedClassFileNameProc = $this->_fileRegistry->findByNewFullyQualifiedName($consumedClassName);
252 | $uses['declarations'][] = $ccn = $consumedClassFileNameProc->getNewNamespace();
253 | $uses['translations'][$consumedClassName] = substr($ccn, strrpos($ccn, '\\')+1) . '\\'
254 | . str_replace($ccn . '\\', '', $consumedClassFileNameProc->getNewFullyQualifiedName());
255 | }
256 | }
257 | }
258 |
259 | foreach ($this->_originalTokens as $tokenNumber => $token) {
260 |
261 | if (!array_key_exists($tokenNumber, $this->_interestingTokenIndex)) {
262 | $this->_newTokens[] = $token;
263 | continue;
264 | }
265 |
266 | // This token is interesting for some reason
267 | $interestingReasons = $this->_interestingTokenIndex[$tokenNumber];
268 |
269 | foreach ($interestingReasons as $interestingReason) {
270 |
271 | switch ($interestingReason) {
272 | case 'topOfFile':
273 | $content = 'namespace ' . $namespace . ';' . "\n";
274 | if (isset($uses['declarations']) && $uses['declarations']) {
275 | foreach ($uses['declarations'] as $useDeclaration) {
276 | $content .= 'use ' . $useDeclaration . ';' . "\n";
277 | }
278 | }
279 | $this->_newTokens[] = "\n\n/**\n * @namespace\n */\n" . $content . "\n";
280 | break;
281 | case 'docblock':
282 | if ($this->_canTokenizeDocblocks) {
283 | $docblockProc = new DocblockContentProcessor($token[1], $this->_prefixes, $this->_fileRegistry);
284 | $this->_newTokens[] = $docblockProc->getContents();
285 | } else {
286 | $this->_newTokens[] = $token[1];
287 | }
288 | break;
289 | case 'className':
290 | $this->_newTokens[] = $className;
291 | break;
292 | case 'consumedClass':
293 | $origConsumedClassName = $token[1];
294 | $fileNameProc = $this->_fileRegistry->findByOriginalClassName($origConsumedClassName);
295 | if ($fileNameProc) {
296 | $newConsumedClass = $fileNameProc->getNewFullyQualifiedName();
297 | if (strpos($newConsumedClass, $namespace) === 0) {
298 | $newConsumedClass = substr($newConsumedClass, strlen($namespace)+1);
299 | } else {
300 | $newConsumedClass = '\\' . $newConsumedClass;
301 | }
302 | } else {
303 | $newConsumedClass = '\\' . str_replace('_', '\\', $token[1]);
304 | }
305 |
306 | if (isset($uses['translations']) && $uses['translations'] && $newConsumedClass{0} == '\\') {
307 | $translationSearchClass = ltrim($newConsumedClass, '\\');
308 | if (array_key_exists($translationSearchClass, $uses['translations'])) {
309 | $newConsumedClass = $uses['translations'][$translationSearchClass];
310 | }
311 | }
312 |
313 | if (isset($uses['declarations']) && $uses['declarations'] && $newConsumedClass{0} == '\\') {
314 | $declarationSearchClass = ltrim($newConsumedClass, '\\');
315 | foreach ($uses['declarations'] as $declarationSearchMatch) {
316 | if (strpos($declarationSearchClass, $declarationSearchMatch) === 0) {
317 | $newConsumedClass = substr($declarationSearchMatch, strrpos($declarationSearchMatch, '\\')+1) . substr($declarationSearchClass, strlen($declarationSearchMatch));
318 | }
319 | }
320 | }
321 |
322 | $this->_newTokens[] = $newConsumedClass;
323 | break;
324 | default:
325 | $this->_newTokens[] = $token;
326 | break;
327 | }
328 |
329 | }
330 |
331 | }
332 |
333 | }
334 |
335 | protected function _registerInterestingToken($name, $tokenNumber, $isSingle = false)
336 | {
337 | $token = $this->_originalTokens[$tokenNumber];
338 |
339 | if (count($token) != 3) {
340 | return;
341 | }
342 |
343 | $tokenObj = new \ArrayObject(
344 | array(
345 | 'number' => $tokenNumber,
346 | 'id' => $token[0],
347 | 'value' => $token[1],
348 | 'line' => $token[2],
349 | 'name' => token_name($token[0])
350 | ),
351 | \ArrayObject::ARRAY_AS_PROPS
352 | );
353 |
354 | if ($isSingle) {
355 | $this->_interestingTokens[$name] = $tokenObj;
356 | } else {
357 | if (!isset($this->_interestingTokens[$name])) {
358 | $this->_interestingTokens[$name] = array();
359 | }
360 | $this->_interestingTokens[$name][] = $tokenObj;
361 | }
362 |
363 | if (!isset($this->_interestingTokenIndex[$tokenNumber])) {
364 | $this->_interestingTokenIndex[$tokenNumber] = array();
365 | }
366 |
367 | $this->_interestingTokenIndex[$tokenNumber][] = $name;
368 | }
369 |
370 | public function __toString()
371 | {
372 | return 'File Contents for: ' . $this->_fileNameProcessor->getOriginalFilePath();
373 | }
374 |
375 |
376 | }
--------------------------------------------------------------------------------