Comparar commits
112 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 6f3cb02964 | |||
| ed35d5e1e0 | |||
| da117f57ef | |||
| e8ce2ebfb4 | |||
| b8159b9c79 | |||
| 7d934c0bc8 | |||
| 3d1329e442 | |||
| b98ee88a3f | |||
| 90987bbc28 | |||
| 9e6d50becb | |||
| 156e6cbd7e | |||
| 73e5d8110b | |||
| a0d96e0824 | |||
| b2296a6f26 | |||
| 058d3aa0f1 | |||
| c038113947 | |||
| 02ac4722b1 | |||
| b66af6da77 | |||
| 6e9179a518 | |||
| a5f806b54a | |||
| c0514d2499 | |||
| 47523ca411 | |||
| 0a80cb904c | |||
| 623eba95f1 | |||
| 4618c35c79 | |||
| a7ff4fd99c | |||
| 2d94cc2e26 | |||
| 77cc6e4631 | |||
| 8517abe185 | |||
| 5f04f28132 | |||
| 1f287d041a | |||
| 54bb7d6201 | |||
| 5b37276a17 | |||
| 3c09f88f4a | |||
| 38512ec204 | |||
| 9b8fbcd90b | |||
| a012e0a41d | |||
| 9b90b2c893 | |||
| a4ba5eb637 | |||
| 010daccdca | |||
| 950b116188 | |||
| bd1ca9b03a | |||
| 2151886f39 | |||
| 6fe620e966 | |||
| 157a655cd4 | |||
| 91b0281b00 | |||
| 2d213e1e4a | |||
| 79fd5762f9 | |||
| 9fb1495599 | |||
| 3ba04ff3a8 | |||
| 9fe39f37e0 | |||
| 9d031fb770 | |||
| b8761c793e | |||
| 72876b0c74 | |||
| 4932ed5b36 | |||
| c3e77b00a4 | |||
| af795101a7 | |||
| a0ae63dbdb | |||
| acf12cead3 | |||
| 143b1a722f | |||
| efc961f804 | |||
| 62b85d379f | |||
| 6de5b1f868 | |||
| 145b0a69de | |||
| f938ae6a0a | |||
| 67460c5e91 | |||
| 0ff1e64bfa | |||
| dfbbb48df2 | |||
| 3e743cb54d | |||
| ba2a53110a | |||
| 5d3041f9f2 | |||
| 5f78d7de67 | |||
| 684f5a39fb | |||
| 99a1b312ee | |||
| c990b4926c | |||
| 8ed05b0134 | |||
| a7fa1f0bcb | |||
| 79c70f2fd9 | |||
| b20d4d39e8 | |||
| e6116881a8 | |||
| 5000e8ab69 | |||
| 9b6f47f2f5 | |||
| e495d95592 | |||
| 7f7c07ddb1 | |||
| ba02370529 | |||
| e9026322ef | |||
| 597d05163c | |||
| 6f8145841a | |||
| 6fa5581ed6 | |||
| 6023d9bb95 | |||
| c69b74bda3 | |||
| 6addfbb5f3 | |||
| f0bfee9092 | |||
| 36a7943ec2 | |||
| c2c6c088ce | |||
| bb6819f493 | |||
| c630d739d4 | |||
| 0bfa39ae25 | |||
| d9375f6f02 | |||
| ec4fb2c274 | |||
| 8e6b2b6d34 | |||
| 10aff89a15 | |||
| 2914cd1430 | |||
| e06a267ac3 | |||
| 581435588d | |||
| ad5649e243 | |||
| 5e2fb75bdf | |||
| 2b5701723e | |||
| 749a0056ea | |||
| 6e9b435b3e | |||
| 56557ab957 | |||
| 381df304ae |
@@ -0,0 +1,30 @@
|
||||
##
|
||||
## Projects
|
||||
##
|
||||
mind3rd/projects/*
|
||||
|
||||
##
|
||||
## PHPDocs
|
||||
##
|
||||
docs/PHPDoc/*
|
||||
docs/PHPDOCS/*
|
||||
|
||||
##
|
||||
## SQLite
|
||||
##
|
||||
mind3rd/SQLite/mind
|
||||
|
||||
##
|
||||
## Temporary files
|
||||
##
|
||||
mind3rd/API/temp/*
|
||||
|
||||
##
|
||||
## Development meta files
|
||||
##
|
||||
*.*~
|
||||
.project
|
||||
.DS_Store
|
||||
./nbproject
|
||||
nbproject
|
||||
nbproject/*
|
||||
@@ -0,0 +1,51 @@
|
||||
TheWebMind
|
||||
===============================================
|
||||
This is the source code for theWebMind project.
|
||||
|
||||
Requirements:
|
||||
---------
|
||||
* PHP 5.3+
|
||||
* PHP-cli
|
||||
* PHP-SQLite
|
||||
|
||||
Installation:
|
||||
-------------
|
||||
For now, only working on mac and Linux...sorry bill!
|
||||
Your HTTPServer's user must have permission to read and write on its folder
|
||||
In your console, run the following command into this directory:
|
||||
$sudo php mind install
|
||||
|
||||
Great! Now you're good to go
|
||||
|
||||
* * *
|
||||
|
||||
Examples and tests:
|
||||
-------------
|
||||
To perform some examples and tests, access in your browser
|
||||
the IDE demo
|
||||
http://[yourMindDir]/docs/ide
|
||||
|
||||
For graphics, diagrams, examples of code, help and documentation, see
|
||||
the docs directory
|
||||
[yourMindDir]/docs/
|
||||
|
||||
Your projects are stored at:
|
||||
[yourMindDir]/projects/[projectName]
|
||||
You can write your codes directly in sources/main.mnd in your
|
||||
project's source directory.
|
||||
You can see the generated documentation and source code on 'docs' and
|
||||
'app' directories, into the project's directory.
|
||||
|
||||
Please, check/change the data and options as you need, on
|
||||
[yourMindDir]/env/defaults.ini
|
||||
|
||||
Unit tests are on Tests directory, run it with PHPUnit
|
||||
[yourMindDir]/Tests
|
||||
|
||||
Useful/interesting links:
|
||||
[Official website](http://thewebmind.org "theWebMind") |
|
||||
[Licenses](https://github.com/felipenmoura/theWebMind/blob/master/licenses/mind3rd.license, "Licenses") |
|
||||
[Documentation](http://docs.thewebmind.org "documentation") |
|
||||
[Contact](mailto:contact@thewebmind.org "contact") |
|
||||
[Twitter](http://twitter.com/thewebmind "twitter") |
|
||||
[Contribute](http://thewebmind.org/contribute "Contribute")
|
||||
@@ -0,0 +1,6 @@
|
||||
mind3rd/API/languages/en/IgnoreFormsTest.php en\IgnoreFormsTest
|
||||
mind3rd/API/languages/en/InflectTest.php en\InflectTest
|
||||
mind3rd/API/languages/en/VerbalizerTest.php en\VerbalizerTest
|
||||
mind3rd/API/languages/pt/IgnoreFormsTest.php pt\IgnoreFormsTest
|
||||
mind3rd/API/languages/pt/InflectTest.php pt\InflectTest
|
||||
mind3rd/API/languages/pt/VerbalizerTest.php pt\VerbalizerTest
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
require_once dirname(__FILE__) . '/../mind3rd/API/classes/Mind.php';
|
||||
require_once dirname(__FILE__) . '/../mind3rd/API/classes/MindSpeaker.php';
|
||||
require_once dirname(__FILE__) . '/../mind3rd/API/cortex/Darwin/Darwin.php';
|
||||
require_once dirname(__FILE__) . '/../mind3rd/API/cortex/Lexer/Lexer.php';
|
||||
require_once dirname(__FILE__) . '/../mind3rd/API/cortex/canonic/Canonic.php';
|
||||
require_once dirname(__FILE__) . '/../mind3rd/API/cortex/syntaxer/Syntaxer.php';
|
||||
|
||||
require_once dirname(__FILE__) . '/../mind3rd/API/classes/MindEntity.php';
|
||||
require_once dirname(__FILE__) . '/../mind3rd/API/utils/constants.php';
|
||||
require_once dirname(__FILE__) . '/../mind3rd/API/classes/VersionManager.php';
|
||||
require_once dirname(__FILE__) . '/../mind3rd/API/classes/MindProject.php';
|
||||
require_once dirname(__FILE__) . '/../mind3rd/API/classes/MindRelation.php';
|
||||
require_once dirname(__FILE__) . '/../mind3rd/API/classes/MindEntity.php';
|
||||
require_once dirname(__FILE__) . '/../mind3rd/API/classes/MindProperty.php';
|
||||
|
||||
require_once dirname(__FILE__) . '/../mind3rd/API/cortex/analyst/Normal.php';
|
||||
require_once dirname(__FILE__) . '/../mind3rd/API/cortex/analyst/Analysis.php';
|
||||
require_once dirname(__FILE__) . '/../mind3rd/API/cortex/analyst/Normalizer.php';
|
||||
require_once dirname(__FILE__) . '/../mind3rd/API/cortex/analyst/Analyst.php';
|
||||
require_once dirname(__FILE__) . '/../mind3rd/API/cortex/tokenizer/Token.php';
|
||||
require_once dirname(__FILE__) . '/../mind3rd/API/cortex/tokenizer/Tokenizer.php';
|
||||
|
||||
if(!class_exists('MindForUnitTest'))
|
||||
{
|
||||
class MindForUnitTest
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->defaults= Array(
|
||||
'pk_prefix'=>'pk_',
|
||||
'fk_prefix'=>'fk_'
|
||||
);
|
||||
}
|
||||
}
|
||||
$_MIND= new MindForUnitTest();
|
||||
}
|
||||
|
||||
/*if(!defined('_MINDSRC_'))
|
||||
define('_MINDSRC_', dirname(__FILE__).'/..');
|
||||
if(!defined('_CONSOLE_LINE_LENGTH_'))
|
||||
define('_CONSOLE_LINE_LENGTH_', 80);
|
||||
$_MIND= new Mind();*/
|
||||
@@ -0,0 +1,181 @@
|
||||
<?php
|
||||
require(dirname(__FILE__) . '/../../../../../Tests/config.php');
|
||||
|
||||
/**
|
||||
* Test class for Analyst.
|
||||
* Generated by PHPUnit on 2011-02-21 at 01:40:36.
|
||||
*/
|
||||
class AnalystPtTest extends PHPUnit_Framework_TestCase {
|
||||
|
||||
/**
|
||||
* @var Analyst
|
||||
*/
|
||||
protected $object;
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp() {
|
||||
// you gotta set the idiom simply to start some required variables
|
||||
// once these tests wont use the idiom as a key subject
|
||||
MindProject::loadIdiom('en');
|
||||
Mind::$langPath= dirname(__FILE__) . '/../../../../../mind3rd/API/languages/en/';
|
||||
Mind::$lexer= new Lexer();
|
||||
$this->object = new Analyst;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called afhas a test is executed.
|
||||
*/
|
||||
protected function tearDown() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* the used words doesn't metter here, the main spine is the keys group,
|
||||
* so, it doesn't metter what language is set
|
||||
*/
|
||||
public function testAnalize1() {
|
||||
$this->assertEquals($this->object->analize(
|
||||
Array
|
||||
('teacher', '', 'has', '', '', '', 'student'),
|
||||
'SQVNONS',
|
||||
Array
|
||||
(2, 128, 1, 8, 16, 32, 2)),
|
||||
Array('min'=>1,
|
||||
'max'=>'n',
|
||||
'linkType'=>'possibility',
|
||||
'linkVerb'=>'has',
|
||||
'rel'=>'student',
|
||||
'focus'=>'teacher'));
|
||||
}
|
||||
public function testAnalize2() {
|
||||
$this->assertEquals($this->object->analize(
|
||||
Array
|
||||
('teacher', '', 'has', '', '', '', 'student'),
|
||||
'SQVNONS',
|
||||
Array
|
||||
(2, 64, 1, 8, 16, 32, 2)),
|
||||
Array('min'=>1,
|
||||
'max'=>'n',
|
||||
'linkType'=>'must',
|
||||
'linkVerb'=>'has',
|
||||
'rel'=>'student',
|
||||
'focus'=>'teacher'));
|
||||
}
|
||||
public function testAnalize3() {
|
||||
$this->assertEquals($this->object->analize(
|
||||
Array
|
||||
('teacher', '', 'have', '', '', '', 'student'),
|
||||
'SQVNONS',
|
||||
Array
|
||||
(2, 128, 1, 4, 16, 8, 2)),
|
||||
Array('min'=>0,
|
||||
'max'=>1,
|
||||
'linkType'=>'possibility',
|
||||
'linkVerb'=>'have',
|
||||
'rel'=>'student',
|
||||
'focus'=>'teacher'));
|
||||
}
|
||||
public function testAnalize4() {
|
||||
$this->assertEquals($this->object->analize(
|
||||
Array
|
||||
('teacher', 'have', '', '', '', 'student'),
|
||||
'SQVNONS',
|
||||
Array
|
||||
(2, 1, 4, 16, 8, 2)),
|
||||
Array('min'=>0,
|
||||
'max'=>1,
|
||||
'linkType'=>'action',
|
||||
'linkVerb'=>'have',
|
||||
'rel'=>'student',
|
||||
'focus'=>'teacher'));
|
||||
}
|
||||
public function testAnalize5() {
|
||||
$this->assertEquals($this->object->analize(
|
||||
Array
|
||||
('teacher', 'has', '', '', '', 'student'),
|
||||
'SQVNONS',
|
||||
Array
|
||||
(2, 1, 8, 16, 32, 2)),
|
||||
Array('min'=>1,
|
||||
'max'=>'n',
|
||||
'linkType'=>'action',
|
||||
'linkVerb'=>'has',
|
||||
'rel'=>'student',
|
||||
'focus'=>'teacher'));
|
||||
}
|
||||
public function testAnalize6() {
|
||||
$this->assertEquals($this->object->analize(
|
||||
Array
|
||||
('teachera', 'has', '', '', '', 'aluna'),
|
||||
'SQVNONS',
|
||||
Array
|
||||
(2, 1, 4, 16, 32, 2)),
|
||||
Array('min'=>0,
|
||||
'max'=>'n',
|
||||
'linkType'=>'action',
|
||||
'linkVerb'=>'has',
|
||||
'rel'=>'aluna',
|
||||
'focus'=>'teachera'));
|
||||
}
|
||||
public function testAnalize7() {
|
||||
$this->assertEquals($this->object->analize(
|
||||
Array
|
||||
('teacher', 'has', '', 'student'),
|
||||
'SQVNONS',
|
||||
Array
|
||||
(2, 1, 32, 2)),
|
||||
Array('min'=>0,
|
||||
'max'=>'n',
|
||||
'linkType'=>'action',
|
||||
'linkVerb'=>'has',
|
||||
'rel'=>'student',
|
||||
'focus'=>'teacher'));
|
||||
}
|
||||
public function testAnalize8() {
|
||||
$this->assertEquals($this->object->analize(
|
||||
Array
|
||||
('teacher', 'has', '', 'student'),
|
||||
'SQVNONS',
|
||||
Array
|
||||
(2, 1, 8, 2)),
|
||||
Array('min'=>0,
|
||||
'max'=>1,
|
||||
'linkType'=>'action',
|
||||
'linkVerb'=>'has',
|
||||
'rel'=>'student',
|
||||
'focus'=>'teacher'));
|
||||
}
|
||||
public function testAnalize9() {
|
||||
$this->assertEquals($this->object->analize(
|
||||
Array
|
||||
('teacher', '', 'has', '', 'student'),
|
||||
'SQVNONS',
|
||||
Array
|
||||
(2, 64, 1, 8, 2)),
|
||||
Array('min'=>1,
|
||||
'max'=>1,
|
||||
'linkType'=>'must',
|
||||
'linkVerb'=>'has',
|
||||
'rel'=>'student',
|
||||
'focus'=>'teacher'));
|
||||
}
|
||||
public function testAnalize10() {
|
||||
$this->assertEquals($this->object->analize(
|
||||
Array
|
||||
('teacher', '', 'has', '', 'student'),
|
||||
'SQVNONS',
|
||||
Array
|
||||
(2, 128, 1, 32, 2)),
|
||||
Array('min'=>0,
|
||||
'max'=>'n',
|
||||
'linkType'=>'possibility',
|
||||
'linkVerb'=>'has',
|
||||
'rel'=>'student',
|
||||
'focus'=>'teacher'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,220 @@
|
||||
<?php
|
||||
|
||||
require_once dirname(__FILE__) . '/../../../../../Tests/config.php';
|
||||
|
||||
/**
|
||||
* Test class for Syntaxer.
|
||||
* Generated by PHPUnit on 2011-02-25 at 09:21:58.
|
||||
*/
|
||||
class SyntaxerTest extends PHPUnit_Framework_TestCase {
|
||||
|
||||
/**
|
||||
* @var Syntaxer
|
||||
*/
|
||||
public $object;
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->setIdiom();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown() {
|
||||
}
|
||||
|
||||
public function setIdiom($idiom='en')
|
||||
{
|
||||
Mind::$currentProject['idiom']= $idiom;
|
||||
Mind::$langPath= dirname(__FILE__) . '/../../../../../mind3rd/API/languages/';
|
||||
require_once dirname(__FILE__) . '/../../../../../mind3rd/API/languages/'.$idiom.'/IgnoreForms.php';
|
||||
require_once dirname(__FILE__) . '/../../../../../mind3rd/API/languages/'.$idiom.'/Verbalizer.php';
|
||||
Tokenizer::loadModifiers(dirname(__FILE__) . '/../../../../../mind3rd/API/languages/'.$idiom.'/');
|
||||
Mind::$tokenizer= new Tokenizer;
|
||||
Mind::$lexer= new Lexer;
|
||||
$this->object = new Syntaxer();
|
||||
}
|
||||
|
||||
public function testSweepWords1() {
|
||||
$this->setIdiom();
|
||||
Mind::$tokenizer->sweep(Array('child', 'of', 'heart', 'has', 'parent', 'of', 'family'));
|
||||
|
||||
$this->object->sweep();
|
||||
|
||||
$this->assertEquals(Tokenizer::$words,
|
||||
Array(
|
||||
'child_heart',
|
||||
'has',
|
||||
'parent_family',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function testSweepWords2() {
|
||||
Mind::$tokenizer->sweep(Array('child',
|
||||
'of',
|
||||
'heart',
|
||||
'and',
|
||||
'friend',
|
||||
'of',
|
||||
'child',
|
||||
'of',
|
||||
'heart',
|
||||
'has',
|
||||
'parent',
|
||||
'of',
|
||||
'family'));
|
||||
$this->object->sweep();
|
||||
$this->assertEquals(Tokenizer::$words,
|
||||
Array(
|
||||
'child_heart',
|
||||
',',
|
||||
'friend_child_heart',
|
||||
'has',
|
||||
'parent_family'
|
||||
)
|
||||
);
|
||||
}
|
||||
public function testSweepWords3() {
|
||||
Mind::$tokenizer->sweep(Array('child',
|
||||
'of',
|
||||
'heart',
|
||||
',',
|
||||
'friend',
|
||||
'of',
|
||||
'kid',
|
||||
'of',
|
||||
'heart',
|
||||
'has',
|
||||
'parent',
|
||||
'of',
|
||||
'family'));
|
||||
$this->object->sweep();
|
||||
$this->assertEquals(Tokenizer::$words,
|
||||
Array(
|
||||
'child_heart',
|
||||
',',
|
||||
'friend_kid_heart',
|
||||
'has',
|
||||
'parent_family'
|
||||
)
|
||||
);
|
||||
}
|
||||
public function testSweepWords4() {
|
||||
Mind::$tokenizer->sweep(Array('child',
|
||||
'of',
|
||||
'heart',
|
||||
',',
|
||||
'friend',
|
||||
'of',
|
||||
'kid',
|
||||
'of',
|
||||
'heart',
|
||||
'has',
|
||||
'parent',
|
||||
'of',
|
||||
'family',
|
||||
',',
|
||||
'mother',
|
||||
'of',
|
||||
'parent'));
|
||||
$this->object->sweep();
|
||||
$this->assertEquals(Tokenizer::$words,
|
||||
Array(
|
||||
'child_heart',
|
||||
',',
|
||||
'friend_kid_heart',
|
||||
'has',
|
||||
'parent_family',
|
||||
',',
|
||||
'mother_parent'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function testSweepWords5() {
|
||||
Mind::$tokenizer->sweep(Array('child',
|
||||
'has',
|
||||
'parent'
|
||||
));
|
||||
$this->object->sweep();
|
||||
$this->assertEquals(Tokenizer::$words,
|
||||
Array(
|
||||
'child',
|
||||
'has',
|
||||
'parent'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public function testSweepWords6() {
|
||||
Mind::$tokenizer->sweep(Array('child',
|
||||
'of',
|
||||
'heart',
|
||||
',',
|
||||
'friend',
|
||||
'of',
|
||||
'kid',
|
||||
'of',
|
||||
'heart',
|
||||
'has',
|
||||
'name of origin:varchar(250)',
|
||||
',',
|
||||
'age:int'));
|
||||
$this->object->sweep();
|
||||
$this->assertEquals(Tokenizer::$words,
|
||||
Array(
|
||||
'child_heart',
|
||||
',',
|
||||
'friend_kid_heart',
|
||||
'has',
|
||||
'name of origin:varchar(250)',
|
||||
',',
|
||||
'age:int'
|
||||
)
|
||||
);
|
||||
}
|
||||
public function testSweepWords7() {
|
||||
Mind::$tokenizer->sweep(Array('child',
|
||||
',',
|
||||
'friend',
|
||||
'has',
|
||||
'name of origin:varchar(250)',
|
||||
',',
|
||||
'age:int'));
|
||||
$this->object->sweep();
|
||||
$this->assertEquals(Tokenizer::$words,
|
||||
Array(
|
||||
'child',
|
||||
',',
|
||||
'friend',
|
||||
'has',
|
||||
'name of origin:varchar(250)',
|
||||
',',
|
||||
'age:int'
|
||||
)
|
||||
);
|
||||
}
|
||||
public function testSweepWords8() {
|
||||
Mind::$tokenizer->sweep(Array('child',
|
||||
'has',
|
||||
'name of origin:varchar(250)',
|
||||
',',
|
||||
'age:int'));
|
||||
$this->object->sweep();
|
||||
$this->assertEquals(Tokenizer::$words,
|
||||
Array(
|
||||
'child',
|
||||
'has',
|
||||
'name of origin:varchar(250)',
|
||||
',',
|
||||
'age:int'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
require(dirname(__FILE__) . '/../../../../../Tests/config.php');
|
||||
|
||||
/**
|
||||
* Test class for Tokenizer.
|
||||
* Generated by PHPUnit on 2011-02-21 at 11:46:35.
|
||||
*/
|
||||
class TokenizerTest extends PHPUnit_Framework_TestCase {
|
||||
|
||||
/**
|
||||
* @var Tokenizer
|
||||
*/
|
||||
protected $object;
|
||||
|
||||
protected $idiom= 'en';
|
||||
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->setIdiom();
|
||||
}
|
||||
|
||||
public function setIdiom($idiom='en')
|
||||
{
|
||||
Mind::$currentProject['idiom']= $idiom;
|
||||
Mind::$langPath= dirname(__FILE__) . '/../../../../../mind3rd/API/languages/';
|
||||
require_once dirname(__FILE__) . '/../../../../../mind3rd/API/languages/'.$idiom.'/IgnoreForms.php';
|
||||
require_once dirname(__FILE__) . '/../../../../../mind3rd/API/languages/'.$idiom.'/Verbalizer.php';
|
||||
Tokenizer::loadModifiers(dirname(__FILE__) . '/../../../../../mind3rd/API/languages/'.$idiom.'/');
|
||||
$this->object = new Tokenizer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown() {
|
||||
|
||||
}
|
||||
|
||||
// these are the tests in Portuguese, that's why we're setting
|
||||
// the idiom to PT in the first line on each test
|
||||
public function testSweep1() {
|
||||
$this->setIdiom('pt');
|
||||
$ar= Array('cada','professor','dever', 'ter', 'um','ou','muitos','aluno','.');
|
||||
$exp= Array(-4, 2, 64, 1, 8, 16, 32, 2, -2);
|
||||
$this->assertEquals($this->object->sweep($ar), $exp);
|
||||
}
|
||||
public function testSweep2() {
|
||||
$this->setIdiom('pt');
|
||||
$ar= Array('professor', 'ter', 'um','aluno','.');
|
||||
$exp= Array(2, 1, 8, 2, -2);
|
||||
$this->assertEquals($this->object->sweep($ar), $exp);
|
||||
}
|
||||
public function testSweep3() {
|
||||
$this->setIdiom('pt');
|
||||
$ar= Array('professor', 'poder', 'ter', 'um','aluno','.');
|
||||
$exp= Array(2, 128, 1, 8, 2, -2);
|
||||
$this->assertEquals($exp, $this->object->sweep($ar));
|
||||
}
|
||||
public function testSweep4() {
|
||||
$this->setIdiom('pt');
|
||||
$ar= Array('professor', 'poder', 'ter', 'um', 'ou', 'muitos','aluno','.');
|
||||
$exp= Array(2, Token::MT_QMAY, 1, 8, Token::MT_OR, Token::MT_MANY, 2, -2);
|
||||
$this->assertEquals($this->object->sweep($ar), $exp);
|
||||
}
|
||||
public function testSweep5() {
|
||||
$this->setIdiom('pt');
|
||||
$ar= Array('cada','professor','dever', 'ter', 'muitos','aluno','.');
|
||||
$exp= Array(-4, 2, 64, 1, 32, 2, -2);
|
||||
$this->assertEquals($this->object->sweep($ar), $exp);
|
||||
}
|
||||
|
||||
// here are the tests in english
|
||||
public function testSweep6() {
|
||||
$ar= Array('each','teacher','must', 'have', 'one','or','many','student','.');
|
||||
$exp= Array(-4, 2, 64, 1, 8, 16, 32, 2, -2);
|
||||
$this->assertEquals($this->object->sweep($ar), $exp);
|
||||
}
|
||||
public function testSweep7() {
|
||||
$ar= Array('teacher', 'have', 'one','student','.');
|
||||
$exp= Array(2, 1, 8, 2, -2);
|
||||
$this->assertEquals($this->object->sweep($ar), $exp);
|
||||
}
|
||||
public function testSweep8() {
|
||||
$ar= Array('teacher', 'may', 'have', 'one','student','.');
|
||||
$exp= Array(2, Token::MT_QMAY, 1, 8, 2, -2);
|
||||
$this->assertEquals($this->object->sweep($ar), $exp);
|
||||
}
|
||||
public function testSweep9() {
|
||||
$ar= Array('teacher', 'must', 'have', 'one','student','.');
|
||||
$exp= Array(2, Token::MT_QMUST, 1, 8, 2, -2);
|
||||
$this->assertEquals($this->object->sweep($ar), $exp);
|
||||
}
|
||||
public function testSweep10() {
|
||||
$ar= Array('each','teacher','may', 'have', 'one','or','many','student','.');
|
||||
$exp= Array(-4, 2, Token::MT_QMAY, 1, 8, 16, 32, 2, -2);
|
||||
$this->assertEquals($this->object->sweep($ar), $exp);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace en;
|
||||
|
||||
require_once dirname(__FILE__) . '/../../../../../mind3rd/API/languages/en/IgnoreForms.php';
|
||||
|
||||
/**
|
||||
* Test class for IgnoreForms.
|
||||
* Generated by PHPUnit on 2011-02-08 at 21:47:15.
|
||||
*/
|
||||
class IgnoreFormsTest extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
/**
|
||||
* @var IgnoreForms
|
||||
*/
|
||||
protected $object;
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->object = new IgnoreForms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown() {
|
||||
|
||||
}
|
||||
|
||||
public function testShouldBeIgnored() {
|
||||
$this->assertTrue(IgnoreForms::shouldBeIgnored('whom'));
|
||||
}
|
||||
|
||||
public function testShouldBeIgnored2() {
|
||||
$this->assertTrue(IgnoreForms::shouldBeIgnored('well'));
|
||||
}
|
||||
|
||||
public function testShouldBeIgnored3() {
|
||||
$this->assertTrue(IgnoreForms::shouldBeIgnored('monthly'));
|
||||
}
|
||||
|
||||
public function testShouldBeIgnored4() {
|
||||
$this->assertTrue(IgnoreForms::shouldBeIgnored('currently'));
|
||||
}
|
||||
|
||||
public function testShouldBeUsed() {
|
||||
$this->assertTrue(IgnoreForms::shouldBeUsed('year'));
|
||||
}
|
||||
public function testShouldBeUsed2() {
|
||||
$this->assertTrue(IgnoreForms::shouldBeUsed('month'));
|
||||
}
|
||||
public function testShouldBeUsed3() {
|
||||
$this->assertTrue(IgnoreForms::shouldBeUsed('now'));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
namespace en;
|
||||
|
||||
require_once dirname(__FILE__) . '/../../../../../mind3rd/API/interfaces/inflection.php';
|
||||
require_once dirname(__FILE__) . '/../../../../../mind3rd/API/languages/en/Inflect.php';
|
||||
|
||||
/**
|
||||
* Test class for Inflect.
|
||||
* Generated by PHPUnit on 2010-11-06 at 23:55:39.
|
||||
*/
|
||||
class InflectTest extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
/**
|
||||
* @var Inflect
|
||||
*/
|
||||
protected $object;
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->object = new Inflect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown() {
|
||||
|
||||
}
|
||||
|
||||
public function testisSingular() {
|
||||
$this->assertTrue(Inflect::isSingular('man'));
|
||||
}
|
||||
|
||||
public function testisSingular2() {
|
||||
$this->assertFalse(Inflect::isSingular('men'));
|
||||
}
|
||||
public function testisSingular3() {
|
||||
$this->assertTrue(Inflect::isSingular('car'));
|
||||
}
|
||||
public function testisSingular4() {
|
||||
$this->assertFalse(Inflect::isSingular('houses'));
|
||||
}
|
||||
public function testisSingular5() {
|
||||
$this->assertFalse(Inflect::isSingular('mice'));
|
||||
}
|
||||
public function testisSingular6() {
|
||||
$this->assertTrue(Inflect::isSingular('train'));
|
||||
}
|
||||
public function testisSingular7() {
|
||||
$this->assertTrue(Inflect::isSingular('kid'));
|
||||
}
|
||||
public function testisSingular8() {
|
||||
$this->assertFalse(Inflect::isSingular('children'));
|
||||
}
|
||||
public function testisSingular9() {
|
||||
$this->assertFalse(Inflect::isSingular('penalties'));
|
||||
}
|
||||
public function testisSingular10() {
|
||||
$this->assertTrue(Inflect::isSingular('penalty'));
|
||||
}
|
||||
|
||||
public function testToPlural() {
|
||||
$this->assertEquals(Inflect::toPlural('man'), 'men');
|
||||
}
|
||||
public function testToPlural1() {
|
||||
$this->assertEquals(Inflect::toPlural('person'), 'people');
|
||||
}
|
||||
public function testToPlural2() {
|
||||
$this->assertEquals(Inflect::toPlural('hotel'), 'hotels');
|
||||
}
|
||||
public function testToPlural3() {
|
||||
$this->assertEquals(Inflect::toPlural('wolf'), 'wolves');
|
||||
}
|
||||
public function testToPlural4() {
|
||||
$this->assertEquals(Inflect::toPlural('motor'), 'motors');
|
||||
}
|
||||
public function testToPlural5() {
|
||||
$this->assertEquals(Inflect::toPlural('robot'), 'robots');
|
||||
}
|
||||
public function testToPlural6() {
|
||||
$this->assertEquals(Inflect::toPlural('penalty'), 'penalties');
|
||||
}
|
||||
|
||||
public function testToSingular() {
|
||||
$this->assertEquals(Inflect::toSingular('women'), 'woman');
|
||||
}
|
||||
public function testToSingular1() {
|
||||
$this->assertEquals(Inflect::toSingular('fishes'), 'fish');
|
||||
}
|
||||
public function testToSingular2() {
|
||||
$this->assertEquals(Inflect::toSingular('barrels'), 'barrel');
|
||||
}
|
||||
public function testToSingular3() {
|
||||
$this->assertEquals(Inflect::toSingular('trains'), 'train');
|
||||
}
|
||||
public function testToSingular4() {
|
||||
$this->assertEquals(Inflect::toSingular('notebooks'), 'notebook');
|
||||
}
|
||||
public function testToSingular5() {
|
||||
$this->assertEquals(Inflect::toSingular('penalties'), 'penalty');
|
||||
}
|
||||
/*public function testToSingular6() {
|
||||
$this->assertEquals(Inflect::toPlural('nerves'), 'nerve');
|
||||
}*/
|
||||
public function testToSingular7() {
|
||||
$this->assertEquals(Inflect::toSingular('nurses'), 'nurse');
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace en;
|
||||
|
||||
require_once dirname(__FILE__) . '/../../../../../mind3rd/API/languages/en/Verbalizer.php';
|
||||
|
||||
/**
|
||||
* Test class for Verbalizer.
|
||||
* Generated by PHPUnit on 2011-02-08 at 21:48:10.
|
||||
*/
|
||||
class VerbalizerTest extends \PHPUnit_Framework_TestCase {
|
||||
|
||||
/**
|
||||
* @var Verbalizer
|
||||
*/
|
||||
protected $object;
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->object = new Verbalizer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown() {
|
||||
|
||||
}
|
||||
|
||||
public function testIsVerb() {
|
||||
$this->assertTrue(Verbalizer::isVerb('run'));
|
||||
}
|
||||
public function testIsVerb2() {
|
||||
$this->assertTrue(Verbalizer::isVerb('runs'));
|
||||
}
|
||||
public function testIsVerb3() {
|
||||
$this->assertTrue(Verbalizer::isVerb('may'));
|
||||
}
|
||||
public function testIsVerb4() {
|
||||
$this->assertTrue(Verbalizer::isVerb('has'));
|
||||
}
|
||||
public function testIsVerb5() {
|
||||
$this->assertTrue(Verbalizer::isVerb('matches'));
|
||||
}
|
||||
public function testIsVerb6() {
|
||||
$this->assertTrue(Verbalizer::isVerb('take'));
|
||||
}
|
||||
public function testIsVerb7() {
|
||||
$this->assertTrue(Verbalizer::isVerb('have'));
|
||||
}
|
||||
public function testIsVerb8() {
|
||||
$this->assertTrue(Verbalizer::isVerb('can'));
|
||||
}
|
||||
public function testIsVerb9() {
|
||||
$this->assertTrue(Verbalizer::isVerb('brushes'));
|
||||
}
|
||||
public function testIsVerb10() {
|
||||
$this->assertTrue(Verbalizer::isVerb('teaches'));
|
||||
}
|
||||
|
||||
public function testToInfinitive() {
|
||||
$this->assertEquals(Verbalizer::toInfinitive('runs'), 'run');
|
||||
}
|
||||
public function testToInfinitive2() {
|
||||
$this->assertEquals(Verbalizer::toInfinitive('matches'), 'match');
|
||||
}
|
||||
public function testToInfinitive3() {
|
||||
$this->assertEquals(Verbalizer::toInfinitive('runs'), 'run');
|
||||
}
|
||||
public function testToInfinitive4() {
|
||||
$this->assertEquals(Verbalizer::toInfinitive('runs'), 'run');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
the
|
||||
at
|
||||
that
|
||||
which
|
||||
whom
|
||||
whose
|
||||
well
|
||||
too
|
||||
another
|
||||
also
|
||||
@@ -0,0 +1,6 @@
|
||||
SVS
|
||||
SQVS
|
||||
SVNONS
|
||||
SVNS
|
||||
SQVNONS
|
||||
SQVNS
|
||||
@@ -0,0 +1,730 @@
|
||||
is
|
||||
are
|
||||
set
|
||||
accept
|
||||
add
|
||||
admire
|
||||
admit
|
||||
advise
|
||||
afford
|
||||
agree
|
||||
alert
|
||||
allow
|
||||
amuse
|
||||
analyse
|
||||
announce
|
||||
annoy
|
||||
answer
|
||||
apologise
|
||||
appear
|
||||
applaud
|
||||
appreciate
|
||||
approve
|
||||
argue
|
||||
arrange
|
||||
arrest
|
||||
arrive
|
||||
ask
|
||||
attach
|
||||
attack
|
||||
attempt
|
||||
attend
|
||||
attract
|
||||
avoid
|
||||
|
||||
back
|
||||
bake
|
||||
balance
|
||||
ban
|
||||
bang
|
||||
bare
|
||||
bat
|
||||
bathe
|
||||
battle
|
||||
beam
|
||||
beg
|
||||
behave
|
||||
belong
|
||||
bleach
|
||||
bless
|
||||
blind
|
||||
blink
|
||||
blot
|
||||
blush
|
||||
boast
|
||||
boil
|
||||
bolt
|
||||
bomb
|
||||
book
|
||||
bore
|
||||
borrow
|
||||
bounce
|
||||
bow
|
||||
box
|
||||
brake
|
||||
brake
|
||||
branch
|
||||
breathe
|
||||
bruise
|
||||
brush
|
||||
bubble
|
||||
bump
|
||||
burn
|
||||
bury
|
||||
buzz
|
||||
calculate
|
||||
call
|
||||
camp
|
||||
care
|
||||
carry
|
||||
carve
|
||||
cause
|
||||
challenge
|
||||
change
|
||||
charge
|
||||
chase
|
||||
cheat
|
||||
check
|
||||
cheer
|
||||
chew
|
||||
choke
|
||||
chop
|
||||
claim
|
||||
clap
|
||||
clean
|
||||
clear
|
||||
clip
|
||||
close
|
||||
coach
|
||||
coil
|
||||
collect
|
||||
colour
|
||||
comb
|
||||
command
|
||||
communicate
|
||||
compare
|
||||
compete
|
||||
complain
|
||||
complete
|
||||
concentrate
|
||||
concern
|
||||
confess
|
||||
confuse
|
||||
connect
|
||||
consider
|
||||
consist
|
||||
contain
|
||||
continue
|
||||
copy
|
||||
correct
|
||||
cough
|
||||
count
|
||||
cover
|
||||
crack
|
||||
crash
|
||||
crawl
|
||||
cross
|
||||
crush
|
||||
cry
|
||||
cure
|
||||
curl
|
||||
curve
|
||||
cycle
|
||||
dam
|
||||
damage
|
||||
dance
|
||||
dare
|
||||
decay
|
||||
deceive
|
||||
decide
|
||||
decorate
|
||||
delay
|
||||
delight
|
||||
deliver
|
||||
depend
|
||||
describe
|
||||
desert
|
||||
deserve
|
||||
destroy
|
||||
detect
|
||||
develop
|
||||
disagree
|
||||
disappear
|
||||
disapprove
|
||||
disarm
|
||||
discover
|
||||
dislike
|
||||
divide
|
||||
double
|
||||
doubt
|
||||
drag
|
||||
drain
|
||||
dream
|
||||
dress
|
||||
drip
|
||||
drop
|
||||
drown
|
||||
drum
|
||||
dry
|
||||
dust
|
||||
earn
|
||||
educate
|
||||
embarrass
|
||||
employ
|
||||
empty
|
||||
encourage
|
||||
end
|
||||
enjoy
|
||||
enter
|
||||
entertain
|
||||
escape
|
||||
examine
|
||||
excite
|
||||
excuse
|
||||
exercise
|
||||
exist
|
||||
expand
|
||||
expect
|
||||
explain
|
||||
explode
|
||||
extend
|
||||
face
|
||||
fade
|
||||
fail
|
||||
fancy
|
||||
fasten
|
||||
fax
|
||||
fear
|
||||
fence
|
||||
fetch
|
||||
file
|
||||
fill
|
||||
film
|
||||
fire
|
||||
fit
|
||||
fix
|
||||
flap
|
||||
flash
|
||||
float
|
||||
flood
|
||||
flow
|
||||
flower
|
||||
fold
|
||||
follow
|
||||
fool
|
||||
force
|
||||
form
|
||||
found
|
||||
frame
|
||||
frighten
|
||||
fry
|
||||
gather
|
||||
gaze
|
||||
glow
|
||||
glue
|
||||
grab
|
||||
grate
|
||||
grease
|
||||
greet
|
||||
grin
|
||||
grip
|
||||
groan
|
||||
guarantee
|
||||
guard
|
||||
guess
|
||||
guide
|
||||
hammer
|
||||
hand
|
||||
handle
|
||||
hang
|
||||
happen
|
||||
harass
|
||||
harm
|
||||
hate
|
||||
haunt
|
||||
head
|
||||
heal
|
||||
heap
|
||||
heat
|
||||
help
|
||||
hook
|
||||
hop
|
||||
hope
|
||||
hover
|
||||
hug
|
||||
hum
|
||||
hunt
|
||||
hurry
|
||||
identify
|
||||
ignore
|
||||
imagine
|
||||
impress
|
||||
improve
|
||||
include
|
||||
increase
|
||||
influence
|
||||
inform
|
||||
inject
|
||||
injure
|
||||
instruct
|
||||
intend
|
||||
interest
|
||||
interfere
|
||||
interrupt
|
||||
introduce
|
||||
invent
|
||||
invite
|
||||
irritate
|
||||
itch
|
||||
jail
|
||||
jam
|
||||
jog
|
||||
join
|
||||
joke
|
||||
judge
|
||||
juggle
|
||||
jump
|
||||
kick
|
||||
kill
|
||||
kiss
|
||||
kneel
|
||||
knit
|
||||
knock
|
||||
knot
|
||||
label
|
||||
land
|
||||
last
|
||||
laugh
|
||||
launch
|
||||
learn
|
||||
level
|
||||
license
|
||||
lick
|
||||
lie
|
||||
lighten
|
||||
like
|
||||
list
|
||||
listen
|
||||
live
|
||||
load
|
||||
lock
|
||||
long
|
||||
look
|
||||
love
|
||||
man
|
||||
manage
|
||||
march
|
||||
mark
|
||||
marry
|
||||
match
|
||||
mate
|
||||
matter
|
||||
measure
|
||||
meddle
|
||||
melt
|
||||
memorise
|
||||
mend
|
||||
messup
|
||||
milk
|
||||
mine
|
||||
miss
|
||||
mix
|
||||
moan
|
||||
moor
|
||||
mourn
|
||||
move
|
||||
muddle
|
||||
mug
|
||||
multiply
|
||||
murder
|
||||
nail
|
||||
name
|
||||
need
|
||||
nest
|
||||
nod
|
||||
note
|
||||
notice
|
||||
number
|
||||
obey
|
||||
object
|
||||
observe
|
||||
obtain
|
||||
occur
|
||||
offend
|
||||
offer
|
||||
open
|
||||
order
|
||||
overflow
|
||||
owe
|
||||
own
|
||||
pack
|
||||
paddle
|
||||
paint
|
||||
park
|
||||
part
|
||||
pass
|
||||
paste
|
||||
pat
|
||||
pause
|
||||
peck
|
||||
pedal
|
||||
peel
|
||||
peep
|
||||
perform
|
||||
permit
|
||||
phone
|
||||
pick
|
||||
pinch
|
||||
pine
|
||||
place
|
||||
plan
|
||||
plant
|
||||
play
|
||||
please
|
||||
plug
|
||||
point
|
||||
poke
|
||||
polish
|
||||
pop
|
||||
possess
|
||||
post
|
||||
pour
|
||||
practise
|
||||
pray
|
||||
preach
|
||||
precede
|
||||
prefer
|
||||
prepare
|
||||
present
|
||||
preserve
|
||||
press
|
||||
pretend
|
||||
prevent
|
||||
prick
|
||||
print
|
||||
produce
|
||||
program
|
||||
promise
|
||||
protect
|
||||
provide
|
||||
pull
|
||||
pump
|
||||
punch
|
||||
puncture
|
||||
punish
|
||||
push
|
||||
question
|
||||
queue
|
||||
race
|
||||
radiate
|
||||
rain
|
||||
raise
|
||||
reach
|
||||
realise
|
||||
receive
|
||||
recognise
|
||||
record
|
||||
reduce
|
||||
reflect
|
||||
refuse
|
||||
regret
|
||||
reign
|
||||
reject
|
||||
rejoice
|
||||
relax
|
||||
release
|
||||
rely
|
||||
remain
|
||||
remember
|
||||
remind
|
||||
remove
|
||||
repair
|
||||
repeat
|
||||
replace
|
||||
reply
|
||||
report
|
||||
reproduce
|
||||
request
|
||||
rescue
|
||||
retire
|
||||
return
|
||||
rhyme
|
||||
rinse
|
||||
risk
|
||||
rob
|
||||
rock
|
||||
roll
|
||||
rot
|
||||
rub
|
||||
ruin
|
||||
rule
|
||||
rush
|
||||
sack
|
||||
sail
|
||||
satisfy
|
||||
save
|
||||
saw
|
||||
scare
|
||||
scatter
|
||||
scold
|
||||
scorch
|
||||
scrape
|
||||
scratch
|
||||
scream
|
||||
screw
|
||||
scribble
|
||||
scrub
|
||||
seal
|
||||
search
|
||||
separate
|
||||
serve
|
||||
settle
|
||||
shade
|
||||
share
|
||||
shave
|
||||
shelter
|
||||
shiver
|
||||
shock
|
||||
shop
|
||||
shrug
|
||||
sigh
|
||||
sign
|
||||
signal
|
||||
sin
|
||||
sip
|
||||
ski
|
||||
skip
|
||||
slap
|
||||
slip
|
||||
slow
|
||||
smash
|
||||
smell
|
||||
smile
|
||||
smoke
|
||||
snatch
|
||||
sneeze
|
||||
sniff
|
||||
snore
|
||||
snow
|
||||
soak
|
||||
soothe
|
||||
sound
|
||||
spare
|
||||
spark
|
||||
sparkle
|
||||
spell
|
||||
spill
|
||||
spoil
|
||||
spot
|
||||
spray
|
||||
sprout
|
||||
squash
|
||||
squeak
|
||||
squeal
|
||||
squeeze
|
||||
stain
|
||||
stamp
|
||||
stare
|
||||
start
|
||||
stay
|
||||
steer
|
||||
step
|
||||
stir
|
||||
stitch
|
||||
stop
|
||||
store
|
||||
strap
|
||||
strengthen
|
||||
stretch
|
||||
strip
|
||||
stroke
|
||||
stuff
|
||||
subtract
|
||||
succeed
|
||||
suck
|
||||
suffer
|
||||
suggest
|
||||
suit
|
||||
supply
|
||||
support
|
||||
suppose
|
||||
surprise
|
||||
surround
|
||||
suspect
|
||||
suspend
|
||||
switch
|
||||
talk
|
||||
tame
|
||||
tap
|
||||
taste
|
||||
tease
|
||||
telephone
|
||||
tempt
|
||||
terrify
|
||||
test
|
||||
thank
|
||||
thaw
|
||||
tick
|
||||
tickle
|
||||
tie
|
||||
time
|
||||
tip
|
||||
tire
|
||||
touch
|
||||
tour
|
||||
tow
|
||||
trace
|
||||
trade
|
||||
train
|
||||
transport
|
||||
trap
|
||||
travel
|
||||
treat
|
||||
tremble
|
||||
trick
|
||||
trip
|
||||
trot
|
||||
trouble
|
||||
trust
|
||||
try
|
||||
tug
|
||||
tumble
|
||||
turn
|
||||
twist
|
||||
type
|
||||
undress
|
||||
unfasten
|
||||
unite
|
||||
unlock
|
||||
unpack
|
||||
untidy
|
||||
use
|
||||
vanish
|
||||
visit
|
||||
wail
|
||||
wait
|
||||
walk
|
||||
wander
|
||||
want
|
||||
warm
|
||||
warn
|
||||
wash
|
||||
waste
|
||||
watch
|
||||
water
|
||||
wave
|
||||
weigh
|
||||
welcome
|
||||
whine
|
||||
whip
|
||||
whirl
|
||||
whisper
|
||||
whistle
|
||||
wink
|
||||
wipe
|
||||
wish
|
||||
wobble
|
||||
wonder
|
||||
work
|
||||
worry
|
||||
wrap
|
||||
wreck
|
||||
wrestle
|
||||
wriggle
|
||||
x-ray
|
||||
yawn
|
||||
yell
|
||||
zip
|
||||
zoom
|
||||
awake
|
||||
be
|
||||
beat
|
||||
become
|
||||
begin
|
||||
bend
|
||||
bet
|
||||
bid
|
||||
bite
|
||||
blow
|
||||
break
|
||||
bring
|
||||
broadcast
|
||||
build
|
||||
burn
|
||||
buy
|
||||
catch
|
||||
choose
|
||||
come
|
||||
cost
|
||||
cut
|
||||
dig
|
||||
do
|
||||
draw
|
||||
dream
|
||||
drive
|
||||
drink
|
||||
eat
|
||||
fall
|
||||
feel
|
||||
fight
|
||||
find
|
||||
fly
|
||||
forget
|
||||
forgive
|
||||
freeze
|
||||
get
|
||||
give
|
||||
go
|
||||
grow
|
||||
hang
|
||||
have
|
||||
hear
|
||||
hide
|
||||
hit
|
||||
hold
|
||||
hurt
|
||||
keep
|
||||
know
|
||||
lay
|
||||
lead
|
||||
learn
|
||||
leave
|
||||
lend
|
||||
let
|
||||
lie
|
||||
lose
|
||||
make
|
||||
mean
|
||||
meet
|
||||
pay
|
||||
put
|
||||
read
|
||||
ride
|
||||
ring
|
||||
rise
|
||||
run
|
||||
say
|
||||
see
|
||||
sell
|
||||
send
|
||||
show
|
||||
shut
|
||||
sing
|
||||
sit
|
||||
sleep
|
||||
speak
|
||||
spend
|
||||
stand
|
||||
swim
|
||||
take
|
||||
teach
|
||||
tear
|
||||
tell
|
||||
think
|
||||
throw
|
||||
understand
|
||||
wake
|
||||
wear
|
||||
win
|
||||
write
|
||||
has
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
require_once dirname(__FILE__) . '/../../../../../mind3rd/API/languages/pt/IgnoreForms.php';
|
||||
|
||||
/**
|
||||
* Test class for pt\IgnoreForms.
|
||||
* Generated by PHPUnit on 2010-12-19 at 11:23:40.
|
||||
*/
|
||||
class IgnoreFormsTest extends PHPUnit_Framework_TestCase {
|
||||
|
||||
/**
|
||||
* @var pt\IgnoreForms
|
||||
*/
|
||||
protected $object;
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->object = new pt\IgnoreForms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown() {
|
||||
|
||||
}
|
||||
|
||||
public function testShouldBeIgnored() {
|
||||
$this->assertTrue(pt\IgnoreForms::shouldBeIgnored('felizmente'));
|
||||
}
|
||||
public function testShouldBeIgnored1() {
|
||||
$this->assertTrue(pt\IgnoreForms::shouldBeIgnored('provavelmente'));
|
||||
}
|
||||
|
||||
|
||||
public function testShouldBeUsed() {
|
||||
$this->assertTrue(pt\IgnoreForms::shouldBeUsed('trabalhará'));
|
||||
}
|
||||
public function testShouldBeUsed1() {
|
||||
$this->assertTrue(pt\IgnoreForms::shouldBeUsed('mente'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,200 @@
|
||||
<?php
|
||||
require_once dirname(__FILE__) . '/../../../../../mind3rd/API/interfaces/inflection.php';
|
||||
require_once dirname(__FILE__) . '/../../../../../mind3rd/API/languages/pt/Inflect.php';
|
||||
|
||||
/**
|
||||
* Test class for pt\Inflect.
|
||||
* Generated by PHPUnit on 2010-11-06 at 23:55:39.
|
||||
*/
|
||||
class InflectTest extends PHPUnit_Framework_TestCase {
|
||||
|
||||
/**
|
||||
* @var pt\Inflect
|
||||
*/
|
||||
protected $object;
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->object = new pt\Inflect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown() {
|
||||
|
||||
}
|
||||
|
||||
public function testisSingular() {
|
||||
$this->assertTrue(pt\Inflect::isSingular('homem'));
|
||||
}
|
||||
public function testisSingular1() {
|
||||
$this->assertFalse(pt\Inflect::isSingular('homens'));
|
||||
}
|
||||
public function testisSingular2() {
|
||||
$this->assertFalse(pt\Inflect::isSingular('caminhões'));
|
||||
}
|
||||
public function testisSingular3() {
|
||||
$this->assertTrue(pt\Inflect::isSingular('caminhão'));
|
||||
}
|
||||
public function testisSingular4() {
|
||||
$this->assertFalse(pt\Inflect::isSingular('pães'));
|
||||
}
|
||||
public function testisSingular5() {
|
||||
$this->assertTrue(pt\Inflect::isSingular('pão'));
|
||||
}
|
||||
public function testisSingular6() {
|
||||
$this->assertFalse(pt\Inflect::isSingular('carros'));
|
||||
}
|
||||
public function testisSingular7() {
|
||||
$this->assertTrue(pt\Inflect::isSingular('atlas'));
|
||||
}
|
||||
public function testisSingular8() {
|
||||
$this->assertTrue(pt\Inflect::isSingular('professor'));
|
||||
}
|
||||
public function testisSingular9() {
|
||||
$this->assertFalse(pt\Inflect::isSingular('professores'));
|
||||
}
|
||||
|
||||
public function testToPlural() {
|
||||
$this->assertEquals(pt\Inflect::toPlural('homem'), 'homens');
|
||||
}
|
||||
public function testToPlural1() {
|
||||
$this->assertEquals(pt\Inflect::toPlural('caminhão'), 'caminhões');
|
||||
}
|
||||
public function testToPlural2() {
|
||||
$this->assertEquals(pt\Inflect::toPlural('pão'), 'pães');
|
||||
}
|
||||
public function testToPlural3() {
|
||||
$this->assertEquals(pt\Inflect::toPlural('carro'), 'carros');
|
||||
}
|
||||
public function testToPlural4() {
|
||||
$this->assertEquals(pt\Inflect::toPlural('átlas'), 'átlas');
|
||||
}
|
||||
public function testToPlural5() {
|
||||
$this->assertEquals(pt\Inflect::toPlural('óculos'), 'óculos');
|
||||
}
|
||||
public function testToPlural6() {
|
||||
$this->assertEquals(pt\Inflect::toPlural('peão'), 'peões');
|
||||
}
|
||||
public function testToPlural7() {
|
||||
$this->assertEquals(pt\Inflect::toPlural('aluna'), 'alunas');
|
||||
}
|
||||
|
||||
public function testToSingular() {
|
||||
$this->assertEquals(pt\Inflect::toSingular('homens'), 'homem');
|
||||
}
|
||||
public function testToSingular1() {
|
||||
$this->assertEquals(pt\Inflect::toSingular('caminhões'), 'caminhão');
|
||||
}
|
||||
public function testToSingular2() {
|
||||
$this->assertEquals(pt\Inflect::toSingular('pães'), 'pão');
|
||||
}
|
||||
public function testToSingular3() {
|
||||
$this->assertEquals(pt\Inflect::toSingular('carros'), 'carro');
|
||||
}
|
||||
public function testToSingular4() {
|
||||
$this->assertEquals(pt\Inflect::toSingular('átlas'), 'átlas');
|
||||
}
|
||||
public function testToSingular5() {
|
||||
$this->assertEquals(pt\Inflect::toSingular('óculos'), 'óculos');
|
||||
}
|
||||
public function testToSingular6() {
|
||||
$this->assertEquals(pt\Inflect::toSingular('peões'), 'peão');
|
||||
}
|
||||
public function testToSingular7() {
|
||||
$this->assertEquals(pt\Inflect::toSingular('alunas'), 'aluna');
|
||||
}
|
||||
public function testToSingular8() {
|
||||
$this->assertEquals(pt\Inflect::toSingular('professores'), 'professor');
|
||||
}
|
||||
|
||||
public function testToFemale() {
|
||||
$this->assertEquals(pt\Inflect::toFemale('aluno'), 'aluna');
|
||||
}
|
||||
public function testToFemale1() {
|
||||
$this->assertEquals(pt\Inflect::toFemale('réu'), 'ré');
|
||||
}
|
||||
public function testToFemale2() {
|
||||
$this->assertEquals(pt\Inflect::toFemale('gato'), 'gata');
|
||||
}
|
||||
public function testToFemale3() {
|
||||
$this->assertEquals(pt\Inflect::toFemale('leão'), 'leoa');
|
||||
}
|
||||
public function testToFemale4() {
|
||||
$this->assertEquals(pt\Inflect::toFemale('chorão'), 'chorona');
|
||||
}
|
||||
public function testToFemale5() {
|
||||
$this->assertEquals(pt\Inflect::toFemale('mestre'), 'mestra');
|
||||
}
|
||||
public function testToFemale6() {
|
||||
$this->assertEquals(pt\Inflect::toFemale('doutor'), 'doutora');
|
||||
}
|
||||
|
||||
public function testToMale1() {
|
||||
$this->assertEquals(pt\Inflect::toMale('cada'), 'cada');
|
||||
}
|
||||
public function testToMale2() {
|
||||
$this->assertEquals(pt\Inflect::toMale('aluna'), 'aluno');
|
||||
}
|
||||
public function testToMale3() {
|
||||
$this->assertEquals(pt\Inflect::toMale('ré'), 'réu');
|
||||
}
|
||||
public function testToMale4() {
|
||||
$this->assertEquals(pt\Inflect::toMale('gata'), 'gato');
|
||||
}
|
||||
public function testToMale5() {
|
||||
$this->assertEquals(pt\Inflect::toMale('leoa'), 'leão');
|
||||
}
|
||||
public function testToMale6() {
|
||||
$this->assertEquals(pt\Inflect::toMale('chorona'), 'chorão');
|
||||
}
|
||||
public function testToMale7() {
|
||||
$this->assertEquals(pt\Inflect::toMale('mestra'), 'mestre');
|
||||
}
|
||||
public function testToMale8() {
|
||||
$this->assertEquals(pt\Inflect::toMale('doutora'), 'doutor');
|
||||
}
|
||||
public function testToMale9() {
|
||||
$this->assertEquals(pt\Inflect::toMale('professora'), 'professor');
|
||||
}
|
||||
|
||||
public function testIsFemale() {
|
||||
$this->assertTrue(pt\Inflect::isFemale('mulher'));
|
||||
}
|
||||
public function testIsFemale1() {
|
||||
$this->assertTrue(pt\Inflect::isFemale('freira'));
|
||||
}
|
||||
public function testIsFemale2() {
|
||||
$this->assertTrue(pt\Inflect::isFemale('casa'));
|
||||
}
|
||||
public function testIsFemale3() {
|
||||
$this->assertTrue(pt\Inflect::isFemale('ré'));
|
||||
}
|
||||
public function testIsFemale4() {
|
||||
$this->assertFalse(pt\Inflect::isFemale('réu'));
|
||||
}
|
||||
public function testIsFemale5() {
|
||||
$this->assertTrue(pt\Inflect::isFemale('amorosa'));
|
||||
}
|
||||
public function testIsFemale6() {
|
||||
$this->assertFalse(pt\Inflect::isFemale('campeão'));
|
||||
}
|
||||
public function testIsFemale7() {
|
||||
$this->assertFalse(pt\Inflect::isFemale('chapél'));
|
||||
}
|
||||
public function testIsFemale8() {
|
||||
$this->assertTrue(pt\Inflect::isFemale('chorona'));
|
||||
}
|
||||
public function testIsFemale9() {
|
||||
$this->assertTrue(pt\Inflect::isFemale('pequenininha'));
|
||||
}
|
||||
public function testIsFemale10() {
|
||||
$this->assertFalse(pt\Inflect::isFemale('professor'));
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
require_once dirname(__FILE__) . '/../../../../../mind3rd/API/classes/Mind.php';
|
||||
require_once dirname(__FILE__) . '/../../../../../mind3rd/API/languages/pt/Verbalizer.php';
|
||||
|
||||
/**
|
||||
* Test class for pt\Verbalizer.
|
||||
* Generated by PHPUnit on 2010-12-17 at 22:16:50.
|
||||
*/
|
||||
class VerbalizerTest extends PHPUnit_Framework_TestCase {
|
||||
|
||||
/**
|
||||
* @var pt\Verbalizer
|
||||
*/
|
||||
protected $object;
|
||||
|
||||
/**
|
||||
* Sets up the fixture, for example, opens a network connection.
|
||||
* This method is called before a test is executed.
|
||||
*/
|
||||
protected function setUp() {
|
||||
$this->object = new pt\Verbalizer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tears down the fixture, for example, closes a network connection.
|
||||
* This method is called after a test is executed.
|
||||
*/
|
||||
protected function tearDown() {
|
||||
|
||||
}
|
||||
|
||||
/* NOTE: we wont be testing any first person verb flection
|
||||
* because such rules are commented on the main class as
|
||||
* mind3rd wont treat such sentences
|
||||
*/
|
||||
|
||||
public function testIsVerb() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('correr'));
|
||||
}
|
||||
public function testIsVerb1() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('nadar'));
|
||||
}
|
||||
public function testIsVerb2() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('nadam'));
|
||||
}
|
||||
public function testIsVerb3() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('ministrarão'));
|
||||
}
|
||||
public function testIsVerb4() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('apresentar'));
|
||||
}
|
||||
public function testIsVerb5() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('sobrescreve'));
|
||||
}
|
||||
public function testIsVerb6() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('lerão'));
|
||||
}
|
||||
public function testIsVerb7() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('correm'));
|
||||
}
|
||||
public function testIsVerb8() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('ministrarão'));
|
||||
}
|
||||
public function testIsVerb9() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('tomarão'));
|
||||
}
|
||||
public function testIsVerb10() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('comerá'));
|
||||
}
|
||||
public function testIsVerb11() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('bebe'));
|
||||
}
|
||||
public function testIsVerb12() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('toma'));
|
||||
}
|
||||
public function testIsVerb13() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('come'));
|
||||
}
|
||||
public function testIsVerb14() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('tomará'));
|
||||
}
|
||||
public function testIsVerb15() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('comerá'));
|
||||
}
|
||||
public function testIsVerb17() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('levantar'));
|
||||
}
|
||||
public function testIsVerb18() {
|
||||
$this->assertFalse(pt\Verbalizer::isVerb('abajur'));
|
||||
}
|
||||
public function testIsVerb19() {
|
||||
$this->assertFalse(pt\Verbalizer::isVerb('cadeira'));
|
||||
}
|
||||
public function testIsVerb20() {
|
||||
$this->assertFalse(pt\Verbalizer::isVerb('violão'));
|
||||
}
|
||||
public function testIsVerb21() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('falhar'));
|
||||
}
|
||||
public function testIsVerb22() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('falharão'));
|
||||
}
|
||||
public function testIsVerb23() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('falhar'));
|
||||
}
|
||||
public function testIsVerb24() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('falhou'));
|
||||
}
|
||||
public function testIsVerb25() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('comenta'));
|
||||
}
|
||||
public function testIsVerb26() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('comentará'));
|
||||
}
|
||||
public function testIsVerb27() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('comentarão'));
|
||||
}
|
||||
public function testIsVerb28() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('correu'));
|
||||
}
|
||||
public function testIsVerb29() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('correrás'));
|
||||
}
|
||||
public function testIsVerb30() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('falhará'));
|
||||
}
|
||||
public function testIsVerb31() {
|
||||
$this->assertTrue(pt\Verbalizer::isVerb('comeu'));
|
||||
}
|
||||
public function testIsVerb32() {
|
||||
$this->assertFalse(pt\Verbalizer::isVerb('professor'));
|
||||
}
|
||||
|
||||
// testing the toInfinitive method
|
||||
// NOTICE that its goals is about the present/future words...
|
||||
// past is not supported
|
||||
public function testToInfinitive1() {
|
||||
$this->assertEquals('saber', pt\Verbalizer::toInfinitive('sei'));
|
||||
}
|
||||
public function testToInfinitive2() {
|
||||
$this->assertEquals('poderá', pt\Verbalizer::toInfinitive('poderá'));
|
||||
}
|
||||
public function testToInfinitive3() {
|
||||
$this->assertEquals('amar', pt\Verbalizer::toInfinitive('ama'));
|
||||
}
|
||||
public function testToInfinitive4() {
|
||||
$this->assertEquals('correr', pt\Verbalizer::toInfinitive('corre'));
|
||||
}
|
||||
public function testToInfinitive5() {
|
||||
$this->assertEquals('correr', pt\Verbalizer::toInfinitive('correm'));
|
||||
}
|
||||
public function testToInfinitive6() {
|
||||
$this->assertEquals('lavar', pt\Verbalizer::toInfinitive('lavam'));
|
||||
}
|
||||
public function testToInfinitive7() {
|
||||
$this->assertEquals('ministrar', pt\Verbalizer::toInfinitive('ministram'));
|
||||
}
|
||||
public function testToInfinitive8() {
|
||||
$this->assertEquals('ter', pt\Verbalizer::toInfinitive('terão'));
|
||||
}
|
||||
public function testToInfinitive9() {
|
||||
$this->assertEquals('alimentar', pt\Verbalizer::toInfinitive('alimentarão'));
|
||||
}
|
||||
public function testToInfinitive10() {
|
||||
$this->assertEquals('pôr', pt\Verbalizer::toInfinitive('põe'));
|
||||
}
|
||||
public function testToInfinitive11() {
|
||||
$this->assertEquals('colocar', pt\Verbalizer::toInfinitive('colocarão'));
|
||||
}
|
||||
public function testToInfinitive12() {
|
||||
$this->assertEquals('varrer', pt\Verbalizer::toInfinitive('varrer'));
|
||||
}
|
||||
public function testToInfinitive13() {
|
||||
$this->assertEquals('poder', pt\Verbalizer::toInfinitive('pode'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -0,0 +1,11 @@
|
||||
a
|
||||
o
|
||||
as
|
||||
os
|
||||
aos
|
||||
que
|
||||
bem
|
||||
também
|
||||
tanto
|
||||
todo
|
||||
cada
|
||||
@@ -0,0 +1,6 @@
|
||||
SVS
|
||||
SQVS
|
||||
SVNONS
|
||||
SVNS
|
||||
SQVNONS
|
||||
SQVNS
|
||||
|
Depois Largura: | Altura: | Tamanho: 144 KiB |
|
Depois Largura: | Altura: | Tamanho: 34 KiB |
|
Depois Largura: | Altura: | Tamanho: 22 KiB |
|
Depois Largura: | Altura: | Tamanho: 98 KiB |
@@ -0,0 +1,55 @@
|
||||
@user=users.
|
||||
@project=projects.
|
||||
@version=versions.
|
||||
@object=objects.
|
||||
@component=components.
|
||||
@property=properties.
|
||||
|
||||
project has many users.
|
||||
|
||||
project has name:varchar(255, required).
|
||||
project has info:text().
|
||||
project has creator:int() // a user key.
|
||||
project has dt_creation:date(-1, "Exec:now()").
|
||||
|
||||
user has many projects.
|
||||
|
||||
user has name:varchar(255).
|
||||
user has login:varchar(40, required).
|
||||
user has pwd:varchar(40, required).
|
||||
user has status:char(1);
|
||||
user has type:char(1, {A=Admin|N=Normal}).
|
||||
|
||||
project has many versions.
|
||||
|
||||
version has version:varchar(9, required).
|
||||
version has tag:varchar(60).
|
||||
version has obs:text(2048).
|
||||
version has originalcode:text().
|
||||
version has machine_lang:varchar(16) // the chosen language, like PHP, Java Python.
|
||||
version has framework:varchar(60) // the chosen framework to generate the code.
|
||||
version has database:varchar(16) // the chosen DBMS to deal with .
|
||||
version has a user.
|
||||
|
||||
version has many objects.
|
||||
|
||||
objects have type:char(1, {T=Table|C=Class|I=Interface}).
|
||||
objects have name:varchar(256).
|
||||
every object has version:int(-1).
|
||||
object has locked:int(-1, "Exec:0") // use 0 or 1.
|
||||
object has info:varchar(2048).
|
||||
|
||||
each object may have many components.
|
||||
|
||||
components have type:char(1, {P=Propertie|M=Method|A=Annotation}).
|
||||
each component have properties.
|
||||
|
||||
All the properties have name:varchar(255, required).
|
||||
And the properties have value:text().
|
||||
Also, the properties have comment:varchar(255).
|
||||
|
||||
properties may have many properties.
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/*######################################################
|
||||
# Generated by Mind 00:09 10/27/2010 #
|
||||
# Generate PostgreSQL DataBase Commands #
|
||||
######################################################*/
|
||||
|
||||
|
||||
/* DDL: table project */
|
||||
CREATE TABLE project
|
||||
(
|
||||
pk_project integer unique not null,
|
||||
name varchar(255) not null ,
|
||||
info text ,
|
||||
creator int4 ,
|
||||
dt_creation timestamp,
|
||||
PRIMARY KEY(pk_project)
|
||||
);
|
||||
|
||||
|
||||
/* DDL: table user */
|
||||
CREATE TABLE user
|
||||
(
|
||||
pk_user integer unique not null,
|
||||
name varchar(255) ,
|
||||
login varchar(40) not null ,
|
||||
pwd varchar(40) not null ,
|
||||
status char(1) ,
|
||||
type char(1) ,
|
||||
PRIMARY KEY(pk_user)
|
||||
);
|
||||
|
||||
|
||||
/* DDL: table project_user */
|
||||
CREATE TABLE project_user
|
||||
(
|
||||
pk_project_user integer unique not null,
|
||||
fk_project integer ,
|
||||
fk_user integer ,
|
||||
PRIMARY KEY(pk_project_user),
|
||||
FOREIGN KEY(fk_user) REFERENCES user(pk_user),
|
||||
FOREIGN KEY(fk_project) REFERENCES project(pk_project)
|
||||
);
|
||||
|
||||
|
||||
/* DDL: table version */
|
||||
CREATE TABLE version
|
||||
(
|
||||
pk_version integer unique not null,
|
||||
version varchar(9) not null ,
|
||||
tag varchar(60) ,
|
||||
obs text ,
|
||||
originalcode text ,
|
||||
machine_lang varchar(16) ,
|
||||
framework varchar(60) ,
|
||||
database varchar(16) ,
|
||||
fk_project integer ,
|
||||
fk_user integer ,
|
||||
PRIMARY KEY(pk_version),
|
||||
FOREIGN KEY (fk_user) REFERENCES user(pk_user),
|
||||
FOREIGN KEY (fk_project) REFERENCES project(pk_project)
|
||||
);
|
||||
|
||||
|
||||
/* DDL: table object */
|
||||
CREATE TABLE object
|
||||
(
|
||||
pk_object integer unique not null,
|
||||
type char(1) ,
|
||||
name varchar(256) ,
|
||||
version int4 ,
|
||||
locked int4 default 0,
|
||||
info varchar(2048) ,
|
||||
fk_version integer ,
|
||||
PRIMARY KEY(pk_object),
|
||||
FOREIGN KEY (fk_version) REFERENCES version(pk_version)
|
||||
);
|
||||
|
||||
|
||||
/* DDL: table component */
|
||||
CREATE TABLE component
|
||||
(
|
||||
pk_component integer unique not null,
|
||||
type char(1) ,
|
||||
fk_object integer ,
|
||||
PRIMARY KEY(pk_component),
|
||||
FOREIGN KEY (fk_object) REFERENCES object(pk_object)
|
||||
);
|
||||
|
||||
|
||||
/* DDL: table property */
|
||||
CREATE TABLE property
|
||||
(
|
||||
pk_property integer unique not null,
|
||||
name varchar(255) not null ,
|
||||
value text ,
|
||||
comment varchar(255) ,
|
||||
fk_component integer ,
|
||||
PRIMARY KEY(pk_property),
|
||||
FOREIGN KEY (fk_component) REFERENCES component(pk_component)
|
||||
);
|
||||
|
||||
|
||||
/* DDL: table property_pointer */
|
||||
CREATE TABLE property_pointer
|
||||
(
|
||||
pk_property_pointer integer unique not null,
|
||||
main_property integer not null ,
|
||||
fk_property integer ,
|
||||
PRIMARY KEY(pk_property_pointer),
|
||||
FOREIGN KEY (fk_property) REFERENCES property(pk_property)
|
||||
);
|
||||
|
Depois Largura: | Altura: | Tamanho: 133 KiB |
|
Depois Largura: | Altura: | Tamanho: 159 KiB |
|
Depois Largura: | Altura: | Tamanho: 106 KiB |
|
Depois Largura: | Altura: | Tamanho: 11 KiB |
|
Depois Largura: | Altura: | Tamanho: 36 KiB |
|
Depois Largura: | Altura: | Tamanho: 40 KiB |
|
Depois Largura: | Altura: | Tamanho: 204 KiB |
@@ -0,0 +1,35 @@
|
||||
{
|
||||
define a mais e a menos relevantes()
|
||||
ter maior relevancia, 3pt
|
||||
pega demais pontuações(entidade)
|
||||
|
||||
pega demais pontuações(entidade)
|
||||
se a entidade tiver poucos campos, 1pt
|
||||
se a entidade tiver apenas campos pequenos, 1pt
|
||||
se a menos da metade dos campos da entidade for not null, 1pt
|
||||
retorna a pontuação adiquirida
|
||||
|
||||
vale a pena mesclar?()
|
||||
pega demais pontuações(menos relevante)
|
||||
vale a pena se tiver atingido 3 pontos
|
||||
|
||||
corrige entidades()
|
||||
exclui relação entre menos relevante e mais relevante
|
||||
adiciona chave da mais relevante na menos relevante como fk E pk para que sejam unicas
|
||||
|
||||
mescla entidades()
|
||||
coloca todas as propriedades da entidade mais fraca, na mais forte
|
||||
altera todas as relações entre a tabela mais fraca e demais tabelas, para que apontem para a mais forte
|
||||
}
|
||||
|
||||
define a mais e a menos relevantes()
|
||||
|
||||
se for 1:1 / 1:1
|
||||
mescla entidades()
|
||||
se 0:1 / 0:1
|
||||
se vale a pena mesclar
|
||||
mescla entidades()
|
||||
senao
|
||||
corrige entidades()
|
||||
Se 0:1 / 1:1
|
||||
corrige entidades()
|
||||
@@ -0,0 +1,14 @@
|
||||
//teacher have student.
|
||||
/*
|
||||
you can use "exec:command()" or "=value" to apply commands
|
||||
or numeric values to your default value
|
||||
students have age:int, sex:boolean, color:varchar(7).
|
||||
*/
|
||||
students have name:varchar(80, required, "=jon(son of bob)", key).
|
||||
|
||||
/* this is another
|
||||
test again */
|
||||
|
||||
teacher have nome:varchar(40, not null, "maria(son of jose) da silva", key).
|
||||
|
||||
and we know that each teacher may have one or many stuends.
|
||||
@@ -0,0 +1 @@
|
||||
Documentation and help file, here.
|
||||
@@ -0,0 +1,2 @@
|
||||
Access this file using your browser and see an example of how you can implement
|
||||
your own interface using the IDE.
|
||||
|
Depois Largura: | Altura: | Tamanho: 1.2 KiB |
@@ -0,0 +1,164 @@
|
||||
<script src='scripts/jquery.js'></script>
|
||||
<body>
|
||||
<input type='button' value='autenticate' onclick="autenticate()"/>
|
||||
<input type='button' value='run test' onclick="runTest()"/>
|
||||
<input type='button' value='run info' onclick="runInfo()"/>
|
||||
<input type='button' value='show projects' onclick="showProjects()"/>
|
||||
<input type='button' value='show users' onclick="showUsers()"/>
|
||||
<input type='button' value='analyze project x' onclick="analyzeX()"/>
|
||||
<input type='button' value='analyze project y' onclick="analyzeY()"/>
|
||||
<input type='button' value='logoff' onclick="logoff()"/>
|
||||
<pre><div id='result' style='white-space:pre;'></div></pre>
|
||||
</body>
|
||||
<script>
|
||||
function setLoading()
|
||||
{
|
||||
document.getElementById('result').innerHTML= " <img src='loading_animation.gif' /><br/>Loading...";
|
||||
}
|
||||
|
||||
function autenticate(){
|
||||
setLoading();
|
||||
$.ajax({
|
||||
type:'POST',
|
||||
url:'../../',
|
||||
data:{
|
||||
program:'auth',
|
||||
login:"admin",
|
||||
pwd:'admin'
|
||||
},
|
||||
success: function(ret){
|
||||
document.getElementById('result').innerHTML= ret
|
||||
}
|
||||
});
|
||||
}
|
||||
function runTest()
|
||||
{
|
||||
setLoading();
|
||||
$.ajax({
|
||||
type:'POST',
|
||||
url:'../../',
|
||||
data:{
|
||||
program:'test',
|
||||
unit: true
|
||||
},
|
||||
success: function(ret){
|
||||
document.getElementById('result').innerHTML= ret
|
||||
}
|
||||
});
|
||||
}
|
||||
function runInfo()
|
||||
{
|
||||
setLoading();
|
||||
$.ajax({
|
||||
type:'POST',
|
||||
url:'../../',
|
||||
data:{
|
||||
program: 'info'
|
||||
},
|
||||
success: function(ret){
|
||||
document.getElementById('result').innerHTML= ret
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function showProjects()
|
||||
{
|
||||
setLoading();
|
||||
$.ajax({
|
||||
type:'POST',
|
||||
url:'../../',
|
||||
data:{
|
||||
program:'show',
|
||||
what:'projects',
|
||||
detailed:'1'
|
||||
},
|
||||
success: function(ret){
|
||||
document.getElementById('result').innerHTML= ret
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function showUsers()
|
||||
{
|
||||
setLoading();
|
||||
$.ajax({
|
||||
type:'POST',
|
||||
url:'../../',
|
||||
data:{
|
||||
program:'show',
|
||||
what:'users',
|
||||
detailed:'1'
|
||||
},
|
||||
success: function(ret){
|
||||
document.getElementById('result').innerHTML= ret
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function analyzeX()
|
||||
{
|
||||
setLoading();
|
||||
$.ajax({
|
||||
type:'POST',
|
||||
url:'../../',
|
||||
data:{
|
||||
program:'use',
|
||||
what:'project',
|
||||
name:'x'
|
||||
},
|
||||
success: function(ret){
|
||||
$.ajax({
|
||||
type:'POST',
|
||||
url:'../../',
|
||||
data:{
|
||||
program:'analyze'
|
||||
},
|
||||
success: function(ret){
|
||||
document.getElementById('result').innerHTML= ret;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function analyzeY()
|
||||
{
|
||||
setLoading();
|
||||
$.ajax({
|
||||
type:'POST',
|
||||
url:'../../',
|
||||
data:{
|
||||
program:'use',
|
||||
what:'project',
|
||||
name:'y'
|
||||
},
|
||||
success: function(ret){
|
||||
$.ajax({
|
||||
type:'POST',
|
||||
url:'../../',
|
||||
data:{
|
||||
program:'analyze'
|
||||
},
|
||||
success: function(retY){
|
||||
document.getElementById('result').innerHTML= retY;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function logoff()
|
||||
{
|
||||
setLoading();
|
||||
$.ajax({
|
||||
type:'POST',
|
||||
url:'../../',
|
||||
data:{
|
||||
program:'exit'
|
||||
},
|
||||
success: function(ret){
|
||||
document.getElementById('result').innerHTML= ret
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
Depois Largura: | Altura: | Tamanho: 12 KiB |
@@ -0,0 +1,16 @@
|
||||
aluno tem professor
|
||||
//professor tem piça
|
||||
professor tem aluno
|
||||
aluno tem foto:arquivo(xx)
|
||||
/*
|
||||
|
||||
blablabla
|
||||
mimimi
|
||||
xxx
|
||||
blabelaebamimi
|
||||
*/
|
||||
aluno tem pai, mãe e papagaio.
|
||||
aluno tem nome:caractere(128, obrigatório, não nulo, "josé's da conceição")
|
||||
pai tem \pilha.
|
||||
mae tem nome, idade e sexo:char().
|
||||
mãe tem nome, idade e sexo.
|
||||
@@ -0,0 +1,16 @@
|
||||
Diagrama de sequência
|
||||
http://www.websequencediagrams.com/
|
||||
Diagrama ER
|
||||
http://thewebmind.org/
|
||||
MindMap
|
||||
http://www.mindmeister.com/
|
||||
Class Diagram
|
||||
http://creately.com
|
||||
Many different charts
|
||||
http://www.lucidchart.com/
|
||||
|
||||
|
||||
|
||||
-- to read and use as reference:
|
||||
Botton-up parse or shift-reduce parsing
|
||||
http://en.wikipedia.org/wiki/Shift-reduce_parsing
|
||||
@@ -1,195 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset='utf-8'>
|
||||
|
||||
<title>felipenmoura/theWebMind @ GitHub</title>
|
||||
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin-top: 1.0em;
|
||||
background-color: #f0f0f0;
|
||||
font-family: Helvetica, Arial, FreeSans, san-serif;
|
||||
color: #444;
|
||||
}
|
||||
#container {
|
||||
margin: 0 auto;
|
||||
width: 700px;
|
||||
}
|
||||
h1 { font-size: 3.8em; color: #000; margin-bottom: 3px; }
|
||||
h1 .small { font-size: 0.4em; }
|
||||
h1 a { text-decoration: none }
|
||||
h2 { font-size: 1.5em; color: #000; }
|
||||
h3 { text-align: center; color: #000; }
|
||||
a { color: #007; }
|
||||
.description { font-size: 1.2em; margin-bottom: 30px; margin-top: 30px; font-style: italic;}
|
||||
.download { float: right; }
|
||||
pre { background: #000; color: #fff; padding: 15px;}
|
||||
hr { border: 0; width: 80%; border-bottom: 1px solid #aaa}
|
||||
.footer { text-align:center; padding-top:30px; font-style: italic; }
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<a href="https://github.com/felipenmoura/theWebMind"><img style="position: absolute; top: 0; right: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub" /></a>
|
||||
|
||||
<div id="container">
|
||||
|
||||
<div class="download">
|
||||
<a href="https://github.com/felipenmoura/theWebMind/zipball/master">
|
||||
<img border="0" width="90" src="https://github.com/images/modules/download/zip.png"></a>
|
||||
<a href="https://github.com/felipenmoura/theWebMind/tarball/master">
|
||||
<img border="0" width="90" src="https://github.com/images/modules/download/tar.png"></a>
|
||||
</div>
|
||||
|
||||
<h1><a href="https://github.com/felipenmoura/theWebMind">theWebMind</a>
|
||||
<span class="small">by <a href="https://github.com/felipenmoura">felipenmoura</a></span></h1>
|
||||
|
||||
<div class="description">
|
||||
An innovating way to build your applications from zero, "talking" to your computer
|
||||
</div>
|
||||
|
||||
|
||||
<p><strong>TheWebMind</strong><br/>
|
||||
This is the source code for theWebMind project.<br/>
|
||||
<hr/>
|
||||
<p>Requirements:</p>
|
||||
<ul type='disc'>
|
||||
<li>PHP 5.3+</li>
|
||||
<li>PHP-cli</li>
|
||||
<li>PHP-SQLite3</li>
|
||||
<li>ReadLine(if you inted to use it in command line, not only with HTTP requisitions)</li>
|
||||
</ul>
|
||||
|
||||
<p>Installation:</p>
|
||||
For now, only working on mac and Linux...sorry bill!</br>
|
||||
Your HTTPServer's user must have permission to read and write on its folder</br>
|
||||
In your console, run the following command into this directory:</br>
|
||||
<pre>$ sudo php mind install</pre>
|
||||
Great! Now you're good to go
|
||||
<br/><br/>
|
||||
<hr/>
|
||||
|
||||
<p>Examples and tests:<br/>
|
||||
To perform some examples and tests, access in your browser the IDE demo<br/>
|
||||
<pre>http://[yourMindDir]/docs/ide</pre>
|
||||
|
||||
<p>For graphics, diagrams, examples of code, help and documentation, see the docs directory<br/>
|
||||
<pre>[yourMindDir]/docs/</pre>
|
||||
|
||||
Your projects are stored at:
|
||||
<pre>[yourMindDir]/projects/[projectName]</pre>
|
||||
You can write your codes directly in sources/main.mnd in your project's source directory.<br/>
|
||||
You can see the generated documentation and source code on 'docs' and 'app' directories, into the project's directory.<br/>
|
||||
|
||||
<p>Please, check/change the data and options as you need, on
|
||||
<pre>[yourMindDir]/env/defaults.ini</pre>
|
||||
|
||||
<p>Unit tests are on Tests directory, run it with PHPUnit
|
||||
<pre>[yourMindDir]/Tests</pre>
|
||||
|
||||
Useful/interesting links:<br/>
|
||||
<a href='http://thewebmind.org/' target='_quot'>Official website</a> |
|
||||
<a href='https://github.com/felipenmoura/theWebMind/blob/master/licenses/mind3rd.license' target='_quot'>Licenses</a> |
|
||||
<a href='http://docs.thewebmind.org' target='_quot'>Documentation |
|
||||
<a href='mailto:contact@thewebmind.org'>Contact</a> |
|
||||
<a href='http://twitter.com/thewebmind' target='_quot'>Twitter</a> |
|
||||
<a href='http://thewebmind.org/contribute' target='_quot'>Contribute</a> |
|
||||
<a href='http://groups.google.com.br/group/thewebmind' target='_quot'>Discussion Group</a></p>
|
||||
|
||||
|
||||
|
||||
<h2>Dependencies</h2>
|
||||
<p>PHP 5.3+
|
||||
SQLite 3
|
||||
Permission to write on its own directories</p>
|
||||
|
||||
|
||||
|
||||
<h2>Install</h2>
|
||||
<p>1) Download and extract it into your www(or htdocs) in your server, or clone the repository in there;
|
||||
|
||||
On LINUX or Mac:
|
||||
2) open the console, and to the just downloaded/cloned folder, then type:
|
||||
php mind install
|
||||
|
||||
3) Enjoy it :)
|
||||
|
||||
On Windows:
|
||||
2) Open your browser and access the just downloaded/cloned directory, plus the "install" directory, for example: http://localhost/thewebmind/install
|
||||
|
||||
3) If all the dependencies are ok, just click the button "install", otherwise, try and fix them, click the "verify again" button, and then, the "install" button;
|
||||
|
||||
4) On windows, you will not be able to access it through console, so you should send "post" messages to its index, or access /ide to see examples and some of its usage</p>
|
||||
|
||||
|
||||
|
||||
<h2>License</h2>
|
||||
<p>The MIT License
|
||||
|
||||
Copyright (c) 2011 TheWebMind.org, Felipe Nascimento de Moura
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE 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.
|
||||
|
||||
Main contacts:
|
||||
felipe@thewebmind.org // http://felipenmoura.org // twitter: @felipenmoura
|
||||
jaydson@thewebmind.org // http://jaydson.org // twitter: @jaydson</p>
|
||||
|
||||
|
||||
|
||||
<h2>Authors</h2>
|
||||
<br/><a href='http://felipenmoura.org' target='_quot'>FelipeNMoura</a> (felipe@thewebmind.org)
|
||||
<br/> </p>
|
||||
|
||||
|
||||
|
||||
<h2>Contacts</h2>
|
||||
<p><a href='http://felipenmoura.org' target='_quot'>Felipe Nascimento de Moura</a> (felipe@thewebmind.org)</p>
|
||||
<p><a href='http://groups.google.com.br/group/thewebmind' target='_quot'>The official discussion group</a></p>
|
||||
|
||||
|
||||
<h2>Download</h2>
|
||||
<p>
|
||||
You can download this project in either
|
||||
<a href="https://github.com/felipenmoura/theWebMind/zipball/master">zip</a> or
|
||||
<a href="https://github.com/felipenmoura/theWebMind/tarball/master">tar formats.
|
||||
</p>
|
||||
<p>You can also clone the project with <a href="http://git-scm.com">Git</a>
|
||||
by running:
|
||||
<pre>$ git clone git://github.com/felipenmoura/theWebMind</pre>
|
||||
</p>
|
||||
|
||||
<div class="footer">
|
||||
get the source code on GitHub : <a href="https://github.com/felipenmoura/theWebMind">felipenmoura/theWebMind</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
try {
|
||||
var pageTracker = _gat._getTracker("UA-1270869-9");
|
||||
pageTracker._trackPageview();
|
||||
} catch(err) {}</script>"
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
$_REQ= Array();
|
||||
$_REQ['request_method']= $_SERVER['REQUEST_METHOD'];
|
||||
$_REQ['env']= 'http';
|
||||
define('_MINDSRC_', getcwd());
|
||||
switch($_REQ['request_method'])
|
||||
{
|
||||
case 'GET' : $_REQ['data']= $_GET;
|
||||
break;
|
||||
case 'POST': $_REQ['data']= $_POST;
|
||||
break;
|
||||
case 'PUT' : parse_str(file_get_contents('php://input'), $put_vars);
|
||||
$_REQ['data'] = $put_vars;
|
||||
break;
|
||||
default:
|
||||
$_REQ['data']= null;
|
||||
}
|
||||
include('mind3rd/API/utils.php');
|
||||
@@ -0,0 +1,28 @@
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2011 TheWebMind.org, Felipe Nascimento de Moura
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
files (the "Software"), to deal in the Software without
|
||||
restriction, including without limitation the rights to use,
|
||||
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE 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.
|
||||
|
||||
Main contacts:
|
||||
felipe@thewebmind.org // http://felipenmoura.org // twitter: @felipenmoura
|
||||
jaydson@thewebmind.org // http://jaydson.org // twitter: @jaydson
|
||||
@@ -0,0 +1,19 @@
|
||||
Copyright 2008-2010 Alistair Kearney, Allen Chang, Scott Hughes
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
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.
|
||||
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* this file will be only accessed trhough the console
|
||||
* if you pass the parameter install to it, it will
|
||||
* create the SQLite database, start it, and try to
|
||||
* create shortcuts, allowing the use of the comand
|
||||
* mind, in your console
|
||||
*/
|
||||
|
||||
$_MIND= Array();
|
||||
$_MIND['env']= 'shell';
|
||||
|
||||
// checks if it has received any argument
|
||||
if(sizeOf($_SERVER['argv'])>0)
|
||||
{
|
||||
// installation should create the required SQLite database and a shortcut command
|
||||
if($_SERVER['argv'][1] == 'install')
|
||||
{
|
||||
// first, for linux and mac computers
|
||||
if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN')
|
||||
{
|
||||
require('mind3rd/env/setup/UnixSetup.php');
|
||||
UnixSetup::install();
|
||||
}else{
|
||||
WinSetup::install();
|
||||
}
|
||||
exit;
|
||||
}
|
||||
// if not installing, it should be redirected to mind3rd/API/shell.php
|
||||
include('location:./mind3rd/API/shell.php');
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/**
|
||||
* This class represents the structure required to use L10N
|
||||
*
|
||||
* @author felipe
|
||||
*/
|
||||
class En {
|
||||
private $messages= Array();
|
||||
|
||||
public $name= 'en';
|
||||
|
||||
/**
|
||||
* This method returns the translated message
|
||||
* @method getMessage
|
||||
* @param String $msg
|
||||
* @return String Returns the string translated, or fals if the required message does not exist
|
||||
*/
|
||||
public function getMessage($msg)
|
||||
{
|
||||
if(isset($this->messages[$msg]))
|
||||
return $this->messages[$msg];
|
||||
else
|
||||
return false;
|
||||
}
|
||||
public function __construct()
|
||||
{
|
||||
$this->messages['programRequired'] = Mind::message("API: You must send the program name, to execute", '[Fail]', false);
|
||||
$this->messages['loginRequired'] = Mind::message("Auth: Both login and password are required", '[Fail]', false);
|
||||
$this->messages['passwordRequired'] = "I need a password for this user, please: ";
|
||||
$this->messages['autenticated'] = Mind::message("\nMain: %s autenticated", "[OK]", false);//"\n[OK] %s autenticated\n";
|
||||
$this->messages['not_allowed'] = Mind::message("\nMain: You have not autenticated your credentials yet", '[Fail]', false);
|
||||
$this->messages['not_allowed_tip'] = "Try calling the command\n auth < login >\nA password will be required.\n";
|
||||
$this->messages['no_such_file'] = Mind::message("\nMain: No such command '%s'", "[Fail]", false);
|
||||
$this->messages['auth_fail'] = Mind::message("\nAuth: Wrong user or password", "[Fail]", false);
|
||||
$this->messages['bye'] = "Logging out...\n";
|
||||
$this->messages['thinking'] = "Please wait while I'm thinking...\n";
|
||||
$this->messages['invalidCreateParams'] = Mind::message("Main: Invalid parameters", "[Fail]", false);
|
||||
$this->messages['invalidOption'] = Mind::message("Invalid option '%s'", '[Fail]', false);
|
||||
$this->messages['projectAlreadyExists'] = Mind::message("There is, already, another project with the same name", '[Fail]', false);
|
||||
$this->messages['projectCreated'] = Mind::message("Created project '%s'", '[Ok]', false);
|
||||
$this->messages['userCreated'] = Mind::message("Created user '%s'", '[Ok]', false);
|
||||
$this->messages['noProject'] = Mind::message("Project '%s' doesn't exist or you have no access", '[Fail]', false);
|
||||
$this->messages['projectOpened'] = Mind::message("Project '%s' opened", '[Ok]', false);
|
||||
$this->messages['currentProjectRequired'] = Mind::message("You must open a project first", '[Fail]', false);
|
||||
$this->messages['sourceFileNotFound'] = Mind::message("The source '%s' was not found for the current project.", '[Fail]', false);
|
||||
$this->messages['currentProjectRequiredTip']= "You can use the command\n use project <projectName>\n";
|
||||
$this->messages['analyseFirst'] = "You will need to analyze the project. It has not been analyzed yet.Execute the 'analyze' command.\n";
|
||||
$this->messages['permissionDenied'] = Mind::message("Permission denied to change/create/delete files.\nPlease, allow the system to change files in mind's root directory", '[Fail]', false);;
|
||||
$this->messages['additionalCounterCol'] = "This field was automatically added to allow an insertion of a new tuple using repeated values for the other keys.";
|
||||
|
||||
$this->messages['http_invalid_requisition'] = <<<MESSAGE
|
||||
Invalid HTTP requisition.
|
||||
You *must* send some POST data acoording your request, and also a variable "program" by post, with the name of the program you want to run.
|
||||
MESSAGE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/**
|
||||
* This class represents the structure required to use L10N
|
||||
*
|
||||
* @author felipe
|
||||
*/
|
||||
class pt {
|
||||
private $messages= Array();
|
||||
|
||||
public $name= 'pt';
|
||||
|
||||
/**
|
||||
* This method returns the translated message
|
||||
* @method getMessage
|
||||
* @param String $msg
|
||||
* @return String Returns the string translated, or fals if the required message does not exist
|
||||
*/
|
||||
public function getMessage($msg)
|
||||
{
|
||||
if(isset($this->messages[$msg]))
|
||||
return $this->messages[$msg];
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct
|
||||
* This method should start all the messages, setting them
|
||||
* to the class::$messages
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
//header('Content-type: text/html; charset=iso-8859-1');
|
||||
$this->messages['programRequired'] = Mind::message("API: Você precisa passar o nome do programa a ser executado.", '[Fail]', false);
|
||||
$this->messages['loginRequired'] = Mind::message("Auth: Tanto login quanto senha são obrigatórios.", '[Fail]', false);
|
||||
$this->messages['passwordRequired'] = "Precisarei do password para este usuário, por favor: ";
|
||||
$this->messages['autenticated'] = Mind::message("\nMain: %s autenticado", "[OK]", false);//"\n[OK] %s autenticated\n";
|
||||
$this->messages['not_allowed'] = Mind::message("\nMain: Você ainda não autenticou suas credenciais.", '[Fail]', false);
|
||||
$this->messages['not_allowed_tip'] = "Tente executar o comando\n auth < login >\nUma senha será solicitada.\n";
|
||||
$this->messages['no_such_file'] = Mind::message("\nMain: Não conheço tal comando: '%s'", "[Fail]", false);
|
||||
$this->messages['auth_fail'] = Mind::message("\nAuth: Usuário ou senha inválidos", "[Fail]", false);
|
||||
$this->messages['bye'] = "Saindo, até logo...\n";
|
||||
$this->messages['thinking'] = "Por favor aguarde, enquanto eu penso...\n";
|
||||
$this->messages['invalidCreateParams'] = Mind::message("Main: Parâmetros inválidos", "[Fail]", false);
|
||||
$this->messages['invalidOption'] = Mind::message("Opção inválida '%s'", '[Fail]', false);
|
||||
$this->messages['projectAlreadyExists'] = Mind::message("Lamento mas já existe um projeto de mesmo nome.", '[Fail]', false);
|
||||
$this->messages['projectCreated'] = Mind::message("Projeto '%s' criado.", '[Ok]', false);
|
||||
$this->messages['userCreated'] = Mind::message("Usuário '%s' criado", '[Ok]', false);
|
||||
$this->messages['noProject'] = Mind::message("Projeto '%s' não existe ou você não tem acesso ao mesmo.", '[Fail]', false);
|
||||
$this->messages['projectOpened'] = Mind::message("Acessando projeto '%s'", '[Ok]', false);
|
||||
$this->messages['currentProjectRequired'] = Mind::message("Primeiro você precisará abrir um projeto.", '[Fail]', false);
|
||||
$this->messages['currentProjectRequiredTip']= "Tente com o comando\n use project <projectName>\n";
|
||||
$this->messages['analyseFirst'] = "Você precisará analisar o projeto, primeiro. O projeto ainda não foi analizado. Execute o comando 'analyze'.\n";
|
||||
$this->messages['sourceFileNotFound'] = Mind::message("O arquivo fonte '%s' não foi encontrado para o projeto atual.", '[Fail]', false);
|
||||
$this->messages['permissionDenied'] = Mind::message("Permissão negada pra acessar, criar, alterar ou excluir um arquivo.\nPor favor, libere acesso ao sistema para o diretório raíz do Mind.\n", '[Fail]', false);
|
||||
$this->messages['additionalCounterCol'] = "Campo adicionado automaticamente, a ser usado como diferencial para cada tupla, a fim de possibilizar um novo registro utilizando as mesmas demais chaves.";
|
||||
|
||||
$this->messages['http_invalid_requisition'] = <<<MESSAGE
|
||||
Requisição HTTP inválida.
|
||||
Você *deve* enviar alguma informação via POST juntamente com o parâmetro "program" com o nome do programa que deseja rodar e seus parâmetros.
|
||||
MESSAGE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
<?php
|
||||
/**
|
||||
* This is the main class
|
||||
* It provides a bunch of static methods to deal with the console
|
||||
* and also, methods and properties to deal with the project and
|
||||
* the system itself
|
||||
*
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
*/
|
||||
class Mind
|
||||
{
|
||||
public $about= null;
|
||||
public $defaults= null;
|
||||
public $conf= null;
|
||||
|
||||
public static $autoloadPaths= Array();
|
||||
public static $currentProject= null;
|
||||
public static $ref= Array();
|
||||
public static $projectsDir= '';
|
||||
public static $pluginList= Array();
|
||||
public static $l10n= null;
|
||||
public static $triggers= Array();
|
||||
public static $modelsDir= "";
|
||||
public static $lexer;
|
||||
public static $canonic;
|
||||
public static $syntaxer;
|
||||
public static $tokenizer;
|
||||
public static $langPath= "";
|
||||
public static $content= "";
|
||||
public static $originalContent= "";
|
||||
public static $curLang= 'en';
|
||||
|
||||
/**
|
||||
* Verifies wheter the software is installed or not
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isInstalled()
|
||||
{
|
||||
return file_exists(_MINDSRC_.'/mind3rd/SQLite/mind');
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns or outputs messages using the L10N library
|
||||
* You can pass a rich string with %s, %i, etc, sending extra parameters
|
||||
* If the boolean flag $echo is sent, it prints it to the output, otherwise,
|
||||
* only returns it
|
||||
* This is an alias for MindSpeaker::write
|
||||
*
|
||||
* @param String $k
|
||||
* @param Bolean $echo
|
||||
* @param mixed... extra parameter to be treated in the string
|
||||
* @return String
|
||||
*/
|
||||
public static function write($k, $echo=true)
|
||||
{
|
||||
return MindSpeaker::write($k, $echo, func_get_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns or prints a message formated to represent failures, passes
|
||||
* or any kind of alert
|
||||
* This is an alias for MindSpeaker::message
|
||||
*
|
||||
* @param String $message The message itself
|
||||
* @param String $status The status to be shown in the end of the message
|
||||
* @param Boolean $echo if it should be printed or not
|
||||
* @return string
|
||||
*/
|
||||
public static function message($message, $status, $echo=true)
|
||||
{
|
||||
return MindSpeaker::message($message, $status, $echo);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alias for MindCommand::readPassword
|
||||
* @param String $stars
|
||||
* @return String $password
|
||||
*/
|
||||
public static function readPassword($stars)
|
||||
{
|
||||
return MindCommand::readPassword($stars);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will copy the whole directory, recursively
|
||||
* but it is focused to the "generate project" tool
|
||||
* This is an alias for MindDir::copyDir
|
||||
*
|
||||
* @author Felipe Nascimento
|
||||
* @name copyDir
|
||||
* @param String $source
|
||||
* @param String $dest
|
||||
* @param [String $flag]
|
||||
* @return boolean
|
||||
*/
|
||||
static function copyDir($source, $dest, $flag= false)
|
||||
{
|
||||
return MindDir::copyDir($source, $dest, $flag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes recusrively a directory
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
* @method deleteDir
|
||||
* @param String $dir
|
||||
* @return boolean
|
||||
*/
|
||||
static function deleteDir($dir)
|
||||
{
|
||||
return MindDir::deleteDir($dir);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a MindPlugin based object to the
|
||||
* plugins and triggers list
|
||||
* Alias for MindPlugin::addPlugin
|
||||
*
|
||||
* @param MindPlugin $plugin
|
||||
*/
|
||||
static function addPlugin(&$plugin)
|
||||
{
|
||||
MindPlugin::addPlugin($plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the project already exists,
|
||||
* false, otherwise
|
||||
* Alias for MindProject::hasProject
|
||||
*
|
||||
* @global Mind $_MIND
|
||||
* @param String $project
|
||||
* @return boolean
|
||||
*/
|
||||
static function hasProject($project)
|
||||
{
|
||||
GLOBAL $_MIND;
|
||||
return MindProject::hasProject($project);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads data from the passed project
|
||||
* Alias for MindProject::openProject
|
||||
*
|
||||
* @param AssocArray $p
|
||||
* @return boolean
|
||||
*/
|
||||
public static function openProject($p)
|
||||
{
|
||||
return MindProject::openProject($p);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a directory to the autoload source paths list
|
||||
* @param String $path
|
||||
*/
|
||||
public static function autoloadRegisterPath($path)
|
||||
{
|
||||
if(is_string($path) && !in_array($path, Mind::$autoloadPaths))
|
||||
Mind::$autoloadPaths[]= $path;
|
||||
else
|
||||
foreach($path as $p)
|
||||
if(!in_array($p, Mind::$autoloadPaths))
|
||||
Mind::$autoloadPaths[]= $p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function Mind(){
|
||||
$path= _MINDSRC_;
|
||||
Mind::$projectsDir= $path.PROJECTS_DIR;
|
||||
Mind::$modelsDir= $path.MODELS_DIR;
|
||||
$this->about= parse_ini_file($path.ABOUT_INI);
|
||||
$this->defaults= parse_ini_file($path.DEFAULTS_INI);
|
||||
$this->conf= parse_ini_file($path.MIND_CONF);
|
||||
require_once($path.L10N_DIR.$this->defaults['default_human_language'].'.php');
|
||||
Mind::$curLang= $this->defaults['default_human_languageName'];
|
||||
Mind::$l10n= new $this->defaults['default_human_language']();
|
||||
Mind::$langPath= $path.LANG_PATH;
|
||||
Mind::$curLang= $this->defaults['default_human_language'];
|
||||
|
||||
$langPath= $path.LANG_PATH;
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . $langPath);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
class Mind
|
||||
{
|
||||
public $about= null;
|
||||
public $defaults= null;
|
||||
public $conf= null;
|
||||
public $l10n= null;
|
||||
|
||||
public function write($k, $echo=true)
|
||||
{
|
||||
//$msg= $this->l10n->xpath("/root/speach[@voice='".$k."']");
|
||||
//echo "/root/".$k;
|
||||
$msg= (string)$this->l10n->$k;
|
||||
if($echo)
|
||||
echo $msg;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
public function message($message, $status)
|
||||
{
|
||||
echo str_pad($message, 80-strlen($status), '.');
|
||||
echo $status."\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
public function Mind(){
|
||||
$path= _MINDSRC_;
|
||||
$this->about= parse_ini_file($path.'/mind3rd/env/about.ini');
|
||||
$this->defaults= parse_ini_file($path.'/mind3rd/env/defaults.ini');
|
||||
$this->conf= parse_ini_file($path.'/mind3rd/env/mind.ini');
|
||||
$this->l10n= SimpleXML_load_file($path.'/mind3rd/API/L10N/'.$this->defaults['defaul_human_language'].'.xml');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
<?php
|
||||
use Symfony\Component\Console\Input\InputArgument,
|
||||
Symfony\Component\Console\Input\InputOption,
|
||||
Symfony\Component\Console;
|
||||
|
||||
/**
|
||||
* This class extends the Command class from Symfony
|
||||
* All the program should extend it
|
||||
*
|
||||
* @author felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
*/
|
||||
class MindCommand extends Symfony\Component\Console\Command\Command
|
||||
{
|
||||
private $restrict= true;
|
||||
private $fileName= null;
|
||||
|
||||
/**
|
||||
* Specifies the name of the file, included with the program
|
||||
* @param String $fName
|
||||
* @return MindCommand
|
||||
*/
|
||||
public function setFileName($fName)
|
||||
{
|
||||
$this->fileName= $fName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the file which the program is refered to
|
||||
* @method getFileName
|
||||
* @return String
|
||||
*/
|
||||
public function getFileName()
|
||||
{
|
||||
return $this->fileName!=null? $this->fileName: $this->getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the restrict property
|
||||
*
|
||||
* @param Boolean $b
|
||||
* @return MindCommand Itself
|
||||
*/
|
||||
public function setRestrict($b)
|
||||
{
|
||||
$this->restrict= $b;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct
|
||||
* @param String $name
|
||||
*/
|
||||
public function __construct($name = null)
|
||||
{
|
||||
parent::__construct($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if the user has already registered or not
|
||||
* according to the specifications of each program
|
||||
*
|
||||
* @method verifyCredentials
|
||||
* @return Boolean
|
||||
*/
|
||||
public function verifyCredentials()
|
||||
{
|
||||
if($this->restrict)
|
||||
if(!isset($_SESSION['auth']))
|
||||
{
|
||||
Mind::write('not_allowed');
|
||||
Mind::write('not_allowed_tip');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the pluggins that should run on
|
||||
* specific already registered events
|
||||
*
|
||||
* @method runPlugins
|
||||
* @param String $evt
|
||||
* @return void
|
||||
*/
|
||||
public function runPlugins($evt)
|
||||
{
|
||||
if(isset(Mind::$pluginList[$this->name]))
|
||||
{
|
||||
foreach(Mind::$pluginList[$this->name][$evt] as $plugin)
|
||||
{
|
||||
if($plugin->active !== false)
|
||||
$plugin->run($this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the program using the cosole interface
|
||||
*
|
||||
* @method execute
|
||||
* @param Console\Input\InputInterface $input
|
||||
* @param Console\Output\OutputInterface $output
|
||||
* @return Boolean
|
||||
*/
|
||||
public function execute(Console\Input\InputInterface $input,
|
||||
Console\Output\OutputInterface $output)
|
||||
{
|
||||
$this->runPlugins('before');
|
||||
return $this->verifyCredentials();
|
||||
}
|
||||
|
||||
public function __() {
|
||||
$this->runPlugins('after');
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls the program by the HTTP interface
|
||||
* @method HTTPExecute
|
||||
* @global Array $_REQ
|
||||
* @return Boolean
|
||||
*/
|
||||
public function HTTPExecute()
|
||||
{
|
||||
GLOBAL $_REQ;
|
||||
if($_REQ['env'] =='http')
|
||||
{
|
||||
$this->runPlugins('before');
|
||||
return $this->verifyCredentials();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* function taken from: http://www.dasprids.de/blog/2008/08/22/getting-a-password-hidden-from-stdin-with-php-cli
|
||||
* this method should read the passwords from console, not showing any character
|
||||
* or replacing them by stars(asterisks)
|
||||
* @method readPassword
|
||||
* @param Boolan $stars if true, show an * for each typed char
|
||||
* @return String password
|
||||
*/
|
||||
public static function readPassword($stars)
|
||||
{
|
||||
// Get current style
|
||||
$oldStyle = shell_exec('stty -g');
|
||||
|
||||
if ($stars === false) {
|
||||
shell_exec('stty -echo');
|
||||
$password = rtrim(fgets(STDIN), "\n");
|
||||
} else {
|
||||
shell_exec('stty -icanon -echo min 1 time 0');
|
||||
|
||||
$password = '';
|
||||
while (true) {
|
||||
$char = fgetc(STDIN);
|
||||
|
||||
if ($char === "\n") {
|
||||
break;
|
||||
} else if (ord($char) === 127) {
|
||||
if (strlen($password) > 0) {
|
||||
fwrite(STDOUT, "\x08 \x08");
|
||||
$password = substr($password, 0, -1);
|
||||
}
|
||||
} else {
|
||||
fwrite(STDOUT, "*");
|
||||
$password .= $char;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset old style
|
||||
shell_exec('stty ' . $oldStyle);
|
||||
|
||||
// Return the password
|
||||
return $password;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will execute the plugins that should run AFTER
|
||||
* the execution of the program, so, call parent::runAction AFTER
|
||||
* each program::runAction command blocks
|
||||
*/
|
||||
public function runAction(){
|
||||
$this->runPlugins('after');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
/*
|
||||
* To change this template, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Basic abstraction of the SQLite layer
|
||||
*
|
||||
* @author felipe
|
||||
*/
|
||||
class MindDB {
|
||||
private $db= null;
|
||||
public $lastInsertedId= 0;
|
||||
|
||||
/**
|
||||
* @method query
|
||||
* @param String $qr
|
||||
* @return Mixed
|
||||
*/
|
||||
public function query($qr)
|
||||
{
|
||||
$ret= sqlite_query($this->db, $qr);
|
||||
$ar_ret= Array();
|
||||
while($tuple= sqlite_fetch_array($ret, SQLITE_ASSOC))
|
||||
{
|
||||
$ar_ret[]= $tuple;
|
||||
}
|
||||
return $ar_ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a command into the database
|
||||
* @param String $command
|
||||
* @return Int
|
||||
*/
|
||||
public function execute($command)
|
||||
{
|
||||
$ret= sqlite_exec($this->db, $command);
|
||||
$this->lastInsertedId= sqlite_last_insert_rowid($this->db);
|
||||
return $this->lastInsertedId;
|
||||
}
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
if(!$db = sqlite_open(_MINDSRC_.'/mind3rd/SQLite/mind'))
|
||||
{
|
||||
Mind::message('Database', '[Fail]');
|
||||
return false;
|
||||
}
|
||||
$this->db= $db;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/**
|
||||
* Description of MindDir
|
||||
*
|
||||
* @author felipe
|
||||
*/
|
||||
class MindDir {
|
||||
/**
|
||||
* This method will copy the whole directory, recursively
|
||||
* but it is focused to the "generate project" tool
|
||||
* @author Felipe Nascimento
|
||||
* @name copyDir
|
||||
* @param String $source
|
||||
* @param String $dest
|
||||
* @param [String $flag]
|
||||
* @return boolean
|
||||
*/
|
||||
static function copyDir($source, $dest, $flag= false)
|
||||
{
|
||||
// Simple copy for a file
|
||||
if($flag)
|
||||
{
|
||||
$s= '...'.substr($source, -30);
|
||||
showLoadStatus("Copying ".$s, $_SESSION['currentPerc']);
|
||||
}
|
||||
if (is_file($source))
|
||||
{
|
||||
$c = copy($source, $dest);
|
||||
chmod($dest, 0777);
|
||||
return $c;
|
||||
}
|
||||
// Make destination directory
|
||||
if(!is_dir($dest))
|
||||
{
|
||||
$oldumask = umask(0);
|
||||
mkdir($dest, 0777);
|
||||
umask($oldumask);
|
||||
}
|
||||
// Loop through the folder
|
||||
$dir = dir($source);
|
||||
while(false !== $entry = $dir->read())
|
||||
{
|
||||
// Skip pointers
|
||||
if ( in_array($entry, array(".","..",".svn") ) )
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// Deep copy directories
|
||||
if ($dest !== "$source/$entry")
|
||||
{
|
||||
Mind::copyDir("$source/$entry", "$dest/$entry", $flag);
|
||||
}
|
||||
}
|
||||
// Clean up
|
||||
$dir->close();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes recusrively a directory
|
||||
* @author thiago <erkethan@free.fr>
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
* @method deleteDir
|
||||
* @param String $dir
|
||||
* @return boolean
|
||||
*/
|
||||
static function deleteDir($dir)
|
||||
{
|
||||
if(!file_exists($dir))
|
||||
return true;
|
||||
if(!is_dir($dir) || is_link($dir))
|
||||
return unlink($dir);
|
||||
foreach(scandir($dir) as $item)
|
||||
{
|
||||
if ($item == '.' || $item == '..')
|
||||
continue;
|
||||
if(!$this->deleteDir($dir . "/" . $item))
|
||||
{
|
||||
chmod($dir . "/" . $item, 0777);
|
||||
if(!$this->deleteDir($dir . "/" . $item))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return rmdir($dir);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
/**
|
||||
* A facade to deal with attributes/properties and methods
|
||||
* related to an entity
|
||||
*
|
||||
* @author felipe
|
||||
*/
|
||||
class MindEntity {
|
||||
|
||||
public $name;
|
||||
public $pks= Array();
|
||||
public $relevance= 0;
|
||||
public $properties= Array();
|
||||
public $relations= Array();
|
||||
public $linkTable= false;
|
||||
private $refTo= Array();
|
||||
private $refBy= Array();
|
||||
public $selfRef= false;
|
||||
|
||||
public function addAutoPk($unique=false)
|
||||
{
|
||||
GLOBAL $_MIND;
|
||||
$pkPrefix= $_MIND->defaults['pk_prefix'];
|
||||
$propName= $pkPrefix.$this->name;
|
||||
|
||||
$pk= new MindProperty();
|
||||
$pk ->setAsKey()
|
||||
->setName($propName)
|
||||
->setDefault(AUTOINCREMENT_DEFVAL)
|
||||
->setRequired(true)
|
||||
->setType('int')
|
||||
->setUnique($unique);
|
||||
$this->addProperty($pk);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the entity as a self referred entity.
|
||||
* It uses the $how to know if it is a multiple or a single reference.
|
||||
*
|
||||
* @param mixed $how 0, 1 or n
|
||||
* @return MindEntity
|
||||
*/
|
||||
public function setSelfReferred($how)
|
||||
{
|
||||
$this->selfRef= $how;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the array of entities which are referred by this entity.
|
||||
* @return Array
|
||||
*/
|
||||
public function &getRefTo()
|
||||
{
|
||||
return $this->refTo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the array of the entities which point to this entity.
|
||||
* @return Array
|
||||
*/
|
||||
public function &getRefBy()
|
||||
{
|
||||
return $this->refBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if the entity has a hardKey, or only weakKeys.
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasHardKey()
|
||||
{
|
||||
foreach($this->pks as &$pk)
|
||||
{
|
||||
if($pk->key === true)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if the definition describes an entity or not
|
||||
*
|
||||
* @param string $definition
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isEntity($definition)
|
||||
{
|
||||
return strpos($definition, ":")? false: true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a property to the current entity
|
||||
*
|
||||
* @global $_MIND
|
||||
* @param MindProperty $property
|
||||
* @return MindEntity
|
||||
*/
|
||||
public function addProperty(MindProperty $property)
|
||||
{
|
||||
GLOBAL $_MIND;
|
||||
$this->properties[$property->name]= $property;
|
||||
if($property->key)
|
||||
$this->pks[$property->name]= $property;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if the current entity has a specified property
|
||||
*
|
||||
* @param string $propName
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasProperty($propName)
|
||||
{
|
||||
return isset($this->properties[$propName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a property from the current entity
|
||||
*
|
||||
* @param string $propName
|
||||
* @return boolean
|
||||
*/
|
||||
public function removeProperty($propName)
|
||||
{
|
||||
if(isset($this->properties[$propName]))
|
||||
unset($this->properties[$propName]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines another entity pointed/refered by this entity
|
||||
* @param MindEntity $ref
|
||||
* @return MindEntity
|
||||
*/
|
||||
public function addRefTo(MindEntity &$ref)
|
||||
{
|
||||
$this->refTo[$ref->name]= &$ref;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a reference TO
|
||||
* @param type $refName
|
||||
* @return MindEntity
|
||||
*/
|
||||
public function removeRefTo($refName)
|
||||
{
|
||||
unset($this->refTo[$refName]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that another entity is pointing to this one
|
||||
* @param MindEntity $ref
|
||||
* @return MindEntity
|
||||
*/
|
||||
public function addRefBy(MindEntity &$ref)
|
||||
{
|
||||
$this->refBy[$ref->name]= &$ref;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a reference BY
|
||||
* @param type $refName
|
||||
* @return MindEntity
|
||||
*/
|
||||
public function removeRefBy($refName)
|
||||
{
|
||||
unset($this->refBy[$refName]);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a reference to the current entity
|
||||
*
|
||||
* @param MindRelation $rel
|
||||
* @return MindEntity
|
||||
*/
|
||||
public function addRef(MindRelation &$rel)
|
||||
{
|
||||
$this->relations[$rel->name]= &$rel;
|
||||
if($rel->focus->name == $this->name)
|
||||
{
|
||||
if($rel->max == QUANTIFIER_MAX_MAX)
|
||||
{
|
||||
$this->relevance++;
|
||||
$this->addRefBy($rel->rel);
|
||||
}else
|
||||
$this->addRefTo($rel->rel);
|
||||
}else{
|
||||
if($rel->max == QUANTIFIER_MAX_MIN)
|
||||
{
|
||||
$this->relevance++;
|
||||
$this->addRefBy($rel->focus);
|
||||
}else
|
||||
$this->addRefTo($rel->focus);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor. It receives the name of the new entity
|
||||
* @param string $word
|
||||
*/
|
||||
public function MindEntity($word)
|
||||
{
|
||||
$this->name= (string)$word;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
/**
|
||||
* Description of MindPlugin
|
||||
*
|
||||
* @author felipe
|
||||
*/
|
||||
class MindPlugin
|
||||
{
|
||||
public $trigger= null;
|
||||
public $event= 'after';
|
||||
public $name;
|
||||
public $version;
|
||||
public $description;
|
||||
public $links= Array();
|
||||
|
||||
public function setTrigger($trg)
|
||||
{
|
||||
$this->trigger= $trg;
|
||||
return $this;
|
||||
}
|
||||
public function setEvent($evt)
|
||||
{
|
||||
$this->event= $evt=='before'? 'before':'after';
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a MindPlugin based object to the
|
||||
* plugins and triggers list
|
||||
*
|
||||
* @param MindPlugin $plugin
|
||||
*/
|
||||
static function addPlugin(&$plugin)
|
||||
{
|
||||
if(in_array($plugin->trigger, Mind::$triggers))
|
||||
{
|
||||
if(!isset(Mind::$pluginList[$plugin->trigger]))
|
||||
Mind::$pluginList[$plugin->trigger]= Array( 'before'=>Array(),
|
||||
'after'=>Array());
|
||||
Mind::$pluginList[$plugin->trigger][$plugin->event][]= $plugin;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
<?php
|
||||
/**
|
||||
* Will keep and deal with the current opened project
|
||||
*
|
||||
* @author felipe
|
||||
*/
|
||||
class MindProject extends VersionManager{
|
||||
|
||||
public static $sourceContent= Array();
|
||||
public static $currentSource= null;
|
||||
|
||||
/**
|
||||
* Returns true if the project already exists,
|
||||
* false, otherwise
|
||||
*
|
||||
* @global Mind $_MIND
|
||||
* @param String $project
|
||||
* @return boolean
|
||||
*/
|
||||
static function hasProject($project)
|
||||
{
|
||||
GLOBAL $_MIND;
|
||||
$projectfile= Mind::$projectsDir.$project;
|
||||
$noAccess= true;
|
||||
|
||||
$db= new MindDB();
|
||||
$hasProject= "SELECT pk_project,
|
||||
project.name as name
|
||||
from project_user,
|
||||
project
|
||||
where fk_user= ".$_SESSION['pk_user']."
|
||||
and project.name = '".$project."'
|
||||
and fk_project = pk_project
|
||||
";
|
||||
$data= $db->query($hasProject);
|
||||
if(sizeof($data)>0)
|
||||
foreach($data as $row)
|
||||
{
|
||||
$noAccess= false;
|
||||
break;
|
||||
}
|
||||
|
||||
if(!file_exists($projectfile) || $noAccess)
|
||||
{
|
||||
Mind::write('noProject', true, $project);
|
||||
return false;
|
||||
}
|
||||
return $row;
|
||||
}
|
||||
|
||||
public static function loadIdiom($idiom)
|
||||
{
|
||||
$idiom= str_replace('\\', DIRECTORY_SEPARATOR, $idiom);
|
||||
$langPath= LANG_PATH.$idiom.'/';
|
||||
|
||||
set_include_path(get_include_path() . PATH_SEPARATOR . $langPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads data from the passed project
|
||||
*
|
||||
* @param AssocArray $p
|
||||
* @return boolean
|
||||
*/
|
||||
public static function openProject($p)
|
||||
{
|
||||
GLOBAL $_REQ;
|
||||
$_SESSION['currentProject']= $p['pk_project'];
|
||||
$_SESSION['currentProjectName']= $p['name'];
|
||||
$_SESSION['currentProjectDir']= Mind::$projectsDir.$p['name'];
|
||||
$p['path']= Mind::$projectsDir.$p['name'];
|
||||
$p['sources']= Mind::$projectsDir.$p['name'].'/sources';
|
||||
$ini= parse_ini_file(Mind::$projectsDir.$p['name'].'/mind.ini');
|
||||
$p= array_merge($p, $ini);
|
||||
|
||||
Mind::$currentProject= $p;
|
||||
Mind::$curLang= Mind::$currentProject['idiom'];
|
||||
Mind::$content= '';
|
||||
|
||||
// loading entities and relations from cache
|
||||
$path= Mind::$currentProject['path']."/temp/";
|
||||
$entities= $path."entities~";
|
||||
$relations= $path."relations~";
|
||||
if($_REQ['env']=='shell')
|
||||
{
|
||||
if(file_exists($entities) && $f= fopen($entities, 'r'))
|
||||
{
|
||||
while (($buffer = fgets($f, 51200)) !== false)
|
||||
{
|
||||
if($tmpObj= @unserialize($buffer))
|
||||
Analyst::$entities[$tmpObj->name]= $tmpObj;
|
||||
}
|
||||
$f= fopen($relations, 'r');
|
||||
while (($buffer = fgets($f, 51200)) !== false)
|
||||
{
|
||||
if($tmpObj= @unserialize($buffer))
|
||||
Analyst::$relations[$tmpObj->name]= $tmpObj;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Mind::write('projectOpened', true, $p['name']);
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function loadSource($source='main')
|
||||
{
|
||||
$srcs= Mind::$currentProject['sources'];
|
||||
if(file_exists($srcs.'/'.$source.'.mnd'))
|
||||
{
|
||||
$main= file_get_contents($srcs.'/'.$source.'.mnd');
|
||||
return $main;
|
||||
}
|
||||
Mind::write('sourceFileNotFound', true, $source);
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function import($src)
|
||||
{
|
||||
self::$sourceContent[$src]= $src;
|
||||
$extraFiles[]= preg_match_all(IMPORT_SOURCE, $src, $matches);
|
||||
$matches= $matches[0];
|
||||
foreach($matches as &$import)
|
||||
{
|
||||
$import= substr($import, 8);
|
||||
$extraContent= self::loadSource($import);
|
||||
self::import($extraContent);
|
||||
}
|
||||
}
|
||||
|
||||
public static function loadSources()
|
||||
{
|
||||
$main= self::loadSource();
|
||||
self::import($main);
|
||||
}
|
||||
|
||||
public static function setUp()
|
||||
{
|
||||
parent::setUp();
|
||||
self::$sourceContent= false;
|
||||
self::$currentSource= null;
|
||||
self::$sourceContent= Array();
|
||||
Analyst::reset();
|
||||
|
||||
MindTimer::init();
|
||||
Mind::$lexer= new Lexer();
|
||||
self::loadSources();
|
||||
}
|
||||
public static function analyze($autoCommit=false)
|
||||
{
|
||||
self::setUp();
|
||||
|
||||
foreach(self::$sourceContent as $k=>&$content)
|
||||
{
|
||||
$currentSource= $k;
|
||||
// search for special/unknown characters
|
||||
if(!Mind::$lexer->sweep($content))
|
||||
return false;
|
||||
// keep substantives and verbs on their canonical form
|
||||
if(!Mind::$canonic->sweep())
|
||||
return false;
|
||||
// mark specific tokens
|
||||
if(!Mind::$tokenizer->sweep())
|
||||
return false;
|
||||
// prepares the model to be used to process data
|
||||
// it transforms the original text into the mind code
|
||||
// itself
|
||||
if(!Mind::$syntaxer->sweep())
|
||||
return false;
|
||||
|
||||
if($autoCommit)
|
||||
{
|
||||
MindProject::commit();
|
||||
}
|
||||
}
|
||||
|
||||
MindTimer::end();
|
||||
|
||||
// do NOT print it if you have MANY entities, the webbrowser freezes
|
||||
//print_r(Analyst::getUniverse());
|
||||
echo Analyst::printWhatYouGet();
|
||||
echo "--------------------\n";
|
||||
echo "Time: ".
|
||||
MindTimer::getElapsedTime().
|
||||
"s\n";
|
||||
$memory= ((memory_get_usage() / 1024)/1024);
|
||||
$memory= number_format($memory, 2);
|
||||
echo "Memory: ".$memory."MBs\n";
|
||||
|
||||
self::cleanUp();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,308 @@
|
||||
<?php
|
||||
/**
|
||||
* Represents the property of an entity(MindEntity::properties)
|
||||
*
|
||||
* @author felipe
|
||||
*/
|
||||
class MindProperty {
|
||||
|
||||
public $definition= "";
|
||||
private $name = false;
|
||||
private $type = "text";
|
||||
private $size = 0;
|
||||
private $options = Array();
|
||||
private $default = null;
|
||||
private $unique = false;
|
||||
private $required = false;
|
||||
public $refTo = false;
|
||||
public $refBy = Array();
|
||||
public $key = false;
|
||||
public $comment = false;
|
||||
|
||||
/**
|
||||
* Sets the entity and property the current property is referred to.
|
||||
* @param MindEntity $entity
|
||||
* @param MindProperty $prop
|
||||
* @return MindProperty
|
||||
*/
|
||||
public function setRefTo(MindEntity $entity, MindProperty $prop)
|
||||
{
|
||||
$this->refTo= Array($entity, $prop);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the properties
|
||||
* @param string $what
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($what)
|
||||
{
|
||||
if(isset($this->$what))
|
||||
return $this->$what;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set name
|
||||
* @param string $val
|
||||
* @return MindProperty
|
||||
*/
|
||||
public function setName($val)
|
||||
{
|
||||
$this->name= (string)$val;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set size
|
||||
* @param int/float $val
|
||||
* @return MindProperty
|
||||
*/
|
||||
public function setSize($val)
|
||||
{
|
||||
$this->size= $val;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Options
|
||||
* @param Array $val
|
||||
* @return MindProperty
|
||||
*/
|
||||
public function setOptions($val)
|
||||
{
|
||||
$this->options= $val;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set type
|
||||
* @param string $val
|
||||
* @return MindProperty
|
||||
*/
|
||||
public function setType($val)
|
||||
{
|
||||
$this->type= (string)$val;
|
||||
$tmpType= self::isKnown($this->type);
|
||||
if(!$tmpType)
|
||||
{
|
||||
//TODO: Darwin::add($this->type);
|
||||
Darwin::addDoubt($this->type, 'dataType');
|
||||
return false;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Default value
|
||||
* @param string $val
|
||||
* @return MindProperty
|
||||
*/
|
||||
public function setDefault($val)
|
||||
{
|
||||
$this->default= (string)$val;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set as unique or not
|
||||
* @param boolean $val
|
||||
* @return MindProperty
|
||||
*/
|
||||
public function setUnique($val)
|
||||
{
|
||||
$this->unique= $val? true: false;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set wheter the property is required(not null) or not
|
||||
* @param boolean $val
|
||||
* @return MindProperty
|
||||
*/
|
||||
public function setRequired($val)
|
||||
{
|
||||
$this->required= $val? true: false;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the property as a key
|
||||
* @return MindProperty
|
||||
*/
|
||||
public function setAsKey()
|
||||
{
|
||||
$this->key= true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the property as a weak key
|
||||
* @return MindProperty
|
||||
*/
|
||||
public function setAsWeakKey()
|
||||
{
|
||||
$this->key= 'weak';
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the string sent indicates that it is about a property
|
||||
* @param String $definition
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isProperty($definition)
|
||||
{
|
||||
return strpos($definition, ":")? true: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the passed property type is known by the system.
|
||||
* If it is not known, then it stores it as a doubt
|
||||
*
|
||||
* @param String $type
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isKnown($type)
|
||||
{
|
||||
foreach(Tokenizer::$dataTypes as $k=>$validTypes)
|
||||
if(in_array($type, $validTypes))
|
||||
return $k;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies on the passed string, if it indicates that the current
|
||||
* property definition should be required or not
|
||||
*
|
||||
* @param String $expression
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isRequired($expression)
|
||||
{
|
||||
$rx= "/".implode('|', Tokenizer::$qualifiers['notnull'])."/i";
|
||||
return (preg_match($rx, $expression))? true: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies on the passed string if it indicates that the current
|
||||
* property definition should be unique or not
|
||||
*
|
||||
* @param String $expression
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isUnique($expression)
|
||||
{
|
||||
$rx= "/".implode('|', Tokenizer::$qualifiers['unique'])."/i";
|
||||
return (preg_match($rx, $expression))? true: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true in case the passed expression represent a property
|
||||
* definition, which has terms saying it should(forcedly) treated as
|
||||
* a key
|
||||
*
|
||||
* @param String $expression
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isKey($expression)
|
||||
{
|
||||
$rx= "/".implode('|', Tokenizer::$qualifiers['key'])."/i";
|
||||
return (preg_match($rx, $expression))? true: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method parses the current property definition due to
|
||||
* identify its specification, like size, type or if it is
|
||||
* not null
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
private function parse()
|
||||
{
|
||||
$str= $this->definition;
|
||||
$one= 1;
|
||||
|
||||
// identifying the data type
|
||||
$typeStart= strpos($str, ':')+1;
|
||||
$typeEnd= strpos($str, '(');
|
||||
$typeEnd= $typeEnd? $typeEnd- $typeStart: strLen($str);
|
||||
$type= substr($str, $typeStart, $typeEnd);
|
||||
$this->setType($type);
|
||||
|
||||
// identifying the name
|
||||
$this->setName(Mind::$lexer->fixWordChars(substr($str, 0, $typeStart-1)));
|
||||
|
||||
// identifying details
|
||||
if(preg_match(PROP_DETAILS, $str, $details))
|
||||
{
|
||||
$details= $details[0];
|
||||
|
||||
// identifying the default value
|
||||
if(preg_match(PROP_DEFAULT, $details, $default))
|
||||
{
|
||||
$default= $default[0];
|
||||
$details= str_replace($default, "", $str, $one);
|
||||
|
||||
// checking if the default value isn't a value or a function call
|
||||
if($default[1]=='=' || strtolower(substr($default, 1, 5)) == EXEC_STRING)
|
||||
{
|
||||
$default= preg_replace(PROP_DEFEXEC, "", $default);
|
||||
}
|
||||
|
||||
$this->setDefault($default);
|
||||
}
|
||||
|
||||
// identifying if it is required
|
||||
if(self::isRequired($details))
|
||||
$this->setRequired(true);
|
||||
|
||||
// identifying if it is a forced key
|
||||
if(self::isKey($details))
|
||||
$this->setAsKey();
|
||||
|
||||
// identifying its size
|
||||
if(preg_match(PROP_SIZE, $details, $size))
|
||||
$this->setSize($size[0]);
|
||||
|
||||
// identifying the options
|
||||
if(preg_match(PROP_OPTIONS, $details, $options))
|
||||
{
|
||||
$options= explode('|',
|
||||
preg_replace(PROP_OPTIONS_CLEAR,
|
||||
'',
|
||||
$options[0])
|
||||
);
|
||||
foreach($options as &$opt)
|
||||
{
|
||||
$opt= explode('=', $opt, 2);
|
||||
}
|
||||
$this->setOptions($options);
|
||||
}
|
||||
|
||||
// checking if it is unique
|
||||
if(self::isUnique($details))
|
||||
{
|
||||
$this->setUnique(true);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* The constructor itself
|
||||
* IT receives by paramether, the definition string, to parse the
|
||||
* property's characteristics and store it on itself
|
||||
*
|
||||
* @param String $definition
|
||||
*/
|
||||
public function MindProperty($definition=false)
|
||||
{
|
||||
if($definition)
|
||||
{
|
||||
$this->definition= $definition;
|
||||
$this->parse();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
/**
|
||||
* Represents a relation between two Entities
|
||||
*
|
||||
* @author felipe
|
||||
*/
|
||||
class MindRelation {
|
||||
|
||||
public $name;
|
||||
private $linkTypes = Array('possibility', 'must', 'action');
|
||||
private $linkType = 'action';
|
||||
private $quantifiers = Array(0, 1, 'n');
|
||||
private $min = 0;
|
||||
private $max = 'n';
|
||||
private $verb = '';
|
||||
private $focus = null;
|
||||
private $rel = null;
|
||||
public $opposite = null;
|
||||
public $uniqueRef = false;
|
||||
public $treated = false; //to be used by Normalizer
|
||||
|
||||
/**
|
||||
* Renames a relation, replacing it into the Analyst relations list
|
||||
*
|
||||
* @param string $newName
|
||||
* @return MindRelation
|
||||
*/
|
||||
public function rename($newName)
|
||||
{
|
||||
Analyst::$relations[$newName]= Analyst::$relations[$this->name];
|
||||
Analyst::$relations[$this->name]= false;
|
||||
$this->name= (string)$newName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the relative entity
|
||||
*
|
||||
* @param MindEntity $rel
|
||||
* @return MindRelation
|
||||
*/
|
||||
public function setRel(MindEntity &$rel)
|
||||
{
|
||||
$this->rel= &$rel;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the focused entity
|
||||
*
|
||||
* @param MindEntity $focus
|
||||
* @return MindRelation
|
||||
*/
|
||||
public function setFocus(MindEntity &$focus)
|
||||
{
|
||||
$this->focus= &$focus;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return properties from the current relation
|
||||
* These properties were set to private due to set limitations
|
||||
* but they may be open for get operations
|
||||
*
|
||||
* @param String $what
|
||||
* @return Mixed
|
||||
*/
|
||||
public function __get($what)
|
||||
{
|
||||
if(isset($this->$what))
|
||||
return $this->$what;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of link(possibility, action or must)
|
||||
* @param string $linkType
|
||||
* @return MindRelation
|
||||
*/
|
||||
public function setLinkType($linkType)
|
||||
{
|
||||
if(in_array($linkType, $this->linkTypes))
|
||||
{
|
||||
$this->linkType= $linkType;
|
||||
return $this;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the minimun value of the relation(0 or 1)
|
||||
* @param Mixed $min
|
||||
* @return MindRelation
|
||||
*/
|
||||
public function setMin($min)
|
||||
{
|
||||
if($min === 0 || $min === 1)
|
||||
{
|
||||
$this->min= $min;
|
||||
return $this;
|
||||
}
|
||||
throw new Exception("Invalid minimum quantifier: ".$min, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximun value for the relation(1 or n)
|
||||
* @param mixed $max
|
||||
* @return MindRelation
|
||||
*/
|
||||
public function setMax($max)
|
||||
{
|
||||
if($max == 1 || $max == 'n')
|
||||
{
|
||||
$this->max= $max;
|
||||
return $this;
|
||||
}
|
||||
throw new Exception("Invalid maximum quantifier: ".$max, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines which verb was used to define the current instruction
|
||||
*
|
||||
* @param string $verb
|
||||
* @return MindRelation
|
||||
*/
|
||||
public function setUsedVerb($verb)
|
||||
{
|
||||
$this->verb= (string)$verb;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies which entities are envolved in this relation
|
||||
*
|
||||
* @param MindEntity $focus
|
||||
* @param MindEntity $rel
|
||||
* @return MindRelation
|
||||
*/
|
||||
public function setEntities(MindEntity &$focus, MindEntity &$rel)
|
||||
{
|
||||
$this->focus= &$focus;
|
||||
$this->rel= &$rel;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The constructor, receiving the name of the relation
|
||||
* @param string $relName
|
||||
*/
|
||||
public function MindRelation($relName)
|
||||
{
|
||||
$this->name= (string)$relName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
class MindSpeaker
|
||||
{
|
||||
/**
|
||||
* This method returns or outputs messages using the L10N library
|
||||
* You can pass a rich string with %s, %i, etc, sending extra parameters
|
||||
* If the boolean flag $echo is sent, it prints it to the output, otherwise,
|
||||
* only returns it
|
||||
*
|
||||
* @param String $k
|
||||
* @param Bolean $echo
|
||||
* @param mixed... extra parameter to be treated in the string
|
||||
* @return String
|
||||
*/
|
||||
public static function write($k, $echo=true, $args=false)
|
||||
{
|
||||
$msg= Mind::$l10n->getMessage($k);
|
||||
if(!$msg)
|
||||
{
|
||||
$msg= Mind::message("L10N: Message $k does not exist", '[Fail]', false);
|
||||
}
|
||||
if(!is_array($args))
|
||||
$args= func_get_args();
|
||||
$parms= "";
|
||||
if(sizeof($args)>2)
|
||||
{
|
||||
for($i=2; $i<sizeof($args); $i++)
|
||||
{
|
||||
$parms.= ', "'.$args[$i].'"';
|
||||
}
|
||||
$parms= '"'.$msg.'"'.$parms;
|
||||
eval("\$print= sprintf(".$parms.");");
|
||||
}else{
|
||||
$print= $msg;
|
||||
}
|
||||
$count= 1;
|
||||
while(strlen($print) >= _CONSOLE_LINE_LENGTH_ && strpos($print, '..')>-1)
|
||||
{
|
||||
$print= preg_replace("/\.\./", '.', $print, $count);
|
||||
}
|
||||
if($echo)
|
||||
echo $print;
|
||||
return $msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns or prints a message formated to represent failures, passes
|
||||
* or any kind of alert
|
||||
*
|
||||
* @param String $message The message itself
|
||||
* @param String $status The status to be shown in the end of the message
|
||||
* @param Boolean $echo if it should be printed or not
|
||||
* @return string
|
||||
*/
|
||||
public static function message($message, $status, $echo=true)
|
||||
{
|
||||
$msg= str_pad($message, _CONSOLE_LINE_LENGTH_ - strlen($status), '.').$status."\n";
|
||||
if($echo)
|
||||
echo $msg;
|
||||
return $msg;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* Description of MindTimer
|
||||
*
|
||||
* @author felipe
|
||||
*
|
||||
*/
|
||||
abstract class MindTimer {
|
||||
|
||||
public static $startingTime= 0;
|
||||
public static $endingTime = 0;
|
||||
|
||||
public static function getElapsedTime()
|
||||
{
|
||||
return number_format(((float)self::$endingTime) - ((float)self::$startingTime), 4);
|
||||
}
|
||||
|
||||
public static function init()
|
||||
{
|
||||
$startingTime= microtime();
|
||||
$startingTime= explode(' ', $startingTime);
|
||||
$startingTime= $startingTime[1] + $startingTime[0];
|
||||
self::$startingTime= $startingTime;
|
||||
}
|
||||
public static function end()
|
||||
{
|
||||
$endingTime= microtime();
|
||||
$endingTime= explode(' ', $endingTime);
|
||||
$endingTime= $endingTime[1] + $endingTime[0];
|
||||
self::$endingTime= $endingTime;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* This class takes care of the version control methods
|
||||
*
|
||||
* @author felipe
|
||||
*/
|
||||
class VersionManager {
|
||||
public static function commit()
|
||||
{
|
||||
// TODO: commiting a project should save the current
|
||||
// situation of the current project
|
||||
echo "COMMITING";
|
||||
}
|
||||
|
||||
public static function setUp()
|
||||
{
|
||||
}
|
||||
|
||||
public static function cleanUp()
|
||||
{
|
||||
$path= Mind::$currentProject['path']."/temp/";
|
||||
$entities= $path."entities~";
|
||||
$relations= $path."relations~";
|
||||
|
||||
$fEnt= fopen($entities, "w+");
|
||||
$fRel= fopen($relations, "w+");
|
||||
if(!$fEnt)
|
||||
{
|
||||
Mind::write('permissionDenied');
|
||||
return;
|
||||
}
|
||||
ftruncate($fEnt, 0);
|
||||
ftruncate($fRel, 0);
|
||||
@chmod($entities, 0777);
|
||||
@chmod($relations, 0777);
|
||||
|
||||
|
||||
foreach(Analyst::$entities as &$entity)
|
||||
{
|
||||
file_put_contents($entities, serialize($entity)."\n", FILE_APPEND);
|
||||
}
|
||||
|
||||
foreach(Analyst::$relations as &$relation)
|
||||
{
|
||||
file_put_contents($relations, serialize($relation)."\n", FILE_APPEND);
|
||||
}
|
||||
fclose($fEnt);
|
||||
fclose($fRel);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* Description of Darwin
|
||||
*
|
||||
* @author felipe
|
||||
*/
|
||||
class Darwin {
|
||||
public static function addDoubt($context, $type)
|
||||
{
|
||||
echo "DUVIDAAAA";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,261 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of TheWebMind 3rd generation.
|
||||
*
|
||||
* Lexer, within the Cortex/Lexer packages.<br/>
|
||||
* Notice that, these packages are being used only for documentation,
|
||||
* not to organize the classes.
|
||||
*
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
* @license licenses/mind3rd.license
|
||||
*/
|
||||
/**
|
||||
* This class sweeps the passed words and validates if
|
||||
* its content matches with the valid chars
|
||||
*
|
||||
* @package Cortex
|
||||
* @subpackage Lexer
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
*/
|
||||
class Lexer
|
||||
{
|
||||
private $validChars;
|
||||
private $replacements;
|
||||
public $lang= 'en';
|
||||
public $originalContent= '';
|
||||
private $content= "";
|
||||
private $tokens= Array();
|
||||
private $glue= '';
|
||||
|
||||
/**
|
||||
* Splits a string using utf8 format.
|
||||
*
|
||||
* Thanks to saeedco (no more information found about him!) I had to
|
||||
* change only a few things on this method.
|
||||
* Source: http://br2.php.net/manual/en/function.str-split.php#83331
|
||||
* Idioms it is supposed to work properly
|
||||
* English
|
||||
* Chinese
|
||||
* Japanese
|
||||
* Arabic
|
||||
* Turkish
|
||||
* Urdu
|
||||
* Russian
|
||||
* Persian
|
||||
* Portuguese
|
||||
*
|
||||
* Of course, if you find any problem, report it to us :)
|
||||
*
|
||||
* @param String $str The string to be splitted.
|
||||
* @return array
|
||||
*/
|
||||
private function str_split_utf8($str) {
|
||||
// place each character of the string into and array
|
||||
$split=1;
|
||||
$array = array();
|
||||
|
||||
/*
|
||||
* SOMEONE HERE, PLEASE! Explain that for me!
|
||||
* ONLY the 'ó' char isnt working when treated...even 'Ó' is!
|
||||
* ALL the other characteres are working just fine!
|
||||
* Someone who could fix it in a better way, please
|
||||
*/
|
||||
$str= str_replace('ó', 'o', $str);
|
||||
|
||||
for ( $i=0; $i < strlen( $str ); ){
|
||||
$value = ord($str[$i]);
|
||||
if($value > 127){
|
||||
if($value >= 192 && $value <= 223)
|
||||
$split=2;
|
||||
elseif($value >= 224 && $value <= 239)
|
||||
$split=3;
|
||||
elseif($value >= 240 && $value <= 247)
|
||||
$split=4;
|
||||
}else{
|
||||
$split=1;
|
||||
}
|
||||
$key = NULL;
|
||||
for ( $j = 0; $j < $split; $j++, $i++ ) {
|
||||
$key .= $str[$i];
|
||||
}
|
||||
array_push( $array, $key );
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the sent char.
|
||||
*
|
||||
* Verifies wether the passed char is a valid char for
|
||||
* that idiom or not.
|
||||
*
|
||||
* @param char $letter
|
||||
* @return boolean
|
||||
*/
|
||||
private function isValidChar($letter)
|
||||
{
|
||||
$letter= ($letter);
|
||||
for($k=0; $k<strlen($this->validChars); $k++)
|
||||
{
|
||||
if($this->validChars[$k] == $letter
|
||||
||
|
||||
ord($this->validChars[$k]) == ord($letter)
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares names for their use.
|
||||
*
|
||||
* Parses the string encoding and returns a valid name
|
||||
* to be used on databases or restricted names
|
||||
*
|
||||
* @param String $word
|
||||
* @return String
|
||||
*/
|
||||
public function fixWordChars($word)
|
||||
{
|
||||
$word= preg_replace(FIX_PROP_NAME, '', strtolower($word));
|
||||
|
||||
$word= $this->str_split_utf8($word);
|
||||
$str= "";
|
||||
for($i=0, $j=sizeof($word); $i<$j; $i++)
|
||||
{
|
||||
$str.= $this->translateChars($word[$i]);
|
||||
}
|
||||
return strtolower($str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes the passed string replacing special chars.
|
||||
*
|
||||
* This method takes each special char and replaces it with
|
||||
* the respective char specified in the choosen idiom.
|
||||
*
|
||||
* @param string $str
|
||||
* @return string
|
||||
*/
|
||||
public function translateChars($str)
|
||||
{
|
||||
$from = $this->replacements[0];
|
||||
$to = $this->replacements[1];
|
||||
return strtr(utf8_decode($str), utf8_decode($from), $to);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sweeps through the content and apply the lexer rules.
|
||||
*
|
||||
* Performs a sweep over the sent content and replace any
|
||||
* special char, also removing any invalid char.
|
||||
* @param string $content
|
||||
* @return string The cleaned content
|
||||
*/
|
||||
public function sweep($content)
|
||||
{
|
||||
Mind::$originalContent= $content;
|
||||
// let's treat the single line comments
|
||||
$content= preg_replace(SINGLE_COMMENT, '', $content);
|
||||
|
||||
// now, it's time to start working with the data
|
||||
$this->content= trim(str_replace("\n", ' ', $content));
|
||||
while(strstr($this->content, ' ')!==false) // ignoring tabs
|
||||
$this->content= str_replace(' ', ' ', $this->content);
|
||||
while(strstr($this->content, ' ')!==false) // ignoring multiple spaces
|
||||
$this->content= str_replace(' ', ' ', $this->content);
|
||||
|
||||
$this->originalContent= $this->content;
|
||||
$this->content= $this->str_split_utf8($this->content);
|
||||
|
||||
// the fixed content;
|
||||
$fixed= "";
|
||||
|
||||
// for each charactere on the content
|
||||
// let's remove the invalid ones
|
||||
$inside= 0;
|
||||
for($i=0, $j=sizeof($this->content); $i<$j; ++$i)
|
||||
{
|
||||
$letter= $this->content[$i];
|
||||
if($this->isValidChar($letter))
|
||||
{
|
||||
if($letter == '(')
|
||||
$inside++;
|
||||
if($letter == ')' && $inside>0)
|
||||
$inside--;
|
||||
if($inside > 0)
|
||||
{
|
||||
if($letter == ' ')
|
||||
$letter= $this->tmpSpace;
|
||||
if($letter == ',')
|
||||
$letter= $this->tmpComa;
|
||||
if($letter == '.')
|
||||
$letter= $this->tmpPeriod;
|
||||
}
|
||||
|
||||
$fixed.= $letter;
|
||||
}
|
||||
}
|
||||
|
||||
// preparing the tokens
|
||||
foreach($this->tokens as $char=>$token)
|
||||
{
|
||||
$fixed= str_replace($char, $token, $fixed);
|
||||
}
|
||||
|
||||
// but content between parentheses should be left with
|
||||
// normal spaces, instead of the space token
|
||||
// restoring the initial format for attribute details
|
||||
$fixed= str_replace($this->tmpSpace, " ", $fixed);
|
||||
$fixed= str_replace($this->tmpComa, ",", $fixed);
|
||||
$fixed= str_replace($this->tmpPeriod, ".", $fixed);
|
||||
|
||||
// let's deal with the \n and multiline comments
|
||||
$fixed= preg_replace(NEW_LINE, $this->tokens[' '], $fixed);
|
||||
$fixed= preg_replace(MULTILINE_COMMENT, '', $fixed);
|
||||
|
||||
$exploded= explode($this->tokens[' '], $fixed);
|
||||
|
||||
$fixed= array_filter($exploded);
|
||||
|
||||
Mind::$content= $fixed;
|
||||
$this->content= "";
|
||||
|
||||
return sizeof(Mind::$content)>0? Mind::$content: false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The constructor
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
GLOBAL $_MIND;
|
||||
$this->glue = chr('176');
|
||||
$this->tmpSpace = chr('177');
|
||||
$this->tmpComa = chr('178');
|
||||
$this->tmpPeriod = chr('179');
|
||||
$this->lang = Mind::$currentProject['idiom'];
|
||||
$xml = simplexml_load_file(Mind::$langPath.$this->lang.'/lexics.xml');
|
||||
|
||||
$this->validChars = (string)$xml->validchars->lower;
|
||||
$this->validChars.= (string)$xml->validchars->upper;
|
||||
$this->validChars.= (string)$xml->validchars->special;
|
||||
$this->validChars.= (string)$xml->validchars->numbers;
|
||||
$this->validChars.= (string)$xml->validchars->symbols;
|
||||
$this->validChars.= " ";
|
||||
|
||||
$this->replacements= Array();
|
||||
$this->replacements[0]= (string)$xml->replacements->from;
|
||||
$this->replacements[1]= (string)$xml->replacements->to;
|
||||
|
||||
$this->tokens[' ']= $this->glue;
|
||||
$this->tokens['.']= $this->glue.'.'.$this->glue;
|
||||
$this->tokens[',']= $this->glue.','.$this->glue;
|
||||
|
||||
// prepare it to the next step
|
||||
Mind::$canonic= new Canonic();
|
||||
}
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,272 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of theWebMind 3rd generation.
|
||||
*
|
||||
* Analyst components, within the Cortex/Analyst packages.<br/>
|
||||
* Notice that, these packages are being used only for documentation,
|
||||
* not to organize the classes.
|
||||
*
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
* @license licenses/mind3rd.license
|
||||
* @filesource
|
||||
*/
|
||||
/**
|
||||
* This is an abstract class to be used to analyze the project.
|
||||
*
|
||||
* @package Cortex
|
||||
* @subpackage Analyst
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
*/
|
||||
abstract class Analysis {
|
||||
|
||||
public static $entities = Array();
|
||||
public static $relations= Array();
|
||||
public static $focused = Array();
|
||||
|
||||
/**
|
||||
* Returns an array with the names of all entities.
|
||||
*
|
||||
* Gets an Array of the names of all the focused entities on
|
||||
* the current expression.
|
||||
* @return Array
|
||||
*/
|
||||
public static function getFocusedNames()
|
||||
{
|
||||
$focused= Array();
|
||||
foreach(self::$focused as $focus)
|
||||
$focused[]= $focus->name;
|
||||
return $focused;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the current focused entities.
|
||||
*/
|
||||
public static function clearFocused()
|
||||
{
|
||||
self::$focused = false;
|
||||
self::$focused = Array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an entity to the focused entities list.
|
||||
* @param MindEntity &$entity The entity to be added to focus
|
||||
*/
|
||||
public static function addToFocus(MindEntity &$entity)
|
||||
{
|
||||
self::$focused[$entity->name]= $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a relation to the focused list.
|
||||
*
|
||||
* Adds a relation between all the focused entities specified in the
|
||||
* current expression and the passed $rel entity
|
||||
*
|
||||
* @param MindEntity &$rel The entity to be added
|
||||
* @param String $linkType The type of like(action, possibility or must)
|
||||
* @param String $linkVerb The verb used to identify the relation
|
||||
* @param Mixed $min The minimun quantifier
|
||||
* @param Mixed $max The maximun quantifier
|
||||
* @param boolean [$uniqueRef] If it should be an unique referation
|
||||
* @return MindRelationCollection An array of all the created relations
|
||||
*/
|
||||
public static function &addRelationToFocused(MindEntity &$rel, $linkType,
|
||||
$linkVerb, $min, $max,
|
||||
$uniqueRef=false)
|
||||
{
|
||||
// for each focused entity
|
||||
foreach(self::$focused as &$focus)
|
||||
{
|
||||
$curRelation= self::addRelationBetween($focus, $rel, $linkType, $linkVerb, $min, $max);
|
||||
$arRet[]= &$curRelation;
|
||||
}
|
||||
return $arRet;
|
||||
}
|
||||
|
||||
public static function &addRelationBetween (MindEntity $focus,
|
||||
MindEntity &$rel, $linkType,
|
||||
$linkVerb, $min, $max,
|
||||
$uniqueRef=false)
|
||||
{
|
||||
$arRet= Array();
|
||||
/*
|
||||
* we will use this relationName as index on an
|
||||
* indexed array to speed up the search for
|
||||
* relations in the future
|
||||
*/
|
||||
$relationName= $focus->name."_".$rel->name;
|
||||
|
||||
// let's create the relation itself
|
||||
$curRelation= new MindRelation($relationName);
|
||||
|
||||
$curRelation->setLinkType($linkType)
|
||||
->setMin($min)
|
||||
->setMax($max)
|
||||
->setUsedVerb($linkVerb)
|
||||
->setEntities(
|
||||
self::$entities[$focus->name],
|
||||
self::$entities[$rel->name]);
|
||||
// now, both entities will POINT to the same relation
|
||||
$focus->addRef($curRelation);
|
||||
$rel->addRef($curRelation);
|
||||
$curRelation->uniqueRef= $uniqueRef;
|
||||
|
||||
// and let's use the relation name as index, as said before
|
||||
self::$relations[$relationName]= $curRelation;
|
||||
return $curRelation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the passed property to all the focused entities.
|
||||
*
|
||||
* @param MindProperty &$prop The property to be added to the focused entities.
|
||||
*/
|
||||
public static function addPropertyToFocused(MindProperty &$prop)
|
||||
{
|
||||
// for each focused entity
|
||||
foreach(self::$focused as $focus)
|
||||
$focus->addProperty($prop);
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyzes the project.
|
||||
*
|
||||
* This method receives each expression and analizes
|
||||
* the best way to act and to store the understood
|
||||
* structure
|
||||
*
|
||||
* @param String $expression
|
||||
* @param String $structure
|
||||
* @param Array $structureKeys
|
||||
* @return Boolean True if everything went ok, false when any error occurred
|
||||
*/
|
||||
public static function analize($expression, $structure, Array $structureKeys){
|
||||
// I'm gonna try to put it in stepByStep style, to
|
||||
// get it easier for me and for you to understand
|
||||
// and follow the thoughts
|
||||
|
||||
// setting up
|
||||
self::clearFocused();
|
||||
$tmpProperties= Array();
|
||||
$i = 0;
|
||||
$linkVerb = null;
|
||||
$min = null;
|
||||
$max = null;
|
||||
$linkType = 'action';
|
||||
$relation = false;
|
||||
$posVerb = false;
|
||||
|
||||
// foreach token
|
||||
foreach($structureKeys as $token)
|
||||
{
|
||||
$word= $expression[$i];
|
||||
$i++;
|
||||
// storing the current used verb
|
||||
if($token==Tokenizer::MT_VERB || $token==Tokenizer::MT_QBE)
|
||||
{
|
||||
$linkVerb= $word;
|
||||
$posVerb= true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// setting quantifiers
|
||||
if($token == Tokenizer::MT_NONE)
|
||||
{
|
||||
$min= 0;
|
||||
continue;
|
||||
}
|
||||
if($token == Tokenizer::MT_ONE || $token == Tokenizer::MT_MANY)
|
||||
{
|
||||
if(!is_null($max))
|
||||
$min= $max;
|
||||
$max= ($token == Tokenizer::MT_ONE)? 1: 'n';
|
||||
}
|
||||
|
||||
// verifying the way the entities will be linked
|
||||
if($token==Tokenizer::MT_QMAY)
|
||||
{
|
||||
$linkType= 'possibility';
|
||||
continue;
|
||||
}
|
||||
if($token==Tokenizer::MT_QMUST)
|
||||
{
|
||||
$linkType= 'must';
|
||||
continue;
|
||||
}
|
||||
|
||||
// if it is a substantive
|
||||
if($token==Tokenizer::MT_SUBST)
|
||||
{
|
||||
// if it is an entity
|
||||
if(MindEntity::isEntity($word))
|
||||
{
|
||||
// fixing any special char
|
||||
$word= Mind::$lexer->fixWordChars($word);
|
||||
|
||||
// yeah, I know it looks crazy, but try to follow my thoughts
|
||||
// let's instantiate a new Entity in case it has not been
|
||||
// instantiated before
|
||||
if(!isset(self::$entities[$word]))
|
||||
self::$entities[$word]= new MindEntity($word);
|
||||
|
||||
// each instruction *should* have one focused entity
|
||||
// we will use the first entity on each expression as focus
|
||||
if(!$posVerb)
|
||||
{
|
||||
self::addToFocus(self::$entities[$word]);
|
||||
}else{
|
||||
$relation= true;
|
||||
// if min or max quantifier have not been set
|
||||
if(is_null($min))
|
||||
$min= ($linkType == 'must')? 1: 0;
|
||||
if(is_null($max))
|
||||
$max= 'n';
|
||||
|
||||
if(in_array($word, array_keys(self::$focused)))
|
||||
{
|
||||
/*if($max != QUANTIFIER_MAX_MAX)
|
||||
continue;*/
|
||||
self::$entities[$word]->setSelfReferred($max);
|
||||
//continue;
|
||||
}
|
||||
/*
|
||||
* here, if it is an entity and the focused
|
||||
* entities have already been selected(post verb),
|
||||
* it means it is the second entity on the
|
||||
* instruction, so, it is a relation between entities
|
||||
*/
|
||||
self::addRelationToFocused(self::$entities[$word],
|
||||
$linkType,
|
||||
$linkVerb,
|
||||
$min,
|
||||
$max);
|
||||
}
|
||||
}else{
|
||||
// ok, after that, this is just easy :)
|
||||
// let's store all the properties to a temporary array
|
||||
$tmpProperties[]= new MindProperty($word);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// adding the properties to the focused entity
|
||||
// we're doing it now, because according to the selected idiom
|
||||
// the sequence of focused entity and properties may vary
|
||||
if(sizeof($tmpProperties)>0 && $posVerb)
|
||||
{
|
||||
foreach($tmpProperties as $prop)
|
||||
self::addPropertyToFocused($prop);
|
||||
}
|
||||
|
||||
// if there was a relation, we will return some details about it
|
||||
if($relation && isset(self::$entities[$word]))
|
||||
return Array('min' =>$min,
|
||||
'max' =>$max,
|
||||
'linkVerb' =>$linkVerb,
|
||||
'linkType' =>$linkType,
|
||||
'focus' =>implode(', ', self::getFocusedNames()),
|
||||
'rel' =>self::$entities[$word]->name);
|
||||
// otherwise, we return the focused entities
|
||||
return self::$focused;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of theWebMind 3rd generation.
|
||||
*
|
||||
* Analyst components, within the Cortex/Analyst packages.<br/>
|
||||
* Notice that, these packages are being used only for documentation,
|
||||
* not to organize the classes.
|
||||
*
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
* @license licenses/mind3rd.license
|
||||
* @filesource
|
||||
*/
|
||||
/**
|
||||
* This class is responsible for the analysis of the system
|
||||
* preparing the relations and apply the first rules
|
||||
*
|
||||
* @package Cortex
|
||||
* @subpackage Analyst
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
*/
|
||||
class Analyst extends Analysis {
|
||||
|
||||
/**
|
||||
* Returns true if the entity is worth mergin with another, or not.
|
||||
* It takes the relevance as parameter to determine wheter the entity
|
||||
* should be merged(stop existing) or not.
|
||||
*
|
||||
* @param MindEntity $en The entity to be analyzed
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isItWorthMerging(MindEntity $en)
|
||||
{
|
||||
GLOBAL $_MIND;
|
||||
if(Normalizer::relevanceAmount($en) < $_MIND->conf['merging_amount_pts'])
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an entity from the entities list.
|
||||
* @param type $entity The entity to be removed
|
||||
*/
|
||||
public static function removeEntity($entity)
|
||||
{
|
||||
unset(self::$entities[$entity]);
|
||||
unset($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a relation between two entities.
|
||||
* But it will NOT remove the refBy or refTo properties of each entity.
|
||||
* It is most often, useful to be used for relations that may have
|
||||
* been represented twice, as the same idea.
|
||||
* It also decreases the relevance of the focused entity.
|
||||
*
|
||||
* @param MindRelation &$rel The relation which will be droped
|
||||
*/
|
||||
public static function unsetRelation(MindRelation &$rel)
|
||||
{
|
||||
if($rel->focus)
|
||||
{
|
||||
$rel->focus->relations[$rel->name]= false;
|
||||
$rel->focus->relevance--;
|
||||
}
|
||||
if($rel->rel)
|
||||
{
|
||||
$rel->focus->removeRefTo($rel->rel->name);
|
||||
$rel->focus->removeRefBy($rel->rel->name);
|
||||
$rel->rel->removeRefTo($rel->focus->name);
|
||||
$rel->rel->removeRefBy($rel->focus->name);
|
||||
$rel->rel->relations[$rel->name]= false;
|
||||
}
|
||||
unset(self::$relations[$rel->name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the whole interpreted context, with all the
|
||||
* analyzed information
|
||||
* @return Array An array with both entities and relations
|
||||
*/
|
||||
public static function getUniverse()
|
||||
{
|
||||
return Array(
|
||||
'entities'=>&self::$entities,
|
||||
'relations'=>&self::$relations
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints out the analyzed content
|
||||
* @param boolean $detailed Pass true if it should show detailed
|
||||
* information about the entities and properties.
|
||||
* @param boolean $showEntities=true
|
||||
* @param boolean $showRelations=true
|
||||
*/
|
||||
public static function printWhatYouGet($detailed=true,
|
||||
$showEntities=true,
|
||||
$showRelations=true)
|
||||
{
|
||||
$props= 0;
|
||||
if($showEntities)
|
||||
{
|
||||
echo "ENTITIES: ".sizeof(self::$entities)."\n";
|
||||
foreach(self::$entities as $k=>$entity)
|
||||
{
|
||||
if(!$detailed)
|
||||
{
|
||||
echo " ".$entity->name.
|
||||
"\n";
|
||||
}else{
|
||||
echo " ".$entity->name.
|
||||
"\n";
|
||||
foreach($entity->properties as $prop)
|
||||
{
|
||||
$details= false;
|
||||
$details= Array();
|
||||
if($prop->size)
|
||||
$details[]= $prop->size;
|
||||
if($prop->unique)
|
||||
$details[]= "unique";
|
||||
if($prop->key)
|
||||
$details[]= "key";
|
||||
if($prop->required)
|
||||
$details[]= "not null";
|
||||
if(!is_null($prop->default) && trim($prop->default) != '')
|
||||
$details[]= ($prop->default!= AUTOINCREMENT_DEFVAL)?
|
||||
'"'.$prop->default.'"':
|
||||
"AUTO_INCREMENT";
|
||||
if(sizeof($prop->options) > 0)
|
||||
{
|
||||
$opts= "{".implode("|", array_keys($prop->default))."}";
|
||||
$details[]= $opts;
|
||||
}
|
||||
|
||||
$props++;
|
||||
echo " ".$prop->name.
|
||||
":".$prop->type.
|
||||
"(".
|
||||
implode(", ", $details).
|
||||
")".
|
||||
($prop->refTo? " => ". $prop->refTo[0]->name.
|
||||
".".
|
||||
$prop->refTo[1]->name
|
||||
: "");
|
||||
if($prop->comment)
|
||||
echo "// ".$prop->comment;
|
||||
echo "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
if($detailed)
|
||||
echo "PROPERTIES: ".$props."\n";
|
||||
}
|
||||
if($showRelations)
|
||||
{
|
||||
echo "RELATIONS:".sizeof(self::$relations)."\n";
|
||||
foreach(self::$relations as $k=>$rel)
|
||||
{
|
||||
if(!$rel)
|
||||
continue;
|
||||
echo " ".$rel->name;
|
||||
if($detailed)
|
||||
{
|
||||
echo ': '.
|
||||
$rel->rel->name.' -> '.
|
||||
$rel->focus->name.
|
||||
($rel->uniqueRef? "[pk]": "").
|
||||
"\n";
|
||||
}
|
||||
}
|
||||
echo "Relations: ".sizeof(self::$relations)."\n";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies normalization rules to the currently analized structure.
|
||||
* This method uses the Normalizer methods and properties to apply
|
||||
* the required rules.
|
||||
*/
|
||||
public static function normalizeIt()
|
||||
{
|
||||
Normalizer::normalize();
|
||||
self::$relations= array_filter(self::$relations);
|
||||
self::$entities= array_filter(self::$entities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the properties of the analyst itself.
|
||||
*/
|
||||
public static function reset()
|
||||
{
|
||||
self::$entities = false;
|
||||
self::$relations= false;
|
||||
self::$entities = Array();
|
||||
self::$relations= Array();
|
||||
self::clearFocused();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sweeps through all the matched expressions.
|
||||
* @param Array $matches
|
||||
*/
|
||||
public static function sweep($matches)
|
||||
{
|
||||
// now we gotta analyze each valid expression
|
||||
foreach($matches as $found)
|
||||
{
|
||||
$len= strlen($found[0]);
|
||||
$expression= array_slice(Token::$words, $found[1], $len);
|
||||
$tokens= array_slice(Token::$spine, $found[1], $len);
|
||||
$struct= $found[0];
|
||||
|
||||
// let's analize it, now
|
||||
// Analyst will store it on its own static structure
|
||||
Analyst::analize($expression, $struct, $tokens);
|
||||
}
|
||||
self::clearFocused();
|
||||
self::normalizeIt();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of theWebMind 3rd generation.
|
||||
* Under Cortex/Analyst structure
|
||||
*
|
||||
* @filesource
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
*/
|
||||
/**
|
||||
* Generic methods to be used by the Normalizer.
|
||||
*
|
||||
* @abstract Normal
|
||||
* @package Cortex
|
||||
* @subpackage Analyst
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
*/
|
||||
abstract class Normal {
|
||||
|
||||
public static $oneByOne = Array();
|
||||
public static $nByN = Array();
|
||||
public static $oneByN = Array();
|
||||
public static $focus = Array();
|
||||
public static $predicate = Array();
|
||||
|
||||
/**
|
||||
* Merges all the poperties from the $rel into the $focus
|
||||
*
|
||||
* @param MindEntity $focus The entity that will receive the other's properties
|
||||
* @param MindEntity $rel The entity which will lose its properties
|
||||
*/
|
||||
public static function mergeProperties(MindEntity &$focus, MindEntity &$rel)
|
||||
{
|
||||
GLOBAL $_MIND;
|
||||
if($_MIND->conf['use_prefix_on_merged_entities'])
|
||||
{
|
||||
$propList= Array();
|
||||
foreach($rel->properties as $prop)
|
||||
{
|
||||
$name= $rel->name.PROPERTY_SEPARATOR.$prop->name;
|
||||
$propList[$name]= $prop;
|
||||
$propList[$name]->setName($name);
|
||||
}
|
||||
$rel->properties= $propList;
|
||||
}
|
||||
$focus->properties= array_merge($focus->properties, $rel->properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the passed entities.
|
||||
*
|
||||
* Merges the $rel entity into the $focus entity, merging
|
||||
* the properties and relations
|
||||
*
|
||||
* @param MindEntity $focus The main entity
|
||||
* @param MindEntity $rel The weaker entity
|
||||
* @return MindEntity
|
||||
*/
|
||||
public static function mergeEntities(MindEntity &$focus,
|
||||
MindEntity &$rel,
|
||||
MindRelation &$relation)
|
||||
{
|
||||
self::mergeProperties($focus, $rel);
|
||||
Analyst::unsetRelation($relation->opposite);
|
||||
Analyst::unsetRelation($relation);
|
||||
Normalizer::redirectRelations($rel, $focus);
|
||||
Analyst::removeEntity($rel->name);
|
||||
return $focus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes 1:1 relations.
|
||||
* It will fix the relations between the passed entities, as they
|
||||
* will not be merged.
|
||||
*
|
||||
* @param MindEntity $focus The pointed entity
|
||||
* @param MindEntity $rel The weaker entity
|
||||
* @param MindRelation $relation The relation between
|
||||
*/
|
||||
public static function fixOneByOneRelation(MindEntity &$focus,
|
||||
MindEntity &$rel,
|
||||
MindRelation &$relation)
|
||||
{
|
||||
/*
|
||||
* excluir a relação entre a mais forte e a mais fraca
|
||||
* marcar a fk como pk
|
||||
*/
|
||||
Analyst::unsetRelation( Analyst::$relations[$rel->name.
|
||||
PROPERTY_SEPARATOR.
|
||||
$focus->name]);
|
||||
Analyst::$relations[$focus->name.
|
||||
PROPERTY_SEPARATOR.
|
||||
$rel->name]->uniqueRef= true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the relevance amount for the passed entity.
|
||||
*
|
||||
* Gets the pontuation amount for the relevance an entity may have.
|
||||
* It takes many directrizes to define how relevant an entity is.
|
||||
* New parameters for such decision can be added here.
|
||||
*
|
||||
* @param MindEntity $entity The entity to be analysed
|
||||
* @return int The relevance the entity has
|
||||
*/
|
||||
public static function relevanceAmount(MindEntity $entity)
|
||||
{
|
||||
GLOBAL $_MIND;
|
||||
$pts= 0;
|
||||
// if the entity has many properties, it might be important
|
||||
if(sizeof($entity->properties) > $_MIND->conf['big_entities_length'])
|
||||
$pts++;
|
||||
// if the entity has many big fields
|
||||
if(self::hasBigProperties($entity) > $_MIND->conf['big_fields_in_entity'])
|
||||
$pts++;
|
||||
// if it has many relations
|
||||
if(sizeof($entity->relations) >= $_MIND->conf['relations_length'])
|
||||
$pts++;
|
||||
return $pts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the most and less relevant entities.
|
||||
* Returns an array with the most relevant entity in the first position
|
||||
* and the other entity in the second position
|
||||
*
|
||||
* @param MindEntity $en1
|
||||
* @param MindEntity $en2
|
||||
* @return Array
|
||||
*/
|
||||
public static function setByRelevance(MindEntity &$en1, MindEntity &$en2)
|
||||
{
|
||||
$en1Rlv= $en1->relevance;
|
||||
$en2Rlv= $en2->relevance;
|
||||
$en1Rlv+= self::relevanceAmount($en1);
|
||||
$en2Rlv+= self::relevanceAmount($en2);
|
||||
if($en1Rlv == $en2Rlv)
|
||||
if(strlen($en1->name) > strlen($en2->name))
|
||||
$en1Rlv++;
|
||||
else
|
||||
$en2Rlv++;
|
||||
if($en1Rlv > $en2Rlv)
|
||||
return Array($en1, $en2);
|
||||
else
|
||||
return Array($en2, $en1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies wether the entity has big properties or not.
|
||||
*
|
||||
* Verifies if the entity has properties classified as big.<br/>
|
||||
* If yes, returns the number of big properties found, or
|
||||
* false(0) if no big property has been found
|
||||
*
|
||||
* @param MindEntity $entity
|
||||
* @return boolean|int The number of big properties, or false when none
|
||||
*/
|
||||
public static function hasBigProperties(MindEntity $entity)
|
||||
{
|
||||
GLOBAL $_MIND;
|
||||
$bigFields= 0;
|
||||
foreach($entity->properties as $prop)
|
||||
if( $prop->size > $_MIND->conf['big_fields_size'] ||
|
||||
$prop->type=='text')
|
||||
$bigFields++;
|
||||
return $bigFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Organizes the relations by its cardinalities.
|
||||
*
|
||||
* Organizes the relations between entities to each group,
|
||||
* separating by n:n, 1:1 or 1:n
|
||||
*
|
||||
*/
|
||||
public static function separateByRelationQuantifiers()
|
||||
{
|
||||
reset(Analyst::$relations);
|
||||
while($rel= current(Analyst::$relations))
|
||||
{
|
||||
next(Analyst::$relations);
|
||||
$relName = $rel->name;
|
||||
$relOtherName= $rel->rel->name.
|
||||
PROPERTY_SEPARATOR.
|
||||
$rel->focus->name;
|
||||
|
||||
if(isset(Analyst::$relations[$relOtherName]))
|
||||
{
|
||||
$otherRel= &Analyst::$relations[$relOtherName];
|
||||
|
||||
Analyst::$relations[$rel->name]->opposite=
|
||||
&Analyst::$relations[$otherRel->name];
|
||||
Analyst::$relations[$otherRel->name]->opposite=
|
||||
&Analyst::$relations[$rel->name];
|
||||
|
||||
// let's look for n/n relations
|
||||
if($otherRel->max=='n' && $rel->max=='n')
|
||||
{
|
||||
self::$nByN[]= &Analyst::$relations[$rel->name];
|
||||
}elseif($otherRel->max==1 && $rel->max==1)
|
||||
{ // 1:1 relation
|
||||
self::$oneByOne[]= &Analyst::$relations[$rel->name];
|
||||
}else{
|
||||
// useless re-definition
|
||||
// if the relation was already specified as 1:n it doesn't
|
||||
// need to be re-specified as n:1
|
||||
Analyst::unsetRelation($otherRel);
|
||||
}
|
||||
}else{
|
||||
if($rel->max == 1)
|
||||
{
|
||||
$tmpFocus= $rel->focus;
|
||||
$rel->setFocus($rel->rel);
|
||||
$rel->setRel($tmpFocus);
|
||||
self::$oneByN[]= &Analyst::$relations[$rel->name];
|
||||
}else
|
||||
self::$oneByN[]= &Analyst::$relations[$rel->name];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,422 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of TheWebMind 3rd generation.
|
||||
*
|
||||
* Normalizer components, within the Cortex/Analyst packages.<br/>
|
||||
* Notice that, these packages are being used only for documentation,
|
||||
* not to organize the classes.
|
||||
*
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
* @license licenses/mind3rd.license
|
||||
*/
|
||||
|
||||
/**
|
||||
* Normalizes the data structure.
|
||||
*
|
||||
* Will normalize the data and entities structure
|
||||
* applying rules and patterns. Thanks for
|
||||
* Edgar F. Codd for all he created and wondered
|
||||
* for the Relational Model
|
||||
*
|
||||
* @package Cortex
|
||||
* @subpackage Analyst
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
* @filesource
|
||||
*/
|
||||
class Normalizer extends Normal{
|
||||
|
||||
public static $tmpEntities = Array();
|
||||
public static $tmpRelations = Array();
|
||||
public static $linkedTables = Array();
|
||||
|
||||
/**
|
||||
* Redirects all the relations between entities.
|
||||
*
|
||||
* Redirects all the relations that point to, or are pointed by the
|
||||
* $from entity, to the $to entity.
|
||||
*
|
||||
* @param MindEntity $from Entity which will lose its references
|
||||
* @param MindEntity $to Entity which will be reffered instead
|
||||
*/
|
||||
public static function redirectRelations(MindEntity &$from, MindEntity &$to)
|
||||
{
|
||||
foreach($from->relations as &$rel)
|
||||
{
|
||||
if(!$rel)
|
||||
continue;
|
||||
if($rel->focus->name == $from->name)
|
||||
{
|
||||
$rel->setFocus($to);
|
||||
$rel->rename($rel->rel->name.
|
||||
PROPERTY_SEPARATOR.
|
||||
$rel->focus->name);
|
||||
}else{
|
||||
$rel->setRel($to);
|
||||
$rel->rename($rel->focus->name.
|
||||
PROPERTY_SEPARATOR.
|
||||
$rel->rel->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes the 1:1 relations, normalizing them
|
||||
*/
|
||||
public static function fixOneByOneRel()
|
||||
{
|
||||
if(sizeof(self::$oneByOne) == 0)
|
||||
return true;
|
||||
reset(self::$oneByOne);
|
||||
$rel= current(self::$oneByOne);
|
||||
|
||||
foreach(self::$oneByOne as &$rel)
|
||||
{
|
||||
$rel= &Analyst::$relations[$rel->name];
|
||||
|
||||
if($rel->focus === $rel->rel)
|
||||
{
|
||||
// self referred (1)
|
||||
$rel->focus->addAutoPk(true);
|
||||
continue;
|
||||
}
|
||||
|
||||
if(is_null($rel) || is_null($rel->focus) || is_null($rel->rel))
|
||||
continue;
|
||||
// defining the focus
|
||||
$entities= self::setByRelevance($rel->focus, $rel->rel);
|
||||
self::$focus= $entities[0];
|
||||
self::$predicate= $entities[1];
|
||||
|
||||
// let's check the minimun quantifiers
|
||||
if($rel->min== 1 && $rel->opposite->min == 1)
|
||||
{
|
||||
// for 1:1 / 1:1 relations
|
||||
self::mergeEntities(self::$focus, self::$predicate, $rel);
|
||||
}elseif($rel->min== 0 && $rel->opposite->min == 0)
|
||||
{
|
||||
// for 0:1 / 0:1 relations
|
||||
if(Analyst::isItWorthMerging(self::$predicate))
|
||||
{
|
||||
self::mergeEntities(self::$focus, self::$predicate, $rel);
|
||||
}else{
|
||||
self::fixOneByOneRelation(self::$focus,
|
||||
self::$predicate,
|
||||
$rel);
|
||||
}
|
||||
}else{
|
||||
// for 0:1 / 1:1 relations
|
||||
self::fixOneByOneRelation(self::$focus,
|
||||
self::$predicate,
|
||||
$rel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an extra entity to link multiple relations.
|
||||
*
|
||||
* Creates the entity to be used as a link between the
|
||||
* other two entities due to an N:N relation
|
||||
*
|
||||
* @param MindRelation $rel
|
||||
* @return MindEntity
|
||||
*/
|
||||
public static function &createNByNEntity(MindRelation &$rel)
|
||||
{
|
||||
$linkTable= false;
|
||||
$relName= $rel->focus->name.
|
||||
PROPERTY_SEPARATOR.
|
||||
$rel->rel->name;
|
||||
$relOtherName= $rel->rel->name.
|
||||
PROPERTY_SEPARATOR.
|
||||
$rel->focus->name;
|
||||
if(isset(Analyst::$entities[$relName]))
|
||||
$linkTable= &Analyst::$entities[$relName];
|
||||
if(isset(Analyst::$entities[$relOtherName]))
|
||||
$linkTable= &Analyst::$entities[$relOtherName];
|
||||
if(!$linkTable)
|
||||
{
|
||||
$linkTable= new MindEntity($relName);
|
||||
Analyst::$entities[$linkTable->name]= $linkTable;
|
||||
}
|
||||
Analyst::$entities[$linkTable->name]->linkTable= Array($rel->focus->name,
|
||||
$rel->rel->name);
|
||||
return Analyst::$entities[$linkTable->name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Create all the relations needed to fix n:n relations.
|
||||
*
|
||||
* It takes the $left and $right entities and set the
|
||||
* $center to reffer to it. The $rel parameter is used
|
||||
* to identifies characteristics from an original
|
||||
* relation, like linkVerb or linkType.
|
||||
*
|
||||
* @param MindEntity $left
|
||||
* @param MindEntity $center
|
||||
* @param MindEntity $right
|
||||
* @param MindRelation $rel
|
||||
*/
|
||||
public static function createNbyNRelations( MindEntity &$left,
|
||||
MindEntity &$center,
|
||||
MindEntity &$right,
|
||||
MindRelation &$rel)
|
||||
{
|
||||
Analyst::addToFocus($left);
|
||||
Analyst::addToFocus($right);
|
||||
$relations= Analyst::addRelationToFocused( $center,
|
||||
$rel->linkType,
|
||||
$rel->linkVerb,
|
||||
0,
|
||||
'n',
|
||||
true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes all the n:n relations
|
||||
*/
|
||||
public static function fixNByNRel()
|
||||
{
|
||||
GLOBAL $_MIND;
|
||||
foreach(self::$nByN as &$rel)
|
||||
{
|
||||
if(!$rel->treated)
|
||||
{
|
||||
if($rel->focus === $rel->rel)
|
||||
{
|
||||
// it is self referred (n)
|
||||
$inflect= Mind::$currentProject['idiom']."\Inflect";
|
||||
$name= $inflect::toPlural($rel->rel->name);
|
||||
$name.= PROPERTY_SEPARATOR.$rel->rel->name;
|
||||
|
||||
if(!isset(Analyst::$entities[$name]))
|
||||
{
|
||||
$tmpEnt= new MindEntity($name);
|
||||
Analyst::$entities[$tmpEnt->name]= $tmpEnt;
|
||||
Analyst::$entities[$tmpEnt->name]->linkTable= true;
|
||||
}
|
||||
$rel->setRel(Analyst::$entities[$name]);
|
||||
|
||||
Analyst::addRelationBetween($rel->focus,
|
||||
$rel->rel,
|
||||
'action',
|
||||
$rel->linkVerb,
|
||||
0,
|
||||
'n',
|
||||
true);
|
||||
|
||||
$rel->focus->addAutoPk(true);
|
||||
$pkName= $_MIND->defaults['pk_prefix'].
|
||||
$rel->focus->name;
|
||||
$fakeFk= new MindProperty();
|
||||
$fakeFk ->setAsKey()
|
||||
->setName($pkName)
|
||||
->setRequired(true)
|
||||
->setType('int')
|
||||
->setRefTo($rel->focus,
|
||||
$rel->focus->pks[$pkName]);
|
||||
$rel->rel->addProperty($fakeFk);
|
||||
|
||||
}else{
|
||||
$entity= self::createNByNEntity($rel);
|
||||
$rel->opposite->treated= true;
|
||||
self::createNbyNRelations($rel->focus,
|
||||
$entity,
|
||||
$rel->rel,
|
||||
$rel);
|
||||
}
|
||||
}
|
||||
Analyst::unsetRelation($rel);
|
||||
Analyst::clearFocused();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all the foreign keys to all the entities that
|
||||
* may need it.
|
||||
*/
|
||||
public static function addFks()
|
||||
{
|
||||
GLOBAL $_MIND;
|
||||
$fkPrefix= $_MIND->defaults['fk_prefix'];
|
||||
$pkPrefix= $_MIND->defaults['pk_prefix'];
|
||||
foreach(Analyst::$relations as &$relation)
|
||||
{
|
||||
$pointed= $relation->focus;
|
||||
$defaultPkName= $pkPrefix.$pointed->name;
|
||||
if($pointed->hasProperty($defaultPkName)
|
||||
&&
|
||||
$pointed->pks[$defaultPkName]->default==AUTOINCREMENT_DEFVAL)
|
||||
$pks= Array($pointed->pks[$defaultPkName]);
|
||||
else
|
||||
$pks= &$pointed->pks;
|
||||
|
||||
foreach($pks as &$pk)
|
||||
{
|
||||
if($pk->key !== true)
|
||||
continue;
|
||||
$tmpName= $pk->name;
|
||||
$propName= $fkPrefix.preg_replace("/^".$pkPrefix."|".$fkPrefix."/",
|
||||
'',
|
||||
$tmpName);
|
||||
$entity= &$relation->rel;
|
||||
|
||||
// we will mark the linkTables
|
||||
if($pointed->linkTable)
|
||||
{
|
||||
self::$linkedTables[$pointed->name]= &$pointed;
|
||||
}elseif($entity->linkTable)
|
||||
{
|
||||
self::$linkedTables[$entity->name]= &$entity;
|
||||
}
|
||||
|
||||
// we've got to treat the repeated properties
|
||||
if($entity->hasProperty($propName)
|
||||
&&
|
||||
$entity->properties[$propName]->refTo)
|
||||
{
|
||||
$propName= $fkPrefix.$pointed->name.
|
||||
PROPERTY_SEPARATOR.
|
||||
$pk->name;
|
||||
}
|
||||
|
||||
// if there ain't not property with that name already
|
||||
if(!$entity->hasProperty($propName))
|
||||
{
|
||||
// let's create it
|
||||
$fk= new MindProperty();
|
||||
$fk ->setName($propName)
|
||||
->setType('int')
|
||||
->setRefTo($relation->focus, $pk);
|
||||
if(!$entity->selfRef)
|
||||
$fk->setRequired(true);
|
||||
if($relation->uniqueRef)
|
||||
{
|
||||
if(!$entity->linkTable||
|
||||
($entity->linkTable && $entity->hasHardKey())
|
||||
||
|
||||
($entity->linkTable && sizeof($entity->getRefBy())==0)
|
||||
)
|
||||
{
|
||||
$fk->setAsWeakKey();
|
||||
}else{
|
||||
$fk->setAsKey();
|
||||
}
|
||||
}
|
||||
$entity->addProperty($fk);
|
||||
}else{
|
||||
// otherwise, we simply use/change the existing one
|
||||
$entity ->properties[$propName]
|
||||
->setRefTo($relation->focus, $pk);
|
||||
if($relation->uniqueRef)
|
||||
$entity ->properties[$propName]->setAsKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all the primary keys the entities will need.
|
||||
*/
|
||||
public static function addPks()
|
||||
{
|
||||
GLOBAL $_MIND;
|
||||
$pkPrefix= $_MIND->defaults['pk_prefix'];
|
||||
foreach(Analyst::$entities as &$entity)
|
||||
{
|
||||
if( sizeof($entity->pks) == 0
|
||||
&&
|
||||
(!$entity->linkTable || sizeof($entity->getRefBy())>0 ))
|
||||
{
|
||||
$propName= $pkPrefix.$entity->name;
|
||||
if(!$entity->hasProperty($propName))
|
||||
{
|
||||
$pk= new MindProperty();
|
||||
$pk ->setAsKey()
|
||||
->setName($propName)
|
||||
->setDefault(AUTOINCREMENT_DEFVAL)
|
||||
->setRequired(true)
|
||||
->setType('int');
|
||||
$entity->addProperty($pk);
|
||||
}else{
|
||||
$entity->properties[$propName]->setAsKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is calledto execute any needed adjust.
|
||||
*/
|
||||
public static function fixOneByNRel()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Will set the primary and foreign keys to entities.
|
||||
*/
|
||||
public static function setUpKeys()
|
||||
{
|
||||
GLOBAL $_MIND;
|
||||
Analyst::$entities= array_filter(Analyst::$entities);
|
||||
Analyst::$relations= array_filter(Analyst::$relations);
|
||||
|
||||
self::addPks(); // OK
|
||||
self::addFks(); // OK
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears static properties setting them to their default value.
|
||||
* Quite useful when used through a command line single session.
|
||||
*/
|
||||
public static function reset()
|
||||
{
|
||||
self::$oneByOne = false;
|
||||
self::$oneByOne = Array();
|
||||
self::$nByN = false;
|
||||
self::$nByN = Array();
|
||||
self::$oneByN = false;
|
||||
self::$oneByN = Array();
|
||||
self::$focus = false;
|
||||
self::$focus = Array();
|
||||
self::$predicate = false;
|
||||
self::$predicate = Array();
|
||||
self::$linkedTables= false;
|
||||
self::$linkedTables= Array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the known structure.
|
||||
*
|
||||
* It will apply the n:n and 1:1 rules, plus setting the
|
||||
* foreign and primary keys to all the entities.
|
||||
* Please, notice that there are rules to be followed here,
|
||||
* such as:<pre>
|
||||
* 1:1 to 1:1 relations will always merge entities
|
||||
* 0:1 to 0:1 relations will always try to identify the less
|
||||
* important and set it to point to the other entity
|
||||
* setting its foreign key as a primary key
|
||||
* 0:1 to 1:1 will decide if it should wether merge or fix the
|
||||
* relation. It will decide it using the following
|
||||
* parameters of decision:
|
||||
* - number of properties: as many, less mergeable
|
||||
* - number of relations: as less reffered,
|
||||
* more mergeable
|
||||
* - big properties: as many big properties,
|
||||
* less mergeable
|
||||
* n:n relations will generate an extra entity, altough,
|
||||
* if the entity with that name already exists, it
|
||||
* takes the existing one.
|
||||
* If the antity ONLY has keys, no pk will be added.
|
||||
* </pre>
|
||||
*/
|
||||
public static function normalize()
|
||||
{
|
||||
self::reset();
|
||||
self::separateByRelationQuantifiers();
|
||||
self::fixOneByOneRel();
|
||||
self::fixNByNRel();
|
||||
self::fixOneByNRel();
|
||||
self::setUpKeys();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of TheWebMind 3rd generation.
|
||||
*
|
||||
* Canonic, within the Cortex/Canonic packages.<br/>
|
||||
* Notice that, these packages are being used only for documentation,
|
||||
* not to organize the classes.
|
||||
*
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
* @license licenses/mind3rd.license
|
||||
*/
|
||||
/**
|
||||
* This class will take the content to be used, and take
|
||||
* it to its canonical form.
|
||||
* It extends the Inflect class, from the selected language
|
||||
*
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
* @package Cortex
|
||||
* @subpackage Canonic
|
||||
*/
|
||||
class Canonic{
|
||||
|
||||
public static $substantives= Array();
|
||||
|
||||
/**
|
||||
* Takes a word to its canonic form(singular/male form).
|
||||
* @param string $word
|
||||
* @return string
|
||||
*/
|
||||
public static function canonize($word)
|
||||
{
|
||||
$inflec= Mind::$currentProject['idiom']."\Inflect";
|
||||
if(!$inflec::isSingular($word))
|
||||
$word= $inflec::toSingular($word);
|
||||
return $word;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sweeps all the content and take all the substantives
|
||||
* to their canonical form.
|
||||
*
|
||||
* @return Array
|
||||
*/
|
||||
public function sweep()
|
||||
{
|
||||
self::$substantives= false;
|
||||
self::$substantives= Array();
|
||||
$content= Mind::$content;
|
||||
$newContent= Array();
|
||||
|
||||
Mind::$tokenizer= new Tokenizer();
|
||||
$ignoreForms= Mind::$currentProject['idiom'].'\IgnoreForms';
|
||||
$verbalizer= Mind::$currentProject['idiom'].'\Verbalizer';
|
||||
$posVerb= false;
|
||||
|
||||
foreach($content as $word)
|
||||
{
|
||||
if($ignoreForms::shouldBeIgnored($word))
|
||||
continue;
|
||||
if(!Tokenizer::isQualifier($word) && !Tokenizer::isQuantifier($word))
|
||||
{
|
||||
if( strlen($word) > 1
|
||||
&&
|
||||
!isset(self::$substantives[$word])
|
||||
&&
|
||||
($isVerb= $verbalizer::isVerb($word))
|
||||
)
|
||||
{
|
||||
// is a verb
|
||||
$word= $verbalizer::toInfinitive($word);
|
||||
}
|
||||
else{
|
||||
// is a substantive
|
||||
$word= explode(':', $word);
|
||||
$word[0]= Canonic::canonize($word[0]);
|
||||
self::$substantives[$word[0]]= true;
|
||||
$word= implode(':', $word);
|
||||
}
|
||||
}
|
||||
$newContent[]= $word;
|
||||
}
|
||||
Mind::$content= $newContent;
|
||||
return $newContent;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of TheWebMind 3rd generation.
|
||||
*
|
||||
* Syntaxer, within the Cortex/Syntaxer packages.<br/>
|
||||
* Notice that, these packages are being used only for documentation,
|
||||
* not to organize the classes.
|
||||
*
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
* @license licenses/mind3rd.license
|
||||
*/
|
||||
/**
|
||||
* Identifies and organizes the valid syntaxes on the content.
|
||||
*
|
||||
* This class will work with the tokenized strucure and
|
||||
* the original code, due to identify patterns and apply
|
||||
* any needed rules.
|
||||
* <pre>
|
||||
* Legend:
|
||||
* Q=May have, Must have
|
||||
* S=Substantive
|
||||
* V=Verb
|
||||
* 0,N=Quantifiers
|
||||
* O=Or
|
||||
* C=Complement/Composite(like "of", or "de")
|
||||
* A=Addition(like "," or "and"
|
||||
*</pre>
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
* @package Cortex
|
||||
* @subpackage Syntaxer
|
||||
*/
|
||||
class Syntaxer {
|
||||
|
||||
public static $sintatics= Array();
|
||||
|
||||
/**
|
||||
* Loads the file which has the list of avaliable sintaxes.
|
||||
*/
|
||||
public static function loadSintaticList()
|
||||
{
|
||||
if(!file_exists('sintatics.list'))
|
||||
$fR= fopen(Mind::$langPath.Mind::$curLang.'/sintatics.list', 'rb');
|
||||
else
|
||||
$fR= fopen('sintatics.list', 'rb');
|
||||
|
||||
while (!feof($fR)){
|
||||
$sint= preg_replace('/\s/', '', fgets($fR, 4096));
|
||||
self::$sintatics[]= $sint;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the identified composed substantives.
|
||||
*
|
||||
* Fixes the composed substantives(defined by the use of
|
||||
* the "of" tokens defined into the qualifiers.xml of the current idiom)
|
||||
*/
|
||||
public function fetchComposedSubstantives()
|
||||
{
|
||||
while(preg_match(COMPOSED_SUBST,
|
||||
Token::$string,
|
||||
$matches,
|
||||
PREG_OFFSET_CAPTURE))
|
||||
{
|
||||
$matches= $matches[0];
|
||||
array_splice(Token::$spine, $matches[1], 3, Token::MT_SUBST);
|
||||
array_splice(Token::$words, $matches[1], 3,
|
||||
Token::$words[$matches[1]].
|
||||
'_'.
|
||||
Token::$words[$matches[1]+2]);
|
||||
Token::$string= preg_replace(COMPOSED_SUBST, 'S', Token::$string, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sweeps the content to apply the rules and identify patterns.
|
||||
*/
|
||||
public function sweep()
|
||||
{
|
||||
// loading stintatic list: all the avaliable, allowed syntaxes
|
||||
// formats, specified by the selected idiom
|
||||
self::loadSintaticList();
|
||||
|
||||
// mounting the regular expression
|
||||
$pattern= implode('|', self::$sintatics);
|
||||
|
||||
// let's find all the patterns that match
|
||||
// that means that we'll find only expressions with valid syntax
|
||||
// reminding that the pattern was dynamicaly created before
|
||||
$pattern= str_replace('S', VALID_SUBST_SYNTAX, $pattern);
|
||||
|
||||
$this->fetchComposedSubstantives();
|
||||
|
||||
// finding the valid syntaxes
|
||||
preg_match_all('/'.$pattern.'/',
|
||||
Token::$string,
|
||||
$matches,
|
||||
PREG_OFFSET_CAPTURE);
|
||||
// as we know it's only one block, we can use it straightly
|
||||
$matches= $matches[0];
|
||||
|
||||
Analyst::sweep($matches);
|
||||
return $matches;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of TheWebMind 3rd generation.
|
||||
*
|
||||
* Token, within the Cortex/Tokenizer packages.<br/>
|
||||
* Notice that, these packages are being used only for documentation,
|
||||
* not to organize the classes.
|
||||
*
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
* @license licenses/mind3rd.license
|
||||
*/
|
||||
/**
|
||||
* The Token itself.
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
* @package Cortex
|
||||
* @subpackage Tokenizer
|
||||
*/
|
||||
class Token
|
||||
{
|
||||
// Tokens to be used
|
||||
// MT stands for MindTokenizer
|
||||
// MS stands for MindSyntaxer
|
||||
const MT_PERIOD = -2;
|
||||
const MS_PERIOD = '.';
|
||||
const MT_COMA = -1;
|
||||
const MS_COMA = ',';
|
||||
const MT_VOID = 0;
|
||||
const MS_VOID = '';
|
||||
const MT_VERB = 1;
|
||||
const MS_VERB = 'V';
|
||||
const MT_SUBST = 2;
|
||||
const MS_SUBST = 'S';
|
||||
const MT_NONE = 4;
|
||||
const MS_NONE = 'N';
|
||||
const MT_ONE = 8;
|
||||
const MS_ONE = 'N';
|
||||
const MT_OR = 16;
|
||||
const MS_OR = 'O';
|
||||
const MT_MANY = 32;
|
||||
const MS_MANY = 'N';
|
||||
const MT_QMUST = 64;
|
||||
const MS_QMUST = 'Q';
|
||||
const MT_QMAY = 128;
|
||||
const MS_QMAY = 'Q';
|
||||
const MT_QNOTNULL= 254;
|
||||
const MT_QKEY = 564;
|
||||
const MT_QOF =1024;
|
||||
const MS_QOF = 'C';
|
||||
const MT_QBE =2048;
|
||||
const MS_QBE = 'B';
|
||||
const MT_QBRAKE = -4;
|
||||
const MS_QBRAKE = 'b';
|
||||
const MT_ANY =4096;
|
||||
const MS_ANY = '*';
|
||||
|
||||
public static $spine= Array();
|
||||
public static $words= Array();
|
||||
public static $string= '';
|
||||
|
||||
/**
|
||||
* Identifies the word type and adds it to the structure.
|
||||
* As the identified type, the word represents an assumed token.
|
||||
* @param string $word
|
||||
* @return string
|
||||
*/
|
||||
public function add($word)
|
||||
{
|
||||
$ignoreForms= Mind::$currentProject['idiom'].'\IgnoreForms';
|
||||
$verbalizer= Mind::$currentProject['idiom'].'\Verbalizer';
|
||||
|
||||
if(in_array($word, Tokenizer::$qualifiers['coma']))
|
||||
{
|
||||
$word= ',';
|
||||
}
|
||||
|
||||
self::$words[]= $word;
|
||||
|
||||
if($ignoreForms::shouldBeIgnored($word))
|
||||
{
|
||||
self::$spine[]= Token::MT_ANY;
|
||||
self::$string.= Token::MS_ANY;
|
||||
return;
|
||||
}
|
||||
if($word==',')
|
||||
{
|
||||
self::$spine[]= Token::MT_COMA;
|
||||
self::$string.= Token::MS_COMA;
|
||||
return;
|
||||
}
|
||||
if($word=='.')
|
||||
{
|
||||
self::$spine[]= Token::MT_PERIOD;
|
||||
self::$string.= Token::MS_PERIOD;
|
||||
return;
|
||||
}
|
||||
|
||||
// let's check for quantifiers
|
||||
if(Tokenizer::isQuantifier('none', $word))
|
||||
{
|
||||
self::$spine[]= Token::MT_NONE;
|
||||
self::$string.= Token::MS_NONE;
|
||||
return;
|
||||
}
|
||||
if(Tokenizer::isQuantifier('one', $word))
|
||||
{
|
||||
self::$spine[]= Token::MT_ONE;
|
||||
self::$string.= Token::MS_ONE;
|
||||
return;
|
||||
}
|
||||
if(Tokenizer::isQuantifier('many', $word))
|
||||
{
|
||||
self::$spine[]= Token::MT_MANY;
|
||||
self::$string.= Token::MS_MANY;
|
||||
return;
|
||||
|
||||
}
|
||||
if(Tokenizer::isQuantifier('or', $word))
|
||||
{
|
||||
self::$spine[]= Token::MT_OR;
|
||||
self::$string.= Token::MS_OR;
|
||||
return;
|
||||
}
|
||||
|
||||
// and here, the qualifiers
|
||||
if(Tokenizer::isQualifier('must', $word))
|
||||
{
|
||||
self::$spine[]= Token::MT_QMUST;
|
||||
self::$string.= Token::MS_QMUST;
|
||||
return;
|
||||
}
|
||||
if(Tokenizer::isQualifier('may', $word))
|
||||
{
|
||||
self::$spine[]= Token::MT_QMAY;
|
||||
self::$string.= Token::MS_QMAY;
|
||||
return;
|
||||
}
|
||||
if(Tokenizer::isQualifier('notnull', $word))
|
||||
{
|
||||
self::$spine[]= Token::MT_QNOTNULL;
|
||||
return;
|
||||
}
|
||||
if(Tokenizer::isQualifier('of', $word))
|
||||
{
|
||||
self::$string.= Token::MS_QOF;
|
||||
self::$spine[]= Token::MT_QOF;
|
||||
return;
|
||||
}
|
||||
if(Tokenizer::isQualifier('be', $word))
|
||||
{
|
||||
self::$spine[]= Token::MT_QBE;
|
||||
self::$string.= Token::MS_QBE;
|
||||
return;
|
||||
}
|
||||
if(Tokenizer::isQualifier('key', $word))
|
||||
{
|
||||
self::$spine[]= Token::MT_QKEY;
|
||||
return;
|
||||
}
|
||||
if(Tokenizer::isQualifier('brake', $word))
|
||||
{
|
||||
self::$spine[]= Token::MT_QBRAKE;
|
||||
self::$string.= Token::MS_QBRAKE;
|
||||
return;
|
||||
}
|
||||
// we know these words are already on its
|
||||
// canonic form, so, we can simply look for
|
||||
// it on the list
|
||||
if($verbalizer::isInVerbList($word))
|
||||
{
|
||||
self::$spine[]= Token::MT_VERB;
|
||||
self::$string.= Token::MS_VERB;
|
||||
return;
|
||||
}
|
||||
self::$spine[]= Token::MT_SUBST;
|
||||
self::$string.= Token::MS_SUBST;
|
||||
|
||||
return $word;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,248 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of TheWebMind 3rd generation.
|
||||
*
|
||||
* Tokenizer, within the Cortex/Tokenizer packages.<br/>
|
||||
* Notice that, these packages are being used only for documentation,
|
||||
* not to organize the classes.
|
||||
*
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
* @license licenses/mind3rd.license
|
||||
*/
|
||||
/**
|
||||
* This class will apply the most important tokens to be used.
|
||||
* It also builds the main structure to compare it to avaliable
|
||||
* sintatics. This structure is called SPINE
|
||||
*
|
||||
* @author Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
* @package Cortex
|
||||
* @subpackage Tokenizer
|
||||
*/
|
||||
class Tokenizer extends Token{
|
||||
|
||||
public static $sintaticsList;
|
||||
public static $quantifiers;
|
||||
public static $qualifiers;
|
||||
public static $spine= Array();
|
||||
public static $string= '';
|
||||
public static $dataTypes= Array();
|
||||
|
||||
/**
|
||||
* Parses a string into an array, splited by comas.
|
||||
* @param Mixed $str
|
||||
* @return Array The string splited by comas, ignoring a space after each coma
|
||||
*/
|
||||
private static function parseByComa($str)
|
||||
{
|
||||
return explode(',', str_replace(', ', ',', (String)$str));
|
||||
}
|
||||
|
||||
/**
|
||||
* This method builds the required structure from the
|
||||
* sent XML file
|
||||
*
|
||||
* @name loadSintatics
|
||||
* @param String $resource
|
||||
* @return AssocArray
|
||||
*/
|
||||
public static function loadSintatics($resource)
|
||||
{
|
||||
while (!feof($resource))
|
||||
{
|
||||
$word= preg_replace(COMA_SEPARATOR, '', fgets($resource, 4096));
|
||||
self::$sintaticsList[$word]= true;
|
||||
}
|
||||
return self::$sintaticsList;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will build the structure of quantifiers
|
||||
* from the passed XML
|
||||
*
|
||||
* @name loadQuantifiers
|
||||
* @param SimpleXML $xml
|
||||
* @return AssocArray
|
||||
*/
|
||||
public static function loadQuantifiers($xml)
|
||||
{
|
||||
self::$quantifiers= Array();
|
||||
self::$quantifiers['none'] = self::parseByComa($xml->none);
|
||||
self::$quantifiers['one'] = self::parseByComa($xml->one);
|
||||
self::$quantifiers['many'] = self::parseByComa($xml->many);
|
||||
self::$quantifiers['or'] = self::parseByComa($xml->or);
|
||||
return self::$quantifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the qualifiers into the class properties.
|
||||
* This method loads and builds the structure required
|
||||
* to use and identify the qualifiers, from a passed XML
|
||||
*
|
||||
* @name loadQualifiers
|
||||
* @param SimpleXML $xml
|
||||
* @return AssocArray
|
||||
*/
|
||||
public static function loadQualifiers($xml)
|
||||
{
|
||||
|
||||
self::$qualifiers= Array();
|
||||
self::$qualifiers['must'] = self::parseByComa($xml->must);
|
||||
self::$qualifiers['may'] = self::parseByComa($xml->may);
|
||||
self::$qualifiers['notnull']= self::parseByComa($xml->notnull);
|
||||
self::$qualifiers['key'] = self::parseByComa($xml->key);
|
||||
self::$qualifiers['of'] = self::parseByComa($xml->of);
|
||||
self::$qualifiers['be'] = self::parseByComa($xml->be);
|
||||
self::$qualifiers['coma'] = self::parseByComa($xml->coma);
|
||||
self::$qualifiers['unique'] = self::parseByComa($xml->unique);
|
||||
self::$qualifiers['brake'] = self::parseByComa($xml->brake);
|
||||
return self::$qualifiers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the possible types to be accepted.
|
||||
* @param SimpleXML $xml
|
||||
* @return Array The parsed avaliable types
|
||||
*/
|
||||
public static function loadTypes($xml)
|
||||
{
|
||||
self::$dataTypes['varchar'] = self::parseByComa($xml->varchar);
|
||||
self::$dataTypes['text'] = self::parseByComa($xml->text);
|
||||
self::$dataTypes['char'] = self::parseByComa($xml->char);
|
||||
self::$dataTypes['int'] = self::parseByComa($xml->int);
|
||||
self::$dataTypes['float'] = self::parseByComa($xml->float);
|
||||
self::$dataTypes['boolean'] = self::parseByComa($xml->boolean);
|
||||
self::$dataTypes['date'] = self::parseByComa($xml->date);
|
||||
self::$dataTypes['time'] = self::parseByComa($xml->time);
|
||||
self::$dataTypes['file'] = self::parseByComa($xml->file);
|
||||
return self::$dataTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies if the passed word is a quantifier.
|
||||
*
|
||||
* This method verifies whether the passed word is
|
||||
* a valid quantifier in the passed list of quantifiers
|
||||
* or if it is a quantifier, in case a list is not sent
|
||||
*
|
||||
* @param string $which In which quantifier the word should be searched
|
||||
* @param string $what The word to be verified
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isQuantifier($which, $what=false)
|
||||
{
|
||||
if($what)
|
||||
return (isset(self::$quantifiers[$which]) &&
|
||||
in_array($what, self::$quantifiers[$which]));
|
||||
foreach(self::$quantifiers as $qt)
|
||||
{
|
||||
if(in_array($which, $qt))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies if the passed word is a qualifier.
|
||||
*
|
||||
* This method verifies whether the passed word is
|
||||
* a valid quantifier in the passed list of qualifiers
|
||||
* or if it is a qualifier, in case a list is not sent
|
||||
*
|
||||
* @param string $which In which qualifier the word should be searched
|
||||
* @param string $what The word to be verified
|
||||
* @return boolean
|
||||
*/
|
||||
public static function isQualifier($which, $what=false)
|
||||
{
|
||||
if($what)
|
||||
return (isset(self::$qualifiers[$which]) &&
|
||||
in_array($what, self::$qualifiers[$which]));
|
||||
|
||||
foreach(self::$qualifiers as $ql)
|
||||
{
|
||||
if(in_array($which, $ql))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called to load each possible modifier
|
||||
*/
|
||||
public static function loadModifiers($modifiersSrc= false)
|
||||
{
|
||||
if(!$modifiersSrc && !file_exists('sintatics.list'))
|
||||
{
|
||||
self::loadSintatics(fopen(Mind::$langPath.Mind::$currentProject['idiom'].
|
||||
'/sintatics.list', 'rb'));
|
||||
$qnt= simplexml_load_file(Mind::$langPath.
|
||||
Mind::$currentProject['idiom'].
|
||||
'/quantifiers.xml');
|
||||
$qlf= simplexml_load_file(Mind::$langPath.
|
||||
Mind::$currentProject['idiom'].
|
||||
'/qualifiers.xml');
|
||||
$tps= simplexml_load_file(Mind::$langPath.
|
||||
Mind::$currentProject['idiom'].
|
||||
'/datatypes.xml');
|
||||
self::loadQuantifiers($qnt);
|
||||
self::loadQualifiers($qlf);
|
||||
self::loadTypes($tps);
|
||||
}else{
|
||||
self::loadSintatics(fopen($modifiersSrc.'sintatics.list', 'rb'));
|
||||
$qnt= simplexml_load_file($modifiersSrc.'quantifiers.xml');
|
||||
$qlf= simplexml_load_file($modifiersSrc.'qualifiers.xml');
|
||||
$tps= simplexml_load_file($modifiersSrc.'datatypes.xml');
|
||||
self::loadQuantifiers($qnt);
|
||||
self::loadQualifiers($qlf);
|
||||
self::loadTypes($tps);
|
||||
}
|
||||
self::$sintaticsList= Array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sweeps the content.
|
||||
*
|
||||
* This method runs through all the words within Mind::$content
|
||||
* and perform all verifications
|
||||
*
|
||||
* @return Array the spine, the whole structure of the abstracted text
|
||||
*/
|
||||
public function sweep($content=false)
|
||||
{
|
||||
if($content)
|
||||
$cont= $content;
|
||||
else
|
||||
$cont= &Mind::$content;
|
||||
|
||||
// seek for data types
|
||||
foreach(self::$dataTypes as $type=>$options)
|
||||
{
|
||||
$cont= preg_replace(
|
||||
"/\:".implode('(\(| )|\:', $options)."(\(| )/",
|
||||
':'.$type.'(',
|
||||
$cont
|
||||
);
|
||||
}
|
||||
|
||||
// adding each word as its token
|
||||
for($i=0, $j=sizeof($cont); $i<$j; $i++)
|
||||
{
|
||||
$word= strtolower($cont[$i]);
|
||||
$this->add($word);
|
||||
}
|
||||
|
||||
Mind::$syntaxer= new Syntaxer();
|
||||
return Token::$spine;
|
||||
}
|
||||
|
||||
/**
|
||||
* The constructor
|
||||
*/
|
||||
public function __construct(){
|
||||
Token::$spine= Array();
|
||||
self::$spine= Array();
|
||||
Token::$words= Array();
|
||||
Token::$string= "";
|
||||
self::loadModifiers();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,804 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console;
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Input\InputDefinition;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Output\Output;
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Command\HelpCommand;
|
||||
use Symfony\Component\Console\Command\ListCommand;
|
||||
use Symfony\Component\Console\Helper\HelperSet;
|
||||
use Symfony\Component\Console\Helper\FormatterHelper;
|
||||
use Symfony\Component\Console\Helper\DialogHelper;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* An Application is the container for a collection of commands.
|
||||
*
|
||||
* It is the main entry point of a Console application.
|
||||
*
|
||||
* This class is optimized for a standard CLI environment.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* $app = new Application('myapp', '1.0 (stable)');
|
||||
* $app->addCommand(new SimpleCommand());
|
||||
* $app->run();
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class Application
|
||||
{
|
||||
protected $commands;
|
||||
protected $aliases;
|
||||
protected $application;
|
||||
protected $wantHelps = false;
|
||||
protected $runningCommand;
|
||||
protected $name;
|
||||
protected $version;
|
||||
protected $catchExceptions;
|
||||
protected $autoExit;
|
||||
protected $definition;
|
||||
protected $helperSet;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $name The name of the application
|
||||
* @param string $version The version of the application
|
||||
*/
|
||||
public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->version = $version;
|
||||
$this->catchExceptions = true;
|
||||
$this->autoExit = true;
|
||||
$this->commands = array();
|
||||
$this->aliases = array();
|
||||
$this->helperSet = new HelperSet(array(
|
||||
new FormatterHelper(),
|
||||
new DialogHelper(),
|
||||
));
|
||||
|
||||
$this->addCommand(new HelpCommand());
|
||||
$this->addCommand(new ListCommand());
|
||||
|
||||
$this->definition = new InputDefinition(array(
|
||||
new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
|
||||
|
||||
new InputOption('--help', '-h', InputOption::PARAMETER_NONE, 'Display this help message.'),
|
||||
new InputOption('--quiet', '-q', InputOption::PARAMETER_NONE, 'Do not output any message.'),
|
||||
new InputOption('--verbose', '-v', InputOption::PARAMETER_NONE, 'Increase verbosity of messages.'),
|
||||
new InputOption('--version', '-V', InputOption::PARAMETER_NONE, 'Display this program version.'),
|
||||
new InputOption('--color', '-c', InputOption::PARAMETER_NONE, 'Force ANSI color output.'),
|
||||
new InputOption('--no-interaction', '-n', InputOption::PARAMETER_NONE, 'Do not ask any interactive question.'),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the current application.
|
||||
*
|
||||
* @param InputInterface $input An Input instance
|
||||
* @param OutputInterface $output An Output instance
|
||||
*
|
||||
* @return integer 0 if everything went fine, or an error code
|
||||
*/
|
||||
public function run(InputInterface $input = null, OutputInterface $output = null)
|
||||
{
|
||||
if (null === $input)
|
||||
{
|
||||
$input = new ArgvInput();
|
||||
}
|
||||
|
||||
if (null === $output)
|
||||
{
|
||||
$output = new ConsoleOutput();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$statusCode = $this->doRun($input, $output);
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
if (!$this->catchExceptions)
|
||||
{
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$this->renderException($e, $output);
|
||||
$statusCode = $e->getCode();
|
||||
|
||||
$statusCode = is_numeric($statusCode) && $statusCode ? $statusCode : 1;
|
||||
}
|
||||
|
||||
if ($this->autoExit)
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
exit($statusCode);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
else
|
||||
{
|
||||
return $statusCode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the current application.
|
||||
*
|
||||
* @param InputInterface $input An Input instance
|
||||
* @param OutputInterface $output An Output instance
|
||||
*
|
||||
* @return integer 0 if everything went fine, or an error code
|
||||
*/
|
||||
public function doRun(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$name = $input->getFirstArgument('command');
|
||||
|
||||
if (true === $input->hasParameterOption(array('--color', '-c')))
|
||||
{
|
||||
$output->setDecorated(true);
|
||||
}
|
||||
|
||||
if (true === $input->hasParameterOption(array('--help', '-H')))
|
||||
{
|
||||
if (!$name)
|
||||
{
|
||||
$name = 'help';
|
||||
$input = new ArrayInput(array('command' => 'help'));
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->wantHelps = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (true === $input->hasParameterOption(array('--no-interaction', '-n')))
|
||||
{
|
||||
$input->setInteractive(false);
|
||||
}
|
||||
|
||||
if (true === $input->hasParameterOption(array('--quiet', '-q')))
|
||||
{
|
||||
$output->setVerbosity(Output::VERBOSITY_QUIET);
|
||||
}
|
||||
elseif (true === $input->hasParameterOption(array('--verbose', '-v')))
|
||||
{
|
||||
$output->setVerbosity(Output::VERBOSITY_VERBOSE);
|
||||
}
|
||||
|
||||
if (true === $input->hasParameterOption(array('--version', '-V')))
|
||||
{
|
||||
$output->writeln($this->getLongVersion());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!$name)
|
||||
{
|
||||
$name = 'list';
|
||||
$input = new ArrayInput(array('command' => 'list'));
|
||||
}
|
||||
|
||||
// the command name MUST be the first element of the input
|
||||
$command = $this->findCommand($name);
|
||||
|
||||
$this->runningCommand = $command;
|
||||
$statusCode = $command->run($input, $output);
|
||||
$this->runningCommand = null;
|
||||
|
||||
return is_numeric($statusCode) ? $statusCode : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a helper set to be used with the command.
|
||||
*
|
||||
* @param HelperSet $helperSet The helper set
|
||||
*/
|
||||
public function setHelperSet(HelperSet $helperSet)
|
||||
{
|
||||
$this->helperSet = $helperSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the helper set associated with the command
|
||||
*
|
||||
* @return HelperSet The HelperSet isntance associated with this command
|
||||
*/
|
||||
public function getHelperSet()
|
||||
{
|
||||
return $this->helperSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the InputDefinition related to this Application.
|
||||
*
|
||||
* @return InputDefinition The InputDefinition instance
|
||||
*/
|
||||
public function getDefinition()
|
||||
{
|
||||
return $this->definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the help message.
|
||||
*
|
||||
* @return string A help message.
|
||||
*/
|
||||
public function getHelp()
|
||||
{
|
||||
$messages = array(
|
||||
$this->getLongVersion(),
|
||||
'',
|
||||
'<comment>Usage:</comment>',
|
||||
sprintf(" [options] command [arguments]\n"),
|
||||
'<comment>Options:</comment>',
|
||||
);
|
||||
|
||||
foreach ($this->definition->getOptions() as $option)
|
||||
{
|
||||
$messages[] = sprintf(' %-29s %s %s',
|
||||
'<info>--'.$option->getName().'</info>',
|
||||
$option->getShortcut() ? '<info>-'.$option->getShortcut().'</info>' : ' ',
|
||||
$option->getDescription()
|
||||
);
|
||||
}
|
||||
|
||||
return implode("\n", $messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to catch exceptions or not during commands execution.
|
||||
*
|
||||
* @param Boolean $boolean Whether to catch exceptions or not during commands execution
|
||||
*/
|
||||
public function setCatchExceptions($boolean)
|
||||
{
|
||||
$this->catchExceptions = (Boolean) $boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to automatically exit after a command execution or not.
|
||||
*
|
||||
* @param Boolean $boolean Whether to automatically exit after a command execution or not
|
||||
*/
|
||||
public function setAutoExit($boolean)
|
||||
{
|
||||
$this->autoExit = (Boolean) $boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the application.
|
||||
*
|
||||
* @return string The application name
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the application name.
|
||||
*
|
||||
* @param string $name The application name
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the application version.
|
||||
*
|
||||
* @return string The application version
|
||||
*/
|
||||
public function getVersion()
|
||||
{
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the application version.
|
||||
*
|
||||
* @param string $version The application version
|
||||
*/
|
||||
public function setVersion($version)
|
||||
{
|
||||
$this->version = $version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the long version of the application.
|
||||
*
|
||||
* @return string The long application version
|
||||
*/
|
||||
public function getLongVersion()
|
||||
{
|
||||
if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion())
|
||||
{
|
||||
return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
|
||||
}
|
||||
else
|
||||
{
|
||||
return '<info>Console Tool</info>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new command.
|
||||
*
|
||||
* @param string $name The command name
|
||||
*
|
||||
* @return Command The newly created command
|
||||
*/
|
||||
public function register($name)
|
||||
{
|
||||
return $this->addCommand(new Command($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an array of command objects.
|
||||
*
|
||||
* @param array $commands An array of commands
|
||||
*/
|
||||
public function addCommands(array $commands)
|
||||
{
|
||||
foreach ($commands as $command)
|
||||
{
|
||||
$this->addCommand($command);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a command object.
|
||||
*
|
||||
* If a command with the same name already exists, it will be overridden.
|
||||
*
|
||||
* @param Command $command A Command object
|
||||
*
|
||||
* @return Command The registered command
|
||||
*/
|
||||
public function addCommand(Command $command)
|
||||
{
|
||||
$command->setApplication($this);
|
||||
|
||||
$this->commands[$command->getFullName()] = $command;
|
||||
|
||||
foreach ($command->getAliases() as $alias)
|
||||
{
|
||||
$this->aliases[$alias] = $command;
|
||||
}
|
||||
|
||||
return $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a registered command by name or alias.
|
||||
*
|
||||
* @param string $name The command name or alias
|
||||
*
|
||||
* @return Command A Command object
|
||||
*/
|
||||
public function getCommand($name)
|
||||
{
|
||||
if (!isset($this->commands[$name]) && !isset($this->aliases[$name]))
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name));
|
||||
}
|
||||
|
||||
$command = isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
|
||||
|
||||
if ($this->wantHelps)
|
||||
{
|
||||
$this->wantHelps = false;
|
||||
|
||||
$helpCommand = $this->getCommand('help');
|
||||
$helpCommand->setCommand($command);
|
||||
|
||||
return $helpCommand;
|
||||
}
|
||||
|
||||
return $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the command exists, false otherwise
|
||||
*
|
||||
* @param string $name The command name or alias
|
||||
*
|
||||
* @return Boolean true if the command exists, false otherwise
|
||||
*/
|
||||
public function hasCommand($name)
|
||||
{
|
||||
return isset($this->commands[$name]) || isset($this->aliases[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all unique namespaces used by currently registered commands.
|
||||
*
|
||||
* It does not returns the global namespace which always exists.
|
||||
*
|
||||
* @return array An array of namespaces
|
||||
*/
|
||||
public function getNamespaces()
|
||||
{
|
||||
$namespaces = array();
|
||||
foreach ($this->commands as $command)
|
||||
{
|
||||
if ($command->getNamespace())
|
||||
{
|
||||
$namespaces[$command->getNamespace()] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return array_keys($namespaces);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a registered namespace by a name or an abbreviation.
|
||||
*
|
||||
* @return string A registered namespace
|
||||
*/
|
||||
public function findNamespace($namespace)
|
||||
{
|
||||
$abbrevs = static::getAbbreviations($this->getNamespaces());
|
||||
|
||||
if (!isset($abbrevs[$namespace]))
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('There are no commands defined in the "%s" namespace.', $namespace));
|
||||
}
|
||||
|
||||
if (count($abbrevs[$namespace]) > 1)
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions($abbrevs[$namespace])));
|
||||
}
|
||||
|
||||
return $abbrevs[$namespace][0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a command by name or alias.
|
||||
*
|
||||
* Contrary to getCommand, this command tries to find the best
|
||||
* match if you give it an abbreviation of a name or alias.
|
||||
*
|
||||
* @param string $name A command name or a command alias
|
||||
*
|
||||
* @return Command A Command instance
|
||||
*/
|
||||
public function findCommand($name)
|
||||
{
|
||||
// namespace
|
||||
$namespace = '';
|
||||
if (false !== $pos = strrpos($name, ':'))
|
||||
{
|
||||
$namespace = $this->findNamespace(substr($name, 0, $pos));
|
||||
$name = substr($name, $pos + 1);
|
||||
}
|
||||
|
||||
$fullName = $namespace ? $namespace.':'.$name : $name;
|
||||
|
||||
// name
|
||||
$commands = array();
|
||||
foreach ($this->commands as $command)
|
||||
{
|
||||
if ($command->getNamespace() == $namespace)
|
||||
{
|
||||
$commands[] = $command->getName();
|
||||
}
|
||||
}
|
||||
|
||||
$abbrevs = static::getAbbreviations($commands);
|
||||
if (isset($abbrevs[$name]) && 1 == count($abbrevs[$name]))
|
||||
{
|
||||
return $this->getCommand($namespace ? $namespace.':'.$abbrevs[$name][0] : $abbrevs[$name][0]);
|
||||
}
|
||||
|
||||
if (isset($abbrevs[$name]) && count($abbrevs[$name]) > 1)
|
||||
{
|
||||
$suggestions = $this->getAbbreviationSuggestions(array_map(function ($command) use ($namespace) { return $namespace.':'.$command; }, $abbrevs[$name]));
|
||||
|
||||
throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $fullName, $suggestions));
|
||||
}
|
||||
|
||||
// aliases
|
||||
$abbrevs = static::getAbbreviations(array_keys($this->aliases));
|
||||
if (!isset($abbrevs[$fullName]))
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('Command "%s" is not defined.', $fullName));
|
||||
}
|
||||
|
||||
if (count($abbrevs[$fullName]) > 1)
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $fullName, $this->getAbbreviationSuggestions($abbrevs[$fullName])));
|
||||
}
|
||||
|
||||
return $this->getCommand($abbrevs[$fullName][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the commands (registered in the given namespace if provided).
|
||||
*
|
||||
* The array keys are the full names and the values the command instances.
|
||||
*
|
||||
* @param string $namespace A namespace name
|
||||
*
|
||||
* @return array An array of Command instances
|
||||
*/
|
||||
public function getCommands($namespace = null)
|
||||
{
|
||||
if (null === $namespace)
|
||||
{
|
||||
return $this->commands;
|
||||
}
|
||||
|
||||
$commands = array();
|
||||
foreach ($this->commands as $name => $command)
|
||||
{
|
||||
if ($namespace === $command->getNamespace())
|
||||
{
|
||||
$commands[$name] = $command;
|
||||
}
|
||||
}
|
||||
|
||||
return $commands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of possible abbreviations given a set of names.
|
||||
*
|
||||
* @param array An array of names
|
||||
*
|
||||
* @return array An array of abbreviations
|
||||
*/
|
||||
static public function getAbbreviations($names)
|
||||
{
|
||||
$abbrevs = array();
|
||||
foreach ($names as $name)
|
||||
{
|
||||
for ($len = strlen($name) - 1; $len > 0; --$len)
|
||||
{
|
||||
$abbrev = substr($name, 0, $len);
|
||||
if (!isset($abbrevs[$abbrev]))
|
||||
{
|
||||
$abbrevs[$abbrev] = array($name);
|
||||
}
|
||||
else
|
||||
{
|
||||
$abbrevs[$abbrev][] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Non-abbreviations always get entered, even if they aren't unique
|
||||
foreach ($names as $name)
|
||||
{
|
||||
$abbrevs[$name] = array($name);
|
||||
}
|
||||
|
||||
return $abbrevs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a text representation of the Application.
|
||||
*
|
||||
* @param string $namespace An optional namespace name
|
||||
*
|
||||
* @return string A string representing the Application
|
||||
*/
|
||||
public function asText($namespace = null)
|
||||
{
|
||||
$commands = $namespace ? $this->getCommands($this->findNamespace($namespace)) : $this->commands;
|
||||
|
||||
$messages = array($this->getHelp(), '');
|
||||
if ($namespace)
|
||||
{
|
||||
$messages[] = sprintf("<comment>Available commands for the \"%s\" namespace:</comment>", $namespace);
|
||||
}
|
||||
else
|
||||
{
|
||||
$messages[] = '<comment>Available commands:</comment>';
|
||||
}
|
||||
|
||||
$width = 0;
|
||||
foreach ($commands as $command)
|
||||
{
|
||||
$width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width;
|
||||
}
|
||||
$width += 2;
|
||||
|
||||
// add commands by namespace
|
||||
foreach ($this->sortCommands($commands) as $space => $commands)
|
||||
{
|
||||
if (!$namespace && '_global' !== $space)
|
||||
{
|
||||
$messages[] = '<comment>'.$space.'</comment>';
|
||||
}
|
||||
|
||||
foreach ($commands as $command)
|
||||
{
|
||||
$aliases = $command->getAliases() ? '<comment> ('.implode(', ', $command->getAliases()).')</comment>' : '';
|
||||
|
||||
$messages[] = sprintf(" <info>%-${width}s</info> %s%s", ($command->getNamespace() ? ':' : '').$command->getName(), $command->getDescription(), $aliases);
|
||||
}
|
||||
}
|
||||
|
||||
return implode("\n", $messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an XML representation of the Application.
|
||||
*
|
||||
* @param string $namespace An optional namespace name
|
||||
* @param Boolean $asDom Whether to return a DOM or an XML string
|
||||
*
|
||||
* @return string|DOMDocument An XML string representing the Application
|
||||
*/
|
||||
public function asXml($namespace = null, $asDom = false)
|
||||
{
|
||||
$commands = $namespace ? $this->getCommands($this->findNamespace($namespace)) : $this->commands;
|
||||
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->formatOutput = true;
|
||||
$dom->appendChild($xml = $dom->createElement('symfony'));
|
||||
|
||||
$xml->appendChild($commandsXML = $dom->createElement('commands'));
|
||||
|
||||
if ($namespace)
|
||||
{
|
||||
$commandsXML->setAttribute('namespace', $namespace);
|
||||
}
|
||||
else
|
||||
{
|
||||
$xml->appendChild($namespacesXML = $dom->createElement('namespaces'));
|
||||
}
|
||||
|
||||
// add commands by namespace
|
||||
foreach ($this->sortCommands($commands) as $space => $commands)
|
||||
{
|
||||
if (!$namespace)
|
||||
{
|
||||
$namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
|
||||
$namespaceArrayXML->setAttribute('id', $space);
|
||||
}
|
||||
|
||||
foreach ($commands as $command)
|
||||
{
|
||||
if (!$namespace)
|
||||
{
|
||||
$namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
|
||||
$commandXML->appendChild($dom->createTextNode($command->getName()));
|
||||
}
|
||||
|
||||
$commandXML = new \DOMDocument('1.0', 'UTF-8');
|
||||
$commandXML->formatOutput = true;
|
||||
$commandXML->loadXML($command->asXml());
|
||||
$node = $commandXML->getElementsByTagName('command')->item(0);
|
||||
$node = $dom->importNode($node, true);
|
||||
|
||||
$commandsXML->appendChild($node);
|
||||
}
|
||||
}
|
||||
|
||||
return $asDom ? $dom : $dom->saveXml();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a catched exception.
|
||||
*
|
||||
* @param Exception $e An exception instance
|
||||
* @param OutputInterface $output An OutputInterface instance
|
||||
*/
|
||||
public function renderException($e, $output)
|
||||
{
|
||||
$strlen = function ($string)
|
||||
{
|
||||
return function_exists('mb_strlen') ? mb_strlen($string) : strlen($string);
|
||||
};
|
||||
|
||||
$title = sprintf(' [%s] ', get_class($e));
|
||||
$len = $strlen($title);
|
||||
$lines = array();
|
||||
foreach (explode("\n", $e->getMessage()) as $line)
|
||||
{
|
||||
$lines[] = sprintf(' %s ', $line);
|
||||
$len = max($strlen($line) + 4, $len);
|
||||
}
|
||||
|
||||
$messages = array(str_repeat(' ', $len), $title.str_repeat(' ', $len - $strlen($title)));
|
||||
|
||||
foreach ($lines as $line)
|
||||
{
|
||||
$messages[] = $line.str_repeat(' ', $len - $strlen($line));
|
||||
}
|
||||
|
||||
$messages[] = str_repeat(' ', $len);
|
||||
|
||||
$output->writeln("\n");
|
||||
foreach ($messages as $message)
|
||||
{
|
||||
$output->writeln("<error>$message</error>");
|
||||
}
|
||||
$output->writeln("\n");
|
||||
|
||||
if (null !== $this->runningCommand)
|
||||
{
|
||||
$output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())));
|
||||
$output->writeln("\n");
|
||||
}
|
||||
|
||||
if (Output::VERBOSITY_VERBOSE === $output->getVerbosity())
|
||||
{
|
||||
$output->writeln('</comment>Exception trace:</comment>');
|
||||
|
||||
// exception related properties
|
||||
$trace = $e->getTrace();
|
||||
array_unshift($trace, array(
|
||||
'function' => '',
|
||||
'file' => $e->getFile() != null ? $e->getFile() : 'n/a',
|
||||
'line' => $e->getLine() != null ? $e->getLine() : 'n/a',
|
||||
'args' => array(),
|
||||
));
|
||||
|
||||
for ($i = 0, $count = count($trace); $i < $count; $i++)
|
||||
{
|
||||
$class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
|
||||
$type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
|
||||
$function = $trace[$i]['function'];
|
||||
$file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
|
||||
$line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
|
||||
|
||||
$output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line));
|
||||
}
|
||||
|
||||
$output->writeln("\n");
|
||||
}
|
||||
}
|
||||
|
||||
private function sortCommands($commands)
|
||||
{
|
||||
$namespacedCommands = array();
|
||||
foreach ($commands as $name => $command)
|
||||
{
|
||||
$key = $command->getNamespace() ? $command->getNamespace() : '_global';
|
||||
|
||||
if (!isset($namespacedCommands[$key]))
|
||||
{
|
||||
$namespacedCommands[$key] = array();
|
||||
}
|
||||
|
||||
$namespacedCommands[$key][$name] = $command;
|
||||
}
|
||||
ksort($namespacedCommands);
|
||||
|
||||
foreach ($namespacedCommands as $name => &$commands)
|
||||
{
|
||||
ksort($commands);
|
||||
}
|
||||
|
||||
return $namespacedCommands;
|
||||
}
|
||||
|
||||
private function getAbbreviationSuggestions($abbrevs)
|
||||
{
|
||||
return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : '');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,809 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console;
|
||||
/*include('Helper/HelperSet.php');
|
||||
include('Helper/HelperInterface.php');
|
||||
include('Helper/Helper.php');
|
||||
include('Helper/DialogHelper.php');
|
||||
include('Helper/FormatterHelper.php');*/
|
||||
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\ArgvInput;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
use Symfony\Component\Console\Input\InputDefinition;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Output\Output;
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Command\HelpCommand;
|
||||
use Symfony\Component\Console\Command\ListCommand;
|
||||
use Symfony\Component\Console\Helper\HelperSet;
|
||||
use Symfony\Component\Console\Helper\FormatterHelper;
|
||||
use Symfony\Component\Console\Helper\DialogHelper;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* An Application is the container for a collection of commands.
|
||||
*
|
||||
* It is the main entry point of a Console application.
|
||||
*
|
||||
* This class is optimized for a standard CLI environment.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* $app = new Application('myapp', '1.0 (stable)');
|
||||
* $app->addCommand(new SimpleCommand());
|
||||
* $app->run();
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class Application
|
||||
{
|
||||
protected $commands;
|
||||
protected $aliases;
|
||||
protected $application;
|
||||
protected $wantHelps = false;
|
||||
protected $runningCommand;
|
||||
protected $name;
|
||||
protected $version;
|
||||
protected $catchExceptions;
|
||||
protected $autoExit;
|
||||
protected $definition;
|
||||
protected $helperSet;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $name The name of the application
|
||||
* @param string $version The version of the application
|
||||
*/
|
||||
public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN')
|
||||
{
|
||||
$this->name = $name;
|
||||
$this->version = $version;
|
||||
$this->catchExceptions = true;
|
||||
$this->autoExit = true;
|
||||
$this->commands = array();
|
||||
$this->aliases = array();
|
||||
$this->helperSet = new HelperSet(array(
|
||||
new FormatterHelper(),
|
||||
new DialogHelper(),
|
||||
));
|
||||
|
||||
$this->addCommand(new HelpCommand());
|
||||
$this->addCommand(new ListCommand());
|
||||
|
||||
$this->definition = new InputDefinition(array(
|
||||
new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'),
|
||||
|
||||
new InputOption('--help', '-h', InputOption::PARAMETER_NONE, 'Display this help message.'),
|
||||
new InputOption('--quiet', '-q', InputOption::PARAMETER_NONE, 'Do not output any message.'),
|
||||
new InputOption('--verbose', '-v', InputOption::PARAMETER_NONE, 'Increase verbosity of messages.'),
|
||||
new InputOption('--version', '-V', InputOption::PARAMETER_NONE, 'Display this program version.'),
|
||||
new InputOption('--color', '-c', InputOption::PARAMETER_NONE, 'Force ANSI color output.'),
|
||||
new InputOption('--no-interaction', '-n', InputOption::PARAMETER_NONE, 'Do not ask any interactive question.'),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the current application.
|
||||
*
|
||||
* @param InputInterface $input An Input instance
|
||||
* @param OutputInterface $output An Output instance
|
||||
*
|
||||
* @return integer 0 if everything went fine, or an error code
|
||||
*/
|
||||
public function run(InputInterface $input = null, OutputInterface $output = null)
|
||||
{
|
||||
if (null === $input)
|
||||
{
|
||||
$input = new ArgvInput();
|
||||
}
|
||||
|
||||
if (null === $output)
|
||||
{
|
||||
$output = new ConsoleOutput();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
$statusCode = $this->doRun($input, $output);
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
if (!$this->catchExceptions)
|
||||
{
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$this->renderException($e, $output);
|
||||
$statusCode = $e->getCode();
|
||||
|
||||
$statusCode = is_numeric($statusCode) && $statusCode ? $statusCode : 1;
|
||||
}
|
||||
|
||||
if ($this->autoExit)
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
exit($statusCode);
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
else
|
||||
{
|
||||
return $statusCode;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the current application.
|
||||
*
|
||||
* @param InputInterface $input An Input instance
|
||||
* @param OutputInterface $output An Output instance
|
||||
*
|
||||
* @return integer 0 if everything went fine, or an error code
|
||||
*/
|
||||
public function doRun(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$name = $input->getFirstArgument('command');
|
||||
|
||||
if (true === $input->hasParameterOption(array('--color', '-c')))
|
||||
{
|
||||
$output->setDecorated(true);
|
||||
}
|
||||
|
||||
if (true === $input->hasParameterOption(array('--help', '-H')))
|
||||
{
|
||||
if (!$name)
|
||||
{
|
||||
$name = 'help';
|
||||
$input = new ArrayInput(array('command' => 'help'));
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->wantHelps = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (true === $input->hasParameterOption(array('--no-interaction', '-n')))
|
||||
{
|
||||
$input->setInteractive(false);
|
||||
}
|
||||
|
||||
if (true === $input->hasParameterOption(array('--quiet', '-q')))
|
||||
{
|
||||
$output->setVerbosity(Output::VERBOSITY_QUIET);
|
||||
}
|
||||
elseif (true === $input->hasParameterOption(array('--verbose', '-v')))
|
||||
{
|
||||
$output->setVerbosity(Output::VERBOSITY_VERBOSE);
|
||||
}
|
||||
|
||||
if (true === $input->hasParameterOption(array('--version', '-V')))
|
||||
{
|
||||
$output->writeln($this->getLongVersion());
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!$name)
|
||||
{
|
||||
$name = 'list';
|
||||
$input = new ArrayInput(array('command' => 'list'));
|
||||
}
|
||||
|
||||
// the command name MUST be the first element of the input
|
||||
$command = $this->findCommand($name);
|
||||
|
||||
$this->runningCommand = $command;
|
||||
$statusCode = $command->run($input, $output);
|
||||
$this->runningCommand = null;
|
||||
|
||||
return is_numeric($statusCode) ? $statusCode : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a helper set to be used with the command.
|
||||
*
|
||||
* @param HelperSet $helperSet The helper set
|
||||
*/
|
||||
public function setHelperSet(HelperSet $helperSet)
|
||||
{
|
||||
$this->helperSet = $helperSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the helper set associated with the command
|
||||
*
|
||||
* @return HelperSet The HelperSet isntance associated with this command
|
||||
*/
|
||||
public function getHelperSet()
|
||||
{
|
||||
return $this->helperSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the InputDefinition related to this Application.
|
||||
*
|
||||
* @return InputDefinition The InputDefinition instance
|
||||
*/
|
||||
public function getDefinition()
|
||||
{
|
||||
return $this->definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the help message.
|
||||
*
|
||||
* @return string A help message.
|
||||
*/
|
||||
public function getHelp()
|
||||
{
|
||||
$messages = array(
|
||||
$this->getLongVersion(),
|
||||
'',
|
||||
'<comment>Usage:</comment>',
|
||||
sprintf(" [options] command [arguments]\n"),
|
||||
'<comment>Options:</comment>',
|
||||
);
|
||||
|
||||
foreach ($this->definition->getOptions() as $option)
|
||||
{
|
||||
$messages[] = sprintf(' %-29s %s %s',
|
||||
'<info>--'.$option->getName().'</info>',
|
||||
$option->getShortcut() ? '<info>-'.$option->getShortcut().'</info>' : ' ',
|
||||
$option->getDescription()
|
||||
);
|
||||
}
|
||||
|
||||
return implode("\n", $messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to catch exceptions or not during commands execution.
|
||||
*
|
||||
* @param Boolean $boolean Whether to catch exceptions or not during commands execution
|
||||
*/
|
||||
public function setCatchExceptions($boolean)
|
||||
{
|
||||
$this->catchExceptions = (Boolean) $boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to automatically exit after a command execution or not.
|
||||
*
|
||||
* @param Boolean $boolean Whether to automatically exit after a command execution or not
|
||||
*/
|
||||
public function setAutoExit($boolean)
|
||||
{
|
||||
$this->autoExit = (Boolean) $boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of the application.
|
||||
*
|
||||
* @return string The application name
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the application name.
|
||||
*
|
||||
* @param string $name The application name
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
$this->name = $name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the application version.
|
||||
*
|
||||
* @return string The application version
|
||||
*/
|
||||
public function getVersion()
|
||||
{
|
||||
return $this->version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the application version.
|
||||
*
|
||||
* @param string $version The application version
|
||||
*/
|
||||
public function setVersion($version)
|
||||
{
|
||||
$this->version = $version;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the long version of the application.
|
||||
*
|
||||
* @return string The long application version
|
||||
*/
|
||||
public function getLongVersion()
|
||||
{
|
||||
if ('UNKNOWN' !== $this->getName() && 'UNKNOWN' !== $this->getVersion())
|
||||
{
|
||||
return sprintf('<info>%s</info> version <comment>%s</comment>', $this->getName(), $this->getVersion());
|
||||
}
|
||||
else
|
||||
{
|
||||
return '<info>Console Tool</info>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new command.
|
||||
*
|
||||
* @param string $name The command name
|
||||
*
|
||||
* @return Command The newly created command
|
||||
*/
|
||||
public function register($name)
|
||||
{
|
||||
return $this->addCommand(new Command($name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an array of command objects.
|
||||
*
|
||||
* @param array $commands An array of commands
|
||||
*/
|
||||
public function addCommands(array $commands)
|
||||
{
|
||||
foreach ($commands as $command)
|
||||
{
|
||||
$this->addCommand($command);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a command object.
|
||||
*
|
||||
* If a command with the same name already exists, it will be overridden.
|
||||
*
|
||||
* @param Command $command A Command object
|
||||
*
|
||||
* @return Command The registered command
|
||||
*/
|
||||
public function addCommand(Command $command)
|
||||
{
|
||||
$command->setApplication($this);
|
||||
|
||||
$this->commands[$command->getFullName()] = $command;
|
||||
|
||||
foreach ($command->getAliases() as $alias)
|
||||
{
|
||||
$this->aliases[$alias] = $command;
|
||||
}
|
||||
|
||||
return $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a registered command by name or alias.
|
||||
*
|
||||
* @param string $name The command name or alias
|
||||
*
|
||||
* @return Command A Command object
|
||||
*/
|
||||
public function getCommand($name)
|
||||
{
|
||||
if (!isset($this->commands[$name]) && !isset($this->aliases[$name]))
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name));
|
||||
}
|
||||
|
||||
$command = isset($this->commands[$name]) ? $this->commands[$name] : $this->aliases[$name];
|
||||
|
||||
if ($this->wantHelps)
|
||||
{
|
||||
$this->wantHelps = false;
|
||||
|
||||
$helpCommand = $this->getCommand('help');
|
||||
$helpCommand->setCommand($command);
|
||||
|
||||
return $helpCommand;
|
||||
}
|
||||
|
||||
return $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the command exists, false otherwise
|
||||
*
|
||||
* @param string $name The command name or alias
|
||||
*
|
||||
* @return Boolean true if the command exists, false otherwise
|
||||
*/
|
||||
public function hasCommand($name)
|
||||
{
|
||||
return isset($this->commands[$name]) || isset($this->aliases[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all unique namespaces used by currently registered commands.
|
||||
*
|
||||
* It does not returns the global namespace which always exists.
|
||||
*
|
||||
* @return array An array of namespaces
|
||||
*/
|
||||
public function getNamespaces()
|
||||
{
|
||||
$namespaces = array();
|
||||
foreach ($this->commands as $command)
|
||||
{
|
||||
if ($command->getNamespace())
|
||||
{
|
||||
$namespaces[$command->getNamespace()] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return array_keys($namespaces);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a registered namespace by a name or an abbreviation.
|
||||
*
|
||||
* @return string A registered namespace
|
||||
*/
|
||||
public function findNamespace($namespace)
|
||||
{
|
||||
$abbrevs = static::getAbbreviations($this->getNamespaces());
|
||||
|
||||
if (!isset($abbrevs[$namespace]))
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('There are no commands defined in the "%s" namespace.', $namespace));
|
||||
}
|
||||
|
||||
if (count($abbrevs[$namespace]) > 1)
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('The namespace "%s" is ambiguous (%s).', $namespace, $this->getAbbreviationSuggestions($abbrevs[$namespace])));
|
||||
}
|
||||
|
||||
return $abbrevs[$namespace][0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a command by name or alias.
|
||||
*
|
||||
* Contrary to getCommand, this command tries to find the best
|
||||
* match if you give it an abbreviation of a name or alias.
|
||||
*
|
||||
* @param string $name A command name or a command alias
|
||||
*
|
||||
* @return Command A Command instance
|
||||
*/
|
||||
public function findCommand($name)
|
||||
{
|
||||
// namespace
|
||||
$namespace = '';
|
||||
if (false !== $pos = strrpos($name, ':'))
|
||||
{
|
||||
$namespace = $this->findNamespace(substr($name, 0, $pos));
|
||||
$name = substr($name, $pos + 1);
|
||||
}
|
||||
|
||||
$fullName = $namespace ? $namespace.':'.$name : $name;
|
||||
|
||||
// name
|
||||
$commands = array();
|
||||
foreach ($this->commands as $command)
|
||||
{
|
||||
if ($command->getNamespace() == $namespace)
|
||||
{
|
||||
$commands[] = $command->getName();
|
||||
}
|
||||
}
|
||||
|
||||
$abbrevs = static::getAbbreviations($commands);
|
||||
if (isset($abbrevs[$name]) && 1 == count($abbrevs[$name]))
|
||||
{
|
||||
return $this->getCommand($namespace ? $namespace.':'.$abbrevs[$name][0] : $abbrevs[$name][0]);
|
||||
}
|
||||
|
||||
if (isset($abbrevs[$name]) && count($abbrevs[$name]) > 1)
|
||||
{
|
||||
$suggestions = $this->getAbbreviationSuggestions(array_map(function ($command) use ($namespace) { return $namespace.':'.$command; }, $abbrevs[$name]));
|
||||
|
||||
throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $fullName, $suggestions));
|
||||
}
|
||||
|
||||
// aliases
|
||||
$abbrevs = static::getAbbreviations(array_keys($this->aliases));
|
||||
if (!isset($abbrevs[$fullName]))
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('Command "%s" is not defined.', $fullName));
|
||||
}
|
||||
|
||||
if (count($abbrevs[$fullName]) > 1)
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('Command "%s" is ambiguous (%s).', $fullName, $this->getAbbreviationSuggestions($abbrevs[$fullName])));
|
||||
}
|
||||
|
||||
return $this->getCommand($abbrevs[$fullName][0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the commands (registered in the given namespace if provided).
|
||||
*
|
||||
* The array keys are the full names and the values the command instances.
|
||||
*
|
||||
* @param string $namespace A namespace name
|
||||
*
|
||||
* @return array An array of Command instances
|
||||
*/
|
||||
public function getCommands($namespace = null)
|
||||
{
|
||||
if (null === $namespace)
|
||||
{
|
||||
return $this->commands;
|
||||
}
|
||||
|
||||
$commands = array();
|
||||
foreach ($this->commands as $name => $command)
|
||||
{
|
||||
if ($namespace === $command->getNamespace())
|
||||
{
|
||||
$commands[$name] = $command;
|
||||
}
|
||||
}
|
||||
|
||||
return $commands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of possible abbreviations given a set of names.
|
||||
*
|
||||
* @param array An array of names
|
||||
*
|
||||
* @return array An array of abbreviations
|
||||
*/
|
||||
static public function getAbbreviations($names)
|
||||
{
|
||||
$abbrevs = array();
|
||||
foreach ($names as $name)
|
||||
{
|
||||
for ($len = strlen($name) - 1; $len > 0; --$len)
|
||||
{
|
||||
$abbrev = substr($name, 0, $len);
|
||||
if (!isset($abbrevs[$abbrev]))
|
||||
{
|
||||
$abbrevs[$abbrev] = array($name);
|
||||
}
|
||||
else
|
||||
{
|
||||
$abbrevs[$abbrev][] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Non-abbreviations always get entered, even if they aren't unique
|
||||
foreach ($names as $name)
|
||||
{
|
||||
$abbrevs[$name] = array($name);
|
||||
}
|
||||
|
||||
return $abbrevs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a text representation of the Application.
|
||||
*
|
||||
* @param string $namespace An optional namespace name
|
||||
*
|
||||
* @return string A string representing the Application
|
||||
*/
|
||||
public function asText($namespace = null)
|
||||
{
|
||||
$commands = $namespace ? $this->getCommands($this->findNamespace($namespace)) : $this->commands;
|
||||
|
||||
$messages = array($this->getHelp(), '');
|
||||
if ($namespace)
|
||||
{
|
||||
$messages[] = sprintf("<comment>Available commands for the \"%s\" namespace:</comment>", $namespace);
|
||||
}
|
||||
else
|
||||
{
|
||||
$messages[] = '<comment>Available commands:</comment>';
|
||||
}
|
||||
|
||||
$width = 0;
|
||||
foreach ($commands as $command)
|
||||
{
|
||||
$width = strlen($command->getName()) > $width ? strlen($command->getName()) : $width;
|
||||
}
|
||||
$width += 2;
|
||||
|
||||
// add commands by namespace
|
||||
foreach ($this->sortCommands($commands) as $space => $commands)
|
||||
{
|
||||
if (!$namespace && '_global' !== $space)
|
||||
{
|
||||
$messages[] = '<comment>'.$space.'</comment>';
|
||||
}
|
||||
|
||||
foreach ($commands as $command)
|
||||
{
|
||||
$aliases = $command->getAliases() ? '<comment> ('.implode(', ', $command->getAliases()).')</comment>' : '';
|
||||
|
||||
$messages[] = sprintf(" <info>%-${width}s</info> %s%s", ($command->getNamespace() ? ':' : '').$command->getName(), $command->getDescription(), $aliases);
|
||||
}
|
||||
}
|
||||
|
||||
return implode("\n", $messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an XML representation of the Application.
|
||||
*
|
||||
* @param string $namespace An optional namespace name
|
||||
* @param Boolean $asDom Whether to return a DOM or an XML string
|
||||
*
|
||||
* @return string|DOMDocument An XML string representing the Application
|
||||
*/
|
||||
public function asXml($namespace = null, $asDom = false)
|
||||
{
|
||||
$commands = $namespace ? $this->getCommands($this->findNamespace($namespace)) : $this->commands;
|
||||
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->formatOutput = true;
|
||||
$dom->appendChild($xml = $dom->createElement('symfony'));
|
||||
|
||||
$xml->appendChild($commandsXML = $dom->createElement('commands'));
|
||||
|
||||
if ($namespace)
|
||||
{
|
||||
$commandsXML->setAttribute('namespace', $namespace);
|
||||
}
|
||||
else
|
||||
{
|
||||
$xml->appendChild($namespacesXML = $dom->createElement('namespaces'));
|
||||
}
|
||||
|
||||
// add commands by namespace
|
||||
foreach ($this->sortCommands($commands) as $space => $commands)
|
||||
{
|
||||
if (!$namespace)
|
||||
{
|
||||
$namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
|
||||
$namespaceArrayXML->setAttribute('id', $space);
|
||||
}
|
||||
|
||||
foreach ($commands as $command)
|
||||
{
|
||||
if (!$namespace)
|
||||
{
|
||||
$namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
|
||||
$commandXML->appendChild($dom->createTextNode($command->getName()));
|
||||
}
|
||||
|
||||
$commandXML = new \DOMDocument('1.0', 'UTF-8');
|
||||
$commandXML->formatOutput = true;
|
||||
$commandXML->loadXML($command->asXml());
|
||||
$node = $commandXML->getElementsByTagName('command')->item(0);
|
||||
$node = $dom->importNode($node, true);
|
||||
|
||||
$commandsXML->appendChild($node);
|
||||
}
|
||||
}
|
||||
|
||||
return $asDom ? $dom : $dom->saveXml();
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a catched exception.
|
||||
*
|
||||
* @param Exception $e An exception instance
|
||||
* @param OutputInterface $output An OutputInterface instance
|
||||
*/
|
||||
public function renderException($e, $output)
|
||||
{
|
||||
$strlen = function ($string)
|
||||
{
|
||||
return function_exists('mb_strlen') ? mb_strlen($string) : strlen($string);
|
||||
};
|
||||
|
||||
$title = sprintf(' [%s] ', get_class($e));
|
||||
$len = $strlen($title);
|
||||
$lines = array();
|
||||
foreach (explode("\n", $e->getMessage()) as $line)
|
||||
{
|
||||
$lines[] = sprintf(' %s ', $line);
|
||||
$len = max($strlen($line) + 4, $len);
|
||||
}
|
||||
|
||||
$messages = array(str_repeat(' ', $len), $title.str_repeat(' ', $len - $strlen($title)));
|
||||
|
||||
foreach ($lines as $line)
|
||||
{
|
||||
$messages[] = $line.str_repeat(' ', $len - $strlen($line));
|
||||
}
|
||||
|
||||
$messages[] = str_repeat(' ', $len);
|
||||
|
||||
$output->writeln("\n");
|
||||
foreach ($messages as $message)
|
||||
{
|
||||
$output->writeln("<error>$message</error>");
|
||||
}
|
||||
$output->writeln("\n");
|
||||
|
||||
if (null !== $this->runningCommand)
|
||||
{
|
||||
$output->writeln(sprintf('<info>%s</info>', sprintf($this->runningCommand->getSynopsis(), $this->getName())));
|
||||
$output->writeln("\n");
|
||||
}
|
||||
|
||||
if (Output::VERBOSITY_VERBOSE === $output->getVerbosity())
|
||||
{
|
||||
$output->writeln('</comment>Exception trace:</comment>');
|
||||
|
||||
// exception related properties
|
||||
$trace = $e->getTrace();
|
||||
array_unshift($trace, array(
|
||||
'function' => '',
|
||||
'file' => $e->getFile() != null ? $e->getFile() : 'n/a',
|
||||
'line' => $e->getLine() != null ? $e->getLine() : 'n/a',
|
||||
'args' => array(),
|
||||
));
|
||||
|
||||
for ($i = 0, $count = count($trace); $i < $count; $i++)
|
||||
{
|
||||
$class = isset($trace[$i]['class']) ? $trace[$i]['class'] : '';
|
||||
$type = isset($trace[$i]['type']) ? $trace[$i]['type'] : '';
|
||||
$function = $trace[$i]['function'];
|
||||
$file = isset($trace[$i]['file']) ? $trace[$i]['file'] : 'n/a';
|
||||
$line = isset($trace[$i]['line']) ? $trace[$i]['line'] : 'n/a';
|
||||
|
||||
$output->writeln(sprintf(' %s%s%s() at <info>%s:%s</info>', $class, $type, $function, $file, $line));
|
||||
}
|
||||
|
||||
$output->writeln("\n");
|
||||
}
|
||||
}
|
||||
|
||||
private function sortCommands($commands)
|
||||
{
|
||||
$namespacedCommands = array();
|
||||
foreach ($commands as $name => $command)
|
||||
{
|
||||
$key = $command->getNamespace() ? $command->getNamespace() : '_global';
|
||||
|
||||
if (!isset($namespacedCommands[$key]))
|
||||
{
|
||||
$namespacedCommands[$key] = array();
|
||||
}
|
||||
|
||||
$namespacedCommands[$key][$name] = $command;
|
||||
}
|
||||
ksort($namespacedCommands);
|
||||
|
||||
foreach ($namespacedCommands as $name => &$commands)
|
||||
{
|
||||
ksort($commands);
|
||||
}
|
||||
|
||||
return $namespacedCommands;
|
||||
}
|
||||
|
||||
private function getAbbreviationSuggestions($abbrevs)
|
||||
{
|
||||
return sprintf('%s, %s%s', $abbrevs[0], $abbrevs[1], count($abbrevs) > 2 ? sprintf(' and %d more', count($abbrevs) - 2) : '');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,538 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Command;
|
||||
|
||||
use Symfony\Component\Console\Input\InputDefinition;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Application;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
/*
|
||||
* Changed by Felipe Nascimento de Moura <felipenmoura@gmail.com>
|
||||
* due to integrate it with plugins, from theWebMind Project
|
||||
* Line 165 and 167
|
||||
* added lines:
|
||||
* $this->runPlugins('before');
|
||||
* and
|
||||
* $this->runPlugins('after');
|
||||
*/
|
||||
/**
|
||||
* Base class for all commands.
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class Command
|
||||
{
|
||||
protected $name;
|
||||
protected $namespace;
|
||||
protected $aliases;
|
||||
protected $definition;
|
||||
protected $help;
|
||||
protected $application;
|
||||
protected $description;
|
||||
protected $ignoreValidationErrors;
|
||||
protected $formatter;
|
||||
protected $applicationDefinitionMerged;
|
||||
protected $code;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $name The name of the command
|
||||
*/
|
||||
public function __construct($name = null)
|
||||
{
|
||||
$this->definition = new InputDefinition();
|
||||
$this->ignoreValidationErrors = false;
|
||||
$this->applicationDefinitionMerged = false;
|
||||
$this->aliases = array();
|
||||
|
||||
if (null !== $name)
|
||||
{
|
||||
$this->setName($name);
|
||||
}
|
||||
|
||||
$this->configure();
|
||||
|
||||
if (!$this->name)
|
||||
{
|
||||
throw new \LogicException('The command name cannot be empty.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the application instance for this command.
|
||||
*
|
||||
* @param Application $application An Application instance
|
||||
*/
|
||||
public function setApplication(Application $application = null)
|
||||
{
|
||||
$this->application = $application;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the current command.
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the current command.
|
||||
*
|
||||
* @param InputInterface $input An InputInterface instance
|
||||
* @param OutputInterface $output An OutputInterface instance
|
||||
*
|
||||
* @return integer 0 if everything went fine, or an error code
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
throw new \LogicException('You must override the execute() method in the concrete command class.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Interacts with the user.
|
||||
*
|
||||
* @param InputInterface $input An InputInterface instance
|
||||
* @param OutputInterface $output An OutputInterface instance
|
||||
*/
|
||||
protected function interact(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the command just after the input has been validated.
|
||||
*
|
||||
* This is mainly useful when a lot of commands extends one main command
|
||||
* where some things need to be initialized based on the input arguments and options.
|
||||
*
|
||||
* @param InputInterface $input An InputInterface instance
|
||||
* @param OutputInterface $output An OutputInterface instance
|
||||
*/
|
||||
protected function initialize(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the command.
|
||||
*
|
||||
* @param InputInterface $input An InputInterface instance
|
||||
* @param OutputInterface $output An OutputInterface instance
|
||||
*/
|
||||
public function run(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
// add the application arguments and options
|
||||
$this->mergeApplicationDefinition();
|
||||
|
||||
// bind the input against the command specific arguments/options
|
||||
try
|
||||
{
|
||||
$input->bind($this->definition);
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
if (!$this->ignoreValidationErrors)
|
||||
{
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
$this->initialize($input, $output);
|
||||
|
||||
if ($input->isInteractive())
|
||||
{
|
||||
$this->interact($input, $output);
|
||||
}
|
||||
|
||||
$input->validate();
|
||||
|
||||
if ($this->code)
|
||||
{
|
||||
return call_user_func($this->code, $input, $output);
|
||||
}
|
||||
else
|
||||
{
|
||||
$ret= $this->execute($input, $output);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the code to execute when running this command.
|
||||
*
|
||||
* @param \Closure $code A \Closure
|
||||
*
|
||||
* @return Command The current instance
|
||||
*/
|
||||
public function setCode(\Closure $code)
|
||||
{
|
||||
$this->code = $code;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges the application definition with the command definition.
|
||||
*/
|
||||
protected function mergeApplicationDefinition()
|
||||
{
|
||||
if (null === $this->application || true === $this->applicationDefinitionMerged)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
$this->definition->setArguments(array_merge(
|
||||
$this->application->getDefinition()->getArguments(),
|
||||
$this->definition->getArguments()
|
||||
));
|
||||
|
||||
$this->definition->addOptions($this->application->getDefinition()->getOptions());
|
||||
|
||||
$this->applicationDefinitionMerged = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an array of argument and option instances.
|
||||
*
|
||||
* @param array|Definition $definition An array of argument and option instances or a definition instance
|
||||
*
|
||||
* @return Command The current instance
|
||||
*/
|
||||
public function setDefinition($definition)
|
||||
{
|
||||
if ($definition instanceof InputDefinition)
|
||||
{
|
||||
$this->definition = $definition;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->definition->setDefinition($definition);
|
||||
}
|
||||
|
||||
$this->applicationDefinitionMerged = false;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the InputDefinition attached to this Command.
|
||||
*
|
||||
* @return InputDefinition $definition An InputDefinition instance
|
||||
*/
|
||||
public function getDefinition()
|
||||
{
|
||||
return $this->definition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an argument.
|
||||
*
|
||||
* @param string $name The argument name
|
||||
* @param integer $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL
|
||||
* @param string $description A description text
|
||||
* @param mixed $default The default value (for InputArgument::OPTIONAL mode only)
|
||||
*
|
||||
* @return Command The current instance
|
||||
*/
|
||||
public function addArgument($name, $mode = null, $description = '', $default = null)
|
||||
{
|
||||
$this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an option.
|
||||
*
|
||||
* @param string $name The option name
|
||||
* @param string $shortcut The shortcut (can be null)
|
||||
* @param integer $mode The option mode: self::PARAMETER_REQUIRED, self::PARAMETER_NONE or self::PARAMETER_OPTIONAL
|
||||
* @param string $description A description text
|
||||
* @param mixed $default The default value (must be null for self::PARAMETER_REQUIRED or self::PARAMETER_NONE)
|
||||
*
|
||||
* @return Command The current instance
|
||||
*/
|
||||
public function addOption($name, $shortcut = null, $mode = null, $description = '', $default = null)
|
||||
{
|
||||
$this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the command.
|
||||
*
|
||||
* This method can set both the namespace and the name if
|
||||
* you separate them by a colon (:)
|
||||
*
|
||||
* $command->setName('foo:bar');
|
||||
*
|
||||
* @param string $name The command name
|
||||
*
|
||||
* @return Command The current instance
|
||||
*/
|
||||
public function setName($name)
|
||||
{
|
||||
if (false !== $pos = strrpos($name, ':'))
|
||||
{
|
||||
$namespace = substr($name, 0, $pos);
|
||||
$name = substr($name, $pos + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
$namespace = $this->namespace;
|
||||
}
|
||||
|
||||
if (!$name)
|
||||
{
|
||||
throw new \InvalidArgumentException('A command name cannot be empty');
|
||||
}
|
||||
|
||||
$this->namespace = $namespace;
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the command namespace.
|
||||
*
|
||||
* @return string The command namespace
|
||||
*/
|
||||
public function getNamespace()
|
||||
{
|
||||
return $this->namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the command name
|
||||
*
|
||||
* @return string The command name
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the fully qualified command name.
|
||||
*
|
||||
* @return string The fully qualified command name
|
||||
*/
|
||||
public function getFullName()
|
||||
{
|
||||
return $this->getNamespace() ? $this->getNamespace().':'.$this->getName() : $this->getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the description for the command.
|
||||
*
|
||||
* @param string $description The description for the command
|
||||
*
|
||||
* @return Command The current instance
|
||||
*/
|
||||
public function setDescription($description)
|
||||
{
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the description for the command.
|
||||
*
|
||||
* @return string The description for the command
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the help for the command.
|
||||
*
|
||||
* @param string $help The help for the command
|
||||
*
|
||||
* @return Command The current instance
|
||||
*/
|
||||
public function setHelp($help)
|
||||
{
|
||||
$this->help = $help;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the help for the command.
|
||||
*
|
||||
* @return string The help for the command
|
||||
*/
|
||||
public function getHelp()
|
||||
{
|
||||
return $this->help;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the processed help for the command replacing the %command.name% and
|
||||
* %command.full_name% patterns with the real values dynamically.
|
||||
*
|
||||
* @return string The processed help for the command
|
||||
*/
|
||||
public function getProcessedHelp()
|
||||
{
|
||||
$name = $this->namespace.':'.$this->name;
|
||||
|
||||
$placeholders = array(
|
||||
'%command.name%',
|
||||
'%command.full_name%'
|
||||
);
|
||||
$replacements = array(
|
||||
$name,
|
||||
$_SERVER['PHP_SELF'].' '.$name
|
||||
);
|
||||
|
||||
return str_replace($placeholders, $replacements, $this->getHelp());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the aliases for the command.
|
||||
*
|
||||
* @param array $aliases An array of aliases for the command
|
||||
*
|
||||
* @return Command The current instance
|
||||
*/
|
||||
public function setAliases($aliases)
|
||||
{
|
||||
$this->aliases = $aliases;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the aliases for the command.
|
||||
*
|
||||
* @return array An array of aliases for the command
|
||||
*/
|
||||
public function getAliases()
|
||||
{
|
||||
return $this->aliases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the synopsis for the command.
|
||||
*
|
||||
* @return string The synopsis
|
||||
*/
|
||||
public function getSynopsis()
|
||||
{
|
||||
return sprintf('%s %s', $this->getFullName(), $this->definition->getSynopsis());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a helper instance by name.
|
||||
*
|
||||
* @param string $name The helper name
|
||||
*
|
||||
* @return mixed The helper value
|
||||
*
|
||||
* @throws \InvalidArgumentException if the helper is not defined
|
||||
*/
|
||||
protected function getHelper($name)
|
||||
{
|
||||
return $this->application->getHelperSet()->get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a helper instance by name.
|
||||
*
|
||||
* @param string $name The helper name
|
||||
*
|
||||
* @return mixed The helper value
|
||||
*
|
||||
* @throws \InvalidArgumentException if the helper is not defined
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
return $this->application->getHelperSet()->get($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a text representation of the command.
|
||||
*
|
||||
* @return string A string representing the command
|
||||
*/
|
||||
public function asText()
|
||||
{
|
||||
$messages = array(
|
||||
'<comment>Usage:</comment>',
|
||||
' '.$this->getSynopsis(),
|
||||
'',
|
||||
);
|
||||
|
||||
if ($this->getAliases())
|
||||
{
|
||||
$messages[] = '<comment>Aliases:</comment> <info>'.implode(', ', $this->getAliases()).'</info>';
|
||||
}
|
||||
|
||||
$messages[] = $this->definition->asText();
|
||||
|
||||
if ($help = $this->getProcessedHelp())
|
||||
{
|
||||
$messages[] = '<comment>Help:</comment>';
|
||||
$messages[] = ' '.implode("\n ", explode("\n", $help))."\n";
|
||||
}
|
||||
|
||||
return implode("\n", $messages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an XML representation of the command.
|
||||
*
|
||||
* @param Boolean $asDom Whether to return a DOM or an XML string
|
||||
*
|
||||
* @return string|DOMDocument An XML string representing the command
|
||||
*/
|
||||
public function asXml($asDom = false)
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->formatOutput = true;
|
||||
$dom->appendChild($commandXML = $dom->createElement('command'));
|
||||
$commandXML->setAttribute('id', $this->getFullName());
|
||||
$commandXML->setAttribute('namespace', $this->getNamespace() ? $this->getNamespace() : '_global');
|
||||
$commandXML->setAttribute('name', $this->getName());
|
||||
|
||||
$commandXML->appendChild($usageXML = $dom->createElement('usage'));
|
||||
$usageXML->appendChild($dom->createTextNode(sprintf($this->getSynopsis(), '')));
|
||||
|
||||
$commandXML->appendChild($descriptionXML = $dom->createElement('description'));
|
||||
$descriptionXML->appendChild($dom->createTextNode(implode("\n ", explode("\n", $this->getDescription()))));
|
||||
|
||||
$commandXML->appendChild($helpXML = $dom->createElement('help'));
|
||||
$help = $this->help;
|
||||
$helpXML->appendChild($dom->createTextNode(implode("\n ", explode("\n", $help))));
|
||||
|
||||
$commandXML->appendChild($aliasesXML = $dom->createElement('aliases'));
|
||||
foreach ($this->getAliases() as $alias)
|
||||
{
|
||||
$aliasesXML->appendChild($aliasXML = $dom->createElement('alias'));
|
||||
$aliasXML->appendChild($dom->createTextNode($alias));
|
||||
}
|
||||
|
||||
$definition = $this->definition->asXml(true);
|
||||
$commandXML->appendChild($dom->importNode($definition->getElementsByTagName('arguments')->item(0), true));
|
||||
$commandXML->appendChild($dom->importNode($definition->getElementsByTagName('options')->item(0), true));
|
||||
|
||||
return $asDom ? $dom : $dom->saveXml();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Command;
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Output\Output;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* HelpCommand displays the help for a given command.
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class HelpCommand extends Command
|
||||
{
|
||||
protected $command;
|
||||
|
||||
/**
|
||||
* @see Command
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this->ignoreValidationErrors = true;
|
||||
|
||||
$this
|
||||
->setDefinition(array(
|
||||
new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'),
|
||||
new InputOption('xml', null, InputOption::PARAMETER_NONE, 'To output help as XML'),
|
||||
))
|
||||
->setName('help')
|
||||
->setAliases(array('?'))
|
||||
->setDescription('Displays help for a command')
|
||||
->setHelp(<<<EOF
|
||||
The <info>help</info> command displays help for a given command:
|
||||
|
||||
<info>./symfony help test:all</info>
|
||||
|
||||
You can also output the help as XML by using the <comment>--xml</comment> option:
|
||||
|
||||
<info>./symfony help --xml test:all</info>
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
public function setCommand(Command $command)
|
||||
{
|
||||
$this->command = $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Command
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
if (null === $this->command)
|
||||
{
|
||||
$this->command = $this->application->getCommand($input->getArgument('command_name'));
|
||||
}
|
||||
|
||||
if ($input->getOption('xml'))
|
||||
{
|
||||
$output->writeln($this->command->asXml(), Output::OUTPUT_RAW);
|
||||
}
|
||||
else
|
||||
{
|
||||
$output->writeln($this->command->asText());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Command;
|
||||
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Output\Output;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ListCommand displays the list of all available commands for the application.
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class ListCommand extends Command
|
||||
{
|
||||
/**
|
||||
* @see Command
|
||||
*/
|
||||
protected function configure()
|
||||
{
|
||||
$this
|
||||
->setDefinition(array(
|
||||
new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'),
|
||||
new InputOption('xml', null, InputOption::PARAMETER_NONE, 'To output help as XML'),
|
||||
))
|
||||
->setName('list')
|
||||
->setDescription('Lists commands')
|
||||
->setHelp(<<<EOF
|
||||
The <info>list</info> command lists all commands:
|
||||
|
||||
<info>./symfony list</info>
|
||||
|
||||
You can also display the commands for a specific namespace:
|
||||
|
||||
<info>./symfony list test</info>
|
||||
|
||||
You can also output the information as XML by using the <comment>--xml</comment> option:
|
||||
|
||||
<info>./symfony list --xml</info>
|
||||
EOF
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Command
|
||||
*/
|
||||
protected function execute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
if ($input->getOption('xml'))
|
||||
{
|
||||
$output->writeln($this->application->asXml($input->getArgument('namespace')), Output::OUTPUT_RAW);
|
||||
}
|
||||
else
|
||||
{
|
||||
$output->writeln($this->application->asText($input->getArgument('namespace')));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Helper;
|
||||
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The Dialog class provides helpers to interact with the user.
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class DialogHelper extends Helper
|
||||
{
|
||||
/**
|
||||
* Asks a question to the user.
|
||||
*
|
||||
* @param OutputInterface $output
|
||||
* @param string|array $question The question to ask
|
||||
* @param string $default The default answer if none is given by the user
|
||||
*
|
||||
* @param string The user answer
|
||||
*/
|
||||
public function ask(OutputInterface $output, $question, $default = null)
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
$output->writeln($question);
|
||||
|
||||
$ret = trim(fgets(STDIN));
|
||||
|
||||
return $ret ? $ret : $default;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks a confirmation to the user.
|
||||
*
|
||||
* The question will be asked until the user answer by nothing, yes, or no.
|
||||
*
|
||||
* @param OutputInterface $output
|
||||
* @param string|array $question The question to ask
|
||||
* @param Boolean $default The default answer if the user enters nothing
|
||||
*
|
||||
* @param Boolean true if the user has confirmed, false otherwise
|
||||
*/
|
||||
public function askConfirmation(OutputInterface $output, $question, $default = true)
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
$answer = 'z';
|
||||
while ($answer && !in_array(strtolower($answer[0]), array('y', 'n')))
|
||||
{
|
||||
$answer = $this->ask($output, $question);
|
||||
}
|
||||
|
||||
if (false === $default)
|
||||
{
|
||||
return $answer && 'y' == strtolower($answer[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
return !$answer || 'y' == strtolower($answer[0]);
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
* Asks for a value and validates the response.
|
||||
*
|
||||
* @param OutputInterface $output
|
||||
* @param string|array $question
|
||||
* @param Closure $validator
|
||||
* @param integer $attempts Max number of times to ask before giving up (false by default, which means infinite)
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function askAndValidate(OutputInterface $output, $question, \Closure $validator, $attempts = false)
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
$error = null;
|
||||
while (false === $attempts || $attempts--)
|
||||
{
|
||||
if (null !== $error)
|
||||
{
|
||||
$output->writeln($this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error'));
|
||||
}
|
||||
|
||||
$value = $this->ask($output, $question, null);
|
||||
|
||||
try
|
||||
{
|
||||
return $validator($value);
|
||||
}
|
||||
catch (\Exception $error)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
throw $error;
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the helper's canonical name
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'dialog';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Helper;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The Formatter class provides helpers to format messages.
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class FormatterHelper extends Helper
|
||||
{
|
||||
/**
|
||||
* Formats a message within a section.
|
||||
*
|
||||
* @param string $section The section name
|
||||
* @param string $message The message
|
||||
* @param string $style The style to apply to the section
|
||||
*/
|
||||
public function formatSection($section, $message, $style = 'info')
|
||||
{
|
||||
return sprintf("<%s>[%s]</%s> %s", $style, $section, $style, $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a message as a block of text.
|
||||
*
|
||||
* @param string|array $messages The message to write in the block
|
||||
* @param string $style The style to apply to the whole block
|
||||
* @param Boolean $large Whether to return a large block
|
||||
*
|
||||
* @return string The formatter message
|
||||
*/
|
||||
public function formatBlock($messages, $style, $large = false)
|
||||
{
|
||||
if (!is_array($messages))
|
||||
{
|
||||
$messages = array($messages);
|
||||
}
|
||||
|
||||
$len = 0;
|
||||
$lines = array();
|
||||
foreach ($messages as $message)
|
||||
{
|
||||
$lines[] = sprintf($large ? ' %s ' : ' %s ', $message);
|
||||
$len = max($this->strlen($message) + ($large ? 4 : 2), $len);
|
||||
}
|
||||
|
||||
$messages = $large ? array(str_repeat(' ', $len)) : array();
|
||||
foreach ($lines as $line)
|
||||
{
|
||||
$messages[] = $line.str_repeat(' ', $len - $this->strlen($line));
|
||||
}
|
||||
if ($large)
|
||||
{
|
||||
$messages[] = str_repeat(' ', $len);
|
||||
}
|
||||
|
||||
foreach ($messages as &$message)
|
||||
{
|
||||
$message = sprintf('<%s>%s</%s>', $style, $message, $style);
|
||||
}
|
||||
|
||||
return implode("\n", $messages);
|
||||
}
|
||||
|
||||
protected function strlen($string)
|
||||
{
|
||||
return function_exists('mb_strlen') ? mb_strlen($string) : strlen($string);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the helper's canonical name
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return 'formatter';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Helper;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Helper is the base class for all helper classes.
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
abstract class Helper implements HelperInterface
|
||||
{
|
||||
protected
|
||||
$helperSet = null;
|
||||
|
||||
/**
|
||||
* Sets the helper set associated with this helper.
|
||||
*
|
||||
* @param HelperSet $helperSet A HelperSet instance
|
||||
*/
|
||||
public function setHelperSet(HelperSet $helperSet = null)
|
||||
{
|
||||
$this->helperSet = $helperSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the helper set associated with this helper.
|
||||
*
|
||||
* @return HelperSet A HelperSet instance
|
||||
*/
|
||||
public function getHelperSet()
|
||||
{
|
||||
return $this->helperSet;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Helper;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* HelperInterface is the interface all helpers must implement.
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
interface HelperInterface
|
||||
{
|
||||
/**
|
||||
* Sets the helper set associated with this helper.
|
||||
*
|
||||
* @param HelperSet $helperSet A HelperSet instance
|
||||
*/
|
||||
function setHelperSet(HelperSet $helperSet = null);
|
||||
|
||||
/**
|
||||
* Gets the helper set associated with this helper.
|
||||
*
|
||||
* @return HelperSet A HelperSet instance
|
||||
*/
|
||||
function getHelperSet();
|
||||
|
||||
/**
|
||||
* Returns the canonical name of this helper.
|
||||
*
|
||||
* @return string The canonical name
|
||||
*/
|
||||
function getName();
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Helper;
|
||||
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* HelperSet represents a set of helpers to be used with a command.
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class HelperSet
|
||||
{
|
||||
protected
|
||||
$helpers = array(),
|
||||
$command = null;
|
||||
|
||||
public function __construct(array $helpers = array())
|
||||
{
|
||||
foreach ($helpers as $alias => $helper)
|
||||
{
|
||||
$this->set($helper, is_int($alias) ? null : $alias);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a helper.
|
||||
*
|
||||
* @param HelperInterface $value The helper instance
|
||||
* @param string $alias An alias
|
||||
*/
|
||||
public function set(HelperInterface $helper, $alias = null)
|
||||
{
|
||||
$this->helpers[$helper->getName()] = $helper;
|
||||
if (null !== $alias)
|
||||
{
|
||||
$this->helpers[$alias] = $helper;
|
||||
}
|
||||
|
||||
$helper->setHelperSet($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the helper if defined.
|
||||
*
|
||||
* @param string $name The helper name
|
||||
*
|
||||
* @return Boolean true if the helper is defined, false otherwise
|
||||
*/
|
||||
public function has($name)
|
||||
{
|
||||
return isset($this->helpers[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a helper value.
|
||||
*
|
||||
* @param string $name The helper name
|
||||
*
|
||||
* @return HelperInterface The helper instance
|
||||
*
|
||||
* @throws \InvalidArgumentException if the helper is not defined
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
if (!$this->has($name))
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
|
||||
}
|
||||
|
||||
return $this->helpers[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the command associated with this helper set.
|
||||
*
|
||||
* @param Command $command A Command instance
|
||||
*/
|
||||
public function setCommand(Command $command = null)
|
||||
{
|
||||
$this->command = $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the command associated with this helper set.
|
||||
*
|
||||
* @return Command A Command instance
|
||||
*/
|
||||
public function getCommand()
|
||||
{
|
||||
return $this->command;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?php
|
||||
|
||||
namespace external\Symfony\Component\Console\Helper;
|
||||
|
||||
use external\Symfony\Component\Console\Command\Command;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* HelperSet represents a set of helpers to be used with a command.
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class HelperSet
|
||||
{
|
||||
protected
|
||||
$helpers = array(),
|
||||
$command = null;
|
||||
|
||||
public function __construct(array $helpers = array())
|
||||
{
|
||||
foreach ($helpers as $alias => $helper)
|
||||
{
|
||||
$this->set($helper, is_int($alias) ? null : $alias);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a helper.
|
||||
*
|
||||
* @param HelperInterface $value The helper instance
|
||||
* @param string $alias An alias
|
||||
*/
|
||||
public function set(HelperInterface $helper, $alias = null)
|
||||
{
|
||||
$this->helpers[$helper->getName()] = $helper;
|
||||
if (null !== $alias)
|
||||
{
|
||||
$this->helpers[$alias] = $helper;
|
||||
}
|
||||
|
||||
$helper->setHelperSet($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the helper if defined.
|
||||
*
|
||||
* @param string $name The helper name
|
||||
*
|
||||
* @return Boolean true if the helper is defined, false otherwise
|
||||
*/
|
||||
public function has($name)
|
||||
{
|
||||
return isset($this->helpers[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a helper value.
|
||||
*
|
||||
* @param string $name The helper name
|
||||
*
|
||||
* @return HelperInterface The helper instance
|
||||
*
|
||||
* @throws \InvalidArgumentException if the helper is not defined
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
if (!$this->has($name))
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('The helper "%s" is not defined.', $name));
|
||||
}
|
||||
|
||||
return $this->helpers[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the command associated with this helper set.
|
||||
*
|
||||
* @param Command $command A Command instance
|
||||
*/
|
||||
public function setCommand(Command $command = null)
|
||||
{
|
||||
$this->command = $command;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the command associated with this helper set.
|
||||
*
|
||||
* @return Command A Command instance
|
||||
*/
|
||||
public function getCommand()
|
||||
{
|
||||
return $this->command;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Input;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ArgvInput represents an input coming from the CLI arguments.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* $input = new ArgvInput();
|
||||
*
|
||||
* By default, the `$_SERVER['argv']` array is used for the input values.
|
||||
*
|
||||
* This can be overriden by explicitly passing the input values in the constructor:
|
||||
*
|
||||
* $input = new ArgvInput($_SERVER['argv']);
|
||||
*
|
||||
* If you pass it yourself, don't forget that the first element of the array
|
||||
* is the name of the running program.
|
||||
*
|
||||
* When passing an argument to the constructor, be sure that it respects
|
||||
* the same rules as the argv one. It's almost always better to use the
|
||||
* `StringInput` when you want to provide your own input.
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
|
||||
* @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02
|
||||
*/
|
||||
class ArgvInput extends Input
|
||||
{
|
||||
protected $tokens;
|
||||
protected $parsed;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $argv An array of parameters from the CLI (in the argv format)
|
||||
* @param InputDefinition $definition A InputDefinition instance
|
||||
*/
|
||||
public function __construct(array $argv = null, InputDefinition $definition = null)
|
||||
{
|
||||
if (null === $argv)
|
||||
{
|
||||
$argv = $_SERVER['argv'];
|
||||
}
|
||||
|
||||
// strip the program name
|
||||
array_shift($argv);
|
||||
|
||||
$this->tokens = $argv;
|
||||
|
||||
parent::__construct($definition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes command line arguments.
|
||||
*/
|
||||
protected function parse()
|
||||
{
|
||||
$this->parsed = $this->tokens;
|
||||
while (null !== ($token = array_shift($this->parsed)))
|
||||
{
|
||||
if ('--' === substr($token, 0, 2))
|
||||
{
|
||||
$this->parseLongOption($token);
|
||||
}
|
||||
elseif ('-' === $token[0])
|
||||
{
|
||||
$this->parseShortOption($token);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->parseArgument($token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a short option.
|
||||
*
|
||||
* @param string $token The current token.
|
||||
*/
|
||||
protected function parseShortOption($token)
|
||||
{
|
||||
$name = substr($token, 1);
|
||||
|
||||
if (strlen($name) > 1)
|
||||
{
|
||||
if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptParameter())
|
||||
{
|
||||
// an option with a value (with no space)
|
||||
$this->addShortOption($name[0], substr($name, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->parseShortOptionSet($name);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->addShortOption($name, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a short option set.
|
||||
*
|
||||
* @param string $token The current token
|
||||
*/
|
||||
protected function parseShortOptionSet($name)
|
||||
{
|
||||
$len = strlen($name);
|
||||
for ($i = 0; $i < $len; $i++)
|
||||
{
|
||||
if (!$this->definition->hasShortcut($name[$i]))
|
||||
{
|
||||
throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $name[$i]));
|
||||
}
|
||||
|
||||
$option = $this->definition->getOptionForShortcut($name[$i]);
|
||||
if ($option->acceptParameter())
|
||||
{
|
||||
$this->addLongOption($option->getName(), $i === $len - 1 ? null : substr($name, $i + 1));
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->addLongOption($option->getName(), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a long option.
|
||||
*
|
||||
* @param string $token The current token
|
||||
*/
|
||||
protected function parseLongOption($token)
|
||||
{
|
||||
$name = substr($token, 2);
|
||||
|
||||
if (false !== $pos = strpos($name, '='))
|
||||
{
|
||||
$this->addLongOption(substr($name, 0, $pos), substr($name, $pos + 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->addLongOption($name, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an argument.
|
||||
*
|
||||
* @param string $token The current token
|
||||
*/
|
||||
protected function parseArgument($token)
|
||||
{
|
||||
if (!$this->definition->hasArgument(count($this->arguments)))
|
||||
{
|
||||
throw new \RuntimeException('Too many arguments.');
|
||||
}
|
||||
|
||||
$this->arguments[$this->definition->getArgument(count($this->arguments))->getName()] = $token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a short option value.
|
||||
*
|
||||
* @param string $shortcut The short option key
|
||||
* @param mixed $value The value for the option
|
||||
*/
|
||||
protected function addShortOption($shortcut, $value)
|
||||
{
|
||||
if (!$this->definition->hasShortcut($shortcut))
|
||||
{
|
||||
throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
|
||||
}
|
||||
|
||||
$this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a long option value.
|
||||
*
|
||||
* @param string $name The long option key
|
||||
* @param mixed $value The value for the option
|
||||
*/
|
||||
protected function addLongOption($name, $value)
|
||||
{
|
||||
if (!$this->definition->hasOption($name))
|
||||
{
|
||||
throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name));
|
||||
}
|
||||
|
||||
$option = $this->definition->getOption($name);
|
||||
|
||||
if (null === $value && $option->acceptParameter())
|
||||
{
|
||||
// if option accepts an optional or mandatory argument
|
||||
// let's see if there is one provided
|
||||
$next = array_shift($this->parsed);
|
||||
if ('-' !== $next[0])
|
||||
{
|
||||
$value = $next;
|
||||
}
|
||||
else
|
||||
{
|
||||
array_unshift($this->parsed, $next);
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $value)
|
||||
{
|
||||
if ($option->isParameterRequired())
|
||||
{
|
||||
throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name));
|
||||
}
|
||||
|
||||
$value = $option->isParameterOptional() ? $option->getDefault() : true;
|
||||
}
|
||||
|
||||
$this->options[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first argument from the raw parameters (not parsed).
|
||||
*
|
||||
* @return string The value of the first argument or null otherwise
|
||||
*/
|
||||
public function getFirstArgument()
|
||||
{
|
||||
foreach ($this->tokens as $token)
|
||||
{
|
||||
if ($token && '-' === $token[0])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return $token;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the raw parameters (not parsed) contains a value.
|
||||
*
|
||||
* This method is to be used to introspect the input parameters
|
||||
* before it has been validated. It must be used carefully.
|
||||
*
|
||||
* @param string|array $values The value(s) to look for in the raw parameters (can be an array)
|
||||
*
|
||||
* @return Boolean true if the value is contained in the raw parameters
|
||||
*/
|
||||
public function hasParameterOption($values)
|
||||
{
|
||||
if (!is_array($values))
|
||||
{
|
||||
$values = array($values);
|
||||
}
|
||||
|
||||
foreach ($this->tokens as $v)
|
||||
{
|
||||
if (in_array($v, $values))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Input;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ArrayInput represents an input provided as an array.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* $input = new ArrayInput(array('name' => 'foo', '--bar' => 'foobar'));
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class ArrayInput extends Input
|
||||
{
|
||||
protected $parameters;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $param An array of parameters
|
||||
* @param InputDefinition $definition A InputDefinition instance
|
||||
*/
|
||||
public function __construct(array $parameters, InputDefinition $definition = null)
|
||||
{
|
||||
$this->parameters = $parameters;
|
||||
|
||||
parent::__construct($definition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first argument from the raw parameters (not parsed).
|
||||
*
|
||||
* @return string The value of the first argument or null otherwise
|
||||
*/
|
||||
public function getFirstArgument()
|
||||
{
|
||||
foreach ($this->parameters as $key => $value)
|
||||
{
|
||||
if ($key && '-' === $key[0])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the raw parameters (not parsed) contains a value.
|
||||
*
|
||||
* This method is to be used to introspect the input parameters
|
||||
* before it has been validated. It must be used carefully.
|
||||
*
|
||||
* @param string|array $value The values to look for in the raw parameters (can be an array)
|
||||
*
|
||||
* @return Boolean true if the value is contained in the raw parameters
|
||||
*/
|
||||
public function hasParameterOption($values)
|
||||
{
|
||||
if (!is_array($values))
|
||||
{
|
||||
$values = array($values);
|
||||
}
|
||||
|
||||
foreach ($this->parameters as $k => $v)
|
||||
{
|
||||
if (!is_int($k))
|
||||
{
|
||||
$v = $k;
|
||||
}
|
||||
|
||||
if (in_array($v, $values))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes command line arguments.
|
||||
*/
|
||||
protected function parse()
|
||||
{
|
||||
foreach ($this->parameters as $key => $value)
|
||||
{
|
||||
if ('--' === substr($key, 0, 2))
|
||||
{
|
||||
$this->addLongOption(substr($key, 2), $value);
|
||||
}
|
||||
elseif ('-' === $key[0])
|
||||
{
|
||||
$this->addShortOption(substr($key, 1), $value);
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->addArgument($key, $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a short option value.
|
||||
*
|
||||
* @param string $shortcut The short option key
|
||||
* @param mixed $value The value for the option
|
||||
*/
|
||||
protected function addShortOption($shortcut, $value)
|
||||
{
|
||||
if (!$this->definition->hasShortcut($shortcut))
|
||||
{
|
||||
throw new \RuntimeException(sprintf('The "-%s" option does not exist.', $shortcut));
|
||||
}
|
||||
|
||||
$this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a long option value.
|
||||
*
|
||||
* @param string $name The long option key
|
||||
* @param mixed $value The value for the option
|
||||
*/
|
||||
protected function addLongOption($name, $value)
|
||||
{
|
||||
if (!$this->definition->hasOption($name))
|
||||
{
|
||||
throw new \RuntimeException(sprintf('The "--%s" option does not exist.', $name));
|
||||
}
|
||||
|
||||
$option = $this->definition->getOption($name);
|
||||
|
||||
if (null === $value)
|
||||
{
|
||||
if ($option->isParameterRequired())
|
||||
{
|
||||
throw new \RuntimeException(sprintf('The "--%s" option requires a value.', $name));
|
||||
}
|
||||
|
||||
$value = $option->isParameterOptional() ? $option->getDefault() : true;
|
||||
}
|
||||
|
||||
$this->options[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an argument value.
|
||||
*
|
||||
* @param string $name The argument name
|
||||
* @param mixed $value The value for the argument
|
||||
*/
|
||||
protected function addArgument($name, $value)
|
||||
{
|
||||
if (!$this->definition->hasArgument($name))
|
||||
{
|
||||
throw new \RuntimeException(sprintf('The "%s" argument does not exist.', $name));
|
||||
}
|
||||
|
||||
$this->arguments[$name] = $value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Input;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Input is the base class for all concrete Input classes.
|
||||
*
|
||||
* Three concrete classes are provided by default:
|
||||
*
|
||||
* * `ArgvInput`: The input comes from the CLI arguments (argv)
|
||||
* * `StringInput`: The input is provided as a string
|
||||
* * `ArrayInput`: The input is provided as an array
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
abstract class Input implements InputInterface
|
||||
{
|
||||
protected $definition;
|
||||
protected $options;
|
||||
protected $arguments;
|
||||
protected $interactive = true;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param InputDefinition $definition A InputDefinition instance
|
||||
*/
|
||||
public function __construct(InputDefinition $definition = null)
|
||||
{
|
||||
if (null === $definition)
|
||||
{
|
||||
$this->definition = new InputDefinition();
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->bind($definition);
|
||||
$this->validate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the current Input instance with the given arguments and options.
|
||||
*
|
||||
* @param InputDefinition $definition A InputDefinition instance
|
||||
*/
|
||||
public function bind(InputDefinition $definition)
|
||||
{
|
||||
$this->arguments = array();
|
||||
$this->options = array();
|
||||
$this->definition = $definition;
|
||||
|
||||
$this->parse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes command line arguments.
|
||||
*/
|
||||
abstract protected function parse();
|
||||
|
||||
public function validate()
|
||||
{
|
||||
if (count($this->arguments) < $this->definition->getArgumentRequiredCount())
|
||||
{
|
||||
throw new \RuntimeException('Not enough arguments.');
|
||||
}
|
||||
}
|
||||
|
||||
public function isInteractive()
|
||||
{
|
||||
return $this->interactive;
|
||||
}
|
||||
|
||||
public function setInteractive($interactive)
|
||||
{
|
||||
$this->interactive = (Boolean) $interactive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the argument values.
|
||||
*
|
||||
* @return array An array of argument values
|
||||
*/
|
||||
public function getArguments()
|
||||
{
|
||||
return array_merge($this->definition->getArgumentDefaults(), $this->arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the argument value for a given argument name.
|
||||
*
|
||||
* @param string $name The argument name
|
||||
*
|
||||
* @return mixed The argument value
|
||||
*/
|
||||
public function getArgument($name)
|
||||
{
|
||||
if (!$this->definition->hasArgument($name))
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
|
||||
}
|
||||
|
||||
return isset($this->arguments[$name]) ? $this->arguments[$name] : $this->definition->getArgument($name)->getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an argument value by name.
|
||||
*
|
||||
* @param string $name The argument name
|
||||
* @param string $value The argument value
|
||||
*/
|
||||
public function setArgument($name, $value)
|
||||
{
|
||||
if (!$this->definition->hasArgument($name))
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
|
||||
}
|
||||
|
||||
$this->arguments[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if an InputArgument object exists by name or position.
|
||||
*
|
||||
* @param string|integer $name The InputArgument name or position
|
||||
*
|
||||
* @return Boolean true if the InputArgument object exists, false otherwise
|
||||
*/
|
||||
public function hasArgument($name)
|
||||
{
|
||||
return $this->definition->hasArgument($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the options values.
|
||||
*
|
||||
* @return array An array of option values
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
return array_merge($this->definition->getOptionDefaults(), $this->options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the option value for a given option name.
|
||||
*
|
||||
* @param string $name The option name
|
||||
*
|
||||
* @return mixed The option value
|
||||
*/
|
||||
public function getOption($name)
|
||||
{
|
||||
if (!$this->definition->hasOption($name))
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
|
||||
}
|
||||
|
||||
return isset($this->options[$name]) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an option value by name.
|
||||
*
|
||||
* @param string $name The option name
|
||||
* @param string $value The option value
|
||||
*/
|
||||
public function setOption($name, $value)
|
||||
{
|
||||
if (!$this->definition->hasOption($name))
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('The "%s" option does not exist.', $name));
|
||||
}
|
||||
|
||||
$this->options[$name] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if an InputOption object exists by name.
|
||||
*
|
||||
* @param string $name The InputOption name
|
||||
*
|
||||
* @return Boolean true if the InputOption object exists, false otherwise
|
||||
*/
|
||||
public function hasOption($name)
|
||||
{
|
||||
return $this->definition->hasOption($name);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Input;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a command line argument.
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class InputArgument
|
||||
{
|
||||
const REQUIRED = 1;
|
||||
const OPTIONAL = 2;
|
||||
const IS_ARRAY = 4;
|
||||
|
||||
protected $name;
|
||||
protected $mode;
|
||||
protected $default;
|
||||
protected $description;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $name The argument name
|
||||
* @param integer $mode The argument mode: self::REQUIRED or self::OPTIONAL
|
||||
* @param string $description A description text
|
||||
* @param mixed $default The default value (for self::OPTIONAL mode only)
|
||||
*/
|
||||
public function __construct($name, $mode = null, $description = '', $default = null)
|
||||
{
|
||||
if (null === $mode)
|
||||
{
|
||||
$mode = self::OPTIONAL;
|
||||
}
|
||||
else if (is_string($mode) || $mode > 7)
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('Argument mode "%s" is not valid.', $mode));
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
$this->mode = $mode;
|
||||
$this->description = $description;
|
||||
|
||||
$this->setDefault($default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the argument name.
|
||||
*
|
||||
* @return string The argument name
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the argument is required.
|
||||
*
|
||||
* @return Boolean true if parameter mode is self::REQUIRED, false otherwise
|
||||
*/
|
||||
public function isRequired()
|
||||
{
|
||||
return self::REQUIRED === (self::REQUIRED & $this->mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the argument can take multiple values.
|
||||
*
|
||||
* @return Boolean true if mode is self::IS_ARRAY, false otherwise
|
||||
*/
|
||||
public function isArray()
|
||||
{
|
||||
return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default value.
|
||||
*
|
||||
* @param mixed $default The default value
|
||||
*/
|
||||
public function setDefault($default = null)
|
||||
{
|
||||
if (self::REQUIRED === $this->mode && null !== $default)
|
||||
{
|
||||
throw new \LogicException('Cannot set a default value except for Parameter::OPTIONAL mode.');
|
||||
}
|
||||
|
||||
if ($this->isArray())
|
||||
{
|
||||
if (null === $default)
|
||||
{
|
||||
$default = array();
|
||||
}
|
||||
else if (!is_array($default))
|
||||
{
|
||||
throw new \LogicException('A default value for an array argument must be an array.');
|
||||
}
|
||||
}
|
||||
|
||||
$this->default = $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default value.
|
||||
*
|
||||
* @return mixed The default value
|
||||
*/
|
||||
public function getDefault()
|
||||
{
|
||||
return $this->default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the description text.
|
||||
*
|
||||
* @return string The description text
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,507 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Input;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A InputDefinition represents a set of valid command line arguments and options.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* $definition = new InputDefinition(array(
|
||||
* new InputArgument('name', InputArgument::REQUIRED),
|
||||
* new InputOption('foo', 'f', InputOption::PARAMETER_REQUIRED),
|
||||
* ));
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class InputDefinition
|
||||
{
|
||||
protected $arguments;
|
||||
protected $requiredCount;
|
||||
protected $hasAnArrayArgument = false;
|
||||
protected $hasOptional;
|
||||
protected $options;
|
||||
protected $shortcuts;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param array $definition An array of InputArgument and InputOption instance
|
||||
*/
|
||||
public function __construct(array $definition = array())
|
||||
{
|
||||
$this->setDefinition($definition);
|
||||
}
|
||||
|
||||
public function setDefinition(array $definition)
|
||||
{
|
||||
$arguments = array();
|
||||
$options = array();
|
||||
foreach ($definition as $item)
|
||||
{
|
||||
if ($item instanceof InputOption)
|
||||
{
|
||||
$options[] = $item;
|
||||
}
|
||||
else
|
||||
{
|
||||
$arguments[] = $item;
|
||||
}
|
||||
}
|
||||
|
||||
$this->setArguments($arguments);
|
||||
$this->setOptions($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the InputArgument objects.
|
||||
*
|
||||
* @param array $arguments An array of InputArgument objects
|
||||
*/
|
||||
public function setArguments($arguments = array())
|
||||
{
|
||||
$this->arguments = array();
|
||||
$this->requiredCount = 0;
|
||||
$this->hasOptional = false;
|
||||
$this->addArguments($arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an array of InputArgument objects.
|
||||
*
|
||||
* @param array $arguments An array of InputArgument objects
|
||||
*/
|
||||
public function addArguments($arguments = array())
|
||||
{
|
||||
if (null !== $arguments)
|
||||
{
|
||||
foreach ($arguments as $argument)
|
||||
{
|
||||
$this->addArgument($argument);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an InputArgument object.
|
||||
*
|
||||
* @param InputArgument $argument An InputArgument object
|
||||
*/
|
||||
public function addArgument(InputArgument $argument)
|
||||
{
|
||||
if (isset($this->arguments[$argument->getName()]))
|
||||
{
|
||||
throw new \LogicException(sprintf('An argument with name "%s" already exist.', $argument->getName()));
|
||||
}
|
||||
|
||||
if ($this->hasAnArrayArgument)
|
||||
{
|
||||
throw new \LogicException('Cannot add an argument after an array argument.');
|
||||
}
|
||||
|
||||
if ($argument->isRequired() && $this->hasOptional)
|
||||
{
|
||||
throw new \LogicException('Cannot add a required argument after an optional one.');
|
||||
}
|
||||
|
||||
if ($argument->isArray())
|
||||
{
|
||||
$this->hasAnArrayArgument = true;
|
||||
}
|
||||
|
||||
if ($argument->isRequired())
|
||||
{
|
||||
++$this->requiredCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
$this->hasOptional = true;
|
||||
}
|
||||
|
||||
$this->arguments[$argument->getName()] = $argument;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an InputArgument by name or by position.
|
||||
*
|
||||
* @param string|integer $name The InputArgument name or position
|
||||
*
|
||||
* @return InputArgument An InputArgument object
|
||||
*/
|
||||
public function getArgument($name)
|
||||
{
|
||||
$arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
|
||||
|
||||
if (!$this->hasArgument($name))
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('The "%s" argument does not exist.', $name));
|
||||
}
|
||||
|
||||
return $arguments[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if an InputArgument object exists by name or position.
|
||||
*
|
||||
* @param string|integer $name The InputArgument name or position
|
||||
*
|
||||
* @return Boolean true if the InputArgument object exists, false otherwise
|
||||
*/
|
||||
public function hasArgument($name)
|
||||
{
|
||||
$arguments = is_int($name) ? array_values($this->arguments) : $this->arguments;
|
||||
|
||||
return isset($arguments[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the array of InputArgument objects.
|
||||
*
|
||||
* @return array An array of InputArgument objects
|
||||
*/
|
||||
public function getArguments()
|
||||
{
|
||||
return $this->arguments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of InputArguments.
|
||||
*
|
||||
* @return integer The number of InputArguments
|
||||
*/
|
||||
public function getArgumentCount()
|
||||
{
|
||||
return $this->hasAnArrayArgument ? PHP_INT_MAX : count($this->arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of required InputArguments.
|
||||
*
|
||||
* @return integer The number of required InputArguments
|
||||
*/
|
||||
public function getArgumentRequiredCount()
|
||||
{
|
||||
return $this->requiredCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default values.
|
||||
*
|
||||
* @return array An array of default values
|
||||
*/
|
||||
public function getArgumentDefaults()
|
||||
{
|
||||
$values = array();
|
||||
foreach ($this->arguments as $argument)
|
||||
{
|
||||
$values[$argument->getName()] = $argument->getDefault();
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the InputOption objects.
|
||||
*
|
||||
* @param array $options An array of InputOption objects
|
||||
*/
|
||||
public function setOptions($options = array())
|
||||
{
|
||||
$this->options = array();
|
||||
$this->shortcuts = array();
|
||||
$this->addOptions($options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an array of InputOption objects.
|
||||
*
|
||||
* @param array $options An array of InputOption objects
|
||||
*/
|
||||
public function addOptions($options = array())
|
||||
{
|
||||
foreach ($options as $option)
|
||||
{
|
||||
$this->addOption($option);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an InputOption object.
|
||||
*
|
||||
* @param InputOption $option An InputOption object
|
||||
*/
|
||||
public function addOption(InputOption $option)
|
||||
{
|
||||
if (isset($this->options[$option->getName()]))
|
||||
{
|
||||
throw new \LogicException(sprintf('An option named "%s" already exist.', $option->getName()));
|
||||
}
|
||||
else if (isset($this->shortcuts[$option->getShortcut()]))
|
||||
{
|
||||
throw new \LogicException(sprintf('An option with shortcut "%s" already exist.', $option->getShortcut()));
|
||||
}
|
||||
|
||||
$this->options[$option->getName()] = $option;
|
||||
if ($option->getShortcut())
|
||||
{
|
||||
$this->shortcuts[$option->getShortcut()] = $option->getName();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an InputOption by name.
|
||||
*
|
||||
* @param string $name The InputOption name
|
||||
*
|
||||
* @return InputOption A InputOption object
|
||||
*/
|
||||
public function getOption($name)
|
||||
{
|
||||
if (!$this->hasOption($name))
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('The "--%s" option does not exist.', $name));
|
||||
}
|
||||
|
||||
return $this->options[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if an InputOption object exists by name.
|
||||
*
|
||||
* @param string $name The InputOption name
|
||||
*
|
||||
* @return Boolean true if the InputOption object exists, false otherwise
|
||||
*/
|
||||
public function hasOption($name)
|
||||
{
|
||||
return isset($this->options[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the array of InputOption objects.
|
||||
*
|
||||
* @return array An array of InputOption objects
|
||||
*/
|
||||
public function getOptions()
|
||||
{
|
||||
return $this->options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if an InputOption object exists by shortcut.
|
||||
*
|
||||
* @param string $name The InputOption shortcut
|
||||
*
|
||||
* @return Boolean true if the InputOption object exists, false otherwise
|
||||
*/
|
||||
public function hasShortcut($name)
|
||||
{
|
||||
return isset($this->shortcuts[$name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an InputOption by shortcut.
|
||||
*
|
||||
* @return InputOption An InputOption object
|
||||
*/
|
||||
public function getOptionForShortcut($shortcut)
|
||||
{
|
||||
return $this->getOption($this->shortcutToName($shortcut));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an array of default values.
|
||||
*
|
||||
* @return array An array of all default values
|
||||
*/
|
||||
public function getOptionDefaults()
|
||||
{
|
||||
$values = array();
|
||||
foreach ($this->options as $option)
|
||||
{
|
||||
$values[$option->getName()] = $option->getDefault();
|
||||
}
|
||||
|
||||
return $values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the InputOption name given a shortcut.
|
||||
*
|
||||
* @param string $shortcut The shortcut
|
||||
*
|
||||
* @return string The InputOption name
|
||||
*/
|
||||
protected function shortcutToName($shortcut)
|
||||
{
|
||||
if (!isset($this->shortcuts[$shortcut]))
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('The "-%s" option does not exist.', $shortcut));
|
||||
}
|
||||
|
||||
return $this->shortcuts[$shortcut];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the synopsis.
|
||||
*
|
||||
* @return string The synopsis
|
||||
*/
|
||||
public function getSynopsis()
|
||||
{
|
||||
$elements = array();
|
||||
foreach ($this->getOptions() as $option)
|
||||
{
|
||||
$shortcut = $option->getShortcut() ? sprintf('-%s|', $option->getShortcut()) : '';
|
||||
$elements[] = sprintf('['.($option->isParameterRequired() ? '%s--%s="..."' : ($option->isParameterOptional() ? '%s--%s[="..."]' : '%s--%s')).']', $shortcut, $option->getName());
|
||||
}
|
||||
|
||||
foreach ($this->getArguments() as $argument)
|
||||
{
|
||||
$elements[] = sprintf($argument->isRequired() ? '%s' : '[%s]', $argument->getName().($argument->isArray() ? '1' : ''));
|
||||
|
||||
if ($argument->isArray())
|
||||
{
|
||||
$elements[] = sprintf('... [%sN]', $argument->getName());
|
||||
}
|
||||
}
|
||||
|
||||
return implode(' ', $elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a textual representation of the InputDefinition.
|
||||
*
|
||||
* @return string A string representing the InputDefinition
|
||||
*/
|
||||
public function asText()
|
||||
{
|
||||
// find the largest option or argument name
|
||||
$max = 0;
|
||||
foreach ($this->getOptions() as $option)
|
||||
{
|
||||
$max = strlen($option->getName()) + 2 > $max ? strlen($option->getName()) + 2 : $max;
|
||||
}
|
||||
foreach ($this->getArguments() as $argument)
|
||||
{
|
||||
$max = strlen($argument->getName()) > $max ? strlen($argument->getName()) : $max;
|
||||
}
|
||||
++$max;
|
||||
|
||||
$text = array();
|
||||
|
||||
if ($this->getArguments())
|
||||
{
|
||||
$text[] = '<comment>Arguments:</comment>';
|
||||
foreach ($this->getArguments() as $argument)
|
||||
{
|
||||
if (null !== $argument->getDefault() && (!is_array($argument->getDefault()) || count($argument->getDefault())))
|
||||
{
|
||||
$default = sprintf('<comment> (default: %s)</comment>', is_array($argument->getDefault()) ? str_replace("\n", '', var_export($argument->getDefault(), true)): $argument->getDefault());
|
||||
}
|
||||
else
|
||||
{
|
||||
$default = '';
|
||||
}
|
||||
|
||||
$text[] = sprintf(" <info>%-${max}s</info> %s%s", $argument->getName(), $argument->getDescription(), $default);
|
||||
}
|
||||
|
||||
$text[] = '';
|
||||
}
|
||||
|
||||
if ($this->getOptions())
|
||||
{
|
||||
$text[] = '<comment>Options:</comment>';
|
||||
|
||||
foreach ($this->getOptions() as $option)
|
||||
{
|
||||
if ($option->acceptParameter() && null !== $option->getDefault() && (!is_array($option->getDefault()) || count($option->getDefault())))
|
||||
{
|
||||
$default = sprintf('<comment> (default: %s)</comment>', is_array($option->getDefault()) ? str_replace("\n", '', print_r($option->getDefault(), true)): $option->getDefault());
|
||||
}
|
||||
else
|
||||
{
|
||||
$default = '';
|
||||
}
|
||||
|
||||
$multiple = $option->isArray() ? '<comment> (multiple values allowed)</comment>' : '';
|
||||
$text[] = sprintf(' %-'.$max.'s %s%s%s%s', '<info>--'.$option->getName().'</info>', $option->getShortcut() ? sprintf('(-%s) ', $option->getShortcut()) : '', $option->getDescription(), $default, $multiple);
|
||||
}
|
||||
|
||||
$text[] = '';
|
||||
}
|
||||
|
||||
return implode("\n", $text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an XML representation of the InputDefinition.
|
||||
*
|
||||
* @param Boolean $asDom Whether to return a DOM or an XML string
|
||||
*
|
||||
* @return string|DOMDocument An XML string representing the InputDefinition
|
||||
*/
|
||||
public function asXml($asDom = false)
|
||||
{
|
||||
$dom = new \DOMDocument('1.0', 'UTF-8');
|
||||
$dom->formatOutput = true;
|
||||
$dom->appendChild($definitionXML = $dom->createElement('definition'));
|
||||
|
||||
$definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
|
||||
foreach ($this->getArguments() as $argument)
|
||||
{
|
||||
$argumentsXML->appendChild($argumentXML = $dom->createElement('argument'));
|
||||
$argumentXML->setAttribute('name', $argument->getName());
|
||||
$argumentXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
|
||||
$argumentXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
|
||||
$argumentXML->appendChild($descriptionXML = $dom->createElement('description'));
|
||||
$descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
|
||||
|
||||
$argumentXML->appendChild($defaultsXML = $dom->createElement('defaults'));
|
||||
$defaults = is_array($argument->getDefault()) ? $argument->getDefault() : ($argument->getDefault() ? array($argument->getDefault()) : array());
|
||||
foreach ($defaults as $default)
|
||||
{
|
||||
$defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
|
||||
$defaultXML->appendChild($dom->createTextNode($default));
|
||||
}
|
||||
}
|
||||
|
||||
$definitionXML->appendChild($optionsXML = $dom->createElement('options'));
|
||||
foreach ($this->getOptions() as $option)
|
||||
{
|
||||
$optionsXML->appendChild($optionXML = $dom->createElement('option'));
|
||||
$optionXML->setAttribute('name', '--'.$option->getName());
|
||||
$optionXML->setAttribute('shortcut', $option->getShortcut() ? '-'.$option->getShortcut() : '');
|
||||
$optionXML->setAttribute('accept_parameter', $option->acceptParameter() ? 1 : 0);
|
||||
$optionXML->setAttribute('is_parameter_required', $option->isParameterRequired() ? 1 : 0);
|
||||
$optionXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
|
||||
$optionXML->appendChild($descriptionXML = $dom->createElement('description'));
|
||||
$descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
|
||||
|
||||
if ($option->acceptParameter())
|
||||
{
|
||||
$optionXML->appendChild($defaultsXML = $dom->createElement('defaults'));
|
||||
$defaults = is_array($option->getDefault()) ? $option->getDefault() : ($option->getDefault() ? array($option->getDefault()) : array());
|
||||
foreach ($defaults as $default)
|
||||
{
|
||||
$defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
|
||||
$defaultXML->appendChild($dom->createTextNode($default));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $asDom ? $dom : $dom->saveXml();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Input;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* InputInterface is the interface implemented by all input classes.
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
interface InputInterface
|
||||
{
|
||||
/**
|
||||
* Returns the first argument from the raw parameters (not parsed).
|
||||
*
|
||||
* @return string The value of the first argument or null otherwise
|
||||
*/
|
||||
function getFirstArgument();
|
||||
|
||||
/**
|
||||
* Returns true if the raw parameters (not parsed) contains a value.
|
||||
*
|
||||
* This method is to be used to introspect the input parameters
|
||||
* before it has been validated. It must be used carefully.
|
||||
*
|
||||
* @param string $value The value to look for in the raw parameters
|
||||
*
|
||||
* @return Boolean true if the value is contained in the raw parameters
|
||||
*/
|
||||
function hasParameterOption($value);
|
||||
|
||||
/**
|
||||
* Binds the current Input instance with the given arguments and options.
|
||||
*
|
||||
* @param InputDefinition $definition A InputDefinition instance
|
||||
*/
|
||||
function bind(InputDefinition $definition);
|
||||
|
||||
function validate();
|
||||
|
||||
function getArguments();
|
||||
|
||||
function getArgument($name);
|
||||
|
||||
function getOptions();
|
||||
|
||||
function getOption($name);
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Input;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a command line option.
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class InputOption
|
||||
{
|
||||
const PARAMETER_NONE = 1;
|
||||
const PARAMETER_REQUIRED = 2;
|
||||
const PARAMETER_OPTIONAL = 4;
|
||||
const PARAMETER_IS_ARRAY = 8;
|
||||
|
||||
protected $name;
|
||||
protected $shortcut;
|
||||
protected $mode;
|
||||
protected $default;
|
||||
protected $description;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $name The option name
|
||||
* @param string $shortcut The shortcut (can be null)
|
||||
* @param integer $mode The option mode: self::PARAMETER_REQUIRED, self::PARAMETER_NONE or self::PARAMETER_OPTIONAL
|
||||
* @param string $description A description text
|
||||
* @param mixed $default The default value (must be null for self::PARAMETER_REQUIRED or self::PARAMETER_NONE)
|
||||
*/
|
||||
public function __construct($name, $shortcut = null, $mode = null, $description = '', $default = null)
|
||||
{
|
||||
if ('--' === substr($name, 0, 2))
|
||||
{
|
||||
$name = substr($name, 2);
|
||||
}
|
||||
|
||||
if (empty($shortcut))
|
||||
{
|
||||
$shortcut = null;
|
||||
}
|
||||
|
||||
if (null !== $shortcut)
|
||||
{
|
||||
if ('-' === $shortcut[0])
|
||||
{
|
||||
$shortcut = substr($shortcut, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (null === $mode)
|
||||
{
|
||||
$mode = self::PARAMETER_NONE;
|
||||
}
|
||||
else if (!is_int($mode) || $mode > 15)
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('Option mode "%s" is not valid.', $mode));
|
||||
}
|
||||
|
||||
$this->name = $name;
|
||||
$this->shortcut = $shortcut;
|
||||
$this->mode = $mode;
|
||||
$this->description = $description;
|
||||
|
||||
if ($this->isArray() && !$this->acceptParameter())
|
||||
{
|
||||
throw new \InvalidArgumentException('Impossible to have an option mode PARAMETER_IS_ARRAY if the option does not accept a parameter.');
|
||||
}
|
||||
|
||||
$this->setDefault($default);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shortcut.
|
||||
*
|
||||
* @return string The shortcut
|
||||
*/
|
||||
public function getShortcut()
|
||||
{
|
||||
return $this->shortcut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name.
|
||||
*
|
||||
* @return string The name
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the option accept a parameter.
|
||||
*
|
||||
* @return Boolean true if parameter mode is not self::PARAMETER_NONE, false otherwise
|
||||
*/
|
||||
public function acceptParameter()
|
||||
{
|
||||
return $this->isParameterRequired() || $this->isParameterOptional();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the option requires a parameter.
|
||||
*
|
||||
* @return Boolean true if parameter mode is self::PARAMETER_REQUIRED, false otherwise
|
||||
*/
|
||||
public function isParameterRequired()
|
||||
{
|
||||
return self::PARAMETER_REQUIRED === (self::PARAMETER_REQUIRED & $this->mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the option takes an optional parameter.
|
||||
*
|
||||
* @return Boolean true if parameter mode is self::PARAMETER_OPTIONAL, false otherwise
|
||||
*/
|
||||
public function isParameterOptional()
|
||||
{
|
||||
return self::PARAMETER_OPTIONAL === (self::PARAMETER_OPTIONAL & $this->mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the option can take multiple values.
|
||||
*
|
||||
* @return Boolean true if mode is self::PARAMETER_IS_ARRAY, false otherwise
|
||||
*/
|
||||
public function isArray()
|
||||
{
|
||||
return self::PARAMETER_IS_ARRAY === (self::PARAMETER_IS_ARRAY & $this->mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default value.
|
||||
*
|
||||
* @param mixed $default The default value
|
||||
*/
|
||||
public function setDefault($default = null)
|
||||
{
|
||||
if (self::PARAMETER_NONE === (self::PARAMETER_NONE & $this->mode) && null !== $default)
|
||||
{
|
||||
throw new \LogicException('Cannot set a default value when using Option::PARAMETER_NONE mode.');
|
||||
}
|
||||
|
||||
if ($this->isArray())
|
||||
{
|
||||
if (null === $default)
|
||||
{
|
||||
$default = array();
|
||||
}
|
||||
elseif (!is_array($default))
|
||||
{
|
||||
throw new \LogicException('A default value for an array option must be an array.');
|
||||
}
|
||||
}
|
||||
|
||||
$this->default = $this->acceptParameter() ? $default : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default value.
|
||||
*
|
||||
* @return mixed The default value
|
||||
*/
|
||||
public function getDefault()
|
||||
{
|
||||
return $this->default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the description text.
|
||||
*
|
||||
* @return string The description text
|
||||
*/
|
||||
public function getDescription()
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Input;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* StringInput represents an input provided as a string.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* $input = new StringInput('foo --bar="foobar"');
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class StringInput extends ArgvInput
|
||||
{
|
||||
const REGEX_STRING = '([^ ]+?)(?: |(?<!\\\\)"|(?<!\\\\)\'|$)';
|
||||
const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $input An array of parameters from the CLI (in the argv format)
|
||||
* @param InputDefinition $definition A InputDefinition instance
|
||||
*/
|
||||
public function __construct($input, InputDefinition $definition = null)
|
||||
{
|
||||
parent::__construct(array(), $definition);
|
||||
|
||||
$this->tokens = $this->tokenize($input);
|
||||
}
|
||||
|
||||
protected function tokenize($input)
|
||||
{
|
||||
$input = preg_replace('/(\r\n|\r|\n|\t)/', ' ', $input);
|
||||
|
||||
$tokens = array();
|
||||
$length = strlen($input);
|
||||
$cursor = 0;
|
||||
while ($cursor < $length)
|
||||
{
|
||||
if (preg_match('/\s+/A', $input, $match, null, $cursor))
|
||||
{
|
||||
}
|
||||
elseif (preg_match('/([^="\' ]+?)(=?)('.self::REGEX_QUOTED_STRING.'+)/A', $input, $match, null, $cursor))
|
||||
{
|
||||
$tokens[] = $match[1].$match[2].stripcslashes(str_replace(array('"\'', '\'"', '\'\'', '""'), '', substr($match[3], 1, strlen($match[3]) - 2)));
|
||||
}
|
||||
elseif (preg_match('/'.self::REGEX_QUOTED_STRING.'/A', $input, $match, null, $cursor))
|
||||
{
|
||||
$tokens[] = stripcslashes(substr($match[0], 1, strlen($match[0]) - 2));
|
||||
}
|
||||
elseif (preg_match('/'.self::REGEX_STRING.'/A', $input, $match, null, $cursor))
|
||||
{
|
||||
$tokens[] = stripcslashes($match[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// should never happen
|
||||
// @codeCoverageIgnoreStart
|
||||
throw new \InvalidArgumentException(sprintf('Unable to parse input near "... %s ..."', substr($input, $cursor, 10)));
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
$cursor += strlen($match[0]);
|
||||
}
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Output;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* ConsoleOutput is the default class for all CLI output. It uses STDOUT.
|
||||
*
|
||||
* This class is a convenient wrapper around `StreamOutput`.
|
||||
*
|
||||
* $output = new ConsoleOutput();
|
||||
*
|
||||
* This is equivalent to:
|
||||
*
|
||||
* $output = new StreamOutput(fopen('php://stdout', 'w'));
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class ConsoleOutput extends StreamOutput
|
||||
{
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param integer $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE)
|
||||
* @param Boolean $decorated Whether to decorate messages or not (null for auto-guessing)
|
||||
*/
|
||||
public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null)
|
||||
{
|
||||
parent::__construct(fopen('php://stdout', 'w'), $verbosity, $decorated);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Output;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* NullOutput suppresses all output.
|
||||
*
|
||||
* $output = new NullOutput();
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class NullOutput extends Output
|
||||
{
|
||||
/**
|
||||
* Writes a message to the output.
|
||||
*
|
||||
* @param string $message A message to write to the output
|
||||
* @param Boolean $newline Whether to add a newline or not
|
||||
*/
|
||||
public function doWrite($message, $newline)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,230 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Output;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base class for output classes.
|
||||
*
|
||||
* There is three level of verbosity:
|
||||
*
|
||||
* * normal: no option passed (normal output - information)
|
||||
* * verbose: -v (more output - debug)
|
||||
* * quiet: -q (no output)
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
abstract class Output implements OutputInterface
|
||||
{
|
||||
const VERBOSITY_QUIET = 0;
|
||||
const VERBOSITY_NORMAL = 1;
|
||||
const VERBOSITY_VERBOSE = 2;
|
||||
|
||||
const OUTPUT_NORMAL = 0;
|
||||
const OUTPUT_RAW = 1;
|
||||
const OUTPUT_PLAIN = 2;
|
||||
|
||||
protected $verbosity;
|
||||
protected $decorated;
|
||||
|
||||
static protected $styles = array(
|
||||
'error' => array('bg' => 'red', 'fg' => 'white'),
|
||||
'info' => array('fg' => 'green'),
|
||||
'comment' => array('fg' => 'yellow'),
|
||||
'question' => array('bg' => 'cyan', 'fg' => 'black'),
|
||||
);
|
||||
static protected $options = array('bold' => 1, 'underscore' => 4, 'blink' => 5, 'reverse' => 7, 'conceal' => 8);
|
||||
static protected $foreground = array('black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'white' => 37);
|
||||
static protected $background = array('black' => 40, 'red' => 41, 'green' => 42, 'yellow' => 43, 'blue' => 44, 'magenta' => 45, 'cyan' => 46, 'white' => 47);
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param integer $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE)
|
||||
* @param Boolean $decorated Whether to decorate messages or not (null for auto-guessing)
|
||||
*/
|
||||
public function __construct($verbosity = self::VERBOSITY_NORMAL, $decorated = null)
|
||||
{
|
||||
$this->decorated = (Boolean) $decorated;
|
||||
$this->verbosity = null === $verbosity ? self::VERBOSITY_NORMAL : $verbosity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new style.
|
||||
*
|
||||
* @param string $name The style name
|
||||
* @param array $options An array of options
|
||||
*/
|
||||
static public function setStyle($name, $options = array())
|
||||
{
|
||||
static::$styles[strtolower($name)] = $options;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the decorated flag.
|
||||
*
|
||||
* @param Boolean $decorated Whether to decorated the messages or not
|
||||
*/
|
||||
public function setDecorated($decorated)
|
||||
{
|
||||
$this->decorated = (Boolean) $decorated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the decorated flag.
|
||||
*
|
||||
* @return Boolean true if the output will decorate messages, false otherwise
|
||||
*/
|
||||
public function isDecorated()
|
||||
{
|
||||
return $this->decorated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the verbosity of the output.
|
||||
*
|
||||
* @param integer $level The level of verbosity
|
||||
*/
|
||||
public function setVerbosity($level)
|
||||
{
|
||||
$this->verbosity = (int) $level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current verbosity of the output.
|
||||
*
|
||||
* @return integer The current level of verbosity
|
||||
*/
|
||||
public function getVerbosity()
|
||||
{
|
||||
return $this->verbosity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a message to the output and adds a newline at the end.
|
||||
*
|
||||
* @param string|array $messages The message as an array of lines of a single string
|
||||
* @param integer $type The type of output
|
||||
*/
|
||||
public function writeln($messages, $type = 0)
|
||||
{
|
||||
$this->write($messages, true, $type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a message to the output.
|
||||
*
|
||||
* @param string|array $messages The message as an array of lines of a single string
|
||||
* @param Boolean $newline Whether to add a newline or not
|
||||
* @param integer $type The type of output
|
||||
*/
|
||||
public function write($messages, $newline = false, $type = 0)
|
||||
{
|
||||
if (self::VERBOSITY_QUIET === $this->verbosity)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_array($messages))
|
||||
{
|
||||
$messages = array($messages);
|
||||
}
|
||||
|
||||
foreach ($messages as $message)
|
||||
{
|
||||
switch ($type)
|
||||
{
|
||||
case Output::OUTPUT_NORMAL:
|
||||
$message = $this->format($message);
|
||||
break;
|
||||
case Output::OUTPUT_RAW:
|
||||
break;
|
||||
case Output::OUTPUT_PLAIN:
|
||||
$message = strip_tags($this->format($message));
|
||||
break;
|
||||
default:
|
||||
throw new \InvalidArgumentException(sprintf('Unknown output type given (%s)', $type));
|
||||
}
|
||||
|
||||
$this->doWrite($message, $newline);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a message to the output.
|
||||
*
|
||||
* @param string $message A message to write to the output
|
||||
* @param Boolean $newline Whether to add a newline or not
|
||||
*/
|
||||
abstract public function doWrite($message, $newline);
|
||||
|
||||
/**
|
||||
* Formats a message according to the given styles.
|
||||
*
|
||||
* @param string $message The message to style
|
||||
*
|
||||
* @return string The styled message
|
||||
*/
|
||||
protected function format($message)
|
||||
{
|
||||
$message = preg_replace_callback('#<([a-z][a-z0-9\-_]+)>#i', array($this, 'replaceStartStyle'), $message);
|
||||
|
||||
return preg_replace_callback('#</([a-z][a-z0-9\-_]+)>#i', array($this, 'replaceEndStyle'), $message);
|
||||
}
|
||||
|
||||
protected function replaceStartStyle($match)
|
||||
{
|
||||
if (!$this->decorated)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!isset(static::$styles[strtolower($match[1])]))
|
||||
{
|
||||
throw new \InvalidArgumentException(sprintf('Unknown style "%s".', $match[1]));
|
||||
}
|
||||
|
||||
$parameters = static::$styles[strtolower($match[1])];
|
||||
$codes = array();
|
||||
|
||||
if (isset($parameters['fg']))
|
||||
{
|
||||
$codes[] = static::$foreground[$parameters['fg']];
|
||||
}
|
||||
|
||||
if (isset($parameters['bg']))
|
||||
{
|
||||
$codes[] = static::$background[$parameters['bg']];
|
||||
}
|
||||
|
||||
foreach (static::$options as $option => $value)
|
||||
{
|
||||
if (isset($parameters[$option]) && $parameters[$option])
|
||||
{
|
||||
$codes[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return "\033[".implode(';', $codes)."m";
|
||||
}
|
||||
|
||||
protected function replaceEndStyle($match)
|
||||
{
|
||||
if (!$this->decorated)
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
return "\033[0m";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Output;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* OutputInterface is the interface implemented by all Output classes.
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
interface OutputInterface
|
||||
{
|
||||
/**
|
||||
* Writes a message to the output.
|
||||
*
|
||||
* @param string|array $messages The message as an array of lines of a single string
|
||||
* @param integer $type The type of output
|
||||
*/
|
||||
public function write($messages, $type = 0);
|
||||
|
||||
/**
|
||||
* Sets the verbosity of the output.
|
||||
*
|
||||
* @param integer $level The level of verbosity
|
||||
*/
|
||||
public function setVerbosity($level);
|
||||
|
||||
/**
|
||||
* Sets the decorated flag.
|
||||
*
|
||||
* @param Boolean $decorated Whether to decorated the messages or not
|
||||
*/
|
||||
public function setDecorated($decorated);
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console\Output;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* StreamOutput writes the output to a given stream.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* $output = new StreamOutput(fopen('php://stdout', 'w'));
|
||||
*
|
||||
* As `StreamOutput` can use any stream, you can also use a file:
|
||||
*
|
||||
* $output = new StreamOutput(fopen('/path/to/output.log', 'a', false));
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage console
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class StreamOutput extends Output
|
||||
{
|
||||
protected $stream;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param mixed $stream A stream resource
|
||||
* @param integer $verbosity The verbosity level (self::VERBOSITY_QUIET, self::VERBOSITY_NORMAL, self::VERBOSITY_VERBOSE)
|
||||
* @param Boolean $decorated Whether to decorate messages or not (null for auto-guessing)
|
||||
*/
|
||||
public function __construct($stream, $verbosity = self::VERBOSITY_NORMAL, $decorated = null)
|
||||
{
|
||||
if (!is_resource($stream) || 'stream' !== get_resource_type($stream))
|
||||
{
|
||||
throw new \InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
|
||||
}
|
||||
|
||||
$this->stream = $stream;
|
||||
|
||||
if (null === $decorated)
|
||||
{
|
||||
$decorated = $this->hasColorSupport($decorated);
|
||||
}
|
||||
|
||||
parent::__construct($verbosity, $decorated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the stream attached to this StreamOutput instance.
|
||||
*
|
||||
* @return resource A stream resource
|
||||
*/
|
||||
public function getStream()
|
||||
{
|
||||
return $this->stream;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a message to the output.
|
||||
*
|
||||
* @param string $message A message to write to the output
|
||||
* @param Boolean $newline Whether to add a newline or not
|
||||
*/
|
||||
public function doWrite($message, $newline)
|
||||
{
|
||||
if (false === @fwrite($this->stream, $message.($newline ? PHP_EOL : '')))
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
// should never happen
|
||||
throw new \RuntimeException('Unable to write output.');
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
|
||||
flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the stream supports colorization.
|
||||
*
|
||||
* Colorization is disabled if not supported by the stream:
|
||||
*
|
||||
* - windows without ansicon
|
||||
* - non tty consoles
|
||||
*
|
||||
* @return Boolean true if the stream supports colorization, false otherwise
|
||||
*/
|
||||
protected function hasColorSupport()
|
||||
{
|
||||
// @codeCoverageIgnoreStart
|
||||
if (DIRECTORY_SEPARATOR == '\\')
|
||||
{
|
||||
return false !== getenv('ANSICON');
|
||||
}
|
||||
else
|
||||
{
|
||||
return function_exists('posix_isatty') && @posix_isatty($this->stream);
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
<?php
|
||||
|
||||
namespace Symfony\Component\Console;
|
||||
|
||||
use Symfony\Component\Console\Application;
|
||||
use Symfony\Component\Console\Input\StringInput;
|
||||
use Symfony\Component\Console\Output\ConsoleOutput;
|
||||
|
||||
/*
|
||||
* This file is part of the symfony framework.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*
|
||||
* This source file is subject to the MIT license that is bundled
|
||||
* with this source code in the file LICENSE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A Shell wraps an Application to add shell capabilities to it.
|
||||
*
|
||||
* This class only works with a PHP compiled with readline support
|
||||
* (either --with-readline or --with-libedit)
|
||||
*
|
||||
* @package symfony
|
||||
* @subpackage cli
|
||||
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
||||
*/
|
||||
class Shell
|
||||
{
|
||||
protected $application;
|
||||
protected $history;
|
||||
protected $output;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* If there is no readline support for the current PHP executable
|
||||
* a \RuntimeException exception is thrown.
|
||||
*
|
||||
* @param Application $application An application instance
|
||||
*/
|
||||
public function __construct(Application $application)
|
||||
{
|
||||
if (!function_exists('readline'))
|
||||
{
|
||||
throw new \RuntimeException('Unable to start the shell as the Readline extension is not enabled.');
|
||||
}
|
||||
|
||||
$this->application = $application;
|
||||
$this->history = getenv('HOME').'/.history_'.$application->getName();
|
||||
$this->output = new ConsoleOutput();
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the shell.
|
||||
*/
|
||||
public function run()
|
||||
{
|
||||
$this->application->setAutoExit(false);
|
||||
$this->application->setCatchExceptions(true);
|
||||
|
||||
readline_read_history($this->history);
|
||||
readline_completion_function(array($this, 'autocompleter'));
|
||||
|
||||
//$this->output->writeln($this->getHeader());
|
||||
while (true)
|
||||
{
|
||||
$command = readline($this->application->getName().' > ');
|
||||
|
||||
if (false === $command)
|
||||
{
|
||||
$this->output->writeln("\n");
|
||||
break;
|
||||
}
|
||||
|
||||
readline_add_history($command);
|
||||
readline_write_history($this->history);
|
||||
|
||||
if (0 !== $ret = $this->application->run(new StringInput($command), $this->output))
|
||||
{
|
||||
$this->output->writeln(sprintf('<error>The command terminated with an error status (%s)</error>', $ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to return autocompletion for the current entered text.
|
||||
*
|
||||
* @param string $text The last segment of the entered text
|
||||
* @param integer $position The current position
|
||||
*/
|
||||
protected function autocompleter($text, $position)
|
||||
{
|
||||
$info = readline_info();
|
||||
$text = substr($info['line_buffer'], 0, $info['end']);
|
||||
|
||||
if ($info['point'] !== $info['end'])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// task name?
|
||||
if (false === strpos($text, ' ') || !$text)
|
||||
{
|
||||
return array_keys($this->application->getCommands());
|
||||
}
|
||||
|
||||
// options and arguments?
|
||||
try
|
||||
{
|
||||
$command = $this->application->findCommand(substr($text, 0, strpos($text, ' ')));
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
$list = array('--help');
|
||||
foreach ($command->getDefinition()->getOptions() as $option)
|
||||
{
|
||||
$list[] = '--'.$option->getName();
|
||||
}
|
||||
|
||||
return $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the shell header.
|
||||
*
|
||||
* @return string The header string
|
||||
*/
|
||||
protected function getHeader()
|
||||
{
|
||||
return <<<EOF
|
||||
Welcome to the <info>{$this->application->getName()}</info> shell (<comment>{$this->application->getVersion()}</comment>).
|
||||
|
||||
At the prompt, type <comment>help</comment> for some help,
|
||||
or <comment>list</comment> to get a list available commands.
|
||||
|
||||
To exit the shell, type <comment>^D</comment>.
|
||||
|
||||
EOF;
|
||||
}
|
||||
}
|
||||