This commit is contained in:
isohuntto 2014-12-19 17:55:57 +03:00
parent 854c5b6e7e
commit 0c03d2498b
3400 changed files with 853482 additions and 0 deletions

15
.gitignore vendored Normal file
View file

@ -0,0 +1,15 @@
nbproject
.idea
assets/*
!assets/.gitignore
protected/runtime/*
!protected/runtime/.gitignore
protected/data/*.db
themes/classic/views/
src/runtime/
src/web/assets/
src/protected/runtime/
src/www/assets/
*.log *.logs log/ logs/

12
.htaccess Normal file
View file

@ -0,0 +1,12 @@
# Do not remove this line or mod_rewrite rules and search engine friendly URLs will stop working
RewriteEngine on
RewriteBase /
RedirectMatch 403 /\..*$
RewriteRule ^(.*)$ /src/www/$1
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule ^/src/www/(.*)$ /src/www/index.php?r=main/$1 [L]

52
README.md Normal file
View file

@ -0,0 +1,52 @@
openbay
=======
We, the team that brought you https://isohunt.to and http://oldpiratebay.org are brining you the next step in torrent evolution. The Pirate Bay source code.
Torrent sites like Isohunt and The Pirate Bay gave us lessons that would be a crime to ignore. Individual torrent sites are easy targets.
Pirate Bay open source code will give absolutely anyone with minimal knowledge of how internet and websites work and some server basic equipment, opportunity to create Pirate Bay copy on his own domain.
Installation
=======
**Step 1. Download source.**
Download the latest engine version at openbay.isohunt.to or at GitHub project web page.
**Step 2. Upload source to chosen hosting.**
Upload the source code to desirable web hosting following the web hosting guide (in common case there is a CPanel tool) or just use FTP
**Step 3. Unzip source to hosting folder (optional)**
This step is quite optional. It depends on your web hosting. Some hostings can unzip sources automatically some of them allows you to make it manually.
**Step 4. Set hosting environment (optional)**
*Apache*
This option **is available by default** in original source pack. You can see it at `conf/example.htaccess`
*Nginx*
This config is available in original source pack at `/conf/example.nginx.conf`
*Sphinx* (**advanced mode**)
[Instruction here](https://github.com/isohuntto/openbay/wiki/sphinx)
*MySQL* (**advanced mode**)
Before the wizard will run you need to create a data base, the schema of the data base will be created by the wizard. Dump here `/src/protected/data/schema.mysql.sql`
**Step 5. Wizard**
Congrats! Now you can open your domain name with any browser and follow the guide provided there. As default you will need to put page title which will appears on all your webpages.
[Detailed instruction here](https://github.com/isohuntto/openbay/wiki/shared-hosting-guide)
How to contribute?
=======
Report issues , submit pull requests to fix problems, or to create summarized and documented feature requests (preferably with pull requests that implement the feature).
**Feel free to contribute to the project in any way you like!**

45
conf/example-nginx.conf Normal file
View file

@ -0,0 +1,45 @@
server {
listen 80;
server_name yourpiratebay.site;
root /home/oldpiratebay/src/www;
index index.php;
set $yii_bootstrap "index.php";
charset utf-8;
gzip on;
gzip_comp_level 3;
gzip_types text/plain text/css text/javascript application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss;
location / {
index index.html $yii_bootstrap;
try_files $uri $uri/ /$yii_bootstrap?$args;
}
location ~ \.(js|css|png|jpg|gif|swf|ico|svg)$ {
fastcgi_hide_header Set-Cookie;
open_file_cache max=10000 inactive=14d;
open_file_cache_errors on;
open_file_cache_min_uses 3;
open_file_cache_valid 1m;
output_buffers 1 2m;
expires 14d;
}
location ~* \.php$ {
fastcgi_split_path_info ^(.+\.php)(.*)$;
set $fsn /$yii_bootstrap;
if (-f $document_root$fastcgi_script_name){
set $fsn $fastcgi_script_name;
}
fastcgi_pass unix:/tmp/php-fpm.sock;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fsn;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fsn;
fastcgi_param HTTPS $https_value;
}
}

View file

@ -0,0 +1,20 @@
[global]
pid = run/php-fpm.pid
events.mechanism = epoll
emergency_restart_interval = 1h
error_log = log/php-fpm.log
[main]
listen = /tmp/php-fpm.sock
user = nobody
group = nobody
pm = dynamic
pm.max_children = 100
pm.start_servers = 20
pm.min_spare_servers = 10
pm.max_spare_servers = 25
pm.max_requests = 200
pm.status_path = /status

82
conf/example-sphinx.conf Normal file
View file

@ -0,0 +1,82 @@
### Openpiratebay
source opb_dbconnect {
type = mysql
sql_host = YOUR_MYSQL_HOST
sql_user = YOUR_MYSQL_USERNAME
sql_pass = YOUR_MYSQL_PASSWORD
sql_db = YOUR_MYSQL_DATABASE
sql_port = 3306
sql_query_pre = SET NAMES utf8
}
index opb_common {
docinfo = extern
charset_type = utf-8
charset_table = 0..9, A..Z->a..z, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F
enable_star = 1
expand_keywords = 1
index_exact_words = 1
morphology = stem_enru
min_stemming_len = 4
dict = keywords
ngram_len = 1
ngram_chars = U+4E00..U+9FBB, U+3400..U+4DB5, U+20000..U+2A6D6, U+FA0E, U+FA0F, U+FA11, U+FA13, U+FA14, U+FA1F, U+FA21, U+FA23, U+FA24, U+FA27, U+FA28, U+FA29, U+3105..U+312C, U+31A0..U+31B7, U+3041, U+3043, U+3045, U+3047, U+3049, U+304B, U+304D, U+304F, U+3051, U+3053, U+3055, U+3057, U+3059, U+305B, U+305D, U+305F, U+3061, U+3063, U+3066, U+3068, U+306A..U+306F, U+3072, U+3075, U+3078, U+307B, U+307E..U+3083, U+3085, U+3087, U+3089..U+308E, U+3090..U+3093, U+30A1, U+30A3, U+30A5, U+30A7, U+30A9, U+30AD, U+30AF, U+30B3, U+30B5, U+30BB, U+30BD, U+30BF, U+30C1, U+30C3, U+30C4, U+30C6, U+30CA, U+30CB, U+30CD, U+30CE, U+30DE, U+30DF, U+30E1, U+30E2, U+30E3, U+30E5, U+30E7, U+30EE, U+30F0..U+30F3, U+30F5, U+30F6, U+31F0, U+31F1, U+31F2, U+31F3, U+31F4, U+31F5, U+31F6, U+31F7, U+31F8, U+31F9, U+31FA, U+31FB, U+31FC, U+31FD, U+31FE, U+31FF, U+AC00..U+D7A3, U+1100..U+1159, U+1161..U+11A2, U+11A8..U+11F9, U+A000..U+A48C, U+A492..U+A4C6
preopen = 1
}
source opbtorrents : opb_dbconnect {
sql_query_range = SELECT MIN(id), MAX(id) FROM torrents
sql_range_step = 100000
sql_query = SELECT tr.id AS id, tr.hash, tr.name, tr.tags, tr.category_id, UNIX_TIMESTAMP(tr.created_at) AS created_at, tr.size, tr.downloads_count, tr.seeders, tr.leechers, tr.torrent_status, \
tr.visible_status, \
tr.files_count AS files_count \
FROM `torrents` AS tr \
WHERE tr.id BETWEEN $start AND $end \
GROUP BY tr.id
sql_field_string = name
sql_field_string = tags
sql_attr_uint = category_id
sql_attr_timestamp = created_at
sql_attr_bigint = size
sql_attr_uint = downloads_count
sql_attr_uint = seeders
sql_attr_uint = leechers
sql_attr_uint = torrent_status
sql_attr_uint = visible_status
sql_attr_uint = files_count
sql_attr_string = hash
}
index opbtorrents : opb_common {
source = opbtorrents
path = /var/lib/sphinx/opbtorrents2
min_infix_len = 3
dict = keywords
}
indexer {
mem_limit = 512M
}
searchd {
listen = 3312
listen = 3306:mysql41
log = /var/log/sphinx/searchd.log
read_timeout = 5
max_children = 0
pid_file = /var/run/sphinx/searchd.pid
max_matches = 100000
seamless_rotate = 0
preopen_indexes = 1
unlink_old = 1
workers = threads
binlog_path = /var/lib/sphinx
}

22
conf/example.htaccess Normal file
View file

@ -0,0 +1,22 @@
# Part 1. ".htaccess" for CPanel under src folder
RewriteEngine on
RewriteBase /
RedirectMatch 403 /\..*$
RewriteRule ^(.*)$ /src/www/$1
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-d
RewriteRule ^/src/www/(.*)$ /src/www/index.php?r=main/$1 [L]
# Part 2. ".htaccess" for application under src/www folder
RewriteEngine on
RedirectMatch 403 /\..*$
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php

1
src/protected/.htaccess Normal file
View file

@ -0,0 +1 @@
deny from all

View file

@ -0,0 +1,84 @@
<?php
class AHttpRequest extends CHttpRequest
{
/**
* IP address of the current user
*
* @var boolean
*/
private $ip_address = null;
public $countryCode = '';
public $isMac = false;
public function init()
{
parent::init();
}
/**
* Returns the user IP address.
*
* @see http://stackoverflow.com/a/916157
* @return string user IP address
*/
public function getUserHostAddress()
{
if (! is_null($this->ip_address)) {
return $this->ip_address;
}
foreach (array(
'HTTP_X_REAL_IP',
'HTTP_CLIENT_IP',
'HTTP_X_FORWARDED_FOR',
'HTTP_X_FORWARDED',
'HTTP_X_CLUSTER_CLIENT_IP',
'HTTP_FORWARDED_FOR',
'HTTP_FORWARDED',
'REMOTE_ADDR'
) as $key) {
if (array_key_exists($key, $_SERVER) === true) {
foreach (explode(',', $_SERVER[$key]) as $ip) {
$ip = trim($ip);
// Allow only IPv4 address, Deny reserved addresses, Deny private addresses
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
return ($this->ip_address = $ip);
}
}
}
}
// NOTE: or use something like this 127.0.0.2
return ($this->ip_address = '0.0.0.0');
}
public function getCountryCode()
{
if (empty($this->countryCode) && ! YII_DEBUG) {
if (empty(Yii::app()->request->cookies['country_code'])) {
$this->countryCode = geoip_country_code_by_name($this->getUserHostAddress());
Yii::app()->request->cookies['country_code'] = new CHttpCookie('country_code', $this->countryCode, array(
'expire' => time() + 86400
));
} else {
$this->countryCode = Yii::app()->request->cookies['country_code'];
}
}
return $this->countryCode;
}
/**
* OS detection needs for Bitlord download links
*/
public function isMac()
{
if (stripos($this->getUserAgent(), 'mac')) {
$this->isMac = true;
}
return $this->isMac;
}
}

View file

@ -0,0 +1,25 @@
<?php
/**
* Controller is the customized base controller class.
* All controller classes for this application should extend from this base class.
*/
class Controller extends CController
{
/**
* @var string the default layout for the controller view. Defaults to 'column1',
* meaning using a single column layout. See 'protected/views/layouts/column1.php'.
*/
public $layout='/layouts/main';
/**
* @var array context menu items. This property will be assigned to {@link CMenu::items}.
*/
public $menu=array();
/**
* @var array the breadcrumbs of the current page. The value of this property will
* be assigned to {@link CBreadcrumbs::links}. Please refer to {@link CBreadcrumbs::links}
* for more details on how to specify this property.
*/
public $breadcrumbs=array();
public $mainPage = false;
}

View file

@ -0,0 +1,40 @@
<?php
class Formatter extends CFormatter
{
public function formatReverseSize($size = 0, $type = 'b')
{
$type = mb_strtolower($type);
if ($type == 'kb') {
return $size * 1024;
} else if ($type == 'mb') {
return $size * 1024 * 1024;
} else if ($type == 'gb') {
return $size * 1024 * 1024 * 1024;
} else {
return $size;
}
}
public function formatAge($value)
{
$now = new DateTime();
$created = new DateTime($value);
$interval = $now->diff($created);
if ($interval->y) {
$format = '%y ' . Yii::t('site', 'year|years', $interval->y);
} else if ($interval->m) {
$format = '%m ' . Yii::t('site', 'month|months', $interval->m);
} else if ($interval->days) {
$format = '%a ' . Yii::t('site', 'day|days', $interval->days);
} else if ($interval->h) {
$format = '%h ' . Yii::t('site', 'hour|hours', $interval->h);
} else {
$format = '%i ' . Yii::t('site', 'min', $interval->i);
}
return $interval->format($format);
}
}

View file

@ -0,0 +1,22 @@
<?php
class Pagination extends CPagination
{
const DEFAULT_PAGE_SIZE = 35;
public $pageVar = 'skip';
public function getCurrentPage($recalculate = true) {
$page = parent::getCurrentPage($recalculate);
$page = ($page) ? (($page + 1) / $this->getPageSize()) : $page;
return (int) $page;
}
public function getPageCount() {
$count = (int) (($this->getItemCount() + $this->getPageSize() - 1) / $this->getPageSize());
$skipCount = $count * $this->getPageSize();
return (int) $skipCount;
}
}

View file

@ -0,0 +1,13 @@
{
"name": "isohunt/thepiratebay",
"description": "Bit Torrent search engine",
"version": "1.0.0",
"type": "project",
"minimum-stability": "stable",
"license": "GPL-3.0",
"homepage": "http://oldpiratebay.org/",
"require": {
"php": ">=5.5.0",
"yiisoft/yii": "1.1.*"
}
}

104
src/protected/composer.lock generated Normal file
View file

@ -0,0 +1,104 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"hash": "03791adf6fa01a218a765e8e7904b0a8",
"packages": [
{
"name": "yiisoft/yii",
"version": "1.1.15",
"source": {
"type": "git",
"url": "https://github.com/yiisoft/yii.git",
"reference": "022a51d34ad2c95db2b77b2075e98f5dd78b08e0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/yiisoft/yii/zipball/022a51d34ad2c95db2b77b2075e98f5dd78b08e0",
"reference": "022a51d34ad2c95db2b77b2075e98f5dd78b08e0",
"shasum": ""
},
"require": {
"php": ">=5.1.0"
},
"bin": [
"framework/yiic"
],
"type": "library",
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Qiang Xue",
"email": "qiang.xue@gmail.com",
"homepage": "http://www.yiiframework.com/",
"role": "Founder and project lead"
},
{
"name": "Alexander Makarov",
"email": "sam@rmcreative.ru",
"homepage": "http://rmcreative.ru/",
"role": "Core framework development"
},
{
"name": "Maurizio Domba",
"homepage": "http://mdomba.info/",
"role": "Core framework development"
},
{
"name": "Carsten Brandt",
"email": "mail@cebe.cc",
"homepage": "http://cebe.cc/",
"role": "Core framework development"
},
{
"name": "Wei Zhuo",
"email": "weizhuo@gmail.com",
"role": "Project site maintenance and development"
},
{
"name": "Sebastián Thierer",
"email": "sebas@artfos.com",
"role": "Component development"
},
{
"name": "Jeffrey Winesett",
"email": "jefftulsa@gmail.com",
"role": "Documentation and marketing"
},
{
"name": "Timur Ruziev",
"email": "resurtm@gmail.com",
"homepage": "http://resurtm.com/",
"role": "Core framework development"
},
{
"name": "Paul Klimov",
"email": "klimov.paul@gmail.com",
"role": "Core framework development"
}
],
"description": "Yii Web Programming Framework",
"homepage": "http://www.yiiframework.com/",
"keywords": [
"framework",
"yii"
],
"time": "2014-06-30 00:14:27"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=5.5.0"
},
"platform-dev": []
}

View file

@ -0,0 +1,8 @@
<?php
// This is the configuration for yiic console application.
// Any writable CConsoleApplication properties can be configured here.
return array(
'basePath'=>dirname(__FILE__).DIRECTORY_SEPARATOR.'..',
'name'=>'My Console Application',
);

View file

@ -0,0 +1,3 @@
<?php
define('YII_DEBUG', false);

View file

@ -0,0 +1,14 @@
<?php
return array(
'' => 'main/index',
'search' => 'main/search',
'browse' => array('main/browse', 'urlSuffix' => '/'),
'recent' => 'main/recent',
'torrent/<id:\d+>/<name:.*>' => 'main/torrent',
'<controller:\w+>' => '<controller>/index',
'<controller:\w+>/<id:\d+>' => '<controller>/view',
'<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
);

View file

@ -0,0 +1,277 @@
<?php
class MainController extends Controller
{
public function actionIndex() {
$this->mainPage = true;
$this->render('index');
}
public function actionError() {
$this->render('/errors/error404');
}
public function actionRecent()
{
$this->pageTitle = 'New Torrents | ' . Yii::app()->name . ' Torrent Search Engine';
$pagination = new Pagination(9975);
$pagination->setPageSize(35);
$torrents = new CActiveDataProvider(LTorrent::model(), array(
'criteria' => array(
'scopes' => array(
'allowed'
)
),
'sort' => array(
'sortVar' => 'Torrent_sort',
'defaultOrder' => array(
'id' => CSort::SORT_DESC
),
'attributes' => LTorrent::$defaultSortAttributes,
),
'pagination' => $pagination,
));
if (empty($torrents)) {
Yii::log('Empty latest torrents set', CLogger::LEVEL_ERROR);
}
$this->render('latest', array(
'torrents' => $torrents
));
}
public function actionTorrent($id)
{
$torrent = LTorrent::model()->findByPk($id);
$this->pageTitle = 'Download ' . $torrent->name . ' - ' . Yii::app()->name;
$cleanDescription = $torrent->description;
$torrent->description = $this->purifyHtml($torrent->description);
Yii::app()->clientScript->registerScript('torrent-view', CClientScript::POS_HEAD);
$this->render('view', array(
'torrent' => $torrent,
'cleanDescription' => $cleanDescription,
));
}
private function checkRequestUri($uri)
{
if ($uri !== Yii::app()->request->getRequestUri()) {
$this->redirect($uri, true, 301);
}
}
protected function purifyHtml($html)
{
// remove bad parsing
$html = preg_replace('#\\\r\\\n|\\\r|\\\n|\\\#sui', '', $html);
$p = new CHtmlPurifier();
$p->options = array(
'HTML.Allowed' => 'img[src],p,br,b,strong,i'
);
$html = $p->purify($html);
$p->options = array(
'HTML.Allowed' => ''
);
$text = $p->purify($html);
if (mb_strlen($text, 'UTF-8') === mb_strlen($html, 'UTF-8')) {
return '<pre>' . $text . '</pre>';
}
return $html;
}
public function actionBrowse($q = null, $iht = null, $status = 0)
{
if ($q || $iht) {
return $this->actionSearch($q, $iht, $status);
}
return $this->actionCategories();
}
protected function checkSearchRequest() {
$uri = Yii::app()->getRequest()->getRequestUri();
if (preg_match('#ihq=([^&]+)#', $uri, $matches)) {
$ihq = $matches[1];
$filtered = preg_replace('#(\s|%20)#ui', '+', $ihq);
$filtered = preg_replace('#%2B#ui', '+', $filtered);
$filtered = preg_replace('#\+{2,}#', '+', $filtered);
$filtered = trim($filtered, '+');
$filteredUri = str_replace($ihq, $filtered, $uri);
if ($uri !== $filteredUri) {
$this->redirect($filteredUri);
}
}
}
public function actionSearch($ihq = null, $iht = null, $status = null)
{
$queryLength = mb_strlen($ihq, 'UTF-8');
// search by hash
$is_hash = false;
if (40 == $queryLength && preg_match('#^[0-9a-f]{40}$#i', $ihq)) {
$is_hash = true;
if ($torrent = Yii::app()->torrentsService->getTorrentByHash($ihq)) {
Yii::app()->request->redirect($torrent->getUrl());
}
}
$this->checkSearchRequest();
if (!empty($iht)) {
if (preg_match('#^\d$#sui', $iht) && LCategory::getCategoryTag($iht)) {
$iht = LCategory::getCategoryTag($iht);
}
}
if (!empty($ihq)) {
$this->pageTitle = ucfirst($ihq) . ' Torrents Search Results | ' . Yii::app()->name . ' Torrent Search Engine';
} elseif (!empty($iht)) {
$this->pageTitle = mb_convert_case($iht, MB_CASE_TITLE, 'utf-8') . ' Torrents | ' . Yii::app()->name . ' Torrent Search Engine';
}
Yii::app()->getRequest()->getQuery('age');
if (Yii::app()->getRequest()->getQuery('ihs', null) === '1') {
$_GET['popular'] = '1';
}
$searchModel = new SearchForm('simple');
$searchModel->words = $ihq;
$searchModel->tags = $iht;
$searchModel->age = Yii::app()->getRequest()->getQuery('age', 0);
$searchModel->popular = empty($_GET['popular']) ? 0 : 1;
$searchModel->status = empty($status) ? 0 : 1;
$searchModel->validate();
$torrents = new CArrayDataProvider(array());
$totalCount = 0;
if (! $searchModel->getErrors()) {
$torrentModel = LTorrent::model();
$torrents = $torrentModel->getSphinxDataProvider($searchModel);
$totalCount = $torrents->getTotalItemCount();
if (empty($totalCount)) {
$words = explode(' ', $searchModel->words);
if (count($words) > 1) {
$searchModel->words = $words;
$torrents = $torrentModel->getSphinxDataProvider($searchModel);
$totalCount = $torrents->getTotalItemCount();
}
}
}
if (isset($_REQUEST['lucky'])) {
$t = $torrents->getData();
if (count($t)) {
$idx = rand(0, count($t) - 1);
Yii::app()->request->redirect($t[$idx]->getUrl());
}
}
$this->render('list', array(
'torrents' => $torrents,
'search' => $searchModel->words,
'categoryTag' => $iht,
'categoriesTags' => LCategory::$categoriesTags,
'totalFound' => $totalCount,
));
}
/**
* Returns SphinxQL search object, initialized for tag search
*
* @param SearchForm $model
* @return \ESphinxQL
*/
protected function getSphinxTagSearchObject(SearchForm $model) {
$objCommon = new ESphinxQL();
$objCommon->addField('id')->addIndex(Yii::app()->params['sphinx']['indexes']['torrents']);
$tagPatterns = array();
if ($model->tags) {
$tagPatterns[] = '"=' . str_replace(' ', '+', $model->tags) . '"';
}
if ($model->category) {
$tagPatterns[] = '"=' . str_replace(' ', '+', LCategory::getCategoryTag($model->category)) . '"';
$objCommon->where('category_id', $model->category);
}
if (count($tagPatterns)) {
$searchPattern = '@tags ' . join(' ', $tagPatterns);
}
$objCommon->option('ranker', 'MATCHANY');
// Filter torrents by status
if (! empty($model->status)) {
$objCommon->where('torrent_status', Torrent::TORRENT_STATUS_GOOD);
}
// Filter torrents by age
if (! empty($model->age)) {
$objCommon->where('created_at', time() - $model->age * 86400, '>=', true);
}
if (! empty($model->popular)) {
$objCommon->order('downloads_count', 'DESC');
}
if ($model->latest) {
$objCommon->order('created_at', 'DESC');
$objCommon->limit($model->latest);
}
// If no ordering is set - default weight+id sorting mode
if (!$objCommon->getOrders()) {
$objCommon->order('weight()', 'DESC');
$objCommon->order('id', 'DESC');
}
if (! empty($searchPattern)) {
$objCommon->search($searchPattern);
}
return $objCommon;
}
public function actionCategories()
{
$this->pageTitle = 'Browse Torrents | ' . Yii::app()->name . ' Torrent Search Engine';
$torrentsByTags = array();
$torrentsIds = LTorrent::getLastTorrentIdsByCategories();
if (empty($torrentsIds)) {
Yii::log('Empty last torrents ids', CLogger::LEVEL_WARNING);
} else {
$torrentModel = LTorrent::model();
$criteria = new CDbCriteria();
$criteria->addInCondition('t.id', $torrentsIds);
foreach ($torrentModel->findAll($criteria) as $torrent) {
$torrentsByTags[$torrent->getCategoryTag()][] = $torrent;
}
}
$this->render('categories', array(
'tags' => LCategory::$categoriesTags,
'torrents' => $torrentsByTags
));
}
}

View file

@ -0,0 +1,40 @@
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET NAMES utf8 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
DROP TABLE IF EXISTS `torrents`;
CREATE TABLE IF NOT EXISTS `torrents` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`description` text,
`category_id` tinyint(4) DEFAULT NULL,
`size` bigint(20) unsigned DEFAULT NULL,
`hash` varchar(40) NOT NULL,
`files_count` int(11) DEFAULT '0',
`created_at` datetime DEFAULT NULL,
`torrent_status` smallint(2) DEFAULT '0',
`visible_status` smallint(2) DEFAULT '0',
`downloads_count` mediumint(8) unsigned NOT NULL DEFAULT '0' COMMENT 'umax = 16777215',
`scrape_date` datetime DEFAULT NULL,
`seeders` mediumint(8) unsigned NOT NULL DEFAULT '0',
`leechers` mediumint(8) unsigned NOT NULL DEFAULT '0',
`tags` varchar(500) DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `hash` (`hash`),
KEY `created_at` (`created_at`),
KEY `size` (`size`),
KEY `seeders` (`seeders`),
KEY `category_id_torrent_status_visible_status` (`category_id`,`torrent_status`,`visible_status`)
);
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
/*!40014 SET FOREIGN_KEY_CHECKS=IF(@OLD_FOREIGN_KEY_CHECKS IS NULL, 1, @OLD_FOREIGN_KEY_CHECKS) */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
INSERT INTO `torrents` (`name`, `description`, `category_id`, `size`, `hash`, `files_count`, `created_at`, `torrent_status`, `visible_status`, `downloads_count`, `scrape_date`, `seeders`, `leechers`, `tags`, `updated_at`) VALUES ('Gothika (2003) [XviD - Italian English Ac3 5.1 - Sub spa] MIRCrew', 'Released: 21 Nov 2003\nRated: R\nRuntime: 98 min\nGenre: Horror, Thriller\nDirector: Mathieu Kassovitz\nWriter: Sebastian Gutierrez\nActors: Halle Berry, Robert Downey Jr., Charles S. Dutton, John Carroll Lynch\nIMDB: 5.8 (79,739 Votes)\n\nDr. Miranda Grey is a psychiatrist who works in a penitentiary, in the mental institution sector. She is married with Dr. Douglas Grey, the chief of department where Dr. Pete Graham also works. Chloe Sava, a patient of Dr. Miranda formerly abused by her stepfather, claims that she is frequently raped by the devil in her cell. After leaving the asylum in a stormy night, Dr. Miranda has a car accident, and when she wakes up, she is an inmate of the institution, being accused of an horrible crime and having no memory of the incident.', 5, 1774407945, '191c5493b54c4f3c8949da29cd41f947a3f7ff42', 2, '2014-12-16 22:51:09', 0, 0, 0, NULL, 0, 0, NULL, '2014-12-16 22:51:09');
INSERT INTO `torrents` (`name`, `description`, `category_id`, `size`, `hash`, `files_count`, `created_at`, `torrent_status`, `visible_status`, `downloads_count`, `scrape_date`, `seeders`, `leechers`, `tags`, `updated_at`) VALUES ('Redirected 2014 720p HDRiP XVID AC3-MAJESTIC', 'Released: 10 Jan 2014\nRated: \nRuntime: 99 min\nGenre: Action, Drama, Thriller\nDirector: Emilis Velyvis\nWriter: Jonas Banys, Lewis Britnell (dialogue editor), Emilis Velyvis\nActors: Vinnie Jones, Scot Williams, Gil Darnell, Oliver Jackson\nIMDB: 8.8 (12,076 Votes)\n\nFour friends - John, Ben, Tim and Michael - turned first-time robbers, get stranded in Eastern Europe through a series of misadventures and have to find their way back home. To do so, they\'ll have to overcome hit men, whores, corrupt cops, smugglers and more, all while rediscovering each other as friends', 5, 2621640304, '03f2ec89a37038a4bac9daa9374c954f47633be1', 3, '2014-12-16 22:51:08', 0, 0, 0, NULL, 0, 0, NULL, '2014-12-16 22:51:08');
INSERT INTO `torrents` (`name`, `description`, `category_id`, `size`, `hash`, `files_count`, `created_at`, `torrent_status`, `visible_status`, `downloads_count`, `scrape_date`, `seeders`, `leechers`, `tags`, `updated_at`) VALUES ('High School of The Dead', 'Released: 23 Aug 2012\nRated: Not Rated\nRuntime: \nGenre: Comedy\nDirector: Hope Chapman\nWriter: Hope Chapman\nActors: Hope Chapman, Kaylyn Dicksion, Lewis Lovhaug, Joe Vargas\nIMDB: 8.1 (128 Votes)\n\n', 1, 3758227976, '51efab8e94204987afb2709b3151545dab533dcc', 12, '2014-12-16 22:51:06', 0, 0, 0, NULL, 0, 0, NULL, '2014-12-16 22:51:08');
INSERT INTO `torrents` (`name`, `description`, `category_id`, `size`, `hash`, `files_count`, `created_at`, `torrent_status`, `visible_status`, `downloads_count`, `scrape_date`, `seeders`, `leechers`, `tags`, `updated_at`) VALUES ('Reach Me 2014 720p BluRay DD5 1 x264-VietHD', 'Released: 21 Nov 2014\nRated: PG-13\nRuntime: 95 min\nGenre: Drama\nDirector: John Herzfeld\nWriter: John Herzfeld\nActors: Lauren Cohan, Kyra Sedgwick, Thomas Jane, Kevin Connolly\nIMDB: 5.8 (126 Votes)\n\nA motivational book written by a mysterious man quickly gains popularity, inspiring a group of people that includes a journalist, his editor, a former inmate, a hip-hop mogul, an actor and an undercover cop to re-evaluate their choices and decisions by confronting their fears in hopes of creating more positive lives.', 5, 7583940211, '1c633b1c24bf2276f7bf5c082f36d858fde6831f', 3, '2014-12-16 22:51:05', 0, 0, 0, NULL, 0, 0, NULL, '2014-12-16 22:51:05');
INSERT INTO `torrents` (`name`, `description`, `category_id`, `size`, `hash`, `files_count`, `created_at`, `torrent_status`, `visible_status`, `downloads_count`, `scrape_date`, `seeders`, `leechers`, `tags`, `updated_at`) VALUES ('Movavi Photo Editor v1.5.0 with Key', NULL, 2, 34659365, 'df4fe16376374f446b0a3125d31f95c39bc09e54', 2, '2014-12-16 22:46:07', 0, 0, 0, NULL, 0, 0, 'software,v1.5', '2014-12-16 22:51:09');

View file

@ -0,0 +1,21 @@
<?php
class ESphinxDataProvider extends CActiveDataProvider {
/**
* Fetches the data from the persistent data storage.
* @return array list of data items
*/
protected function fetchData() {
return $this->model->findAll($this->getCriteria());
}
/**
* Calculates the total number of data items.
* @return integer the total number of data items.
*/
protected function calculateTotalItemCount() {
return $this->getPagination()->getItemCount();
}
}

View file

@ -0,0 +1,596 @@
<?php
/*
Read Documentation, Luke.
$sphinxql = new SphinxQL();
$query = $sphinxql->newQuery();
$query->addIndex('my_index')
->addField('field_name', 'alias')
->addField('another_field')
->addFields(array(array('field' => 'title', 'alias' => 'title_alias'), array('field' => 'user_id')))
->search('some words to search for')
// string (is given directly to sphinx, so can contain @field directives)
->where('time', time()-3600, '>', false)
// field, value, operator='=', quote=true
->whereIn('tags_i_need', array(1, 2, 3), 'all')
->whereIn('tags_i_do_not_want', array(4, 5, 6), 'none')
->whereIn('tags_i_would_like_one_of', array(7, 8, 9), 'any')
// field, array values, type='any'
->order('weight()', 'desc')
// field, sort='desc'
->offset(10)->limit(50)
// defaults are 0 and 20, same as the sphinx defaults
->option('max_query_time', '100')
// option name, option value
->groupBy('field')
->in_group_order_by('another_field', 'desc');
// sphinx-specific, check their docs
$result = $query->execute();
$stats = $sphinx->stats();
// ------
$sphinxql = new SphinxQL();
$result = $sphinxql->query('INSERT INTO realtime_index (id, title, content) VALUES ( 1, "title news", "content news" )');
*/
class ESphinxQL {
/**
* @var array The indexes that are to be searched
*/
protected $_indexes = array();
/**
* @var array The fields that are to be returned in the result set
*/
protected $_fields = array();
/**
* @var string A string to be searched for in the indexes
*/
protected $_search = null;
/**
* @var array A set of WHERE conditions
*/
protected $_wheres = array();
/**
* @var array The GROUP BY field
*/
protected $_group = null;
/**
* @var array The IN GROUP ORDER BY options
*/
protected $_group_order = null;
/**
* @var array A set of ORDER clauses
*/
protected $_orders = array();
/**
* @var integer The offset to start returning results from
*/
protected $_offset = 0;
/**
* @var integer The maximum number of results to return
*/
protected $_limit = 20;
/**
* @var array A set of OPTION clauses
*/
protected $_options = array();
/**
* Builds the query string from the information you've given.
*
* @return string The resulting query
*/
public function build() {
$fields = array();
$wheres = array();
$orders = array();
$options = array();
$query = '';
foreach ($this->_fields as $field) {
if (!isset($field['field']) || !is_string($field['field'])) {
continue;
}
if (isset($field['alias']) && is_string($field['alias'])) {
$fields[] = sprintf("%s AS %s", $field['field'], $field['alias']);
} else {
$fields[] = sprintf("%s", $field['field']);
}
}
unset($field);
if (is_string($this->_search)) {
$wheres[] = sprintf("MATCH(%s)", $this->_search);
}
foreach ($this->_wheres as $where) {
$wheres[] = sprintf("%s %s %s", $where['field'], $where['operator'], $where['value']);
}
unset($where);
foreach ($this->_orders as $order) {
$orders[] = sprintf("%s %s", $order['field'], $order['sort']);
}
unset($order);
foreach ($this->_options as $option) {
$options[] = sprintf("%s=%s", $option['name'], $option['value']);
}
unset($option);
$query .= sprintf('SELECT %s ', count($fields) ? implode(', ', $fields) : '*' );
$query .= sprintf('FROM %s ', implode(',', $this->_indexes));
if (count($wheres) > 0) {
$query .= sprintf('WHERE %s ', implode(' AND ', $wheres));
}
if (is_string($this->_group)) {
$query .= sprintf('GROUP BY %s ', $this->_group);
}
if (is_array($this->_group_order)) {
$query .= sprintf('WITHIN GROUP ORDER BY %s %s ', $this->_group_order['field'], $this->_group_order['sort']);
}
if (count($orders) > 0) {
$query .= sprintf('ORDER BY %s ', implode(', ', $orders));
}
$query .= sprintf('LIMIT %d, %d ', $this->_offset, $this->_limit);
if (count($options) > 0) {
$query .= sprintf('OPTION %s ', implode(', ', $options));
}
while (substr($query, -1, 1) == ' ') {
$query = substr($query, 0, -1);
}
return $query;
}
/**
* Adds an entry to the list of indexes to be searched.
*
* @param string The index to add
*
* @return SphinxQL_Query $this
*/
public function addIndex($index) {
if (is_string($index)) {
array_push($this->_indexes, $index);
}
return $this;
}
/**
* Removes an entry from the list of indexes to be searched.
*
* @param string The index to remove
*
* @return SphinxQL_Query $this
*/
public function removeIndex($index) {
if (is_string($index)) {
while ($pos = array_search($index, $this->_indexes)) {
unset($this->_indexes[$pos]);
}
}
return $this;
}
/**
* Adds a entry to the list of fields to return from the query.
*
* @param string Field to add
* @param string Alias for that field, optional
*
* @return SphinxQL_Query $this
*/
public function addField($field, $alias = null) {
if (!is_string($alias)) {
$alias = null;
}
if (is_string($field)) {
$this->_fields[] = array('field' => $field, 'alias' => $alias);
}
return $this;
}
/**
* Adds multiple entries at once to the list of fields to return.
* Takes an array structured as so:
* array(array('field' => 'user_id', 'alias' => 'user')), ...)
* The alias is optional.
*
* @param array Array of fields to add
*
* @return SphinxQL_Query $this
*/
public function addFields($array) {
if (is_array($array)) {
foreach ($array as $entry) {
if (is_array($entry) && isset($entry['field'])) {
if (!isset($entry['alias']) || is_string($entry['alias'])) {
$entry['alias'] = null;
$this->addField($entry['field'], $entry['alias']);
}
}
}
}
return $this;
}
/**
* Removes a field from the list of fields to search.
*
* @param string Alias of the field to remove
*
* @return SphinxQL_Query $this
*/
public function removeField($alias) {
if (is_string($alias) && array_key_exists($this->_fields, $alias)) {
unset($this->_fields[$alias]);
}
return $this;
}
/**
* Removes multiple fields at once from the list of fields to search.
*
* @param array|mixed List of aliases of fields to remove
*
* @return SphinxQL_Query $this
*/
public function removeFields($array) {
if (is_array($array)) {
foreach ($array as $alias) {
$this->removeField($alias);
}
}
return $this;
}
public function setCountFieldOnly()
{
$this->_fields = array();
$this->addField('count(*)');
}
public function hasGroupBy()
{
return !($this->_group === null && $this->_group_order === null);
}
/**
* Sets the text to be matched against the index(es)
*
* @param string Text to be searched
*
* @return SphinxQL_Query $this
*/
public function search($search) {
if (is_string($search)) {
$this->_search = Yii::app()->sphinx->quoteValue($search);
}
return $this;
}
/**
* Escapes the query for the MATCH() function
*
* @param string $string The string to escape for the MATCH
*
* @return string The escaped string
*/
public function escapeMatch($string) {
$from = array('\\', '(', ')', '|', '-', '!', '@', '~', '"', '&', '/', '^', '$', '=');
$to = array('\\\\', '\(', '\)', '\|', '\-', '\!', '\@', '\~', '\"', '\&', '\/', '\^', '\$', '\=');
return str_replace($from, $to, $string);
}
/**
* Escapes the query for the MATCH() function
* Allows some of the control characters to pass through for use with a search field: -, |, "
* It also does some tricks to wrap/unwrap within " the string and prevents errors
*
* @param string $string The string to escape for the MATCH
*
* @return string The escaped string
*/
public function halfEscapeMatch($string) {
$from_to = array(
'\\' => '\\\\',
'(' => '\(',
')' => '\)',
//'!' => '\!',
'@' => '\@',
'~' => '\~',
'&' => '\&',
'/' => '\/',
//'^' => '\^',
//'$' => '\$',
//'=' => '\=',
);
$string = str_replace(array_keys($from_to), array_values($from_to), $string);
// this manages to lower the error rate by a lot
if (substr_count($string, '"') % 2 !== 0) {
$string .= '"';
}
$from_to_preg = array(
"'\"([^\s]+)-([^\s]*)\"'" => "\\1\-\\2",
"'([^\s]+)-([^\s]*)'" => "\"\\1\-\\2\""
);
$string = preg_replace(array_keys($from_to_preg), array_values($from_to_preg), $string);
return $string;
}
/**
* Removes the search text from the query.
*
* @return SphinxQL_Query $this
*/
public function removeSearch() {
$this->_search = null;
return $this;
}
/**
* Sets the offset for the query
*
* @param integer Offset
*
* @return SphinxQL_Query $this
*/
public function offset($offset) {
if (is_integer($offset)) {
$this->_offset = $offset;
}
return $this;
}
/**
* Sets the limit for the query
*
* @param integer Limit
*
* @return SphinxQL_Query $this
*/
public function limit($limit) {
if (is_integer($limit)) {
$this->_limit = $limit;
}
return $this;
}
/**
* Adds a WHERE condition to the query.
*
* @param string The field/expression for the condition
* @param string The field/expression/value to compare the field to
* @param string The operator (=, <, >, etc)
* @param bool Whether or not to quote the value, defaults to true
*
* @return SphinxQL_Query $this
*/
public function where($field, $value, $operator = null, $quote = false) {
if (!in_array($operator, array('=', '!=', '>', '<', '>=', '<=', 'AND', 'NOT IN', 'IN', 'BETWEEN'))) {
$operator = '=';
}
if (!is_string($field)) {
return false;
}
if (!is_scalar($value)) {
return false;
}
if ($quote) {
$value = Yii::app()->sphinx->quoteValue($value);
}
$this->_wheres[] = array('field' => $field, 'operator' => $operator, 'value' => $value);
return $this;
}
/**
* Adds a WHERE <field> <not> IN (<value x>, <value y>, <value ...>) condition to the query, mainly used for MVAs.
*
* @param string The field/expression for the condition
* @param array The values to compare the field to
* @param string Whether this is a match-all, match-any (default) or match-none condition
*
* @return SphinxQL_Query $this
*/
public function whereIn($field, $values, $how = 'any') {
if (!is_array($values)) {
$values = array($values);
}
if ($how == 'all') {
foreach ($values as $value) {
$this->where($field, $value, '=');
}
} elseif ($how == 'none') {
foreach ($values as $value) {
$this->where($field, $value, '!=');
}
} else {
$this->where($field, '(' . implode(', ', $values) . ')', 'IN', false);
}
return $this;
}
/**
* Sets the GROUP BY condition for the query.
*
* @param string The field/expression for the condition
*
* @return SphinxQL_Query $this
*/
public function groupBy($field) {
if (is_string($field)) {
$this->_group = $field;
}
return $this;
}
/**
* Removes the GROUP BY condition from the query.
*
* @param string The field/expression for the condition
* @param string The alias for the result set (optional)
*
* @return SphinxQL_Query $this
*/
public function removeGroupBy($field) {
$this->_group = null;
return $this;
}
public function getOrders() {
return $this->_orders;
}
public function setOrders(array $orders) {
$this->_orders = $orders;
return $this;
}
/**
* Adds an ORDER condition to the query.
*
* @param string The field/expression for the condition
* @param string The sort type (can be 'asc' or 'desc', capitals are also OK)
*
* @return SphinxQL_Query $this
*/
public function order($field, $sort) {
if (is_string($field) && is_string($sort)) {
$this->_orders[] = array('field' => $field, 'sort' => $sort);
}
return $this;
}
/**
* Sets the WITHIN GROUP ORDER BY condition for the query. This is a
* Sphinx-specific extension to SQL.
*
* @param string The field/expression for the condition
* @param string The sort type (can be 'asc' or 'desc', capitals are also OK)
*
* @return SphinxQL_Query $this
*/
public function groupOrder($field, $sort) {
if (is_string($field) && is_string($sort)) {
$this->_group_order = array('field' => $field, 'sort' => $sort);
}
return $this;
}
/**
* Removes the WITHIN GROUP ORDER BY condition for the query. This is a
* Sphinx-specific extension to SQL.
*
* @return SphinxQL_Query $this
*/
public function removeGroupOrder() {
$this->_group_order = null;
return $this;
}
/**
* Adds an OPTION to the query. This is a Sphinx-specific extension to SQL.
*
* @param string The option name
* @param string The option value
*
* @return SphinxQL_Query $this
*/
public function option($name, $value) {
if (is_string($name) && is_string($value)) {
$this->_options[] = array('name' => $name, 'value' => $value);
}
return $this;
}
/**
* Removes an OPTION from the query.
*
* @param string The option name
* @param string The option value, optional
*
* @return SphinxQL_Query $this
*/
public function removeOption($name, $value = null) {
$changed = false;
if (is_string($name) && ( ( $value == null ) || is_string($value) )) {
foreach ($this->_options as $key => $option) {
if (( $option['name'] == $name ) && ( ( $value == null ) || ( $value == $option['value'] ) )) {
unset($this->_options[$key]);
$changed = true;
}
}
if ($changed) {
array_keys($this->_options);
}
}
return $this;
}
}

