├── i18n
├── ko.json
├── zh-hans.json
├── ja.json
├── zh-hant.json
├── he.json
├── vi.json
├── nb.json
├── uk.json
├── ru.json
├── sv.json
├── be-tarask.json
├── eu.json
├── fa.json
├── mk.json
├── nl.json
├── pt-br.json
├── pt.json
├── ast.json
├── en.json
├── gl.json
├── it.json
├── ms.json
├── qqq.json
├── dsb.json
├── hsb.json
├── oc.json
├── ia.json
├── es.json
├── roa-tara.json
├── tl.json
├── bcl.json
├── ilo.json
├── fr.json
├── ksh.json
└── de.json
├── .gitignore
├── src
├── Hashable.php
├── Comparable.php
├── Immutable.php
├── Typeable.php
└── Language
│ ├── Selection
│ ├── SelectionRequest.php
│ ├── SubjectSelection.php
│ └── PropertySelection.php
│ ├── Description
│ ├── Conjunction.php
│ ├── Disjunction.php
│ ├── Description.php
│ ├── AnyValue.php
│ ├── ValueDescription.php
│ ├── DescriptionCollection.php
│ └── SomeProperty.php
│ ├── Option
│ ├── SortOptions.php
│ ├── SortExpression.php
│ ├── PropertyValueSortExpression.php
│ └── QueryOptions.php
│ └── Query.php
├── .scrutinizer.yml
├── .travis.yml
├── Tests
├── bootstrap.php
├── Phpunit
│ ├── Language
│ │ ├── Description
│ │ │ ├── AnyValueTest.php
│ │ │ ├── ConjunctionTest.php
│ │ │ ├── DisjunctionTest.php
│ │ │ ├── ValueDescriptionTest.php
│ │ │ ├── SomePropertyTest.php
│ │ │ ├── DescriptionTest.php
│ │ │ └── DescriptionCollectionTest.php
│ │ ├── Selection
│ │ │ ├── SubjectSelectionTest.php
│ │ │ ├── PropertySelectionTest.php
│ │ │ └── SelectionRequestTest.php
│ │ ├── Option
│ │ │ ├── SortExpressionTest.php
│ │ │ ├── SortOptionsTest.php
│ │ │ ├── QueryOptionsTest.php
│ │ │ └── PropertyValueSortExpressionTest.php
│ │ └── QueryTest.php
│ └── AskTestCase.php
└── testLoader.php
├── Ask.php
├── phpunit.xml.dist
├── composer.json
├── Ask.mw.php
├── Ask.i18n.php
├── README.md
└── COPYING
/i18n/ko.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "아라"
5 | ]
6 | },
7 | "ask-desc": "Ask 쿼리 언어의 PHP 구현을 포함하는 라이브러리"
8 | }
--------------------------------------------------------------------------------
/i18n/zh-hans.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Qiyue2001"
5 | ]
6 | },
7 | "ask-desc": "包含以PHP实现的ASK查询语言的库"
8 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .*
2 | *~
3 | *.kate-swp
4 |
5 | !.gitignore
6 | !.gitreview
7 |
8 | !*.yml
9 |
10 | vendor/
11 | composer.phar
12 | composer.lock
13 |
14 | build/
--------------------------------------------------------------------------------
/i18n/ja.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Shirayuki"
5 | ]
6 | },
7 | "ask-desc": "クエリ言語 Ask の、PHP での実装を含むライブラリ"
8 | }
--------------------------------------------------------------------------------
/i18n/zh-hant.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Justincheng12345"
5 | ]
6 | },
7 | "ask-desc": "包含以PHP實現的ASK查詢語言的庫"
8 | }
--------------------------------------------------------------------------------
/i18n/he.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Amire80"
5 | ]
6 | },
7 | "ask-desc": "ספרייה שמממשת את שפת השאילתות Ask ב־PHP"
8 | }
--------------------------------------------------------------------------------
/i18n/vi.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Minh Nguyen"
5 | ]
6 | },
7 | "ask-desc": "Thư viện PHP cho ngôn ngữ truy vấn Ask"
8 | }
--------------------------------------------------------------------------------
/i18n/nb.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Jeblad"
5 | ]
6 | },
7 | "ask-desc": "Bibliotek med PHP-implementasjon av Ask-spørrespråket"
8 | }
--------------------------------------------------------------------------------
/i18n/uk.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Ата"
5 | ]
6 | },
7 | "ask-desc": "Бібліотека, що містить PHP-реалізацію мови запитів Ask"
8 | }
--------------------------------------------------------------------------------
/i18n/ru.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Okras"
5 | ]
6 | },
7 | "ask-desc": "Библиотека, содержащая PHP-реализацию язык запросов Ask"
8 | }
--------------------------------------------------------------------------------
/i18n/sv.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "LittleGun"
5 | ]
6 | },
7 | "ask-desc": "Bibliotek med en PHP implementering av Ask frågespråk"
8 | }
--------------------------------------------------------------------------------
/i18n/be-tarask.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Wizardist"
5 | ]
6 | },
7 | "ask-desc": "Бібліятэка, якая рэалізуе на PHP мову запытаў Ask"
8 | }
--------------------------------------------------------------------------------
/i18n/eu.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Theklan"
5 | ]
6 | },
7 | "ask-desc": "Ask query hizkuntzaren PHP inplementazioa duen liburutegia"
8 | }
--------------------------------------------------------------------------------
/i18n/fa.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Reza1615"
5 | ]
6 | },
7 | "ask-desc": "کتابخانه شامل پیادهسازی پیاچپی از زبان کوئری پرس و جو است"
8 | }
--------------------------------------------------------------------------------
/i18n/mk.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Bjankuloski06"
5 | ]
6 | },
7 | "ask-desc": "Библиотека што содржи PHP-примена на јазикот за барање Ask"
8 | }
--------------------------------------------------------------------------------
/i18n/nl.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Siebrand"
5 | ]
6 | },
7 | "ask-desc": "Bibliotheek die een PHP-implementatie bevat van de querytaal Ask"
8 | }
--------------------------------------------------------------------------------
/i18n/pt-br.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Cainamarques"
5 | ]
6 | },
7 | "ask-desc": "Biblioteca contendo uma implementação PHP da linguagem Ask"
8 | }
--------------------------------------------------------------------------------
/i18n/pt.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Cainamarques"
5 | ]
6 | },
7 | "ask-desc": "Biblioteca contendo uma implementação PHP da linguagem Ask"
8 | }
--------------------------------------------------------------------------------
/i18n/ast.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Xuacu"
5 | ]
6 | },
7 | "ask-desc": "Biblioteca que contien un encadarmáu en PHP del llinguaxe de consulta Ask"
8 | }
--------------------------------------------------------------------------------
/i18n/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Jeroen De Dauw"
5 | ]
6 | },
7 | "ask-desc": "Library containing a PHP implementation of the Ask query language"
8 | }
--------------------------------------------------------------------------------
/i18n/gl.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Toliño"
5 | ]
6 | },
7 | "ask-desc": "Biblioteca que contén unha integración PHP da linguaxe de consulta Ask"
8 | }
--------------------------------------------------------------------------------
/i18n/it.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Beta16"
5 | ]
6 | },
7 | "ask-desc": "Libreria contenente un'implementazione PHP del linguaggio di query Ask"
8 | }
--------------------------------------------------------------------------------
/i18n/ms.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Anakmalaysia"
5 | ]
6 | },
7 | "ask-desc": "Perpustakaan yang mengandungi pelaksanaan PHP bahasa pertanyaan Ask"
8 | }
--------------------------------------------------------------------------------
/i18n/qqq.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Shirayuki"
5 | ]
6 | },
7 | "ask-desc": "{{desc|name=Ask|url=http://www.mediawiki.org/wiki/Extension:Ask}}"
8 | }
--------------------------------------------------------------------------------
/i18n/dsb.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Michawiki"
5 | ]
6 | },
7 | "ask-desc": "Biblioteka, kótaraž wopśimujo PHP-implementaciju napšašowańskeje rěcy Ask"
8 | }
--------------------------------------------------------------------------------
/i18n/hsb.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Michawiki"
5 | ]
6 | },
7 | "ask-desc": "Biblioteka, kotraž PHP-implementaciju naprašowanskeje rěče Ask wobsahuje"
8 | }
--------------------------------------------------------------------------------
/i18n/oc.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Cedric31"
5 | ]
6 | },
7 | "ask-desc": "Bibliotèca que conten una implementacion PHP del lengatge de requèsta Ask"
8 | }
--------------------------------------------------------------------------------
/i18n/ia.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "McDutchie"
5 | ]
6 | },
7 | "ask-desc": "Bibliotheca que contine un implementation in PHP del linguage de consulta ASK"
8 | }
--------------------------------------------------------------------------------
/i18n/es.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Fitoschido"
5 | ]
6 | },
7 | "ask-desc": "Biblioteca que contiene una implementación en PHP del lenguaje de consulta de Ask"
8 | }
--------------------------------------------------------------------------------
/i18n/roa-tara.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Joetaras"
5 | ]
6 | },
7 | "ask-desc": "Libbrerie ca tène 'n'imblemendazione PHP d'a lènghe pe le 'nderrogaziune Ask"
8 | }
--------------------------------------------------------------------------------
/i18n/tl.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "AnakngAraw"
5 | ]
6 | },
7 | "ask-desc": "Aklatan na naglalaman ng isang pagsasakatuparan ng PHP ng wika ng pag-uungkat ng Ask"
8 | }
--------------------------------------------------------------------------------
/i18n/bcl.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Geopoet"
5 | ]
6 | },
7 | "ask-desc": "An Librari na igwang laog na implementasyon kan PHP kan lengguwahe nin Hapot sa kahaputan"
8 | }
--------------------------------------------------------------------------------
/i18n/ilo.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Lam-ang"
5 | ]
6 | },
7 | "ask-desc": "Biblioteka nga aglaon ti maysa a PHP a panangigaretget iti panagsukisok a pagsasao ti Ask"
8 | }
--------------------------------------------------------------------------------
/i18n/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Gomoko",
5 | "Tpt"
6 | ]
7 | },
8 | "ask-desc": "Bibliothèque contenant une implémentation PHP du langage de requête Ask"
9 | }
--------------------------------------------------------------------------------
/i18n/ksh.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Purodha"
5 | ]
6 | },
7 | "ask-desc": "En Biblijoteek met en PHP jeschrevve Projramme, di di Schprooch Ask för et Befroore ömsäze."
8 | }
--------------------------------------------------------------------------------
/i18n/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "@metadata": {
3 | "authors": [
4 | "Kghbln",
5 | "Metalhead64"
6 | ]
7 | },
8 | "ask-desc": "Ergänzt eine Bibliothek, die eine PHP-Implementierung der Abfragesprache „Ask“ enthält"
9 | }
--------------------------------------------------------------------------------
/src/Hashable.php:
--------------------------------------------------------------------------------
1 |
12 | */
13 | interface Hashable extends \Hashable {}
14 |
--------------------------------------------------------------------------------
/src/Comparable.php:
--------------------------------------------------------------------------------
1 |
12 | */
13 | interface Comparable extends \Comparable {}
14 |
--------------------------------------------------------------------------------
/src/Immutable.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | interface Immutable extends \Immutable {}
15 |
--------------------------------------------------------------------------------
/.scrutinizer.yml:
--------------------------------------------------------------------------------
1 | build: true
2 | inherit: true
3 |
4 | before_commands:
5 | - "composer install --prefer-source"
6 |
7 | tools:
8 | php_code_sniffer: true
9 | php_cpd: true
10 | php_cs_fixer: true
11 | php_loc: true
12 | php_mess_detector: true
13 | php_pdepend: true
14 | php_analyzer: true
15 | sensiolabs_security_checker: true
16 |
--------------------------------------------------------------------------------
/src/Typeable.php:
--------------------------------------------------------------------------------
1 |
12 | */
13 | interface Typeable {
14 |
15 | /**
16 | * Returns a type identifier for the object.
17 | * This identifier does not have to be globally unique,
18 | * though is expected to be unique for objects of the same type.
19 | *
20 | * @since 1.0
21 | *
22 | * @return string
23 | */
24 | public function getType();
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/Language/Selection/SelectionRequest.php:
--------------------------------------------------------------------------------
1 |
15 | */
16 | abstract class SelectionRequest implements \Ask\Comparable, \Ask\Hashable, \Ask\Typeable {
17 |
18 | const TYPE_PROP = 'property';
19 | const TYPE_SUBJECT = 'subject';
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 5.3
5 | - 5.4
6 | - 5.5
7 | - 5.6
8 | - 7
9 | - hhvm
10 |
11 | before_script:
12 | - composer self-update
13 |
14 | script:
15 | - phpunit --coverage-clover build/logs/clover.xml
16 |
17 | after_script:
18 | - composer require satooshi/php-coveralls:dev-master
19 | - php vendor/bin/coveralls -v
20 |
21 | notifications:
22 | email:
23 | recipients:
24 | - jeroendedauw@gmail.com
25 | on_success: change
26 | on_failure: always
27 | irc:
28 | channels:
29 | - "chat.freenode.net#wikidata-feed"
30 | on_success: change
31 | on_failure: always
32 |
33 | cache:
34 | directories:
35 | - $HOME/.composer/cache
36 |
--------------------------------------------------------------------------------
/Tests/bootstrap.php:
--------------------------------------------------------------------------------
1 |
10 | */
11 |
12 |
13 | if ( php_sapi_name() !== 'cli' ) {
14 | die( 'Not an entry point' );
15 | }
16 |
17 | $pwd = getcwd();
18 | chdir( __DIR__ . '/..' );
19 | passthru( 'composer update' );
20 | chdir( $pwd );
21 |
22 | if ( !is_readable( __DIR__ . '/../vendor/autoload.php' ) ) {
23 | die( 'You need to install this package with Composer before you can run the tests' );
24 | }
25 |
26 | require_once( __DIR__ . '/../vendor/autoload.php' );
27 |
28 | require_once( __DIR__ . '/testLoader.php' );
29 |
--------------------------------------------------------------------------------
/Tests/Phpunit/Language/Description/AnyValueTest.php:
--------------------------------------------------------------------------------
1 |
20 | */
21 | class AnyValueTest extends DescriptionTest {
22 |
23 | /**
24 | * {@inheritdoc}
25 | */
26 | protected function getInstances() {
27 | $instances = array();
28 |
29 | $instances[] = new AnyValue();
30 |
31 | return $instances;
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/Language/Description/Conjunction.php:
--------------------------------------------------------------------------------
1 |
17 | */
18 | final class Conjunction extends DescriptionCollection {
19 |
20 | /**
21 | * {@inheritdoc}
22 | *
23 | * @since 1.0
24 | *
25 | * @return string
26 | */
27 | public function getType() {
28 | return 'conjunction';
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/Language/Description/Disjunction.php:
--------------------------------------------------------------------------------
1 |
17 | */
18 | final class Disjunction extends DescriptionCollection {
19 |
20 | /**
21 | * {@inheritdoc}
22 | *
23 | * @since 1.0
24 | *
25 | * @return string
26 | */
27 | public function getType() {
28 | return 'disjunction';
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/Tests/Phpunit/Language/Selection/SubjectSelectionTest.php:
--------------------------------------------------------------------------------
1 |
20 | */
21 | class SubjectSelectionTest extends SelectionRequestTest {
22 |
23 | /**
24 | * {@inheritdoc}
25 | */
26 | protected function getInstances() {
27 | $instances = array();
28 |
29 | $instances[] = new SubjectSelection();
30 |
31 | return $instances;
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/Language/Description/Description.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | abstract class Description implements \Ask\Comparable, \Ask\Hashable, \Ask\Typeable {
16 |
17 | /**
18 | * Returns the size of the description.
19 | *
20 | * @since 1.0
21 | *
22 | * @return integer
23 | */
24 | public abstract function getSize();
25 |
26 | /**
27 | * Returns the depth of the description.
28 | *
29 | * @since 1.0
30 | *
31 | * @return integer
32 | */
33 | public abstract function getDepth();
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/Ask.php:
--------------------------------------------------------------------------------
1 |
11 | */
12 |
13 | if ( defined( 'Ask_VERSION' ) ) {
14 | // Do not initialize more than once.
15 | return 1;
16 | }
17 |
18 | define( 'Ask_VERSION', '1.0.3-alpha' );
19 |
20 | // Attempt to include the dependencies if one has not been loaded yet.
21 | // This is the path to the autoloader generated by composer in case of a composer install.
22 | if ( !defined( 'DATAVALUES_VERSION' ) && is_readable( __DIR__ . '/vendor/autoload.php' ) ) {
23 | include_once( __DIR__ . '/vendor/autoload.php' );
24 | }
25 |
26 | if ( defined( 'MEDIAWIKI' ) ) {
27 | call_user_func( function() {
28 | require_once __DIR__ . '/Ask.mw.php';
29 | } );
30 | }
31 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
14 |
15 |
16 | Tests/Phpunit
17 |
18 |
19 |
20 |
21 | src
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Tests/Phpunit/Language/Selection/PropertySelectionTest.php:
--------------------------------------------------------------------------------
1 |
21 | */
22 | class PropertySelectionTest extends SelectionRequestTest {
23 |
24 | /**
25 | * {@inheritdoc}
26 | */
27 | protected function getInstances() {
28 | $instances = array();
29 |
30 | $instances[] = new PropertySelection(
31 | new StringValue( 'p42' )
32 | );
33 |
34 | $instances[] = new PropertySelection(
35 | new StringValue( '_geo' )
36 | );
37 |
38 | return $instances;
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/Language/Option/SortOptions.php:
--------------------------------------------------------------------------------
1 |
12 | */
13 | class SortOptions implements \Ask\Immutable {
14 |
15 | /**
16 | * The sort expressions that make up these sort options.
17 | *
18 | * @since 1.0
19 | *
20 | * @var SortExpression[]
21 | */
22 | protected $expressions;
23 |
24 | /**
25 | * @since 1.0
26 | *
27 | * @param SortExpression[] $expressions
28 | */
29 | public function __construct( array $expressions ) {
30 | $this->expressions = $expressions;
31 | }
32 |
33 | /**
34 | * Returns the sort expressions that make up these sort options.
35 | *
36 | * @since 1.0
37 | *
38 | * @return SortExpression[]
39 | */
40 | public function getExpressions() {
41 | return $this->expressions;
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/Tests/testLoader.php:
--------------------------------------------------------------------------------
1 |
10 | */
11 |
12 | spl_autoload_register( function ( $className ) {
13 | $className = ltrim( $className, '\\' );
14 | $fileName = '';
15 | $namespace = '';
16 |
17 | if ( $lastNsPos = strripos( $className, '\\') ) {
18 | $namespace = substr( $className, 0, $lastNsPos );
19 | $className = substr( $className, $lastNsPos + 1 );
20 | $fileName = str_replace( '\\', '/', $namespace ) . '/';
21 | }
22 |
23 | $fileName .= str_replace( '_', '/', $className ) . '.php';
24 |
25 | $namespaceSegments = explode( '\\', $namespace );
26 |
27 | if ( count( $namespaceSegments ) > 1 && $namespaceSegments[0] === 'Ask' && $namespaceSegments[1] === 'Tests' ) {
28 | $fileName = substr( $fileName, 4 );
29 | require_once __DIR__ . '/../' . $fileName;
30 | }
31 | } );
32 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ask/ask",
3 | "type": "library",
4 | "description": "Library containing a PHP implementation of the Ask query language",
5 | "keywords": [
6 | "ask",
7 | "wikidata",
8 | "SMW",
9 | "Semantic MediaWiki"
10 | ],
11 | "homepage": "https://github.com/wmde/Ask",
12 | "license": "GPL-2.0+",
13 | "authors": [
14 | {
15 | "name": "Jeroen De Dauw",
16 | "email": "jeroendedauw@gmail.com",
17 | "homepage": "http://jeroendedauw.com",
18 | "role": "Developer"
19 | },
20 | {
21 | "name": "Markus Krötzsch",
22 | "homepage": "http://korrekt.org",
23 | "role": "Author of the code this lib is based on"
24 | }
25 | ],
26 | "support": {
27 | "irc": "irc://irc.freenode.net/wikidata"
28 | },
29 | "require": {
30 | "php": ">=5.3.0",
31 | "data-values/data-values": "~2.0@dev|~1.0|~0.1"
32 | },
33 | "autoload": {
34 | "files" : [
35 | "Ask.php"
36 | ],
37 | "psr-4": {
38 | "Ask\\": "src/"
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Ask.mw.php:
--------------------------------------------------------------------------------
1 |
11 | */
12 |
13 | if ( !defined( 'MEDIAWIKI' ) ) {
14 | die( 'Not an entry point.' );
15 | }
16 |
17 | $GLOBALS['wgExtensionCredits']['other'][] = array(
18 | 'path' => __FILE__,
19 | 'name' => 'Ask',
20 | 'version' => Ask_VERSION,
21 | 'author' => array(
22 | '[https://www.mediawiki.org/wiki/User:Jeroen_De_Dauw Jeroen De Dauw]',
23 |
24 | // A big part of this library is conceptually based on code from Semantic MediaWiki 1.9 written by Markus
25 | 'Markus Krötzsch',
26 | ),
27 | 'url' => 'https://github.com/wmde/Ask',
28 | 'descriptionmsg' => 'ask-desc',
29 | 'license-name' => 'GPL-2.0+'
30 | );
31 |
32 | $GLOBALS['wgMessagesDirs']['AskExtension'] = __DIR__ . '/i18n';
33 | $GLOBALS['wgExtensionMessagesFiles']['AskExtension'] = __DIR__ . '/Ask.i18n.php';
34 |
--------------------------------------------------------------------------------
/src/Language/Selection/SubjectSelection.php:
--------------------------------------------------------------------------------
1 |
12 | */
13 | final class SubjectSelection extends SelectionRequest implements \Ask\Immutable {
14 |
15 | /**
16 | * @see Typeable::getType
17 | *
18 | * @since 1.0
19 | *
20 | * @return string
21 | */
22 | public function getType() {
23 | return SelectionRequest::TYPE_SUBJECT;
24 | }
25 |
26 | /**
27 | * @see Comparable::equals
28 | *
29 | * @since 1.0
30 | *
31 | * @param mixed $mixed
32 | *
33 | * @return boolean
34 | */
35 | public function equals( $mixed ) {
36 | return $mixed instanceof SubjectSelection;
37 | }
38 |
39 | /**
40 | * @see Hashable::getHash
41 | *
42 | * @since 1.0
43 | *
44 | * @return string
45 | */
46 | public function getHash() {
47 | return sha1( $this->getType() );
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/src/Language/Option/SortExpression.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | abstract class SortExpression implements \Ask\Immutable, \Ask\Typeable {
16 |
17 | const PROPERTY_VALUE = 'propertyValue';
18 |
19 | const DIRECTION_ASCENDING = 'asc';
20 | const DIRECTION_DESCENDING = 'desc';
21 |
22 | /**
23 | * The sort direction.
24 | * This is one of the SortExpression::DIRECTION_ constants.
25 | *
26 | * @var string|null
27 | */
28 | protected $direction = null;
29 |
30 | /**
31 | * Returns the sort direction.
32 | * This is one of the SortExpression::DIRECTION_ constants.
33 | *
34 | * @since 1.0
35 | *
36 | * @return string
37 | */
38 | public function getDirection() {
39 | assert( $this->direction !== null );
40 | return $this->direction;
41 | }
42 |
43 | protected function assertIsDirection( $direction ) {
44 | if ( !is_string( $direction ) || !in_array( $direction, array( self::DIRECTION_ASCENDING, self::DIRECTION_DESCENDING ) ) ) {
45 | throw new InvalidArgumentException( '$direction needs to be one of the direction constants' );
46 | }
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/Tests/Phpunit/Language/Option/SortExpressionTest.php:
--------------------------------------------------------------------------------
1 |
17 | */
18 | abstract class SortExpressionTest extends \Ask\Tests\Phpunit\AskTestCase {
19 |
20 | /**
21 | * @since 1.0
22 | *
23 | * @return SortExpression[]
24 | */
25 | protected abstract function getInstances();
26 |
27 | /**
28 | * @since 1.0
29 | *
30 | * @return SortExpression[][]
31 | */
32 | public function instanceProvider() {
33 | return $this->arrayWrap( $this->getInstances() );
34 | }
35 |
36 | /**
37 | * @dataProvider instanceProvider
38 | *
39 | * @since 1.0
40 | *
41 | * @param SortExpression $expression
42 | */
43 | public function testReturnValueOfGetDirection( SortExpression $expression ) {
44 | $direction = $expression->getDirection();
45 |
46 | $this->assertInternalType( 'string', $direction );
47 | $this->assertTrue(
48 | in_array( $direction, array( SortExpression::DIRECTION_ASCENDING, SortExpression::DIRECTION_DESCENDING ) ),
49 | 'Sort direction is one of the known values'
50 | );
51 | }
52 |
53 | }
54 |
--------------------------------------------------------------------------------
/src/Language/Description/AnyValue.php:
--------------------------------------------------------------------------------
1 |
16 | */
17 | final class AnyValue extends Description implements \Ask\Immutable {
18 |
19 | /**
20 | * {@inheritdoc}
21 | *
22 | * @since 1.0
23 | *
24 | * @return integer
25 | */
26 | public function getSize() {
27 | return 0;
28 | }
29 |
30 | /**
31 | * {@inheritdoc}
32 | *
33 | * @since 1.0
34 | *
35 | * @return integer
36 | */
37 | public function getDepth() {
38 | return 0;
39 | }
40 |
41 | /**
42 | * {@inheritdoc}
43 | *
44 | * @since 1.0
45 | *
46 | * @return string
47 | */
48 | public function getType() {
49 | return 'anyValue';
50 | }
51 |
52 | /**
53 | * @see Comparable::equals
54 | *
55 | * @since 1.0
56 | *
57 | * @param mixed $mixed
58 | *
59 | * @return boolean
60 | */
61 | public function equals( $mixed ) {
62 | return $mixed instanceof AnyValue;
63 | }
64 |
65 | /**
66 | * @see Hashable::getHash
67 | *
68 | * @since 1.0
69 | *
70 | * @return string
71 | */
72 | public function getHash() {
73 | return sha1( $this->getType() );
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/Tests/Phpunit/AskTestCase.php:
--------------------------------------------------------------------------------
1 |
15 | */
16 | abstract class AskTestCase extends \PHPUnit_Framework_TestCase {
17 |
18 | /**
19 | * Utility method taking an array of elements and wrapping
20 | * each element in it's own array. Useful for data providers
21 | * that only return a single argument.
22 | *
23 | * @since 1.0
24 | *
25 | * @param array $elements
26 | *
27 | * @return array
28 | */
29 | protected function arrayWrap( array $elements ) {
30 | return array_map(
31 | function( $element ) {
32 | return array( $element );
33 | },
34 | $elements
35 | );
36 | }
37 |
38 | protected function assertPrimitiveStructure( $value ) {
39 | if ( is_array( $value ) || is_object( $value ) ) {
40 | // TODO: would be good if we could reject objects that are not simple maps
41 | $value = (array)$value;
42 |
43 | if ( empty( $value ) ) {
44 | $this->assertTrue( true );
45 | }
46 |
47 | foreach ( $value as $subValue ) {
48 | $this->assertPrimitiveStructure( $subValue );
49 | }
50 | }
51 | else {
52 | $this->assertFalse( is_resource( $value ), 'Value should not be a resource' );
53 | }
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/Language/Option/PropertyValueSortExpression.php:
--------------------------------------------------------------------------------
1 |
15 | */
16 | class PropertyValueSortExpression extends SortExpression {
17 |
18 | /**
19 | * The property value to sort by.
20 | *
21 | * @since 1.0
22 | *
23 | * @var DataValue
24 | */
25 | protected $property;
26 |
27 | /**
28 | * @since 1.0
29 | *
30 | * @param DataValue $propertyId
31 | * @param string $direction One of the SortExpression::DIRECTION_ constants
32 | *
33 | * @throws InvalidArgumentException
34 | */
35 | public function __construct( DataValue $propertyId, $direction ) {
36 | $this->property = $propertyId;
37 |
38 | $this->assertIsDirection( $direction );
39 |
40 | $this->direction = $direction;
41 | }
42 |
43 | /**
44 | * Returns the property value to sort by.
45 | *
46 | * @since 1.0
47 | *
48 | * @return DataValue
49 | */
50 | public function getPropertyId() {
51 | return $this->property;
52 | }
53 |
54 | /**
55 | * {@inheritdoc}
56 | *
57 | * @since 1.0
58 | *
59 | * @return string
60 | */
61 | public function getType() {
62 | return SortExpression::PROPERTY_VALUE;
63 | }
64 |
65 | }
66 |
--------------------------------------------------------------------------------
/Ask.i18n.php:
--------------------------------------------------------------------------------
1 |
24 | */
25 | class SortOptionsTest extends AskTestCase {
26 |
27 | /**
28 | * @dataProvider sortExpressionListProvider
29 | */
30 | public function testGetExpressions( array $expressions ) {
31 | $options = new SortOptions( $expressions );
32 |
33 | $this->assertEquals( $expressions, $options->getExpressions() );
34 | }
35 |
36 | public function sortExpressionListProvider() {
37 | $argLists = array();
38 |
39 | $argLists[] = array( array() );
40 |
41 | $argLists[] = array( array(
42 | new PropertyValueSortExpression(
43 | new StringValue( 'foo' ),
44 | SortExpression::DIRECTION_ASCENDING
45 | )
46 | ) );
47 |
48 | $argLists[] = array( array(
49 | new PropertyValueSortExpression(
50 | new StringValue( 'foo' ),
51 | SortExpression::DIRECTION_ASCENDING
52 | ),
53 | new PropertyValueSortExpression(
54 | new StringValue( 'bar' ),
55 | SortExpression::DIRECTION_DESCENDING
56 | ),
57 | ) );
58 |
59 | return $argLists;
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/Language/Option/QueryOptions.php:
--------------------------------------------------------------------------------
1 |
12 | */
13 | class QueryOptions implements \Ask\Immutable {
14 |
15 | /**
16 | * The query limit. At most this many results will be selected.
17 | *
18 | * @since 1.0
19 | *
20 | * @var int
21 | */
22 | protected $limit;
23 |
24 | /**
25 | * The query offset. The first this many matching results will be skipped.
26 | *
27 | * @since 1.0
28 | *
29 | * @var int
30 | */
31 | protected $offset;
32 |
33 | /**
34 | * The query sort.
35 | *
36 | * @since 1.0
37 | *
38 | * @var SortOptions
39 | */
40 | protected $sort;
41 |
42 | /**
43 | * @since 1.0
44 | *
45 | * @param int $limit
46 | * @param int $offset
47 | * @param SortOptions|null $sort
48 | */
49 | public function __construct( $limit, $offset, SortOptions $sort = null ) {
50 | $this->limit = $limit;
51 | $this->offset = $offset;
52 | $this->sort = $sort === null ? new SortOptions( array() ) : $sort;
53 | }
54 |
55 | /**
56 | * Returns the query limit.
57 | *
58 | * @since 1.0
59 | *
60 | * @return int
61 | */
62 | public function getLimit() {
63 | return $this->limit;
64 | }
65 |
66 | /**
67 | * Returns the query offset.
68 | *
69 | * @since 1.0
70 | *
71 | * @return int
72 | */
73 | public function getOffset() {
74 | return $this->offset;
75 | }
76 |
77 | /**
78 | * Returns the query sort options.
79 | *
80 | * @since 1.0
81 | *
82 | * @return SortOptions
83 | */
84 | public function getSort() {
85 | return $this->sort;
86 | }
87 |
88 | }
89 |
--------------------------------------------------------------------------------
/src/Language/Selection/PropertySelection.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | final class PropertySelection extends SelectionRequest implements \Ask\Immutable {
16 |
17 | /**
18 | * The property for which to select values.
19 | *
20 | * @since 1.0
21 | *
22 | * @var DataValue
23 | */
24 | protected $propertyId;
25 |
26 | /**
27 | * @since 1.0
28 | *
29 | * @param DataValue $propertyId
30 | */
31 | public function __construct( DataValue $propertyId ) {
32 | $this->propertyId = $propertyId;
33 | }
34 |
35 | /**
36 | * @see Typeable::getType
37 | *
38 | * @since 1.0
39 | *
40 | * @return string
41 | */
42 | public function getType() {
43 | return SelectionRequest::TYPE_PROP;
44 | }
45 |
46 | /**
47 | * Returns the print request's property.
48 | *
49 | * @since 1.0
50 | *
51 | * @return DataValue
52 | */
53 | public function getPropertyId() {
54 | return $this->propertyId;
55 | }
56 |
57 | /**
58 | * @see Comparable::equals
59 | *
60 | * @since 1.0
61 | *
62 | * @param mixed $mixed
63 | *
64 | * @return boolean
65 | */
66 | public function equals( $mixed ) {
67 | return $mixed instanceof PropertySelection
68 | && $this->propertyId->equals( $mixed->getPropertyId() );
69 | }
70 |
71 | /**
72 | * @see Hashable::getHash
73 | *
74 | * @since 1.0
75 | *
76 | * @return string
77 | */
78 | public function getHash() {
79 | return sha1( $this->getType() . $this->propertyId->getHash() );
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/Tests/Phpunit/Language/Option/QueryOptionsTest.php:
--------------------------------------------------------------------------------
1 |
22 | */
23 | class QueryOptionsTest extends AskTestCase {
24 |
25 | /**
26 | * @since 1.0
27 | *
28 | * @return QueryOptions[]
29 | */
30 | protected function getInstances() {
31 | $instances = array();
32 |
33 | $instances[] = new QueryOptions(
34 | 100,
35 | 0
36 | );
37 |
38 | $instances[] = new QueryOptions(
39 | 5,
40 | 100
41 | );
42 |
43 | $instances[] = new QueryOptions(
44 | 9000,
45 | 42,
46 | new SortOptions( array() )
47 | );
48 |
49 | return $instances;
50 | }
51 |
52 | /**
53 | * @since 1.0
54 | *
55 | * @return QueryOptions[][]
56 | */
57 | public function instanceProvider() {
58 | return $this->arrayWrap( $this->getInstances() );
59 | }
60 |
61 | /**
62 | * @dataProvider constructorArgumentProvider
63 | */
64 | public function testConstructSetsFields( $limit, $offset, SortOptions $sort ) {
65 | $queryOptions = new QueryOptions( $limit, $offset, $sort );
66 |
67 | $this->assertEquals( $limit, $queryOptions->getLimit() );
68 | $this->assertEquals( $offset, $queryOptions->getOffset() );
69 | $this->assertEquals( $sort, $queryOptions->getSort() );
70 | }
71 |
72 | public function constructorArgumentProvider() {
73 | $argLists = array();
74 |
75 | $argLists[] = array( 1, 2, new SortOptions( array() ) );
76 |
77 | $argLists[] = array( 100, 0, new SortOptions( array() ) );
78 |
79 | return $argLists;
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/Tests/Phpunit/Language/Option/PropertyValueSortExpressionTest.php:
--------------------------------------------------------------------------------
1 |
23 | */
24 | class PropertyValueSortExpressionTest extends SortExpressionTest {
25 |
26 | public function testCanConstruct() {
27 | new PropertyValueSortExpression(
28 | new StringValue( 'foo' ),
29 | SortExpression::DIRECTION_ASCENDING
30 | );
31 |
32 | $this->assertTrue( true );
33 | }
34 |
35 | public function testGetPropertyId() {
36 | $propertyId = new StringValue( 'foo' );
37 |
38 | $sortExpression = new PropertyValueSortExpression(
39 | $propertyId,
40 | SortExpression::DIRECTION_ASCENDING
41 | );
42 |
43 | $this->assertEquals( $propertyId, $sortExpression->getPropertyId() );
44 | }
45 |
46 | /**
47 | * @see SortExpressionTest::getInstances
48 | *
49 | * @since 1.0
50 | *
51 | * @return SortExpression[]
52 | */
53 | protected function getInstances() {
54 | $instances = array();
55 |
56 | $instances[] = new PropertyValueSortExpression(
57 | new StringValue( 'foo' ),
58 | SortExpression::DIRECTION_ASCENDING
59 | );
60 |
61 | $instances[] = new PropertyValueSortExpression(
62 | new StringValue( 'foo' ),
63 | SortExpression::DIRECTION_DESCENDING
64 | );
65 |
66 | return $instances;
67 | }
68 |
69 | /**
70 | * @dataProvider invalidSortDirectionProvider
71 | */
72 | public function testCannotConstructWithInvalidSortDirection( $invalidSortDirection ) {
73 | $this->setExpectedException( 'InvalidArgumentException' );
74 |
75 | new PropertyValueSortExpression(
76 | new StringValue( 'foo' ),
77 | $invalidSortDirection
78 | );
79 | }
80 |
81 | public function invalidSortDirectionProvider() {
82 | return array(
83 | array( null ),
84 | array( array() ),
85 | array( true ),
86 | array( 4.2 ),
87 | array( 'foo' ),
88 | );
89 | }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/Tests/Phpunit/Language/Selection/SelectionRequestTest.php:
--------------------------------------------------------------------------------
1 |
17 | */
18 | abstract class SelectionRequestTest extends \Ask\Tests\Phpunit\AskTestCase {
19 |
20 | /**
21 | * @since 1.0
22 | *
23 | * @return SelectionRequest[]
24 | */
25 | protected abstract function getInstances();
26 |
27 | /**
28 | * @since 1.0
29 | *
30 | * @return SelectionRequest[][]
31 | */
32 | public function instanceProvider() {
33 | return $this->arrayWrap( $this->getInstances() );
34 | }
35 |
36 | /**
37 | * @dataProvider instanceProvider
38 | *
39 | * @since 1.0
40 | *
41 | * @param SelectionRequest $request
42 | */
43 | public function testReturnTypeOfGetType( SelectionRequest $request ) {
44 | $this->assertInternalType( 'string', $request->getType() );
45 | }
46 |
47 | /**
48 | * @dataProvider instanceProvider
49 | *
50 | * @since 1.0
51 | *
52 | * @param SelectionRequest $object
53 | */
54 | public function testComparableSelfIsEqual( SelectionRequest $object ) {
55 | $this->assertTrue( $object->equals( $object ), 'Description is equal to itself' );
56 | }
57 |
58 | /**
59 | * @dataProvider instanceProvider
60 | *
61 | * @since 1.0
62 | *
63 | * @param SelectionRequest $object
64 | */
65 | public function testComparableNotEqual( SelectionRequest $object ) {
66 | $this->assertFalse( $object->equals( '~[,,_,,]:3' ), 'Description not equal to string' );
67 | $this->assertFalse( $object->equals( new \stdClass() ), 'Description not equal to empty object' );
68 | }
69 |
70 | /**
71 | * @dataProvider instanceProvider
72 | *
73 | * @since 1.0
74 | *
75 | * @param SelectionRequest $object
76 | */
77 | public function testGetHashReturnType( SelectionRequest $object ) {
78 | $this->assertInternalType( 'string', $object->getHash() );
79 | }
80 |
81 | /**
82 | * @dataProvider instanceProvider
83 | *
84 | * @since 1.0
85 | *
86 | * @param SelectionRequest $object
87 | */
88 | public function testGetHashStability( SelectionRequest $object ) {
89 | $this->assertEquals( $object->getHash(), $object->getHash() );
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/src/Language/Query.php:
--------------------------------------------------------------------------------
1 |
16 | */
17 | class Query implements \Ask\Immutable {
18 |
19 | const OPT_LIMIT = 'limit';
20 | const OPT_OFFSET = 'offset';
21 | const OPT_SORT = 'sort';
22 |
23 | /**
24 | * The query's description.
25 | * This is the selection criterion of the query that determines which entities match.
26 | * It is conceptually similar to the WHERE clause in an SQL query.
27 | *
28 | * @since 1.0
29 | *
30 | * @var Description
31 | */
32 | protected $description;
33 |
34 | /**
35 | * The query's selection requests.
36 | * These determine which information should be selected from the matching entities.
37 | * It is conceptually similar to the SELECT clause in an SQL query.
38 | *
39 | * @since 1.0
40 | *
41 | * @var SelectionRequest[]
42 | */
43 | protected $selectionRequests;
44 |
45 | /**
46 | * The query's options.
47 | *
48 | * @since 1.0
49 | *
50 | * @var QueryOptions
51 | */
52 | protected $options;
53 |
54 | /**
55 | * @since 1.0
56 | *
57 | * @param Description $description
58 | * @param SelectionRequest[] $selectionRequests
59 | * @param QueryOptions $options
60 | */
61 | public function __construct( Description $description, array $selectionRequests, QueryOptions $options ) {
62 | $this->description = $description;
63 | $this->selectionRequests = $selectionRequests;
64 | $this->options = $options;
65 | }
66 |
67 | /**
68 | * Returns the query description.
69 | *
70 | * @since 1.0
71 | *
72 | * @return Description
73 | */
74 | public function getDescription() {
75 | return $this->description;
76 | }
77 |
78 | /**
79 | * Returns the query's selection requests.
80 | *
81 | * @since 1.0
82 | *
83 | * @return SelectionRequest[]
84 | */
85 | public function getSelectionRequests() {
86 | return $this->selectionRequests;
87 | }
88 |
89 | /**
90 | * Returns the query's options.
91 | *
92 | * @since 1.0
93 | *
94 | * @return QueryOptions
95 | */
96 | public function getOptions() {
97 | return $this->options;
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/Tests/Phpunit/Language/Description/ConjunctionTest.php:
--------------------------------------------------------------------------------
1 |
27 | */
28 | class ConjunctionTest extends DescriptionCollectionTest {
29 |
30 | /**
31 | * {@inheritdoc}
32 | */
33 | protected function getInstances() {
34 | $instances = array();
35 |
36 | $instances[] = new Conjunction( array() );
37 | $instances[] = new Conjunction( array( new Conjunction( array() ) ) );
38 | $instances[] = new Conjunction( array( new Disjunction( array() ), new Disjunction( array() ) ) );
39 | $instances[] = new Conjunction( array( new AnyValue() ) );
40 | $instances[] = new Conjunction( array( new ValueDescription( new StringValue( 'ohi' ) ) ) );
41 |
42 | foreach ( $this->descriptionsProvider() as $argList ) {
43 | $instances[] = new Conjunction( $argList[0] );
44 | }
45 |
46 | return $instances;
47 | }
48 |
49 | /**
50 | * @dataProvider instanceProvider
51 | *
52 | * @since 1.0
53 | *
54 | * @param Conjunction $description
55 | */
56 | public function testGetDescriptions( Conjunction $description ) {
57 | $descriptions = $description->getDescriptions();
58 |
59 | $this->assertInternalType( 'array', $descriptions );
60 |
61 | foreach ( $descriptions as $subInstance ) {
62 | $this->assertInstanceOf( 'Ask\Language\Description\Description', $subInstance );
63 | }
64 |
65 | $newInstance = new Disjunction( $descriptions );
66 |
67 | $this->assertEquals( $descriptions, $newInstance->getDescriptions(), 'Descriptions are returned as it was passed to the constructor' );
68 | }
69 |
70 | /**
71 | * @see DescriptionCollectionTest::newFromDescriptions
72 | *
73 | * @param Description[] $descriptions
74 | *
75 | * @return DescriptionCollection
76 | */
77 | protected function newFromDescriptions( array $descriptions ) {
78 | return new Conjunction( $descriptions );
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/Tests/Phpunit/Language/Description/DisjunctionTest.php:
--------------------------------------------------------------------------------
1 |
27 | */
28 | class DisjunctionTest extends DescriptionCollectionTest {
29 |
30 | /**
31 | * {@inheritdoc}
32 | */
33 | protected function getInstances() {
34 | $instances = array();
35 |
36 | $instances[] = new Disjunction( array() );
37 | $instances[] = new Disjunction( array( new Conjunction( array() ) ) );
38 | $instances[] = new Disjunction( array( new Disjunction( array() ), new Disjunction( array() ) ) );
39 | $instances[] = new Disjunction( array( new AnyValue() ) );
40 | $instances[] = new Disjunction( array( new ValueDescription( new StringValue( 'ohi' ) ) ) );
41 |
42 | foreach ( $this->descriptionsProvider() as $argList ) {
43 | $instances[] = new Disjunction( $argList[0] );
44 | }
45 |
46 | return $instances;
47 | }
48 |
49 | /**
50 | * @dataProvider instanceProvider
51 | *
52 | * @since 1.0
53 | *
54 | * @param Disjunction $description
55 | */
56 | public function testGetDescriptions( Disjunction $description ) {
57 | $descriptions = $description->getDescriptions();
58 |
59 | $this->assertInternalType( 'array', $descriptions );
60 |
61 | foreach ( $descriptions as $subInstance ) {
62 | $this->assertInstanceOf( 'Ask\Language\Description\Description', $subInstance );
63 | }
64 |
65 | $newInstance = new Disjunction( $descriptions );
66 |
67 | $this->assertEquals( $descriptions, $newInstance->getDescriptions(), 'Descriptions are returned as it was passed to the constructor' );
68 | }
69 |
70 | /**
71 | * @see DescriptionCollectionTest::newFromDescriptions
72 | *
73 | * @param Description[] $descriptions
74 | *
75 | * @return DescriptionCollection
76 | */
77 | protected function newFromDescriptions( array $descriptions ) {
78 | return new Disjunction( $descriptions );
79 | }
80 |
81 | }
82 |
--------------------------------------------------------------------------------
/Tests/Phpunit/Language/QueryTest.php:
--------------------------------------------------------------------------------
1 |
26 | */
27 | class QueryTest extends \Ask\Tests\Phpunit\AskTestCase {
28 |
29 | public function descriptionProvider() {
30 | $descriptions = array();
31 |
32 | $descriptions[] = new AnyValue();
33 | $descriptions[] = new Conjunction( array() );
34 | $descriptions[] = new Disjunction( array() );
35 |
36 | return $this->arrayWrap( $descriptions );
37 | }
38 |
39 | /**
40 | * @dataProvider descriptionProvider
41 | *
42 | * @param Description $description
43 | */
44 | public function testGetDescriptions( Description $description ) {
45 | $query = new Query( $description, array(), new QueryOptions( 100, 0 ) );
46 |
47 | $obtainedDescription = $query->getDescription();
48 |
49 | $this->assertInstanceOf( '\Ask\Language\Description\Description', $obtainedDescription );
50 |
51 | $this->assertEquals( $description, $obtainedDescription );
52 | }
53 |
54 | public function selectionRequestsProvider() {
55 | $requestsLists = array();
56 |
57 | $requestsLists[] = array(
58 | new PropertySelection( new StringValue( 'q42' ) ),
59 | new PropertySelection( new StringValue( '_geo' ) ),
60 | );
61 |
62 | return $this->arrayWrap( $requestsLists );
63 | }
64 |
65 | /**
66 | * @dataProvider selectionRequestsProvider
67 | *
68 | * @param array $selectionRequests
69 | */
70 | public function testGetSelectionRequests( array $selectionRequests ) {
71 | $query = new Query( new AnyValue(), $selectionRequests, new QueryOptions( 100, 0 ) );
72 |
73 | $obtainedRequests = $query->getSelectionRequests();
74 |
75 | $this->assertInternalType( 'array', $obtainedRequests );
76 | $this->assertContainsOnlyInstancesOf( '\Ask\Language\Selection\SelectionRequest', $obtainedRequests );
77 |
78 | $this->assertEquals( $selectionRequests, $obtainedRequests );
79 | }
80 |
81 | public function instanceProvider() {
82 | $instances = array();
83 |
84 | $instances[] = new Query(
85 | new AnyValue(),
86 | array(
87 | new PropertySelection( new StringValue( 'q42' ) ),
88 | new PropertySelection( new StringValue( '_geo' ) ),
89 | ),
90 | new QueryOptions( 100, 0 )
91 | );
92 |
93 | return $this->arrayWrap( $instances );
94 | }
95 |
96 | }
97 |
--------------------------------------------------------------------------------
/Tests/Phpunit/Language/Description/ValueDescriptionTest.php:
--------------------------------------------------------------------------------
1 |
22 | */
23 | class ValueDescriptionTest extends DescriptionTest {
24 |
25 | /**
26 | * {@inheritdoc}
27 | */
28 | protected function getInstances() {
29 | $instances = array();
30 |
31 | $values = array(
32 | new StringValue( 'ohi there' ),
33 | new NumberValue( 4.2 ),
34 | );
35 |
36 | $comparators = array(
37 | ValueDescription::COMP_EQUAL,
38 | ValueDescription::COMP_LEQ,
39 | ValueDescription::COMP_GEQ,
40 | ValueDescription::COMP_NEQ,
41 | ValueDescription::COMP_LIKE,
42 | ValueDescription::COMP_NLIKE,
43 | ValueDescription::COMP_LESS,
44 | ValueDescription::COMP_GREATER,
45 | );
46 |
47 | foreach ( $values as $value ) {
48 | foreach ( $comparators as $comparator ) {
49 | $instances[] = new ValueDescription( $value, $comparator );
50 | }
51 | }
52 |
53 | return $instances;
54 | }
55 |
56 | /**
57 | * @dataProvider instanceProvider
58 | *
59 | * @since 1.0
60 | *
61 | * @param ValueDescription $description
62 | */
63 | public function testGetValue( ValueDescription $description ) {
64 | $value = $description->getValue();
65 |
66 | $this->assertInstanceOf( 'DataValues\DataValue', $value );
67 |
68 | $newInstance = new ValueDescription( $value );
69 |
70 | $this->assertTrue( $value->equals( $newInstance->getValue() ), 'Value is returned as it was passed to the constructor' );
71 | }
72 |
73 | /**
74 | * @dataProvider instanceProvider
75 | *
76 | * @since 1.0
77 | *
78 | * @param ValueDescription $description
79 | */
80 | public function testGetComparator( ValueDescription $description ) {
81 | $comparator = $description->getComparator();
82 |
83 | $this->assertInternalType( 'integer', $comparator );
84 |
85 | $newInstance = new ValueDescription( $description->getValue(), $comparator );
86 |
87 | $this->assertEquals( $comparator, $newInstance->getComparator(), 'Comparator is returned as it was passed to the constructor' );
88 | }
89 |
90 | /**
91 | * @dataProvider invalidComparatorProvider
92 | */
93 | public function testCannotConstructWithInvalidComparator( $invalidComparator ) {
94 | $this->setExpectedException( 'InvalidArgumentException' );
95 | new ValueDescription( new StringValue( 'foo' ), $invalidComparator );
96 | }
97 |
98 | public function invalidComparatorProvider() {
99 | return array(
100 | array( null ),
101 | array( array() ),
102 | array( 4.2 ),
103 | array( true ),
104 | array( 'foo' ),
105 | array( '' ),
106 | );
107 | }
108 |
109 | }
110 |
--------------------------------------------------------------------------------
/Tests/Phpunit/Language/Description/SomePropertyTest.php:
--------------------------------------------------------------------------------
1 |
23 | */
24 | class SomePropertyTest extends DescriptionTest {
25 |
26 | /**
27 | * {@inheritdoc}
28 | */
29 | protected function getInstances() {
30 | $instances = array();
31 |
32 | $instances[] = new SomeProperty( new StringValue( '_geo' ), new AnyValue() );
33 | $instances[] = new SomeProperty( new StringValue( 'p42' ), new Conjunction( array() ) );
34 | $instances[] = new SomeProperty( new StringValue( 'foo' ), new AnyValue(), true );
35 | $instances[] = new SomeProperty( new StringValue( '~=[,,_,,]:3' ), new AnyValue(), false );
36 |
37 | return $instances;
38 | }
39 |
40 | /**
41 | * @dataProvider instanceProvider
42 | *
43 | * @since 1.0
44 | *
45 | * @param SomeProperty $description
46 | */
47 | public function testGetDescription( SomeProperty $description ) {
48 | $subDescription = $description->getSubDescription();
49 |
50 | $this->assertInstanceOf( 'Ask\Language\Description\Description', $subDescription );
51 |
52 | $newInstance = new SomeProperty( $description->getPropertyId(), $subDescription );
53 |
54 | $this->assertEquals(
55 | $subDescription,
56 | $newInstance->getSubDescription(),
57 | 'Description is returned as it was passed to the constructor'
58 | );
59 | }
60 |
61 | /**
62 | * @dataProvider instanceProvider
63 | *
64 | * @since 1.0
65 | *
66 | * @param SomeProperty $description
67 | */
68 | public function testGetProperty( SomeProperty $description ) {
69 | $property = $description->getPropertyId();
70 |
71 | $this->assertInstanceOf( '\DataValues\DataValue', $property );
72 |
73 | $newInstance = new SomeProperty( $property, $description->getSubDescription() );
74 |
75 | $this->assertEquals(
76 | $property,
77 | $newInstance->getPropertyId(),
78 | 'Property is returned as it was passed to the constructor'
79 | );
80 | }
81 |
82 | /**
83 | * @dataProvider instanceProvider
84 | *
85 | * @since 1.0
86 | *
87 | * @param SomeProperty $description
88 | */
89 | public function testIsSubProperty( SomeProperty $description ) {
90 | $isSubProperty = $description->isSubProperty();
91 |
92 | $this->assertInternalType( 'boolean', $isSubProperty );
93 |
94 | $newInstance = new SomeProperty( $description->getPropertyId(), $description->getSubDescription(), $isSubProperty );
95 |
96 | $this->assertEquals(
97 | $isSubProperty,
98 | $newInstance->isSubProperty(),
99 | 'Is sub property is returned as it was passed to the constructor'
100 | );
101 | }
102 |
103 | }
104 |
--------------------------------------------------------------------------------
/Tests/Phpunit/Language/Description/DescriptionTest.php:
--------------------------------------------------------------------------------
1 |
17 | */
18 | abstract class DescriptionTest extends \Ask\Tests\Phpunit\AskTestCase {
19 |
20 | /**
21 | * @since 1.0
22 | *
23 | * @return Description[]
24 | */
25 | protected abstract function getInstances();
26 |
27 | /**
28 | * @since 1.0
29 | *
30 | * @return Description[][]
31 | */
32 | public function instanceProvider() {
33 | return $this->arrayWrap( $this->getInstances() );
34 | }
35 |
36 | /**
37 | * @dataProvider instanceProvider
38 | *
39 | * @since 1.0
40 | *
41 | * @param Description $description
42 | */
43 | public function testReturnTypeOfGetSize( Description $description ) {
44 | $size = $description->getSize();
45 |
46 | $this->assertInternalType( 'integer', $size );
47 | $this->assertGreaterThanOrEqual( 0, $size );
48 | $this->assertEquals( $size, $description->getSize() );
49 | }
50 |
51 | /**
52 | * @dataProvider instanceProvider
53 | *
54 | * @since 1.0
55 | *
56 | * @param Description $description
57 | */
58 | public function testReturnTypeOfGetDepth( Description $description ) {
59 | $depth = $description->getDepth();
60 |
61 | $this->assertInternalType( 'integer', $depth );
62 | $this->assertGreaterThanOrEqual( 0, $depth );
63 | $this->assertEquals( $depth, $description->getDepth() );
64 | }
65 |
66 | /**
67 | * @dataProvider instanceProvider
68 | *
69 | * @since 1.0
70 | *
71 | * @param Description $description
72 | */
73 | public function testComparableSelfIsEqual( Description $description ) {
74 | $this->assertTrue( $description->equals( $description ), 'Description is equal to itself' );
75 | }
76 |
77 | /**
78 | * @dataProvider instanceProvider
79 | *
80 | * @since 1.0
81 | *
82 | * @param Description $description
83 | */
84 | public function testComparableNotEqual( Description $description ) {
85 | $this->assertFalse( $description->equals( '~[,,_,,]:3' ), 'Description not equal to string' );
86 | $this->assertFalse( $description->equals( new \stdClass() ), 'Description not equal to empty object' );
87 | $this->assertFalse( $description->equals( new FooDescription() ), 'Description not equal to a FooDescription' );
88 | }
89 |
90 | /**
91 | * @dataProvider instanceProvider
92 | *
93 | * @since 1.0
94 | *
95 | * @param Description $description
96 | */
97 | public function testGetHashReturnType( Description $description ) {
98 | $this->assertInternalType( 'string', $description->getHash() );
99 | }
100 |
101 | /**
102 | * @dataProvider instanceProvider
103 | *
104 | * @since 1.0
105 | *
106 | * @param Description $description
107 | */
108 | public function testGetHashStability( Description $description ) {
109 | $this->assertEquals( $description->getHash(), $description->getHash() );
110 | }
111 |
112 | }
113 |
114 | class FooDescription extends \Ask\Language\Description\DescriptionCollection {
115 |
116 | public function __construct() {
117 | parent::__construct( array() );
118 | }
119 |
120 | public function getType() {
121 | return 'foo';
122 | }
123 |
124 | public function equals( $t ) {
125 | return false;
126 | }
127 |
128 | }
129 |
--------------------------------------------------------------------------------
/Tests/Phpunit/Language/Description/DescriptionCollectionTest.php:
--------------------------------------------------------------------------------
1 |
23 | */
24 | abstract class DescriptionCollectionTest extends DescriptionTest {
25 |
26 | public function descriptionsProvider() {
27 | $descriptionLists = array();
28 |
29 | $descriptionLists[] = array();
30 |
31 | $descriptionLists[] = array(
32 | new AnyValue(),
33 | new ValueDescription( new StringValue( 'nyan nyan' ) )
34 | );
35 |
36 | $descriptionList = array();
37 | $numbers = range( 0, 100 );
38 | shuffle( $numbers );
39 |
40 | foreach ( $numbers as $number ) {
41 | $descriptionList[] = new ValueDescription( new NumberValue( $number ) );
42 | }
43 |
44 | $descriptionLists[] = $descriptionList;
45 |
46 | return $this->arrayWrap( $descriptionLists );
47 | }
48 |
49 | /**
50 | * @param Description[] $descriptions
51 | *
52 | * @return DescriptionCollection
53 | */
54 | protected abstract function newFromDescriptions( array $descriptions );
55 |
56 | /**
57 | * @dataProvider descriptionsProvider
58 | *
59 | * @param Description[] $descriptions
60 | */
61 | public function testEqualsOrderInsensitivity( array $descriptions ) {
62 | $sameDescriptions = $descriptions;
63 | shuffle( $sameDescriptions );
64 |
65 | $description = $this->newFromDescriptions( $descriptions );
66 | $sameDescription = $this->newFromDescriptions( $sameDescriptions );
67 |
68 | $message = 'Two collection descriptions with same sub descriptions should be equal';
69 |
70 | $this->assertTrue( $description->equals( $sameDescription ), $message );
71 | $this->assertTrue( $sameDescription->equals( $description ), $message );
72 | }
73 |
74 | /**
75 | * @dataProvider descriptionsProvider
76 | *
77 | * @param Description[] $descriptions
78 | */
79 | public function testGetHashOrderInsensitivity( array $descriptions ) {
80 | $sameDescriptions = $descriptions;
81 | shuffle( $sameDescriptions );
82 |
83 | $description = $this->newFromDescriptions( $descriptions );
84 | $sameDescription = $this->newFromDescriptions( $sameDescriptions );
85 |
86 | $this->assertEquals( $description->getHash(), $sameDescription->getHash() );
87 | }
88 |
89 | /**
90 | * @dataProvider descriptionsProvider
91 | *
92 | * @param Description[] $descriptions
93 | */
94 | public function testDifferentSizeNotEquals( array $descriptions ) {
95 | $firstDescription = $this->newFromDescriptions( $descriptions );
96 |
97 | $descriptions[] = new AnyValue();
98 |
99 | $secondDescription = $this->newFromDescriptions( $descriptions );
100 |
101 | $this->assertFalse( $firstDescription->equals( $secondDescription ) );
102 | }
103 |
104 | public function testDifferentContainedDescriptionCausesInequality() {
105 | $firstDescription = $this->newFromDescriptions( array( new AnyValue() ) );
106 | $secondDescription = $this->newFromDescriptions( array( new Conjunction( array() ) ) );
107 |
108 | $this->assertFalse( $secondDescription->equals( $firstDescription ) );
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/src/Language/Description/ValueDescription.php:
--------------------------------------------------------------------------------
1 |
24 | */
25 | class ValueDescription extends Description implements \Ask\Immutable {
26 |
27 | // This list has values backwards compatible with SMW_CMP_.
28 | const COMP_EQUAL = 1;
29 | const COMP_LEQ = 2; // Less than or equal
30 | const COMP_GEQ = 3; // Greater than or equal
31 | const COMP_NEQ = 4; // Not equal
32 | const COMP_LIKE = 5;
33 | const COMP_NLIKE = 6; // Not like
34 | const COMP_LESS = 7; // Strictly less than
35 | const COMP_GREATER = 8; // Strictly greater than
36 |
37 | /**
38 | * The value to compare to.
39 | *
40 | * @since 1.0
41 | *
42 | * @var DataValue
43 | */
44 | protected $value;
45 |
46 | /**
47 | * The comparator to use to determine if the value matches.
48 | *
49 | * @since 1.0
50 | *
51 | * @var int
52 | */
53 | protected $comparator;
54 |
55 | /**
56 | * @since 1.0
57 | *
58 | * @param DataValue $value
59 | * @param int $comparator
60 | *
61 | * @throws InvalidArgumentException
62 | */
63 | public function __construct( DataValue $value, $comparator = self::COMP_EQUAL ) {
64 | $this->assertComparatorValidity( $comparator );
65 |
66 | $this->value = $value;
67 | $this->comparator = $comparator;
68 | }
69 |
70 | protected function assertComparatorValidity( $comparator ) {
71 | if ( !is_int( $comparator ) || $comparator < self::COMP_EQUAL || $comparator > self::COMP_GREATER ) {
72 | throw new InvalidArgumentException( 'Invalid comparator specified' );
73 | }
74 | }
75 |
76 | /**
77 | * Returns the value to compare against.
78 | *
79 | * @since 1.0
80 | *
81 | * @return DataValue
82 | */
83 | public function getValue() {
84 | return $this->value;
85 | }
86 |
87 | /**
88 | * Returns the comparator to use when comparing against the value.
89 | *
90 | * @since 1.0
91 | *
92 | * @return int
93 | */
94 | public function getComparator() {
95 | return $this->comparator;
96 | }
97 |
98 | /**
99 | * {@inheritdoc}
100 | *
101 | * @since 1.0
102 | *
103 | * @return integer
104 | */
105 | public function getSize() {
106 | return 1;
107 | }
108 |
109 | /**
110 | * {@inheritdoc}
111 | *
112 | * @since 1.0
113 | *
114 | * @return integer
115 | */
116 | public function getDepth() {
117 | return 0;
118 | }
119 |
120 | /**
121 | * {@inheritdoc}
122 | *
123 | * @since 1.0
124 | *
125 | * @return string
126 | */
127 | public function getType() {
128 | return 'valueDescription';
129 | }
130 |
131 | /**
132 | * @see Comparable::equals
133 | *
134 | * @since 1.0
135 | *
136 | * @param mixed $mixed
137 | *
138 | * @return boolean
139 | */
140 | public function equals( $mixed ) {
141 | return $mixed instanceof ValueDescription
142 | && $this->comparator === $mixed->getComparator()
143 | && $this->value->equals( $mixed->getValue() );
144 | }
145 |
146 | /**
147 | * @see Hashable::getHash
148 | *
149 | * @since 1.0
150 | *
151 | * @return string
152 | */
153 | public function getHash() {
154 | return sha1( $this->getType() . $this->value->getHash() . $this->comparator );
155 | }
156 |
157 | }
158 |
--------------------------------------------------------------------------------
/src/Language/Description/DescriptionCollection.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | abstract class DescriptionCollection extends Description implements \Ask\Immutable {
16 |
17 | /**
18 | * The descriptions that make up this collection of descriptions.
19 | *
20 | * @var Description[]
21 | */
22 | private $descriptions;
23 |
24 | /**
25 | * Cache for the hash.
26 | *
27 | * @var string|null
28 | */
29 | private $hash = null;
30 |
31 | /**
32 | * @since 1.0
33 | *
34 | * @param Description[] $descriptions
35 | */
36 | public function __construct( array $descriptions ) {
37 | $this->descriptions = $descriptions;
38 | }
39 |
40 | /**
41 | * {@inheritdoc}
42 | *
43 | * @since 1.0
44 | *
45 | * @return integer
46 | */
47 | public function getSize() {
48 | $size = 0;
49 |
50 | foreach ( $this->descriptions as $description ) {
51 | $size += $description->getSize();
52 | }
53 |
54 | assert( $size >= 0 );
55 |
56 | return $size;
57 | }
58 |
59 | /**
60 | * {@inheritdoc}
61 | *
62 | * @since 1.0
63 | *
64 | * @return integer
65 | */
66 | public function getDepth() {
67 | $depth = 0;
68 |
69 | foreach ( $this->descriptions as $description ) {
70 | $depth = max( $depth, $description->getDepth() );
71 | }
72 |
73 | assert( $depth >= 0 );
74 |
75 | return $depth;
76 | }
77 |
78 | /**
79 | * Returns the descriptions that make up this collection of descriptions.
80 | *
81 | * @since 1.0
82 | *
83 | * @return Description[]
84 | */
85 | public function getDescriptions() {
86 | return $this->descriptions;
87 | }
88 |
89 | /**
90 | * @see Comparable::equals
91 | *
92 | * Note: it is possible this method provides false negatives due to
93 | * equivalent expressions being expressed in different structures.
94 | * This is however likely not important.
95 | *
96 | * @since 1.0
97 | *
98 | * @param mixed $mixed
99 | *
100 | * @return boolean
101 | */
102 | public function equals( $mixed ) {
103 | if ( !is_object( $mixed )
104 | || ( get_class( $mixed ) !== get_called_class() ) ) {
105 | return false;
106 | }
107 |
108 | $descriptions = $this->descriptions;
109 | $moreDescriptions = $mixed->getDescriptions();
110 |
111 | if ( count( $descriptions ) !== count( $moreDescriptions ) ) {
112 | return false;
113 | }
114 |
115 | $this->sortCollection( $descriptions );
116 | $this->sortCollection( $moreDescriptions );
117 | reset( $moreDescriptions );
118 |
119 | foreach ( $descriptions as $description ) {
120 | if ( !$description->equals( current( $moreDescriptions ) ) ) {
121 | return false;
122 | }
123 |
124 | next( $moreDescriptions );
125 | }
126 |
127 | return true;
128 | }
129 |
130 | /**
131 | * @see Hashable::getHash
132 | *
133 | * @since 1.0
134 | *
135 | * @return string
136 | */
137 | public function getHash() {
138 | if ( $this->hash === null ) {
139 | $this->sortCollection( $this->descriptions );
140 |
141 | $this->hash = sha1(
142 | $this->getType() .
143 | implode(
144 | '|',
145 | array_map(
146 | function( Hashable $hashable ) {
147 | return $hashable->getHash();
148 | },
149 | $this->descriptions
150 | )
151 | )
152 | );
153 | }
154 |
155 | return $this->hash;
156 | }
157 |
158 | /**
159 | * Does an associative sort that works for Hashable objects.
160 | *
161 | * @since 1.0
162 | *
163 | * @param Hashable[] $array
164 | */
165 | final protected function sortCollection( array &$array ) {
166 | usort(
167 | $array,
168 | function ( Hashable $a, Hashable $b ) {
169 | return $a->getHash() > $b->getHash() ? 1 : -1;
170 | }
171 | );
172 | }
173 |
174 | }
175 |
--------------------------------------------------------------------------------
/src/Language/Description/SomeProperty.php:
--------------------------------------------------------------------------------
1 |
22 | */
23 | final class SomeProperty extends Description implements \Ask\Immutable {
24 |
25 | /**
26 | * The property that should be present.
27 | *
28 | * @var DataValue
29 | */
30 | private $propertyId;
31 |
32 | /**
33 | * The description the properties value should match.
34 | *
35 | * @var Description
36 | */
37 | private $subDescription;
38 |
39 | /**
40 | * If the property is a sub property or not.
41 | *
42 | * For instance in the Wikibase Claim context,
43 | * a non-sub property would point to the property
44 | * of the main snak, while a sub property would
45 | * point to a qualifier.
46 | *
47 | * @var boolean
48 | */
49 | private $isSubProperty;
50 |
51 | /**
52 | * Cache for the hash.
53 | *
54 | * @var string|null
55 | */
56 | private $hash = null;
57 |
58 | /**
59 | * @since 1.0
60 | *
61 | * @param DataValue $propertyId
62 | * @param Description $subDescription
63 | * @param boolean $isSubProperty
64 | *
65 | * @throws InvalidArgumentException
66 | */
67 | public function __construct( DataValue $propertyId, Description $subDescription, $isSubProperty = false ) {
68 | $this->propertyId = $propertyId;
69 | $this->subDescription = $subDescription;
70 |
71 | if ( !is_bool( $isSubProperty ) ) {
72 | throw new InvalidArgumentException( '$isSubProperty must be of type boolean' );
73 | }
74 |
75 | $this->isSubProperty = $isSubProperty;
76 | }
77 |
78 | /**
79 | * Returns the description.
80 | *
81 | * @since 1.0
82 | *
83 | * @return Description
84 | */
85 | public function getSubDescription() {
86 | return $this->subDescription;
87 | }
88 |
89 | /**
90 | * Returns the property.
91 | *
92 | * @since 1.0
93 | *
94 | * @return DataValue
95 | */
96 | public function getPropertyId() {
97 | return $this->propertyId;
98 | }
99 |
100 | /**
101 | * Returns if the property is a sub property.
102 | *
103 | * @since 1.0
104 | *
105 | * @return boolean
106 | */
107 | public function isSubProperty() {
108 | return $this->isSubProperty;
109 | }
110 |
111 | /**
112 | * {@inheritdoc}
113 | *
114 | * @since 1.0
115 | *
116 | * @return integer
117 | */
118 | public function getSize() {
119 | return $this->subDescription->getSize() + 1;
120 | }
121 |
122 | /**
123 | * {@inheritdoc}
124 | *
125 | * @since 1.0
126 | *
127 | * @return integer
128 | */
129 | public function getDepth() {
130 | return $this->subDescription->getDepth() + 1;
131 | }
132 |
133 | /**
134 | * {@inheritdoc}
135 | *
136 | * @since 1.0
137 | *
138 | * @return string
139 | */
140 | public function getType() {
141 | return 'someProperty';
142 | }
143 |
144 | /**
145 | * @see Comparable::equals
146 | *
147 | * @since 1.0
148 | *
149 | * @param mixed $mixed
150 | *
151 | * @return boolean
152 | */
153 | public function equals( $mixed ) {
154 | return $mixed instanceof SomeProperty
155 | && $this->isSubProperty === $mixed->isSubProperty()
156 | && $this->propertyId->equals( $mixed->getPropertyId() )
157 | && $this->subDescription->equals( $mixed->getSubDescription() );
158 | }
159 |
160 | /**
161 | * @see Hashable::getHash
162 | *
163 | * @since 1.0
164 | *
165 | * @return string
166 | */
167 | public function getHash() {
168 | if ( $this->hash === null ) {
169 | $this->hash = sha1(
170 | $this->getType() .
171 | $this->propertyId->getHash() .
172 | $this->subDescription->getHash() .
173 | $this->isSubProperty
174 | );
175 | }
176 |
177 | return $this->hash;
178 | }
179 |
180 | }
181 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | This library is no longer under development and is no longer maintained.
2 |
3 | # Ask
4 |
5 | Library containing a PHP implementation of the Ask query language.
6 |
7 | The implementation consists out of domain objects that represent various parts of Ask queries.
8 |
9 | [](http://travis-ci.org/wmde/Ask)
10 | [](https://coveralls.io/r/wmde/Ask?branch=master)
11 | [](https://scrutinizer-ci.com/g/wmde/Ask/)
12 |
13 | On Packagist:
14 | [](https://packagist.org/packages/ask/ask)
15 | [](https://packagist.org/packages/ask/ask)
16 |
17 | ## Requirements
18 |
19 | * PHP 5.3 or later
20 | * [DataValues](https://github.com/DataValues/DataValues) 0.1 or later
21 |
22 | ## Installation
23 |
24 | You can use [Composer](http://getcomposer.org/) to download and install
25 | this package as well as its dependencies. Alternatively you can simply clone
26 | the git repository and take care of loading yourself.
27 |
28 | ### Composer
29 |
30 | To add this package as a local, per-project dependency to your project, simply add a
31 | dependency on `ask/ask` to your project's `composer.json` file.
32 | Here is a minimal example of a `composer.json` file that just defines a dependency on
33 | Ask 1.0:
34 |
35 | {
36 | "require": {
37 | "ask/ask": "1.0.*"
38 | }
39 | }
40 |
41 | ### Manual
42 |
43 | Get the Ask code, either via git, or some other means. Also get all dependencies.
44 | You can find a list of the dependencies in the "require" section of the composer.json file.
45 | Load all dependencies and the load the Ask library by including its entry point:
46 | Ask.php.
47 |
48 | ## Structure
49 |
50 | The Ask library defines the Ask query language. Its important components are:
51 |
52 | * Ask\Language - everything part of the ask language itself
53 |
54 | * Ask\Language\Description - descriptions (aka concepts)
55 | * Ask\Language\Option - QueryOptions object and its parts
56 | * Ask\Language\Selection - selection requests
57 | * Ask\Language\Query.php - the object defining what a query is
58 |
59 | ### Description
60 |
61 | Each query has a single description which specifies which entities match. This is similar to the
62 | WHERE part of an SQL string. There different types of descriptions are listed below. Since several
63 | types of descriptions can be composed out of one or more sub descriptions, tree like structures can
64 | be created.
65 |
66 | * Description - abstract base class
67 |
68 | * AnyValue - A description that matches any object
69 | * Conjunction - Description of a collection of many descriptions, all of which must be satisfied (AND)
70 | * Disjunction - Description of a collection of many descriptions, at least one of which must be satisfied (OR)
71 | * SomeProperty - Description of a set of instances that have an attribute with some value that fits another (sub)description
72 | * ValueDescription - Description of one data value, or of a range of data values
73 |
74 | All descriptions reside in the Ask\Language\Description namespace.
75 |
76 | ### Option
77 |
78 | The options a query consist out of are defined by the QueryOptions class. This class
79 | contains limit, offset and sorting options.
80 |
81 | Sorting options are defined by the SortOptions class, which contains a list of
82 | SortExpression objects.
83 |
84 | All options related classes reside in the Ask\Language\Option namespace.
85 |
86 | ### Selection
87 |
88 | Specifying what information a query should select from matching entities is done via the selection
89 | requests in the query object. Selection requests are thus akin to the SELECT part of an SQL string.
90 | They thus have no effect on which entities match the query and are returned. All types of selection
91 | request implement abstract base class SelectionRequest and can be found in the Ask\Language\Selection
92 | namespace.
93 |
94 | ## Usage
95 |
96 | #### A query for the first hundred entities that are compared
97 |
98 | ```php
99 | use Ask\Language\Query;
100 | use Ask\Language\Description\AnyValue;
101 | use Ask\Language\Option\QueryOptions;
102 |
103 | $myAwesomeQuery = new Query(
104 | new AnyValue(),
105 | array(),
106 | new QueryOptions( 100, 0 )
107 | );
108 | ```
109 |
110 | #### A query with an offset of 50
111 |
112 | ```php
113 | $myAwesomeQuery = new Query(
114 | new AnyValue(),
115 | array(),
116 | new QueryOptions( 100, 50 )
117 | );
118 | ```
119 |
120 | #### A query to get the ''cost'' of the first hundred entities that have a ''cost'' property
121 |
122 | This is assuming 'p42' is an identifier for a ''cost'' property.
123 |
124 | ```php
125 | $awesomePropertyId = new PropertyValue( 'p42' );
126 |
127 | $myAwesomeQuery = new Query(
128 | new SomeProperty( $awesomePropertyId, new AnyValue() ),
129 | array(
130 | new PropertySelection( $awesomePropertyId )
131 | ),
132 | new QueryOptions( 100, 0 )
133 | );
134 | ```
135 |
136 | #### A query to get the first hundred entities that have 9000.1 as value for their ''cost'' property.
137 |
138 | This is assuming 'p42' is an identifier for a ''cost'' property.
139 |
140 | ```php
141 | $awesomePropertyId = new PropertyValue( 'p42' );
142 | $someCost = new NumericValue( 9000.1 );
143 |
144 | $myAwesomeQuery = new Query(
145 | new SomeProperty( $awesomePropertyId, new ValueDescription( $someCost ) ),
146 | array(),
147 | new QueryOptions( 100, 0 )
148 | );
149 | ```
150 |
151 | #### A query getting the hundred entities with highest ''cost'', highest ''cost'' first
152 |
153 | This is assuming 'p42' is an identifier for a ''cost'' property.
154 |
155 | ```php
156 | $awesomePropertyId = new PropertyValue( 'p42' );
157 |
158 | $myAwesomeQuery = new Query(
159 | new AnyValue(),
160 | array(),
161 | new QueryOptions(
162 | 100,
163 | 0,
164 | new SortOptions( array(
165 | new PropertyValueSortExpression( $awesomePropertyId, SortExpression::DESCENDING )
166 | ) )
167 | )
168 | );
169 | ```
170 |
171 | #### A query to get the hundred first entities that have a ''cost'' either equal to 42 or bigger than 9000
172 |
173 | This is assuming 'p42' is an identifier for a ''cost'' property.
174 |
175 | ```php
176 | $awesomePropertyId = new PropertyValue( 'p42' );
177 | $costOf42 = new NumericValue( 42 );
178 | $costOf9000 = new NumericValue( 9000 );
179 |
180 | $myAwesomeQuery = new Query(
181 | new SomeProperty(
182 | $awesomePropertyId,
183 | new Disjunction( array(
184 | new ValueDescription( $costOf42 ),
185 | new ValueDescription( $costOf9000, ValueDescription::COMP_GRTR ),
186 | ) )
187 | ),
188 | array(),
189 | new QueryOptions( 100, 0 )
190 | );
191 | ```
192 |
193 | ## Tests
194 |
195 | This library comes with a set up PHPUnit tests that cover all non-trivial code. You can run these
196 | tests using the PHPUnit configuration file found in the root directory. The tests can also be run
197 | via TravisCI, as a TravisCI configuration file is also provided in the root directory.
198 |
199 | ## Authors
200 |
201 | Ask has been written by [Jeroen De Dauw](https://www.mediawiki.org/wiki/User:Jeroen_De_Dauw)
202 | as [Wikimedia Germany](https://wikimedia.de) employee for the [Wikidata project](https://wikidata.org/).
203 |
204 | This library is a reimplementation of the Ask language domain objects in
205 | [Semantic MediaWiki](https://semantic-mediawiki.org/), which have been written by
206 | [Markus Krötzsch](http://korrekt.org/). This reimplementation is conceptually almost
207 | entirely based on the original code and contains small portions of it.
208 |
209 | ## Release notes
210 |
211 | ### 1.0.3 (alpha)
212 |
213 | * Installation together with DataValues 2.x is now supported.
214 |
215 | ### 1.0.2 (2014-10-16)
216 |
217 | * Installation together with DataValues 1.x is now supported.
218 |
219 | ### 1.0.1 (2014-01-21)
220 |
221 | * Removed custom autoloader. The Composer support for PSR-4 is now used.
222 | * The PHPUnit bootstrap file now automatically runs "composer update".
223 |
224 | ### 1.0 (2013-11-17)
225 |
226 | Initial release with these features:
227 |
228 | * PHP implementation of the Ask language core
229 | * Implementation of descriptions, selection requests and sort options initially needed for Wikidata
230 |
231 | ## Links
232 |
233 | * [Ask on Packagist](https://packagist.org/packages/ask/ask)
234 | * [Ask on Ohloh](https://www.ohloh.net/p/ask)
235 | * [Ask on coveralls.io](https://coveralls.io/r/wmde/Ask?branch=master)
236 | * [Ask on ScrutinizerCI](https://scrutinizer-ci.com/g/wmde/Ask/)
237 | * [Ask on TravisCI](https://travis-ci.org/wmde/Ask)
238 | * [NodeJS implementation of Ask](https://github.com/JeroenDeDauw/AskJS)
239 |
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 | The license text below "----" applies to all files within this distribution, other
2 | than those that are in a directory which contains files named "LICENSE" or
3 | "COPYING", or a subdirectory thereof. For those files, the license text contained in
4 | said file overrides any license information contained in directories of smaller depth.
5 | Alternative licenses are typically used for software that is provided by external
6 | parties, and merely packaged with this software for convenience.
7 | ----
8 |
9 | GNU GENERAL PUBLIC LICENSE
10 | Version 2, June 1991
11 |
12 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
13 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
14 | Everyone is permitted to copy and distribute verbatim copies
15 | of this license document, but changing it is not allowed.
16 |
17 | Preamble
18 |
19 | The licenses for most software are designed to take away your
20 | freedom to share and change it. By contrast, the GNU General Public
21 | License is intended to guarantee your freedom to share and change free
22 | software--to make sure the software is free for all its users. This
23 | General Public License applies to most of the Free Software
24 | Foundation's software and to any other program whose authors commit to
25 | using it. (Some other Free Software Foundation software is covered by
26 | the GNU Lesser General Public License instead.) You can apply it to
27 | your programs, too.
28 |
29 | When we speak of free software, we are referring to freedom, not
30 | price. Our General Public Licenses are designed to make sure that you
31 | have the freedom to distribute copies of free software (and charge for
32 | this service if you wish), that you receive source code or can get it
33 | if you want it, that you can change the software or use pieces of it
34 | in new free programs; and that you know you can do these things.
35 |
36 | To protect your rights, we need to make restrictions that forbid
37 | anyone to deny you these rights or to ask you to surrender the rights.
38 | These restrictions translate to certain responsibilities for you if you
39 | distribute copies of the software, or if you modify it.
40 |
41 | For example, if you distribute copies of such a program, whether
42 | gratis or for a fee, you must give the recipients all the rights that
43 | you have. You must make sure that they, too, receive or can get the
44 | source code. And you must show them these terms so they know their
45 | rights.
46 |
47 | We protect your rights with two steps: (1) copyright the software, and
48 | (2) offer you this license which gives you legal permission to copy,
49 | distribute and/or modify the software.
50 |
51 | Also, for each author's protection and ours, we want to make certain
52 | that everyone understands that there is no warranty for this free
53 | software. If the software is modified by someone else and passed on, we
54 | want its recipients to know that what they have is not the original, so
55 | that any problems introduced by others will not reflect on the original
56 | authors' reputations.
57 |
58 | Finally, any free program is threatened constantly by software
59 | patents. We wish to avoid the danger that redistributors of a free
60 | program will individually obtain patent licenses, in effect making the
61 | program proprietary. To prevent this, we have made it clear that any
62 | patent must be licensed for everyone's free use or not licensed at all.
63 |
64 | The precise terms and conditions for copying, distribution and
65 | modification follow.
66 |
67 | GNU GENERAL PUBLIC LICENSE
68 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
69 |
70 | 0. This License applies to any program or other work which contains
71 | a notice placed by the copyright holder saying it may be distributed
72 | under the terms of this General Public License. The "Program", below,
73 | refers to any such program or work, and a "work based on the Program"
74 | means either the Program or any derivative work under copyright law:
75 | that is to say, a work containing the Program or a portion of it,
76 | either verbatim or with modifications and/or translated into another
77 | language. (Hereinafter, translation is included without limitation in
78 | the term "modification".) Each licensee is addressed as "you".
79 |
80 | Activities other than copying, distribution and modification are not
81 | covered by this License; they are outside its scope. The act of
82 | running the Program is not restricted, and the output from the Program
83 | is covered only if its contents constitute a work based on the
84 | Program (independent of having been made by running the Program).
85 | Whether that is true depends on what the Program does.
86 |
87 | 1. You may copy and distribute verbatim copies of the Program's
88 | source code as you receive it, in any medium, provided that you
89 | conspicuously and appropriately publish on each copy an appropriate
90 | copyright notice and disclaimer of warranty; keep intact all the
91 | notices that refer to this License and to the absence of any warranty;
92 | and give any other recipients of the Program a copy of this License
93 | along with the Program.
94 |
95 | You may charge a fee for the physical act of transferring a copy, and
96 | you may at your option offer warranty protection in exchange for a fee.
97 |
98 | 2. You may modify your copy or copies of the Program or any portion
99 | of it, thus forming a work based on the Program, and copy and
100 | distribute such modifications or work under the terms of Section 1
101 | above, provided that you also meet all of these conditions:
102 |
103 | a) You must cause the modified files to carry prominent notices
104 | stating that you changed the files and the date of any change.
105 |
106 | b) You must cause any work that you distribute or publish, that in
107 | whole or in part contains or is derived from the Program or any
108 | part thereof, to be licensed as a whole at no charge to all third
109 | parties under the terms of this License.
110 |
111 | c) If the modified program normally reads commands interactively
112 | when run, you must cause it, when started running for such
113 | interactive use in the most ordinary way, to print or display an
114 | announcement including an appropriate copyright notice and a
115 | notice that there is no warranty (or else, saying that you provide
116 | a warranty) and that users may redistribute the program under
117 | these conditions, and telling the user how to view a copy of this
118 | License. (Exception: if the Program itself is interactive but
119 | does not normally print such an announcement, your work based on
120 | the Program is not required to print an announcement.)
121 |
122 | These requirements apply to the modified work as a whole. If
123 | identifiable sections of that work are not derived from the Program,
124 | and can be reasonably considered independent and separate works in
125 | themselves, then this License, and its terms, do not apply to those
126 | sections when you distribute them as separate works. But when you
127 | distribute the same sections as part of a whole which is a work based
128 | on the Program, the distribution of the whole must be on the terms of
129 | this License, whose permissions for other licensees extend to the
130 | entire whole, and thus to each and every part regardless of who wrote it.
131 |
132 | Thus, it is not the intent of this section to claim rights or contest
133 | your rights to work written entirely by you; rather, the intent is to
134 | exercise the right to control the distribution of derivative or
135 | collective works based on the Program.
136 |
137 | In addition, mere aggregation of another work not based on the Program
138 | with the Program (or with a work based on the Program) on a volume of
139 | a storage or distribution medium does not bring the other work under
140 | the scope of this License.
141 |
142 | 3. You may copy and distribute the Program (or a work based on it,
143 | under Section 2) in object code or executable form under the terms of
144 | Sections 1 and 2 above provided that you also do one of the following:
145 |
146 | a) Accompany it with the complete corresponding machine-readable
147 | source code, which must be distributed under the terms of Sections
148 | 1 and 2 above on a medium customarily used for software interchange; or,
149 |
150 | b) Accompany it with a written offer, valid for at least three
151 | years, to give any third party, for a charge no more than your
152 | cost of physically performing source distribution, a complete
153 | machine-readable copy of the corresponding source code, to be
154 | distributed under the terms of Sections 1 and 2 above on a medium
155 | customarily used for software interchange; or,
156 |
157 | c) Accompany it with the information you received as to the offer
158 | to distribute corresponding source code. (This alternative is
159 | allowed only for noncommercial distribution and only if you
160 | received the program in object code or executable form with such
161 | an offer, in accord with Subsection b above.)
162 |
163 | The source code for a work means the preferred form of the work for
164 | making modifications to it. For an executable work, complete source
165 | code means all the source code for all modules it contains, plus any
166 | associated interface definition files, plus the scripts used to
167 | control compilation and installation of the executable. However, as a
168 | special exception, the source code distributed need not include
169 | anything that is normally distributed (in either source or binary
170 | form) with the major components (compiler, kernel, and so on) of the
171 | operating system on which the executable runs, unless that component
172 | itself accompanies the executable.
173 |
174 | If distribution of executable or object code is made by offering
175 | access to copy from a designated place, then offering equivalent
176 | access to copy the source code from the same place counts as
177 | distribution of the source code, even though third parties are not
178 | compelled to copy the source along with the object code.
179 |
180 | 4. You may not copy, modify, sublicense, or distribute the Program
181 | except as expressly provided under this License. Any attempt
182 | otherwise to copy, modify, sublicense or distribute the Program is
183 | void, and will automatically terminate your rights under this License.
184 | However, parties who have received copies, or rights, from you under
185 | this License will not have their licenses terminated so long as such
186 | parties remain in full compliance.
187 |
188 | 5. You are not required to accept this License, since you have not
189 | signed it. However, nothing else grants you permission to modify or
190 | distribute the Program or its derivative works. These actions are
191 | prohibited by law if you do not accept this License. Therefore, by
192 | modifying or distributing the Program (or any work based on the
193 | Program), you indicate your acceptance of this License to do so, and
194 | all its terms and conditions for copying, distributing or modifying
195 | the Program or works based on it.
196 |
197 | 6. Each time you redistribute the Program (or any work based on the
198 | Program), the recipient automatically receives a license from the
199 | original licensor to copy, distribute or modify the Program subject to
200 | these terms and conditions. You may not impose any further
201 | restrictions on the recipients' exercise of the rights granted herein.
202 | You are not responsible for enforcing compliance by third parties to
203 | this License.
204 |
205 | 7. If, as a consequence of a court judgment or allegation of patent
206 | infringement or for any other reason (not limited to patent issues),
207 | conditions are imposed on you (whether by court order, agreement or
208 | otherwise) that contradict the conditions of this License, they do not
209 | excuse you from the conditions of this License. If you cannot
210 | distribute so as to satisfy simultaneously your obligations under this
211 | License and any other pertinent obligations, then as a consequence you
212 | may not distribute the Program at all. For example, if a patent
213 | license would not permit royalty-free redistribution of the Program by
214 | all those who receive copies directly or indirectly through you, then
215 | the only way you could satisfy both it and this License would be to
216 | refrain entirely from distribution of the Program.
217 |
218 | If any portion of this section is held invalid or unenforceable under
219 | any particular circumstance, the balance of the section is intended to
220 | apply and the section as a whole is intended to apply in other
221 | circumstances.
222 |
223 | It is not the purpose of this section to induce you to infringe any
224 | patents or other property right claims or to contest validity of any
225 | such claims; this section has the sole purpose of protecting the
226 | integrity of the free software distribution system, which is
227 | implemented by public license practices. Many people have made
228 | generous contributions to the wide range of software distributed
229 | through that system in reliance on consistent application of that
230 | system; it is up to the author/donor to decide if he or she is willing
231 | to distribute software through any other system and a licensee cannot
232 | impose that choice.
233 |
234 | This section is intended to make thoroughly clear what is believed to
235 | be a consequence of the rest of this License.
236 |
237 | 8. If the distribution and/or use of the Program is restricted in
238 | certain countries either by patents or by copyrighted interfaces, the
239 | original copyright holder who places the Program under this License
240 | may add an explicit geographical distribution limitation excluding
241 | those countries, so that distribution is permitted only in or among
242 | countries not thus excluded. In such case, this License incorporates
243 | the limitation as if written in the body of this License.
244 |
245 | 9. The Free Software Foundation may publish revised and/or new versions
246 | of the General Public License from time to time. Such new versions will
247 | be similar in spirit to the present version, but may differ in detail to
248 | address new problems or concerns.
249 |
250 | Each version is given a distinguishing version number. If the Program
251 | specifies a version number of this License which applies to it and "any
252 | later version", you have the option of following the terms and conditions
253 | either of that version or of any later version published by the Free
254 | Software Foundation. If the Program does not specify a version number of
255 | this License, you may choose any version ever published by the Free Software
256 | Foundation.
257 |
258 | 10. If you wish to incorporate parts of the Program into other free
259 | programs whose distribution conditions are different, write to the author
260 | to ask for permission. For software which is copyrighted by the Free
261 | Software Foundation, write to the Free Software Foundation; we sometimes
262 | make exceptions for this. Our decision will be guided by the two goals
263 | of preserving the free status of all derivatives of our free software and
264 | of promoting the sharing and reuse of software generally.
265 |
266 | NO WARRANTY
267 |
268 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
269 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
270 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
271 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
272 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
273 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
274 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
275 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
276 | REPAIR OR CORRECTION.
277 |
278 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
279 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
280 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
281 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
282 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
283 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
284 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
285 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
286 | POSSIBILITY OF SUCH DAMAGES.
287 |
288 | END OF TERMS AND CONDITIONS
289 |
290 | How to Apply These Terms to Your New Programs
291 |
292 | If you develop a new program, and you want it to be of the greatest
293 | possible use to the public, the best way to achieve this is to make it
294 | free software which everyone can redistribute and change under these terms.
295 |
296 | To do so, attach the following notices to the program. It is safest
297 | to attach them to the start of each source file to most effectively
298 | convey the exclusion of warranty; and each file should have at least
299 | the "copyright" line and a pointer to where the full notice is found.
300 |
301 |
302 | Copyright (C)
303 |
304 | This program is free software; you can redistribute it and/or modify
305 | it under the terms of the GNU General Public License as published by
306 | the Free Software Foundation; either version 2 of the License, or
307 | (at your option) any later version.
308 |
309 | This program is distributed in the hope that it will be useful,
310 | but WITHOUT ANY WARRANTY; without even the implied warranty of
311 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
312 | GNU General Public License for more details.
313 |
314 | You should have received a copy of the GNU General Public License along
315 | with this program; if not, write to the Free Software Foundation, Inc.,
316 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
317 |
318 | Also add information on how to contact you by electronic and paper mail.
319 |
320 | If the program is interactive, make it output a short notice like this
321 | when it starts in an interactive mode:
322 |
323 | Gnomovision version 69, Copyright (C) year name of author
324 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
325 | This is free software, and you are welcome to redistribute it
326 | under certain conditions; type `show c' for details.
327 |
328 | The hypothetical commands `show w' and `show c' should show the appropriate
329 | parts of the General Public License. Of course, the commands you use may
330 | be called something other than `show w' and `show c'; they could even be
331 | mouse-clicks or menu items--whatever suits your program.
332 |
333 | You should also get your employer (if you work as a programmer) or your
334 | school, if any, to sign a "copyright disclaimer" for the program, if
335 | necessary. Here is a sample; alter the names:
336 |
337 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
338 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
339 |
340 | , 1 April 1989
341 | Ty Coon, President of Vice
342 |
343 | This General Public License does not permit incorporating your program into
344 | proprietary programs. If your program is a subroutine library, you may
345 | consider it more useful to permit linking proprietary applications with the
346 | library. If this is what you want to do, use the GNU Lesser General
347 | Public License instead of this License.
348 |
--------------------------------------------------------------------------------