View file

@ -0,0 +1,34 @@
<?php
class InstallerModule extends CWebModule
{
private $_assetsUrl;
public function init()
{
parent::init();
Yii::setPathOfAlias('installer', dirname(__FILE__));
Yii::app()->setComponents(array(
'errorHandler'=>array(
'class'=>'CErrorHandler',
'errorAction'=>parent::getId().'/default/error',
),
'widgetFactory' => array(
'class'=>'CWidgetFactory',
'widgets' => array()
)
), false);
}
public function getAssetsUrl()
{
if($this->_assetsUrl===null)
$this->_assetsUrl=Yii::app()->getAssetManager()->publish(Yii::getPathOfAlias('installer.assets'));
return $this->_assetsUrl;
}
public function setAssetsUrl($value)
{
$this->_assetsUrl=$value;
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,229 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
<svg xmlns="http://www.w3.org/2000/svg">
<metadata></metadata>
<defs>
<font id="glyphicons_halflingsregular" horiz-adv-x="1200" >
<font-face units-per-em="1200" ascent="960" descent="-240" />
<missing-glyph horiz-adv-x="500" />
<glyph />
<glyph />
<glyph unicode="&#xd;" />
<glyph unicode=" " />
<glyph unicode="*" d="M100 500v200h259l-183 183l141 141l183 -183v259h200v-259l183 183l141 -141l-183 -183h259v-200h-259l183 -183l-141 -141l-183 183v-259h-200v259l-183 -183l-141 141l183 183h-259z" />
<glyph unicode="+" d="M0 400v300h400v400h300v-400h400v-300h-400v-400h-300v400h-400z" />
<glyph unicode="&#xa0;" />
<glyph unicode="&#x2000;" horiz-adv-x="652" />
<glyph unicode="&#x2001;" horiz-adv-x="1304" />
<glyph unicode="&#x2002;" horiz-adv-x="652" />
<glyph unicode="&#x2003;" horiz-adv-x="1304" />
<glyph unicode="&#x2004;" horiz-adv-x="434" />
<glyph unicode="&#x2005;" horiz-adv-x="326" />
<glyph unicode="&#x2006;" horiz-adv-x="217" />
<glyph unicode="&#x2007;" horiz-adv-x="217" />
<glyph unicode="&#x2008;" horiz-adv-x="163" />
<glyph unicode="&#x2009;" horiz-adv-x="260" />
<glyph unicode="&#x200a;" horiz-adv-x="72" />
<glyph unicode="&#x202f;" horiz-adv-x="260" />
<glyph unicode="&#x205f;" horiz-adv-x="326" />
<glyph unicode="&#x20ac;" d="M100 500l100 100h113q0 47 5 100h-218l100 100h135q37 167 112 257q117 141 297 141q242 0 354 -189q60 -103 66 -209h-181q0 55 -25.5 99t-63.5 68t-75 36.5t-67 12.5q-24 0 -52.5 -10t-62.5 -32t-65.5 -67t-50.5 -107h379l-100 -100h-300q-6 -46 -6 -100h406l-100 -100 h-300q9 -74 33 -132t52.5 -91t62 -54.5t59 -29t46.5 -7.5q29 0 66 13t75 37t63.5 67.5t25.5 96.5h174q-31 -172 -128 -278q-107 -117 -274 -117q-205 0 -324 158q-36 46 -69 131.5t-45 205.5h-217z" />
<glyph unicode="&#x2212;" d="M200 400h900v300h-900v-300z" />
<glyph unicode="&#x25fc;" horiz-adv-x="500" d="M0 0z" />
<glyph unicode="&#x2601;" d="M-14 494q0 -80 56.5 -137t135.5 -57h750q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5z" />
<glyph unicode="&#x2709;" d="M0 100l400 400l200 -200l200 200l400 -400h-1200zM0 300v600l300 -300zM0 1100l600 -603l600 603h-1200zM900 600l300 300v-600z" />
<glyph unicode="&#x270f;" d="M-13 -13l333 112l-223 223zM187 403l214 -214l614 614l-214 214zM887 1103l214 -214l99 92q13 13 13 32.5t-13 33.5l-153 153q-15 13 -33 13t-33 -13z" />
<glyph unicode="&#xe001;" d="M0 1200h1200l-500 -550v-550h300v-100h-800v100h300v550z" />
<glyph unicode="&#xe002;" d="M14 84q18 -55 86 -75.5t147 5.5q65 21 109 69t44 90v606l600 155v-521q-64 16 -138 -7q-79 -26 -122.5 -83t-25.5 -111q18 -55 86 -75.5t147 4.5q70 23 111.5 63.5t41.5 95.5v881q0 10 -7 15.5t-17 2.5l-752 -193q-10 -3 -17 -12.5t-7 -19.5v-689q-64 17 -138 -7 q-79 -25 -122.5 -82t-25.5 -112z" />
<glyph unicode="&#xe003;" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233z" />
<glyph unicode="&#xe005;" d="M100 784q0 64 28 123t73 100.5t104.5 64t119 20.5t120 -38.5t104.5 -104.5q48 69 109.5 105t121.5 38t118.5 -20.5t102.5 -64t71 -100.5t27 -123q0 -57 -33.5 -117.5t-94 -124.5t-126.5 -127.5t-150 -152.5t-146 -174q-62 85 -145.5 174t-149.5 152.5t-126.5 127.5 t-94 124.5t-33.5 117.5z" />
<glyph unicode="&#xe006;" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1z" />
<glyph unicode="&#xe007;" d="M-72 800h479l146 400h2l146 -400h472l-382 -278l145 -449l-384 275l-382 -275l146 447zM168 71l2 1zM237 700l196 -142l-73 -226l192 140l195 -141l-74 229l193 140h-235l-77 211l-78 -211h-239z" />
<glyph unicode="&#xe008;" d="M0 0v143l400 257v100q-37 0 -68.5 74.5t-31.5 125.5v200q0 124 88 212t212 88t212 -88t88 -212v-200q0 -51 -31.5 -125.5t-68.5 -74.5v-100l400 -257v-143h-1200z" />
<glyph unicode="&#xe009;" d="M0 0v1100h1200v-1100h-1200zM100 100h100v100h-100v-100zM100 300h100v100h-100v-100zM100 500h100v100h-100v-100zM100 700h100v100h-100v-100zM100 900h100v100h-100v-100zM300 100h600v400h-600v-400zM300 600h600v400h-600v-400zM1000 100h100v100h-100v-100z M1000 300h100v100h-100v-100zM1000 500h100v100h-100v-100zM1000 700h100v100h-100v-100zM1000 900h100v100h-100v-100z" />
<glyph unicode="&#xe010;" d="M0 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM0 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400 q-21 0 -35.5 14.5t-14.5 35.5zM600 50v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5zM600 650v400q0 21 14.5 35.5t35.5 14.5h400q21 0 35.5 -14.5t14.5 -35.5v-400 q0 -21 -14.5 -35.5t-35.5 -14.5h-400q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe011;" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200 q-21 0 -35.5 14.5t-14.5 35.5zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 450v200q0 21 14.5 35.5t35.5 14.5h200 q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM800 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe012;" d="M0 50v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM0 450q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v200q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5 t-14.5 -35.5v-200zM0 850v200q0 21 14.5 35.5t35.5 14.5h200q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5zM400 50v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5 t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 450v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5zM400 850v200q0 21 14.5 35.5t35.5 14.5h700q21 0 35.5 -14.5t14.5 -35.5 v-200q0 -21 -14.5 -35.5t-35.5 -14.5h-700q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe013;" d="M29 454l419 -420l818 820l-212 212l-607 -607l-206 207z" />
<glyph unicode="&#xe014;" d="M106 318l282 282l-282 282l212 212l282 -282l282 282l212 -212l-282 -282l282 -282l-212 -212l-282 282l-282 -282z" />
<glyph unicode="&#xe015;" d="M23 693q0 200 142 342t342 142t342 -142t142 -342q0 -142 -78 -261l300 -300q7 -8 7 -18t-7 -18l-109 -109q-8 -7 -18 -7t-18 7l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 693q0 -136 97 -233t234 -97t233.5 96.5t96.5 233.5t-96.5 233.5t-233.5 96.5 t-234 -97t-97 -233zM300 600v200h100v100h200v-100h100v-200h-100v-100h-200v100h-100z" />
<glyph unicode="&#xe016;" d="M23 694q0 200 142 342t342 142t342 -142t142 -342q0 -141 -78 -262l300 -299q7 -7 7 -18t-7 -18l-109 -109q-8 -8 -18 -8t-18 8l-300 300q-119 -78 -261 -78q-200 0 -342 142t-142 342zM176 694q0 -136 97 -233t234 -97t233.5 97t96.5 233t-96.5 233t-233.5 97t-234 -97 t-97 -233zM300 601h400v200h-400v-200z" />
<glyph unicode="&#xe017;" d="M23 600q0 183 105 331t272 210v-166q-103 -55 -165 -155t-62 -220q0 -177 125 -302t302 -125t302 125t125 302q0 120 -62 220t-165 155v166q167 -62 272 -210t105 -331q0 -118 -45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5 zM500 750q0 -21 14.5 -35.5t35.5 -14.5h100q21 0 35.5 14.5t14.5 35.5v400q0 21 -14.5 35.5t-35.5 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-400z" />
<glyph unicode="&#xe018;" d="M100 1h200v300h-200v-300zM400 1v500h200v-500h-200zM700 1v800h200v-800h-200zM1000 1v1200h200v-1200h-200z" />
<glyph unicode="&#xe019;" d="M26 601q0 -33 6 -74l151 -38l2 -6q14 -49 38 -93l3 -5l-80 -134q45 -59 105 -105l133 81l5 -3q45 -26 94 -39l5 -2l38 -151q40 -5 74 -5q27 0 74 5l38 151l6 2q46 13 93 39l5 3l134 -81q56 44 104 105l-80 134l3 5q24 44 39 93l1 6l152 38q5 40 5 74q0 28 -5 73l-152 38 l-1 6q-16 51 -39 93l-3 5l80 134q-44 58 -104 105l-134 -81l-5 3q-45 25 -93 39l-6 1l-38 152q-40 5 -74 5q-27 0 -74 -5l-38 -152l-5 -1q-50 -14 -94 -39l-5 -3l-133 81q-59 -47 -105 -105l80 -134l-3 -5q-25 -47 -38 -93l-2 -6l-151 -38q-6 -48 -6 -73zM385 601 q0 88 63 151t152 63t152 -63t63 -151q0 -89 -63 -152t-152 -63t-152 63t-63 152z" />
<glyph unicode="&#xe020;" d="M100 1025v50q0 10 7.5 17.5t17.5 7.5h275v100q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5v-100h275q10 0 17.5 -7.5t7.5 -17.5v-50q0 -11 -7 -18t-18 -7h-1050q-11 0 -18 7t-7 18zM200 100v800h900v-800q0 -41 -29.5 -71t-70.5 -30h-700q-41 0 -70.5 30 t-29.5 71zM300 100h100v700h-100v-700zM500 100h100v700h-100v-700zM500 1100h300v100h-300v-100zM700 100h100v700h-100v-700zM900 100h100v700h-100v-700z" />
<glyph unicode="&#xe021;" d="M1 601l656 644l644 -644h-200v-600h-300v400h-300v-400h-300v600h-200z" />
<glyph unicode="&#xe022;" d="M100 25v1150q0 11 7 18t18 7h475v-500h400v-675q0 -11 -7 -18t-18 -7h-850q-11 0 -18 7t-7 18zM700 800v300l300 -300h-300z" />
<glyph unicode="&#xe023;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 500v400h100 v-300h200v-100h-300z" />
<glyph unicode="&#xe024;" d="M-100 0l431 1200h209l-21 -300h162l-20 300h208l431 -1200h-538l-41 400h-242l-40 -400h-539zM488 500h224l-27 300h-170z" />
<glyph unicode="&#xe025;" d="M0 0v400h490l-290 300h200v500h300v-500h200l-290 -300h490v-400h-1100zM813 200h175v100h-175v-100z" />
<glyph unicode="&#xe026;" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM188 600q0 -170 121 -291t291 -121t291 121t121 291t-121 291t-291 121 t-291 -121t-121 -291zM350 600h150v300h200v-300h150l-250 -300z" />
<glyph unicode="&#xe027;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM350 600l250 300 l250 -300h-150v-300h-200v300h-150z" />
<glyph unicode="&#xe028;" d="M0 25v475l200 700h800l199 -700l1 -475q0 -11 -7 -18t-18 -7h-1150q-11 0 -18 7t-7 18zM200 500h200l50 -200h300l50 200h200l-97 500h-606z" />
<glyph unicode="&#xe029;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM500 397v401 l297 -200z" />
<glyph unicode="&#xe030;" d="M23 600q0 -118 45.5 -224.5t123 -184t184 -123t224.5 -45.5t224.5 45.5t184 123t123 184t45.5 224.5h-150q0 -177 -125 -302t-302 -125t-302 125t-125 302t125 302t302 125q136 0 246 -81l-146 -146h400v400l-145 -145q-157 122 -355 122q-118 0 -224.5 -45.5t-184 -123 t-123 -184t-45.5 -224.5z" />
<glyph unicode="&#xe031;" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5q198 0 355 -122l145 145v-400h-400l147 147q-112 80 -247 80q-177 0 -302 -125t-125 -302h-150zM100 0v400h400l-147 -147q112 -80 247 -80q177 0 302 125t125 302h150q0 -118 -45.5 -224.5t-123 -184t-184 -123 t-224.5 -45.5q-198 0 -355 122z" />
<glyph unicode="&#xe032;" d="M100 0h1100v1200h-1100v-1200zM200 100v900h900v-900h-900zM300 200v100h100v-100h-100zM300 400v100h100v-100h-100zM300 600v100h100v-100h-100zM300 800v100h100v-100h-100zM500 200h500v100h-500v-100zM500 400v100h500v-100h-500zM500 600v100h500v-100h-500z M500 800v100h500v-100h-500z" />
<glyph unicode="&#xe033;" d="M0 100v600q0 41 29.5 70.5t70.5 29.5h100v200q0 82 59 141t141 59h300q82 0 141 -59t59 -141v-200h100q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-900q-41 0 -70.5 29.5t-29.5 70.5zM400 800h300v150q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-150z" />
<glyph unicode="&#xe034;" d="M100 0v1100h100v-1100h-100zM300 400q60 60 127.5 84t127.5 17.5t122 -23t119 -30t110 -11t103 42t91 120.5v500q-40 -81 -101.5 -115.5t-127.5 -29.5t-138 25t-139.5 40t-125.5 25t-103 -29.5t-65 -115.5v-500z" />
<glyph unicode="&#xe035;" d="M0 275q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 127 70.5 231.5t184.5 161.5t245 57t245 -57t184.5 -161.5t70.5 -231.5v-300q0 -11 7 -18t18 -7h50q11 0 18 7t7 18v300q0 116 -49.5 227t-131 192.5t-192.5 131t-227 49.5t-227 -49.5t-192.5 -131t-131 -192.5 t-49.5 -227v-300zM200 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14zM800 20v460q0 8 6 14t14 6h160q8 0 14 -6t6 -14v-460q0 -8 -6 -14t-14 -6h-160q-8 0 -14 6t-6 14z" />
<glyph unicode="&#xe036;" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM688 459l141 141l-141 141l71 71l141 -141l141 141l71 -71l-141 -141l141 -141l-71 -71l-141 141l-141 -141z" />
<glyph unicode="&#xe037;" d="M0 400h300l300 -200v800l-300 -200h-300v-400zM700 857l69 53q111 -135 111 -310q0 -169 -106 -302l-67 54q86 110 86 248q0 146 -93 257z" />
<glyph unicode="&#xe038;" d="M0 401v400h300l300 200v-800l-300 200h-300zM702 858l69 53q111 -135 111 -310q0 -170 -106 -303l-67 55q86 110 86 248q0 145 -93 257zM889 951l7 -8q123 -151 123 -344q0 -189 -119 -339l-7 -8l81 -66l6 8q142 178 142 405q0 230 -144 408l-6 8z" />
<glyph unicode="&#xe039;" d="M0 0h500v500h-200v100h-100v-100h-200v-500zM0 600h100v100h400v100h100v100h-100v300h-500v-600zM100 100v300h300v-300h-300zM100 800v300h300v-300h-300zM200 200v100h100v-100h-100zM200 900h100v100h-100v-100zM500 500v100h300v-300h200v-100h-100v-100h-200v100 h-100v100h100v200h-200zM600 0v100h100v-100h-100zM600 1000h100v-300h200v-300h300v200h-200v100h200v500h-600v-200zM800 800v300h300v-300h-300zM900 0v100h300v-100h-300zM900 900v100h100v-100h-100zM1100 200v100h100v-100h-100z" />
<glyph unicode="&#xe040;" d="M0 200h100v1000h-100v-1000zM100 0v100h300v-100h-300zM200 200v1000h100v-1000h-100zM500 0v91h100v-91h-100zM500 200v1000h200v-1000h-200zM700 0v91h100v-91h-100zM800 200v1000h100v-1000h-100zM900 0v91h200v-91h-200zM1000 200v1000h200v-1000h-200z" />
<glyph unicode="&#xe041;" d="M0 700l1 475q0 10 7.5 17.5t17.5 7.5h474l700 -700l-500 -500zM148 953q0 -42 29 -71q30 -30 71.5 -30t71.5 30q29 29 29 71t-29 71q-30 30 -71.5 30t-71.5 -30q-29 -29 -29 -71z" />
<glyph unicode="&#xe042;" d="M1 700l1 475q0 11 7 18t18 7h474l700 -700l-500 -500zM148 953q0 -42 30 -71q29 -30 71 -30t71 30q30 29 30 71t-30 71q-29 30 -71 30t-71 -30q-30 -29 -30 -71zM701 1200h100l700 -700l-500 -500l-50 50l450 450z" />
<glyph unicode="&#xe043;" d="M100 0v1025l175 175h925v-1000l-100 -100v1000h-750l-100 -100h750v-1000h-900z" />
<glyph unicode="&#xe044;" d="M200 0l450 444l450 -443v1150q0 20 -14.5 35t-35.5 15h-800q-21 0 -35.5 -15t-14.5 -35v-1151z" />
<glyph unicode="&#xe045;" d="M0 100v700h200l100 -200h600l100 200h200v-700h-200v200h-800v-200h-200zM253 829l40 -124h592l62 124l-94 346q-2 11 -10 18t-18 7h-450q-10 0 -18 -7t-10 -18zM281 24l38 152q2 10 11.5 17t19.5 7h500q10 0 19.5 -7t11.5 -17l38 -152q2 -10 -3.5 -17t-15.5 -7h-600 q-10 0 -15.5 7t-3.5 17z" />
<glyph unicode="&#xe046;" d="M0 200q0 -41 29.5 -70.5t70.5 -29.5h1000q41 0 70.5 29.5t29.5 70.5v600q0 41 -29.5 70.5t-70.5 29.5h-150q-4 8 -11.5 21.5t-33 48t-53 61t-69 48t-83.5 21.5h-200q-41 0 -82 -20.5t-70 -50t-52 -59t-34 -50.5l-12 -20h-150q-41 0 -70.5 -29.5t-29.5 -70.5v-600z M356 500q0 100 72 172t172 72t172 -72t72 -172t-72 -172t-172 -72t-172 72t-72 172zM494 500q0 -44 31 -75t75 -31t75 31t31 75t-31 75t-75 31t-75 -31t-31 -75zM900 700v100h100v-100h-100z" />
<glyph unicode="&#xe047;" d="M53 0h365v66q-41 0 -72 11t-49 38t1 71l92 234h391l82 -222q16 -45 -5.5 -88.5t-74.5 -43.5v-66h417v66q-34 1 -74 43q-18 19 -33 42t-21 37l-6 13l-385 998h-93l-399 -1006q-24 -48 -52 -75q-12 -12 -33 -25t-36 -20l-15 -7v-66zM416 521l178 457l46 -140l116 -317h-340 z" />
<glyph unicode="&#xe048;" d="M100 0v89q41 7 70.5 32.5t29.5 65.5v827q0 28 -1 39.5t-5.5 26t-15.5 21t-29 14t-49 14.5v71l471 -1q120 0 213 -88t93 -228q0 -55 -11.5 -101.5t-28 -74t-33.5 -47.5t-28 -28l-12 -7q8 -3 21.5 -9t48 -31.5t60.5 -58t47.5 -91.5t21.5 -129q0 -84 -59 -156.5t-142 -111 t-162 -38.5h-500zM400 200h161q89 0 153 48.5t64 132.5q0 90 -62.5 154.5t-156.5 64.5h-159v-400zM400 700h139q76 0 130 61.5t54 138.5q0 82 -84 130.5t-239 48.5v-379z" />
<glyph unicode="&#xe049;" d="M200 0v57q77 7 134.5 40.5t65.5 80.5l173 849q10 56 -10 74t-91 37q-6 1 -10.5 2.5t-9.5 2.5v57h425l2 -57q-33 -8 -62 -25.5t-46 -37t-29.5 -38t-17.5 -30.5l-5 -12l-128 -825q-10 -52 14 -82t95 -36v-57h-500z" />
<glyph unicode="&#xe050;" d="M-75 200h75v800h-75l125 167l125 -167h-75v-800h75l-125 -167zM300 900v300h150h700h150v-300h-50q0 29 -8 48.5t-18.5 30t-33.5 15t-39.5 5.5t-50.5 1h-200v-850l100 -50v-100h-400v100l100 50v850h-200q-34 0 -50.5 -1t-40 -5.5t-33.5 -15t-18.5 -30t-8.5 -48.5h-49z " />
<glyph unicode="&#xe051;" d="M33 51l167 125v-75h800v75l167 -125l-167 -125v75h-800v-75zM100 901v300h150h700h150v-300h-50q0 29 -8 48.5t-18 30t-33.5 15t-40 5.5t-50.5 1h-200v-650l100 -50v-100h-400v100l100 50v650h-200q-34 0 -50.5 -1t-39.5 -5.5t-33.5 -15t-18.5 -30t-8 -48.5h-50z" />
<glyph unicode="&#xe052;" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 350q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM0 650q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1000q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 950q0 -20 14.5 -35t35.5 -15h600q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-600q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" />
<glyph unicode="&#xe053;" d="M0 50q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM0 650q0 -20 14.5 -35t35.5 -15h1100q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5 v-100zM200 350q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM200 950q0 -20 14.5 -35t35.5 -15h700q21 0 35.5 15t14.5 35v100q0 21 -14.5 35.5t-35.5 14.5h-700q-21 0 -35.5 -14.5 t-14.5 -35.5v-100z" />
<glyph unicode="&#xe054;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM100 650v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1000q-21 0 -35.5 15 t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM500 950v100q0 21 14.5 35.5t35.5 14.5h600q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-600 q-21 0 -35.5 15t-14.5 35z" />
<glyph unicode="&#xe055;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h1100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-1100 q-21 0 -35.5 15t-14.5 35z" />
<glyph unicode="&#xe056;" d="M0 50v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 350v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM0 650v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15t-14.5 35zM0 950v100q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-100q-21 0 -35.5 15 t-14.5 35zM300 50v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 350v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800 q-21 0 -35.5 15t-14.5 35zM300 650v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15h-800q-21 0 -35.5 15t-14.5 35zM300 950v100q0 21 14.5 35.5t35.5 14.5h800q21 0 35.5 -14.5t14.5 -35.5v-100q0 -20 -14.5 -35t-35.5 -15 h-800q-21 0 -35.5 15t-14.5 35z" />
<glyph unicode="&#xe057;" d="M-101 500v100h201v75l166 -125l-166 -125v75h-201zM300 0h100v1100h-100v-1100zM500 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35 v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 650q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM500 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100 q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100z" />
<glyph unicode="&#xe058;" d="M1 50q0 -20 14.5 -35t35.5 -15h600q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-600q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 350q0 -20 14.5 -35t35.5 -15h300q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-300q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 650 q0 -20 14.5 -35t35.5 -15h500q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-500q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM1 950q0 -20 14.5 -35t35.5 -15h100q20 0 35 15t15 35v100q0 21 -15 35.5t-35 14.5h-100q-21 0 -35.5 -14.5t-14.5 -35.5v-100zM801 0v1100h100v-1100 h-100zM934 550l167 -125v75h200v100h-200v75z" />
<glyph unicode="&#xe059;" d="M0 275v650q0 31 22 53t53 22h750q31 0 53 -22t22 -53v-650q0 -31 -22 -53t-53 -22h-750q-31 0 -53 22t-22 53zM900 600l300 300v-600z" />
<glyph unicode="&#xe060;" d="M0 44v1012q0 18 13 31t31 13h1112q19 0 31.5 -13t12.5 -31v-1012q0 -18 -12.5 -31t-31.5 -13h-1112q-18 0 -31 13t-13 31zM100 263l247 182l298 -131l-74 156l293 318l236 -288v500h-1000v-737zM208 750q0 56 39 95t95 39t95 -39t39 -95t-39 -95t-95 -39t-95 39t-39 95z " />
<glyph unicode="&#xe062;" d="M148 745q0 124 60.5 231.5t165 172t226.5 64.5q123 0 227 -63t164.5 -169.5t60.5 -229.5t-73 -272q-73 -114 -166.5 -237t-150.5 -189l-57 -66q-10 9 -27 26t-66.5 70.5t-96 109t-104 135.5t-100.5 155q-63 139 -63 262zM342 772q0 -107 75.5 -182.5t181.5 -75.5 q107 0 182.5 75.5t75.5 182.5t-75.5 182t-182.5 75t-182 -75.5t-75 -181.5z" />
<glyph unicode="&#xe063;" d="M1 600q0 122 47.5 233t127.5 191t191 127.5t233 47.5t233 -47.5t191 -127.5t127.5 -191t47.5 -233t-47.5 -233t-127.5 -191t-191 -127.5t-233 -47.5t-233 47.5t-191 127.5t-127.5 191t-47.5 233zM173 600q0 -177 125.5 -302t301.5 -125v854q-176 0 -301.5 -125 t-125.5 -302z" />
<glyph unicode="&#xe064;" d="M117 406q0 94 34 186t88.5 172.5t112 159t115 177t87.5 194.5q21 -71 57.5 -142.5t76 -130.5t83 -118.5t82 -117t70 -116t50 -125.5t18.5 -136q0 -89 -39 -165.5t-102 -126.5t-140 -79.5t-156 -33.5q-114 6 -211.5 53t-161.5 139t-64 210zM243 414q14 -82 59.5 -136 t136.5 -80l16 98q-7 6 -18 17t-34 48t-33 77q-15 73 -14 143.5t10 122.5l9 51q-92 -110 -119.5 -185t-12.5 -156z" />
<glyph unicode="&#xe065;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5q366 -6 397 -14l-186 -186h-311q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v125l200 200v-225q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM436 341l161 50l412 412l-114 113l-405 -405zM995 1015l113 -113l113 113l-21 85l-92 28z" />
<glyph unicode="&#xe066;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h261l2 -80q-133 -32 -218 -120h-145q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5l200 153v-53q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5 zM423 524q30 38 81.5 64t103 35.5t99 14t77.5 3.5l29 -1v-209l360 324l-359 318v-216q-7 0 -19 -1t-48 -8t-69.5 -18.5t-76.5 -37t-76.5 -59t-62 -88t-39.5 -121.5z" />
<glyph unicode="&#xe067;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q61 0 127 -23l-178 -177h-349q-41 0 -70.5 -29.5t-29.5 -70.5v-500q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v69l200 200v-169q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5 t-117.5 282.5zM342 632l283 -284l567 567l-137 137l-430 -431l-146 147z" />
<glyph unicode="&#xe068;" d="M0 603l300 296v-198h200v200h-200l300 300l295 -300h-195v-200h200v198l300 -296l-300 -300v198h-200v-200h195l-295 -300l-300 300h200v200h-200v-198z" />
<glyph unicode="&#xe069;" d="M200 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-1100l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe070;" d="M0 50v1000q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-437l500 487v-487l500 487v-1100l-500 488v-488l-500 488v-438q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5z" />
<glyph unicode="&#xe071;" d="M136 550l564 550v-487l500 487v-1100l-500 488v-488z" />
<glyph unicode="&#xe072;" d="M200 0l900 550l-900 550v-1100z" />
<glyph unicode="&#xe073;" d="M200 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200q-21 0 -35.5 -14.5t-14.5 -35.5v-800zM600 150q0 -21 14.5 -35.5t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v800q0 21 -14.5 35.5t-35.5 14.5h-200 q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" />
<glyph unicode="&#xe074;" d="M200 150q0 -20 14.5 -35t35.5 -15h800q21 0 35.5 15t14.5 35v800q0 21 -14.5 35.5t-35.5 14.5h-800q-21 0 -35.5 -14.5t-14.5 -35.5v-800z" />
<glyph unicode="&#xe075;" d="M0 0v1100l500 -487v487l564 -550l-564 -550v488z" />
<glyph unicode="&#xe076;" d="M0 0v1100l500 -487v487l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438l-500 -488v488z" />
<glyph unicode="&#xe077;" d="M300 0v1100l500 -487v437q0 21 14.5 35.5t35.5 14.5h100q21 0 35.5 -14.5t14.5 -35.5v-1000q0 -21 -14.5 -35.5t-35.5 -14.5h-100q-21 0 -35.5 14.5t-14.5 35.5v438z" />
<glyph unicode="&#xe078;" d="M100 250v100q0 21 14.5 35.5t35.5 14.5h1000q21 0 35.5 -14.5t14.5 -35.5v-100q0 -21 -14.5 -35.5t-35.5 -14.5h-1000q-21 0 -35.5 14.5t-14.5 35.5zM100 500h1100l-550 564z" />
<glyph unicode="&#xe079;" d="M185 599l592 -592l240 240l-353 353l353 353l-240 240z" />
<glyph unicode="&#xe080;" d="M272 194l353 353l-353 353l241 240l572 -571l21 -22l-1 -1v-1l-592 -591z" />
<glyph unicode="&#xe081;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h200v-200h200v200h200v200h-200v200h-200v-200h-200v-200z" />
<glyph unicode="&#xe082;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM300 500h600v200h-600v-200z" />
<glyph unicode="&#xe083;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM246 459l213 -213l141 142l141 -142l213 213l-142 141l142 141l-213 212l-141 -141l-141 142l-212 -213l141 -141 z" />
<glyph unicode="&#xe084;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM270 551l276 -277l411 411l-175 174l-236 -236l-102 102z" />
<glyph unicode="&#xe085;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM364 700h143q4 0 11.5 -1t11 -1t6.5 3t3 9t1 11t3.5 8.5t3.5 6t5.5 4t6.5 2.5t9 1.5t9 0.5h11.5h12.5 q19 0 30 -10t11 -26q0 -22 -4 -28t-27 -22q-5 -1 -12.5 -3t-27 -13.5t-34 -27t-26.5 -46t-11 -68.5h200q5 3 14 8t31.5 25.5t39.5 45.5t31 69t14 94q0 51 -17.5 89t-42 58t-58.5 32t-58.5 15t-51.5 3q-50 0 -90.5 -12t-75 -38.5t-53.5 -74.5t-19 -114zM500 300h200v100h-200 v-100z" />
<glyph unicode="&#xe086;" d="M3 600q0 162 80 299.5t217.5 217.5t299.5 80t299.5 -80t217.5 -217.5t80 -299.5t-80 -299.5t-217.5 -217.5t-299.5 -80t-299.5 80t-217.5 217.5t-80 299.5zM400 300h400v100h-100v300h-300v-100h100v-200h-100v-100zM500 800h200v100h-200v-100z" />
<glyph unicode="&#xe087;" d="M0 500v200h195q31 125 98.5 199.5t206.5 100.5v200h200v-200q54 -20 113 -60t112.5 -105.5t71.5 -134.5h203v-200h-203q-25 -102 -116.5 -186t-180.5 -117v-197h-200v197q-140 27 -208 102.5t-98 200.5h-194zM290 500q24 -73 79.5 -127.5t130.5 -78.5v206h200v-206 q149 48 201 206h-201v200h200q-25 74 -75.5 127t-124.5 77v-204h-200v203q-75 -23 -130 -77t-79 -126h209v-200h-210z" />
<glyph unicode="&#xe088;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM356 465l135 135 l-135 135l109 109l135 -135l135 135l109 -109l-135 -135l135 -135l-109 -109l-135 135l-135 -135z" />
<glyph unicode="&#xe089;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM322 537l141 141 l87 -87l204 205l142 -142l-346 -345z" />
<glyph unicode="&#xe090;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -115 62 -215l568 567q-100 62 -216 62q-171 0 -292.5 -121.5t-121.5 -292.5zM391 245q97 -59 209 -59q171 0 292.5 121.5t121.5 292.5 q0 112 -59 209z" />
<glyph unicode="&#xe091;" d="M0 547l600 453v-300h600v-300h-600v-301z" />
<glyph unicode="&#xe092;" d="M0 400v300h600v300l600 -453l-600 -448v301h-600z" />
<glyph unicode="&#xe093;" d="M204 600l450 600l444 -600h-298v-600h-300v600h-296z" />
<glyph unicode="&#xe094;" d="M104 600h296v600h300v-600h298l-449 -600z" />
<glyph unicode="&#xe095;" d="M0 200q6 132 41 238.5t103.5 193t184 138t271.5 59.5v271l600 -453l-600 -448v301q-95 -2 -183 -20t-170 -52t-147 -92.5t-100 -135.5z" />
<glyph unicode="&#xe096;" d="M0 0v400l129 -129l294 294l142 -142l-294 -294l129 -129h-400zM635 777l142 -142l294 294l129 -129v400h-400l129 -129z" />
<glyph unicode="&#xe097;" d="M34 176l295 295l-129 129h400v-400l-129 130l-295 -295zM600 600v400l129 -129l295 295l142 -141l-295 -295l129 -130h-400z" />
<glyph unicode="&#xe101;" d="M23 600q0 118 45.5 224.5t123 184t184 123t224.5 45.5t224.5 -45.5t184 -123t123 -184t45.5 -224.5t-45.5 -224.5t-123 -184t-184 -123t-224.5 -45.5t-224.5 45.5t-184 123t-123 184t-45.5 224.5zM456 851l58 -302q4 -20 21.5 -34.5t37.5 -14.5h54q20 0 37.5 14.5 t21.5 34.5l58 302q4 20 -8 34.5t-32 14.5h-207q-21 0 -33 -14.5t-8 -34.5zM500 300h200v100h-200v-100z" />
<glyph unicode="&#xe102;" d="M0 800h100v-200h400v300h200v-300h400v200h100v100h-111q1 1 1 6.5t-1.5 15t-3.5 17.5l-34 172q-11 39 -41.5 63t-69.5 24q-32 0 -61 -17l-239 -144q-22 -13 -40 -35q-19 24 -40 36l-238 144q-33 18 -62 18q-39 0 -69.5 -23t-40.5 -61l-35 -177q-2 -8 -3 -18t-1 -15v-6 h-111v-100zM100 0h400v400h-400v-400zM200 900q-3 0 14 48t36 96l18 47l213 -191h-281zM700 0v400h400v-400h-400zM731 900l202 197q5 -12 12 -32.5t23 -64t25 -72t7 -28.5h-269z" />
<glyph unicode="&#xe103;" d="M0 -22v143l216 193q-9 53 -13 83t-5.5 94t9 113t38.5 114t74 124q47 60 99.5 102.5t103 68t127.5 48t145.5 37.5t184.5 43.5t220 58.5q0 -189 -22 -343t-59 -258t-89 -181.5t-108.5 -120t-122 -68t-125.5 -30t-121.5 -1.5t-107.5 12.5t-87.5 17t-56.5 7.5l-99 -55z M238.5 300.5q19.5 -6.5 86.5 76.5q55 66 367 234q70 38 118.5 69.5t102 79t99 111.5t86.5 148q22 50 24 60t-6 19q-7 5 -17 5t-26.5 -14.5t-33.5 -39.5q-35 -51 -113.5 -108.5t-139.5 -89.5l-61 -32q-369 -197 -458 -401q-48 -111 -28.5 -117.5z" />
<glyph unicode="&#xe104;" d="M111 408q0 -33 5 -63q9 -56 44 -119.5t105 -108.5q31 -21 64 -16t62 23.5t57 49.5t48 61.5t35 60.5q32 66 39 184.5t-13 157.5q79 -80 122 -164t26 -184q-5 -33 -20.5 -69.5t-37.5 -80.5q-10 -19 -14.5 -29t-12 -26t-9 -23.5t-3 -19t2.5 -15.5t11 -9.5t19.5 -5t30.5 2.5 t42 8q57 20 91 34t87.5 44.5t87 64t65.5 88.5t47 122q38 172 -44.5 341.5t-246.5 278.5q22 -44 43 -129q39 -159 -32 -154q-15 2 -33 9q-79 33 -120.5 100t-44 175.5t48.5 257.5q-13 -8 -34 -23.5t-72.5 -66.5t-88.5 -105.5t-60 -138t-8 -166.5q2 -12 8 -41.5t8 -43t6 -39.5 t3.5 -39.5t-1 -33.5t-6 -31.5t-13.5 -24t-21 -20.5t-31 -12q-38 -10 -67 13t-40.5 61.5t-15 81.5t10.5 75q-52 -46 -83.5 -101t-39 -107t-7.5 -85z" />
<glyph unicode="&#xe105;" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5t145.5 -23.5t132.5 -59t116.5 -83.5t97 -90t74.5 -85.5t49 -63.5t20 -30l26 -40l-26 -40q-6 -10 -20 -30t-49 -63.5t-74.5 -85.5t-97 -90t-116.5 -83.5t-132.5 -59t-145.5 -23.5 t-145.5 23.5t-132.5 59t-116.5 83.5t-97 90t-74.5 85.5t-49 63.5t-20 30zM120 600q7 -10 40.5 -58t56 -78.5t68 -77.5t87.5 -75t103 -49.5t125 -21.5t123.5 20t100.5 45.5t85.5 71.5t66.5 75.5t58 81.5t47 66q-1 1 -28.5 37.5t-42 55t-43.5 53t-57.5 63.5t-58.5 54 q49 -74 49 -163q0 -124 -88 -212t-212 -88t-212 88t-88 212q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l105 105q-37 24 -75 72t-57 84l-20 36z" />
<glyph unicode="&#xe106;" d="M-61 600l26 40q6 10 20 30t49 63.5t74.5 85.5t97 90t116.5 83.5t132.5 59t145.5 23.5q61 0 121 -17l37 142h148l-314 -1200h-148l37 143q-82 21 -165 71.5t-140 102t-109.5 112t-72 88.5t-29.5 43zM120 600q210 -282 393 -336l37 141q-107 18 -178.5 101.5t-71.5 193.5 q0 85 46 158q-102 -87 -226 -258zM377 656q49 -124 154 -191l47 47l23 87q-30 28 -59 69t-44 68l-14 26zM780 161l38 145q22 15 44.5 34t46 44t40.5 44t41 50.5t33.5 43.5t33 44t24.5 34q-97 127 -140 175l39 146q67 -54 131.5 -125.5t87.5 -103.5t36 -52l26 -40l-26 -40 q-7 -12 -25.5 -38t-63.5 -79.5t-95.5 -102.5t-124 -100t-146.5 -79z" />
<glyph unicode="&#xe107;" d="M-97.5 34q13.5 -34 50.5 -34h1294q37 0 50.5 35.5t-7.5 67.5l-642 1056q-20 34 -48 36.5t-48 -29.5l-642 -1066q-21 -32 -7.5 -66zM155 200l445 723l445 -723h-345v100h-200v-100h-345zM500 600l100 -300l100 300v100h-200v-100z" />
<glyph unicode="&#xe108;" d="M100 262v41q0 20 11 44.5t26 38.5l363 325v339q0 62 44 106t106 44t106 -44t44 -106v-339l363 -325q15 -14 26 -38.5t11 -44.5v-41q0 -20 -12 -26.5t-29 5.5l-359 249v-263q100 -91 100 -113v-64q0 -20 -13 -28.5t-32 0.5l-94 78h-222l-94 -78q-19 -9 -32 -0.5t-13 28.5 v64q0 22 100 113v263l-359 -249q-17 -12 -29 -5.5t-12 26.5z" />
<glyph unicode="&#xe109;" d="M0 50q0 -20 14.5 -35t35.5 -15h1000q21 0 35.5 15t14.5 35v750h-1100v-750zM0 900h1100v150q0 21 -14.5 35.5t-35.5 14.5h-150v100h-100v-100h-500v100h-100v-100h-150q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 100v100h100v-100h-100zM100 300v100h100v-100h-100z M100 500v100h100v-100h-100zM300 100v100h100v-100h-100zM300 300v100h100v-100h-100zM300 500v100h100v-100h-100zM500 100v100h100v-100h-100zM500 300v100h100v-100h-100zM500 500v100h100v-100h-100zM700 100v100h100v-100h-100zM700 300v100h100v-100h-100zM700 500 v100h100v-100h-100zM900 100v100h100v-100h-100zM900 300v100h100v-100h-100zM900 500v100h100v-100h-100z" />
<glyph unicode="&#xe110;" d="M0 200v200h259l600 600h241v198l300 -295l-300 -300v197h-159l-600 -600h-341zM0 800h259l122 -122l141 142l-181 180h-341v-200zM678 381l141 142l122 -123h159v198l300 -295l-300 -300v197h-241z" />
<glyph unicode="&#xe111;" d="M0 400v600q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-600q0 -41 -29.5 -70.5t-70.5 -29.5h-596l-304 -300v300h-100q-41 0 -70.5 29.5t-29.5 70.5z" />
<glyph unicode="&#xe112;" d="M100 600v200h300v-250q0 -113 6 -145q17 -92 102 -117q39 -11 92 -11q37 0 66.5 5.5t50 15.5t36 24t24 31.5t14 37.5t7 42t2.5 45t0 47v25v250h300v-200q0 -42 -3 -83t-15 -104t-31.5 -116t-58 -109.5t-89 -96.5t-129 -65.5t-174.5 -25.5t-174.5 25.5t-129 65.5t-89 96.5 t-58 109.5t-31.5 116t-15 104t-3 83zM100 900v300h300v-300h-300zM800 900v300h300v-300h-300z" />
<glyph unicode="&#xe113;" d="M-30 411l227 -227l352 353l353 -353l226 227l-578 579z" />
<glyph unicode="&#xe114;" d="M70 797l580 -579l578 579l-226 227l-353 -353l-352 353z" />
<glyph unicode="&#xe115;" d="M-198 700l299 283l300 -283h-203v-400h385l215 -200h-800v600h-196zM402 1000l215 -200h381v-400h-198l299 -283l299 283h-200v600h-796z" />
<glyph unicode="&#xe116;" d="M18 939q-5 24 10 42q14 19 39 19h896l38 162q5 17 18.5 27.5t30.5 10.5h94q20 0 35 -14.5t15 -35.5t-15 -35.5t-35 -14.5h-54l-201 -961q-2 -4 -6 -10.5t-19 -17.5t-33 -11h-31v-50q0 -20 -14.5 -35t-35.5 -15t-35.5 15t-14.5 35v50h-300v-50q0 -20 -14.5 -35t-35.5 -15 t-35.5 15t-14.5 35v50h-50q-21 0 -35.5 15t-14.5 35q0 21 14.5 35.5t35.5 14.5h535l48 200h-633q-32 0 -54.5 21t-27.5 43z" />
<glyph unicode="&#xe117;" d="M0 0v800h1200v-800h-1200zM0 900v100h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-100h-1200z" />
<glyph unicode="&#xe118;" d="M1 0l300 700h1200l-300 -700h-1200zM1 400v600h200q0 41 29.5 70.5t70.5 29.5h300q41 0 70.5 -29.5t29.5 -70.5h500v-200h-1000z" />
<glyph unicode="&#xe119;" d="M302 300h198v600h-198l298 300l298 -300h-198v-600h198l-298 -300z" />
<glyph unicode="&#xe120;" d="M0 600l300 298v-198h600v198l300 -298l-300 -297v197h-600v-197z" />
<glyph unicode="&#xe121;" d="M0 100v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM31 400l172 739q5 22 23 41.5t38 19.5h672q19 0 37.5 -22.5t23.5 -45.5l172 -732h-1138zM800 100h100v100h-100v-100z M1000 100h100v100h-100v-100z" />
<glyph unicode="&#xe122;" d="M-101 600v50q0 24 25 49t50 38l25 13v-250l-11 5.5t-24 14t-30 21.5t-24 27.5t-11 31.5zM100 500v250v8v8v7t0.5 7t1.5 5.5t2 5t3 4t4.5 3.5t6 1.5t7.5 0.5h200l675 250v-850l-675 200h-38l47 -276q2 -12 -3 -17.5t-11 -6t-21 -0.5h-8h-83q-20 0 -34.5 14t-18.5 35 q-55 337 -55 351zM1100 200v850q0 21 14.5 35.5t35.5 14.5q20 0 35 -14.5t15 -35.5v-850q0 -20 -15 -35t-35 -15q-21 0 -35.5 15t-14.5 35z" />
<glyph unicode="&#xe123;" d="M74 350q0 21 13.5 35.5t33.5 14.5h18l117 173l63 327q15 77 76 140t144 83l-18 32q-6 19 3 32t29 13h94q20 0 29 -10.5t3 -29.5q-18 -36 -18 -37q83 -19 144 -82.5t76 -140.5l63 -327l118 -173h17q20 0 33.5 -14.5t13.5 -35.5q0 -20 -13 -40t-31 -27q-8 -3 -23 -8.5 t-65 -20t-103 -25t-132.5 -19.5t-158.5 -9q-125 0 -245.5 20.5t-178.5 40.5l-58 20q-18 7 -31 27.5t-13 40.5zM497 110q12 -49 40 -79.5t63 -30.5t63 30.5t39 79.5q-48 -6 -102 -6t-103 6z" />
<glyph unicode="&#xe124;" d="M21 445l233 -45l-78 -224l224 78l45 -233l155 179l155 -179l45 233l224 -78l-78 224l234 45l-180 155l180 156l-234 44l78 225l-224 -78l-45 233l-155 -180l-155 180l-45 -233l-224 78l78 -225l-233 -44l179 -156z" />
<glyph unicode="&#xe125;" d="M0 200h200v600h-200v-600zM300 275q0 -75 100 -75h61q124 -100 139 -100h250q46 0 83 57l238 344q29 31 29 74v100q0 44 -30.5 84.5t-69.5 40.5h-328q28 118 28 125v150q0 44 -30.5 84.5t-69.5 40.5h-50q-27 0 -51 -20t-38 -48l-96 -198l-145 -196q-20 -26 -20 -63v-400z M400 300v375l150 213l100 212h50v-175l-50 -225h450v-125l-250 -375h-214l-136 100h-100z" />
<glyph unicode="&#xe126;" d="M0 400v600h200v-600h-200zM300 525v400q0 75 100 75h61q124 100 139 100h250q46 0 83 -57l238 -344q29 -31 29 -74v-100q0 -44 -30.5 -84.5t-69.5 -40.5h-328q28 -118 28 -125v-150q0 -44 -30.5 -84.5t-69.5 -40.5h-50q-27 0 -51 20t-38 48l-96 198l-145 196 q-20 26 -20 63zM400 525l150 -212l100 -213h50v175l-50 225h450v125l-250 375h-214l-136 -100h-100v-375z" />
<glyph unicode="&#xe127;" d="M8 200v600h200v-600h-200zM308 275v525q0 17 14 35.5t28 28.5l14 9l362 230q14 6 25 6q17 0 29 -12l109 -112q14 -14 14 -34q0 -18 -11 -32l-85 -121h302q85 0 138.5 -38t53.5 -110t-54.5 -111t-138.5 -39h-107l-130 -339q-7 -22 -20.5 -41.5t-28.5 -19.5h-341 q-7 0 -90 81t-83 94zM408 289l100 -89h293l131 339q6 21 19.5 41t28.5 20h203q16 0 25 15t9 36q0 20 -9 34.5t-25 14.5h-457h-6.5h-7.5t-6.5 0.5t-6 1t-5 1.5t-5.5 2.5t-4 4t-4 5.5q-5 12 -5 20q0 14 10 27l147 183l-86 83l-339 -236v-503z" />
<glyph unicode="&#xe128;" d="M-101 651q0 72 54 110t139 38l302 -1l-85 121q-11 16 -11 32q0 21 14 34l109 113q13 12 29 12q11 0 25 -6l365 -230q7 -4 17 -10.5t26.5 -26t16.5 -36.5v-526q0 -13 -86 -93.5t-94 -80.5h-341q-16 0 -29.5 20t-19.5 41l-130 339h-107q-84 0 -139 39t-55 111zM-1 601h222 q15 0 28.5 -20.5t19.5 -40.5l131 -339h293l107 89v502l-343 237l-87 -83l145 -184q10 -11 10 -26q0 -11 -5 -20q-1 -3 -3.5 -5.5l-4 -4t-5 -2.5t-5.5 -1.5t-6.5 -1t-6.5 -0.5h-7.5h-6.5h-476v-100zM1000 201v600h200v-600h-200z" />
<glyph unicode="&#xe129;" d="M97 719l230 -363q4 -6 10.5 -15.5t26 -25t36.5 -15.5h525q13 0 94 83t81 90v342q0 15 -20 28.5t-41 19.5l-339 131v106q0 84 -39 139t-111 55t-110 -53.5t-38 -138.5v-302l-121 84q-15 12 -33.5 11.5t-32.5 -13.5l-112 -110q-22 -22 -6 -53zM172 739l83 86l183 -146 q22 -18 47 -5q3 1 5.5 3.5l4 4t2.5 5t1.5 5.5t1 6.5t0.5 6.5v7.5v6.5v456q0 22 25 31t50 -0.5t25 -30.5v-202q0 -16 20 -29.5t41 -19.5l339 -130v-294l-89 -100h-503zM400 0v200h600v-200h-600z" />
<glyph unicode="&#xe130;" d="M2 585q-16 -31 6 -53l112 -110q13 -13 32 -13.5t34 10.5l121 85q0 -51 -0.5 -153.5t-0.5 -148.5q0 -84 38.5 -138t110.5 -54t111 55t39 139v106l339 131q20 6 40.5 19.5t20.5 28.5v342q0 7 -81 90t-94 83h-525q-17 0 -35.5 -14t-28.5 -28l-10 -15zM77 565l236 339h503 l89 -100v-294l-340 -130q-20 -6 -40 -20t-20 -29v-202q0 -22 -25 -31t-50 0t-25 31v456v14.5t-1.5 11.5t-5 12t-9.5 7q-24 13 -46 -5l-184 -146zM305 1104v200h600v-200h-600z" />
<glyph unicode="&#xe131;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM298 701l2 -201h300l-2 -194l402 294l-402 298v-197h-300z" />
<glyph unicode="&#xe132;" d="M0 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t231.5 47.5q122 0 232.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-218 -217.5t-300 -80t-299.5 80t-217.5 217.5t-80 299.5zM200 600l402 -294l-2 194h300l2 201h-300v197z" />
<glyph unicode="&#xe133;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600h200v-300h200v300h200l-300 400z" />
<glyph unicode="&#xe134;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q162 0 299.5 -80t217.5 -218t80 -300t-80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM300 600l300 -400l300 400h-200v300h-200v-300h-200z" />
<glyph unicode="&#xe135;" d="M5 597q0 122 47.5 232.5t127.5 190.5t190.5 127.5t232.5 47.5q121 0 231.5 -47.5t190.5 -127.5t127.5 -190.5t47.5 -232.5q0 -162 -80 -299.5t-217.5 -217.5t-299.5 -80t-300 80t-218 217.5t-80 299.5zM254 780q-8 -33 5.5 -92.5t7.5 -87.5q0 -9 17 -44t16 -60 q12 0 23 -5.5t23 -15t20 -13.5q24 -12 108 -42q22 -8 53 -31.5t59.5 -38.5t57.5 -11q8 -18 -15 -55t-20 -57q42 -71 87 -80q0 -6 -3 -15.5t-3.5 -14.5t4.5 -17q104 -3 221 112q30 29 47 47t34.5 49t20.5 62q-14 9 -37 9.5t-36 7.5q-14 7 -49 15t-52 19q-9 0 -39.5 -0.5 t-46.5 -1.5t-39 -6.5t-39 -16.5q-50 -35 -66 -12q-4 2 -3.5 25.5t0.5 25.5q-6 13 -26.5 17t-24.5 7q2 22 -2 41t-16.5 28t-38.5 -20q-23 -25 -42 4q-19 28 -8 58q6 16 22 22q6 -1 26 -1.5t33.5 -4t19.5 -13.5q12 -19 32 -37.5t34 -27.5l14 -8q0 3 9.5 39.5t5.5 57.5 q-4 23 14.5 44.5t22.5 31.5q5 14 10 35t8.5 31t15.5 22.5t34 21.5q-6 18 10 37q8 0 23.5 -1.5t24.5 -1.5t20.5 4.5t20.5 15.5q-10 23 -30.5 42.5t-38 30t-49 26.5t-43.5 23q11 39 2 44q31 -13 58 -14.5t39 3.5l11 4q7 36 -16.5 53.5t-64.5 28.5t-56 23q-19 -3 -37 0 q-15 -12 -36.5 -21t-34.5 -12t-44 -8t-39 -6q-15 -3 -45.5 0.5t-45.5 -2.5q-21 -7 -52 -26.5t-34 -34.5q-3 -11 6.5 -22.5t8.5 -18.5q-3 -34 -27.5 -90.5t-29.5 -79.5zM518 916q3 12 16 30t16 25q10 -10 18.5 -10t14 6t14.5 14.5t16 12.5q0 -24 17 -66.5t17 -43.5 q-9 2 -31 5t-36 5t-32 8t-30 14zM692 1003h1h-1z" />
<glyph unicode="&#xe136;" d="M0 164.5q0 21.5 15 37.5l600 599q-33 101 6 201.5t135 154.5q164 92 306 -9l-259 -138l145 -232l251 126q13 -175 -151 -267q-123 -70 -253 -23l-596 -596q-15 -16 -36.5 -16t-36.5 16l-111 110q-15 15 -15 36.5z" />
<glyph unicode="&#xe137;" horiz-adv-x="1220" d="M0 196v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 596v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000 q-41 0 -70.5 29.5t-29.5 70.5zM0 996v100q0 41 29.5 70.5t70.5 29.5h1000q41 0 70.5 -29.5t29.5 -70.5v-100q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM600 596h500v100h-500v-100zM800 196h300v100h-300v-100zM900 996h200v100h-200v-100z" />
<glyph unicode="&#xe138;" d="M100 1100v100h1000v-100h-1000zM150 1000h900l-350 -500v-300l-200 -200v500z" />
<glyph unicode="&#xe139;" d="M0 200v200h1200v-200q0 -41 -29.5 -70.5t-70.5 -29.5h-1000q-41 0 -70.5 29.5t-29.5 70.5zM0 500v400q0 41 29.5 70.5t70.5 29.5h300v100q0 41 29.5 70.5t70.5 29.5h200q41 0 70.5 -29.5t29.5 -70.5v-100h300q41 0 70.5 -29.5t29.5 -70.5v-400h-500v100h-200v-100h-500z M500 1000h200v100h-200v-100z" />
<glyph unicode="&#xe140;" d="M0 0v400l129 -129l200 200l142 -142l-200 -200l129 -129h-400zM0 800l129 129l200 -200l142 142l-200 200l129 129h-400v-400zM729 329l142 142l200 -200l129 129v-400h-400l129 129zM729 871l200 200l-129 129h400v-400l-129 129l-200 -200z" />
<glyph unicode="&#xe141;" d="M0 596q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 596q0 -172 121.5 -293t292.5 -121t292.5 121t121.5 293q0 171 -121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM291 655 q0 23 15.5 38.5t38.5 15.5t39 -16t16 -38q0 -23 -16 -39t-39 -16q-22 0 -38 16t-16 39zM400 850q0 22 16 38.5t39 16.5q22 0 38 -16t16 -39t-16 -39t-38 -16q-23 0 -39 16.5t-16 38.5zM514 609q0 32 20.5 56.5t51.5 29.5l122 126l1 1q-9 14 -9 28q0 22 16 38.5t39 16.5 q22 0 38 -16t16 -39t-16 -39t-38 -16q-14 0 -29 10l-55 -145q17 -22 17 -51q0 -36 -25.5 -61.5t-61.5 -25.5t-61.5 25.5t-25.5 61.5zM800 655q0 22 16 38t39 16t38.5 -15.5t15.5 -38.5t-16 -39t-38 -16q-23 0 -39 16t-16 39z" />
<glyph unicode="&#xe142;" d="M-40 375q-13 -95 35 -173q35 -57 94 -89t129 -32q63 0 119 28q33 16 65 40.5t52.5 45.5t59.5 64q40 44 57 61l394 394q35 35 47 84t-3 96q-27 87 -117 104q-20 2 -29 2q-46 0 -78.5 -16.5t-67.5 -51.5l-389 -396l-7 -7l69 -67l377 373q20 22 39 38q23 23 50 23 q38 0 53 -36q16 -39 -20 -75l-547 -547q-52 -52 -125 -52q-55 0 -100 33t-54 96q-5 35 2.5 66t31.5 63t42 50t56 54q24 21 44 41l348 348q52 52 82.5 79.5t84 54t107.5 26.5q25 0 48 -4q95 -17 154 -94.5t51 -175.5q-7 -101 -98 -192l-252 -249l-253 -256l7 -7l69 -60 l517 511q67 67 95 157t11 183q-16 87 -67 154t-130 103q-69 33 -152 33q-107 0 -197 -55q-40 -24 -111 -95l-512 -512q-68 -68 -81 -163z" />
<glyph unicode="&#xe143;" d="M80 784q0 131 98.5 229.5t230.5 98.5q143 0 241 -129q103 129 246 129q129 0 226 -98.5t97 -229.5q0 -46 -17.5 -91t-61 -99t-77 -89.5t-104.5 -105.5q-197 -191 -293 -322l-17 -23l-16 23q-43 58 -100 122.5t-92 99.5t-101 100q-71 70 -104.5 105.5t-77 89.5t-61 99 t-17.5 91zM250 784q0 -27 30.5 -70t61.5 -75.5t95 -94.5l22 -22q93 -90 190 -201q82 92 195 203l12 12q64 62 97.5 97t64.5 79t31 72q0 71 -48 119.5t-105 48.5q-74 0 -132 -83l-118 -171l-114 174q-51 80 -123 80q-60 0 -109.5 -49.5t-49.5 -118.5z" />
<glyph unicode="&#xe144;" d="M57 353q0 -95 66 -159l141 -142q68 -66 159 -66q93 0 159 66l283 283q66 66 66 159t-66 159l-141 141q-8 9 -19 17l-105 -105l212 -212l-389 -389l-247 248l95 95l-18 18q-46 45 -75 101l-55 -55q-66 -66 -66 -159zM269 706q0 -93 66 -159l141 -141q7 -7 19 -17l105 105 l-212 212l389 389l247 -247l-95 -96l18 -17q47 -49 77 -100l29 29q35 35 62.5 88t27.5 96q0 93 -66 159l-141 141q-66 66 -159 66q-95 0 -159 -66l-283 -283q-66 -64 -66 -159z" />
<glyph unicode="&#xe145;" d="M200 100v953q0 21 30 46t81 48t129 38t163 15t162 -15t127 -38t79 -48t29 -46v-953q0 -41 -29.5 -70.5t-70.5 -29.5h-600q-41 0 -70.5 29.5t-29.5 70.5zM300 300h600v700h-600v-700zM496 150q0 -43 30.5 -73.5t73.5 -30.5t73.5 30.5t30.5 73.5t-30.5 73.5t-73.5 30.5 t-73.5 -30.5t-30.5 -73.5z" />
<glyph unicode="&#xe146;" d="M0 0l303 380l207 208l-210 212h300l267 279l-35 36q-15 14 -15 35t15 35q14 15 35 15t35 -15l283 -282q15 -15 15 -36t-15 -35q-14 -15 -35 -15t-35 15l-36 35l-279 -267v-300l-212 210l-208 -207z" />
<glyph unicode="&#xe148;" d="M295 433h139q5 -77 48.5 -126.5t117.5 -64.5v335q-6 1 -15.5 4t-11.5 3q-46 14 -79 26.5t-72 36t-62.5 52t-40 72.5t-16.5 99q0 92 44 159.5t109 101t144 40.5v78h100v-79q38 -4 72.5 -13.5t75.5 -31.5t71 -53.5t51.5 -84t24.5 -118.5h-159q-8 72 -35 109.5t-101 50.5 v-307l64 -14q34 -7 64 -16.5t70 -31.5t67.5 -52t47.5 -80.5t20 -112.5q0 -139 -89 -224t-244 -96v-77h-100v78q-152 17 -237 104q-40 40 -52.5 93.5t-15.5 139.5zM466 889q0 -29 8 -51t16.5 -34t29.5 -22.5t31 -13.5t38 -10q7 -2 11 -3v274q-61 -8 -97.5 -37.5t-36.5 -102.5 zM700 237q170 18 170 151q0 64 -44 99.5t-126 60.5v-311z" />
<glyph unicode="&#xe149;" d="M100 600v100h166q-24 49 -44 104q-10 26 -14.5 55.5t-3 72.5t25 90t68.5 87q97 88 263 88q129 0 230 -89t101 -208h-153q0 52 -34 89.5t-74 51.5t-76 14q-37 0 -79 -14.5t-62 -35.5q-41 -44 -41 -101q0 -28 16.5 -69.5t28 -62.5t41.5 -72h241v-100h-197q8 -50 -2.5 -115 t-31.5 -94q-41 -59 -99 -113q35 11 84 18t70 7q33 1 103 -16t103 -17q76 0 136 30l50 -147q-41 -25 -80.5 -36.5t-59 -13t-61.5 -1.5q-23 0 -128 33t-155 29q-39 -4 -82 -17t-66 -25l-24 -11l-55 145l16.5 11t15.5 10t13.5 9.5t14.5 12t14.5 14t17.5 18.5q48 55 54 126.5 t-30 142.5h-221z" />
<glyph unicode="&#xe150;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM602 900l298 300l298 -300h-198v-900h-200v900h-198z" />
<glyph unicode="&#xe151;" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v200h100v-100h200v-100h-300zM700 400v100h300v-200h-99v-100h-100v100h99v100h-200zM700 700v500h300v-500h-100v100h-100v-100h-100zM801 900h100v200h-100v-200z" />
<glyph unicode="&#xe152;" d="M2 300h198v900h200v-900h198l-298 -300zM700 0v500h300v-500h-100v100h-100v-100h-100zM700 700v200h100v-100h200v-100h-300zM700 1100v100h300v-200h-99v-100h-100v100h99v100h-200zM801 200h100v200h-100v-200z" />
<glyph unicode="&#xe153;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 100v400h300v-500h-100v100h-200zM800 1100v100h200v-500h-100v400h-100zM901 200h100v200h-100v-200z" />
<glyph unicode="&#xe154;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM800 400v100h200v-500h-100v400h-100zM800 800v400h300v-500h-100v100h-200zM901 900h100v200h-100v-200z" />
<glyph unicode="&#xe155;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h500v-200h-500zM700 400v200h400v-200h-400zM700 700v200h300v-200h-300zM700 1000v200h200v-200h-200z" />
<glyph unicode="&#xe156;" d="M2 300l298 -300l298 300h-198v900h-200v-900h-198zM700 100v200h200v-200h-200zM700 400v200h300v-200h-300zM700 700v200h400v-200h-400zM700 1000v200h500v-200h-500z" />
<glyph unicode="&#xe157;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q162 0 281 -118.5t119 -281.5v-300q0 -165 -118.5 -282.5t-281.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500z" />
<glyph unicode="&#xe158;" d="M0 400v300q0 163 119 281.5t281 118.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-163 0 -281.5 117.5t-118.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM400 300l333 250l-333 250v-500z" />
<glyph unicode="&#xe159;" d="M0 400v300q0 163 117.5 281.5t282.5 118.5h300q163 0 281.5 -119t118.5 -281v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-300q-165 0 -282.5 117.5t-117.5 282.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 700l250 -333l250 333h-500z" />
<glyph unicode="&#xe160;" d="M0 400v300q0 165 117.5 282.5t282.5 117.5h300q165 0 282.5 -117.5t117.5 -282.5v-300q0 -162 -118.5 -281t-281.5 -119h-300q-165 0 -282.5 118.5t-117.5 281.5zM200 300q0 -41 29.5 -70.5t70.5 -29.5h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5 h-500q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM300 400h500l-250 333z" />
<glyph unicode="&#xe161;" d="M0 400v300h300v200l400 -350l-400 -350v200h-300zM500 0v200h500q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-500v200h400q165 0 282.5 -117.5t117.5 -282.5v-300q0 -165 -117.5 -282.5t-282.5 -117.5h-400z" />
<glyph unicode="&#xe162;" d="M217 519q8 -19 31 -19h302q-155 -438 -160 -458q-5 -21 4 -32l9 -8h9q14 0 26 15q11 13 274.5 321.5t264.5 308.5q14 19 5 36q-8 17 -31 17l-301 -1q1 4 78 219.5t79 227.5q2 15 -5 27l-9 9h-9q-15 0 -25 -16q-4 -6 -98 -111.5t-228.5 -257t-209.5 -237.5q-16 -19 -6 -41 z" />
<glyph unicode="&#xe163;" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q47 0 100 15v185h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h500v185q-14 4 -114 7.5t-193 5.5l-93 2q-165 0 -282.5 -117.5t-117.5 -282.5v-300zM600 400v300h300v200l400 -350l-400 -350v200h-300z " />
<glyph unicode="&#xe164;" d="M0 400q0 -165 117.5 -282.5t282.5 -117.5h300q163 0 281.5 117.5t118.5 282.5v98l-78 73l-122 -123v-148q0 -41 -29.5 -70.5t-70.5 -29.5h-500q-41 0 -70.5 29.5t-29.5 70.5v500q0 41 29.5 70.5t70.5 29.5h156l118 122l-74 78h-100q-165 0 -282.5 -117.5t-117.5 -282.5 v-300zM496 709l353 342l-149 149h500v-500l-149 149l-342 -353z" />
<glyph unicode="&#xe165;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM406 600 q0 80 57 137t137 57t137 -57t57 -137t-57 -137t-137 -57t-137 57t-57 137z" />
<glyph unicode="&#xe166;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 800l445 -500l450 500h-295v400h-300v-400h-300zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe167;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 700h300v-300h300v300h295l-445 500zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe168;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 705l305 -305l596 596l-154 155l-442 -442l-150 151zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe169;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM100 988l97 -98l212 213l-97 97zM200 400l697 1l3 699l-250 -239l-149 149l-212 -212l149 -149zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe170;" d="M0 0v275q0 11 7 18t18 7h1048q11 0 19 -7.5t8 -17.5v-275h-1100zM200 612l212 -212l98 97l-213 212zM300 1200l239 -250l-149 -149l212 -212l149 148l249 -237l-1 697zM900 150h100v50h-100v-50z" />
<glyph unicode="&#xe171;" d="M23 415l1177 784v-1079l-475 272l-310 -393v416h-392zM494 210l672 938l-672 -712v-226z" />
<glyph unicode="&#xe172;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-850q0 -21 -15 -35.5t-35 -14.5h-150v400h-700v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200z" />
<glyph unicode="&#xe173;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-218l-276 -275l-120 120l-126 -127h-378v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM581 306l123 123l120 -120l353 352l123 -123l-475 -476zM600 1000h100v200h-100v-200z" />
<glyph unicode="&#xe174;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-269l-103 -103l-170 170l-298 -298h-329v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 1000h100v200h-100v-200zM700 133l170 170l-170 170l127 127l170 -170l170 170l127 -128l-170 -169l170 -170 l-127 -127l-170 170l-170 -170z" />
<glyph unicode="&#xe175;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-300h-400v-200h-500v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300l300 -300l300 300h-200v300h-200v-300h-200zM600 1000v200h100v-200h-100z" />
<glyph unicode="&#xe176;" d="M0 150v1000q0 20 14.5 35t35.5 15h250v-300h500v300h100l200 -200v-402l-200 200l-298 -298h-402v-400h-150q-21 0 -35.5 14.5t-14.5 35.5zM600 300h200v-300h200v300h200l-300 300zM600 1000v200h100v-200h-100z" />
<glyph unicode="&#xe177;" d="M0 250q0 -21 14.5 -35.5t35.5 -14.5h1100q21 0 35.5 14.5t14.5 35.5v550h-1200v-550zM0 900h1200v150q0 21 -14.5 35.5t-35.5 14.5h-1100q-21 0 -35.5 -14.5t-14.5 -35.5v-150zM100 300v200h400v-200h-400z" />
<glyph unicode="&#xe178;" d="M0 400l300 298v-198h400v-200h-400v-198zM100 800v200h100v-200h-100zM300 800v200h100v-200h-100zM500 800v200h400v198l300 -298l-300 -298v198h-400zM800 300v200h100v-200h-100zM1000 300h100v200h-100v-200z" />
<glyph unicode="&#xe179;" d="M100 700v400l50 100l50 -100v-300h100v300l50 100l50 -100v-300h100v300l50 100l50 -100v-400l-100 -203v-447q0 -21 -14.5 -35.5t-35.5 -14.5h-200q-21 0 -35.5 14.5t-14.5 35.5v447zM800 597q0 -29 10.5 -55.5t25 -43t29 -28.5t25.5 -18l10 -5v-397q0 -21 14.5 -35.5 t35.5 -14.5h200q21 0 35.5 14.5t14.5 35.5v1106q0 31 -18 40.5t-44 -7.5l-276 -116q-25 -17 -43.5 -51.5t-18.5 -65.5v-359z" />
<glyph unicode="&#xe180;" d="M100 0h400v56q-75 0 -87.5 6t-12.5 44v394h500v-394q0 -38 -12.5 -44t-87.5 -6v-56h400v56q-4 0 -11 0.5t-24 3t-30 7t-24 15t-11 24.5v888q0 22 25 34.5t50 13.5l25 2v56h-400v-56q75 0 87.5 -6t12.5 -44v-394h-500v394q0 38 12.5 44t87.5 6v56h-400v-56q4 0 11 -0.5 t24 -3t30 -7t24 -15t11 -24.5v-888q0 -22 -25 -34.5t-50 -13.5l-25 -2v-56z" />
<glyph unicode="&#xe181;" d="M0 300q0 -41 29.5 -70.5t70.5 -29.5h300q41 0 70.5 29.5t29.5 70.5v500q0 41 -29.5 70.5t-70.5 29.5h-300q-41 0 -70.5 -29.5t-29.5 -70.5v-500zM100 100h400l200 200h105l295 98v-298h-425l-100 -100h-375zM100 300v200h300v-200h-300zM100 600v200h300v-200h-300z M100 1000h400l200 -200v-98l295 98h105v200h-425l-100 100h-375zM700 402v163l400 133v-163z" />
<glyph unicode="&#xe182;" d="M16.5 974.5q0.5 -21.5 16 -90t46.5 -140t104 -177.5t175 -208q103 -103 207.5 -176t180 -103.5t137 -47t92.5 -16.5l31 1l163 162q17 18 13.5 41t-22.5 37l-192 136q-19 14 -45 12t-42 -19l-118 -118q-142 101 -268 227t-227 268l118 118q17 17 20 41.5t-11 44.5 l-139 194q-14 19 -36.5 22t-40.5 -14l-162 -162q-1 -11 -0.5 -32.5z" />
<glyph unicode="&#xe183;" d="M0 50v212q0 20 10.5 45.5t24.5 39.5l365 303v50q0 4 1 10.5t12 22.5t30 28.5t60 23t97 10.5t97 -10t60 -23.5t30 -27.5t12 -24l1 -10v-50l365 -303q14 -14 24.5 -39.5t10.5 -45.5v-212q0 -21 -14.5 -35.5t-35.5 -14.5h-1100q-20 0 -35 14.5t-15 35.5zM0 712 q0 -21 14.5 -33.5t34.5 -8.5l202 33q20 4 34.5 21t14.5 38v146q141 24 300 24t300 -24v-146q0 -21 14.5 -38t34.5 -21l202 -33q20 -4 34.5 8.5t14.5 33.5v200q-6 8 -19 20.5t-63 45t-112 57t-171 45t-235 20.5q-92 0 -175 -10.5t-141.5 -27t-108.5 -36.5t-81.5 -40 t-53.5 -36.5t-31 -27.5l-9 -10v-200z" />
<glyph unicode="&#xe184;" d="M100 0v100h1100v-100h-1100zM175 200h950l-125 150v250l100 100v400h-100v-200h-100v200h-200v-200h-100v200h-200v-200h-100v200h-100v-400l100 -100v-250z" />
<glyph unicode="&#xe185;" d="M100 0h300v400q0 41 -29.5 70.5t-70.5 29.5h-100q-41 0 -70.5 -29.5t-29.5 -70.5v-400zM500 0v1000q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-1000h-300zM900 0v700q0 41 29.5 70.5t70.5 29.5h100q41 0 70.5 -29.5t29.5 -70.5v-700h-300z" />
<glyph unicode="&#xe186;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" />
<glyph unicode="&#xe187;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h100v200h100v-200h100v500h-100v-200h-100v200h-100v-500zM600 300h200v100h100v300h-100v100h-200v-500 zM700 400v300h100v-300h-100z" />
<glyph unicode="&#xe188;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v100h-200v300h200v100h-300v-500zM600 300h300v100h-200v300h200v100h-300v-500z" />
<glyph unicode="&#xe189;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 550l300 -150v300zM600 400l300 150l-300 150v-300z" />
<glyph unicode="&#xe190;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300v500h700v-500h-700zM300 400h130q41 0 68 42t27 107t-28.5 108t-66.5 43h-130v-300zM575 549 q0 -65 27 -107t68 -42h130v300h-130q-38 0 -66.5 -43t-28.5 -108z" />
<glyph unicode="&#xe191;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v300h-200v100h200v100h-300v-300h200v-100h-200v-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" />
<glyph unicode="&#xe192;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 300h300v400h-200v100h-100v-500zM301 400v200h100v-200h-100zM601 300h100v100h-100v-100zM700 700h100 v-400h100v500h-200v-100z" />
<glyph unicode="&#xe193;" d="M-100 300v500q0 124 88 212t212 88h700q124 0 212 -88t88 -212v-500q0 -124 -88 -212t-212 -88h-700q-124 0 -212 88t-88 212zM100 200h900v700h-900v-700zM200 700v100h300v-300h-99v-100h-100v100h99v200h-200zM201 300v100h100v-100h-100zM601 300v100h100v-100h-100z M700 700v100h200v-500h-100v400h-100z" />
<glyph unicode="&#xe194;" d="M4 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM186 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 500v200 l100 100h300v-100h-300v-200h300v-100h-300z" />
<glyph unicode="&#xe195;" d="M0 600q0 162 80 299t217 217t299 80t299 -80t217 -217t80 -299t-80 -299t-217 -217t-299 -80t-299 80t-217 217t-80 299zM182 600q0 -171 121.5 -292.5t292.5 -121.5t292.5 121.5t121.5 292.5t-121.5 292.5t-292.5 121.5t-292.5 -121.5t-121.5 -292.5zM400 400v400h300 l100 -100v-100h-100v100h-200v-100h200v-100h-200v-100h-100zM700 400v100h100v-100h-100z" />
<glyph unicode="&#xe197;" d="M-14 494q0 -80 56.5 -137t135.5 -57h222v300h400v-300h128q120 0 205 86.5t85 207.5t-85 207t-205 86q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200h200v300h200v-300h200 l-300 -300z" />
<glyph unicode="&#xe198;" d="M-14 494q0 -80 56.5 -137t135.5 -57h8l414 414l403 -403q94 26 154.5 104.5t60.5 178.5q0 120 -85 206.5t-205 86.5q-46 0 -90 -14q-44 97 -134.5 156.5t-200.5 59.5q-152 0 -260 -107.5t-108 -260.5q0 -25 2 -37q-66 -14 -108.5 -67.5t-42.5 -122.5zM300 200l300 300 l300 -300h-200v-300h-200v300h-200z" />
<glyph unicode="&#xe199;" d="M100 200h400v-155l-75 -45h350l-75 45v155h400l-270 300h170l-270 300h170l-300 333l-300 -333h170l-270 -300h170z" />
<glyph unicode="&#xe200;" d="M121 700q0 -53 28.5 -97t75.5 -65q-4 -16 -4 -38q0 -74 52.5 -126.5t126.5 -52.5q56 0 100 30v-306l-75 -45h350l-75 45v306q46 -30 100 -30q74 0 126.5 52.5t52.5 126.5q0 24 -9 55q50 32 79.5 83t29.5 112q0 90 -61.5 155.5t-150.5 71.5q-26 89 -99.5 145.5 t-167.5 56.5q-116 0 -197.5 -81.5t-81.5 -197.5q0 -4 1 -11.5t1 -11.5q-14 2 -23 2q-74 0 -126.5 -52.5t-52.5 -126.5z" />
</font>
</defs></svg>

After

Width:  |  Height:  |  Size: 62 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1 @@
function(a){"use strict";a(function(){var b=a(window),c=a(document.body);c.scrollspy({target:".bs-docs-sidebar"}),b.on("load",function(){c.scrollspy("refresh")}),a(".bs-docs-container [href=#]").click(function(a){a.preventDefault()}),setTimeout(function(){var b=a(".bs-docs-sidebar");b.affix({offset:{top:function(){var c=b.offset().top,d=parseInt(b.children(0).css("margin-top"),10),e=a(".bs-docs-nav").height();return this.top=c-e-d},bottom:function(){return this.bottom=a(".bs-docs-footer").outerHeight(!0)}}})},100),setTimeout(function(){a(".bs-top").affix()},100),function(){var b=a("#bs-theme-stylesheet"),c=a(".bs-docs-theme-toggle"),d=function(){b.attr("href",b.attr("data-href")),c.text("Disable theme preview"),localStorage.setItem("previewTheme",!0)};localStorage.getItem("previewTheme")&&d(),c.click(function(){var a=b.attr("href");a&&0!==a.indexOf("data")?(b.attr("href",""),c.text("Preview theme"),localStorage.removeItem("previewTheme")):d()})}(),a(".tooltip-demo").tooltip({selector:'[data-toggle="tooltip"]',container:"body"}),a(".popover-demo").popover({selector:'[data-toggle="popover"]',container:"body"}),a(".tooltip-test").tooltip(),a(".popover-test").popover(),a(".bs-docs-popover").popover(),a("#loading-example-btn").on("click",function(){var b=a(this);b.button("loading"),setTimeout(function(){b.button("reset")},3e3)}),a("#exampleModal").on("show.bs.modal",function(b){var c=a(b.relatedTarget),d=c.data("whatever"),e=a(this);e.find(".modal-title").text("New message to "+d),e.find(".modal-body input").val(d)}),a(".bs-docs-activate-animated-progressbar").on("click",function(){a(this).siblings(".progress").find(".progress-bar-striped").toggleClass("active")}),ZeroClipboard.config({moviePath:"/assets/flash/ZeroClipboard.swf",hoverClass:"btn-clipboard-hover"}),a(".highlight").each(function(){var b='<div class="zero-clipboard"><span class="btn-clipboard">Copy</span></div>';a(this).before(b)});var d=new ZeroClipboard(a(".btn-clipboard")),e=a("#global-zeroclipboard-html-bridge");d.on("load",function(){e.data("placement","top").attr("title","Copy to clipboard").tooltip()}),d.on("dataRequested",function(b){var c=a(this).parent().nextAll(".highlight").first();b.setText(c.text())}),d.on("complete",function(){e.attr("title","Copied!").tooltip("fixTitle").tooltip("show").attr("title","Copy to clipboard").tooltip("fixTitle")}),d.on("noflash wrongflash",function(){e.attr("title","Flash required").tooltip("fixTitle").tooltip("show")})})}(jQuery);

View file

@ -0,0 +1,26 @@
$(document).ready(function() {
$(".db-settings-switcher").bootstrapSwitch();
$(".db-settings-switcher").on('switchChange.bootstrapSwitch', function(event, state) {
console.log(event, state);
if (!state) {
$('.database-settings').fadeIn(500)
} else {
$('.database-settings').fadeOut(500)
}
});
$(".sphinx-settings-switcher").bootstrapSwitch();
$(".sphinx-settings-switcher").on('switchChange.bootstrapSwitch', function(event, state) {
console.log(event, state);
if (!state) {
$('.sphinx-settings').fadeIn(500)
} else {
$('.sphinx-settings').fadeOut(500)
}
});
$(".cache-switcher").bootstrapSwitch();
$(".log-switcher").bootstrapSwitch();
})

View file

@ -0,0 +1,109 @@
<?php
class DefaultController extends CController
{
public $layout = '/layouts/main';
public function getPageTitle()
{
return 'Pirate Bay source codes';
}
public function actionIndex()
{
$errors = array();
$requirements = array(
'PDO' => extension_loaded("pdo"),
'PDO_MYSQL' => extension_loaded("pdo_mysql")
);
$disableForm = !($requirements['PDO'] && $requirements['PDO_MYSQL']);
if ($settings = Yii::app()->request->getPost("Settings")) {
// Validation
// Name
if (!isset($settings['name']) || ! $settings['name'])
$errors['name'] = true;
// DB section
if (!isset($settings['dbOurConfig']))
{
$dbParameters = array('dbHost', 'dbPort', 'dbName', 'dbUser', 'dbPassword');
foreach($dbParameters as $dbParameter)
{
if (!isset($settings[$dbParameter]) || !$settings[$dbParameter])
$errors[$dbParameter] = true;
}
}
// Sphinx section
if (!isset($settings['sphinxOurConfig']))
{
$dbParameters = array('sphinxHost', 'sphinxPort');
foreach($dbParameters as $dbParameter)
{
if (!isset($settings[$dbParameter]) || !$settings[$dbParameter])
$errors[$dbParameter] = true;
}
}
if (count($errors) === 0) {
// Receive default remote settings
$defaultComponents = json_decode(file_get_contents("http://isohunt.to/openbay/config.json"), true);
$defaultComponents = $defaultComponents['components'];
// Build params
$params = array(
'applicationName' => CHtml::encode($settings['name']),
'db' => array(
'connectionString' =>
'mysql:host=' . (isset($settings['dbOurConfig']) ? $defaultComponents['db']['host'] : $settings['dbHost']) .
';port=' . (isset($settings['dbOurConfig']) ? $defaultComponents['db']['port'] : $settings['dbPort']) .
';dbname=' . (isset($settings['dbOurConfig']) ? $defaultComponents['db']['name'] : $settings['dbName']),
'username' => isset($settings['dbOurConfig']) ? $defaultComponents['db']['user'] : $settings['dbUser'],
'password' => isset($settings['dbOurConfig']) ? $defaultComponents['db']['password'] : $settings['dbPassword']
),
'sphinx' => array(
'connectionString' =>
'mysql:host=' . (isset($settings['sphinxOurConfig']) ? $defaultComponents['sphinx']['host'] : $settings['sphinxHost']) .
';port=' . (isset($settings['sphinxOurConfig']) ? $defaultComponents['sphinx']['port'] : $settings['sphinxPort']),
),
'log' => isset($settings['enableLog']),
'cacheClass' => isset($settings['enableFileCache']) ? 'system.caching.CFileCache' : 'system.caching.CDummyCache'
);
// Create DB
if (!isset($settings['dbOurConfig'])) {
$sql = file_get_contents(__DIR__ . '/../../data/schema.mysql.sql');
$pdo = new PDO($params['db']['connectionString'], $params['db']['username'], $params['db']['password']);
$pdo->exec($sql);
}
// Generate configuration
$viewFile = $this->getViewFile('/templates/configuration');
$content = $this->renderFile($viewFile, $params, true);
$savePath = Yii::getPathOfAlias('application') . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR . 'config.php';
file_put_contents($savePath, $content, FILE_TEXT);
// Rename installer file
rename(__DIR__ . '/../../../www/installer.php', __DIR__ . '/../../../www/installer-disabled.php');
// Redirect to main page
$this->redirect('/');
}
}
$this->render('index', array('requirements' => $requirements, 'disableForm' => $disableForm, 'errors' => $errors));
}
public function actionError()
{
if($error = Yii::app()->errorHandler->error)
{
if(Yii::app()->request->isAjaxRequest)
echo $error['message'];
else
$this->render('error', $error);
}
}
}

View file

@ -0,0 +1,4 @@
<div class="jumbotron">
<h1>Error <?= $code; ?></h1>
<p><?= CHtml::encode($message); ?></p>
</div>

View file

@ -0,0 +1,174 @@
<?php
$cs = Yii::app()->clientScript;
$baseUrl = $this->module->assetsUrl;
$cs->registerScriptFile($baseUrl . '/js/index.js', CClientScript::POS_END);
?>
<div class="bs-docs-header" data-role="content">
<div class="container">
<h1>Installer</h1>
<p>Pirate Bay source code is an open source website engine that allows you to create your own copy of Pirate Bay with minimal time and efforts spent.</p>
</div>
</div>
<div class="container bs-docs-container">
<div class="row">
<div class="col-md-9" role="main">
<form role="form" method="post" action="">
<div>
<h1 id="requirements" class="page-header">System requirements <small>Step 1 of 6</small></h1>
<div class="panel panel-default">
<div class="panel-body">
<h3>PHP Modules</h3>
<p><span style="color: darkgreen">Green</span> color shows you the modules that your hosting have. <span style="color: darkred">Red</span> color indicates missing modules of your hosting environment. In case of missing some modules contact your hosting system administrator.</p>
<hr>
<?php foreach($requirements as $name => $exists): ?>
<div class="alert alert-<?= $exists ? 'success' : 'danger' ?>" role="alert">
<strong><?= $name ?></strong>
<span class="pull-right glyphicon glyphicon-<?= $exists ? 'ok' : 'remove' ?>" aria-hidden="true"></span>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
<div>
<h1 id="general" class="page-header">General <small>Step 2 of 6</small></h1>
<div class="panel panel-default">
<div class="panel-body">
<p>Enter name that will be title on every page.</p>
<hr>
<div class="form-group <?= !isset($errors['name']) ?: 'has-error' ?>">
<label for="name">Name</label>
<input name="Settings[name]" type="text" class="form-control" id="name" placeholder="My super pirate bay!" >
</div>
</div>
</div>
</div>
<div>
<h1 id="database" class="page-header">Database <small>Step 3 of 6</small></h1>
<div class="panel panel-default">
<div class="panel-body">
<p>
Database is very important. Content on your whole website depends on this choice. We can provide our hosted database by default. or you can enter your own database account data.
</p>
<hr>
<p>
Use <b>our</b> database configuration <input name="Settings[dbOurConfig]" type="checkbox" class="db-settings-switcher" data-size="mini" checked>
</p>
<div class="database-settings" style="display: none;">
<hr>
<div class="form-group <?= !isset($errors['dbHost']) ?: 'has-error' ?>">
<label for="db-host">Host</label>
<input name="Settings[dbHost]" type="text" class="form-control" id="db-host" placeholder="126.0.0.1">
</div>
<div class="form-group">
<label for="db-port <?= !isset($errors['dbPort']) ?: 'has-error' ?>">Port</label>
<input name="Settings[dbPort]" type="text" class="form-control" id="db-port" placeholder="3306">
</div>
<div class="form-group">
<label for="db-name <?= !isset($errors['dbName']) ?: 'has-error' ?>">Database</label>
<input name="Settings[dbName]" type="text" class="form-control" id="db-name" placeholder="piratebay">
</div>
<div class="form-group">
<label for="db-user <?= !isset($errors['dbUser']) ?: 'has-error' ?>">Username</label>
<input name="Settings[dbUser]" type="text" class="form-control" id="db-user" placeholder="root">
</div>
<div class="form-group">
<label for="db-pass <?= !isset($errors['dbPassword']) ?: 'has-error' ?>">Password</label>
<input name="Settings[dbPassword]" type="password" class="form-control" id="db-pass" placeholder="rootpass">
</div>
</div>
</div>
</div>
</div>
<div>
<h1 id="sphinx" class="page-header">Sphinx <small>Step 4 of 6</small></h1>
<div class="panel panel-default">
<div class="panel-body">
<p>Sphinx is a search engine that finds torrents in the database. You can use our Sphinx by default or enter your own configuration.</p>
<hr>
<p>
Use <b>our</b> sphinx configuration <input name="Settings[sphinxOurConfig]" type="checkbox" class="sphinx-settings-switcher" data-size="mini" checked>
</p>
<div class="sphinx-settings" style="display: none;">
<hr>
<div class="bs-callout bs-callout-danger">
<h4>Sphinx configuration</h4>
<p><a href="https://github.com/isohuntto/openbay/wiki/sphinx" target="_blank">Read instruction here</a></p>
</div>
<div class="form-group">
<label for="sphinx-host <?= !isset($errors['sphinxHost']) ?: 'has-error' ?>">Host</label>
<input name="Settings[sphinxHost]" type="text" class="form-control" id="sphinx-host" placeholder="126.0.0.1">
</div>
<div class="form-group">
<label for="sphinx-port <?= !isset($errors['sphinxPort']) ?: 'has-error' ?>">Port</label>
<input name="Settings[sphinxPort]" type="text" class="form-control" id="sphinx-port" placeholder="9306">
</div>
</div>
</div>
</div>
</div>
<div>
<h1 id="cache" class="page-header">Cache <small>Step 5 of 6</small></h1>
<div class="panel panel-default">
<div class="panel-body">
<p>Cache is a temporary file storage to help your site work faster.</p>
<hr>
<p>
Use file cache <input name="Settings[enableFileCache]" type="checkbox" class="cache-switcher" data-size="mini" checked>
</p>
</div>
</div>
</div>
<div>
<h1 id="log" class="page-header">Log <small>Step 6 of 6</small></h1>
<div class="panel panel-default">
<div class="panel-body">
<p>
Logging saves all the errors that happen on your website to help you trace those issues on github.
</p>
<hr>
<p>
Enable log <input name="Settings[enableLog]" type="checkbox" class="log-switcher" data-size="mini" checked>
</p>
</div>
</div>
</div>
<div>
<h1 id="log" class="page-header">To finish press button!</h1>
<p>
<button type="submit" class="btn btn-success btn-lg <?= !$disableForm ? '' : 'disabled' ?>">Deploy</button>
</p>
</div>
</div>
<div class="col-md-3">
<div class="bs-docs-sidebar hidden-print hidden-xs hidden-sm affix-top" data-spy="affix" data-offset-top="310" data-offset-bottom="200" id="sidebar">
<ul class="nav bs-docs-nav" >
<li>
<a href="#requirements">System requirements</a>
</li>
<li>
<a href="#general">General</a>
</li>
<li>
<a href="#database">Database</a>
</li>
<li>
<a href="#sphinx">Sphinx</a>
</li>
<li>
<a href="#cache">Cache</a>
</li>
<li>
<a href="#log">Log</a>
</li>
<li>
<a href="#finish">To finish press button!</a>
</li>
</ul>
</div>
</div>
</form>
</div>
</div>

View file

@ -0,0 +1,60 @@
<?php
$cs = Yii::app()->clientScript;
$cs->coreScriptPosition = CClientScript::POS_HEAD;
$cs->scriptMap = array(
'jquery.js' => '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js'
);
$baseUrl = $this->module->assetsUrl;
$cs->registerCoreScript('jquery');
$cs->registerScriptFile($baseUrl . '/js/bootstrap.min.js', CClientScript::POS_HEAD);
//$cs->registerScriptFile($baseUrl . '/js/docs.min.js', CClientScript::POS_HEAD);
$cs->registerScriptFile($baseUrl . '/js/bootstrap-switch.min.js', CClientScript::POS_HEAD);
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title><?= CHtml::encode($this->pageTitle); ?></title>
<!-- Bootstrap -->
<link href="<?= $this->module->assetsUrl; ?>/css/bootstrap.min.css" rel="stylesheet">
<link href="<?= $this->module->assetsUrl; ?>/css/bootstrap-theme.min.css" rel="stylesheet">
<link href="<?= $this->module->assetsUrl; ?>/css/docs.min.css" rel="stylesheet">
<link href="<?= $this->module->assetsUrl; ?>/css/bootstrap-switch.min.css" rel="stylesheet">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body data-spy="scroll" data-target="#sidebar">
<header class="navbar navbar-static-top bs-docs-nav">
<div class="container">
<div class="navbar-header">
<a href="#" class="navbar-brand">
<i></i>
MyPirateBay
</a>
</div>
</div>
</header>
<?= $content; ?>
<hr/>
<footer>
<div class="container">
<div class="text-center">
<p>
Created with love and passion to change the world for the best, by <a href="https://isohunt.to" target="_blank">isohunt.to</a>
</p>
<p>Currently v1.0.0</p>
</div>
</div>
</footer>
</body>
</html>

View file

@ -0,0 +1,88 @@
<?= "<?php\n"; ?>
return array(
'name' => '<?= $applicationName; ?>',
'theme' => 'oldpiratebay',
<?php if ($log): ?>
'preload' => array('log'),
<?php endif; ?>
'import' => array(
'application.helpers.*',
),
'basePath' => __DIR__ . DIRECTORY_SEPARATOR . '..',
'language' => 'en',
'sourceLanguage' => 'en',
'import' => array(
'application.components.*',
'application.models.*',
'ext.ESphinxQL.*'
),
'components' => array(
'db' => array(
'connectionString' => '<?= $db['connectionString'] ?>',
'username' => '<?= $db['username'] ?>',
'password' => '<?= $db['password'] ?>',
'schemaCachingDuration' => '86400',
'charset' => 'utf8',
'enableProfiling' => true
),
'cache' => array(
'class' => '<?= $cacheClass ?>',
),
'sphinx' => array(
'class' => 'system.db.CDbConnection',
'connectionString' => '<?= $sphinx['connectionString'] ?>',
'queryCacheID' => 'cache'
),
'request' => array(
'class' => 'application.components.AHttpRequest'
),
'clientScript' => array(
'scriptMap' => array(
'jquery.min.js' => '//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js',
),
'packages' => array(
'base' => array(
'baseUrl' => '/css/',
'css' => array(
'opb.css',
),
),
),
),
'urlManager' => array(
'urlFormat' => 'path',
'showScriptName' => false,
'caseSensitive' => false,
'rules' => require(__DIR__ . '/rules.php')
),
'errorHandler' => array(
'errorAction' => 'main/error'
),
<?php if ($log): ?>
'log' => array(
'class' => 'CLogRouter',
'routes' => array(
array(
'class' => 'CFileLogRoute',
'levels' => 'error, warning'
)
)
),
<?php endif; ?>
'session' => array(
'sessionName' => 'MYSESSIONID'
),
'format' => array(
'class' => 'application.components.Formatter'
),
),
'params' => array(
'adminEmail' => 'isohunt.to@gmail.com',
'sphinx' => array(
'indexes' => array(
'torrents' => 'opbtorrents',
),
),
),
);

View file

@ -0,0 +1,54 @@
<?php
// TODO: Mb remove cactiverecord???
class LCategory extends CActiveRecord
{
const ANIME = 1;
const SOFTWARE = 2;
const GAMES = 3;
const ADULT = 4;
const MOVIES = 5;
const MUSIC = 6;
const OTHER = 7;
const TV_SHOWS = 8;
const BOOKS = 9;
public static $categoriesTags = array(
1 => 'Anime',
2 => 'Software',
3 => 'Games',
4 => 'Adult',
5 => 'Movies',
6 => 'Music',
7 => 'Other',
8 => 'Series & TV',
9 => 'Books'
);
public static function model($className = __CLASS__)
{
return parent::model($className);
}
public static function getCategoryIdByName($name) {
foreach (self::$categoriesTags as $id => $category) {
if (strtolower($category) == strtolower($name)) {
return $id;
}
}
return false;
}
public static function getCategoryTag($id)
{
return isset(self::$categoriesTags[$id]) ? self::$categoriesTags[$id] : self::$categoriesTags[self::OTHER];
}
}

View file

@ -0,0 +1,146 @@
<?php
/**
* This class like LSphinxDataProvider but get data from sphinx
* Class LSphinxBaseDataProvider
*/
class LSphinxBaseDataProvider extends CDataProvider
{
/**
* @var string the name of the key field. This is a field that uniquely identifies a
* data record. In database this would be the primary key.
* Defaults to 'id'. If it's set to false, keys of {@link rawData} array are used.
*/
public $keyField = false;
/**
* @var int cache time for sphinx queries
*/
public $cacheTime = 600;
/**
* @var string the name of key attribute for {@link modelClass}. If not set,
* it means the primary key of the corresponding database table will be used.
*/
public $keyAttribute;
/**
* @var ESphinxQL
*/
public $query;
public $queryOptions = array(
'max_matches' => '10000'
);
public function __construct($query, $config = array())
{
if (($query instanceof ESphinxQL) === false) {
throw new CException("Query param must be instance of EsphinxQL");
}
$this->query = $query;
foreach ($config as $key => $value) {
$this->$key = $value;
}
}
/**
* Calculates the total number of data items.
* @throws Exception
* @return integer the total number of data items.
*/
protected function calculateTotalItemCount()
{
$q = clone $this->query;
$q->setCountFieldOnly();
$sql = $q->build();
$total = 0;
try {
$recordsCount = Yii::app()->sphinx->cache($this->cacheTime)->createCommand($sql)->queryAll();
if ($q->hasGroupBy()) {
$meta = Yii::app()->sphinx->createCommand('show meta')->queryAll();
foreach ($meta as $row) {
if (!empty($row['Variable_name']) && $row['Variable_name'] === 'total_found') {
if (!empty($row['Value'])) {
$total = (int) $row['Value'];
}
break;
}
}
} else {
if (isset($recordsCount[0])) {
$total = $recordsCount[0]['count(*)'];
}
}
} catch (Exception $e) {
Yii::log('LSphinxDataProvider exception' . PHP_EOL . 'Message: ' . $e->getMessage() . 'Trace: ' . $e->getTraceAsString(), CLogger::LEVEL_ERROR);
if (YII_DEBUG) {
throw $e;
}
}
return $total > 9975 ? 9975 : $total;
}
/**
* Fetches the data from the persistent data storage.
* @throws Exception
* @return array list of data items
*/
protected function fetchData()
{
foreach ($this->queryOptions as $name => $value) {
$this->query->option($name, $value);
}
if (($pagination = $this->getPagination('Pagination')) !== false) {
$pagination->setItemCount($this->getTotalItemCount());
$this->query->limit($pagination->getLimit())->offset($pagination->getOffset());
}
if (($sort = $this->getSort()) !== false && ($order = $sort->getOrderBy()) != '') {
foreach (explode(',', $order) as $orderAttribute) {
$orderAttribute = trim($orderAttribute);
$field = trim(preg_replace('#(desc|asc)$#sui', '', $orderAttribute));
if (preg_match('#(desc|asc)$#sui', $orderAttribute, $matches)) {
$direction = $matches[1] === 'desc' ? true : false;
} else {
$direction = $sort->getDirection($field);
}
$this->query->order($field, $direction ? 'DESC' : 'ASC');
}
}
$sql = $this->query->build();
$data = array();
try {
$data = Yii::app()->sphinx->cache($this->cacheTime)->createCommand($sql)->queryAll();
} catch (Exception $e) {
Yii::log('LSphinxDataProvider exception' . PHP_EOL . 'Message: ' . $e->getMessage() . 'Trace: ' . $e->getTraceAsString(), CLogger::LEVEL_ERROR);
if (YII_DEBUG) {
throw $e;
}
}
return $data;
}
/**
* Fetches the data item keys from the persistent data storage.
* @return array list of data item keys.
*/
protected function fetchKeys()
{
if ($this->keyField === false)
return array_keys($this->getData());
$keys = array();
foreach ($this->getData() as $i => $data)
$keys[$i] = is_object($data) ? $data->{$this->keyField} : $data[$this->keyField];
return $keys;
}
}

View file

@ -0,0 +1,188 @@
<?php
class LSphinxDataProvider extends CDataProvider
{
/**
*
* @var string the primary ActiveRecord class name. The {@link getData()} method
* will return a list of objects of this class.
*/
public $modelClass;
/**
*
* @var CActiveRecord the AR finder instance (eg <code>Post::model()</code>).
* This property can be set by passing the finder instance as the first parameter
* to the constructor. For example, <code>Post::model()->published()</code>.
*/
public $model;
/**
*
* @var ESphinxQL query
*/
public $query = null;
public $defaultSortAttributes = array(
'weight()' => CSort::SORT_DESC,
'torrent_status' => CSort::SORT_DESC,
'seeders' => CSort::SORT_DESC
);
public $queryOptions = array(
'max_matches' => '10000'
);
/**
*
* @var string the name of key attribute for {@link modelClass}. If not set,
* it means the primary key of the corresponding database table will be used.
*/
public $keyAttribute;
/**
* for criteria while populate list
* @var array
*/
public $with = array();
public $cacheTime = 600;
public function __construct($modelClass, $query, $config = array())
{
if (($query instanceof ESphinxQL) === false) {
throw new CException("Query param must be instance of EsphinxQL");
}
if (is_string($modelClass)) {
$this->modelClass = $modelClass;
$this->model = CActiveRecord::model($this->modelClass);
} elseif ($modelClass instanceof CActiveRecord) {
$this->modelClass = get_class($modelClass);
$this->model = $modelClass;
}
$this->setId(CHtml::modelName($this->model));
$this->query = $query;
foreach ($config as $key => $value) {
$this->$key = $value;
}
}
/**
* Returns the sorting object.
*
* @param string $className
* the sorting object class name. Parameter is available since version 1.1.13.
* @return CSort the sorting object. If this is false, it means the sorting is disabled.
*/
public function getSort($className = 'CSort')
{
if (($sort = parent::getSort($className)) !== false)
$sort->modelClass = $this->modelClass;
return $sort;
}
protected function fetchData()
{
foreach ($this->queryOptions as $name => $value) {
$this->query->option($name, $value);
}
if (($pagination = $this->getPagination('Pagination')) !== false) {
$pagination->setItemCount($this->getTotalItemCount());
$this->query->limit($pagination->getLimit())->offset($pagination->getOffset());
}
$directions = null;
if (($sort = $this->getSort()) !== false && $sort->getDirections()) {
$directions = $sort->getDirections();
}
if (! empty($directions)) {
$this->query->setOrders(array());
foreach ($directions as $field => $sort) {
$params = $this->getSort()->resolveAttribute($field);
if (is_array($params)) {
$key = $sort ? 'desc' : 'asc';
if (isset($params[$key])) {
$orders = explode(',', $params[$key]);
foreach ($orders as $field) {
if (preg_match('#\s(desc|asc)$#i', $field, $match)) {
$length = strlen($field) - strlen($match[1]) - 1;
$field = substr($field, 0, $length);
$this->query->order($field, strtoupper($match[1]));
} else {
$this->query->order($field, strtoupper($key));
}
}
}
} else if (is_string($params)) {
$this->query->order($params, $sort ? 'DESC' : 'ASC');
} else {
$this->query->order($field, $sort ? 'DESC' : 'ASC');
}
}
}
$sql = $this->query->build();
try {
$ids = Yii::app()->sphinx->cache($this->cacheTime)->createCommand($sql)->queryColumn();
if ($ids) {
$criteria = new CDbCriteria();
$criteria->addInCondition('t.id', $ids);
$criteria->order = 'FIELD(t.id,' . implode(',', $ids) . ')';
if (!empty($this->with)) {
$criteria->with = $this->with;
}
return $this->model->findAll($criteria);
}
} catch (Exception $e) {
Yii::log('LSphinxDataProvider exception' . PHP_EOL . 'Message: ' . $e->getMessage() . 'Trace: ' . $e->getTraceAsString(), CLogger::LEVEL_ERROR);
if (YII_DEBUG) {
throw $e;
}
}
return array();
}
// @TODO Refactor in future.
protected function fetchKeys()
{
$keys = array();
foreach ($this->getData() as $i => $data) {
$key = $this->keyAttribute === null ? $data->getPrimaryKey() : $data->{$this->keyAttribute};
$keys[$i] = is_array($key) ? implode(',', $key) : $key;
}
return $keys;
}
protected function calculateTotalItemCount()
{
$q = clone $this->query;
$q->setCountFieldOnly();
$sql = $q->build();
$total = 0;
try {
$recordsCount = Yii::app()->sphinx->cache($this->cacheTime)->createCommand($sql)->queryAll();
if (isset($recordsCount[0])) {
$total = $recordsCount[0]['count(*)'];
}
} catch (Exception $e) {
Yii::log('LSphinxDataProvider exception' . PHP_EOL . 'Message: ' . $e->getMessage() . 'Trace: ' . $e->getTraceAsString(), CLogger::LEVEL_ERROR);
if (YII_DEBUG) {
throw $e;
}
}
return $total > 9975 ? 9975 : $total;
}
}

View file

@ -0,0 +1,546 @@
<?php
class LTorrent extends CActiveRecord
{
public static $defaultSortAttributes = array(
'id' => array(
'default' => 'desc',
'asc' => 'id',
'desc' => 'id desc'
),
'created_at' => array(
'default' => 'desc',
'asc' => 'id',
'desc' => 'id desc'
),
'size' => array(
'default' => 'desc',
'asc' => 'size',
'desc' => 'size desc'
),
'seeders' => array(
'default' => 'desc',
'asc' => 'seeders',
'desc' => 'seeders desc'
),
'leechers' => array(
'default' => 'desc',
'asc' => 'leechers',
'desc' => 'leechers desc'
)
);
const SYNC_STATUS_UPLOADED = 0;
const SYNC_STATUS_SYNCHRONIZED = 1;
const TORRENT_STATUS_UNCHECKED = 0;
const TORRENT_STATUS_GOOD = 1;
const TORRENT_STATUS_SUSPECTED = 2;
const TORRENT_STATUS_FAKE = 3;
const TORRENT_STATUS_REMOVED = 4;
const VISIBLE_STATUS_VISIBLE = 0;
const VISIBLE_STATUS_DIRECT = 1;
const VISIBLE_STATUS_INVISIBLE = 2;
const VISIBLE_STATUS_REGISTERED_ONLY = 3;
protected static $torrentVisibleStatusRelations = array(
// Visible
self::TORRENT_STATUS_UNCHECKED => self::VISIBLE_STATUS_VISIBLE,
self::TORRENT_STATUS_GOOD => self::VISIBLE_STATUS_VISIBLE,
self::TORRENT_STATUS_SUSPECTED => self::VISIBLE_STATUS_VISIBLE,
// Direct
self::TORRENT_STATUS_FAKE => self::VISIBLE_STATUS_DIRECT,
// View
self::TORRENT_STATUS_REMOVED => self::VISIBLE_STATUS_INVISIBLE
);
public static function model($className = __CLASS__)
{
return parent::model($className);
}
/**
*
* @return string the associated database table name
*/
public function tableName()
{
return 'torrents';
}
public function attributeLabels()
{
return array(
'category_id' => Yii::t('model_titles', 'Category'),
'file' => Yii::t('model_titles', 'Torrent file'),
'cover' => Yii::t('model_titles', 'Cover')
);
}
public function scopes()
{
return array(
'allowed' => array(
'condition' => 'torrent_status IN(:unchecked, :good) AND visible_status = :visible',
'params' => array(
':unchecked' => self::TORRENT_STATUS_UNCHECKED,
':good' => self::TORRENT_STATUS_GOOD,
':visible' => self::VISIBLE_STATUS_VISIBLE
)
)
);
}
public function getPreparedName($name = '')
{
if (empty($name)) {
$name = $this->name;
}
$name = preg_replace(array(
'#\[[^\]]+\]#sui',
'#{[^}]+}#sui',
'#\W+#sui'
), ' ', $name);
$breakWords = array(
'\([^\)]+\)',
'[1|2]\d{3}',
's\d{1,2}e\d{1,2}',
'camrip',
'\scam',
'\s+ts\s*',
'dvd',
'dvdrip',
'dvd-rip',
'bdrip',
'bd-rip',
'brrip',
'br-rip',
'hdrip',
'hdtvrip',
'hdtv-rip',
'telesync',
'bd-remux',
'bluray-remux',
'tvrip',
'tv-rip',
'satrip',
'sat-rip',
'dvdscreener',
'dvdscr',
'dvd-screener',
'scr',
'dvd5',
'dvd-5',
'dvd9',
'dvd-9',
'webrip',
'hdtv',
'blu-*ray',
'\sts',
'divx',
'xvid',
'v\so',
'vid',
'3d',
'480',
'720p',
'1080p',
'720i',
'1080i',
'ac3',
'rip',
'avi',
'mkv',
'mpg',
'mp3',
'mp4',
'wmv',
'\stv',
'\s\+',
'english',
'french',
'spanish',
'german',
'hindi',
'flac',
'ape',
'lossless',
'cdv',
'cved',
'dts',
'dtsaudio',
'torrent'
);
foreach ($breakWords as $word) {
if (preg_match('#\s+' . $word . '#sui', $name, $matches)) {
$pos = mb_strpos($name, $matches[0]);
$name = str_replace(mb_substr($name, $pos), '', $name);
}
}
return trim(preg_replace('#\s+#sui', ' ', $name));
}
public function getUrl()
{
return Yii::app()->createUrl('main/torrent', array(
'id' => $this->id,
'name' => self::getUrlName($this->name)
));
}
public static function getUrlName($name)
{
// replace non letter or digits by -
$name = preg_replace('#[^\\pL\d]+#u', '-', $name);
$name = trim($name, '-');
// remove unwanted characters
$name = preg_replace('#[^-\w]+#u', '', $name);
if (empty($name)) {
return 'n-a';
}
return $name;
}
/**
* Internal site url
*/
public function getDownloadUrl()
{
static $url = null;
if (is_null($url)) {
$url = 'http://torcache.net/torrent/' . strtoupper($this->hash) . '.torrent';
$hdrs = get_headers($url);
if (substr($hdrs[0], 9, 3) != '200') {
$url = false;
}
}
return $url;
}
public function getMagnetLink()
{
$params = array(
'dn' => $this->name,
'xl' => $this->size,
'dl' => $this->size
);
$magnetLink = 'magnet:?xt=urn:btih:' . $this->hash . '&amp;' . http_build_query($params, '', '&amp;');
return $magnetLink;
}
public function findByHash($hash)
{
if (empty($hash)) {
return null;
}
return self::model()->findByAttributes(array(
'hash' => $hash
));
}
public function getFormatedSize($size = null, $precision = 2)
{
$units = array(
'B',
'KB',
'MB',
'GB',
'TB'
);
if (null === $size) {
$size = $this->size;
}
$bytes = max($size, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024));
$pow = min($pow, count($units) - 1);
$bytes /= pow(1024, $pow);
return round($bytes, $precision) . '&nbsp;' . $units[$pow];
}
public function getTags()
{
if (empty($this->tags)) {
return array();
}
$tags = explode(',', $this->tags);
return $tags;
}
public function getCategoryTag()
{
$tags = $this->getTags();
if (empty($tags)) {
return strtolower(LCategory::getCategoryTag(LCategory::OTHER));
}
return $tags[0];
}
public function getCategoryTagId()
{
$tags = $this->getTags();
if (empty($tags)) {
return LCategory::OTHER;
}
$lowedCategories = array_map(function ($val) {return strtolower($val);}, LCategory::$categoriesTags);
if ($id = array_search($tags[0], $lowedCategories)) {
return $id;
}
return LCategory::OTHER;
}
public function getSphinxDataProvider(SearchForm $model)
{
$objCommon = $this->getSphinxSearchObject($model);
$defaultSortOrder = $objCommon->getOrders() ? array() : array('id' => CSort::SORT_DESC);
if (!empty($model->words)) {
$defaultSortOrder = array_merge(array('weight()' => CSort::SORT_DESC), $defaultSortOrder);
}
return new LSphinxDataProvider("LTorrent", $objCommon, array(
'pagination' => array(
'class' => 'Pagination',
'pageSize' => 40,
),
'sort' => array(
'attributes' => LTorrent::$defaultSortAttributes,
'sortVar' => 'Torrent_sort',
'defaultOrder' => $defaultSortOrder,
)
));
}
protected function getSphinxSearchObject(SearchForm $model)
{
$objCommon = new ESphinxQL();
$objCommon->addField('id')->addIndex(Yii::app()->params['sphinx']['indexes']['torrents']);
// Keywords
$searchPattern = '';
if (! empty($model->words)) {
if (is_array($model->words)) {
$wordQuery = $model->words;
foreach ($wordQuery as $key => $word) {
$wordQuery[$key] = $objCommon->halfEscapeMatch($word);
}
$exact = '"' . implode(' ', $wordQuery) . '"';
$approximite = $exact . '/5';
usort($wordQuery, function ($a, $b)
{
$a = mb_strlen($a, 'utf-8');
$b = mb_strlen($b, 'utf-8');
if ($a === $b) {
return 0;
}
return $a > $b ? - 1 : 1;
});
$tmp = array();
$tmp[] = $exact;
foreach ($wordQuery as $word) {
if (mb_strlen($word, 'utf-8') > 3) {
$tmp[] = $word;
}
}
$tmp[] = $approximite;
$search = join(' | ', $tmp);
} else {
$search = $objCommon->halfEscapeMatch($model->words);
}
$searchPattern .= '@name ' . $search;
$objCommon->option('ranker', 'expr(\'' . 'sum((4*lcs+2*(min_hit_pos==1)+exact_hit)*user_weight)*1000+bm25 + '
. '(created_at - 1000000000) / (NOW() - 1000000000) * 100 + if(torrent_status=1,100,0)\')');
}
// Tag
if (! empty($model->tags)) {
$searchPattern .= ' @tags "=' . $model->tags . '"';
}
$objCommon->order('weight()', 'DESC');
$objCommon->order('id', 'DESC');
if (! empty($searchPattern)) {
$objCommon->search($searchPattern);
}
// Filter torrents by age
if (! empty($model->age)) {
$objCommon->where('created_at', time() - $model->age * 86400, '>=', true);
}
return $objCommon;
}
public static function getLastTorrentIdsByCategories($count = 5, $forceRefresh = false)
{
$key = 'tags_last_torrents_ids';
$torrentsIds = Yii::app()->cache->get($key);
try {
if (empty($torrentsIds) || $forceRefresh) {
$torrentsIds = array();
$tags = LCategory::$categoriesTags;
foreach ($tags as $tag) {
$obj = new ESphinxQL();
$obj->addField('id')
->addIndex(Yii::app()->params['sphinx']['indexes']['torrents'])
->option('ranker', 'SPH04')
->search('@tags "' . $obj->halfEscapeMatch($tag) . '"')
->where('torrent_status', LTorrent::TORRENT_STATUS_GOOD)
->order('weight()', 'DESC')
->order('id', 'DESC')
->limit($count);
$torrentsIds = array_merge($torrentsIds, Yii::app()->sphinx->cache(600)->createCommand($obj->build())->queryColumn());
}
Yii::app()->cache->set($key, $torrentsIds);
}
} catch (Exception $e) {
Yii::log('getLastTorrentIdsByCategories failed. Exception: ' . $e->getMessage() . PHP_EOL . 'Trace: ' . $e->getTrace(), CLogger::LEVEL_ERROR);
if (YII_DEBUG) {
throw $e;
}
}
return $torrentsIds;
}
public function getBBParsed($str = null)
{
if ($str === null) {
$str = $this->description;
}
if (! extension_loaded('bbcode')) {
return $str;
}
$arrayBBCode = array(
'' => array(
'type' => BBCODE_TYPE_ROOT,
'childs' => '!i'
),
'b' => array(
'type' => BBCODE_TYPE_NOARG,
'open_tag' => '<b>',
'close_tag' => '</b>'
),
'i' => array(
'type' => BBCODE_TYPE_NOARG,
'open_tag' => '<i>',
'close_tag' => '</i>',
'childs' => 'b'
),
'u' => array(
'type' => BBCODE_TYPE_NOARG,
'open_tag' => '',
'close_tag' => ''
),
's' => array(
'type' => BBCODE_TYPE_NOARG,
'open_tag' => '',
'close_tag' => ''
),
'img' => array(
'type' => BBCODE_TYPE_NOARG,
'open_tag' => '<img src="',
'close_tag' => '" />',
'childs' => ''
),
'url' => array(
'type' => BBCODE_TYPE_OPTARG,
'open_tag' => '<a href="{PARAM}">',
'close_tag' => '</a>',
'default_arg' => '{CONTENT}',
'childs' => 'b,i'
),
'quote' => array(
'type' => BBCODE_TYPE_NOARG,
'open_tag' => '',
'close_tag' => ''
),
'code' => array(
'type' => BBCODE_TYPE_NOARG,
'open_tag' => '<pre>',
'close_tag' => '</pre>'
),
'size' => array(
'type' => BBCODE_TYPE_OPTARG,
'open_tag' => '',
'close_tag' => '',
'default_arg' => '{CONTENT}',
'childs' => 'b,i'
),
'color' => array(
'type' => BBCODE_TYPE_OPTARG,
'open_tag' => '',
'close_tag' => '',
'default_arg' => '{CONTENT}',
'childs' => 'b,i'
)
);
$BBHandler = bbcode_create($arrayBBCode);
return bbcode_parse($BBHandler, $str);
}
public function getPureDescription($str = null)
{
if ($str === null) {
$str = $this->description;
}
$p = new CHtmlPurifier();
$p->options = array(
'HTML.Allowed' => 'br,p,ul,li,b,i,a[href],pre,img[src|alt]',
'HTML.Nofollow' => true,
'Core.EscapeInvalidTags' => true
);
return $p->purify($str);
}
public function getDescriptionWithLazyImage($str = null)
{
if ($str === null) {
$str = $this->description;
}
return preg_replace('#(<img[^>]+?)(src=("[^"]"|[^\s>]+))([^>]*>)#sui', '\1 data-url=\3 src="" \4', $str);
}
protected function replaceImageLinksWithTag($str)
{
$str = preg_replace('#\[img\]\s*(http://[^\[\ ]+)\s*\[/img\]#sui', '<img src="\\1" />', $str);
$str = preg_replace('#(?<!["=])http://[^\[\ ]+\.(jpeg|jpg|png|gif)#sui', '<img src="\\0" />', $str);
return $str;
}
public function getFullyPreparedDescription()
{
$str = $this->getBBParsed();
$str = $this->getPureDescription($str);
$str = $this->replaceImageLinksWithTag($str);
$str = $this->getDescriptionWithLazyImage($str);
return $str;
}
}

View file

@ -0,0 +1,122 @@
<?php
class SphinxSyntaxValidator extends CValidator
{
public function validateAttribute($object, $attribute)
{
$value = trim($object->$attribute);
if (empty($value)) {
return;
}
// Check validation for "|"
if (substr_count($value, '|') > 0) {
$parts = explode('|', $value);
$p = trim($parts[0]);
if (! $p || in_array($p, array(
'$',
'^'
))) {
$this->addError($object, $attribute, 'Wrong query syntax: operator OR can not be first lexem or use before other operators in query');
return;
}
}
// Check validation for ^field-start field-end$ query
if (count($value) > 0 && $value[0] == '$') {
$this->addError($object, $attribute, 'Wrong query syntax: operator field-end$ can not be by first position in query');
return;
}
// Check validation for NOT operator
if (substr_count($value, '!') > 0) {
if (! trim(preg_replace('#\s*(![^ !]+)\s*#mui', '', $value))) {
$this->addError($object, $attribute, 'Wrong query syntax: operator NOT can not be use without simple tokens');
return;
}
$parts = explode('!', $value);
if (count($parts) > 0 && ! trim($parts[count($parts) - 1])) {
$this->addError($object, $attribute, 'Wrong query syntax: after operator NOT must be follow lexem');
return;
}
}
}
}
class SearchForm extends CFormModel
{
// Form type constants
const ADVANCED_FORM = 'advanced';
const SIMPLE_FORM = 'simple';
// Encoding
const ENCODING = 'UTF-8';
public $age;
public $tags;
public $popular;
public $status;
public $category;
// Count of items to be found, if > 0 - pagination shouldn't be used and Sphinx is limited to this number of records
public $latest = 0;
// Simple form fields
// With public getter and setter method
protected $words;
protected static $filesRegex = '#\s*\*\s*(?P<filesPattern>[^\*]*)\*\s*#u';
public function rules()
{
return array(
// Simple form
array(
'age, popular, status',
'safe',
'on' => 'simple'
),
array(
'words',
'length',
'min' => 2,
'max' => 255,
'on' => 'simple'
),
array(
'words',
'sphinxSyntaxValidator',
'on' => 'simple'
),
);
}
public function attributeLabels()
{
return array(
'words' => Yii::t('site_texts', 'Keywords')
);
}
public function setWords($words)
{
if (is_string($words)) {
// Convert words to lower case
$words = mb_strtolower(trim($words), self::ENCODING);
}
$this->words = $words;
}
public function getWords()
{
return $this->words;
}
}

7
src/protected/vendor/autoload.php vendored Normal file
View file

@ -0,0 +1,7 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer' . '/autoload_real.php';
return ComposerAutoloaderInite9bdd1350b26ea0a58ea4a952272ba99::getLoader();

1
src/protected/vendor/bin/yiic vendored Symbolic link
View file

@ -0,0 +1 @@
../yiisoft/yii/framework/yiic

View file

@ -0,0 +1,386 @@
<?php
/*
* This file is part of Composer.
*
* (c) Nils Adermann <naderman@naderman.de>
* Jordi Boggiano <j.boggiano@seld.be>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Composer\Autoload;
/**
* ClassLoader implements a PSR-0 class loader
*
* See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md
*
* $loader = new \Composer\Autoload\ClassLoader();
*
* // register classes with namespaces
* $loader->add('Symfony\Component', __DIR__.'/component');
* $loader->add('Symfony', __DIR__.'/framework');
*
* // activate the autoloader
* $loader->register();
*
* // to enable searching the include path (eg. for PEAR packages)
* $loader->setUseIncludePath(true);
*
* In this example, if you try to use a class in the Symfony\Component
* namespace or one of its children (Symfony\Component\Console for instance),
* the autoloader will first look for the class under the component/
* directory, and it will then fallback to the framework/ directory if not
* found before giving up.
*
* This class is loosely based on the Symfony UniversalClassLoader.
*
* @author Fabien Potencier <fabien@symfony.com>
* @author Jordi Boggiano <j.boggiano@seld.be>
*/
class ClassLoader
{
// PSR-4
private $prefixLengthsPsr4 = array();
private $prefixDirsPsr4 = array();
private $fallbackDirsPsr4 = array();
// PSR-0
private $prefixesPsr0 = array();
private $fallbackDirsPsr0 = array();
private $useIncludePath = false;
private $classMap = array();
public function getPrefixes()
{
if (!empty($this->prefixesPsr0)) {
return call_user_func_array('array_merge', $this->prefixesPsr0);
}
return array();
}
public function getPrefixesPsr4()
{
return $this->prefixDirsPsr4;
}
public function getFallbackDirs()
{
return $this->fallbackDirsPsr0;
}
public function getFallbackDirsPsr4()
{
return $this->fallbackDirsPsr4;
}
public function getClassMap()
{
return $this->classMap;
}
/**
* @param array $classMap Class to filename map
*/
public function addClassMap(array $classMap)
{
if ($this->classMap) {
$this->classMap = array_merge($this->classMap, $classMap);
} else {
$this->classMap = $classMap;
}
}
/**
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*/
public function add($prefix, $paths, $prepend = false)
{
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
);
}
return;
}
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-0 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
// Register directories for a new namespace.
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
);
}
}
/**
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param array|string $paths The PSR-0 base directories
*/
public function set($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr0 = (array) $paths;
} else {
$this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
}
}
/**
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param array|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*/
public function setPsr4($prefix, $paths)
{
if (!$prefix) {
$this->fallbackDirsPsr4 = (array) $paths;
} else {
$length = strlen($prefix);
if ('\\' !== $prefix[$length - 1]) {
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
}
}
/**
* Turns on searching the include path for class files.
*
* @param bool $useIncludePath
*/
public function setUseIncludePath($useIncludePath)
{
$this->useIncludePath = $useIncludePath;
}
/**
* Can be used to check if the autoloader uses the include path to check
* for classes.
*
* @return bool
*/
public function getUseIncludePath()
{
return $this->useIncludePath;
}
/**
* Registers this instance as an autoloader.
*
* @param bool $prepend Whether to prepend the autoloader or not
*/
public function register($prepend = false)
{
spl_autoload_register(array($this, 'loadClass'), true, $prepend);
}
/**
* Unregisters this instance as an autoloader.
*/
public function unregister()
{
spl_autoload_unregister(array($this, 'loadClass'));
}
/**
* Loads the given class or interface.
*
* @param string $class The name of the class
* @return bool|null True if loaded, null otherwise
*/
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
return true;
}
}
/**
* Finds the path to the file where the class is defined.
*
* @param string $class The name of the class
*
* @return string|false The path if found, false otherwise
*/
public function findFile($class)
{
// work around for PHP 5.3.0 - 5.3.2 https://bugs.php.net/50731
if ('\\' == $class[0]) {
$class = substr($class, 1);
}
// class map lookup
if (isset($this->classMap[$class])) {
return $this->classMap[$class];
}
$file = $this->findFileWithExtension($class, '.php');
// Search for Hack files if we are running on HHVM
if ($file === null && defined('HHVM_VERSION')) {
$file = $this->findFileWithExtension($class, '.hh');
}
if ($file === null) {
// Remember that this class does not exist.
return $this->classMap[$class] = false;
}
return $file;
}
private function findFileWithExtension($class, $ext)
{
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;
$first = $class[0];
if (isset($this->prefixLengthsPsr4[$first])) {
foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) {
if (0 === strpos($class, $prefix)) {
foreach ($this->prefixDirsPsr4[$prefix] as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) {
return $file;
}
}
}
}
}
// PSR-4 fallback dirs
foreach ($this->fallbackDirsPsr4 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
return $file;
}
}
// PSR-0 lookup
if (false !== $pos = strrpos($class, '\\')) {
// namespaced class name
$logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
. strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
} else {
// PEAR-like class name
$logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
}
if (isset($this->prefixesPsr0[$first])) {
foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
if (0 === strpos($class, $prefix)) {
foreach ($dirs as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
}
}
}
// PSR-0 fallback dirs
foreach ($this->fallbackDirsPsr0 as $dir) {
if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
return $file;
}
}
// PSR-0 include paths.
if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
return $file;
}
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*/
function includeFile($file)
{
include $file;
}

View file

@ -0,0 +1,9 @@
<?php
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

View file

@ -0,0 +1,9 @@
<?php
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

View file

@ -0,0 +1,9 @@
<?php
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);
return array(
);

View file

@ -0,0 +1,50 @@
<?php
// autoload_real.php @generated by Composer
class ComposerAutoloaderInite9bdd1350b26ea0a58ea4a952272ba99
{
private static $loader;
public static function loadClassLoader($class)
{
if ('Composer\Autoload\ClassLoader' === $class) {
require __DIR__ . '/ClassLoader.php';
}
}
public static function getLoader()
{
if (null !== self::$loader) {
return self::$loader;
}
spl_autoload_register(array('ComposerAutoloaderInite9bdd1350b26ea0a58ea4a952272ba99', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader();
spl_autoload_unregister(array('ComposerAutoloaderInite9bdd1350b26ea0a58ea4a952272ba99', 'loadClassLoader'));
$map = require __DIR__ . '/autoload_namespaces.php';
foreach ($map as $namespace => $path) {
$loader->set($namespace, $path);
}
$map = require __DIR__ . '/autoload_psr4.php';
foreach ($map as $namespace => $path) {
$loader->setPsr4($namespace, $path);
}
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
$loader->register(true);
return $loader;
}
}
function composerRequiree9bdd1350b26ea0a58ea4a952272ba99($file)
{
require $file;
}

View file

@ -0,0 +1,88 @@
[
{
"name": "yiisoft/yii",
"version": "1.1.15",
"version_normalized": "1.1.15.0",
"source": {
"type": "git",
"url": "https://github.com/yiisoft/yii.git",
"reference": "022a51d34ad2c95db2b77b2075e98f5dd78b08e0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/yiisoft/yii/zipball/022a51d34ad2c95db2b77b2075e98f5dd78b08e0",
"reference": "022a51d34ad2c95db2b77b2075e98f5dd78b08e0",
"shasum": ""
},
"require": {
"php": ">=5.1.0"
},
"time": "2014-06-30 00:14:27",
"bin": [
"framework/yiic"
],
"type": "library",
"installation-source": "dist",
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Qiang Xue",
"email": "qiang.xue@gmail.com",
"homepage": "http://www.yiiframework.com/",
"role": "Founder and project lead"
},
{
"name": "Alexander Makarov",
"email": "sam@rmcreative.ru",
"homepage": "http://rmcreative.ru/",
"role": "Core framework development"
},
{
"name": "Maurizio Domba",
"homepage": "http://mdomba.info/",
"role": "Core framework development"
},
{
"name": "Carsten Brandt",
"email": "mail@cebe.cc",
"homepage": "http://cebe.cc/",
"role": "Core framework development"
},
{
"name": "Wei Zhuo",
"email": "weizhuo@gmail.com",
"role": "Project site maintenance and development"
},
{
"name": "Sebastián Thierer",
"email": "sebas@artfos.com",
"role": "Component development"
},
{
"name": "Jeffrey Winesett",
"email": "jefftulsa@gmail.com",
"role": "Documentation and marketing"
},
{
"name": "Timur Ruziev",
"email": "resurtm@gmail.com",
"homepage": "http://resurtm.com/",
"role": "Core framework development"
},
{
"name": "Paul Klimov",
"email": "klimov.paul@gmail.com",
"role": "Core framework development"
}
],
"description": "Yii Web Programming Framework",
"homepage": "http://www.yiiframework.com/",
"keywords": [
"framework",
"yii"
]
}
]

View file

@ -0,0 +1,17 @@
# This file is used to fix authors email addresses in old svn commit history
# See git docs for details:
# http://www.kernel.org/pub/software/scm/git/docs/git-shortlog.html#_mapping_authors
Qiang Xue <qiang.xue@gmail.com> qiang.xue <qiang.xue@c7f931c7-7552-0410-b027-2fb3d89d9100>
Qiang Xue <qiang.xue@gmail.com> qiang.xue@gmail.com <qiang.xue@gmail.com@c7f931c7-7552-0410-b027-2fb3d89d9100>
Alexander Makarov <sam@rmcreative.ru> alexander.makarow@gmail.com <alexander.makarow@gmail.com@c7f931c7-7552-0410-b027-2fb3d89d9100>
Alexander Makarov <sam@rmcreative.ru> alexander.makarow <alexander.makarow@c7f931c7-7552-0410-b027-2fb3d89d9100>
Maurizio Domba <mdomba@gmail.com> mdomba@gmail.com <mdomba@gmail.com@c7f931c7-7552-0410-b027-2fb3d89d9100>
Maurizio Domba <mdomba@gmail.com> mdomba <mdomba@c7f931c7-7552-0410-b027-2fb3d89d9100>
kidol <keyboard.idol@gmail.com> keyboard.idol@gmail.com <keyboard.idol@gmail.com@c7f931c7-7552-0410-b027-2fb3d89d9100>
Sebastián Thierer <sebathi@gmail.com> sebathi <sebathi@c7f931c7-7552-0410-b027-2fb3d89d9100>
Mike Haertl <haertl.mike@gmail.com> haertl.mike <haertl.mike@c7f931c7-7552-0410-b027-2fb3d89d9100>
Jeff <jefftulsa@gmail.com> jefftulsa@gmail.com <jefftulsa@gmail.com@c7f931c7-7552-0410-b027-2fb3d89d9100>
Jeff <jefftulsa@gmail.com> jefftulsa <jefftulsa@c7f931c7-7552-0410-b027-2fb3d89d9100>
Wei Zhuo <weizhuo@gmail.com> weizhuo <weizhuo@c7f931c7-7552-0410-b027-2fb3d89d9100>

View file

@ -0,0 +1,18 @@
language: php
php:
- 5.2
- 5.3
- 5.4
- 5.5
services:
- redis-server
before_script:
- ./tests/travis/mysql-setup.sh
- ./tests/travis/postgresql-setup.sh
- ./tests/travis/memcache-setup.sh
- cd tests
script: phpunit --colors --no-globals-backup --exclude-group mssql,oci framework

1660
src/protected/vendor/yiisoft/yii/CHANGELOG vendored Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,38 @@
How to contribute to Yii?
=========================
When contributing to Yii you have to follow some conventions and a simple
workflow. It allows us to handle the requests quickly and ensure best quality
for the Yii core code.
Following guidelines will result in less work for both you and the core team.
Contributing code and fix bugs
------------------------------
Please take the time and read the following guide from beginning to the end:
https://github.com/yiisoft/yii/wiki/Git-workflow-for-Yii-contributors
For code style see:
https://github.com/yiisoft/yii/wiki/Core-framework-code-style
A common issue for many pull requests is inconsistent line endings. You can
learn about dealing with it at:
https://help.github.com/articles/dealing-with-line-endings
**Thanks for your contribution!**
Contributing translations
-------------------------
Contributing translations does not have a workflow like with code. You don't
need to create an issue, pull request will be enough.
See the following guide on how to contribute to Yii documentation:
https://github.com/yiisoft/yii/wiki/Documentation-translation-guidelines
This one is also available in Russian language:
https://github.com/yiisoft/yii/wiki/Russian-Translation-Guidelines
**Thanks for your contribution!**

View file

@ -0,0 +1,31 @@
The Yii framework is free software. It is released under the terms of
the following BSD License.
Copyright (c) 2008-2013 by Yii Software LLC (http://www.yiisoft.com)
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
* Neither the name of Yii Software LLC nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

64
src/protected/vendor/yiisoft/yii/README vendored Normal file
View file

@ -0,0 +1,64 @@
Yii Web Programming Framework
=============================
Thank you for choosing Yii - a high-performance component-based PHP framework.
INSTALLATION
------------
Please make sure the release file is unpacked under a Web-accessible
directory. You shall see the following files and directories:
demos/ demos
framework/ framework source files
requirements/ requirement checker
CHANGELOG describing changes in every Yii release
LICENSE license of Yii
README this file
UPGRADE upgrading instructions
REQUIREMENTS
------------
The minimum requirement by Yii is that your Web server supports
PHP 5.1.0 or above. Yii has been tested with Apache HTTP server
on Windows and Linux operating systems.
Please access the following URL to check if your Web server reaches
the requirements by Yii, assuming "YiiPath" is where Yii is installed:
http://hostname/YiiPath/requirements/index.php
QUICK START
-----------
Yii comes with a command line tool called "yiic" that can create
a skeleton Yii application for you to start with.
On command line, type in the following commands:
$ cd YiiPath/framework (Linux)
cd YiiPath\framework (Windows)
$ ./yiic webapp ../testdrive (Linux)
yiic webapp ..\testdrive (Windows)
The new Yii application will be created at "YiiPath/testdrive".
You can access it with the following URL:
http://hostname/YiiPath/testdrive/index.php
WHAT's NEXT
-----------
Please visit the project website for tutorials, class reference
and join discussions with other Yii users.
The Yii Developer Team
http://www.yiiframework.com

View file

@ -0,0 +1,65 @@
Yii Web Programming Framework
=============================
Thank you for choosing Yii - a high-performance component-based PHP framework.
[![Build Status](https://secure.travis-ci.org/yiisoft/yii.png)](http://travis-ci.org/yiisoft/yii)
INSTALLATION
------------
Please make sure the release file is unpacked under a Web-accessible
directory. You shall see the following files and directories:
demos/ demos
framework/ framework source files
requirements/ requirement checker
CHANGELOG describing changes in every Yii release
LICENSE license of Yii
README this file
UPGRADE upgrading instructions
REQUIREMENTS
------------
The minimum requirement by Yii is that your Web server supports
PHP 5.1.0 or above. Yii has been tested with Apache HTTP server
on Windows and Linux operating systems.
Please access the following URL to check if your Web server reaches
the requirements by Yii, assuming "YiiPath" is where Yii is installed:
http://hostname/YiiPath/requirements/index.php
QUICK START
-----------
Yii comes with a command line tool called "yiic" that can create
a skeleton Yii application for you to start with.
On command line, type in the following commands:
$ cd YiiPath/framework (Linux)
cd YiiPath\framework (Windows)
$ ./yiic webapp ../testdrive (Linux)
yiic webapp ..\testdrive (Windows)
The new Yii application will be created at "YiiPath/testdrive".
You can access it with the following URL:
http://hostname/YiiPath/testdrive/index.php
WHAT's NEXT
-----------
Please visit the project website for tutorials, class reference
and join discussions with other Yii users.
The Yii Developer Team
http://www.yiiframework.com

502
src/protected/vendor/yiisoft/yii/UPGRADE vendored Normal file
View file

@ -0,0 +1,502 @@
Upgrading Instructions for Yii Framework v1.1.15
================================================
!!!IMPORTANT!!!
The following upgrading instructions are cumulative. That is,
if you want to upgrade from version A to version C and there is
version B between A and C, you need to following the instructions
for both A and B.
General upgrade instructions
----------------------------
- Make a backup.
- Clean up your 'assets' folder.
- Replace 'framework' dir with the new one or point GIT to a fresh
release and update.
- Check if everything is OK, if not — revert from backup and post
issues to Yii issue tracker.
Upgrading from v1.1.14
----------------------
Upgrading from v1.1.13
----------------------
- CActiveRecord::count() now respects group by and having. If your code relied
on ignoring it your application may break and should be updated.
- Vendors: phlymail's Net_IDNA was replaced by PEAR Net_IDNA2. The latter library is better maintained than the former.
In case your code relies on bundled phlymail's Net_IDNA you should change it a bit. Old way of encoding IDNs:
require_once(Yii::getPathOfAlias('system.vendors.idna_convert').DIRECTORY_SEPARATOR.'idna_convert.class.php');
$idnaConvert=new idna_convert();
$result=$idnaConvert->encode($value);
New:
require_once(Yii::getPathOfAlias('system.vendors.Net_IDNA2.Net').DIRECTORY_SEPARATOR.'IDNA2.php');
$idna=new Net_IDNA2();
$result=$idna->encode($value);
- CAPTCHA appearance has been changed. Non-free Duality.ttf font (used by CCaptchaAction) replaced by open/free
SpicyRice.ttf. New font is distributed under SIL Open Font License version 1.1. Do not forget to adjust font path
in case your application relies on Duality.ttf font file.
- CSecurityManager::computeHMAC() method is now public and third parameter has been added. You must change signature
of this method in the extended child class to fit new circumstances. Otherwise an E_STRICT error will be issued.
- CClientScript::registerScriptFile() and CClientScript::registerScript() methods signature changed.
Update your subclasses that override registerScriptFile() or registerScript() if any.
- CActiveRecord::refreshMetaData() now clears meta data for all objects of the particular Active Record class.
Also CActiveRecord::refreshMetaData() will not create new meta data at once - new CActiveRecordMetaData instance
will be created on the first demand.
- Oracle related note: in case you're using COciSchema::resetSequence() or CDbSchema::resetSequence() methods with
the Oracle database, keep in mind that its behavior has changed to be consistent with the same methods for
the other database management systems. Please refer to its documentation for more details and don't forget
to adjust your code respectively.
- Signature of the CJuiInputWidget::resolveNameID() method has changed. If you're overriding this method you must
change your code to fit it. This method now accepts two parameters, it means you have to adjust code of the
overlapped descendant method signature as follows:
protected function resolveNameID($nameProperty='name',$attributeProperty='attribute')
And ancestor method call to:
parent::resolveNameID($nameProperty,$attributeProperty);
- In case you've used your own relation types extended from `CHasOneRelation` or
`CHasManyRelation` make sure you update these to reflect moving `through` property
from both these to `CActiveRelation`.
- CSecurityManager::generateRandomKey() has been deprecated in favor of CSecurityManager::generateRandomString().
Try not to use it anymore and avoid CSecurityManager::generateRandomKey() method in your code.
Upgrading from v1.1.12
----------------------
- Both jQuery and jQueryUI were updated. Check [jQuery UI upgrade guide](http://jqueryui.com/upgrade-guide/1.9/)
and [jQuery release notes](http://blog.jquery.com/2012/08/09/jquery-1-8-released/).
- We completed the behavior of CFormatter::sizeFormat() which has been introduced in Yii 1.1.11. If you are using it with your own translation file
you have to move your translations to the `yii` category in `yii.php` file which is handled by the application component `coreMessages`.
We also fixed the default translation strings to be correct English and apply to choice format, so you have to adjust your translation file keys.
- Be sure to clean all your existing cache during the upgrade. The cache values from CDbCommand has been
changed to an array to be able to store false values (returned when no records are found).
- Make sure all your event handlers in behaviors are public methods, as we are not supporting protected methods as event handlers anymore.
- We fixed the calls to CActiveRecord::beforeFind() for consistency so that beforeFind() now always gets called for every relation
on eager loading even if the main query does not return a result. This has been the case for all CActiveRecord::find*()-methods
already but now also applies for findBySql() and findAllBySql().
- Criteria modification in CActiveRecord::beforeFind() did not apply to the query when model was loaded in a relational context.
Since version 1.1.13 changes to query criteria made in beforeFind() now also apply to the query when model is loaded in a relational context.
The main problem here is that you can not use the `t`-alias for your table anymore, you have to change your code to
use the table alias currently in use as this is different in relational context.
You can get that alias by calling `$this->getTableAlias();` in your active record class
or `$this->owner->getTableAlias()` in behavior context.
Example:
$criteria->condition = 't.myfield = 1';
You need to change that to:
$alias = $this->owner->getTableAlias();
$criteria->condition = $alias.'.myfield = 1';
- Make sure you are using `CCaptcha::checkRequirements()` method for checking whether CAPTCHA could be rendered successfully in your environment.
`extension_loaded('gd')` expression is not enough and wrong because CAPTCHA could be rendered via ImageMagick with fallback to GD since 1.1.13
(thus checking code is not simple as it seems).
- In case you're using MSSQL driver make sure authentication credentials you use have permissions to use
`sys.extended_properties` system view. This is critical for retrieving additional metadata on tables.
Upgrading from v1.1.11
----------------------
- Changes in CCookieCollection::add() (introduced in 1.1.11) were reverted as they were triggering E_STRICT on some old PHP-versions
If your application relies on these newly added changes. You should change your code from
$cookies->add(new CHttpCookie($name, $value));
to
$cookies[$name] = new CHttpCookie($name, $value);
- CActiveRecord::resetScope() method signature changed. Please update your subclasses that override resetScope() if any.
Upgrading from v1.1.10
----------------------
- API of public method CConsoleCommand::confirm() changed. If you are overriding this method make sure to update your code.
The method now has a 2nd parameter for the default value which will be used if no selection is made, so you have to
adjust the signature to fit
public function confirm($message,$default=false)
and the parent call to
parent::confirm($message,$default);
- API of protected method CConsoleCommand::afterAction() changed, if you are overriding this method make sure to update your code.
method now has a 3rd parameter for application exit code, so you have to adjust the signature to fit
protected function afterAction($action,$params,$exitCode=0)
and the parent call to
parent::afterAction($action,$params,$exitCode);
- CDateFormat::format() now will return null if the parameter $time is null. Previously it would return 1/1/1970.
- If you are using CJavaScript::encode in your application with parameter coming
from user input, set second argument to true:
CJavaScript::encode($userInput, true);
It will disable prefixing parameters with "js:". If you need to pass JavaScript
expression it's now preferrable to wrap these with CJavaScriptExpression:
CJavaScript::encode(new CJavaScriptExpression('alert("Yii!");'), true);
Note that second "safe" parameter doesn't affect CJavaScriptExpression in any way.
Upgrading from v1.1.9
---------------------
- Previously xSendFile() was returning false if the file was not found.
This has been removed to allow relative file paths. If you are relying on this check,
you will need to do it manually before calling xSendFile().
Upgrading from v1.1.8
---------------------
- CConfiguration::createObject, CController::paginate and CHtml::getActiveId deprecated since 1.0.x were removed. Use
Yii::createComponent, new CPagination directly and CHtml::activeId respectively.
- In CErrorHandler::handleException() the checking for ajax call has been removed
as it was preventing to customize the display of the exception during an ajax call.
- Previously in case of validation error the CSS "error" class was not added to the row container at all when
checkBoxList or radioButtonList where used. This is fixed now and proper "error" CSS class is added to the row
container but in case of validation error, all labels from the list are shown in red because of the CSS rule.
To fix this and display only the attribute label in red:
in <projectdir>/css/form.css the line:
div.form div.error label
should be changed to
div.form div.error label:first-child
- If you've used "through" ActiveRecord option in your relation definitions it's good to update code as shown below.
Old style of defining this option still works but is now deprecated.
Change
~~~
class Group extends CActiveRecord
{
public function relations()
{
return array(
'roles'=>array(self::HAS_MANY,'Role','group_id'),
'users'=>array(self::HAS_MANY,'User','user_id','through'=>'roles'),
);
}
}
~~~
to
~~~
class Group extends CActiveRecord
{
public function relations()
{
return array(
'roles'=>array(self::HAS_MANY,'Role','group_id'),
'users'=>array(self::HAS_MANY,'User',array('user_id'=>'id'),'through'=>'roles'),
);
}
}
~~~
Upgrading from v1.1.7
---------------------
- CDbAuthManager will now quote columns and tables referenced in its SQL code.
If your auth tables were created in a case-insensitive fashion (e.g. on PostgreSQL)
while your DBMS is case-sensitive, this change may cause DB query errors.
To fix this issue, you will have to rename the table names and columns, or re-create
the auth tables by following the SQL code given in framework/web/auth/*.sql.
- jQuery was upgraded to 1.6.1. Check your client side code and if you have issues consider
downgrading to 1.5.1 or 1.4.4.
Upgrading from v1.1.6
---------------------
- Make sure you are using latest stable PHPUnit 3.5 if you are using unit tests.
Upgrading from v1.1.5
---------------------
- In CActiveRecord::relations(), if a relation involves composite foreign keys, the foreign key
columns must be separated by commas now. Previously, the columns can be separated by either
commas or spaces. If your mode code are generated by Gii or yiic shell, you do not need to
worry about this.
- CLDR data was updated to a newest available version so data formats, month
names and other regional data can be changed.
Upgrading from v1.1.4
---------------------
- CHtml will no longer render null attributes for HTML tags. This means if $htmlOptions is
array('class'=>null), it will no longer render the 'class' attribute in the HTML tag.
it would render the class attribute as class="". We expect this will not cause much trouble
in upgrading. However, in case problems happen, you may set the attribute to be an empty string
to solve them.
- Now by default CWebLogRoute does not render logs in FireBug for ajax calls.
To get logs rendered for ajax calls in FireBug set CWebLogRoute::ignoreAjaxInFireBug to false
- The implementation of CCache::flush() was changed a little. Child classes should now implement
a flushValues() method. If you use any custom cache class with flush functionality, you should
rename the flush method accordingly.
- The prompt and empty options used in CHtml methods will NOT be HTML-encoded anymore. It will now
always convert ">" and "<" into "&gt;" and "lt;", respectively. This should be sufficient in most
cases. But if your application uses some other special characters, or if you allow user inputs
to be used as prompt and empty text labels, please call CHtml::encode() explicitly on these option
values.
Upgrading from v1.1.3
---------------------
- Zii was merged into Yii so if you are using SVN to keep framework
up to date, you'll need to delete 'framework/zii' and then update it.
Upgrading from v1.1.2
---------------------
- When using the skin feature, you now need to explicitly configure
the 'enableSkin' property of 'widgetFactory' application component
to be true. Also, if you have configured the 'widgets' property, you
should rename it to be 'skinnableWidgets'. These changes are due to
the introduction of the global widget customization feature.
Please see the guide (the "Theming" section) for more details.
- CAutoComplete is now deprecated and will be removed in Yii 1.2. Consider
using CJuiAutoComplete.
- Now it's not possible to reuse CActiveFinder. So if you have code like this:
$finder = Post::model()->with('comments');
$posts1 = $finder->findAll();
$posts2 = $finder->findAll();
you should rewrite it to:
$posts1 = Post::model()->with('comments');
$posts2 = Post::model()->with('comments');
- The 'condition' declared in the scopes of the related AR classes will now
be put in the 'ON' clause of the JOIN statement when performing relational AR queries.
Upgrading from v1.1.1
---------------------
Upgrading from v1.1.0
---------------------
- CHtml::beginForm() will automatically generate hidden fields to represent
the parameters in the query string when the form uses GET method.
To avoid submitting duplicated query parameters, you may use createUrl()
to explicitly specify the action of the form. You may also need to remove
the hidden fields that you previously render for the same purpose.
- The code generated by yiic tool is changed. If you are using yiic tool
to generate new CRUD code on a previously generated skeleton, you are recommended
to run "yiic webapp" again to re-generate the skeleton. Make sure you backup
your work before you do this.
- CMenu now renders the 'active' CSS class for the 'li' tag instead of the
hyperlink tag. You should adjust your CSS code accordingly if you use CMenu
in your application.
- CUrlManager::parsePathInfo() is changed to be non-static. If you override
this method or your existing code calls this method directly (neither is common),
you need to change your code accordingly.
- CController::forward() will exit the application by default now. If you want
to keep the old behavior, you may pass false as the second parameter.
- The jQuery copy included in the framework has been upgraded to version 1.4.2.
This may cause some incompatibility problems to your existing jQuery code or plugins.
If you want to keep using version 1.3.2, you may do so by configuring
CClientScript::scriptMap property.
- The default theme for JQuery UI widgets was changed from 'smoothness' to 'base'.
If you are using 'smoothness', you will need to manually download this theme from
jqueryui.com and configure the 'theme' property of the JQuery UI widgets accordingly.
Upgrading from v1.1rc
---------------------
- CRudColumn is renamed as CButtonColumn
- CDataColumn.dataField and dataExpression are renamed as name and value, respectively
- The alias name for the primary table in an AR query is fixed to be 't'
Upgrading from v1.1b
--------------------
Upgrading from v1.1a
--------------------
- CSort::attributes is changed. Now the array keys refer to attribute names
and array values refer to virtual attribute definitions. Please read the
API documentation for this property to learn more details. This change will
affect your code only when you explicitly specify this property.
Upgrading from v1.0.x
---------------------
- Application and module parameter names are changed to be case-sensitive.
In 1.0.x, they are case-insensitive.
- For tabular input, using Field[$i] is not valid anymore. Attribute names
should look like [$i]Field in order to support array-typed fields
(e.g. [$i]Field[$index]).
- Please read the Guide for further details on how to upgrade from v1.0.x to v1.1.
Upgrading from v1.0.12
----------------------
Upgrading from v1.0.11
----------------------
Upgrading from v1.0.10
----------------------
Upgrading from v1.0.9
---------------------
Upgrading from v1.0.8
---------------------
- ActiveRecord lazy loading is changed for optimization purpose. Previously,
when lazy loading occurs, the related table will be joined with the primary
table. Now, the related table will be queried without joining the primary table.
As a result, if you are using lazy loading and the corresponding relation
declaration includes reference to the primary table, the query will fail.
To fix this problem, please specify the lazy loading query options with the
actual primary table column values.
Upgrading from v1.0.7
---------------------
- A directory imported using Yii::import() will have precedence over
any existing include paths. For example, if we import 'application.models.*',
then the corresponding directory will be searched before any other
existing include paths. This also means, a directory imported later will
have precedence over directories imported earlier. Previously, this order
was reversed. This change may affect you if you have several classes with
the same name and they are imported via different directories. You will need
to adjust the import order of these directories to make sure your existing
applications are not broken due to this change.
Upgrading from v1.0.6
---------------------
- Default named scope will no longer be applied to INSERT, UPDATE and
DELETE queries. It is only applied to SELECT queries. You should be aware
of this change if you override CActiveRecord::defaultScope() in your code.
- The signature of CWebUser::logout() is changed. If you override this method,
you will need to modify your method declaration accordingly.
Upgrading from v1.0.5
---------------------
Upgrading from v1.0.4
---------------------
- CWebUser::checkAccess() takes an additional parameter to allow caching
the access check results. If you override this method, you will need to
modify your method declaration accordingly. Because the new parameter will
enable caching the access check results by default, please double check
your code containing this method call to make sure the behavior is as expected.
- CDateParser has been renamed to CDateTimeParser
Upgrading from v1.0.3
---------------------
- The signature of CWebModule::init() is modified. Its parameter is removed.
If your application uses modules, you have to modify your module class
files accordingly.
Upgrading from v1.0.2
---------------------
- Controllers that are organized in subdirectories are now referenced
using the ID format "path/to/xyz". Previously it was "path.to.xyz".
If you use "path.to.xyz" in your application, you have to modify it
to "path/to/xyz".
- CHtml::coreScript() is removed. If you used this in your application,
please use the following alternative:
Yii::app()->clientScript->registerCoreScript($name);
Upgrading from v1.0.1
---------------------
- Due to the introduction of the scenario-based massive assignment feature,
we removed CActiveRecord::protectedAttributes(). Please use safeAttributes()
to specify which attributes are safe to be massively assigned.
For more details about scenario-based assignment and validation,
please read the following tutorial section:
http://www.yiiframework.com/doc/guide/form.model#securing-attribute-assignments
- The signature of CModel::validate() has been changed to:
CModel::validate($scenario='', $attributes=null)
That is, the order of the two parameters has been swapped. If your application
contains code that invokes the validate() method (of either a CFormModel
or a CActiveRecord object) with some parameter, please make sure you fix
the parameter order.
- The usage of CActiveRecord::with() and the 'with' option in relations
has been changed. In order to query child relations, we should specify the 'with'
parameter/option like the following now:
Post::model()->with(array('comments', 'author.profile'))->findAll();
Previously, this should be written as:
Post::model()->with(array('comments', 'author'=>'profile'))->findAll();
If your code does not involve child relations (like 'profile' in the above),
nothing needs to be changed.
This change has been introduced in order to support dynamic relational
query options. For example, we can specify that comments be sorted in
descending order (assuming in the relations() method it is specified as
ascending order):
Post::model()->with(array(
'comments'=>array('order'=>'createTime DESC'),
'author.profile',
))->findAll();
Upgrading from v1.0.0
---------------------
- An $scenario parameter is added to both CModel::beforeValidate() and afterValidate().
If you override these methods in your child classes (form models, AR classes),
make sure you change the method signature accordingly.

View file

@ -0,0 +1 @@
deny from all

17
src/protected/vendor/yiisoft/yii/build/build vendored Executable file
View file

@ -0,0 +1,17 @@
#!/usr/bin/env php
<?php
/**
* build script file.
*
* This is a command line script that provides various commands
* for building an Yii release.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
$root=dirname(__FILE__);
$config=array('basePath'=>$root);
require_once($root.'/../framework/yiic.php');

View file

@ -0,0 +1,23 @@
@echo off
rem -------------------------------------------------------------
rem build script for Windows.
rem
rem This is the bootstrap script for running build on Windows.
rem
rem @author Qiang Xue <qiang.xue@gmail.com>
rem @link http://www.yiiframework.com/
rem @copyright 2008 Yii Software LLC
rem @license http://www.yiiframework.com/license/
rem @version $Id$
rem -------------------------------------------------------------
@setlocal
set BUILD_PATH=%~dp0
if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe
%PHP_COMMAND% "%BUILD_PATH%build" %*
@endlocal

View file

@ -0,0 +1,276 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Phing build file for Yii.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2009 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
-->
<project name="yii" basedir="." default="help">
<!-- task definitions -->
<taskdef name="yii-init-build" classname="YiiInitTask" classpath="tasks" />
<!--
<taskdef name="yii-pear" classname="YiiPearTask" classpath="tasks"/>
-->
<!-- init yii.version, yii.revision and yii.winbuild -->
<yii-init-build />
<!-- these are required external commands -->
<property name="php" value="php" /> <!-- PHP parser -->
<property name="hhc" value="hhc" /> <!-- compile phpdoc into CHM -->
<property name="pdflatex" value="pdflatex" /> <!-- generates PDF from LaTex -->
<property name="pkgname" value="${phing.project.name}-${yii.version}.${yii.revision}"/>
<property name="docname" value="${phing.project.name}-docs-${yii.version}.${yii.revision}"/>
<property name="pearname" value="${phing.project.name}-${yii.release}.tgz" />
<!-- directory definitions -->
<property name="build.base.dir" value="release"/>
<property name="build.dist.dir" value="${build.base.dir}/dist"/>
<property name="build.src.dir" value="${build.base.dir}/${pkgname}"/>
<property name="build.pear.src.dir" value="${build.src.dir}/framework" />
<property name="build.doc.dir" value="${build.base.dir}/${docname}"/>
<property name="build.web.dir" value="${build.base.dir}/web"/>
<tstamp>
<format property="DATE" pattern="%b %e %Y" />
</tstamp>
<if>
<equals arg1="${yii.winbuild}" arg2="true"/>
<then>
<property name="build" value="build"/>
</then>
<else>
<property name="build" value="php build"/>
</else>
</if>
<!-- source files in the framework -->
<fileset dir=".." id="framework">
<exclude name="**/.gitignore"/>
<exclude name="**/*.bak"/>
<exclude name="**/*~"/>
<include name="framework/**/*"/>
<include name="requirements/**/*"/>
<include name="demos/**/*"/>
<include name="CHANGELOG"/>
<include name="UPGRADE"/>
<include name="LICENSE"/>
<include name="README"/>
</fileset>
<!-- doc files -->
<fileset dir="../docs" id="docs">
<exclude name="**/.gitignore"/>
<exclude name="**/*.bak"/>
<exclude name="**/*~"/>
<include name="guide/**/*"/>
<include name="blog/**/*"/>
</fileset>
<fileset dir="../docs/guide" id="docs-guide">
<exclude name="**/.gitignore"/>
<exclude name="**/*.bak"/>
<exclude name="**/*~"/>
<include name="**/*"/>
</fileset>
<fileset dir="../docs/blog" id="docs-blog">
<exclude name="**/.gitignore"/>
<exclude name="**/*.bak"/>
<exclude name="**/*~"/>
<include name="**/*"/>
</fileset>
<fileset dir="." id="writables">
<include name="${build.src.dir}/**/runtime" />
<include name="${build.src.dir}/**/assets" />
<include name="${build.src.dir}/demos/**/data" />
</fileset>
<fileset dir="." id="executables">
<include name="${build.src.dir}/**/yiic" />
</fileset>
<target name="src" depends="sync">
<echo>Building package ${pkgname}...</echo>
<echo>Copying files to build directory...</echo>
<copy todir="${build.src.dir}">
<fileset refid="framework"/>
</copy>
<echo>Changing file permissions...</echo>
<chmod mode="0777">
<fileset refid="writables" />
</chmod>
<chmod mode="0755">
<fileset refid="executables" />
</chmod>
<echo>Generating source release file...</echo>
<mkdir dir="${build.dist.dir}" />
<if>
<equals arg1="${yii.winbuild}" arg2="true"/>
<then>
<tar destfile="${build.dist.dir}/${pkgname}.tar.gz" compression="gzip">
<fileset dir="${build.base.dir}">
<include name="${pkgname}/**/*"/>
</fileset>
</tar>
</then>
<else>
<exec command="tar czpf ${pkgname}.tar.gz ${pkgname}" dir="${build.base.dir}"/>
<move file="${build.base.dir}/${pkgname}.tar.gz" todir="${build.dist.dir}" />
</else>
</if>
<zip destfile="${build.dist.dir}/${pkgname}.zip">
<fileset dir="${build.base.dir}">
<include name="${pkgname}/**/*"/>
</fileset>
</zip>
</target>
<target name="doc" depends="sync">
<echo>Building documentation...</echo>
<echo>Building Guide PDF...</echo>
<exec command="${build} guideLatex" dir="." passthru="true" />
<exec command="${pdflatex} guide.tex -interaction=nonstopmode -max-print-line=120" dir="commands/guide" passthru="true"/>
<exec command="${pdflatex} guide.tex -interaction=nonstopmode -max-print-line=120" dir="commands/guide" passthru="true"/>
<exec command="${pdflatex} guide.tex -interaction=nonstopmode -max-print-line=120" dir="commands/guide" passthru="true"/>
<move file="commands/guide/guide.pdf" tofile="${build.doc.dir}/yii-guide-${yii.version}.pdf" />
<echo>Building Blog PDF...</echo>
<exec command="${build} blogLatex" dir="." passthru="true" />
<exec command="${pdflatex} blog.tex -interaction=nonstopmode -max-print-line=120" dir="commands/blog" passthru="true"/>
<exec command="${pdflatex} blog.tex -interaction=nonstopmode -max-print-line=120" dir="commands/blog" passthru="true"/>
<exec command="${pdflatex} blog.tex -interaction=nonstopmode -max-print-line=120" dir="commands/blog" passthru="true"/>
<move file="commands/blog/blog.pdf" tofile="${build.doc.dir}/yii-blog-${yii.version}.pdf" />
<echo>Building API...</echo>
<exec command="${build} api ${build.doc.dir}" dir="." passthru="true" />
<!--
<echo>Building API CHM...</echo>
<exec command="${hhc} ${build.doc.dir}/api/manual.hhp" />
<move file="${build.doc.dir}/api/manual.chm" tofile="${build.doc.dir}/yii-api-${yii.version}.chm" />
<delete>
<fileset dir="${build.doc.dir}/api">
<include name="manual.*" />
</fileset>
</delete>
-->
<echo>Generating doc release file...</echo>
<mkdir dir="${build.dist.dir}" />
<tar destfile="${build.dist.dir}/${docname}.tar.gz" compression="gzip">
<fileset dir="${build.base.dir}">
<include name="${docname}/**/*"/>
</fileset>
</tar>
<zip destfile="${build.dist.dir}/${docname}.zip">
<fileset dir="${build.base.dir}">
<include name="${docname}/**/*"/>
</fileset>
</zip>
</target>
<target name="web" depends="sync">
<echo>Building online API...</echo>
<mkdir dir="${build.web.dir}/common/data/${yii.version}" />
<exec command="${build} api ${build.web.dir}/common/data/${yii.version} online" dir="." passthru="true" />
<echo>Copying tutorials...</echo>
<copy todir="${build.web.dir}/common/data/${yii.version}/tutorials/guide">
<fileset refid="docs-guide"/>
</copy>
<copy todir="${build.web.dir}/common/data/${yii.version}/tutorials/blog">
<fileset refid="docs-blog"/>
</copy>
<echo>Copying release text files...</echo>
<mkdir dir="${build.web.dir}/frontend/www/files" />
<copy file="../CHANGELOG" tofile="${build.web.dir}/frontend/www/files/CHANGELOG-${yii.version}.txt" />
<copy file="../UPGRADE" tofile="${build.web.dir}/frontend/www/files/UPGRADE-${yii.version}.txt" />
<echo>
Finished building Web files.
Please update yiisite/common/data/versions.php file with the following code:
'1.1'=>array(
'version'=>'${yii.version}',
'revision'=>'${yii.revision}',
'date'=>'${yii.date}',
'latest'=>true,
),
</echo>
</target>
<target name="sync">
<echo>Synchronizing code changes for ${pkgname}...</echo>
<echo>Building autoload map...</echo>
<exec command="${build} autoload" dir="." passthru="true"/>
<echo>Building yiilite.php...</echo>
<exec command="${build} lite" dir="." passthru="true"/>
</target>
<target name="message">
<echo>Extracting i18n messages...</echo>
<exec command="${build} message ../framework/messages/config.php" dir="." passthru="true"/>
</target>
<!--
<target name="pear" depends="clean,build">
<echo>Generating pear package for ${phing.project.name}-${yii.release}</echo>
<mkdir dir="${build.dist.dir}" />
<yii-pear pkgdir="${build.pear.src.dir}"
channel="pear.php.net"
version="${yii.release}"
state="stable"
category="framework"
package="${phing.project.name}"
summary="Yii PHP Framework"
pkgdescription="Yii PHP Framework: Best for Web 2.0 Development"
notes="http://www.yiiframework.com/files/CHANGELOG-${yii.release}.txt"
license="BSD"
/>
<exec command="pear package" dir="${build.pear.src.dir}" passthru="true" />
<move file="${build.pear.src.dir}/${pearname}" tofile="${build.dist.dir}/${pearname}" />
</target>
-->
<target name="clean">
<echo>Cleaning up the build...</echo>
<delete dir="${build.base.dir}"/>
</target>
<target name="help">
<echo>
Welcome to use Yii build script!
--------------------------------
You may use the following command format to build a target:
phing &lt;target name&gt;
where &lt;target name&gt; can be one of the following:
- sync : synchronize yiilite.php and YiiBase.php
- message : extract i18n messages of the framework
- src : build source release
- doc : build documentation release (Windows only)
- clean : clean up the build
</echo>
</target>
</project>

View file

@ -0,0 +1,364 @@
<?php
/**
* ApiCommand class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
Yii::import('application.commands.api.ApiModel');
/**
* MessageCommand extracts messages to be translated from source files.
* The extracted messages are saved as PHP message source files
* under the specified directory.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package system.build
* @since 1.0
*/
class ApiCommand extends CConsoleCommand
{
const URL_PATTERN='/\{\{([^\}]+)\|([^\}]+)\}\}/';
public $classes;
public $packages;
public $pageTitle;
public $themePath;
public $currentClass;
public $baseSourceUrl="https://github.com/yiisoft/yii/blob";
public $version;
public function getHelp()
{
return <<<EOD
USAGE
build api <output-path> [mode]
build api check
DESCRIPTION
This command generates offline API documentation for the Yii framework.
PARAMETERS
* output-path: required, the directory where the generated documentation would be saved.
* mode: optional, either 'online' or 'offline' (default).
Indicates whether the generated documentation are for online or offline use.
* check: check PHPDoc for proper @param syntax
EXAMPLES
* build api yii/doc online - builds api ONLINE documentation in folder yii/doc
* build api yii/doc - builds api OFFLINE (default) documentation in folder yii/doc
* build api check - cheks PHPDoc @param directives
EOD;
}
/**
* Execute the action.
* @param array command line parameters specific for this command
*/
public function run($args)
{
$options=array(
'fileTypes'=>array('php'),
'exclude'=>array(
'.gitignore',
'/yiilite.php',
'/yiit.php',
'/cli',
'/i18n/data',
'/messages',
'/vendors',
'/views',
'/web/js',
'/web/widgets/views',
'/utils/mimeTypes.php',
'/gii/assets',
'/gii/components',
'/gii/controllers',
'/gii/generators',
'/gii/models',
'/gii/views',
),
);
if(!isset($args[0]))
$this->usageError('the output directory is not specified.');
if($args[0]=='check') {
$checkFiles=CFileHelper::findFiles(YII_PATH,$options);
$model=new ApiModel;
$model->check($checkFiles);
exit();
}
if(!is_dir($docPath=$args[0]))
$this->usageError("the output directory {$docPath} does not exist.");
$offline=true;
if(isset($args[1]) && $args[1]==='online')
$offline=false;
$this->version=Yii::getVersion();
/*
* development version - link to master
* release version link to tags
*/
if(substr($this->version,-3)=='dev')
$this->baseSourceUrl .= '/master/framework';
else
$this->baseSourceUrl .= '/'.$this->version.'/framework';
$this->pageTitle='Yii Framework Class Reference';
$themePath=dirname(__FILE__).'/api';
echo "\nBuilding.. : " . $this->pageTitle."\n";
echo "Type...... : " . ( $offline ? "offline" : "online" ). "\n";
echo "Version... : " . $this->version."\n";
echo "Source URL : " . $this->baseSourceUrl."\n\n";
echo "Building model...\n";
$model=$this->buildModel(YII_PATH,$options);
$this->classes=$model->classes;
$this->packages=$model->packages;
echo "Building pages...\n";
if($offline)
$this->buildOfflinePages($docPath.DIRECTORY_SEPARATOR.'api',$themePath);
else
{
$this->buildOnlinePages($docPath.DIRECTORY_SEPARATOR.'api',$themePath);
$this->buildKeywords($docPath);
$this->buildPackages($docPath);
}
echo "Done.\n\n";
}
protected function buildPackages($docPath)
{
file_put_contents($docPath.'/api/packages.txt',serialize($this->packages));
}
protected function buildKeywords($docPath)
{
$keywords=array();
foreach($this->classes as $class)
$keywords[]=$class->name;
foreach($this->classes as $class)
{
$name=$class->name;
foreach($class->properties as $property)
{
if(!$property->isInherited)
$keywords[]=$name.'.'.$property->name;
}
foreach($class->methods as $method)
{
if(!$method->isInherited)
$keywords[]=$name.'.'.$method->name.'()';
}
}
file_put_contents($docPath.'/api/keywords.txt',implode(',',$keywords));
}
public function render($view,$data=null,$return=false,$layout='main')
{
$viewFile=$this->themePath."/views/{$view}.php";
$layoutFile=$this->themePath."/layouts/{$layout}.php";
$content=$this->renderFile($viewFile,$data,true);
return $this->renderFile($layoutFile,array('content'=>$content),$return);
}
public function renderPartial($view,$data=null,$return=false)
{
$viewFile=$this->themePath."/views/{$view}.php";
return $this->renderFile($viewFile,$data,$return);
}
public function renderSourceLink($sourcePath,$line=null)
{
if($line===null)
return CHtml::link('framework'.$sourcePath,$this->baseSourceUrl.$sourcePath,array('class'=>'sourceLink'));
else
return CHtml::link('framework'.$sourcePath.'#'.$line, $this->baseSourceUrl.$sourcePath.'#L'.$line,array('class'=>'sourceLink'));
}
public function highlight($code,$limit=20)
{
$code=preg_replace("/^ /m",'',rtrim(str_replace("\t"," ",$code)));
$code=highlight_string("<?php\n".$code,true);
return preg_replace('/&lt;\\?php<br \\/>/','',$code,1);
}
protected function buildOfflinePages($docPath,$themePath)
{
$this->themePath=$themePath;
@mkdir($docPath);
$content=$this->render('index',null,true);
$content=preg_replace_callback(self::URL_PATTERN,array($this,'fixOfflineLink'),$content);
file_put_contents($docPath.'/index.html',$content);
foreach($this->classes as $name=>$class)
{
$this->currentClass=$name;
$this->pageTitle=$name;
$content=$this->render('class',array('class'=>$class),true);
$content=preg_replace_callback(self::URL_PATTERN,array($this,'fixOfflineLink'),$content);
file_put_contents($docPath.'/'.$name.'.html',$content);
}
CFileHelper::copyDirectory($this->themePath.'/assets',$docPath);
$content=$this->renderPartial('chmProject',null,true);
file_put_contents($docPath.'/manual.hhp',$content);
$content=$this->renderPartial('chmIndex',null,true);
file_put_contents($docPath.'/manual.hhk',$content);
$content=$this->renderPartial('chmContents',null,true);
file_put_contents($docPath.'/manual.hhc',$content);
}
protected function buildOnlinePages($docPath,$themePath)
{
$this->themePath=$themePath;
@mkdir($docPath);
$content=$this->renderPartial('index',null,true);
$content=preg_replace_callback(self::URL_PATTERN,array($this,'fixOnlineLink'),$content);
file_put_contents($docPath.'/index.html',$content);
foreach($this->classes as $name=>$class)
{
$this->currentClass=$name;
$this->pageTitle=$name;
$content=$this->renderPartial('class',array('class'=>$class),true);
$content=preg_replace_callback(self::URL_PATTERN,array($this,'fixOnlineLink'),$content);
file_put_contents($docPath.'/'.$name.'.html',$content);
}
}
protected function buildModel($sourcePath,$options)
{
$files=CFileHelper::findFiles($sourcePath,$options);
$model=new ApiModel;
$model->build($files);
return $model;
}
public function renderInheritance($class)
{
$parents=array($class->signature);
foreach($class->parentClasses as $parent)
{
if(isset($this->classes[$parent]))
$parents[]='{{'.$parent.'|'.$parent.'}}';
else
$parents[]=$parent;
}
return implode(" &raquo;\n",$parents);
}
public function renderImplements($class)
{
$interfaces=array();
foreach($class->interfaces as $interface)
{
if(isset($this->classes[$interface]))
$interfaces[]='{{'.$interface.'|'.$interface.'}}';
else
$interfaces[]=$interface;
}
return implode(', ',$interfaces);
}
public function renderSubclasses($class)
{
$subclasses=array();
foreach($class->subclasses as $subclass)
{
if(isset($this->classes[$subclass]))
$subclasses[]='{{'.$subclass.'|'.$subclass.'}}';
else
$subclasses[]=$subclass;
}
return implode(', ',$subclasses);
}
public function renderTypeUrl($type)
{
if(isset($this->classes[$type]) && $type!==$this->currentClass)
return '{{'.$type.'|'.$type.'}}';
else
return $type;
}
public function renderSubjectUrl($type,$subject,$text=null)
{
if($text===null)
$text=$subject;
if(isset($this->classes[$type])) {
return '{{'.$type.'::'.$subject.'-detail'.'|'.$text.'}}';
}
else
return $text;
}
public function renderPropertySignature($property)
{
if(!empty($property->signature))
return $property->signature;
$sig='';
if(!empty($property->getter))
$sig=$property->getter->signature;
if(!empty($property->setter))
{
if($sig!=='')
$sig.='<br/>';
$sig.=$property->setter->signature;
}
return $sig;
}
public function fixMethodAnchor($class,$name)
{
if(isset($this->classes[$class]->properties[$name]))
return $name."()";
else
return $name;
}
protected function fixOfflineLink($matches)
{
if(($pos=strpos($matches[1],'::'))!==false)
{
$className=substr($matches[1],0,$pos);
$method=substr($matches[1],$pos+2);
return "<a href=\"{$className}.html#{$method}\">{$matches[2]}</a>";
}
else
return "<a href=\"{$matches[1]}.html\">{$matches[2]}</a>";
}
protected function fixOnlineLink($matches)
{
if(($pos=strpos($matches[1],'::'))!==false)
{
$className=substr($matches[1],0,$pos);
$method=substr($matches[1],$pos+2);
if($className==='index')
return "<a href=\"/doc/api/#{$method}\">{$matches[2]}</a>";
else
return "<a href=\"/doc/api/{$className}#{$method}\">{$matches[2]}</a>";
}
else
{
if($matches[1]==='index')
return "<a href=\"/doc/api/\">{$matches[2]}</a>";
else
return "<a href=\"/doc/api/{$matches[1]}\">{$matches[2]}</a>";
}
}
}

View file

@ -0,0 +1,83 @@
<?php
/**
* AutoloadCommand class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* AutoloadCommand generates the class map for {@link YiiBase}.
* The class file YiiBase.php will be modified with updated class map.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package system.build
* @since 1.0
*/
class AutoloadCommand extends CConsoleCommand
{
public function getHelp()
{
return <<<EOD
USAGE
build autoload
DESCRIPTION
This command updates YiiBase.php with the latest class map.
The class map is used by Yii::autoload() to quickly include a class on demand.
Do not run this command unless you change or add core framework classes.
EOD;
}
/**
* Execute the action.
* @param array command line parameters specific for this command
*/
public function run($args)
{
$options=array(
'fileTypes'=>array('php'),
'exclude'=>array(
'.gitignore',
'/messages',
'/views',
'/cli',
'/yii.php',
'/yiit.php',
'/yiilite.php',
'/web/js',
'/vendors',
'/i18n/data',
'/utils/mimeTypes.php',
'/test',
'/zii',
'/gii',
),
);
$files=CFileHelper::findFiles(YII_PATH,$options);
$map='';
foreach($files as $file)
{
if(($pos=strpos($file,YII_PATH))!==0)
die("Invalid file '$file' found.");
$path=str_replace('\\','/',substr($file,strlen(YII_PATH)));
$className=substr(basename($path),0,-4);
if($className[0]==='C')
$map.="\t\t'$className' => '$path',\n";
}
$yiiBase=file_get_contents(YII_PATH.'/YiiBase.php');
$newYiiBase=preg_replace('/private\s+static\s+\$_coreClasses\s*=\s*array\s*\([^\)]*\)\s*;/',"private static \$_coreClasses=array(\n{$map}\t);",$yiiBase);
if($yiiBase!==$newYiiBase)
{
file_put_contents(YII_PATH.'/YiiBase.php',$newYiiBase);
echo "YiiBase.php is updated successfully.\n";
}
else
echo "Nothing changed.\n";
}
}

View file

@ -0,0 +1,79 @@
<?php
class BlogLatexCommand extends CConsoleCommand
{
function getHelp()
{
return <<<EOD
USAGE
yiic bloglatex
DESCRIPTION
This command generates latex files for the definitive guide.
The generated latex files are stored in the blog directory.
EOD;
}
function getSourceDir()
{
return dirname(__FILE__).'/../../docs/blog';
}
function getOutputDir()
{
return dirname(__FILE__).'/blog';
}
function run($args)
{
require_once(dirname(__FILE__).'/markdown/MarkdownHtml2Tex.php');
$sourcePath=$this->getSourceDir();
$chapters=$this->getTopics();
$toc = '';
foreach($chapters as $chapter=>$sections)
{
$toc .= sprintf("\chapter{%s}\n", $chapter);
foreach($sections as $path=>$section)
{
echo "creating '$section'...";
$content=file_get_contents($sourcePath."/{$path}.txt");
$this->createLatexFile($chapter,$section,$content, $path);
echo "done\n";
$toc .= sprintf("\input{%s}\n", $path);
}
}
$main_file = sprintf('%s/main.tex', $this->getOutputDir());
file_put_contents($main_file, $toc);
}
function getTopics()
{
$file = $this->getSourceDir().'/toc.txt';
$lines=file($file);
$chapter='';
$guideTopics=array();
foreach($lines as $line)
{
if(($line=trim($line))==='')
continue;
if($line[0]==='*')
$chapter=trim($line,'* ');
else if($line[0]==='-' && preg_match('/\[(.*?)\]\((.*?)\)/',$line,$matches))
$guideTopics[$chapter][$matches[2]]=$matches[1];
}
return $guideTopics;
}
function createLatexFile($chapter, $section, $content, $path)
{
$parser=new MarkdownParserLatex;
$content=$parser->transform($content);
$img_src = $this->getSourceDir().'/images';
$img_dst = $this->getOutputDir();
$html2tex = new MarkdownHtml2Tex($img_src, $img_dst);
$tex = $html2tex->parse_html($content, $path);
$filename = sprintf('%s/%s.tex', $this->getOutputDir(), $path);
file_put_contents($filename, $tex);
}
}

View file

@ -0,0 +1,58 @@
<?php
/**
* CheckBomCommand
*
* Checks for BOM files in a directory. If --fix provided, removes BOM where found.
* Use --path=my/path to run on non-framework directory.
*
* @author Alex Makarov <sam@rmcreative.ru>
* @package system.build
* @since 1.1.9
*/
class CheckBomCommand extends CConsoleCommand
{
const BOM="\xEF\xBB\xBF";
public function actionIndex($path=null,$fix=null)
{
if($path===null)
$path=YII_PATH;
echo "Checking $path for files with BOM.\n";
$checkFiles=CFileHelper::findFiles($path,array(
'exclude'=>array(
'.gitignore',
),
));
$detected=false;
foreach($checkFiles as $file)
{
$fileObj=new SplFileObject($file);
if(!$fileObj->eof() && false!==strpos($fileObj->fgets(),self::BOM))
{
if(!$detected)
{
echo "Detected BOM in:\n";
$detected=true;
}
echo $file."\n";
if($fix)
{
file_put_contents($file, substr(file_get_contents($file), 3));
}
}
}
if(!$detected)
{
echo "No files with BOM were detected.\n";
}
else if($fix)
{
echo "All files were fixed.\n";
}
}
}

View file

@ -0,0 +1,509 @@
<?php
/**
* CldrCommand class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* CldrCommand converts the locale data from the {@link http://www.unicode.org/cldr/ CLDR project}
* to PHP scripts so that they can be more easily used in PHP programming.
*
* The script respects locale inheritance so that the PHP data for a child locale
* will contain all its parents' locale data if they are not specified in the child locale.
* Therefore, to import the data for a locale, only the PHP script for that particular locale
* needs to be included.
*
* Note, only the data relevant to number and date formatting are extracted.
* Each PHP script file is named as the corresponding locale ID in lower case.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package system.build
* @since 1.0
*/
class CldrCommand extends CConsoleCommand
{
protected $pluralRules = array();
public function getHelp()
{
return <<<EOD
USAGE
build cldr <data-path>
DESCRIPTION
This command converts the locale data from the CLDR project
to PHP scripts so that they can be more easily used in PHP programming.
The script respects locale inheritance so that the PHP data for
a child locale will contain all its parent locale data if they are
not specified in the child locale. Therefore, to import the data
for a locale, only the PHP script for that particular locale needs
to be included.
Note, only the data relevant to number and date formatting are extracted.
Each PHP script file is named as the corresponding locale ID in lower case.
The resulting PHP scripts are created under the same directory that
contains the original CLDR data.
PARAMETERS
* data-path: required, the original CLDR data directory. This
directory should contain "main" subdirectory with hundreds of XML files
and "supplemental" subdirectory with "plurals.xml".
EOD;
}
/**
* Execute the action.
* @param array command line parameters specific for this command
*/
public function run($args)
{
if(!isset($args[0]))
{
$cldrPath = dirname(__FILE__).'/../temp';
$args[0] = $cldrPath.'/common';
//$this->usageError('the CLDR data directory is not specified.');
}
if(!is_dir($basePath=$args[0]))
{
if (!mkdir($basePath, 0777, true))
{
$this->usageError("Directory '$basePath' can not be created.");
}
//$this->usageError("Directory '$basePath' does not exist.");
}
if(!is_dir($path=$basePath.DIRECTORY_SEPARATOR.'main'))
{
// look for zip file
if(!is_file($zipFile=$cldrPath.'/core.zip')) {
// download latest core.zip file
$latestUrl = 'http://www.unicode.org/Public/cldr/latest/core.zip';
$ch = curl_init($latestUrl);
$fp = fopen($zipFile, "w");
curl_setopt($ch, CURLOPT_FILE, $fp);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
if (curl_exec($ch)===FALSE)
{
$this->usageError("Failed to download from '$latestUrl'.");
};
curl_close($ch);
fclose($fp);
}
// unzip file
$zip = new ZipArchive;
if ($zip->open($zipFile) === TRUE)
{
$zip->extractTo($cldrPath);
$zip->close();
}
else
{
$this->usageError("Failed to unzip '$zipFile'.");
}
}
if(!is_file($pluralFile=$basePath.DIRECTORY_SEPARATOR.'supplemental'.DIRECTORY_SEPARATOR.'plurals.xml'))
$this->usageError("File '$pluralFile' does not exist.");
// parse plural.xml before locale files
$pluralXml = simplexml_load_file($pluralFile);
$this->parsePluralRules($pluralXml);
// collect XML files to be processed
$options=array(
'exclude'=>array('.gitignore'),
'fileTypes'=>array('xml'),
'level'=>0,
);
$files=CFileHelper::findFiles(realpath($path),$options);
$sourceFiles=array();
foreach($files as $file)
$sourceFiles[basename($file)]=$file;
// sort by file name so that inheritances can be processed properly
ksort($sourceFiles);
// process root first because it is inherited by all
if(isset($sourceFiles['root.xml']))
{
$this->process($sourceFiles['root.xml']);
unset($sourceFiles['root.xml']);
foreach($sourceFiles as $sourceFile)
$this->process($sourceFile);
// clean up temporary files
function rrmdir($path)
{
return is_file($path)?
@unlink($path):
array_map('rrmdir',glob($path.'/*'))==@rmdir($path);
}
rrmdir($cldrPath);
}
else
die('Unable to find the required root.xml under CLDR "main" data directory.');
}
protected function process($path)
{
$source=basename($path);
echo "processing $source...";
$dir=dirname($path);
$locale=substr($source,0,-4);
$target=$locale.'.php';
$i18nDataPath = dirname(__FILE__).'/../../framework/i18n/data';
// retrieve parent data first
if(($pos=strrpos($locale,'_'))!==false)
$data=require($i18nDataPath.DIRECTORY_SEPARATOR.strtolower(substr($locale,0,$pos)).'.php');
else if($locale!=='root')
$data=require($i18nDataPath.DIRECTORY_SEPARATOR.'root.php');
else
$data=array();
$xml=simplexml_load_file($path);
$this->parseVersion($xml,$data);
$this->parseNumberSymbols($xml,$data);
$this->parseNumberFormats($xml,$data);
$this->parseCurrencySymbols($xml,$data);
$this->parseLanguages($xml,$data);
$this->parseScripts($xml,$data);
$this->parseTerritories($xml,$data);
$this->parseMonthNames($xml,$data);
$this->parseWeekDayNames($xml,$data);
$this->parseEraNames($xml,$data);
$this->parseDateFormats($xml,$data);
$this->parseTimeFormats($xml,$data);
$this->parseDateTimeFormat($xml,$data);
$this->parsePeriodNames($xml,$data);
$this->parseOrientation($xml,$data);
$this->addPluralRules($data, $locale);
$data=str_replace("\r",'',var_export($data,true));
$locale=substr(basename($path),0,-4);
$content=<<<EOD
/**
* Locale data for '$locale'.
*
* This file is automatically generated by yiic cldr command.
*
* Copyright © 1991-2007 Unicode, Inc. All rights reserved.
* Distributed under the Terms of Use in http://www.unicode.org/copyright.html.
*
* @copyright 2008-2013 Yii Software LLC (http://www.yiiframework.com/license/)
*/
return $data;
EOD;
file_put_contents($i18nDataPath.DIRECTORY_SEPARATOR.strtolower($locale).'.php',"<?php\n".$content."\n");
echo "done.\n";
}
protected function parseVersion($xml,&$data)
{
preg_match('/[\d\.]+/',(string)$xml->identity->version['number'],$matches);
$data['version']=$matches[0];
}
protected function parseNumberSymbols($xml,&$data)
{
foreach($xml->xpath('/ldml/numbers/symbols/*') as $symbol)
{
$name=$symbol->getName();
if(!isset($data['numberSymbols'][$name]) || (string)$symbol['draft']==='')
$data['numberSymbols'][$name]=(string)$symbol;
}
}
protected function parseNumberFormats($xml,&$data)
{
$pattern=$xml->xpath('/ldml/numbers/decimalFormats/decimalFormatLength/decimalFormat/pattern');
if(isset($pattern[0]))
$data['decimalFormat']=(string)$pattern[0];
$pattern=$xml->xpath('/ldml/numbers/scientificFormats/scientificFormatLength/scientificFormat/pattern');
if(isset($pattern[0]))
$data['scientificFormat']=(string)$pattern[0];
$pattern=$xml->xpath('/ldml/numbers/percentFormats/percentFormatLength/percentFormat/pattern');
if(isset($pattern[0]))
$data['percentFormat']=(string)$pattern[0];
$pattern=$xml->xpath('/ldml/numbers/currencyFormats/currencyFormatLength/currencyFormat/pattern');
if(isset($pattern[0]))
$data['currencyFormat']=(string)$pattern[0];
}
protected function parseCurrencySymbols($xml,&$data)
{
$currencies=$xml->xpath('/ldml/numbers/currencies/currency');
foreach($currencies as $currency)
{
if((string)$currency->symbol!='')
$data['currencySymbols'][(string)$currency['type']]=(string)$currency->symbol;
}
}
protected function parseLanguages($xml,&$data)
{
$languages=$xml->xpath('/ldml/localeDisplayNames/languages/language');
foreach($languages as $language)
{
if((string)$language!='')
$data['languages'][strtolower(str_replace('-','_',(string)$language['type']))]=(string)$language;
}
}
protected function parseScripts($xml,&$data)
{
$scripts=$xml->xpath('/ldml/localeDisplayNames/scripts/script');
foreach($scripts as $script)
{
if((string)$script!='')
$data['scripts'][strtolower(str_replace('-','_',(string)$script['type']))]=(string)$script;
}
}
protected function parseTerritories($xml,&$data)
{
$territories=$xml->xpath('/ldml/localeDisplayNames/territories/territory');
foreach($territories as $territory)
{
if((string)$territory!='')
$data['territories'][strtolower(str_replace('-','_',(string)$territory['type']))]=(string)$territory;
}
}
protected function parseMonthNames($xml,&$data)
{
$monthTypes=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/months/monthContext[@type=\'format\']/monthWidth');
if(is_array($monthTypes))
{
foreach($monthTypes as $monthType)
{
$names=array();
foreach($monthType->xpath('month') as $month)
$names[(string)$month['type']]=(string)$month;
if($names!==array())
foreach($names as $type=>$name)
$data['monthNames'][(string)$monthType['type']][$type]=$name;
}
}
if(!isset($data['monthNames']['abbreviated']))
$data['monthNames']['abbreviated']=$data['monthNames']['wide'];
$monthTypes=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/months/monthContext[@type=\'stand-alone\']/monthWidth');
if(is_array($monthTypes))
{
foreach($monthTypes as $monthType)
{
$names=array();
foreach($monthType->xpath('month') as $month)
$names[(string)$month['type']]=(string)$month;
if($names!==array())
foreach($names as $type=>$name)
$data['monthNamesSA'][(string)$monthType['type']][$type]=$name;
}
}
}
protected function parseWeekDayNames($xml,&$data)
{
static $mapping=array(
'sun'=>0,
'mon'=>1,
'tue'=>2,
'wed'=>3,
'thu'=>4,
'fri'=>5,
'sat'=>6,
);
$dayTypes=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/days/dayContext[@type=\'format\']/dayWidth');
if(is_array($dayTypes))
{
foreach($dayTypes as $dayType)
{
$names=array();
foreach($dayType->xpath('day') as $day)
$names[$mapping[(string)$day['type']]]=(string)$day;
if($names!==array())
$data['weekDayNames'][(string)$dayType['type']]=$names;
}
}
if(!isset($data['weekDayNames']['abbreviated']))
$data['weekDayNames']['abbreviated']=$data['weekDayNames']['wide'];
$dayTypes=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/days/dayContext[@type=\'stand-alone\']/dayWidth');
if(is_array($dayTypes))
{
foreach($dayTypes as $dayType)
{
$names=array();
foreach($dayType->xpath('day') as $day)
$names[$mapping[(string)$day['type']]]=(string)$day;
if($names!==array())
$data['weekDayNamesSA'][(string)$dayType['type']]=$names;
}
}
}
protected function parsePeriodNames($xml,&$data)
{
$am=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/dayPeriods/dayPeriodContext[@type=\'format\']/dayPeriodWidth[@type=\'wide\']/dayPeriod[@type=\'am\']');
if(is_array($am) && isset($am[0]))
$data['amName']=(string)$am[0];
$pm=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/dayPeriods/dayPeriodContext[@type=\'format\']/dayPeriodWidth[@type=\'wide\']/dayPeriod[@type=\'pm\']');
if(is_array($pm) && isset($pm[0]))
$data['pmName']=(string)$pm[0];
}
protected function parseEraNames($xml,&$data)
{
$era=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/eras/eraAbbr');
if(is_array($era) && isset($era[0]))
{
foreach($era[0]->xpath('era') as $e)
$data['eraNames']['abbreviated'][(string)$e['type']]=(string)$e;
}
$era=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/eras/eraNames');
if(is_array($era) && isset($era[0]))
{
foreach($era[0]->xpath('era') as $e)
$data['eraNames']['wide'][(string)$e['type']]=(string)$e;
}
else if(!isset($data['eraNames']['wide']))
$data['eraNames']['wide']=$data['eraNames']['abbreviated'];
$era=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/eras/eraNarrow');
if(is_array($era) && isset($era[0]))
{
foreach($era[0]->xpath('era') as $e)
$data['eraNames']['narrow'][(string)$e['type']]=(string)$e;
}
else if(!isset($data['eraNames']['narrow']))
$data['eraNames']['narrow']=$data['eraNames']['abbreviated'];
}
protected function parseDateFormats($xml,&$data)
{
$types=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/dateFormats/dateFormatLength');
if(is_array($types))
{
foreach($types as $type)
{
$pattern=$type->xpath('dateFormat/pattern');
$data['dateFormats'][(string)$type['type']]=(string)$pattern[0];
}
}
}
protected function parseTimeFormats($xml,&$data)
{
$types=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/timeFormats/timeFormatLength');
if(is_array($types))
{
foreach($types as $type)
{
$pattern=$type->xpath('timeFormat/pattern');
$data['timeFormats'][(string)$type['type']]=(string)$pattern[0];
}
}
}
protected function parseDateTimeFormat($xml,&$data)
{
$types=$xml->xpath('/ldml/dates/calendars/calendar[@type=\'gregorian\']/dateTimeFormats/dateTimeFormatLength');
if(is_array($types) && isset($types[0]))
{
$picked = $types[0];
foreach($types as $element) {
$attrs = $element->attributes();
if($attrs['type'] == 'medium')
{
$picked = $element;
break;
}
}
$pattern=$picked->xpath('dateTimeFormat/pattern');
$data['dateTimeFormat']=(string)$pattern[0];
}
}
protected function parseOrientation($xml,&$data)
{
$orientation=$xml->xpath('/ldml/layout/orientation[@characters=\'right-to-left\']');
if(!empty($orientation))
$data['orientation']='rtl';
else if(!isset($data['orientation']))
$data['orientation']='ltr';
}
/**
* @see http://cldr.unicode.org/index/cldr-spec/plural-rules
*/
protected function parsePluralRules($xml)
{
echo "Processing plural.xml...";
$patterns = array(
'/\s+is\s+not\s+/i'=>'!=', //is not
'/\s+is\s+/i'=>'==', //is
'/n\s+mod\s+(\d+)/i'=>'fmod(n,$1)', //mod (CLDR's "mod" is "fmod()", not "%")
'/^(.*?)\s+not\s+(?:in|within)\s+(\d+)\.\.(\d+)/i'=>'($1<$2||$1>$3)', //not in, not within
'/^(.*?)\s+within\s+(\d+)\.\.(\d+)/i'=>'($1>=$2&&$1<=$3)', //within
'/^(.*?)\s+in\s+(\d+)\.\.(\d+)/i'=>'($1>=$2&&$1<=$3&&fmod($1,1)==0)', //in
);
foreach($xml->plurals->pluralRules as $node)
{
$attributes=$node->attributes();
$locales=explode(' ',$attributes['locales']);
$rules=array();
if(!empty($node->pluralRule))
{
foreach($node->pluralRule as $rule)
{
$expr_or=preg_split('/\s+or\s+/i', $rule);
foreach ($expr_or as $key_or => $val_or)
{
$expr_and=preg_split('/\s+and\s+/i', $val_or);
$expr_and=preg_replace(array_keys($patterns), array_values($patterns), $expr_and);
$expr_or[$key_or]=implode('&&', $expr_and);
}
$rules[]=implode('||', $expr_or);
}
//append last rule to match "other"
$rules[] = 'true';
foreach ($locales as $locale)
{
$this->pluralRules[$locale] = $rules;
}
}
}
echo "Done.\n";
}
protected function addPluralRules(&$data, $locale)
{
if (!empty($this->pluralRules[$locale]))
$data['pluralRules']=$this->pluralRules[$locale];
}
}

View file

@ -0,0 +1,79 @@
<?php
class GuideLatexCommand extends CConsoleCommand
{
function getHelp()
{
return <<<EOD
USAGE
yiic guidelatex
DESCRIPTION
This command generates latex files for the definitive guide.
The generated latex files are stored in the guide directory.
EOD;
}
function getSourceDir()
{
return dirname(__FILE__).'/../../docs/guide';
}
function getOutputDir()
{
return dirname(__FILE__).'/guide';
}
function run($args)
{
require_once(dirname(__FILE__).'/markdown/MarkdownHtml2Tex.php');
$sourcePath=$this->getSourceDir();
$chapters=$this->getGuideTopics();
$toc = '';
foreach($chapters as $chapter=>$sections)
{
$toc .= sprintf("\\chapter{%s}\n", $chapter);
foreach($sections as $path=>$section)
{
echo "creating '$section'...";
$content=file_get_contents($sourcePath."/{$path}.txt");
$this->createLatexFile($chapter,$section,$content, $path);
echo "done\n";
$toc .= sprintf("\\input{%s}\n", $path);
}
}
$main_file = sprintf('%s/main.tex', $this->getOutputDir());
file_put_contents($main_file, $toc);
}
function getGuideTopics()
{
$file = $this->getSourceDir().'/toc.txt';
$lines=file($file);
$chapter='';
$guideTopics=array();
foreach($lines as $line)
{
if(($line=trim($line))==='')
continue;
if($line[0]==='*')
$chapter=trim($line,'* ');
else if($line[0]==='-' && preg_match('/\[(.*?)\]\((.*?)\)/',$line,$matches))
$guideTopics[$chapter][$matches[2]]=$matches[1];
}
return $guideTopics;
}
function createLatexFile($chapter, $section, $content, $path)
{
$parser=new MarkdownParserLatex;
$content=$parser->transform($content);
$img_src = $this->getSourceDir().'/images';
$img_dst = $this->getOutputDir();
$html2tex = new MarkdownHtml2Tex($img_src, $img_dst);
$tex = $html2tex->parse_html($content, $path);
$filename = sprintf('%s/%s.tex', $this->getOutputDir(), $path);
file_put_contents($filename, $tex);
}
}

View file

@ -0,0 +1,219 @@
<?php
/**
* LiteCommand class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* LiteCommand generates yiilite.php by merging commonly used Yii class
* files into a single one and removes all comments and trace statements.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package system.build
* @since 1.0
*/
class LiteCommand extends CConsoleCommand
{
public function getHelp()
{
return <<<EOD
USAGE
build lite
DESCRIPTION
This command generates yiilite.php by merging commonly used Yii class
files into a single one and removes all comments and trace statements.
You should not execute this command unless you change some framework
file and need to update yii.php accordingly.
EOD;
}
/**
* Execute the action.
* @param array command line parameters specific for this command
*/
public function run($args)
{
$lastupdate=date('Y/m/d H:i:s');
$comments="
/**
* Yii bootstrap file.
*
* This file is automatically generated using 'build lite' command.
* It is the result of merging commonly used Yii class files with
* comments and trace statements removed away.
*
* By using this file instead of yii.php, an Yii application may
* improve performance due to the reduction of PHP parsing time.
* The performance improvement is especially obvious when PHP APC extension
* is enabled.
*
* DO NOT modify this file manually.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
* @version \$Id: \$
* @since 1.0
*/
";
$content=$this->minifyYii(dirname(__FILE__).'/lite/index.php');
$content="<?php\n".preg_replace('/^(\?>|<\?php)/mu','',$content)."\n?>";
$content=$this->stripComments($content);
$content=preg_replace('/^require(_once)?.*\s*;\s*$/mu','',$content);
$content=preg_replace('/^\s*Yii::trace.*\s*;\s*$/mu','',$content);
// $content=preg_replace('/^\s*Yii::(begin|end)Profile.*\s*;\s*$/mu','',$content);
$content=$this->stripEmptyLines($content);
$content=substr_replace($content,$comments,5,0);
file_put_contents(YII_PATH.DIRECTORY_SEPARATOR.'yiilite.php',$content);
echo "Done.\n";
}
protected function minifyYii($entryScript)
{
try
{
ob_start();
$this->runRequest($entryScript);
$_SERVER['REQUEST_URI']='/index.php';
$this->runRequest($entryScript,array('r'=>'post'));
ob_end_clean();
}
catch(CException $e)
{
echo $e;
die();
}
$classes=array_merge(get_declared_classes(),get_declared_interfaces());
$results=array();
foreach($classes as $class)
{
$c=new ReflectionClass($class);
if(strpos($c->getFileName(),YII_PATH)===0 && strpos($c->getFileName(),YII_PATH.DIRECTORY_SEPARATOR.'console')!==0)
$results[$class]=$c->getFileName();
}
$results=$this->sortByInheritance($results);
$content='';
foreach($results as $fileName=>$class)
$content.="\n".file_get_contents($fileName);
return $content;
}
protected function sortByInheritance($classes)
{
$results=array();
foreach($classes as $class=>$fileName)
$this->processClass($class,$classes,$results);
return $results;
}
protected function processClass($class,$classes,&$results)
{
$parentClass=get_parent_class($class);
if($parentClass!==false && isset($classes[$parentClass]))
{
if(!isset($results[$classes[$parentClass]]))
$this->processClass($parentClass,$classes,$results);
}
if(!isset($results[$classes[$class]]))
{
// some file may contain multiple classes
// we only want to include when the primary one appears
if($class[0]!=='C' || $class===substr(basename($classes[$class]),0,-4))
$results[$classes[$class]]=$class;
}
}
protected function runRequest($entryScript,$params=array())
{
restore_error_handler();
restore_exception_handler();
Yii::setApplication(null);
Yii::setPathOfAlias('application',null);
$_GET=$params;
require($entryScript);
}
protected function stripComments($source)
{
$tokens = token_get_all($source);
$output = '';
foreach ($tokens as $token)
{
if (is_string($token))
{
// simple 1-character token
$output .= $token;
}
else
{
// token array
list($id, $text) = $token;
switch ($id) {
case T_DOC_COMMENT: // and this
// no action on comments
break;
default:
// anything else -> output "as is"
$output .= $text;
break;
}
}
}
return $output;
}
protected function stripEmptyLines($string)
{
$string = preg_replace("/[\r\n]+[\s\t]*[\r\n]+/", "\n", $string);
$string = preg_replace("/^[\s\t]*[\r\n]+/", "", $string);
return $string;
}
protected function unfoldFile($fileName)
{
static $unfoldedFiles=array();
$pattern='^(Yii::import|require_once|include_once)\s*\(.*?[\'"]([^\*]*?)[\'"].*?\);';
echo "adding $fileName...\n";
$content=file_get_contents($fileName);
while(preg_match("/$pattern/m",$content,$matches,PREG_OFFSET_CAPTURE))
{
$offset=$matches[0][1];
$length=strlen($matches[0][0]);
$type=$matches[1][0];
$file=trim($matches[2][0],"'\"");
if($type==='Yii::import')
{
// replace system with framework path and dot with directory separator
$file=substr_replace(strtr($file,'.',DIRECTORY_SEPARATOR),YII_PATH,0,6).'.php';
}
else
{
$file=YII_PATH.$file;
}
if(($file=realpath($file))===false || !is_file($file))
die('Unable to process file '.$fileName.' about '.$matches[0][0]);
if(isset($unfoldedFiles[$file]))
{
$content=substr_replace($content,'',$offset,$length);
}
else
{
$unfoldedFiles[$file]=true;
$content=substr_replace($content,$this->unfoldFile($file),$offset,$length);
}
}
return $content;
}
}

View file

@ -0,0 +1,162 @@
<?php
/**
* TranslationsCommand class file.
*
* @author Alexander Makarov <sam@rmcreative.ru>
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2012 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* TranslationsCommand handles tasks related to framework translations.
*
* @author Alexander Makarov <sam@rmcreative.ru>
* @package system.build
* @since 1.1.11
*/
class TranslationsCommand extends CConsoleCommand
{
public function getHelp()
{
return <<<EOD
This command handles tasks related to framework translations.
USAGE
build translations report --sourcePath=<path> --translationPath=<path>
PARAMETERS
* sourcePath: required, the directory where the original documentation files are.
* translationPath: required, the directory where the translated documentation files are.
* title: optional, custom report title
EXAMPLES
* build translations report --sourcePath="../docs/guide" --translationPath="../docs/guide/ru" --title="Russian guide translation report" > report_guide_ru.html
* build translations report --sourcePath="../docs/blog" --translationPath="../docs/blog/ru" --title="Russian blog translation report" > report_blog_ru.html
* build translations report --sourcePath="../framework/views" --translationPath="../framework/views/ru" --title="Russian framework views translation report" > report_views_ru.html
EOD;
}
public function actionIndex()
{
echo $this->getHelp();
}
/**
* Generates summary report for given translation and original directories
*
* @param string $sourcePath the directory where the original documentation files are
* @param string $translationPath the directory where the translated documentation files are
* @param string $title custom title to use for report
*/
public function actionReport($sourcePath, $translationPath, $title = 'Translation report')
{
$sourcePath=trim($sourcePath, '/\\');
$translationPath=trim($translationPath, '/\\');
$results = array();
$dir = new DirectoryIterator($sourcePath);
foreach ($dir as $fileinfo) {
if (!$fileinfo->isDot() && !$fileinfo->isDir()) {
$translatedFilePath = $translationPath.'/'.$fileinfo->getFilename();
$sourceFilePath = $sourcePath.'/'.$fileinfo->getFilename();
$errors = $this->checkFiles($translatedFilePath);
$diff = empty($errors) ? $this->getDiff($translatedFilePath, $sourceFilePath) : '';
if(!empty($diff)) {
$errors[] = 'Translation outdated.';
}
$result = array(
'errors' => $errors,
'diff' => $diff,
);
$results[$fileinfo->getFilename()] = $result;
}
}
// checking if there are obsolete translation files
$dir = new DirectoryIterator($translationPath);
foreach ($dir as $fileinfo) {
if (!$fileinfo->isDot() && !$fileinfo->isDir()) {
$translatedFilePath = $translationPath.'/'.$fileinfo->getFilename();
$errors = $this->checkFiles(null, $translatedFilePath);
if(!empty($errors)) {
$results[$fileinfo->getFilename()]['errors'] = $errors;
}
}
}
$this->renderFile(dirname(__FILE__).'/translations/report_html.php', array(
'results' => $results,
'sourcePath' => $sourcePath,
'translationPath' => $translationPath,
'title' => $title,
));
}
/**
* Checks for files existence
*
* @param string $translatedFilePath
* @param string $sourceFilePath
* @return array errors
*/
protected function checkFiles($translatedFilePath = null, $sourceFilePath = null)
{
$errors = array();
if($translatedFilePath!==null && !file_exists($translatedFilePath)) {
$errors[] = 'Translation does not exist.';
}
if($sourceFilePath!==null && !file_exists($sourceFilePath)) {
$errors[] = 'Source does not exist.';
}
return $errors;
}
/**
* Getting DIFF from git
*
* @param string $translatedFilePath path pointing to translated file
* @param string $sourceFilePath path pointing to original file
* @return string DIFF
*/
protected function getDiff($translatedFilePath, $sourceFilePath)
{
$lastTranslationHash = shell_exec('git log -1 --format=format:"%H" -- '.$translatedFilePath);
return shell_exec('git diff '.$lastTranslationHash.'..HEAD -- '.$sourceFilePath);
}
/**
* Adds all necessary HTML tags and classes to diff output
*
* @param string $diff DIFF
* @return string highlighted DIFF
*/
protected function highlightDiff($diff)
{
$lines = explode("\n", $diff);
foreach ($lines as $key => $val) {
if (mb_substr($val,0,1,'utf-8') === '@') {
$lines[$key] = '<span class="info">'.CHtml::encode($val).'</span>';
}
else if (mb_substr($val,0,1,'utf-8') === '+') {
$lines[$key] = '<ins>'.CHtml::encode($val).'</ins>';
}
else if (mb_substr($val,0,1,'utf-8') === '-') {
$lines[$key] = '<del>'.CHtml::encode($val).'</del>';
}
else {
$lines[$key] = CHtml::encode($val);
}
}
return implode("\n", $lines);
}
}

View file

@ -0,0 +1,196 @@
<?php
/**
* Utf8Command class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* Utf8Command will help you to make sure files are encoded properly.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @package system.build
* @since 1.1.11
*/
class Utf8Command extends CConsoleCommand
{
public function getHelp()
{
return <<<EOD
USAGE
yiic utf8 <action> <file>
DESCRIPTION
This command can detect and remove UTF-8 BOM headers. It also supports
detection of wrong file encodings (non UTF-8).
PARAMETERS
* action: required, the name of the action to execute. The following
actions are available:
- checkbom: checks for UTF-8 BOM header
- fixbom: removes UTF-8 BOM header
- checkencoding: checks for correct UTF-8 encoding
* file: optional, the file to process. If not set, all (!) translation files
will be processed.
EOD;
}
public function run($args)
{
if(!isset($args[0]))
$this->usageError("Please specify a valid action");
if(!in_array($args[0],array('checkbom','fixbom','checkencoding')))
$this->usageError("Invalid action '{$args[0]}' specified");
if(isset($args[1]) && !file_exists($args[1]))
$this->usageError("File '{$args[1]}' does not exist");
if('checkbom'===$args[0])
{
if(isset($args[1]))
{
if($this->checkBom($args[1]))
echo "UTF-8 BOM header detected";
else
echo "File seems to be clean";
}
else
{
$affectedFiles='';
foreach($this->findTranslationFiles() as $file)
{
if($this->checkBom($file))
$affectedFiles.="{$file}\r\n";
}
if(empty($affectedFiles))
echo "All files seem to be clean";
else
echo "Detected UTF-8 BOM header in the following files:\r\n".trim($affectedFiles);
}
}
elseif('fixbom'===$args[0])
{
if(isset($args[1]))
{
if(!$this->checkBom($args[1]))
echo "Nothing to fix, no UTF-8 BOM header detected";
else
{
$this->fixBom($args[1]);
echo "UTF-8 BOM header removed";
}
}
else
{
$affectedFiles='';
foreach($this->findTranslationFiles() as $file)
{
if($this->checkBom($file))
{
$affectedFiles.="{$file}\r\n";
$this->fixBom($file);
}
}
if(empty($affectedFiles))
echo "Nothing to fix, all files seem to be clean";
else
echo "Removed UTF-8 BOM header from the following files:\r\n".trim($affectedFiles);
}
}
elseif('checkencoding'===$args[0])
{
if(isset($args[1]))
{
if($this->checkEncoding($args[1]))
echo "File does have a correct UTF-8 encoding";
else
echo "Wrong encoding detected";
}
else
{
$affectedFiles='';
foreach($this->findTranslationFiles() as $file)
{
if(!$this->checkEncoding($file))
$affectedFiles.="{$file}\r\n";
}
if(empty($affectedFiles))
echo "All files seem to have the correct UTF-8 encoding";
else
echo "Wrong encoding of the following files detected:\r\n".trim($affectedFiles);
}
}
}
public function checkBom($file)
{
$data=file_get_contents($file,false,null,0,3);
return bin2hex($data)==='efbbbf';
}
public function fixBom($file)
{
$data=file_get_contents($file,false,null,3);
file_put_contents($file,$data);
}
public function checkEncoding($file)
{
$data=file_get_contents($file);
return preg_match('/./u',$data) && $this->is_utf8($data);
}
public function findTranslationFiles()
{
return CFileHelper::findFiles(
dirname(Yii::app()->basePath),
array(
'fileTypes' => array('txt', 'php'),
'exclude' => array(
'/index.php',
'/members.txt',
'/blog/source',
'/css',
'/framework',
'/guide/source',
'/protected',
'/requirements/views/source',
'/views/source',
),
)
);
}
/** php.net/manual/de/function.mb-detect-encoding.php#85294 */
public function is_utf8($str) {
$c=0; $b=0;
$bits=0;
$len=strlen($str);
for($i=0; $i<$len; $i++){
$c=ord($str[$i]);
if($c > 128){
if(($c >= 254)) return false;
elseif($c >= 252) $bits=6;
elseif($c >= 248) $bits=5;
elseif($c >= 240) $bits=4;
elseif($c >= 224) $bits=3;
elseif($c >= 192) $bits=2;
else return false;
if(($i+$bits) > $len) return false;
while($bits > 1){
$i++;
$b=ord($str[$i]);
if($b < 128 || $b > 191) return false;
$bits--;
}
}
}
return true;
}
}

View file

@ -0,0 +1,817 @@
<?php
/**
* ApiModel class file.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/
* @copyright 2008-2013 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
/**
* ApiModel represents the documentation for the Yii framework.
* @author Qiang Xue <qiang.xue@gmail.com>
* @package system.build
* @since 1.0
*/
class ApiModel
{
public $classes=array();
public $packages;
private $_currentClass;
public function build($sourceFiles)
{
$this->findClasses($sourceFiles);
$this->processClasses();
}
protected function findClasses($sourceFiles)
{
$this->classes=array();
foreach($sourceFiles as $file)
require_once($file);
$classes=array_merge(get_declared_classes(),get_declared_interfaces());
foreach($classes as $class)
{
$r=new ReflectionClass($class);
if(in_array($r->getFileName(),$sourceFiles))
$this->classes[$class]=true;
}
ksort($this->classes);
}
protected function processClasses()
{
$this->packages=array();
foreach($this->classes as $class=>$value)
{
$doc=$this->processClass(new ReflectionClass($class));
$this->classes[$class]=$doc;
$this->packages[$doc->package][]=$class;
}
ksort($this->packages);
// find out child classes for each class or interface
foreach($this->classes as $class)
{
if(isset($class->parentClasses[0]))
{
$parent=$class->parentClasses[0];
if(isset($this->classes[$parent]))
$this->classes[$parent]->subclasses[]=$class->name;
}
foreach($class->interfaces as $interface)
{
if(isset($this->classes[$interface]))
$this->classes[$interface]->subclasses[]=$class->name;
}
}
}
protected function processClass($class)
{
$doc=new ClassDoc;
$doc->name=$class->getName();
$doc->loadSource($class);
$this->_currentClass=$doc->name;
for($parent=$class;$parent=$parent->getParentClass();)
$doc->parentClasses[]=$parent->getName();
foreach($class->getInterfaces() as $interface)
$doc->interfaces[]=$interface->getName();
$doc->isInterface=$class->isInterface();
$doc->isAbstract=$class->isAbstract();
$doc->isFinal=$class->isFinal();
$doc->methods=$this->processMethods($class);
$doc->properties=$this->processProperties($class);
$doc->signature=($doc->isInterface?'interface ':'class ').$doc->name;
if($doc->isFinal)
$doc->signature='final '.$doc->signature;
if($doc->isAbstract && !$doc->isInterface)
$doc->signature='abstract '.$doc->signature;
if(in_array('CComponent',$doc->parentClasses))
{
$doc->properties=array_merge($doc->properties,$this->processComponentProperties($class));
$doc->events=$this->processComponentEvents($class);
}
ksort($doc->properties);
foreach($doc->properties as $property)
{
if($property->isProtected)
$doc->protectedPropertyCount++;
else
$doc->publicPropertyCount++;
if(!$property->isInherited)
$doc->nativePropertyCount++;
}
foreach($doc->methods as $method)
{
if($method->isProtected)
$doc->protectedMethodCount++;
else
$doc->publicMethodCount++;
if(!$method->isInherited)
$doc->nativeMethodCount++;
}
foreach($doc->events as $event)
{
if(!$event->isInherited)
$doc->nativeEventCount++;
}
$this->processComment($doc,$class->getDocComment());
return $doc;
}
protected function processComment($doc,$comment)
{
$comment=strtr(trim(preg_replace('/^\s*\**( |\t)?/m','',trim($comment,'/'))),"\r",'');
if(preg_match('/^\s*@\w+/m',$comment,$matches,PREG_OFFSET_CAPTURE))
{
$meta=substr($comment,$matches[0][1]);
$comment=trim(substr($comment,0,$matches[0][1]));
}
else
$meta='';
if(($pos=strpos($comment,"\n"))!==false)
$doc->introduction=$this->processDescription(substr($comment,0,$pos));
else
$doc->introduction=$this->processDescription($comment);
$doc->description=$this->processDescription($comment);
$this->processTags($doc,$meta);
}
protected function processDescription($text)
{
if(($text=trim($text))==='')
return '';
$text=preg_replace_callback('/\{@include\s+([^\s\}]+)\s*\}/s',array($this,'processInclude'),$text);
$text=preg_replace('/^(\r| |\t)*$/m',"<br/><br/>",$text);
$text=preg_replace_callback('/<pre>(.*?)<\/pre>/is',array($this,'processCode'),$text);
$text=preg_replace_callback('/\{@link\s+([^\s\}]+)(.*?)\}/s',array($this,'processLink'),$text);
return $text;
}
protected function processCode($matches)
{
$match=preg_replace('/<br\/><br\/>/','',$matches[1]);
return "<pre>".htmlspecialchars($match)."</pre>";
}
protected function resolveInternalUrl($url)
{
$url=rtrim($url,'()');
if(($pos=strpos($url,'::'))!==false)
{
$class=substr($url,0,$pos);
$method=substr($url,$pos+2);
}
else if(isset($this->classes[$url]))
return $url;
else
{
$class=$this->_currentClass;
$method=$url;
}
return $this->getMethodUrl($class,$method);
}
protected function getMethodUrl($class,$method)
{
if(!isset($this->classes[$class]))
return '';
if(method_exists($class,$method) || property_exists($class,$method))
return $class.'::'.$method;
if(method_exists($class,'get'.$method) || method_exists($class,'set'.$method))
return $class.'::'.$method;
if(($parent=get_parent_class($class))!==false)
return $this->getMethodUrl($parent,$method);
else
return '';
}
protected function processLink($matches)
{
$url=$matches[1];
if(($text=trim($matches[2]))==='')
$text=$url;
if(preg_match('/^(http|ftp):\/\//i',$url)) // an external URL
return "<a href=\"$url\">$text</a>";
$url=$this->resolveInternalUrl($url);
return $url===''?$text:'{{'.$url.'|'.$text.'}}';
}
protected function processInclude($matches)
{
$class=new ReflectionClass($this->_currentClass);
$fileName=dirname($class->getFileName()).DIRECTORY_SEPARATOR.$matches[1];
if(is_file($fileName))
return file_get_contents($fileName);
else
return $matches[0];
}
protected function processTags($object,$comment)
{
$tags=preg_split('/^\s*@/m',$comment,-1,PREG_SPLIT_NO_EMPTY);
foreach($tags as $tag)
{
$segs=preg_split('/\s+/',trim($tag),2);
$tagName=$segs[0];
$param=isset($segs[1])?trim($segs[1]):'';
$tagMethod='tag'.ucfirst($tagName);
if(method_exists($this,$tagMethod))
$this->$tagMethod($object,$param);
else if(property_exists($object,$tagName))
$object->$tagName=$param;
}
}
protected function processMethods($class)
{
$methods=array();
foreach($class->getMethods() as $method)
{
if($method->isPublic() || $method->isProtected())
{
$doc=$this->processMethod($class,$method);
$methods[$doc->name]=$doc;
}
}
ksort($methods);
return $methods;
}
protected function processMethod($class,$method)
{
$doc=new MethodDoc;
$doc->name=$method->getName();
$doc->loadSource($method);
$doc->definedBy=$method->getDeclaringClass()->getName();
$doc->isAbstract=$method->isAbstract();
$doc->isFinal=$method->isFinal();
$doc->isProtected=$method->isProtected();
$doc->isStatic=$method->isStatic();
$doc->isInherited=$doc->definedBy!==$class->getName();
$doc->input=array();
foreach($method->getParameters() as $param)
{
$p=new ParamDoc;
$p->name=$param->getName();
$p->isOptional=$param->isOptional();
if($param->isDefaultValueAvailable())
$p->defaultValue=$param->getDefaultValue();
$p->isPassedByReference=$param->isPassedByReference();
$doc->input[]=$p;
}
reset($doc->input);
$this->processComment($doc,$method->getDocComment());
$params=array();
foreach($doc->input as $param)
{
$type=empty($param->type)?'':$this->getTypeUrl($param->type).' ';
if($param->isOptional)
$params[]=$type.($param->isPassedByReference?'&':'').'$'.$param->name.'='.str_replace("\r",'',var_export($param->defaultValue,true));
else
$params[]=$type.($param->isPassedByReference?'&':'').'$'.$param->name;
}
$doc->signature='{{'.$class->name.'::'.$doc->name.'|<b>'.$doc->name.'</b>}}('.implode(', ',$params).')';
if($doc->output!==null)
$doc->signature=$this->getTypeUrl($doc->output->type).' '.$doc->signature;
else
$doc->signature='void '.$doc->signature;
if(($modifier=implode(' ',Reflection::getModifierNames($method->getModifiers())))!=='')
$doc->signature=$modifier.' '.$doc->signature;
return $doc;
}
protected function getTypeUrl($type)
{
if(isset($this->classes[$type]) && $type!==$this->_currentClass)
return '{{'.$type.'|'.$type.'}}';
else
return $type;
}
protected function processProperties($class)
{
$properties=array();
foreach($class->getProperties() as $property)
{
if($property->isPublic() || $property->isProtected())
{
$p=$this->processProperty($class,$property);
$properties[$p->name]=$p;
}
}
return $properties;
}
protected function processProperty($class,$property)
{
$doc=new PropertyDoc;
$doc->name=$property->getName();
$doc->definedBy=$property->getDeclaringClass()->getName();
$doc->readOnly=false;
$doc->isStatic=$property->isStatic();
$doc->isProtected=$property->isProtected();
$doc->isInherited=$doc->definedBy!==$class->getName();
$this->processComment($doc,$property->getDocComment());
$doc->signature='<b>$'.$doc->name.'</b>;';
if($doc->type!==null)
$doc->signature=$this->getTypeUrl($doc->type) . ' ' . $doc->signature;
if(($modifier=implode(' ',Reflection::getModifierNames($property->getModifiers())))!=='')
$doc->signature=$modifier.' '.$doc->signature;
return $doc;
}
protected function processComponentProperties($class)
{
$properties=array();
foreach($class->getMethods() as $method)
{
if($this->isPropertyMethod($method) && ($method->isPublic() || $method->isProtected()))
{
$p=$this->processComponentProperty($class,$method);
$properties[$p->name]=$p;
}
}
return $properties;
}
protected function processComponentProperty($class,$method)
{
$doc=new PropertyDoc;
$name=$method->getName();
$doc->name=strtolower($name[3]).substr($name,4);
$doc->isProtected=$method->isProtected();
$doc->isStatic=false;
$doc->readOnly=!$class->hasMethod('set'.substr($name,3));
$doc->definedBy=$method->getDeclaringClass()->getName();
$doc->isInherited=$doc->definedBy!==$class->getName();
$doc->getter=$this->processMethod($class,$method);
if(!$doc->readOnly)
$doc->setter=$this->processMethod($class,$class->getMethod('set'.substr($name,3)));
$this->processComment($doc,$method->getDocComment());
return $doc;
}
protected function processComponentEvents($class)
{
$events=array();
foreach($class->getMethods() as $method)
{
if($this->isEventMethod($method) && ($method->isPublic() || $method->isProtected()))
{
$e=$this->processComponentEvent($class,$method);
$events[$e->name]=$e;
}
}
return $events;
}
protected function processComponentEvent($class,$method)
{
$doc=new EventDoc;
$doc->name=$method->getName();
$doc->definedBy=$method->getDeclaringClass()->getName();
$doc->isInherited=$doc->definedBy!==$class->getName();
$doc->trigger=$this->processMethod($class,$method);
$this->processComment($doc,$method->getDocComment());
return $doc;
}
protected function tagParam($object,$comment)
{
if($object instanceof FunctionDoc)
{
$param=current($object->input);
if($param!==false)
{
$segs=preg_split('/\s+/',$comment,2);
$param->type=$segs[0];
if(preg_match('/\[\s*\]/',$param->type))
$param->type='array';
if(isset($segs[1]))
{
/*
* remove $variablename from description
*/
$segs[1]=trim(preg_replace('/^\$\w+/','',$segs[1]));
$param->description=$this->processDescription($segs[1]);
if(empty($object->introduction))
{
if(substr($object->name,0,3)=='set')
$object->introduction='Sets '.$param->description;
}
}
next($object->input);
}
}
}
protected function tagReturn($object,$comment)
{
$segs=preg_split('/\s+/',$comment,2);
if($object instanceof FunctionDoc)
{
$object->output=new ParamDoc;
$object->output->type=$segs[0];
if(isset($segs[1]))
{
$object->output->description=$this->processDescription($segs[1]);
if(empty($object->introduction))
{
/*
* If no custom introduction, add automatically
* with this getters introduction displayed in public methods table is resolved
*/
if(substr($object->name,0,5)=='getIs')
$object->introduction='Checks '.$object->output->description;
elseif(substr($object->name,0,3)=='get')
$object->introduction='Returns '.$object->output->description;
elseif(substr($object->name,0,3)=='has')
$object->introduction='Determines '.$object->output->description;
}
}
}
else if($object instanceof PropertyDoc)
{
$object->type=$segs[0];
if(isset($segs[1]) && empty($object->description))
{
if(($pos=strpos($segs[1],'.'))!==false)
$object->introduction=$this->processDescription(substr($segs[1],0,$pos+1));
else
$object->introduction=$this->processDescription($segs[1]);
$object->description=$this->processDescription($segs[1]);
}
}
}
protected function tagVar($object,$comment)
{
if($object instanceof PropertyDoc)
{
$segs=preg_split('/\s+/',$comment,2);
$object->type=$segs[0];
if(isset($segs[1]) && empty($object->description))
{
if(($pos=strpos($segs[1],'.'))!==false)
$object->introduction=$this->processDescription(substr($segs[1],0,$pos+1));
else
$object->introduction=$this->processDescription($segs[1]);
$object->description=$this->processDescription($segs[1]);
}
}
}
protected function tagSee($object,$comment)
{
$segs=preg_split('/\s+/',trim($comment),2);
$matches[1]=$segs[0];
$matches[2]=isset($segs[1])?$segs[1]:'';
$object->see[]=$this->processLink($matches);
}
protected function isPropertyMethod($method)
{
$methodName=$method->getName();
return $method->getNumberOfRequiredParameters()===0
&& !$method->isStatic()
&& strncasecmp($methodName,'get',3)===0
&& isset($methodName[3]);
}
protected function isEventMethod($method)
{
$methodName=$method->getName();
return strncasecmp($methodName,'on',2)===0
&& !$method->isStatic()
&& isset($methodName[2]);
}
protected function getClassFiles($basePath)
{
$files=array();
$folder=opendir($basePath);
while($file=readdir($folder))
{
if($file==='.' || $file==='..')
continue;
$fullPath=realpath($basePath.DIRECTORY_SEPARATOR.$file);
if($this->isValidPath($fullPath))
{
if(is_file($fullPath))
$files[]=$fullPath;
else
$files=array_merge($files,$this->getClassFiles($fullPath));
}
}
closedir($folder);
return $files;
}
protected function isValidPath($path)
{
if(is_file($path) && substr($path,-4)!=='.php')
return false;
$path=strtr($path,'\\','/');
foreach($this->_excludes as $exclude)
{
if(($exclude[0]==='/' && $this->_sourcePath.$exclude===$path) || ($exclude[0]!=='/' && basename($path)===$exclude))
return false;
}
return true;
}
protected function findTargets()
{
$oldClasses=get_declared_classes();
$oldInterfaces=get_declared_interfaces();
$oldFunctions=get_defined_functions();
$oldConstants=get_defined_constants(true);
$classFiles=$this->getClassFiles($this->_sourcePath);
require_once($this->_sourcePath.'/yii.php');
foreach($classFiles as $classFile)
require_once($classFile);
$classes=array_values(array_diff(get_declared_classes(),$oldClasses));
$interfaces=array_values(array_diff(get_declared_interfaces(),$oldInterfaces));
$classes=array_merge($classes,$interfaces);
$n=count($classes);
for($i=0;$i<$n;++$i)
{
$class=new ReflectionClass($classes[$i]);
$fileName=strtr($class->getFileName(),'\\','/');
foreach($this->_excludes as $exclude)
{
if(($exclude[0]==='/' && strpos($fileName,$this->_sourcePath.$exclude)===0))
{
unset($classes[$i]);
break;
}
}
}
sort($classes);
$newFunctions=get_defined_functions();
$newConstants=get_defined_constants(true);
$functions=array_values(array_diff($newFunctions['user'],$oldFunctions['user']));
$constants=$newConstants['user'];
return array($classes,$functions,$constants);
}
/*
* Calls checkSource for every file in $sourceFiles
* @param array $sourceFiles array of source file path that we need to check
*/
public function check($sourceFiles)
{
echo "Checking PHPDoc @param in source files ...\n";
foreach($sourceFiles as $no=>$sourceFile)
{
$this->checkSource($sourceFile);
}
echo "Done.\n\n";
}
/*
* Checks @param directives in a source file
* Detects:
* missing @param directive (there is no @param directive for a function parameter)
* missing function parameter (@param directive exists but that parameter is not in a function declaration)
* missmatch parameters (if @param directive has different parameter name than a function - possible spelling error or wrong order of @param directives)
*/
protected function checkSource($sourceFile)
{
$fileContent=file($sourceFile);
$docParam=array();
foreach($fileContent as $no=>$line)
{
/*
* Get lines with @param, and parameter name
*/
if(preg_match('/^\s*\*\s*@param\s[A-Za-z0-9_\|\[\]]+\s(\$\w+)\s./',$line,$matches,PREG_OFFSET_CAPTURE))
{
$docParam[]=array(
'docLine'=>$no+1,
'docName'=>$matches[1][0],
);
continue;
}
/*
* If function without parameters, there should be no parameters in $docParam
*/
if(preg_match('/^\s*\w+[\s\w]*\sfunction\s\w+\(\s*\)/',$line,$matches,PREG_OFFSET_CAPTURE))
{
if(isset($docParam[0])) {
$value=$docParam[0];
echo "ERROR.............: Parameter name not found!\n";
echo "Source file.......: ".$sourceFile."\n";
echo "PHPDoc line.......: ".$value['docLine']."\n";
echo "PHPDoc parameter..: ".$value['docName']."\n\n";
$docParam=array();
}
continue;
}
/*
* Get function variables in $matches[1][0]
*/
if(preg_match('/^\s*\w+[\s\w]*\sfunction\s\w+\((.+)\)/',$line,$matches,PREG_OFFSET_CAPTURE))
{
$params=explode(",",$matches[1][0]);
foreach($params as $br=>$param)
{
/*
* Strip anything that does not begin with $ (class types) eg. CHttpRequest $request
*/
$param=preg_replace('/^\w+/','',trim($param));
/*
* Strip default value if exists ex. data=array() (with spaces)
*/
$param=preg_replace('/\s*=.+/','',trim($param));
/*
* Strip & if pass by reference
*/
if($param[0]=='&')
$param=substr($param,1);
/*
* add parameter info to the docParam array
*/
$docParam[$br]['parameterName']=$param;
$docParam[$br]['parameterLine']=$no+1;
}
/*
* All info gathered, let's make some checking
*/
foreach($docParam as $value)
{
if(!isset($value['docLine']) || !isset($value['docName']) && isset($value['parameterName']))
{
echo "ERROR.............: Documentation not found!\n";
echo "Source file.......: ".$sourceFile."\n";
echo "Parameter line....: ".$value['parameterLine']."\n";
echo "Parameter name....: ".$value['parameterName']."\n\n";
}
if(!isset($value['parameterName']) || !isset($value['parameterLine']))
{
echo "ERROR.............: Parameter name not found!\n";
echo "Source file.......: ".$sourceFile."\n";
echo "PHPDoc line.......: ".$value['docLine']."\n";
echo "PHPDoc parameter..: ".$value['docName']."\n\n";
}
if( isset($value['docName']) && isset($value['parameterName']) && $value['docName']!==$value['parameterName'])
{
echo "ERROR.............: Wrong parameter order!\n";
echo "Source file.......: ".$sourceFile."\n";
echo "PHPDoc line.......: ".$value['docLine']."\n";
echo "PHPDoc parameter..: ".$value['docName']."\n";
echo "Parameter line....: ".$value['parameterLine']."\n";
echo "Parameter name....: ".$value['parameterName']."\n\n";
}
}
/*
* reset $docParam
*/
$docParam=array();
}
}
}
}
class BaseDoc
{
public $name;
public $since;
public $see;
public $introduction;
public $description;
public $sourcePath;
public $startLine;
public $endLine;
public function loadSource($reflection)
{
$this->sourcePath=str_replace('\\','/',str_replace(YII_PATH,'',$reflection->getFileName()));
$this->startLine=$reflection->getStartLine();
$this->endLine=$reflection->getEndLine();
}
public function getSourceUrl($baseUrl,$line=null)
{
if($line===null)
return $baseUrl.$this->sourcePath;
else
return $baseUrl.$this->sourcePath.'#'.$line;
}
public function getSourceCode()
{
$lines=file(YII_PATH.$this->sourcePath);
return implode("",array_slice($lines,$this->startLine-1,$this->endLine-$this->startLine+1));
}
}
class ClassDoc extends BaseDoc
{
public $parentClasses=array();
public $subclasses=array();
public $interfaces=array();
public $isInterface;
public $isAbstract;
public $isFinal;
public $signature;
public $properties=array();
public $methods=array();
public $events=array();
public $constants=array();
public $protectedPropertyCount=0;
public $publicPropertyCount=0;
public $protectedMethodCount=0;
public $publicMethodCount=0;
public $nativePropertyCount=0;
public $nativeMethodCount=0;
public $nativeEventCount=0;
public $package;
public $version;
}
class PropertyDoc extends BaseDoc
{
public $isProtected;
public $isStatic;
public $readOnly;
public $isInherited;
public $definedBy;
public $type;
public $signature;
public $getter;
public $setter;
}
class FunctionDoc extends BaseDoc
{
public $signature;
public $input=array();
public $output;
}
class MethodDoc extends FunctionDoc
{
public $isAbstract;
public $isFinal;
public $isProtected;
public $isStatic;
public $isInherited;
public $definedBy;
}
class EventDoc extends BaseDoc
{
public $isInherited;
public $definedBy;
public $trigger;
}
class ParamDoc
{
public $name;
public $description;
public $type;
public $isOptional;
public $defaultValue;
public $isPassedByReference;
}

View file

@ -0,0 +1,105 @@
pre {
color: #000000;
background-color: #FFF5E6;
font-family: "courier new", "times new roman", monospace;
line-height: 1.3em;
/* Put a nice border around it. */
padding: 1px;
width: 90%;
/* Don't wrap its contents, and show scrollbars. */
/* white-space: nowrap;*/
overflow: auto;
/* Stop after about 24 lines, and just show a scrollbar. */
/* max-height: 24em; */
margin: 5px;
padding-left: 20px;
border: 1px solid #FFE6BF;
border-left: 6px solid #FFE6BF;
}
div.code {
display: none;
color: #000000;
background-color: #FFF5E6;
font-family: "courier new", "times new roman", monospace;
line-height: 1.3em;
/* Put a nice border around it. */
padding: 1px;
width: 90%;
/* Don't wrap its contents, and show scrollbars. */
/* white-space: nowrap;*/
overflow: auto;
/* Stop after about 24 lines, and just show a scrollbar. */
/* max-height: 24em; */
margin: 5px;
padding-left: 20px;
border-left: 6px solid #FFE6BF;
}
table.summaryTable {
background: #E6ECFF;
border-collapse: collapse;
width: 100%;
}
table.summaryTable th, table.summaryTable td {
border: 1px #BFCFFF solid;
padding: 0.2em;
}
table.summaryTable th {
background: #CCD9FF;
text-align: left;
}
#nav {
padding: 3px;
margin: 0 0 10px 0;
border-top: 1px #BFCFFF solid;
}
#classDescription {
padding: 5px;
margin: 10px 0 20px 0;
border-bottom: 1px solid #BFCFFF;
}
.detailHeader {
font-weight: bold;
font-size: 12pt;
margin: 30px 0 5px 0;
border-bottom: 1px solid #BFCFFF;
}
.detailHeaderTag {
font-weight: normal;
font-size: 10pt;
}
.signature, .signature2 {
padding: 3px;
color: #000000;
font-family: "courier new", "times new roman", monospace;
line-height: 1.3em;
}
.signature {
margin: 10px 0 10px 0;
background: #E6ECFF;
border: 1px #BFCFFF solid;
}
.paramNameCol {
width: 12%;
font-weight: bold;
}
.paramTypeCol {
width: 12%;
}
.sourceCode {
margin: 5px 0;
padding:5px;
background:#FFF5E6;
}

View file

@ -0,0 +1,32 @@
body
{
}
body, div, span, p, input
{
font-family: Verdana, sans-serif, Arial;
font-size: 10pt;
color: #333333;
}
#apiPage {
}
#apiHeader {
padding: 3px;
color: white;
background: #6078BF;
margin-bottom: 5px;
font-weight: bold;
}
#apiHeader a {
color: white;
}
#apiFooter {
margin-top: 5px;
padding: 3px;
border-top: 1px solid #BFCFFF;
text-align: center;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,52 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="language" content="en" />
<link rel="stylesheet" type="text/css" href="css/style.css" />
<link rel="stylesheet" type="text/css" href="css/api.css" />
<script type="text/javascript" src="js/jquery.js"></script>
<title><?php echo $this->pageTitle; ?></title>
</head>
<body>
<div id="apiPage">
<div id="apiHeader">
<a href="http://www.yiiframework.com">Yii Framework</a> v<?php echo Yii::getVersion(); ?> Class Reference
</div><!-- end of header -->
<div id="content">
<?php echo $content; ?>
</div><!-- end of content -->
<div id="apiFooter">
&copy; 2008-2013 by <a href="http://www.yiisoft.com">Yii Software LLC</a><br/>
All Rights Reserved.<br/>
</div><!-- end of footer -->
<script type="text/javascript">
/*<![CDATA[*/
$("a.toggle").toggle(function(){
$(this).text($(this).text().replace(/Hide/,'Show'));
$(this).parents(".summary").find(".inherited").hide();
},function(){
$(this).text($(this).text().replace(/Show/,'Hide'));
$(this).parents(".summary").find(".inherited").show();
});
$(".sourceCode a.show").toggle(function(){
$(this).text($(this).text().replace(/show/,'hide'));
$(this).parents(".sourceCode").find("div.code").show();
},function(){
$(this).text($(this).text().replace(/hide/,'show'));
$(this).parents(".sourceCode").find("div.code").hide();
});
$("a.sourceLink").click(function(){
$(this).attr('target','_blank');
});
/*]]>*/
</script>
</div><!-- end of page -->
</body>
</html>

View file

@ -0,0 +1,35 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<meta name="GENERATOR" content="yiidoc http://www.yiiframework.com">
</head>
<body>
<object type="text/site properties">
<param name="Window Styles" value="0x800025">
<param name="FrameName" value="right">
<param name="ImageType" value="Folder">
<param name="comment" value="title:Online Help">
<param name="comment" value="base:index.html">
</object>
<ul>
<li><object type="text/sitemap">
<param name="Name" value="All Packages">
<param name="Local" value="index.html">
</object>
<?php foreach($this->packages as $package=>$classes): ?>
<li><object type="text/sitemap">
<param name="Name" value="<?php echo $package; ?>">
</object>
<ul>
<?php foreach($classes as $class): ?>
<li><object type="text/sitemap">
<param name="Name" value="<?php echo $class; ?>">
<param name="Local" value="<?php echo $class; ?>.html">
</object>
<?php endforeach; ?>
</ul>
<?php endforeach; ?>
</ul>
</body>
</html>

View file

@ -0,0 +1,42 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<meta name="GENERATOR" content="yiidoc http://www.yiiframework.com">
</head>
<body>
<ul>
<?php foreach($this->classes as $name=>$class): ?>
<li><object type="text/sitemap">
<param name="Name" value="<?php echo $class->name; ?>">
<param name="Local" value="<?php echo $class->name; ?>.html">
</object>
<ul>
<?php foreach($class->properties as $property): ?>
<?php if(!$property->isInherited): ?>
<li><object type="text/sitemap">
<param name="Name" value="<?php echo $property->name; ?>">
<param name="Local" value="<?php echo $class->name . '.html#' . $property->name; ?>">
</object>
<?php endif; ?>
<?php endforeach; ?>
<?php foreach($class->events as $event): ?>
<?php if(!$event->isInherited): ?>
<li><object type="text/sitemap">
<param name="Name" value="<?php echo $event->name; ?>">
<param name="Local" value="<?php echo $class->name . '.html#' . $event->name; ?>">
</object>
<?php endif; ?>
<?php endforeach; ?>
<?php foreach($class->methods as $method): ?>
<?php if(!$method->isInherited): ?>
<li><object type="text/sitemap">
<param name="Name" value="<?php echo $method->name; ?>()">
<param name="Local" value="<?php echo $class->name . '.html#' . $method->name; ?>">
</object>
<?php endif; ?>
<?php endforeach; ?>
</ul>
<?php endforeach; ?>
</ul>
</body>
</html>

View file

@ -0,0 +1,22 @@
[OPTIONS]
Binary TOC=Yes
Compatibility=1.1 or later
Compiled File=manual.chm
Contents File=manual.hhc
Default Window=main
Default Topic=index.html
Display compile progress=Yes
Error log file=_errorlog.txt
Full-text search=Yes
Language=0x409 English (United States)
Title=Yii Framework v<?php echo Yii::getVersion(); ?> Class Reference
Binary Index=Yes
Index file=manual.hhk
Default Font=
Auto Index=Yes
Create CHI file=No
Full text search stop list file=
Display compile notes=Yes
[WINDOWS]
main="Yii Framework v<?php echo Yii::getVersion(); ?> Class Reference","manual.hhc","manual.hhk","index.html","index.html",,,,,0x63520,250,0x104e,[10,10,900,700],0xb0000,,,,,,0

View file

@ -0,0 +1,29 @@
<h1><?php echo $class->name; ?></h1>
<div id="nav">
{{index|All Packages}}
<?php if(!empty($class->properties)): ?>
| <a href="#properties">Properties</a>
<?php endif; ?>
<?php if(!empty($class->methods)): ?>
| <a href="#methods">Methods</a>
<?php endif; ?>
<?php if(!empty($class->events)): ?>
| <a href="#events">Events</a>
<?php endif; ?>
</div>
<?php $this->renderPartial('classSummary',array('class'=>$class)); ?>
<a name="properties"></a>
<?php $this->renderPartial('propertySummary',array('class'=>$class,'protected'=>false)); ?>
<?php $this->renderPartial('propertySummary',array('class'=>$class,'protected'=>true)); ?>
<a name="methods"></a>
<?php $this->renderPartial('methodSummary',array('class'=>$class,'protected'=>false)); ?>
<?php $this->renderPartial('methodSummary',array('class'=>$class,'protected'=>true)); ?>
<a name="events"></a>
<?php $this->renderPartial('eventSummary',array('class'=>$class)); ?>
<?php $this->renderPartial('propertyDetails',array('class'=>$class)); ?>
<?php $this->renderPartial('methodDetails',array('class'=>$class)); ?>

View file

@ -0,0 +1,46 @@
<table class="summaryTable docClass">
<colgroup>
<col class="col-name" />
<col class="col-value" />
</colgroup>
<tr>
<th>Package</th>
<td><?php echo '{{index::'.$class->package.'|'.$class->package.'}}'; ?></td>
</tr>
<tr>
<th>Inheritance</th>
<td><?php echo $this->renderInheritance($class); ?></td>
</tr>
<?php if(!empty($class->interfaces)): ?>
<tr>
<th>Implements</th>
<td><?php echo $this->renderImplements($class); ?></td>
</tr>
<?php endif; ?>
<?php if(!empty($class->subclasses)): ?>
<tr>
<th>Subclasses</th>
<td><?php echo $this->renderSubclasses($class); ?></td>
</tr>
<?php endif; ?>
<?php if(!empty($class->since)): ?>
<tr>
<th>Since</th>
<td><?php echo $class->since; ?></td>
</tr>
<?php endif; ?>
<?php if(!empty($class->version)): ?>
<tr>
<th>Version</th>
<td><?php echo $class->version; ?></td>
</tr>
<?php endif; ?>
<tr>
<th>Source Code</th>
<td><?php echo $this->renderSourceLink($class->sourcePath); ?></td>
</tr>
</table>
<div id="classDescription">
<?php echo $class->description; ?>
</div>

View file

@ -0,0 +1,23 @@
<?php if(!$class->nativePropertyCount) return; ?>
<h2>Event Details</h2>
<?php foreach($class->events as $event): ?>
<?php if($event->isInherited) continue; ?>
<div class="detailHeader" id="<?php echo $event->name.'-detail'; ?>">
<?php echo $event->name; ?>
<span class="detailHeaderTag">
event
<?php if(!empty($event->since)): ?>
(available since v<?php echo $event->since; ?>)
<?php endif; ?>
</span>
</div>
<div class="signature">
<?php echo $event->trigger->signature; ?>
</div>
<p><?php echo $event->description; ?></p>
<?php $this->renderPartial('seeAlso',array('object'=>$event)); ?>
<?php endforeach; ?>

View file

@ -0,0 +1,25 @@
<?php if(empty($class->events)) return; ?>
<div class="summary docEvent">
<h2>Events</h2>
<p><a href="#" class="toggle">Hide inherited events</a></p>
<table class="summaryTable">
<colgroup>
<col class="col-event" />
<col class="col-description" />
<col class="col-defined" />
</colgroup>
<tr>
<th>Event</th><th>Description</th><th>Defined By</th>
</tr>
<?php foreach($class->events as $event): ?>
<tr<?php echo $event->isInherited?' class="inherited"':''; ?> id="<?php echo $event->name; ?>">
<td><?php echo $this->renderSubjectUrl($event->definedBy,$event->name); ?></td>
<td><?php echo $event->introduction; ?></td>
<td><?php echo $this->renderTypeUrl($event->definedBy); ?></td>
</tr>
<?php endforeach; ?>
</table>
</div>

View file

@ -0,0 +1,23 @@
<h1>Class Reference</h1>
<table class="summaryTable docIndex">
<colgroup>
<col class="col-package" />
<col class="col-class" />
<col class="col-description" />
</colgroup>
<tr>
<th>Package</th><th>Class</th><th>Description</th>
</tr>
<?php foreach($this->packages as $package=>$classes): ?>
<?php foreach($classes as $i=>$class): ?>
<tr>
<?php if(!$i): ?>
<td rowspan="<?php echo count($classes); ?>"><?php echo '<a name="'.$package.'"></a>' . $package; ?></td>
<?php endif; ?>
<td><?php echo '{{'.$class.'|'.$class.'}}'; ?></td>
<td><?php echo $this->classes[$class]->introduction; ?></td>
</tr>
<?php endforeach; ?>
<?php endforeach; ?>
</table>

View file

@ -0,0 +1,46 @@
<?php if(!$class->nativeMethodCount) return; ?>
<h2>Method Details</h2>
<?php foreach($class->methods as $method): ?>
<?php if($method->isInherited) continue; ?>
<div class="detailHeader" id="<?php echo $this->fixMethodAnchor($method->definedBy,$method->name).'-detail'; ?>">
<?php echo $method->name; ?>()
<span class="detailHeaderTag">
method
<?php if(!empty($method->since)): ?>
(available since v<?php echo $method->since; ?>)
<?php endif; ?>
</span>
</div>
<table class="summaryTable">
<tr><td colspan="3">
<div class="signature2">
<?php echo preg_replace('/\{\{([^\{\}]*?)\|([^\{\}]*?)\}\}\(/','$2(',$method->signature); ?>
</div>
</td></tr>
<?php if(!empty($method->input) || !empty($method->output)): ?>
<?php foreach($method->input as $param): ?>
<tr>
<td class="paramNameCol">$<?php echo $param->name; ?></td>
<td class="paramTypeCol"><?php echo $this->renderTypeUrl($param->type); ?></td>
<td class="paramDescCol"><?php echo $param->description; ?></td>
</tr>
<?php endforeach; ?>
<?php if(!empty($method->output)): ?>
<tr>
<td class="paramNameCol"><?php echo '{return}'; ?></td>
<td class="paramTypeCol"><?php echo $this->renderTypeUrl($method->output->type); ?></td>
<td class="paramDescCol"><?php echo $method->output->description; ?></td>
</tr>
<?php endif; ?>
<?php endif; ?>
</table>
<?php $this->renderPartial('sourceCode',array('object'=>$method)); ?>
<p><?php echo $method->description; ?></p>
<?php $this->renderPartial('seeAlso',array('object'=>$method)); ?>
<?php endforeach; ?>

View file

@ -0,0 +1,28 @@
<?php if($protected && !$class->protectedMethodCount || !$protected && !$class->publicMethodCount) return; ?>
<div class="summary docMethod">
<h2><?php echo $protected ? 'Protected Methods' : 'Public Methods'; ?></h2>
<p><a href="#" class="toggle">Hide inherited methods</a></p>
<table class="summaryTable">
<colgroup>
<col class="col-method" />
<col class="col-description" />
<col class="col-defined" />
</colgroup>
<tr>
<th>Method</th><th>Description</th><th>Defined By</th>
</tr>
<?php foreach($class->methods as $method): ?>
<?php if($protected && $method->isProtected || !$protected && !$method->isProtected): ?>
<?php $methodAnchor=$this->fixMethodAnchor($method->definedBy,$method->name); ?>
<tr<?php echo $method->isInherited?' class="inherited"':''; ?> id="<?php echo $methodAnchor; ?>">
<td><?php echo $this->renderSubjectUrl($method->definedBy,$methodAnchor,$method->name.'()'); ?></td>
<td><?php echo $method->introduction; ?></td>
<td><?php echo $this->renderTypeUrl($method->definedBy); ?></td>
</tr>
<?php endif; ?>
<?php endforeach; ?>
</table>
</div>

View file

@ -0,0 +1,24 @@
<?php if(!$class->nativePropertyCount) return; ?>
<h2>Property Details</h2>
<?php foreach($class->properties as $property): ?>
<?php if($property->isInherited) continue; ?>
<div class="detailHeader" id="<?php echo $property->name.'-detail'; ?>">
<?php echo $property->name; ?>
<span class="detailHeaderTag">
property
<?php if($property->readOnly) echo ' <em>read-only</em> '; ?>
<?php if(!empty($property->since)): ?>
(available since v<?php echo $property->since; ?>)
<?php endif; ?>
</span>
</div>
<div class="signature">
<?php echo $this->renderPropertySignature($property); ?>
</div>
<p><?php echo $property->description; ?></p>
<?php $this->renderPartial('seeAlso',array('object'=>$property)); ?>
<?php endforeach; ?>

View file

@ -0,0 +1,29 @@
<?php if($protected && !$class->protectedPropertyCount || !$protected && !$class->publicPropertyCount) return; ?>
<div class="summary docProperty">
<h2><?php echo $protected ? 'Protected Properties' : 'Public Properties'; ?></h2>
<p><a href="#" class="toggle">Hide inherited properties</a></p>
<table class="summaryTable">
<colgroup>
<col class="col-property" />
<col class="col-type" />
<col class="col-description" />
<col class="col-defined" />
</colgroup>
<tr>
<th>Property</th><th>Type</th><th>Description</th><th>Defined By</th>
</tr>
<?php foreach($class->properties as $property): ?>
<?php if($protected && $property->isProtected || !$protected && !$property->isProtected): ?>
<tr<?php echo $property->isInherited?' class="inherited"':''; ?> id="<?php echo $property->name; ?>">
<td><?php echo $this->renderSubjectUrl($property->definedBy,$property->name); ?></td>
<td><?php echo $this->renderTypeUrl($property->type); ?></td>
<td><?php echo $property->introduction; ?></td>
<td><?php echo $this->renderTypeUrl($property->definedBy); ?></td>
</tr>
<?php endif; ?>
<?php endforeach; ?>
</table>
</div>

View file

@ -0,0 +1,9 @@
<?php if(empty($object->see)) return; ?>
<div class="SeeAlso">
<h4>See Also</h4>
<ul>
<?php foreach($object->see as $url): ?>
<li><?php echo $url; ?></li>
<?php endforeach; ?>
</ul>
</div>

View file

@ -0,0 +1,4 @@
<div class="sourceCode">
<b>Source Code:</b> <?php echo $this->renderSourceLink($object->sourcePath,$object->startLine); ?> (<b><a href="#" class="show">show</a></b>)
<div class="code"><?php echo $this->highlight($object->getSourceCode()); ?></div>
</div>

View file

@ -0,0 +1,30 @@
\documentclass[a4paper,11pt,twoside]{book}
\input{preamble} % configurations
\begin{document}
\frontmatter
\include{title} % include title page
\addcontentsline{toc}{chapter}{Contents}
\pagenumbering{roman}
\tableofcontents
\include{preface} % include preface
\include{license} % include other frontmatter
\mainmatter
\input{main} % include chapter list
%\appendix
%\include{history}
%\backmatter
%\include{bibliography} % include bibliography
%\include{index} % include index
\end{document}

View file

@ -0,0 +1,37 @@
\chapter*{License of Yii}
\addcontentsline{toc}{chapter}{License}
The Yii framework is free software.
It is released under the terms of the following BSD License.
Copyright \copyright 2008-2010 by Yii Software LLC.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
\begin{enumerate}
\item Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
\item Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
\item Neither the name of Yii Software LLC nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
\end{enumerate}
{\footnotesize
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
}

View file

@ -0,0 +1,144 @@
\usepackage{xspace, calc, enumerate, fancyhdr, alltt, color, ifthen, hyphenat}
\usepackage[pdftex]{graphicx}
\usepackage[pdftex]{hyperref}
%----- remove hyphen character for texttt ----
\renewcommand{\BreakableUnderscore}{\nobreak\textunderscore\discretionary{}{}{}\nobreak}
\renewcommand{\BreakableBackslash}{\nobreak\textbackslash\discretionary{}{}{}\nobreak}
\renewcommand{\BreakableSlash}{\nobreak/\discretionary{}{}{}\nobreak}
\renewcommand{\BreakablePeriod}{\nobreak.\discretionary{}{}{}\nobreak}
\renewcommand{\BreakableColon}{\nobreak:\discretionary{}{}{}\nobreak}
\definecolor{lightp}{rgb}{0.4,0.2,0.8}
%------ syntax highlighting colors --------
\definecolor{string}{rgb}{1,0.0,0.53}
\definecolor{comment}{rgb}{0.2,0.6,0.0}
\definecolor{keyword}{rgb}{0.0,0.3,1.0}
\definecolor{reserved}{rgb}{0.0,0.3,1.0}
\definecolor{identifier}{rgb}{0.0,0.0,0.0}
\definecolor{brackets}{rgb}{0.60,0.80,0.0}
\definecolor{code}{rgb}{0.0,0.0,0.0}
\definecolor{number}{rgb}{0.93,0.0,0.0}
\definecolor{inlinetags}{rgb}{0.0,0.0,1.0}
\definecolor{quotes}{rgb}{1,0.0,0.53}
\definecolor{var}{rgb}{0.0,0.66,0.66}
\definecolor{inlinedoc}{rgb}{0.0,0.66,0.66}
\definecolor{default}{rgb}{0.0,0.0,0.0}
%---- change link style ---- See http://andy-roberts.net/misc/latex/pdftutorial.html
\hypersetup{colorlinks, urlcolor=lightp, linkcolor=blue, bookmarksopen=true, pdfstartview={FitH}}
%------------------------Page set-up-----------------------------------------
\renewcommand{\baselinestretch}{1.15} % line spacing 115%
\setlength{\hoffset}{-1in}
\setlength{\oddsidemargin}{4cm}
\setlength{\evensidemargin}{2cm}
\setlength{\voffset}{3cm - 1in}
\setlength{\topmargin}{0cm}
\setlength{\headheight}{14.5pt}
%\setlength{\headsep}{0cm}
\setlength{\marginparwidth}{0cm}
\setlength{\marginparsep}{0cm}
\setlength{\marginparpush}{0cm}
%\setlength{\footskip}{0cm}
\setlength{\textheight}{242mm - \headheight - \headsep - \footskip}
\setlength{\textwidth}{15cm}
\setlength{\parindent}{0cm}
\setlength{\parskip}{0.75\baselineskip}
%------------------------------------------------------------------------------
%------------------------Setup headings and spacing---------------------
\makeatletter
\renewcommand{\section}{\@startsection%
{section}% name
{1}% level
{0mm}% indent
{0.5\baselineskip}% beforeskip
{0.1mm}% afterskip
{\normalfont\Large\bfseries}% style
}
\renewcommand{\subsection}{\@startsection%
{subsection}% name
{2}% level
{0mm}% indent
{0.5\baselineskip}% beforeskip
{0.1mm}% afterskip
{\normalfont\large\bfseries}% style
}
\makeatother
%------------------------------------------------------------------------------
% Modify the first page of the chapters: no chapter word, big chapter
% number, title adjusted to right, and a line below.
%-----------------------------------------------------------------------
\makeatletter
\def\@makechapterhead#1{%
% {\parindent \z@\raggedleft
{\parindent \z@\raggedright
\ifnum \c@secnumdepth >\m@ne
{\fontsize{20pt}{30pt}\selectfont\Huge\textsc{{Chapter \thechapter}}}
\fi
\rule{\columnwidth}{0.25pt} \par
{\Huge\textsc{\textbf{#1}}\par}
\nobreak
\vskip 70\p@
}}
\def\@makeschapterhead#1{%
% {\parindent\z@\raggedleft
{\parindent\z@\raggedright
{\Huge\textsc{#1}\par}
\nobreak
\vskip 70\p@
}}
\makeatother
%-----------------------------------------------------------------------
% Modify the caption definition to make text italic and smaller than normal size text
%-----------------------------------------------------------------------
\makeatletter
\newsavebox{\capbox}
\renewcommand{\@makecaption}[2]{%
\vspace{0pt}\sbox{\capbox}{\textbf{#1}: \small{#2}}%
\ifthenelse{\lengthtest{\wd\capbox > 0.85\linewidth}}%
{\center{\parbox[t]{0.8\linewidth}{\textbf{#1}: \small{#2}}}}%
{\begin{center}\textbf{#1}: \small{#2}\end{center}}%
} \makeatother
%-----------------------------------------------------------------------
% Pages and Fancyheadings stuff
%-----------------------------------------------------------------------
\pagestyle{fancy}
% \pagestyle{fancyplain}
%\setlength{\headrulewidth}{0.1pt} \setlength{\footrulewidth}{0pt}
\newcommand{\clearemptydoublepage}{\newpage\thispagestyle{empty}\cleardoublepage}
\cfoot{}
% Chapter
\renewcommand{\chaptermark}[1]{\markboth{\thechapter.\ #1}{}}
% % Section
\renewcommand{\sectionmark}[1]{\markright{\thesection\ #1}}
\fancyhf{}
\fancyhead[LE,RO]{\bfseries\thepage}
\fancyhead[LO]{\nouppercase{\bfseries\rightmark}}
\fancyhead[RE]{\nouppercase{\scshape\leftmark}}
% \lhead[\fancyplain{}{\bf\thepage}]{\fancyplain{}{\bf\rightmark}}
% \rhead[\fancyplain{}{\bf\leftmark}]{\fancyplain{}{\bf\thepage}}
\fancypagestyle{plain}{%
\fancyhf{} % clear all header and footer fields
\renewcommand{\headrulewidth}{0pt}
\renewcommand{\footrulewidth}{0pt}}
%-----------------------------------------------------------------------
% boxes
\newsavebox{\fmboxb}
\newenvironment{tipbox}
{\vspace{-2mm}\begin{center}\begin{lrbox}{\fmboxb}\hspace{2mm}
\begin{minipage}{0.85\textwidth} \vspace{1mm}\small\setlength{\parskip}{0.75\baselineskip}}
{ \vspace{2mm} \end{minipage}
\hspace{2mm}\end{lrbox}\fbox{\usebox{\fmboxb}}\end{center}}

View file

@ -0,0 +1,25 @@
%Title Page:
%\renewcommand{\baselinestretch}{1}
\thispagestyle{empty}
\begin{center}
\bfseries \rule{0cm}{1.5cm} \Huge
Building a Blog System using Yii
\vspace{1.5cm}
\end{center}
\begin{center}
\bfseries \Large Qiang Xue
\end{center}
%\begin{center} \large \today \end{center}
\begin{center}
Copyright 2008-2013. All Rights Reserved.
\end{center}
\vfill
%Take a blank Page
\pagebreak \thispagestyle{empty} \cleardoublepage
%\renewcommand{\baselinestretch}{1.1}

View file

@ -0,0 +1,30 @@
\documentclass[a4paper,11pt,twoside]{book}
\input{preamble} % configurations
\begin{document}
\frontmatter
\include{title} % include title page
\addcontentsline{toc}{chapter}{Contents}
\pagenumbering{roman}
\tableofcontents
\include{preface} % include preface
\include{license} % include other frontmatter
\mainmatter
\input{main} % include chapter list
%\appendix
%\include{history}
%\backmatter
%\include{bibliography} % include bibliography
%\include{index} % include index
\end{document}

View file

@ -0,0 +1,37 @@
\chapter*{License of Yii}
\addcontentsline{toc}{chapter}{License}
The Yii framework is free software.
It is released under the terms of the following BSD License.
Copyright \copyright 2008-2010 by Yii Software LLC.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
\begin{enumerate}
\item Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
\item Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided
with the distribution.
\item Neither the name of Yii Software LLC nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
\end{enumerate}
{\footnotesize
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
}

Some files were not shown because too many files have changed in this diff Show more