init
This commit is contained in:
commit
da1024a5b3
0
.gitignore
vendored
Normal file
0
.gitignore
vendored
Normal file
14
.htaccess
Normal file
14
.htaccess
Normal file
|
@ -0,0 +1,14 @@
|
|||
<IfModule mod_rewrite.c>
|
||||
Options +FollowSymlinks
|
||||
RewriteEngine On
|
||||
</IfModule>
|
||||
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteCond %{REQUEST_URI} ^/.*
|
||||
RewriteRule ^(.*)$ web/$1 [L]
|
||||
|
||||
RewriteCond %{REQUEST_URI} !^/web/
|
||||
RewriteCond %{REQUEST_FILENAME} !-f [OR]
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^.*$ web/index.php
|
||||
</IfModule>
|
32
LICENSE.md
Normal file
32
LICENSE.md
Normal file
|
@ -0,0 +1,32 @@
|
|||
The Yii framework is free software. It is released under the terms of
|
||||
the following BSD License.
|
||||
|
||||
Copyright © 2008 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.
|
233
README.md
Normal file
233
README.md
Normal file
|
@ -0,0 +1,233 @@
|
|||
<p align="center">
|
||||
<a href="https://github.com/yiisoft" target="_blank">
|
||||
<img src="https://avatars0.githubusercontent.com/u/993323" height="100px">
|
||||
</a>
|
||||
<h1 align="center">Yii 2 Basic Project Template</h1>
|
||||
<br>
|
||||
</p>
|
||||
|
||||
Yii 2 Basic Project Template is a skeleton [Yii 2](http://www.yiiframework.com/) application best for
|
||||
rapidly creating small projects.
|
||||
|
||||
The template contains the basic features including user login/logout and a contact page.
|
||||
It includes all commonly used configurations that would allow you to focus on adding new
|
||||
features to your application.
|
||||
|
||||
[](https://packagist.org/packages/yiisoft/yii2-app-basic)
|
||||
[](https://packagist.org/packages/yiisoft/yii2-app-basic)
|
||||
[](https://travis-ci.org/yiisoft/yii2-app-basic)
|
||||
|
||||
DIRECTORY STRUCTURE
|
||||
-------------------
|
||||
|
||||
assets/ contains assets definition
|
||||
commands/ contains console commands (controllers)
|
||||
config/ contains application configurations
|
||||
controllers/ contains Web controller classes
|
||||
mail/ contains view files for e-mails
|
||||
models/ contains model classes
|
||||
runtime/ contains files generated during runtime
|
||||
tests/ contains various tests for the basic application
|
||||
vendor/ contains dependent 3rd-party packages
|
||||
views/ contains view files for the Web application
|
||||
web/ contains the entry script and Web resources
|
||||
|
||||
|
||||
|
||||
REQUIREMENTS
|
||||
------------
|
||||
|
||||
The minimum requirement by this project template that your Web server supports PHP 5.4.0.
|
||||
|
||||
|
||||
INSTALLATION
|
||||
------------
|
||||
|
||||
### Install via Composer
|
||||
|
||||
If you do not have [Composer](http://getcomposer.org/), you may install it by following the instructions
|
||||
at [getcomposer.org](http://getcomposer.org/doc/00-intro.md#installation-nix).
|
||||
|
||||
You can then install this project template using the following command:
|
||||
|
||||
~~~
|
||||
php composer.phar create-project --prefer-dist --stability=dev yiisoft/yii2-app-basic basic
|
||||
~~~
|
||||
|
||||
Now you should be able to access the application through the following URL, assuming `basic` is the directory
|
||||
directly under the Web root.
|
||||
|
||||
~~~
|
||||
http://localhost/basic/web/
|
||||
~~~
|
||||
|
||||
### Install from an Archive File
|
||||
|
||||
Extract the archive file downloaded from [yiiframework.com](http://www.yiiframework.com/download/) to
|
||||
a directory named `basic` that is directly under the Web root.
|
||||
|
||||
Set cookie validation key in `config/web.php` file to some random secret string:
|
||||
|
||||
```php
|
||||
'request' => [
|
||||
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
|
||||
'cookieValidationKey' => '<secret random string goes here>',
|
||||
],
|
||||
```
|
||||
|
||||
You can then access the application through the following URL:
|
||||
|
||||
~~~
|
||||
http://localhost/basic/web/
|
||||
~~~
|
||||
|
||||
|
||||
### Install with Docker
|
||||
|
||||
Update your vendor packages
|
||||
|
||||
docker-compose run --rm php composer update --prefer-dist
|
||||
|
||||
Run the installation triggers (creating cookie validation code)
|
||||
|
||||
docker-compose run --rm php composer install
|
||||
|
||||
Start the container
|
||||
|
||||
docker-compose up -d
|
||||
|
||||
You can then access the application through the following URL:
|
||||
|
||||
http://127.0.0.1:8000
|
||||
|
||||
**NOTES:**
|
||||
- Minimum required Docker engine version `17.04` for development (see [Performance tuning for volume mounts](https://docs.docker.com/docker-for-mac/osxfs-caching/))
|
||||
- The default configuration uses a host-volume in your home directory `.docker-composer` for composer caches
|
||||
|
||||
|
||||
CONFIGURATION
|
||||
-------------
|
||||
|
||||
### Database
|
||||
|
||||
Edit the file `config/db.php` with real data, for example:
|
||||
|
||||
```php
|
||||
return [
|
||||
'class' => 'yii\db\Connection',
|
||||
'dsn' => 'mysql:host=localhost;dbname=yii2basic',
|
||||
'username' => 'root',
|
||||
'password' => '1234',
|
||||
'charset' => 'utf8',
|
||||
];
|
||||
```
|
||||
|
||||
**NOTES:**
|
||||
- Yii won't create the database for you, this has to be done manually before you can access it.
|
||||
- Check and edit the other files in the `config/` directory to customize your application as required.
|
||||
- Refer to the README in the `tests` directory for information specific to basic application tests.
|
||||
|
||||
|
||||
TESTING
|
||||
-------
|
||||
|
||||
Tests are located in `tests` directory. They are developed with [Codeception PHP Testing Framework](http://codeception.com/).
|
||||
By default there are 3 test suites:
|
||||
|
||||
- `unit`
|
||||
- `functional`
|
||||
- `acceptance`
|
||||
|
||||
Tests can be executed by running
|
||||
|
||||
```
|
||||
vendor/bin/codecept run
|
||||
```
|
||||
|
||||
The command above will execute unit and functional tests. Unit tests are testing the system components, while functional
|
||||
tests are for testing user interaction. Acceptance tests are disabled by default as they require additional setup since
|
||||
they perform testing in real browser.
|
||||
|
||||
|
||||
### Running acceptance tests
|
||||
|
||||
To execute acceptance tests do the following:
|
||||
|
||||
1. Rename `tests/acceptance.suite.yml.example` to `tests/acceptance.suite.yml` to enable suite configuration
|
||||
|
||||
2. Replace `codeception/base` package in `composer.json` with `codeception/codeception` to install full featured
|
||||
version of Codeception
|
||||
|
||||
3. Update dependencies with Composer
|
||||
|
||||
```
|
||||
composer update
|
||||
```
|
||||
|
||||
4. Download [Selenium Server](http://www.seleniumhq.org/download/) and launch it:
|
||||
|
||||
```
|
||||
java -jar ~/selenium-server-standalone-x.xx.x.jar
|
||||
```
|
||||
|
||||
In case of using Selenium Server 3.0 with Firefox browser since v48 or Google Chrome since v53 you must download [GeckoDriver](https://github.com/mozilla/geckodriver/releases) or [ChromeDriver](https://sites.google.com/a/chromium.org/chromedriver/downloads) and launch Selenium with it:
|
||||
|
||||
```
|
||||
# for Firefox
|
||||
java -jar -Dwebdriver.gecko.driver=~/geckodriver ~/selenium-server-standalone-3.xx.x.jar
|
||||
|
||||
# for Google Chrome
|
||||
java -jar -Dwebdriver.chrome.driver=~/chromedriver ~/selenium-server-standalone-3.xx.x.jar
|
||||
```
|
||||
|
||||
As an alternative way you can use already configured Docker container with older versions of Selenium and Firefox:
|
||||
|
||||
```
|
||||
docker run --net=host selenium/standalone-firefox:2.53.0
|
||||
```
|
||||
|
||||
5. (Optional) Create `yii2_basic_tests` database and update it by applying migrations if you have them.
|
||||
|
||||
```
|
||||
tests/bin/yii migrate
|
||||
```
|
||||
|
||||
The database configuration can be found at `config/test_db.php`.
|
||||
|
||||
|
||||
6. Start web server:
|
||||
|
||||
```
|
||||
tests/bin/yii serve
|
||||
```
|
||||
|
||||
7. Now you can run all available tests
|
||||
|
||||
```
|
||||
# run all available tests
|
||||
vendor/bin/codecept run
|
||||
|
||||
# run acceptance tests
|
||||
vendor/bin/codecept run acceptance
|
||||
|
||||
# run only unit and functional tests
|
||||
vendor/bin/codecept run unit,functional
|
||||
```
|
||||
|
||||
### Code coverage support
|
||||
|
||||
By default, code coverage is disabled in `codeception.yml` configuration file, you should uncomment needed rows to be able
|
||||
to collect code coverage. You can run your tests and collect coverage with the following command:
|
||||
|
||||
```
|
||||
#collect coverage for all tests
|
||||
vendor/bin/codecept run -- --coverage-html --coverage-xml
|
||||
|
||||
#collect coverage only for unit tests
|
||||
vendor/bin/codecept run unit -- --coverage-html --coverage-xml
|
||||
|
||||
#collect coverage for unit and functional tests
|
||||
vendor/bin/codecept run functional,unit -- --coverage-html --coverage-xml
|
||||
```
|
||||
|
||||
You can see code coverage output under the `tests/_output` directory.
|
81
Vagrantfile
vendored
Normal file
81
Vagrantfile
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
require 'yaml'
|
||||
require 'fileutils'
|
||||
|
||||
required_plugins = %w( vagrant-hostmanager vagrant-vbguest )
|
||||
required_plugins.each do |plugin|
|
||||
exec "vagrant plugin install #{plugin}" unless Vagrant.has_plugin? plugin
|
||||
end
|
||||
|
||||
domains = {
|
||||
app: 'yii2basic.dev'
|
||||
}
|
||||
|
||||
vagrantfile_dir_path = File.dirname(__FILE__)
|
||||
|
||||
config = {
|
||||
local: vagrantfile_dir_path + '/vagrant/config/vagrant-local.yml',
|
||||
example: vagrantfile_dir_path + '/vagrant/config/vagrant-local.example.yml'
|
||||
}
|
||||
|
||||
# copy config from example if local config not exists
|
||||
FileUtils.cp config[:example], config[:local] unless File.exist?(config[:local])
|
||||
# read config
|
||||
options = YAML.load_file config[:local]
|
||||
|
||||
# check github token
|
||||
if options['github_token'].nil? || options['github_token'].to_s.length != 40
|
||||
puts "You must place REAL GitHub token into configuration:\n/yii2-app-basic/vagrant/config/vagrant-local.yml"
|
||||
exit
|
||||
end
|
||||
|
||||
# vagrant configurate
|
||||
Vagrant.configure(2) do |config|
|
||||
# select the box
|
||||
config.vm.box = 'bento/ubuntu-16.04'
|
||||
|
||||
# should we ask about box updates?
|
||||
config.vm.box_check_update = options['box_check_update']
|
||||
|
||||
config.vm.provider 'virtualbox' do |vb|
|
||||
# machine cpus count
|
||||
vb.cpus = options['cpus']
|
||||
# machine memory size
|
||||
vb.memory = options['memory']
|
||||
# machine name (for VirtualBox UI)
|
||||
vb.name = options['machine_name']
|
||||
end
|
||||
|
||||
# machine name (for vagrant console)
|
||||
config.vm.define options['machine_name']
|
||||
|
||||
# machine name (for guest machine console)
|
||||
config.vm.hostname = options['machine_name']
|
||||
|
||||
# network settings
|
||||
config.vm.network 'private_network', ip: options['ip']
|
||||
|
||||
# sync: folder 'yii2-app-advanced' (host machine) -> folder '/app' (guest machine)
|
||||
config.vm.synced_folder './', '/app', owner: 'vagrant', group: 'vagrant'
|
||||
|
||||
# disable folder '/vagrant' (guest machine)
|
||||
config.vm.synced_folder '.', '/vagrant', disabled: true
|
||||
|
||||
# hosts settings (host machine)
|
||||
config.vm.provision :hostmanager
|
||||
config.hostmanager.enabled = true
|
||||
config.hostmanager.manage_host = true
|
||||
config.hostmanager.ignore_private_ip = false
|
||||
config.hostmanager.include_offline = true
|
||||
config.hostmanager.aliases = domains.values
|
||||
|
||||
# quick fix for failed guest additions installations
|
||||
# config.vbguest.auto_update = false
|
||||
|
||||
# provisioners
|
||||
config.vm.provision 'shell', path: './vagrant/provision/once-as-root.sh', args: [options['timezone']]
|
||||
config.vm.provision 'shell', path: './vagrant/provision/once-as-vagrant.sh', args: [options['github_token']], privileged: false
|
||||
config.vm.provision 'shell', path: './vagrant/provision/always-as-root.sh', run: 'always'
|
||||
|
||||
# post-install message (vagrant console)
|
||||
config.vm.post_up_message = "App URL: http://#{domains[:app]}"
|
||||
end
|
47
assets/AppAsset.php
Normal file
47
assets/AppAsset.php
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace app\assets;
|
||||
|
||||
use yii\web\AssetBundle;
|
||||
|
||||
/**
|
||||
* Main application asset bundle.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class AppAsset extends AssetBundle {
|
||||
|
||||
public $basePath = '@webroot';
|
||||
public $baseUrl = '@web';
|
||||
public $css = [
|
||||
'css/site.css',
|
||||
'ajaxFileUpload/ajaxFilesUpload.css',
|
||||
'datetimepicker/bootstrap-datetimepicker.css',
|
||||
'icheck/skins/all.css',
|
||||
'select2/css/select2.min.css'
|
||||
];
|
||||
public $js = [
|
||||
'js/md5.min.js',
|
||||
'icheck/icheck.min.js',
|
||||
'ajaxFileUpload/ajaxFilesUpload.js',
|
||||
'datetimepicker/moment-with-locales.js',
|
||||
'datetimepicker/bootstrap-datetimepicker.js',
|
||||
'js/boostrap-notify.min.js',
|
||||
'js/socket.io.min.js',
|
||||
'select2/js/select2.min.js',
|
||||
'js/editor.js',
|
||||
'js/common.js'
|
||||
];
|
||||
public $depends = [
|
||||
'yii\web\YiiAsset',
|
||||
'yii\bootstrap\BootstrapAsset',
|
||||
];
|
||||
|
||||
}
|
23
assets/DashboardAsset.php
Normal file
23
assets/DashboardAsset.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
namespace app\assets;
|
||||
|
||||
use yii\web\AssetBundle;
|
||||
|
||||
class DashboardAsset extends AssetBundle {
|
||||
|
||||
public $basePath = '@webroot';
|
||||
public $baseUrl = '@web';
|
||||
public $css = [
|
||||
];
|
||||
public $js = [
|
||||
'js/user.js'
|
||||
];
|
||||
public $depends = [
|
||||
'yii\web\YiiAsset',
|
||||
'app\assets\AppAsset',
|
||||
'yii\jui\JuiAsset',
|
||||
'yii\bootstrap\BootstrapAsset',
|
||||
];
|
||||
|
||||
}
|
28
assets/UserAsset.php
Normal file
28
assets/UserAsset.php
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
|
||||
namespace app\assets;
|
||||
|
||||
use yii\web\AssetBundle;
|
||||
|
||||
class UserAsset extends AssetBundle {
|
||||
|
||||
public $basePath = '@webroot';
|
||||
public $baseUrl = '@web';
|
||||
public $css = [
|
||||
'select2/css/select2.min.css',
|
||||
'ajaxFileUpload/ajaxFilesUpload.css'
|
||||
];
|
||||
public $js = [
|
||||
'js/md5.min.js',
|
||||
'select2/js/select2.min.js',
|
||||
'ajaxFileUpload/ajaxFilesUpload.js',
|
||||
'js/user.js'
|
||||
];
|
||||
public $depends = [
|
||||
'yii\web\YiiAsset',
|
||||
'app\assets\AppAsset',
|
||||
// 'yii\jui\JuiAsset',
|
||||
'yii\bootstrap\BootstrapAsset',
|
||||
];
|
||||
|
||||
}
|
37
codeception.yml
Normal file
37
codeception.yml
Normal file
|
@ -0,0 +1,37 @@
|
|||
actor: Tester
|
||||
paths:
|
||||
tests: tests
|
||||
log: tests/_output
|
||||
data: tests/_data
|
||||
helpers: tests/_support
|
||||
settings:
|
||||
bootstrap: _bootstrap.php
|
||||
memory_limit: 1024M
|
||||
colors: true
|
||||
modules:
|
||||
config:
|
||||
Yii2:
|
||||
configFile: 'config/test.php'
|
||||
cleanup: false
|
||||
|
||||
# To enable code coverage:
|
||||
#coverage:
|
||||
# #c3_url: http://localhost:8080/index-test.php/
|
||||
# enabled: true
|
||||
# #remote: true
|
||||
# #remote_config: '../codeception.yml'
|
||||
# whitelist:
|
||||
# include:
|
||||
# - models/*
|
||||
# - controllers/*
|
||||
# - commands/*
|
||||
# - mail/*
|
||||
# blacklist:
|
||||
# include:
|
||||
# - assets/*
|
||||
# - config/*
|
||||
# - runtime/*
|
||||
# - vendor/*
|
||||
# - views/*
|
||||
# - web/*
|
||||
# - tests/*
|
34
commands/HelloController.php
Normal file
34
commands/HelloController.php
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
/**
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
namespace app\commands;
|
||||
|
||||
use yii\console\Controller;
|
||||
use yii\console\ExitCode;
|
||||
|
||||
/**
|
||||
* This command echoes the first argument that you have entered.
|
||||
*
|
||||
* This command is provided as an example for you to learn how to create console commands.
|
||||
*
|
||||
* @author Qiang Xue <qiang.xue@gmail.com>
|
||||
* @since 2.0
|
||||
*/
|
||||
class HelloController extends Controller
|
||||
{
|
||||
/**
|
||||
* This command echoes what you have entered as the message.
|
||||
* @param string $message the message to be echoed.
|
||||
* @return int Exit code
|
||||
*/
|
||||
public function actionIndex($message = 'hello world')
|
||||
{
|
||||
echo $message . "\n";
|
||||
|
||||
return ExitCode::OK;
|
||||
}
|
||||
}
|
147
components/CacheRbacDbManager.php
Normal file
147
components/CacheRbacDbManager.php
Normal file
|
@ -0,0 +1,147 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
namespace app\components;
|
||||
|
||||
use yii\helpers\ArrayHelper;
|
||||
|
||||
/**
|
||||
* Description of CacheRbacManager
|
||||
*
|
||||
* @author Kdg
|
||||
*/
|
||||
class CacheRbacDbManager extends \yii\rbac\DbManager {
|
||||
|
||||
/**
|
||||
* @var string the ID of the cache application component that is used to cache rbac.
|
||||
* Defaults to 'cache' which refers to the primary cache application component.
|
||||
*/
|
||||
public $cache = 'cache';
|
||||
|
||||
/**
|
||||
* @var integer Lifetime of cached data in seconds
|
||||
*/
|
||||
public $cacheDuration = 3600;
|
||||
|
||||
/**
|
||||
* @var string cache key name
|
||||
*/
|
||||
public $cacheKeyName = 'RbacCached';
|
||||
|
||||
/**
|
||||
* @var array php cache
|
||||
*/
|
||||
protected $cachedData = [];
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function checkAccess($userId, $permissionName, $params = []) {
|
||||
if (!empty($params))
|
||||
return parent::checkAccess($userId, $permissionName, $params);
|
||||
$cacheKey = 'checkAccess:' . $userId . ':' . $permissionName;
|
||||
$cached = $this->getValue($cacheKey);
|
||||
if (empty($cached)) {
|
||||
$cached = parent::checkAccess($userId, $permissionName);
|
||||
$this->setValue($cacheKey, $cached);
|
||||
}
|
||||
return $cached;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function checkAccessRecursive($user, $itemName, $params, $assignments) {
|
||||
$cacheKey = 'checkAccessRecursive:' . $user . ':' . $itemName;
|
||||
if (!empty($params))
|
||||
$cacheKey .= ':' . current($params)->primaryKey;
|
||||
$cached = $this->getValue($cacheKey);
|
||||
if (empty($cached)) {
|
||||
$cached = parent::checkAccessRecursive($user, $itemName, $params, $assignments);
|
||||
$this->setValue($cacheKey, $cached);
|
||||
}
|
||||
return $cached;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function getItem($name) {
|
||||
$cacheKey = 'Item:' . $name;
|
||||
$cached = $this->getValue($cacheKey);
|
||||
if (empty($cached)) {
|
||||
$cached = parent::getItem($name);
|
||||
$this->setValue($cacheKey, $cached);
|
||||
}
|
||||
return $cached;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getAssignments($userId) {
|
||||
if (empty($userId))
|
||||
return parent::getAssignments($userId);
|
||||
$cacheKey = 'Assignments:' . $userId;
|
||||
$cached = $this->getValue($cacheKey);
|
||||
if (empty($cached)) {
|
||||
$cached = parent::getAssignments($userId);
|
||||
$this->setValue($cacheKey, $cached);
|
||||
}
|
||||
return $cached;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a value in cache
|
||||
* @param $key
|
||||
* @param $value
|
||||
* @return mixed
|
||||
*/
|
||||
protected function setValue($key, $value) {
|
||||
$this->cachedData = $this->getCache()->get($this->cacheKeyName);
|
||||
if (empty($this->cachedData))
|
||||
$this->cachedData = [];
|
||||
$this->cachedData[$key] = $value;
|
||||
return $this->getCache()->set($this->cacheKeyName, $this->cachedData, $this->cacheDuration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached value
|
||||
* @param $key
|
||||
* @return mixed
|
||||
*/
|
||||
protected function getValue($key) {
|
||||
$cached = ArrayHelper::getValue($this->cachedData, $key);
|
||||
if (!isset($cached)) {
|
||||
$cacheData = $this->getCache()->get($this->cacheKeyName);
|
||||
$cached = $this->cachedData[$key] = ArrayHelper::getValue($cacheData, $key);
|
||||
}
|
||||
return $cached;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cached value
|
||||
* @param $key
|
||||
* @return mixed
|
||||
*/
|
||||
public function deleteAllCache() {
|
||||
return $this->getCache()->delete($this->cacheKeyName);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return \yii\caching\Cache
|
||||
*/
|
||||
private function getCache() {
|
||||
if (is_string($this->cache)) {
|
||||
$this->cache = \Yii::$app->get($this->cache);
|
||||
}
|
||||
return $this->cache;
|
||||
}
|
||||
|
||||
}
|
73
composer.json
Normal file
73
composer.json
Normal file
|
@ -0,0 +1,73 @@
|
|||
{
|
||||
"name": "yiisoft/yii2-app-basic",
|
||||
"description": "Yii 2 Basic Project Template",
|
||||
"keywords": ["yii2", "framework", "basic", "project template"],
|
||||
"homepage": "http://www.yiiframework.com/",
|
||||
"type": "project",
|
||||
"license": "BSD-3-Clause",
|
||||
"support": {
|
||||
"issues": "https://github.com/yiisoft/yii2/issues?state=open",
|
||||
"forum": "http://www.yiiframework.com/forum/",
|
||||
"wiki": "http://www.yiiframework.com/wiki/",
|
||||
"irc": "irc://irc.freenode.net/yii",
|
||||
"source": "https://github.com/yiisoft/yii2"
|
||||
},
|
||||
"minimum-stability": "stable",
|
||||
"require": {
|
||||
"php": ">=5.4.0",
|
||||
"yiisoft/yii2": "~2.0.14",
|
||||
"yiisoft/yii2-bootstrap": "~2.0.0",
|
||||
"yiisoft/yii2-swiftmailer": "~2.0.0",
|
||||
"dmstr/yii2-adminlte-asset": "^2.1",
|
||||
"yiisoft/yii2-smarty": "^2.0",
|
||||
"yii2mod/yii2-rbac": "*",
|
||||
"linslin/yii2-curl": "*",
|
||||
"phpoffice/phpexcel": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"yiisoft/yii2-debug": "~2.0.0",
|
||||
"yiisoft/yii2-gii": "~2.0.0",
|
||||
"yiisoft/yii2-faker": "~2.0.0",
|
||||
|
||||
"codeception/base": "^2.2.3",
|
||||
"codeception/verify": "~0.3.1",
|
||||
"codeception/specify": "~0.4.3"
|
||||
},
|
||||
"config": {
|
||||
"process-timeout": 1800,
|
||||
"fxp-asset": {
|
||||
"enabled": false
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"post-install-cmd": [
|
||||
"yii\\composer\\Installer::postInstall"
|
||||
],
|
||||
"post-create-project-cmd": [
|
||||
"yii\\composer\\Installer::postCreateProject",
|
||||
"yii\\composer\\Installer::postInstall"
|
||||
]
|
||||
},
|
||||
"extra": {
|
||||
"yii\\composer\\Installer::postCreateProject": {
|
||||
"setPermission": [
|
||||
{
|
||||
"runtime": "0777",
|
||||
"web/assets": "0777",
|
||||
"yii": "0755"
|
||||
}
|
||||
]
|
||||
},
|
||||
"yii\\composer\\Installer::postInstall": {
|
||||
"generateCookieValidationKey": [
|
||||
"config/web.php"
|
||||
]
|
||||
}
|
||||
},
|
||||
"repositories": [
|
||||
{
|
||||
"type": "composer",
|
||||
"url": "https://asset-packagist.org"
|
||||
}
|
||||
]
|
||||
}
|
4361
composer.lock
generated
Normal file
4361
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
4
config/aliases.php
Normal file
4
config/aliases.php
Normal file
|
@ -0,0 +1,4 @@
|
|||
<?php
|
||||
|
||||
\Yii::setAlias('images_folder', '/data/uploads');
|
||||
|
56
config/console.php
Normal file
56
config/console.php
Normal file
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
$params = require __DIR__ . '/params.php';
|
||||
$db = require __DIR__ . '/db.php';
|
||||
|
||||
$config = [
|
||||
'id' => 'basic-console',
|
||||
'basePath' => dirname(__DIR__),
|
||||
'bootstrap' => ['log'],
|
||||
'controllerNamespace' => 'app\commands',
|
||||
'aliases' => [
|
||||
'@bower' => '@vendor/bower-asset',
|
||||
'@npm' => '@vendor/npm-asset',
|
||||
],
|
||||
'components' => [
|
||||
'authManager' => [
|
||||
'class' => 'yii\rbac\DbManager',
|
||||
'defaultRoles' => ['guest', 'user'],
|
||||
],
|
||||
'cache' => [
|
||||
'class' => 'yii\caching\FileCache',
|
||||
],
|
||||
'log' => [
|
||||
'targets' => [
|
||||
[
|
||||
'class' => 'yii\log\FileTarget',
|
||||
'levels' => ['error', 'warning'],
|
||||
],
|
||||
],
|
||||
],
|
||||
'urlManager' => [
|
||||
'showScriptName' => false,
|
||||
'class' => 'yii\web\UrlManager',
|
||||
'scriptUrl' => "/index.php"
|
||||
],
|
||||
'db' => $db,
|
||||
],
|
||||
'params' => $params,
|
||||
/*
|
||||
'controllerMap' => [
|
||||
'fixture' => [ // Fixture generation command line.
|
||||
'class' => 'yii\faker\FixtureController',
|
||||
],
|
||||
],
|
||||
*/
|
||||
];
|
||||
|
||||
if (YII_ENV_DEV) {
|
||||
// configuration adjustments for 'dev' environment
|
||||
$config['bootstrap'][] = 'gii';
|
||||
$config['modules']['gii'] = [
|
||||
'class' => 'yii\gii\Module',
|
||||
];
|
||||
}
|
||||
|
||||
return $config;
|
14
config/db.php
Normal file
14
config/db.php
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'class' => 'yii\db\Connection',
|
||||
// 'dsn' => 'mysql:host=localhost;dbname=khuvuichoi',
|
||||
'dsn' => 'sqlite:@app/db/app.db',
|
||||
'username' => 'root',
|
||||
'password' => '',
|
||||
'charset' => 'utf8',
|
||||
// Schema cache options (for production environment)
|
||||
//'enableSchemaCache' => true,
|
||||
//'schemaCacheDuration' => 60,
|
||||
//'schemaCache' => 'cache',
|
||||
];
|
5
config/params.php
Normal file
5
config/params.php
Normal file
|
@ -0,0 +1,5 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'adminEmail' => 'admin@example.com',
|
||||
];
|
42
config/test.php
Normal file
42
config/test.php
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
$params = require __DIR__ . '/params.php';
|
||||
$db = require __DIR__ . '/test_db.php';
|
||||
|
||||
/**
|
||||
* Application configuration shared by all test types
|
||||
*/
|
||||
return [
|
||||
'id' => 'basic-tests',
|
||||
'basePath' => dirname(__DIR__),
|
||||
'aliases' => [
|
||||
'@bower' => '@vendor/bower-asset',
|
||||
'@npm' => '@vendor/npm-asset',
|
||||
],
|
||||
'language' => 'en-US',
|
||||
'components' => [
|
||||
'db' => $db,
|
||||
'mailer' => [
|
||||
'useFileTransport' => true,
|
||||
],
|
||||
'assetManager' => [
|
||||
'basePath' => __DIR__ . '/../web/assets',
|
||||
],
|
||||
'urlManager' => [
|
||||
'showScriptName' => true,
|
||||
],
|
||||
'user' => [
|
||||
'identityClass' => 'app\models\User',
|
||||
],
|
||||
'request' => [
|
||||
'cookieValidationKey' => 'test',
|
||||
'enableCsrfValidation' => false,
|
||||
// but if you absolutely need it set cookie domain to localhost
|
||||
/*
|
||||
'csrfCookie' => [
|
||||
'domain' => 'localhost',
|
||||
],
|
||||
*/
|
||||
],
|
||||
],
|
||||
'params' => $params,
|
||||
];
|
6
config/test_db.php
Normal file
6
config/test_db.php
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
$db = require __DIR__ . '/db.php';
|
||||
// test database! Important not to run tests on production or development databases
|
||||
$db['dsn'] = 'mysql:host=localhost;dbname=yii2_basic_tests';
|
||||
|
||||
return $db;
|
143
config/web.php
Normal file
143
config/web.php
Normal file
|
@ -0,0 +1,143 @@
|
|||
<?php
|
||||
|
||||
$params = require __DIR__ . '/params.php';
|
||||
$db = require __DIR__ . '/db.php';
|
||||
|
||||
$config = [
|
||||
'id' => 'basic',
|
||||
'homeUrl' => ['/dashboard'],
|
||||
'name' => 'AIParking Server',
|
||||
'defaultRoute' => 'dashboard',
|
||||
'basePath' => dirname(__DIR__),
|
||||
'bootstrap' => ['log'],
|
||||
'timeZone' => 'Asia/Ho_Chi_Minh',
|
||||
'language' => 'vi-VN',
|
||||
'aliases' => [
|
||||
'@bower' => '@vendor/bower-asset',
|
||||
'@npm' => '@vendor/npm-asset',
|
||||
],
|
||||
'modules' => [
|
||||
'rbac' => [
|
||||
'class' => 'yii2mod\rbac\Module',
|
||||
],
|
||||
],
|
||||
'components' => [
|
||||
'authManager' => [
|
||||
'class' => 'yii\rbac\DbManager', //'app\components\CacheRbacDbManager',
|
||||
'defaultRoles' => ['guest', 'user'],
|
||||
],
|
||||
'mongodb' => [
|
||||
'class' => '\yii\mongodb\Connection',
|
||||
'dsn' => 'mongodb://localhost:27017/human',
|
||||
],
|
||||
'view' => [
|
||||
'theme' => [
|
||||
'pathMap' => [
|
||||
'@app/views' => '@vendor/dmstr/yii2-adminlte-asset/example-views/yiisoft/yii2-app'
|
||||
],
|
||||
],
|
||||
'defaultExtension' => 'tpl',
|
||||
'renderers' => [
|
||||
'tpl' => [
|
||||
'class' => 'yii\smarty\ViewRenderer',
|
||||
//'cachePath' => '@runtime/Smarty/cache',
|
||||
],
|
||||
],
|
||||
],
|
||||
'assetManager' => [
|
||||
'bundles' => [
|
||||
'dmstr\web\AdminLteAsset' => [
|
||||
'skin' => 'skin-blue',
|
||||
],
|
||||
],
|
||||
],
|
||||
'request' => [
|
||||
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
|
||||
'cookieValidationKey' => 'eqHsmuZKxCrVYfeBbpt5suJvVHafnK7O',
|
||||
'enableCsrfValidation' => false,
|
||||
'parsers' => [
|
||||
'application/json' => 'yii\web\JsonParser',
|
||||
]
|
||||
],
|
||||
'cache' => [
|
||||
'class' => 'yii\caching\FileCache',
|
||||
],
|
||||
'user' => [
|
||||
'identityClass' => 'app\models\User',
|
||||
'enableAutoLogin' => true,
|
||||
],
|
||||
'errorHandler' => [
|
||||
'errorAction' => 'site/error',
|
||||
],
|
||||
'mailer' => [
|
||||
'class' => 'yii\swiftmailer\Mailer',
|
||||
'view' => [
|
||||
'defaultExtension' => 'tpl',
|
||||
'renderers' => [
|
||||
'tpl' => [
|
||||
'class' => 'yii\smarty\ViewRenderer',
|
||||
'cachePath' => '@runtime/Smarty/cache',
|
||||
],
|
||||
],
|
||||
],
|
||||
'viewPath' => '@app/mail',
|
||||
'transport' => [
|
||||
'class' => 'Swift_SmtpTransport',
|
||||
'host' => 'smtp.gmail.com',
|
||||
'username' => 'sunrise.media.apps@gmail.com',
|
||||
'password' => 'admin@123456',
|
||||
'port' => '587',
|
||||
'encryption' => 'tls', //ssl use post 465
|
||||
],
|
||||
'useFileTransport' => false,
|
||||
],
|
||||
'i18n' => [
|
||||
'translations' => [
|
||||
'app*' => [
|
||||
'class' => 'yii\i18n\PhpMessageSource',
|
||||
'basePath' => '@app/messages',
|
||||
//'sourceLanguage' => 'en-US',
|
||||
'fileMap' => []
|
||||
],
|
||||
],
|
||||
],
|
||||
'log' => [
|
||||
'traceLevel' => YII_DEBUG ? 3 : 0,
|
||||
'targets' => [
|
||||
[
|
||||
'class' => 'yii\log\FileTarget',
|
||||
'levels' => ['error', 'warning'],
|
||||
],
|
||||
],
|
||||
],
|
||||
'db' => $db
|
||||
],
|
||||
'params' => $params,
|
||||
];
|
||||
|
||||
if (YII_ENV_DEV) {
|
||||
// configuration adjustments for 'dev' environment
|
||||
$config['bootstrap'][] = 'debug';
|
||||
$config['modules']['debug'] = [
|
||||
'class' => 'yii\debug\Module',
|
||||
// 'allowedIPs' => ['127.0.0.1', '::1'],
|
||||
'allowedIPs' => ['*'],
|
||||
];
|
||||
|
||||
$config['bootstrap'][] = 'gii';
|
||||
$config['modules']['gii'] = [
|
||||
'class' => 'yii\gii\Module',
|
||||
// 'allowedIPs' => ['127.0.0.1', '::1'],
|
||||
'allowedIPs' => ['*'],
|
||||
'generators' => [
|
||||
'crud' => [
|
||||
'class' => 'yii\gii\generators\crud\Generator',
|
||||
'templates' => [
|
||||
'adminlte' => '@vendor/dmstr/yii2-adminlte-asset/gii/templates/crud/simple',
|
||||
]
|
||||
]
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
return $config;
|
43
controllers/ApiController.php
Normal file
43
controllers/ApiController.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace app\controllers;
|
||||
|
||||
use Yii;
|
||||
use yii\web\Controller;
|
||||
use yii\filters\VerbFilter;
|
||||
use yii\helpers\FileHelper;
|
||||
use app\models\User;
|
||||
use app\models\Gate;
|
||||
use app\models\Camera;
|
||||
use app\models\Card;
|
||||
use app\models\CardGroup;
|
||||
use app\models\Logs;
|
||||
use app\models\Config;
|
||||
|
||||
/**
|
||||
* CardController implements the CRUD actions for Card model.
|
||||
*/
|
||||
class ApiController extends Controller {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function behaviors() {
|
||||
return [
|
||||
'verbs' => [
|
||||
'class' => VerbFilter::className(),
|
||||
'actions' => [
|
||||
'delete' => ['POST'],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function actionLogin() {
|
||||
if (Yii::$app->request->post()) {
|
||||
$post = Yii::$app->request->bodyParams;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
49
controllers/DashboardController.php
Normal file
49
controllers/DashboardController.php
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
namespace app\controllers;
|
||||
|
||||
use Yii;
|
||||
use app\models\Logs;
|
||||
use app\models\LogsSearch;
|
||||
use yii\web\Controller;
|
||||
use yii\filters\VerbFilter;
|
||||
use yii\helpers\Url;
|
||||
|
||||
/**
|
||||
* ScriptController implements the CRUD actions for Script model.
|
||||
*/
|
||||
class DashboardController extends Controller {
|
||||
|
||||
public function init() {
|
||||
parent::init();
|
||||
if (Yii::$app->user->isGuest) {
|
||||
return $this->redirect(['/site/login']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function behaviors() {
|
||||
return [
|
||||
'verbs' => [
|
||||
'class' => VerbFilter::className(),
|
||||
'actions' => [
|
||||
'delete' => ['POST'],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all Script models.
|
||||
* @return mixed
|
||||
*/
|
||||
public function actionIndex() {
|
||||
$this->view->title = "Bảng tổng hợp";
|
||||
|
||||
return $this->render('index', [
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
122
controllers/SiteController.php
Normal file
122
controllers/SiteController.php
Normal file
|
@ -0,0 +1,122 @@
|
|||
<?php
|
||||
|
||||
namespace app\controllers;
|
||||
|
||||
use Yii;
|
||||
use yii\filters\AccessControl;
|
||||
use yii\web\Controller;
|
||||
use yii\web\Response;
|
||||
use yii\filters\VerbFilter;
|
||||
use app\models\LoginForm;
|
||||
use app\models\ContactForm;
|
||||
|
||||
class SiteController extends Controller {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function behaviors() {
|
||||
return [
|
||||
'access' => [
|
||||
'class' => AccessControl::className(),
|
||||
'only' => ['logout'],
|
||||
'rules' => [
|
||||
[
|
||||
'actions' => ['logout'],
|
||||
'allow' => true,
|
||||
'roles' => ['@'],
|
||||
],
|
||||
],
|
||||
],
|
||||
'verbs' => [
|
||||
'class' => VerbFilter::className(),
|
||||
'actions' => [
|
||||
'logout' => ['post'],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function actions() {
|
||||
return [
|
||||
'error' => [
|
||||
'class' => 'yii\web\ErrorAction',
|
||||
],
|
||||
'captcha' => [
|
||||
'class' => 'yii\captcha\CaptchaAction',
|
||||
'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays homepage.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function actionIndex() {
|
||||
return $this->render('index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Login action.
|
||||
*
|
||||
* @return Response|string
|
||||
*/
|
||||
public function actionLogin() {
|
||||
if (!Yii::$app->user->isGuest) {
|
||||
return $this->goHome();
|
||||
}
|
||||
|
||||
$model = new LoginForm();
|
||||
if ($model->load(Yii::$app->request->post()) && $model->login()) {
|
||||
return $this->redirect(["/dashboard"]);
|
||||
}
|
||||
|
||||
$model->password = '';
|
||||
return $this->render('login', [
|
||||
'model' => $model,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logout action.
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function actionLogout() {
|
||||
Yii::$app->user->logout();
|
||||
|
||||
return $this->goHome();
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays contact page.
|
||||
*
|
||||
* @return Response|string
|
||||
*/
|
||||
public function actionContact() {
|
||||
$model = new ContactForm();
|
||||
if ($model->load(Yii::$app->request->post()) && $model->contact(Yii::$app->params['adminEmail'])) {
|
||||
Yii::$app->session->setFlash('contactFormSubmitted');
|
||||
|
||||
return $this->refresh();
|
||||
}
|
||||
return $this->render('contact', [
|
||||
'model' => $model,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays about page.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function actionAbout() {
|
||||
return $this->render('about');
|
||||
}
|
||||
|
||||
}
|
272
controllers/UserController.php
Normal file
272
controllers/UserController.php
Normal file
|
@ -0,0 +1,272 @@
|
|||
<?php
|
||||
|
||||
namespace app\controllers;
|
||||
|
||||
use Yii;
|
||||
use app\models\User;
|
||||
use app\models\UserSearch;
|
||||
use yii\web\Controller;
|
||||
use yii\web\NotFoundHttpException;
|
||||
use yii\filters\VerbFilter;
|
||||
use yii\helpers\Url;
|
||||
use app\models\AuthItem;
|
||||
use app\models\AuthAssignment;
|
||||
|
||||
/**
|
||||
* UserController implements the CRUD actions for User model.
|
||||
*/
|
||||
class UserController extends Controller {
|
||||
|
||||
public function init() {
|
||||
parent::init();
|
||||
if (Yii::$app->user->isGuest) {
|
||||
return $this->redirect(['/site/login']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function behaviors() {
|
||||
return [
|
||||
'verbs' => [
|
||||
'class' => VerbFilter::className(),
|
||||
'actions' => [
|
||||
'delete' => ['POST'],
|
||||
],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all User models.
|
||||
* @return mixed
|
||||
*/
|
||||
public function actionIndex() {
|
||||
$searchModel = new UserSearch();
|
||||
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
|
||||
return $this->renderAjax("index", [
|
||||
'searchModel' => $searchModel,
|
||||
'dataProvider' => $dataProvider
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a single User model.
|
||||
* @param integer $id
|
||||
* @return mixed
|
||||
* @throws NotFoundHttpException if the model cannot be found
|
||||
*/
|
||||
public function actionView($id) {
|
||||
if (!Yii::$app->user->can("administrator")) {
|
||||
Yii::$app->response->format = "json";
|
||||
return [
|
||||
"title" => "403",
|
||||
"form" => Yii::t("app", "Bạn không có quyền truy cập!")
|
||||
];
|
||||
}
|
||||
|
||||
$model = $this->findModel($id);
|
||||
if (Yii::$app->request->isAjax) {
|
||||
Yii::$app->response->format = "json";
|
||||
return [
|
||||
"title" => "<i class='fa fa-user'></i> " . Yii::t("app", "Thông tin người dùng"),
|
||||
"form" => $this->renderPartial("view", [
|
||||
"model" => $model
|
||||
])
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new User model.
|
||||
* If creation is successful, the browser will be redirected to the 'view' page.
|
||||
* @return mixed
|
||||
*/
|
||||
public function actionCreate() {
|
||||
$model = new User();
|
||||
if (Yii::$app->request->post()) {
|
||||
$post = Yii::$app->request->post();
|
||||
Yii::$app->response->format = "json";
|
||||
$check = User::findOne(["username" => $post['Username']]);
|
||||
if ($check) {
|
||||
return [
|
||||
'stt' => false,
|
||||
"reason" => 'username'
|
||||
];
|
||||
}
|
||||
$check2 = User::findOne(['email' => $post['Email']]);
|
||||
if ($check2) {
|
||||
return [
|
||||
'stt' => false,
|
||||
"reason" => 'email'
|
||||
];
|
||||
}
|
||||
$user_id = $model->create($post);
|
||||
$auth = Yii::$app->authManager;
|
||||
foreach ($post['Role'] as $key => $value) {
|
||||
$role = $auth->getRole($value);
|
||||
if ($role != null) {
|
||||
$auth->assign($role, $user_id);
|
||||
}
|
||||
}
|
||||
return [
|
||||
'stt' => true,
|
||||
'url' => Url::to(['/user'])
|
||||
];
|
||||
} else {
|
||||
Yii::$app->response->format = "json";
|
||||
return [
|
||||
"title" => "<i class='fa fa-plus-circle'></i> " . Yii::t("app", "Tạo người dùng mới"),
|
||||
"form" => $this->renderPartial("form", [
|
||||
"model" => $model,
|
||||
"roles" => AuthItem::roleArray(),
|
||||
"url" => Url::to(['/user/create'])
|
||||
])
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates an existing User model.
|
||||
* If update is successful, the browser will be redirected to the 'view' page.
|
||||
* @param integer $id
|
||||
* @return mixed
|
||||
* @throws NotFoundHttpException if the model cannot be found
|
||||
*/
|
||||
public function actionUpdate($id) {
|
||||
$model = $this->findModel($id);
|
||||
if (Yii::$app->request->post()) {
|
||||
$post = Yii::$app->request->post();
|
||||
if ($post['Username'] !== $model->username) {
|
||||
$check = User::findOne(["username" => $post['Username']]);
|
||||
if ($check)
|
||||
return false;
|
||||
}
|
||||
if ($post['Password'] !== "") {
|
||||
$model->password = md5($post['Password']);
|
||||
}
|
||||
$model->first_name = $post['Name'];
|
||||
$model->username = $post['Username'];
|
||||
$model->phone_number = $post['PhoneNumber'];
|
||||
$model->email = $post['Email'];
|
||||
$model->save();
|
||||
AuthAssignment::deleteAll(['user_id' => $id]);
|
||||
$auth = Yii::$app->authManager;
|
||||
foreach ($post['Role'] as $key => $value) {
|
||||
$role = $auth->getRole($value);
|
||||
if ($role != null) {
|
||||
$auth->assign($role, $id);
|
||||
}
|
||||
}
|
||||
Yii::$app->response->format = "json";
|
||||
return [
|
||||
'stt' => true,
|
||||
'url' => Url::to(['/user'])
|
||||
];
|
||||
} else {
|
||||
Yii::$app->response->format = "json";
|
||||
return [
|
||||
"title" => "<i class='fa fa-edit'></i> " . Yii::t("app", "Sửa thông tin người dùng"),
|
||||
"form" => $this->renderPartial("form", [
|
||||
"model" => $model,
|
||||
"roles" => AuthItem::roleArray(),
|
||||
"url" => Url::to(['/user/update', 'id' => $id])
|
||||
])
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an existing User model.
|
||||
* If deletion is successful, the browser will be redirected to the 'index' page.
|
||||
* @param integer $id
|
||||
* @return mixed
|
||||
* @throws NotFoundHttpException if the model cannot be found
|
||||
*/
|
||||
public function actionDelete($id) {
|
||||
if (Yii::$app->request->isAjax) {
|
||||
$this->findModel($id)->delete();
|
||||
AuthAssignment::deleteAll(['user_id' => $id]);
|
||||
Yii::$app->response->format = "json";
|
||||
return ["url" => Url::to(['/user'])];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the User model based on its primary key value.
|
||||
* If the model is not found, a 404 HTTP exception will be thrown.
|
||||
* @param integer $id
|
||||
* @return User the loaded model
|
||||
* @throws NotFoundHttpException if the model cannot be found
|
||||
*/
|
||||
protected function findModel($id) {
|
||||
if (($model = User::findOne($id)) !== null) {
|
||||
return $model;
|
||||
}
|
||||
|
||||
throw new NotFoundHttpException('The requested page does not exist.');
|
||||
}
|
||||
|
||||
public function actionProfiles() {
|
||||
$model = $this->findModel(Yii::$app->user->id);
|
||||
if (Yii::$app->request->post()) {
|
||||
$post = Yii::$app->request->post();
|
||||
$model->first_name = $post['Name'];
|
||||
$model->phone_number = $post['PhoneNumber'];
|
||||
$model->email = $post['Email'];
|
||||
return $model->save();
|
||||
} else {
|
||||
Yii::$app->response->format = "json";
|
||||
if (Yii::$app->user->isGuest) {
|
||||
return [
|
||||
"title" => "Lỗi",
|
||||
"form" => "Bạn chưa đăng nhập hệ thống"
|
||||
];
|
||||
}
|
||||
return [
|
||||
"title" => "Thông tin cá nhân",
|
||||
"form" => $this->renderPartial('profiles', [
|
||||
"model" => $model
|
||||
])
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function actionChangePassword() {
|
||||
$model = $this->findModel(Yii::$app->user->id);
|
||||
if (Yii::$app->request->post()) {
|
||||
$post = Yii::$app->request->post();
|
||||
$model->password = md5($post['NewPassword']);
|
||||
$model->save();
|
||||
return true;
|
||||
} else {
|
||||
Yii::$app->response->format = "json";
|
||||
if (Yii::$app->user->isGuest) {
|
||||
return [
|
||||
"title" => "Lỗi",
|
||||
"form" => "Bạn chưa đăng nhập hệ thống"
|
||||
];
|
||||
}
|
||||
return [
|
||||
"title" => "Đổi mật khẩu",
|
||||
"form" => $this->renderPartial('password', [
|
||||
"model" => $model
|
||||
])
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
public function actionAvatar() {
|
||||
if (Yii::$app->request->post()) {
|
||||
$model = new \app\models\UploadForm();
|
||||
$path = "avatar/" . Yii::$app->user->id;
|
||||
$url = $model->UploadGlobal("image", ["PNG", "JPG", "JPEG", "GIF"], $path);
|
||||
$UserInfo = User::findOne(Yii::$app->user->id);
|
||||
$UserInfo->user_image = $url;
|
||||
$UserInfo->save();
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
9
docker-compose.yml
Normal file
9
docker-compose.yml
Normal file
|
@ -0,0 +1,9 @@
|
|||
version: '2'
|
||||
services:
|
||||
php:
|
||||
image: yiisoftware/yii2-php:7.1-apache
|
||||
volumes:
|
||||
- ~/.composer-docker/cache:/root/.composer/cache:delegated
|
||||
- ./:/app:delegated
|
||||
ports:
|
||||
- '8000:80'
|
88
helpers/UserGrid.php
Normal file
88
helpers/UserGrid.php
Normal file
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
namespace app\helpers;
|
||||
|
||||
use Yii;
|
||||
use yii\helpers\Html;
|
||||
use yii\helpers\Url;
|
||||
|
||||
class UserGrid {
|
||||
|
||||
public static function engineNameFunc() {
|
||||
return function ($data) {
|
||||
return $data->app->app_name;
|
||||
};
|
||||
}
|
||||
|
||||
public static function getLayout() {
|
||||
return "{items}<div class='row'><div class='col-md-4'>{summary}</div><div class='col-md-8 text-right'>{pager}</div></div>";
|
||||
}
|
||||
|
||||
public static function actionTemplate() {
|
||||
return "{view} {update} {delete}";
|
||||
}
|
||||
|
||||
public static function avatar() {
|
||||
return function($model) {
|
||||
return "23432";
|
||||
};
|
||||
}
|
||||
|
||||
public static function roles() {
|
||||
return function($model) {
|
||||
return $model->roleName;
|
||||
};
|
||||
}
|
||||
|
||||
public static function view() {
|
||||
return function($url, $model) {
|
||||
if (\Yii::$app->user->can("administrator")) {
|
||||
return Html::button("<i class='fa fa-search'></i>", [
|
||||
"class" => "btn btn-info btn-xs",
|
||||
"data" => [
|
||||
"toggle" => "tooltip",
|
||||
"href" => Url::to(['/user/view', 'id' => $model->id])
|
||||
],
|
||||
"title" => Yii::t("app", "View"),
|
||||
"onclick" => "user.form(this);"
|
||||
]);
|
||||
}
|
||||
return "";
|
||||
};
|
||||
}
|
||||
|
||||
public static function update() {
|
||||
return function($url, $model) {
|
||||
if (\Yii::$app->user->can("administrator")) {
|
||||
return Html::button("<i class='fa fa-pencil'></i>", [
|
||||
"class" => "btn btn-success btn-xs",
|
||||
"data" => [
|
||||
"toggle" => "tooltip",
|
||||
"href" => Url::to(['/user/update', 'id' => $model->id])
|
||||
],
|
||||
"title" => Yii::t("app", "Edit"),
|
||||
"onclick" => "user.form(this);"
|
||||
]);
|
||||
}
|
||||
return "";
|
||||
};
|
||||
}
|
||||
|
||||
public static function delete() {
|
||||
return function($url, $model) {
|
||||
if (\Yii::$app->user->can("administrator")) {
|
||||
return Html::button("<i class='fa fa-trash'></i>", [
|
||||
"class" => "btn btn-danger btn-xs",
|
||||
"data" => [
|
||||
"toggle" => "tooltip",
|
||||
"href" => Url::to(['/user/delete', 'id' => $model->id])
|
||||
],
|
||||
"title" => Yii::t("app", "Delete"),
|
||||
"onclick" => "user.delete(this);"
|
||||
]);
|
||||
}
|
||||
return "";
|
||||
};
|
||||
}
|
||||
|
||||
}
|
22
mail/layouts/html.php
Normal file
22
mail/layouts/html.php
Normal file
|
@ -0,0 +1,22 @@
|
|||
<?php
|
||||
use yii\helpers\Html;
|
||||
|
||||
/* @var $this \yii\web\View view component instance */
|
||||
/* @var $message \yii\mail\MessageInterface the message being composed */
|
||||
/* @var $content string main view render result */
|
||||
?>
|
||||
<?php $this->beginPage() ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=<?= Yii::$app->charset ?>" />
|
||||
<title><?= Html::encode($this->title) ?></title>
|
||||
<?php $this->head() ?>
|
||||
</head>
|
||||
<body>
|
||||
<?php $this->beginBody() ?>
|
||||
<?= $content ?>
|
||||
<?php $this->endBody() ?>
|
||||
</body>
|
||||
</html>
|
||||
<?php $this->endPage() ?>
|
17
mail/layouts/html.tpl
Normal file
17
mail/layouts/html.tpl
Normal file
|
@ -0,0 +1,17 @@
|
|||
{use class="yii\helpers\Html"}
|
||||
|
||||
{$this->beginPage()}
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset={$app->charset}" />
|
||||
<title>{$this->title|escape}</title>
|
||||
{$this->head()}
|
||||
</head>
|
||||
<body>
|
||||
{$this->beginBody()}
|
||||
{$content}
|
||||
{$this->endBody()}
|
||||
</body>
|
||||
</html>
|
||||
{$this->endPage()}
|
7
mail/layouts/text.tpl
Normal file
7
mail/layouts/text.tpl
Normal file
|
@ -0,0 +1,7 @@
|
|||
{use class="yii\helpers\Html"}
|
||||
|
||||
{$this->beginPage()}
|
||||
{$this->beginBody()}
|
||||
{$content}
|
||||
{$this->endBody()}
|
||||
{$this->endPage()}
|
3
mail/mailContent.tpl
Normal file
3
mail/mailContent.tpl
Normal file
|
@ -0,0 +1,3 @@
|
|||
{$content}
|
||||
<br>
|
||||
Click vào <a href="{$url}"><b>ĐÂY</b></a> để xem chi tiết
|
9
messages/vi/app.php
Normal file
9
messages/vi/app.php
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
|
||||
return [];
|
48
models/AuthAssignment.php
Normal file
48
models/AuthAssignment.php
Normal file
|
@ -0,0 +1,48 @@
|
|||
<?php
|
||||
|
||||
namespace app\models;
|
||||
|
||||
use Yii;
|
||||
|
||||
/**
|
||||
* This is the model class for table "auth_assignment".
|
||||
*
|
||||
* @property string $item_name
|
||||
* @property string $user_id
|
||||
* @property int $created_at
|
||||
*/
|
||||
class AuthAssignment extends \yii\db\ActiveRecord
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function tableName()
|
||||
{
|
||||
return 'auth_assignment';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
[['item_name', 'user_id'], 'required'],
|
||||
[['created_at'], 'integer'],
|
||||
[['item_name', 'user_id'], 'string', 'max' => 64],
|
||||
[['item_name', 'user_id'], 'unique', 'targetAttribute' => ['item_name', 'user_id']],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function attributeLabels()
|
||||
{
|
||||
return [
|
||||
'item_name' => 'Item Name',
|
||||
'user_id' => 'User ID',
|
||||
'created_at' => 'Created At',
|
||||
];
|
||||
}
|
||||
}
|
98
models/AuthItem.php
Normal file
98
models/AuthItem.php
Normal file
|
@ -0,0 +1,98 @@
|
|||
<?php
|
||||
|
||||
namespace app\models;
|
||||
|
||||
use Yii;
|
||||
|
||||
/**
|
||||
* This is the model class for table "auth_item".
|
||||
*
|
||||
* @property string $name
|
||||
* @property int $type
|
||||
* @property string $description
|
||||
* @property string $rule_name
|
||||
* @property resource $data
|
||||
* @property int $created_at
|
||||
* @property int $updated_at
|
||||
*
|
||||
* @property AuthItemChild[] $authItemChildren
|
||||
* @property AuthItemChild[] $authItemChildren0
|
||||
* @property AuthItem[] $children
|
||||
* @property AuthItem[] $parents
|
||||
*/
|
||||
class AuthItem extends \yii\db\ActiveRecord {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function tableName() {
|
||||
return 'auth_item';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function rules() {
|
||||
return [
|
||||
[['name', 'type'], 'required'],
|
||||
[['type', 'created_at', 'updated_at'], 'integer'],
|
||||
[['description', 'data'], 'string'],
|
||||
[['name', 'rule_name'], 'string', 'max' => 64],
|
||||
[['name'], 'unique'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function attributeLabels() {
|
||||
return [
|
||||
'name' => 'Name',
|
||||
'type' => 'Type',
|
||||
'description' => 'Description',
|
||||
'rule_name' => 'Rule Name',
|
||||
'data' => 'Data',
|
||||
'created_at' => 'Created At',
|
||||
'updated_at' => 'Updated At',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \yii\db\ActiveQuery
|
||||
*/
|
||||
public function getAuthItemChildren() {
|
||||
return $this->hasMany(AuthItemChild::className(), ['parent' => 'name']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \yii\db\ActiveQuery
|
||||
*/
|
||||
public function getAuthItemChildren0() {
|
||||
return $this->hasMany(AuthItemChild::className(), ['child' => 'name']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \yii\db\ActiveQuery
|
||||
*/
|
||||
public function getChildren() {
|
||||
return $this->hasMany(AuthItem::className(), ['name' => 'child'])->viaTable('auth_item_child', ['parent' => 'name']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \yii\db\ActiveQuery
|
||||
*/
|
||||
public function getParents() {
|
||||
return $this->hasMany(AuthItem::className(), ['name' => 'parent'])->viaTable('auth_item_child', ['child' => 'name']);
|
||||
}
|
||||
|
||||
public static function roleArray() {
|
||||
$ls = self::find()->all();
|
||||
$re = [];
|
||||
foreach ($ls as $key => $value) {
|
||||
if (!in_array($value->name, ['hoa_sy', 'kiem_duyet', 'quy_trinh_cu', 'kiem_duyet_kich_ban', 'kiem_duyet_phan_canh', 'kiem_duyet_to_mau', 'kiem_duyet_ve_dong', 'kiem_duyet_sach_xen', 'kiem_duyet_ky_thuat']))
|
||||
$re[$value->name] = Yii::t("app", $value->description);
|
||||
}
|
||||
return $re;
|
||||
}
|
||||
|
||||
}
|
64
models/ContactForm.php
Normal file
64
models/ContactForm.php
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?php
|
||||
|
||||
namespace app\models;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Model;
|
||||
|
||||
/**
|
||||
* ContactForm is the model behind the contact form.
|
||||
*/
|
||||
class ContactForm extends Model
|
||||
{
|
||||
public $name;
|
||||
public $email;
|
||||
public $subject;
|
||||
public $body;
|
||||
public $verifyCode;
|
||||
|
||||
|
||||
/**
|
||||
* @return array the validation rules.
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
// name, email, subject and body are required
|
||||
[['name', 'email', 'subject', 'body'], 'required'],
|
||||
// email has to be a valid email address
|
||||
['email', 'email'],
|
||||
// verifyCode needs to be entered correctly
|
||||
['verifyCode', 'captcha'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array customized attribute labels
|
||||
*/
|
||||
public function attributeLabels()
|
||||
{
|
||||
return [
|
||||
'verifyCode' => 'Verification Code',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends an email to the specified email address using the information collected by this model.
|
||||
* @param string $email the target email address
|
||||
* @return bool whether the model passes validation
|
||||
*/
|
||||
public function contact($email)
|
||||
{
|
||||
if ($this->validate()) {
|
||||
Yii::$app->mailer->compose()
|
||||
->setTo($email)
|
||||
->setFrom([$this->email => $this->name])
|
||||
->setSubject($this->subject)
|
||||
->setTextBody($this->body)
|
||||
->send();
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
75
models/LoginForm.php
Normal file
75
models/LoginForm.php
Normal file
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
|
||||
namespace app\models;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Model;
|
||||
|
||||
/**
|
||||
* LoginForm is the model behind the login form.
|
||||
*
|
||||
* @property User|null $user This property is read-only.
|
||||
*
|
||||
*/
|
||||
class LoginForm extends Model {
|
||||
|
||||
public $username;
|
||||
public $password;
|
||||
public $rememberMe = true;
|
||||
private $_user = false;
|
||||
|
||||
/**
|
||||
* @return array the validation rules.
|
||||
*/
|
||||
public function rules() {
|
||||
return [
|
||||
// username and password are both required
|
||||
[['username', 'password'], 'required'],
|
||||
// rememberMe must be a boolean value
|
||||
['rememberMe', 'boolean'],
|
||||
// password is validated by validatePassword()
|
||||
['password', 'validatePassword'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the password.
|
||||
* This method serves as the inline validation for password.
|
||||
*
|
||||
* @param string $attribute the attribute currently being validated
|
||||
* @param array $params the additional name-value pairs given in the rule
|
||||
*/
|
||||
public function validatePassword($attribute, $params) {
|
||||
if (!$this->hasErrors()) {
|
||||
$user = $this->getUser();
|
||||
if (!$user || !$user->validatePassword($this->password)) {
|
||||
$this->addError($attribute, 'Incorrect username or password.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs in a user using the provided username and password.
|
||||
* @return bool whether the user is logged in successfully
|
||||
*/
|
||||
public function login() {
|
||||
if ($this->validate()) {
|
||||
return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds user by [[username]]
|
||||
*
|
||||
* @return User|null
|
||||
*/
|
||||
public function getUser() {
|
||||
if ($this->_user === false) {
|
||||
$this->_user = User::findByUsername($this->username);
|
||||
}
|
||||
|
||||
return $this->_user;
|
||||
}
|
||||
|
||||
}
|
160
models/UploadForm.php
Normal file
160
models/UploadForm.php
Normal file
|
@ -0,0 +1,160 @@
|
|||
<?php
|
||||
|
||||
namespace app\models;
|
||||
|
||||
use yii\base\Model;
|
||||
use yii\web\UploadedFile;
|
||||
|
||||
class UploadForm extends Model {
|
||||
|
||||
/**
|
||||
* @var UploadedFile[]
|
||||
*/
|
||||
public $imageFiles;
|
||||
|
||||
public function rules() {
|
||||
return [
|
||||
[['imageFiles'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg, jpeg, pdf, rar, zip', 'maxFiles' => 70],
|
||||
];
|
||||
}
|
||||
|
||||
public function upload($params) {
|
||||
if ($this->validate()) {
|
||||
$currentStorage = Storage::findOne(['stt' => 1])->folder;
|
||||
// $root = \Yii::getAlias('@app') . '/web/data/uploads/';
|
||||
$root = $currentStorage . "/uploads/";
|
||||
$folder = $root . $params['project_type'] . "/" . $params['project_id'] . "/" . $params['p_id'];
|
||||
if (!file_exists($folder))
|
||||
mkdir($folder, 0777, true);
|
||||
|
||||
$files = [];
|
||||
foreach ($this->imageFiles as $file) {
|
||||
$file->saveAs($folder . "/" . $file->baseName . '.' . $file->extension);
|
||||
$files[] = $file->baseName . '.' . $file->extension;
|
||||
}
|
||||
$model = new Images();
|
||||
$model->create($params, $files);
|
||||
$results = Results::findOne(['project_id' => $params['project_id_raw'], 'p_id' => $params['p_id_raw']]);
|
||||
$results->content = "yes";
|
||||
if ($results->create_at == $results->modified_at) {
|
||||
$results->modified_at = time();
|
||||
}
|
||||
$results->save();
|
||||
return true;
|
||||
} else {
|
||||
var_dump($this->errors);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function uploadZip($params) {
|
||||
return $this->UploadFile('file' . $params["name"], ["RAR", "ZIP", "MPG", "MXF"], $params);
|
||||
}
|
||||
|
||||
public function uploadDoc($params) {
|
||||
return $this->UploadFile('file' . $params["name"], ["DOC", "DOCX", "XLS", "XLSX"], $params);
|
||||
}
|
||||
|
||||
public function uploadWord($params) {
|
||||
return $this->UploadFile('file' . $params["name"], ["DOC", "DOCX", "RAR", "ZIP"], $params);
|
||||
}
|
||||
|
||||
public function uploadMp3($params) {
|
||||
return $this->UploadFile('file' . $params["name"], ["MP3", "WAV", "RAR", "ZIP"], $params);
|
||||
}
|
||||
|
||||
public function UploadFile($file, $fileTypes, $params) {
|
||||
$currentStorage = Storage::findOne(['stt' => 1])->folder;
|
||||
// $root = \Yii::getAlias('@app') . '/web/data/uploads';
|
||||
$root = $currentStorage . "/uploads";
|
||||
$LocalPath = "/" . $params['project_type'] . "/" . $params['project_id'] . "/" . $params['p_id'];
|
||||
$RootFolder = $root . $LocalPath;
|
||||
// $name = $_FILES[$file]["name"];
|
||||
// $array = explode(".", $name);
|
||||
// $nr = count($array);
|
||||
// $ext = $array[$nr - 1];
|
||||
// $fileName = md5($params['project_type'] . "/" . $params['project_id'] . "/" . $params['p_id']);
|
||||
$destfile = $_FILES[$file]["name"];
|
||||
if (!empty($_FILES)) {
|
||||
$tempFile = $_FILES[$file]['tmp_name'];
|
||||
$targetPath = $RootFolder;
|
||||
if (!file_exists($targetPath)) {
|
||||
@mkdir($targetPath, 0777, true);
|
||||
}
|
||||
$targetFile = $targetPath . '/' . $destfile;
|
||||
$targetFileLocal = $LocalPath . '/' . $destfile;
|
||||
// Validate the file type
|
||||
$fileParts = pathinfo($_FILES[$file]['name']);
|
||||
if (in_array(strtoupper($fileParts['extension']), $fileTypes)) {
|
||||
move_uploaded_file($tempFile, $targetFile);
|
||||
if (file_exists($targetFile)) {
|
||||
return $targetFileLocal;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function UploadGlobal($file, $fileTypes, $path) {
|
||||
$root = \Yii::getAlias('@app') . '/web/data/uploads';
|
||||
$LocalPath = "/" . $path;
|
||||
$RootFolder = $root . $LocalPath;
|
||||
// $name = $_FILES[$file]["name"];
|
||||
// $array = explode(".", $name);
|
||||
// $nr = count($array);
|
||||
// $ext = $array[$nr - 1];
|
||||
// $fileName = md5($path);
|
||||
$destfile = time() . "_" . $_FILES[$file]["name"]; // time() . "_" . $fileName . "." . $ext;
|
||||
if (!empty($_FILES)) {
|
||||
$tempFile = $_FILES[$file]['tmp_name'];
|
||||
$targetPath = $RootFolder;
|
||||
if (!file_exists($targetPath)) {
|
||||
@mkdir($targetPath, 0777, true);
|
||||
}
|
||||
$targetFile = $targetPath . '/' . $destfile;
|
||||
$targetFileLocal = $LocalPath . '/' . $destfile;
|
||||
// Validate the file type
|
||||
$fileParts = pathinfo($_FILES[$file]['name']);
|
||||
if (in_array(strtoupper($fileParts['extension']), $fileTypes)) {
|
||||
move_uploaded_file($tempFile, $targetFile);
|
||||
if (file_exists($targetFile)) {
|
||||
return $targetFileLocal;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Move file
|
||||
public function MoveFile($file, $folder) {
|
||||
$currentStorage = Storage::findOne(['stt' => 1])->folder;
|
||||
$root = $currentStorage . "/uploads";
|
||||
// $root = \Yii::getAlias('@app') . '/web/data/uploads/';
|
||||
$tempdir = $file;
|
||||
if (trim($tempdir) !== "") {
|
||||
$tempdir = $root . trim($tempdir);
|
||||
} else {
|
||||
$tempdir = "/dddddddddddddddddddddeeeeeeeeeeeee";
|
||||
}
|
||||
if (file_exists($tempdir)) {
|
||||
$destfile = basename($tempdir);
|
||||
$dir = $root . $folder;
|
||||
$file_dir = $dir . '/' . $destfile;
|
||||
$link = $destfile;
|
||||
if (!file_exists($dir)) {
|
||||
@mkdir($dir, 0777, true);
|
||||
}
|
||||
$output = shell_exec("mv {$tempdir} {$file_dir}");
|
||||
} else {
|
||||
$link = $file;
|
||||
}
|
||||
return $link;
|
||||
}
|
||||
|
||||
}
|
203
models/User.php
Normal file
203
models/User.php
Normal file
|
@ -0,0 +1,203 @@
|
|||
<?php
|
||||
|
||||
namespace app\models;
|
||||
|
||||
use Yii;
|
||||
use yii\db\ActiveRecord;
|
||||
|
||||
class User extends ActiveRecord implements \yii\web\IdentityInterface {
|
||||
|
||||
public static function tableName() {
|
||||
return 'user';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function rules() {
|
||||
return [
|
||||
[['username', 'password'], 'required'],
|
||||
[['email'], 'email'],
|
||||
[['username', 'email'], 'unique'],
|
||||
[['phone_number'], 'string', 'max' => 30],
|
||||
[['username', 'password', 'password_reset_token', 'first_name', 'last_name'], 'string', 'max' => 250],
|
||||
[['user_image', 'email'], 'string', 'max' => 500]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function attributeLabels() {
|
||||
return [
|
||||
'first_name' => "Tên đăng nhập",
|
||||
'last_name' => 'Last Name',
|
||||
'username' => "Họ tên",
|
||||
'phone_number' => "Điện thoại",
|
||||
'email' => "Email",
|
||||
'roleName' => "Phân quyền"
|
||||
];
|
||||
}
|
||||
|
||||
public static function findIdentity($id) {
|
||||
$user = self::find()
|
||||
->where([
|
||||
"id" => $id
|
||||
])
|
||||
->one();
|
||||
if ($user == null) {
|
||||
return null;
|
||||
}
|
||||
return new static($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public static function findIdentityByAccessToken($token, $userType = null) {
|
||||
|
||||
$user = self::find()
|
||||
->where(["accessToken" => $token])
|
||||
->one();
|
||||
if (!count($user)) {
|
||||
return null;
|
||||
}
|
||||
return new static($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds user by username
|
||||
*
|
||||
* @param string $username
|
||||
* @return static|null
|
||||
*/
|
||||
public static function findByUsername($username) {
|
||||
$user = self::find()
|
||||
->where([
|
||||
"username" => $username
|
||||
])
|
||||
->one();
|
||||
if ($user == null) {
|
||||
return null;
|
||||
}
|
||||
return new static($user);
|
||||
}
|
||||
|
||||
public static function findByUser($username) {
|
||||
$user = self::find()
|
||||
->where([
|
||||
"username" => $username
|
||||
])
|
||||
->one();
|
||||
if ($user == null) {
|
||||
return null;
|
||||
}
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getId() {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getAuthKey() {
|
||||
return $this->authKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function validateAuthKey($authKey) {
|
||||
return $this->authKey === $authKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates password
|
||||
*
|
||||
* @param string $password password to validate
|
||||
* @return boolean if password provided is valid for current user
|
||||
*/
|
||||
public function validatePassword($password) {
|
||||
return $this->password === md5($password);
|
||||
}
|
||||
|
||||
public function create($data) {
|
||||
$r = $this->load([
|
||||
'first_name' => $data['Name'],
|
||||
'username' => $data['Username'],
|
||||
'password' => $data['Password'] !== "" ? md5($data['Password']) : md5('123456a@'),
|
||||
'phone_number' => $data['PhoneNumber'],
|
||||
'email' => $data['Email']
|
||||
], '');
|
||||
if ($r) {
|
||||
try {
|
||||
$this->save();
|
||||
return $this->id;
|
||||
} catch (\Exception $ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getRole() {
|
||||
return AuthAssignment::findOne(['user_id' => $this->id])->item_name;
|
||||
}
|
||||
|
||||
public function getRoleName() {
|
||||
$roles = $this->roles;
|
||||
$lists = "";
|
||||
foreach ($roles as $key => $value) {
|
||||
$lists .= \yii\helpers\Html::label(Yii::t("app", AuthItem::findOne(['name' => $value])->description), "", ["class" => "label label-info"]) . " ";
|
||||
}
|
||||
return $lists;
|
||||
}
|
||||
|
||||
public function getRoleNameLists() {
|
||||
$roles = $this->roles;
|
||||
$lists = [];
|
||||
foreach ($roles as $key => $value) {
|
||||
$lists[] = AuthItem::findOne(['name' => $value])->description;
|
||||
}
|
||||
return implode(",", $lists);
|
||||
}
|
||||
|
||||
public function getRoles() {
|
||||
$roleArray = [];
|
||||
$roles = AuthAssignment::find()->andWhere(['user_id' => $this->id])->all();
|
||||
foreach ($roles as $key => $value) {
|
||||
$roleArray[] = $value->item_name;
|
||||
}
|
||||
return $roleArray;
|
||||
}
|
||||
|
||||
public static function securityArray($all = false) {
|
||||
$ls = AuthAssignment::find()->andWhere(['IN', 'item_name', ["security"]])->all();
|
||||
$temp = [];
|
||||
foreach ($ls as $key => $value) {
|
||||
$temp[] = $value->user_id;
|
||||
}
|
||||
$lsID = array_unique($temp);
|
||||
$re = [];
|
||||
foreach ($lsID as $key => $value) {
|
||||
if ($all) {
|
||||
$re[$value] = self::findOne($value)->first_name;
|
||||
} else {
|
||||
$check = Gate::findOne(['user_id' => $value]);
|
||||
if (!$check)
|
||||
$re[$value] = self::findOne($value)->first_name;
|
||||
}
|
||||
}
|
||||
return $re;
|
||||
}
|
||||
|
||||
public function getAvatar() {
|
||||
$directoryAsset = Yii::$app->assetManager->getPublishedUrl('@vendor/almasaeed2010/adminlte/dist');
|
||||
return $this->user_image == null ? $directoryAsset . "/img/user2-160x160.jpg" : Yii::getAlias("@images_folder") . $this->user_image;
|
||||
}
|
||||
|
||||
}
|
77
models/UserSearch.php
Normal file
77
models/UserSearch.php
Normal file
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
namespace app\models;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Model;
|
||||
use yii\data\ActiveDataProvider;
|
||||
use app\models\User;
|
||||
|
||||
/**
|
||||
* UserSearch represents the model behind the search form of `app\models\User`.
|
||||
*/
|
||||
class UserSearch extends User
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
[['id'], 'integer'],
|
||||
[['first_name', 'last_name', 'phone_number', 'username', 'email', 'password', 'authKey', 'password_reset_token', 'user_image'], 'safe'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function scenarios()
|
||||
{
|
||||
// bypass scenarios() implementation in the parent class
|
||||
return Model::scenarios();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates data provider instance with search query applied
|
||||
*
|
||||
* @param array $params
|
||||
*
|
||||
* @return ActiveDataProvider
|
||||
*/
|
||||
public function search($params)
|
||||
{
|
||||
$query = User::find();
|
||||
|
||||
// add conditions that should always apply here
|
||||
|
||||
$dataProvider = new ActiveDataProvider([
|
||||
'query' => $query,
|
||||
]);
|
||||
|
||||
$this->load($params);
|
||||
|
||||
if (!$this->validate()) {
|
||||
// uncomment the following line if you do not want to return any records when validation fails
|
||||
// $query->where('0=1');
|
||||
return $dataProvider;
|
||||
}
|
||||
|
||||
// grid filtering conditions
|
||||
$query->andFilterWhere([
|
||||
'id' => $this->id,
|
||||
]);
|
||||
|
||||
$query->andFilterWhere(['like', 'first_name', $this->first_name])
|
||||
->andFilterWhere(['like', 'last_name', $this->last_name])
|
||||
->andFilterWhere(['like', 'phone_number', $this->phone_number])
|
||||
->andFilterWhere(['like', 'username', $this->username])
|
||||
->andFilterWhere(['like', 'email', $this->email])
|
||||
->andFilterWhere(['like', 'password', $this->password])
|
||||
->andFilterWhere(['like', 'authKey', $this->authKey])
|
||||
->andFilterWhere(['like', 'password_reset_token', $this->password_reset_token])
|
||||
->andFilterWhere(['like', 'user_image', $this->user_image]);
|
||||
|
||||
return $dataProvider;
|
||||
}
|
||||
}
|
174
models/common.php
Normal file
174
models/common.php
Normal file
|
@ -0,0 +1,174 @@
|
|||
<?php
|
||||
|
||||
namespace app\models;
|
||||
|
||||
use Yii;
|
||||
|
||||
class common extends \yii\db\ActiveRecord {
|
||||
|
||||
public function formatName($name) {
|
||||
return preg_replace('/[^a-zA-Z0-9 _-]/', '', $this->vn2latin($name, true));
|
||||
}
|
||||
|
||||
public function vn2latin($cs, $tolower = false) {
|
||||
/* Mảng chứa tất cả ký tự có dấu trong Tiếng Việt */
|
||||
$marTViet = array("à", "á", "ạ", "ả", "ã", "â", "ầ", "ấ", "ậ", "ẩ", "ẫ", "ă",
|
||||
"ằ", "ắ", "ặ", "ẳ", "ẵ", "è", "é", "ẹ", "ẻ", "ẽ", "ê", "ề",
|
||||
"ế", "ệ", "ể", "ễ",
|
||||
"ì", "í", "ị", "ỉ", "ĩ",
|
||||
"ò", "ó", "ọ", "ỏ", "õ", "ô", "ồ", "ố", "ộ", "ổ", "ỗ", "ơ",
|
||||
"ờ", "ớ", "ợ", "ở", "ỡ",
|
||||
"ù", "ú", "ụ", "ủ", "ũ", "ư", "ừ", "ứ", "ự", "ử", "ữ",
|
||||
"ỳ", "ý", "ỵ", "ỷ", "ỹ",
|
||||
"đ",
|
||||
"À", "Á", "Ạ", "Ả", "Ã", "Â", "Ầ", "Ấ", "Ậ", "Ẩ", "Ẫ", "Ă",
|
||||
"Ằ", "Ắ", "Ặ", "Ẳ", "Ẵ",
|
||||
"È", "É", "Ẹ", "Ẻ", "Ẽ", "Ê", "Ề", "Ế", "Ệ", "Ể", "Ễ",
|
||||
"Ì", "Í", "Ị", "Ỉ", "Ĩ",
|
||||
"Ò", "Ó", "Ọ", "Ỏ", "Õ", "Ô", "Ồ", "Ố", "Ộ", "Ổ", "Ỗ", "Ơ", "Ờ", "Ớ", "Ợ", "Ở", "Ỡ",
|
||||
"Ù", "Ú", "Ụ", "Ủ", "Ũ", "Ư", "Ừ", "Ứ", "Ự", "Ử", "Ữ",
|
||||
"Ỳ", "Ý", "Ỵ", "Ỷ", "Ỹ",
|
||||
"Đ", " ");
|
||||
|
||||
/* Mảng chứa tất cả ký tự không dấu tương ứng với mảng $marTViet bên trên */
|
||||
$marKoDau = array("a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a",
|
||||
"a", "a", "a", "a", "a", "a",
|
||||
"e", "e", "e", "e", "e", "e", "e", "e", "e", "e", "e",
|
||||
"i", "i", "i", "i", "i",
|
||||
"o", "o", "o", "o", "o", "o", "o", "o", "o", "o", "o", "o",
|
||||
"o", "o", "o", "o", "o",
|
||||
"u", "u", "u", "u", "u", "u", "u", "u", "u", "u", "u",
|
||||
"y", "y", "y", "y", "y",
|
||||
"d",
|
||||
"A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A", "A",
|
||||
"A", "A", "A", "A", "A",
|
||||
"E", "E", "E", "E", "E", "E", "E", "E", "E", "E", "E",
|
||||
"I", "I", "I", "I", "I",
|
||||
"O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O", "O",
|
||||
"U", "U", "U", "U", "U", "U", "U", "U", "U", "U", "U",
|
||||
"Y", "Y", "Y", "Y", "Y",
|
||||
"D", "-");
|
||||
|
||||
if ($tolower) {
|
||||
return strtolower(str_replace($marTViet, $marKoDau, $cs));
|
||||
}
|
||||
return str_replace($marTViet, $marKoDau, $cs);
|
||||
}
|
||||
|
||||
public function formatTime($time, $format = "d/m/Y") {
|
||||
// $now = time();
|
||||
// $range = $now - $time;
|
||||
// if ($range > 60 * 60 * 12) {
|
||||
return date($format, $time);
|
||||
// } else {
|
||||
// return Yii::$app->formatter->asRelativeTime($time);
|
||||
// }
|
||||
}
|
||||
|
||||
//Upload
|
||||
public function UploadFile($file, $fileTypes, $dir) {
|
||||
$LocalPath = "data/" . $dir;
|
||||
$RootFolder = Yii::getAlias('@webroot') . "/" . $LocalPath;
|
||||
$name = $_FILES[$file]["name"];
|
||||
$array = explode(".", $name);
|
||||
$nr = count($array);
|
||||
$ext = $array[$nr - 1];
|
||||
$fileName = preg_replace('/[^a-zA-Z0-9 _-]/', '', $this->vn2latin($array[0], true));
|
||||
$destfile = time() . "_" . $fileName . "." . $ext;
|
||||
if (!empty($_FILES)) {
|
||||
$tempFile = $_FILES[$file]['tmp_name'];
|
||||
$targetPath = $RootFolder;
|
||||
if (!file_exists($targetPath)) {
|
||||
@mkdir($targetPath, 0777, true);
|
||||
}
|
||||
$targetFile = $targetPath . '/' . $destfile;
|
||||
$targetFileLocal = $LocalPath . '/' . $destfile;
|
||||
// Validate the file type
|
||||
$fileParts = pathinfo($_FILES[$file]['name']);
|
||||
if (in_array(strtoupper($fileParts['extension']), $fileTypes)) {
|
||||
move_uploaded_file($tempFile, $targetFile);
|
||||
if (file_exists($targetFile)) {
|
||||
return $targetFileLocal;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Move file
|
||||
public function MoveFile($file, $folder) {
|
||||
$exp = explode("/", $file);
|
||||
$t = [];
|
||||
foreach ($exp as $key => $value) {
|
||||
if ($key < count($exp) - 1) {
|
||||
$t[] = $value;
|
||||
}
|
||||
}
|
||||
$folderOld = implode("/", $t);
|
||||
$root = \Yii::getAlias('@app') . '/web/data/uploads' . trim($folderOld);
|
||||
chdir($root);
|
||||
$nameArr = explode(".", basename($file));
|
||||
$name = $this->formatName($nameArr[0]);
|
||||
$ext = $nameArr[count($nameArr) - 1];
|
||||
rename(basename($file), $name . "." . $ext);
|
||||
$tempdir = $root . "/" . $name . "." . $ext;
|
||||
if (file_exists($tempdir)) {
|
||||
$destfile = basename($tempdir);
|
||||
$dir = Yii::getAlias('@webroot') . "/data/uploads" . $folder;
|
||||
$file_dir = $dir . '/' . $destfile;
|
||||
if (!file_exists($dir)) {
|
||||
@mkdir($dir, 0777, true);
|
||||
}
|
||||
$output = shell_exec("mv {$tempdir} {$file_dir}");
|
||||
$link = $folder . "/" . $destfile;
|
||||
} else {
|
||||
$link = $file;
|
||||
}
|
||||
return $link;
|
||||
}
|
||||
|
||||
//File size
|
||||
public function filesize_formatted($path) {
|
||||
$size = filesize($path);
|
||||
$units = array('B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
|
||||
$power = $size > 0 ? floor(log($size, 1024)) : 0;
|
||||
return number_format($size / pow(1024, $power), 2, '.', ',') . " " . $units[$power];
|
||||
}
|
||||
|
||||
public function getExtension($file) {
|
||||
$f = basename($file);
|
||||
$ls = explode(".", $file);
|
||||
return strtolower($ls[count($ls) - 1]);
|
||||
}
|
||||
|
||||
public function convertIntToTime($seconds) {
|
||||
$hours = floor($seconds / 3600);
|
||||
$mins = floor($seconds / 60 % 60);
|
||||
$secs = floor($seconds % 60);
|
||||
if ($hours > 0) {
|
||||
return sprintf('%02d:%02d:%02d', $hours, $mins, $secs);
|
||||
} else {
|
||||
return sprintf('%02d:%02d', $mins, $secs);
|
||||
}
|
||||
}
|
||||
|
||||
public function visiblePharse($stt, $tab, $pharse) {
|
||||
$visible = false;
|
||||
if ($stt != 0) {
|
||||
if ($stt == -1) {
|
||||
if ($tab == $pharse) {
|
||||
$visible = true;
|
||||
}
|
||||
} else {
|
||||
$visible = true;
|
||||
}
|
||||
} else {
|
||||
$visible = true;
|
||||
}
|
||||
return $visible;
|
||||
}
|
||||
|
||||
}
|
160
requirements.php
Normal file
160
requirements.php
Normal file
|
@ -0,0 +1,160 @@
|
|||
<?php
|
||||
/**
|
||||
* Application requirement checker script.
|
||||
*
|
||||
* In order to run this script use the following console command:
|
||||
* php requirements.php
|
||||
*
|
||||
* In order to run this script from the web, you should copy it to the web root.
|
||||
* If you are using Linux you can create a hard link instead, using the following command:
|
||||
* ln ../requirements.php requirements.php
|
||||
*/
|
||||
|
||||
// you may need to adjust this path to the correct Yii framework path
|
||||
// uncomment and adjust the following line if Yii is not located at the default path
|
||||
//$frameworkPath = dirname(__FILE__) . '/vendor/yiisoft/yii2';
|
||||
|
||||
|
||||
if (!isset($frameworkPath)) {
|
||||
$searchPaths = [
|
||||
dirname(__FILE__) . '/vendor/yiisoft/yii2',
|
||||
dirname(__FILE__) . '/../vendor/yiisoft/yii2',
|
||||
];
|
||||
foreach($searchPaths as $path) {
|
||||
if (is_dir($path)) {
|
||||
$frameworkPath = $path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!isset($frameworkPath) || !is_dir($frameworkPath)) {
|
||||
$message = "<h1>Error</h1>\n\n"
|
||||
. "<p><strong>The path to yii framework seems to be incorrect.</strong></p>\n"
|
||||
. '<p>You need to install Yii framework via composer or adjust the framework path in file <abbr title="' . __FILE__ . '">' . basename(__FILE__) . "</abbr>.</p>\n"
|
||||
. '<p>Please refer to the <abbr title="' . dirname(__FILE__) . "/README.md\">README</abbr> on how to install Yii.</p>\n";
|
||||
|
||||
if (!empty($_SERVER['argv'])) {
|
||||
// do not print HTML when used in console mode
|
||||
echo strip_tags($message);
|
||||
} else {
|
||||
echo $message;
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
|
||||
require_once($frameworkPath . '/requirements/YiiRequirementChecker.php');
|
||||
$requirementsChecker = new YiiRequirementChecker();
|
||||
|
||||
$gdMemo = $imagickMemo = 'Either GD PHP extension with FreeType support or ImageMagick PHP extension with PNG support is required for image CAPTCHA.';
|
||||
$gdOK = $imagickOK = false;
|
||||
|
||||
if (extension_loaded('imagick')) {
|
||||
$imagick = new Imagick();
|
||||
$imagickFormats = $imagick->queryFormats('PNG');
|
||||
if (in_array('PNG', $imagickFormats)) {
|
||||
$imagickOK = true;
|
||||
} else {
|
||||
$imagickMemo = 'Imagick extension should be installed with PNG support in order to be used for image CAPTCHA.';
|
||||
}
|
||||
}
|
||||
|
||||
if (extension_loaded('gd')) {
|
||||
$gdInfo = gd_info();
|
||||
if (!empty($gdInfo['FreeType Support'])) {
|
||||
$gdOK = true;
|
||||
} else {
|
||||
$gdMemo = 'GD extension should be installed with FreeType support in order to be used for image CAPTCHA.';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adjust requirements according to your application specifics.
|
||||
*/
|
||||
$requirements = array(
|
||||
// Database :
|
||||
array(
|
||||
'name' => 'PDO extension',
|
||||
'mandatory' => true,
|
||||
'condition' => extension_loaded('pdo'),
|
||||
'by' => 'All DB-related classes',
|
||||
),
|
||||
array(
|
||||
'name' => 'PDO SQLite extension',
|
||||
'mandatory' => false,
|
||||
'condition' => extension_loaded('pdo_sqlite'),
|
||||
'by' => 'All DB-related classes',
|
||||
'memo' => 'Required for SQLite database.',
|
||||
),
|
||||
array(
|
||||
'name' => 'PDO MySQL extension',
|
||||
'mandatory' => false,
|
||||
'condition' => extension_loaded('pdo_mysql'),
|
||||
'by' => 'All DB-related classes',
|
||||
'memo' => 'Required for MySQL database.',
|
||||
),
|
||||
array(
|
||||
'name' => 'PDO PostgreSQL extension',
|
||||
'mandatory' => false,
|
||||
'condition' => extension_loaded('pdo_pgsql'),
|
||||
'by' => 'All DB-related classes',
|
||||
'memo' => 'Required for PostgreSQL database.',
|
||||
),
|
||||
// Cache :
|
||||
array(
|
||||
'name' => 'Memcache extension',
|
||||
'mandatory' => false,
|
||||
'condition' => extension_loaded('memcache') || extension_loaded('memcached'),
|
||||
'by' => '<a href="http://www.yiiframework.com/doc-2.0/yii-caching-memcache.html">MemCache</a>',
|
||||
'memo' => extension_loaded('memcached') ? 'To use memcached set <a href="http://www.yiiframework.com/doc-2.0/yii-caching-memcache.html#$useMemcached-detail">MemCache::useMemcached</a> to <code>true</code>.' : ''
|
||||
),
|
||||
// CAPTCHA:
|
||||
array(
|
||||
'name' => 'GD PHP extension with FreeType support',
|
||||
'mandatory' => false,
|
||||
'condition' => $gdOK,
|
||||
'by' => '<a href="http://www.yiiframework.com/doc-2.0/yii-captcha-captcha.html">Captcha</a>',
|
||||
'memo' => $gdMemo,
|
||||
),
|
||||
array(
|
||||
'name' => 'ImageMagick PHP extension with PNG support',
|
||||
'mandatory' => false,
|
||||
'condition' => $imagickOK,
|
||||
'by' => '<a href="http://www.yiiframework.com/doc-2.0/yii-captcha-captcha.html">Captcha</a>',
|
||||
'memo' => $imagickMemo,
|
||||
),
|
||||
// PHP ini :
|
||||
'phpExposePhp' => array(
|
||||
'name' => 'Expose PHP',
|
||||
'mandatory' => false,
|
||||
'condition' => $requirementsChecker->checkPhpIniOff("expose_php"),
|
||||
'by' => 'Security reasons',
|
||||
'memo' => '"expose_php" should be disabled at php.ini',
|
||||
),
|
||||
'phpAllowUrlInclude' => array(
|
||||
'name' => 'PHP allow url include',
|
||||
'mandatory' => false,
|
||||
'condition' => $requirementsChecker->checkPhpIniOff("allow_url_include"),
|
||||
'by' => 'Security reasons',
|
||||
'memo' => '"allow_url_include" should be disabled at php.ini',
|
||||
),
|
||||
'phpSmtp' => array(
|
||||
'name' => 'PHP mail SMTP',
|
||||
'mandatory' => false,
|
||||
'condition' => strlen(ini_get('SMTP')) > 0,
|
||||
'by' => 'Email sending',
|
||||
'memo' => 'PHP mail SMTP server required',
|
||||
),
|
||||
);
|
||||
|
||||
// OPcache check
|
||||
if (!version_compare(phpversion(), '5.5', '>=')) {
|
||||
$requirements[] = array(
|
||||
'name' => 'APC extension',
|
||||
'mandatory' => false,
|
||||
'condition' => extension_loaded('apc'),
|
||||
'by' => '<a href="http://www.yiiframework.com/doc-2.0/yii-caching-apccache.html">ApcCache</a>',
|
||||
);
|
||||
}
|
||||
|
||||
$requirementsChecker->checkYii()->check($requirements)->render();
|
0
runtime/temp.txt
Normal file
0
runtime/temp.txt
Normal file
6
tests/_bootstrap.php
Normal file
6
tests/_bootstrap.php
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
define('YII_ENV', 'test');
|
||||
defined('YII_DEBUG') or define('YII_DEBUG', true);
|
||||
|
||||
require_once __DIR__ . '/../vendor/yiisoft/yii2/Yii.php';
|
||||
require __DIR__ .'/../vendor/autoload.php';
|
1
tests/_data/.gitkeep
Normal file
1
tests/_data/.gitkeep
Normal file
|
@ -0,0 +1 @@
|
|||
|
2
tests/_output/.gitignore
vendored
Normal file
2
tests/_output/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
*
|
||||
!.gitignore
|
26
tests/_support/AcceptanceTester.php
Normal file
26
tests/_support/AcceptanceTester.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
|
||||
/**
|
||||
* Inherited Methods
|
||||
* @method void wantToTest($text)
|
||||
* @method void wantTo($text)
|
||||
* @method void execute($callable)
|
||||
* @method void expectTo($prediction)
|
||||
* @method void expect($prediction)
|
||||
* @method void amGoingTo($argumentation)
|
||||
* @method void am($role)
|
||||
* @method void lookForwardTo($achieveValue)
|
||||
* @method void comment($description)
|
||||
* @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
|
||||
*
|
||||
* @SuppressWarnings(PHPMD)
|
||||
*/
|
||||
class AcceptanceTester extends \Codeception\Actor
|
||||
{
|
||||
use _generated\AcceptanceTesterActions;
|
||||
|
||||
/**
|
||||
* Define custom actions here
|
||||
*/
|
||||
}
|
23
tests/_support/FunctionalTester.php
Normal file
23
tests/_support/FunctionalTester.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
|
||||
|
||||
/**
|
||||
* Inherited Methods
|
||||
* @method void wantToTest($text)
|
||||
* @method void wantTo($text)
|
||||
* @method void execute($callable)
|
||||
* @method void expectTo($prediction)
|
||||
* @method void expect($prediction)
|
||||
* @method void amGoingTo($argumentation)
|
||||
* @method void am($role)
|
||||
* @method void lookForwardTo($achieveValue)
|
||||
* @method void comment($description)
|
||||
* @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
|
||||
*
|
||||
* @SuppressWarnings(PHPMD)
|
||||
*/
|
||||
class FunctionalTester extends \Codeception\Actor
|
||||
{
|
||||
use _generated\FunctionalTesterActions;
|
||||
|
||||
}
|
26
tests/_support/UnitTester.php
Normal file
26
tests/_support/UnitTester.php
Normal file
|
@ -0,0 +1,26 @@
|
|||
<?php
|
||||
|
||||
|
||||
/**
|
||||
* Inherited Methods
|
||||
* @method void wantToTest($text)
|
||||
* @method void wantTo($text)
|
||||
* @method void execute($callable)
|
||||
* @method void expectTo($prediction)
|
||||
* @method void expect($prediction)
|
||||
* @method void amGoingTo($argumentation)
|
||||
* @method void am($role)
|
||||
* @method void lookForwardTo($achieveValue)
|
||||
* @method void comment($description)
|
||||
* @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
|
||||
*
|
||||
* @SuppressWarnings(PHPMD)
|
||||
*/
|
||||
class UnitTester extends \Codeception\Actor
|
||||
{
|
||||
use _generated\UnitTesterActions;
|
||||
|
||||
/**
|
||||
* Define custom actions here
|
||||
*/
|
||||
}
|
10
tests/acceptance.suite.yml.example
Normal file
10
tests/acceptance.suite.yml.example
Normal file
|
@ -0,0 +1,10 @@
|
|||
class_name: AcceptanceTester
|
||||
modules:
|
||||
enabled:
|
||||
- WebDriver:
|
||||
url: http://127.0.0.1:8080/
|
||||
browser: firefox
|
||||
- Yii2:
|
||||
part: orm
|
||||
entryScript: index-test.php
|
||||
cleanup: false
|
12
tests/acceptance/AboutCest.php
Normal file
12
tests/acceptance/AboutCest.php
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?php
|
||||
|
||||
use yii\helpers\Url;
|
||||
|
||||
class AboutCest
|
||||
{
|
||||
public function ensureThatAboutWorks(AcceptanceTester $I)
|
||||
{
|
||||
$I->amOnPage(Url::toRoute('/site/about'));
|
||||
$I->see('About', 'h1');
|
||||
}
|
||||
}
|
34
tests/acceptance/ContactCest.php
Normal file
34
tests/acceptance/ContactCest.php
Normal file
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
use yii\helpers\Url;
|
||||
|
||||
class ContactCest
|
||||
{
|
||||
public function _before(\AcceptanceTester $I)
|
||||
{
|
||||
$I->amOnPage(Url::toRoute('/site/contact'));
|
||||
}
|
||||
|
||||
public function contactPageWorks(AcceptanceTester $I)
|
||||
{
|
||||
$I->wantTo('ensure that contact page works');
|
||||
$I->see('Contact', 'h1');
|
||||
}
|
||||
|
||||
public function contactFormCanBeSubmitted(AcceptanceTester $I)
|
||||
{
|
||||
$I->amGoingTo('submit contact form with correct data');
|
||||
$I->fillField('#contactform-name', 'tester');
|
||||
$I->fillField('#contactform-email', 'tester@example.com');
|
||||
$I->fillField('#contactform-subject', 'test subject');
|
||||
$I->fillField('#contactform-body', 'test content');
|
||||
$I->fillField('#contactform-verifycode', 'testme');
|
||||
|
||||
$I->click('contact-button');
|
||||
|
||||
$I->wait(2); // wait for button to be clicked
|
||||
|
||||
$I->dontSeeElement('#contact-form');
|
||||
$I->see('Thank you for contacting us. We will respond to you as soon as possible.');
|
||||
}
|
||||
}
|
18
tests/acceptance/HomeCest.php
Normal file
18
tests/acceptance/HomeCest.php
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?php
|
||||
|
||||
use yii\helpers\Url;
|
||||
|
||||
class HomeCest
|
||||
{
|
||||
public function ensureThatHomePageWorks(AcceptanceTester $I)
|
||||
{
|
||||
$I->amOnPage(Url::toRoute('/site/index'));
|
||||
$I->see('My Company');
|
||||
|
||||
$I->seeLink('About');
|
||||
$I->click('About');
|
||||
$I->wait(2); // wait for page to be opened
|
||||
|
||||
$I->see('This is the About page.');
|
||||
}
|
||||
}
|
21
tests/acceptance/LoginCest.php
Normal file
21
tests/acceptance/LoginCest.php
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?php
|
||||
|
||||
use yii\helpers\Url;
|
||||
|
||||
class LoginCest
|
||||
{
|
||||
public function ensureThatLoginWorks(AcceptanceTester $I)
|
||||
{
|
||||
$I->amOnPage(Url::toRoute('/site/login'));
|
||||
$I->see('Login', 'h1');
|
||||
|
||||
$I->amGoingTo('try to login with correct credentials');
|
||||
$I->fillField('input[name="LoginForm[username]"]', 'admin');
|
||||
$I->fillField('input[name="LoginForm[password]"]', 'admin');
|
||||
$I->click('login-button');
|
||||
$I->wait(2); // wait for button to be clicked
|
||||
|
||||
$I->expectTo('see user info');
|
||||
$I->see('Logout');
|
||||
}
|
||||
}
|
1
tests/acceptance/_bootstrap.php
Normal file
1
tests/acceptance/_bootstrap.php
Normal file
|
@ -0,0 +1 @@
|
|||
<?php
|
29
tests/bin/yii
Normal file
29
tests/bin/yii
Normal file
|
@ -0,0 +1,29 @@
|
|||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* Yii console bootstrap file.
|
||||
*
|
||||
* @link http://www.yiiframework.com/
|
||||
* @copyright Copyright (c) 2008 Yii Software LLC
|
||||
* @license http://www.yiiframework.com/license/
|
||||
*/
|
||||
|
||||
defined('YII_DEBUG') or define('YII_DEBUG', true);
|
||||
defined('YII_ENV') or define('YII_ENV', 'test');
|
||||
|
||||
require __DIR__ . '/../../vendor/autoload.php';
|
||||
require __DIR__ . '/../../vendor/yiisoft/yii2/Yii.php';
|
||||
|
||||
$config = yii\helpers\ArrayHelper::merge(
|
||||
require __DIR__ . '/../../config/console.php',
|
||||
[
|
||||
'components' => [
|
||||
'db' => require __DIR__ . '/../../config/test_db.php'
|
||||
]
|
||||
]
|
||||
);
|
||||
|
||||
|
||||
$application = new yii\console\Application($config);
|
||||
$exitCode = $application->run();
|
||||
exit($exitCode);
|
20
tests/bin/yii.bat
Normal file
20
tests/bin/yii.bat
Normal file
|
@ -0,0 +1,20 @@
|
|||
@echo off
|
||||
|
||||
rem -------------------------------------------------------------
|
||||
rem Yii command line bootstrap script for Windows.
|
||||
rem
|
||||
rem @author Qiang Xue <qiang.xue@gmail.com>
|
||||
rem @link http://www.yiiframework.com/
|
||||
rem @copyright Copyright (c) 2008 Yii Software LLC
|
||||
rem @license http://www.yiiframework.com/license/
|
||||
rem -------------------------------------------------------------
|
||||
|
||||
@setlocal
|
||||
|
||||
set YII_PATH=%~dp0
|
||||
|
||||
if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe
|
||||
|
||||
"%PHP_COMMAND%" "%YII_PATH%yii" %*
|
||||
|
||||
@endlocal
|
13
tests/functional.suite.yml
Normal file
13
tests/functional.suite.yml
Normal file
|
@ -0,0 +1,13 @@
|
|||
# Codeception Test Suite Configuration
|
||||
|
||||
# suite for functional (integration) tests.
|
||||
# emulate web requests and make application process them.
|
||||
# (tip: better to use with frameworks).
|
||||
|
||||
# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES.
|
||||
#basic/web/index.php
|
||||
class_name: FunctionalTester
|
||||
modules:
|
||||
enabled:
|
||||
- Filesystem
|
||||
- Yii2
|
57
tests/functional/ContactFormCest.php
Normal file
57
tests/functional/ContactFormCest.php
Normal file
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
class ContactFormCest
|
||||
{
|
||||
public function _before(\FunctionalTester $I)
|
||||
{
|
||||
$I->amOnPage(['site/contact']);
|
||||
}
|
||||
|
||||
public function openContactPage(\FunctionalTester $I)
|
||||
{
|
||||
$I->see('Contact', 'h1');
|
||||
}
|
||||
|
||||
public function submitEmptyForm(\FunctionalTester $I)
|
||||
{
|
||||
$I->submitForm('#contact-form', []);
|
||||
$I->expectTo('see validations errors');
|
||||
$I->see('Contact', 'h1');
|
||||
$I->see('Name cannot be blank');
|
||||
$I->see('Email cannot be blank');
|
||||
$I->see('Subject cannot be blank');
|
||||
$I->see('Body cannot be blank');
|
||||
$I->see('The verification code is incorrect');
|
||||
}
|
||||
|
||||
public function submitFormWithIncorrectEmail(\FunctionalTester $I)
|
||||
{
|
||||
$I->submitForm('#contact-form', [
|
||||
'ContactForm[name]' => 'tester',
|
||||
'ContactForm[email]' => 'tester.email',
|
||||
'ContactForm[subject]' => 'test subject',
|
||||
'ContactForm[body]' => 'test content',
|
||||
'ContactForm[verifyCode]' => 'testme',
|
||||
]);
|
||||
$I->expectTo('see that email address is wrong');
|
||||
$I->dontSee('Name cannot be blank', '.help-inline');
|
||||
$I->see('Email is not a valid email address.');
|
||||
$I->dontSee('Subject cannot be blank', '.help-inline');
|
||||
$I->dontSee('Body cannot be blank', '.help-inline');
|
||||
$I->dontSee('The verification code is incorrect', '.help-inline');
|
||||
}
|
||||
|
||||
public function submitFormSuccessfully(\FunctionalTester $I)
|
||||
{
|
||||
$I->submitForm('#contact-form', [
|
||||
'ContactForm[name]' => 'tester',
|
||||
'ContactForm[email]' => 'tester@example.com',
|
||||
'ContactForm[subject]' => 'test subject',
|
||||
'ContactForm[body]' => 'test content',
|
||||
'ContactForm[verifyCode]' => 'testme',
|
||||
]);
|
||||
$I->seeEmailIsSent();
|
||||
$I->dontSeeElement('#contact-form');
|
||||
$I->see('Thank you for contacting us. We will respond to you as soon as possible.');
|
||||
}
|
||||
}
|
59
tests/functional/LoginFormCest.php
Normal file
59
tests/functional/LoginFormCest.php
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?php
|
||||
|
||||
class LoginFormCest
|
||||
{
|
||||
public function _before(\FunctionalTester $I)
|
||||
{
|
||||
$I->amOnRoute('site/login');
|
||||
}
|
||||
|
||||
public function openLoginPage(\FunctionalTester $I)
|
||||
{
|
||||
$I->see('Login', 'h1');
|
||||
|
||||
}
|
||||
|
||||
// demonstrates `amLoggedInAs` method
|
||||
public function internalLoginById(\FunctionalTester $I)
|
||||
{
|
||||
$I->amLoggedInAs(100);
|
||||
$I->amOnPage('/');
|
||||
$I->see('Logout (admin)');
|
||||
}
|
||||
|
||||
// demonstrates `amLoggedInAs` method
|
||||
public function internalLoginByInstance(\FunctionalTester $I)
|
||||
{
|
||||
$I->amLoggedInAs(\app\models\User::findByUsername('admin'));
|
||||
$I->amOnPage('/');
|
||||
$I->see('Logout (admin)');
|
||||
}
|
||||
|
||||
public function loginWithEmptyCredentials(\FunctionalTester $I)
|
||||
{
|
||||
$I->submitForm('#login-form', []);
|
||||
$I->expectTo('see validations errors');
|
||||
$I->see('Username cannot be blank.');
|
||||
$I->see('Password cannot be blank.');
|
||||
}
|
||||
|
||||
public function loginWithWrongCredentials(\FunctionalTester $I)
|
||||
{
|
||||
$I->submitForm('#login-form', [
|
||||
'LoginForm[username]' => 'admin',
|
||||
'LoginForm[password]' => 'wrong',
|
||||
]);
|
||||
$I->expectTo('see validations errors');
|
||||
$I->see('Incorrect username or password.');
|
||||
}
|
||||
|
||||
public function loginSuccessfully(\FunctionalTester $I)
|
||||
{
|
||||
$I->submitForm('#login-form', [
|
||||
'LoginForm[username]' => 'admin',
|
||||
'LoginForm[password]' => 'admin',
|
||||
]);
|
||||
$I->see('Logout (admin)');
|
||||
$I->dontSeeElement('form#login-form');
|
||||
}
|
||||
}
|
1
tests/functional/_bootstrap.php
Normal file
1
tests/functional/_bootstrap.php
Normal file
|
@ -0,0 +1 @@
|
|||
<?php
|
11
tests/unit.suite.yml
Normal file
11
tests/unit.suite.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Codeception Test Suite Configuration
|
||||
|
||||
# suite for unit (internal) tests.
|
||||
# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES.
|
||||
|
||||
class_name: UnitTester
|
||||
modules:
|
||||
enabled:
|
||||
- Asserts
|
||||
- Yii2:
|
||||
part: [orm, email]
|
3
tests/unit/_bootstrap.php
Normal file
3
tests/unit/_bootstrap.php
Normal file
|
@ -0,0 +1,3 @@
|
|||
<?php
|
||||
|
||||
// add unit testing specific bootstrap code here
|
43
tests/unit/models/ContactFormTest.php
Normal file
43
tests/unit/models/ContactFormTest.php
Normal file
|
@ -0,0 +1,43 @@
|
|||
<?php
|
||||
|
||||
namespace tests\models;
|
||||
|
||||
class ContactFormTest extends \Codeception\Test\Unit
|
||||
{
|
||||
private $model;
|
||||
/**
|
||||
* @var \UnitTester
|
||||
*/
|
||||
public $tester;
|
||||
|
||||
public function testEmailIsSentOnContact()
|
||||
{
|
||||
/** @var ContactForm $model */
|
||||
$this->model = $this->getMockBuilder('app\models\ContactForm')
|
||||
->setMethods(['validate'])
|
||||
->getMock();
|
||||
|
||||
$this->model->expects($this->once())
|
||||
->method('validate')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$this->model->attributes = [
|
||||
'name' => 'Tester',
|
||||
'email' => 'tester@example.com',
|
||||
'subject' => 'very important letter subject',
|
||||
'body' => 'body of current message',
|
||||
];
|
||||
|
||||
expect_that($this->model->contact('admin@example.com'));
|
||||
|
||||
// using Yii2 module actions to check email was sent
|
||||
$this->tester->seeEmailIsSent();
|
||||
|
||||
$emailMessage = $this->tester->grabLastSentEmail();
|
||||
expect('valid email is sent', $emailMessage)->isInstanceOf('yii\mail\MessageInterface');
|
||||
expect($emailMessage->getTo())->hasKey('admin@example.com');
|
||||
expect($emailMessage->getFrom())->hasKey('tester@example.com');
|
||||
expect($emailMessage->getSubject())->equals('very important letter subject');
|
||||
expect($emailMessage->toString())->contains('body of current message');
|
||||
}
|
||||
}
|
51
tests/unit/models/LoginFormTest.php
Normal file
51
tests/unit/models/LoginFormTest.php
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?php
|
||||
|
||||
namespace tests\models;
|
||||
|
||||
use app\models\LoginForm;
|
||||
|
||||
class LoginFormTest extends \Codeception\Test\Unit
|
||||
{
|
||||
private $model;
|
||||
|
||||
protected function _after()
|
||||
{
|
||||
\Yii::$app->user->logout();
|
||||
}
|
||||
|
||||
public function testLoginNoUser()
|
||||
{
|
||||
$this->model = new LoginForm([
|
||||
'username' => 'not_existing_username',
|
||||
'password' => 'not_existing_password',
|
||||
]);
|
||||
|
||||
expect_not($this->model->login());
|
||||
expect_that(\Yii::$app->user->isGuest);
|
||||
}
|
||||
|
||||
public function testLoginWrongPassword()
|
||||
{
|
||||
$this->model = new LoginForm([
|
||||
'username' => 'demo',
|
||||
'password' => 'wrong_password',
|
||||
]);
|
||||
|
||||
expect_not($this->model->login());
|
||||
expect_that(\Yii::$app->user->isGuest);
|
||||
expect($this->model->errors)->hasKey('password');
|
||||
}
|
||||
|
||||
public function testLoginCorrect()
|
||||
{
|
||||
$this->model = new LoginForm([
|
||||
'username' => 'demo',
|
||||
'password' => 'demo',
|
||||
]);
|
||||
|
||||
expect_that($this->model->login());
|
||||
expect_not(\Yii::$app->user->isGuest);
|
||||
expect($this->model->errors)->hasntKey('password');
|
||||
}
|
||||
|
||||
}
|
44
tests/unit/models/UserTest.php
Normal file
44
tests/unit/models/UserTest.php
Normal file
|
@ -0,0 +1,44 @@
|
|||
<?php
|
||||
|
||||
namespace tests\models;
|
||||
|
||||
use app\models\User;
|
||||
|
||||
class UserTest extends \Codeception\Test\Unit
|
||||
{
|
||||
public function testFindUserById()
|
||||
{
|
||||
expect_that($user = User::findIdentity(100));
|
||||
expect($user->username)->equals('admin');
|
||||
|
||||
expect_not(User::findIdentity(999));
|
||||
}
|
||||
|
||||
public function testFindUserByAccessToken()
|
||||
{
|
||||
expect_that($user = User::findIdentityByAccessToken('100-token'));
|
||||
expect($user->username)->equals('admin');
|
||||
|
||||
expect_not(User::findIdentityByAccessToken('non-existing'));
|
||||
}
|
||||
|
||||
public function testFindUserByUsername()
|
||||
{
|
||||
expect_that($user = User::findByUsername('admin'));
|
||||
expect_not(User::findByUsername('not-admin'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @depends testFindUserByUsername
|
||||
*/
|
||||
public function testValidateUser($user)
|
||||
{
|
||||
$user = User::findByUsername('admin');
|
||||
expect_that($user->validateAuthKey('test100key'));
|
||||
expect_not($user->validateAuthKey('test102key'));
|
||||
|
||||
expect_that($user->validatePassword('admin'));
|
||||
expect_not($user->validatePassword('123456'));
|
||||
}
|
||||
|
||||
}
|
2
vagrant/config/.gitignore
vendored
Normal file
2
vagrant/config/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
# local configuration
|
||||
vagrant-local.yml
|
22
vagrant/config/vagrant-local.example.yml
Normal file
22
vagrant/config/vagrant-local.example.yml
Normal file
|
@ -0,0 +1,22 @@
|
|||
# Your personal GitHub token
|
||||
github_token: <your-personal-github-token>
|
||||
# Read more: https://github.com/blog/1509-personal-api-tokens
|
||||
# You can generate it here: https://github.com/settings/tokens
|
||||
|
||||
# Guest OS timezone
|
||||
timezone: Europe/London
|
||||
|
||||
# Are we need check box updates for every 'vagrant up'?
|
||||
box_check_update: false
|
||||
|
||||
# Virtual machine name
|
||||
machine_name: yii2basic
|
||||
|
||||
# Virtual machine IP
|
||||
ip: 192.168.83.137
|
||||
|
||||
# Virtual machine CPU cores number
|
||||
cpus: 1
|
||||
|
||||
# Virtual machine RAM
|
||||
memory: 1024
|
38
vagrant/nginx/app.conf
Normal file
38
vagrant/nginx/app.conf
Normal file
|
@ -0,0 +1,38 @@
|
|||
server {
|
||||
charset utf-8;
|
||||
client_max_body_size 128M;
|
||||
sendfile off;
|
||||
|
||||
listen 80; ## listen for ipv4
|
||||
#listen [::]:80 default_server ipv6only=on; ## listen for ipv6
|
||||
|
||||
server_name yii2basic.dev;
|
||||
root /app/web/;
|
||||
index index.php;
|
||||
|
||||
access_log /app/vagrant/nginx/log/yii2basic.access.log;
|
||||
error_log /app/vagrant/nginx/log/yii2basic.error.log;
|
||||
|
||||
location / {
|
||||
# Redirect everything that isn't a real file to index.php
|
||||
try_files $uri $uri/ /index.php$is_args$args;
|
||||
}
|
||||
|
||||
# uncomment to avoid processing of calls to non-existing static files by Yii
|
||||
#location ~ \.(js|css|png|jpg|gif|swf|ico|pdf|mov|fla|zip|rar)$ {
|
||||
# try_files $uri =404;
|
||||
#}
|
||||
#error_page 404 /404.html;
|
||||
|
||||
location ~ \.php$ {
|
||||
include fastcgi_params;
|
||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||
#fastcgi_pass 127.0.0.1:9000;
|
||||
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
|
||||
try_files $uri =404;
|
||||
}
|
||||
|
||||
location ~ /\.(ht|svn|git) {
|
||||
deny all;
|
||||
}
|
||||
}
|
3
vagrant/nginx/log/.gitignore
vendored
Normal file
3
vagrant/nginx/log/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
#nginx logs
|
||||
yii2basic.access.log
|
||||
yii2basic.error.log
|
18
vagrant/provision/always-as-root.sh
Normal file
18
vagrant/provision/always-as-root.sh
Normal file
|
@ -0,0 +1,18 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
#== Bash helpers ==
|
||||
|
||||
function info {
|
||||
echo " "
|
||||
echo "--> $1"
|
||||
echo " "
|
||||
}
|
||||
|
||||
#== Provision script ==
|
||||
|
||||
info "Provision-script user: `whoami`"
|
||||
|
||||
info "Restart web-stack"
|
||||
service php7.0-fpm restart
|
||||
service nginx restart
|
||||
service mysql restart
|
71
vagrant/provision/once-as-root.sh
Normal file
71
vagrant/provision/once-as-root.sh
Normal file
|
@ -0,0 +1,71 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
#== Import script args ==
|
||||
|
||||
timezone=$(echo "$1")
|
||||
|
||||
#== Bash helpers ==
|
||||
|
||||
function info {
|
||||
echo " "
|
||||
echo "--> $1"
|
||||
echo " "
|
||||
}
|
||||
|
||||
#== Provision script ==
|
||||
|
||||
info "Provision-script user: `whoami`"
|
||||
|
||||
export DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
info "Configure timezone"
|
||||
timedatectl set-timezone ${timezone} --no-ask-password
|
||||
|
||||
info "Prepare root password for MySQL"
|
||||
debconf-set-selections <<< "mariadb-server-10.0 mysql-server/root_password password \"''\""
|
||||
debconf-set-selections <<< "mariadb-server-10.0 mysql-server/root_password_again password \"''\""
|
||||
echo "Done!"
|
||||
|
||||
info "Update OS software"
|
||||
apt-get update
|
||||
apt-get upgrade -y
|
||||
|
||||
info "Install additional software"
|
||||
apt-get install -y php7.0-curl php7.0-cli php7.0-intl php7.0-mysqlnd php7.0-gd php7.0-fpm php7.0-mbstring php7.0-xml unzip nginx mariadb-server-10.0 php.xdebug
|
||||
|
||||
info "Configure MySQL"
|
||||
sed -i "s/.*bind-address.*/bind-address = 0.0.0.0/" /etc/mysql/mariadb.conf.d/50-server.cnf
|
||||
mysql -uroot <<< "CREATE USER 'root'@'%' IDENTIFIED BY ''"
|
||||
mysql -uroot <<< "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%'"
|
||||
mysql -uroot <<< "DROP USER 'root'@'localhost'"
|
||||
mysql -uroot <<< "FLUSH PRIVILEGES"
|
||||
echo "Done!"
|
||||
|
||||
info "Configure PHP-FPM"
|
||||
sed -i 's/user = www-data/user = vagrant/g' /etc/php/7.0/fpm/pool.d/www.conf
|
||||
sed -i 's/group = www-data/group = vagrant/g' /etc/php/7.0/fpm/pool.d/www.conf
|
||||
sed -i 's/owner = www-data/owner = vagrant/g' /etc/php/7.0/fpm/pool.d/www.conf
|
||||
cat << EOF > /etc/php/7.0/mods-available/xdebug.ini
|
||||
zend_extension=xdebug.so
|
||||
xdebug.remote_enable=1
|
||||
xdebug.remote_connect_back=1
|
||||
xdebug.remote_port=9000
|
||||
xdebug.remote_autostart=1
|
||||
EOF
|
||||
echo "Done!"
|
||||
|
||||
info "Configure NGINX"
|
||||
sed -i 's/user www-data/user vagrant/g' /etc/nginx/nginx.conf
|
||||
echo "Done!"
|
||||
|
||||
info "Enabling site configuration"
|
||||
ln -s /app/vagrant/nginx/app.conf /etc/nginx/sites-enabled/app.conf
|
||||
echo "Done!"
|
||||
|
||||
info "Initailize databases for MySQL"
|
||||
mysql -uroot <<< "CREATE DATABASE yii2basic"
|
||||
mysql -uroot <<< "CREATE DATABASE yii2basic_test"
|
||||
echo "Done!"
|
||||
|
||||
info "Install composer"
|
||||
curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
|
31
vagrant/provision/once-as-vagrant.sh
Normal file
31
vagrant/provision/once-as-vagrant.sh
Normal file
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
#== Import script args ==
|
||||
|
||||
github_token=$(echo "$1")
|
||||
|
||||
#== Bash helpers ==
|
||||
|
||||
function info {
|
||||
echo " "
|
||||
echo "--> $1"
|
||||
echo " "
|
||||
}
|
||||
|
||||
#== Provision script ==
|
||||
|
||||
info "Provision-script user: `whoami`"
|
||||
|
||||
info "Configure composer"
|
||||
composer config --global github-oauth.github.com ${github_token}
|
||||
echo "Done!"
|
||||
|
||||
info "Install project dependencies"
|
||||
cd /app
|
||||
composer --no-progress --prefer-dist install
|
||||
|
||||
info "Create bash-alias 'app' for vagrant user"
|
||||
echo 'alias app="cd /app"' | tee /home/vagrant/.bash_aliases
|
||||
|
||||
info "Enabling colorized prompt for guest console"
|
||||
sed -i "s/#force_color_prompt=yes/force_color_prompt=yes/" /home/vagrant/.bashrc
|
33
vendor/2amigos/yii2-arrayquery-component/.php_cs
vendored
Normal file
33
vendor/2amigos/yii2-arrayquery-component/.php_cs
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
<?php
|
||||
$finder = PhpCsFixer\Finder::create()
|
||||
->in(__DIR__)
|
||||
;
|
||||
|
||||
return PhpCsFixer\Config::create()
|
||||
->setRiskyAllowed(true)
|
||||
->setRules(array(
|
||||
'@PSR2' => true,
|
||||
'array_syntax' => array('syntax' => 'short'),
|
||||
'combine_consecutive_unsets' => true,
|
||||
// 'header_comment' => array('header' => $header),
|
||||
'no_extra_consecutive_blank_lines' => array(
|
||||
'break',
|
||||
'continue',
|
||||
'extra',
|
||||
'return',
|
||||
'throw',
|
||||
'use',
|
||||
'parenthesis_brace_block',
|
||||
'square_brace_block',
|
||||
'curly_brace_block'
|
||||
),
|
||||
'no_useless_else' => true,
|
||||
'no_useless_return' => true,
|
||||
'ordered_class_elements' => true,
|
||||
'ordered_imports' => true,
|
||||
'phpdoc_add_missing_param_annotation' => true,
|
||||
'psr4' => true,
|
||||
'strict_comparison' => true,
|
||||
))
|
||||
->setFinder($finder)
|
||||
;
|
16
vendor/2amigos/yii2-arrayquery-component/CHANGELOG.md
vendored
Normal file
16
vendor/2amigos/yii2-arrayquery-component/CHANGELOG.md
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
# Changelog
|
||||
|
||||
## 1.0.1 - 2015-03-04
|
||||
|
||||
## Changed
|
||||
- Added CONTRIBUTING.md file
|
||||
|
||||
## 1.0.0 - 2015-03-04
|
||||
|
||||
## Changed
|
||||
- Refactored extension to follow new 2amigOS! extension standards based on
|
||||
[yii2-extension-skeleton](https://github.com/2amigos/yii2-extension-skeleton)
|
||||
- Updated tests
|
||||
|
||||
## Fixed
|
||||
- Fixed bug when checking "or" conditions
|
32
vendor/2amigos/yii2-arrayquery-component/CONTRIBUTING.md
vendored
Normal file
32
vendor/2amigos/yii2-arrayquery-component/CONTRIBUTING.md
vendored
Normal file
|
@ -0,0 +1,32 @@
|
|||
# Contributing
|
||||
|
||||
Contributions are **welcome** and will be fully **credited**.
|
||||
|
||||
We accept contributions via Pull Requests on [Github](https://github.com/2amigos/yii2-arrayquery-component).
|
||||
|
||||
|
||||
## Pull Requests
|
||||
|
||||
- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](http://pear.php.net/package/PHP_CodeSniffer).
|
||||
|
||||
- **Add tests!** - Your patch won't be accepted if it doesn't have tests.
|
||||
|
||||
- **Document any change in behaviour** - Make sure the `README.md` and any other relevant documentation are kept up-to-date.
|
||||
|
||||
- **Consider our release cycle** - We try to follow [SemVer v2.0.0](http://semver.org/). Randomly breaking public APIs is not an option.
|
||||
|
||||
- **Create feature branches** - Don't ask us to pull from your master branch.
|
||||
|
||||
- **One pull request per feature** - If you want to do more than one thing, send multiple pull requests.
|
||||
|
||||
- **Send coherent history** - Make sure each individual commit in your pull request is meaningful. If you had to make multiple intermediate commits while developing, please squash them before submitting.
|
||||
|
||||
|
||||
## Running Tests
|
||||
|
||||
``` bash
|
||||
$ phpunit
|
||||
```
|
||||
|
||||
|
||||
**Happy coding**!
|
28
vendor/2amigos/yii2-arrayquery-component/LICENSE.md
vendored
Normal file
28
vendor/2amigos/yii2-arrayquery-component/LICENSE.md
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
# The BSD License (BSD)
|
||||
|
||||
Copyright (c) 2013-2015, 2amigOS! Consulting Group LLC.
|
||||
|
||||
> 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 2amigOS! Consulting Group, 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 HOLDER 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.
|
79
vendor/2amigos/yii2-arrayquery-component/README.md
vendored
Normal file
79
vendor/2amigos/yii2-arrayquery-component/README.md
vendored
Normal file
|
@ -0,0 +1,79 @@
|
|||
ArrayQuery Component for Yii2
|
||||
=============================
|
||||
|
||||
[](https://github.com/2amigos/yii2-arrayquery-component/tags)
|
||||
[](LICENSE.md)
|
||||
[](https://travis-ci.org/2amigos/yii2-arrayquery-component)
|
||||
[](https://scrutinizer-ci.com/g/2amigos/yii2-arrayquery-component/code-structure)
|
||||
[](https://scrutinizer-ci.com/g/2amigos/yii2-arrayquery-component)
|
||||
[](https://packagist.org/packages/2amigos/yii2-arrayquery-component)
|
||||
|
||||
Allows searching/filtering of an array. This component is very useful when displaying array data in GridViews with an
|
||||
ArrayDataProvider.
|
||||
|
||||
Installation
|
||||
------------
|
||||
The preferred way to install this extension is through [composer](http://getcomposer.org/download/).
|
||||
|
||||
Either run
|
||||
|
||||
```
|
||||
php composer.phar require "2amigos/yii2-arrayquery-component" "*"
|
||||
```
|
||||
or add
|
||||
|
||||
```
|
||||
"2amigos/yii2-arrayquery-component" : "*"
|
||||
```
|
||||
|
||||
to the require section of your application's `composer.json` file.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
```
|
||||
\\ $models is the array elements to used with ArrayDataProvider
|
||||
|
||||
$query = new ArrayQuery($models);
|
||||
|
||||
$models = $query
|
||||
->addCondition('name', '~2amigos')
|
||||
->addCondition('name', 'cebe/yii2-gravatar', 'or')
|
||||
->find();
|
||||
|
||||
$dataProvider = new ArrayDataProvider([
|
||||
'allModels' => $models,
|
||||
'pagination' => [
|
||||
'pageSize' => 50,
|
||||
],
|
||||
'sort' => [
|
||||
'attributes' => [], // to be specified
|
||||
],
|
||||
]);
|
||||
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
``` bash
|
||||
$ phpunit
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
Please see [CONTRIBUTING](CONTRIBUTING.md) for details.
|
||||
|
||||
## Credits
|
||||
|
||||
- [Antonio Ramirez](https://github.com/tonydspaniard)
|
||||
- [All Contributors](../../contributors)
|
||||
|
||||
## License
|
||||
|
||||
The BSD License (BSD). Please see [License File](LICENSE.md) for more information.
|
||||
|
||||
|
||||
> [](http://www.2amigos.us)
|
||||
|
||||
<i>Custom Software | Web & Mobile Software Development</i>
|
||||
[www.2amigos.us](http://www.2amigos.us)
|
46
vendor/2amigos/yii2-arrayquery-component/composer.json
vendored
Normal file
46
vendor/2amigos/yii2-arrayquery-component/composer.json
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
{
|
||||
"name": "2amigos/yii2-arrayquery-component",
|
||||
"description": "Yii2 component that allows for searching/filtering the elements of an array.",
|
||||
"type": "yii2-extension",
|
||||
"keywords": [
|
||||
"2amigos",
|
||||
"yii",
|
||||
"yii2",
|
||||
"yii 2",
|
||||
"extension",
|
||||
"component",
|
||||
"arrayquery"
|
||||
],
|
||||
"homepage": "http://yiiwheels.com/extension/arrayquery-component",
|
||||
"license": "BSD-3-Clause",
|
||||
"authors": [
|
||||
{
|
||||
"name": "2amigOS! Consulting Group",
|
||||
"email": "hola@2amigos.us",
|
||||
"homepage": "http://2amigos.us",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/dosamigos/yii2-arrayquery-component/issues",
|
||||
"source": "https://github.com/dosamigos/yii2-arrayquery-component"
|
||||
},
|
||||
"require": {
|
||||
"yiisoft/yii2": "~2.0.11"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~5.6",
|
||||
"friendsofphp/php-cs-fixer": "^2.0",
|
||||
"scrutinizer/ocular": "~1.1"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"dosamigos\\arrayquery\\": "src"
|
||||
}
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0-dev"
|
||||
}
|
||||
}
|
||||
}
|
208
vendor/2amigos/yii2-arrayquery-component/src/ArrayQuery.php
vendored
Normal file
208
vendor/2amigos/yii2-arrayquery-component/src/ArrayQuery.php
vendored
Normal file
|
@ -0,0 +1,208 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2013-2017 2amigos! Consulting Group LLC
|
||||
* @link http://2amigos.us
|
||||
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
|
||||
*/
|
||||
namespace dosamigos\arrayquery;
|
||||
|
||||
use dosamigos\arrayquery\conditions\Equal;
|
||||
use dosamigos\arrayquery\conditions\GreaterThan;
|
||||
use dosamigos\arrayquery\conditions\GreaterThanOrEqual;
|
||||
use dosamigos\arrayquery\conditions\LessThan;
|
||||
use dosamigos\arrayquery\conditions\LessThanOrEqual;
|
||||
use dosamigos\arrayquery\conditions\Like;
|
||||
use dosamigos\arrayquery\conditions\NotLike;
|
||||
|
||||
/**
|
||||
* ArrayQuery allows to filter an array by apply conditions.
|
||||
*
|
||||
* @author Antonio Ramirez <hola@2amigos.us>
|
||||
* @link http://www.ramirezcobos.com/
|
||||
* @link http://www.2amigos.us/
|
||||
* @package dosamigos\arrayquery
|
||||
*/
|
||||
class ArrayQuery
|
||||
{
|
||||
/**
|
||||
* @var array the data to search, filter.
|
||||
*/
|
||||
private $data;
|
||||
/**
|
||||
* @var array the array tokenized so user can search multidimensional array by key paths -ie `parentkey.child`
|
||||
*/
|
||||
private $tokens;
|
||||
/**
|
||||
* @var array the conditions to apply
|
||||
*/
|
||||
private $conditions = [];
|
||||
|
||||
|
||||
/**
|
||||
* @param array $array
|
||||
*/
|
||||
public function __construct(array $array)
|
||||
{
|
||||
$this->data = $array;
|
||||
foreach ($array as $k => $item) {
|
||||
$this->tokens[$k] = $this->tokenize($item, '', false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a condition to apply the array
|
||||
*
|
||||
* @param string $key the key to search in the array
|
||||
* @param mixed $value the value to search. It supports SQL like operator plus some custom ones:
|
||||
* - `~` or `like` : like `%value%` in SQL
|
||||
* - `n~` or `nlike` : like `NOT LIKE` in SQL
|
||||
* @param string $operator the operator. It can be `and` or `or`. If any of `or` matches it will be added to the
|
||||
* successful results.
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public function addCondition($key, $value, $operator = 'and')
|
||||
{
|
||||
if ($value != null) { // not accepting null values
|
||||
$operation = null;
|
||||
$operator = strcasecmp($operator, 'or') !== 0 ? 'and' : 'or';
|
||||
|
||||
if (preg_match('/^(?:\s*(<>|<=|>=|<|>|=|~|n~|like|nlike))?(.*)$/i', $value, $matches)) {
|
||||
$operation = $matches[1];
|
||||
$value = trim($matches[2]);
|
||||
}
|
||||
|
||||
if (empty($operation) || strlen($operation) > 5) {
|
||||
$operation = '=';
|
||||
}
|
||||
|
||||
switch ($operation) {
|
||||
case '<':
|
||||
$condition = new LessThan($value);
|
||||
break;
|
||||
case '>':
|
||||
$condition = new GreaterThan($value);
|
||||
break;
|
||||
case '<>':
|
||||
$condition = new Equal($value);
|
||||
$condition->reverse();
|
||||
break;
|
||||
case '<=':
|
||||
$condition = new LessThanOrEqual($value);
|
||||
break;
|
||||
case '>=':
|
||||
$condition = new GreaterThanOrEqual($value);
|
||||
break;
|
||||
case '~':
|
||||
case 'like':
|
||||
$condition = new Like($value);
|
||||
break;
|
||||
case 'n~':
|
||||
case 'nlike':
|
||||
$condition = new NotLike($value);
|
||||
break;
|
||||
case '=':
|
||||
default:
|
||||
$condition = new Equal($value);
|
||||
}
|
||||
$this->conditions[$operator][] = ['condition' => $condition, 'key' => $key];
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first matched result.
|
||||
* @return array the first matched result, empty array if none found.
|
||||
*/
|
||||
public function one()
|
||||
{
|
||||
foreach ($this->tokens as $key => $token) {
|
||||
if (!$this->matches($token)) {
|
||||
continue;
|
||||
}
|
||||
return $this->data[$key];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns array of matched results.
|
||||
* @return array the matched results.
|
||||
*/
|
||||
public function find()
|
||||
{
|
||||
if (empty($this->conditions)) {
|
||||
return $this->data;
|
||||
}
|
||||
$results = [];
|
||||
foreach ($this->tokens as $key => $token) {
|
||||
if (!$this->matches($token)) {
|
||||
continue;
|
||||
}
|
||||
$results[$key] = $this->data[$key];
|
||||
}
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tokenizes the array to ease the search in multidimensional arrays.
|
||||
*
|
||||
* @param array $array the array to tokenize
|
||||
* @param string $prefix the key prefix
|
||||
* @param bool $addParent whether to add parent value anyway. False
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function tokenize($array, $prefix = '', $addParent = true)
|
||||
{
|
||||
$paths = [];
|
||||
$px = empty($prefix) ? null : $prefix . ".";
|
||||
foreach ($array as $key => $items) {
|
||||
if (is_array($items)) {
|
||||
$addParent && $paths[$px . $key] = $items;
|
||||
foreach ($this->tokenize($items, $px . $key) as $k => $path) {
|
||||
$paths[$k] = $path;
|
||||
}
|
||||
} elseif (is_object($items)) {
|
||||
$addParent && $paths[$px . $key] = $items;
|
||||
foreach ($this->tokenize(get_object_vars($items), $px . $key) as $k => $path) {
|
||||
$paths[$k] = $path;
|
||||
}
|
||||
} else {
|
||||
$paths[$px . $key] = $items;
|
||||
}
|
||||
}
|
||||
return $paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks data against conditions
|
||||
*
|
||||
* @param mixed $data the data to match against.
|
||||
*
|
||||
* @return bool true if matches condition
|
||||
*/
|
||||
private function matches($data)
|
||||
{
|
||||
$matches = true;
|
||||
$conditions = isset($this->conditions['and']) ? $this->conditions['and'] : [];
|
||||
foreach ($conditions as $condition) {
|
||||
$key = $condition['key'];
|
||||
$condition = $condition['condition'];
|
||||
if (!array_key_exists($key, $data) || !$condition->matches($data[$key])) {
|
||||
$matches = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$conditions = isset($this->conditions['or']) ? $this->conditions['or'] : [];
|
||||
foreach ($conditions as $condition) {
|
||||
$key = $condition['key'];
|
||||
$condition = $condition['condition'];
|
||||
if (array_key_exists($key, $data) && $condition->matches($data[$key])) {
|
||||
$matches = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return $matches;
|
||||
}
|
||||
}
|
77
vendor/2amigos/yii2-arrayquery-component/src/conditions/Condition.php
vendored
Normal file
77
vendor/2amigos/yii2-arrayquery-component/src/conditions/Condition.php
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2013-2017 2amigOS! Consulting Group LLC
|
||||
* @link http://2amigos.us
|
||||
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
|
||||
*/
|
||||
namespace dosamigos\arrayquery\conditions;
|
||||
|
||||
|
||||
/**
|
||||
* Condition abstract base class where all conditions extend from
|
||||
*
|
||||
* @author Antonio Ramirez <hola@2amigos.us>
|
||||
* @link http://www.ramirezcobos.com/
|
||||
* @link http://www.2amigos.us/
|
||||
* @package dosamigos\arrayquery\conditions
|
||||
*/
|
||||
abstract class Condition
|
||||
{
|
||||
/**
|
||||
* @var mixed the value to match against
|
||||
*/
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* @var bool whether to reverse or not
|
||||
*/
|
||||
protected $negate = false;
|
||||
|
||||
/**
|
||||
* @param mixed $value the value to match against
|
||||
*/
|
||||
public function __construct($value)
|
||||
{
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverses the condition
|
||||
* @return $this
|
||||
*/
|
||||
public function reverse()
|
||||
{
|
||||
$this->negate = !$this->negate;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the value passes condition
|
||||
*
|
||||
* @param mixed $data the data to match
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
abstract public function matches($data);
|
||||
|
||||
/**
|
||||
* Checks whether the value and the data are of same type
|
||||
*
|
||||
* @param mixed $value
|
||||
* @param mixed $against
|
||||
*
|
||||
* @return bool true if both are of same type
|
||||
*/
|
||||
protected function checkType($value, $against)
|
||||
{
|
||||
if (is_numeric($value) && is_numeric($against)) {
|
||||
$value = filter_var($value, FILTER_SANITIZE_NUMBER_FLOAT);
|
||||
$against = filter_var($against, FILTER_SANITIZE_NUMBER_FLOAT);
|
||||
}
|
||||
|
||||
if (gettype($value) != gettype($against)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
28
vendor/2amigos/yii2-arrayquery-component/src/conditions/Equal.php
vendored
Normal file
28
vendor/2amigos/yii2-arrayquery-component/src/conditions/Equal.php
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2013-2017 2amigOS! Consulting Group LLC
|
||||
* @link http://2amigos.us
|
||||
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
|
||||
*/
|
||||
namespace dosamigos\arrayquery\conditions;
|
||||
|
||||
|
||||
/**
|
||||
* Equal checks if value is equal to the data searched.
|
||||
*
|
||||
* @author Antonio Ramirez <hola@2amigos.us>
|
||||
* @link http://www.ramirezcobos.com/
|
||||
* @link http://www.2amigos.us/
|
||||
* @package dosamigos\arrayquery\conditions
|
||||
*/
|
||||
class Equal extends Condition
|
||||
{
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function matches($data)
|
||||
{
|
||||
return (($this->checkType($data, $this->value) && strcmp($data, $this->value) === 0) xor $this->negate);
|
||||
}
|
||||
}
|
38
vendor/2amigos/yii2-arrayquery-component/src/conditions/GreaterThan.php
vendored
Normal file
38
vendor/2amigos/yii2-arrayquery-component/src/conditions/GreaterThan.php
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2013-2017 2amigOS! Consulting Group LLC
|
||||
* @link http://2amigos.us
|
||||
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
|
||||
*/
|
||||
namespace dosamigos\arrayquery\conditions;
|
||||
|
||||
/**
|
||||
* GreaterThan checks if value is greater than the data searched.
|
||||
*
|
||||
* @author Antonio Ramirez <hola@2amigos.us>
|
||||
* @link http://www.ramirezcobos.com/
|
||||
* @link http://www.2amigos.us/
|
||||
* @package dosamigos\arrayquery\conditions
|
||||
*/
|
||||
class GreaterThan extends Condition
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns [[LessThan]] condition
|
||||
* @return LessThan
|
||||
*/
|
||||
public function reverse()
|
||||
{
|
||||
return new LessThan($this->value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function matches($data)
|
||||
{
|
||||
return ($this->checkType($data, $this->value) && $data > $this->value);
|
||||
}
|
||||
|
||||
}
|
40
vendor/2amigos/yii2-arrayquery-component/src/conditions/GreaterThanOrEqual.php
vendored
Normal file
40
vendor/2amigos/yii2-arrayquery-component/src/conditions/GreaterThanOrEqual.php
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2013-2017 2amigOS! Consulting Group LLC
|
||||
* @link http://2amigos.us
|
||||
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
|
||||
*/
|
||||
namespace dosamigos\arrayquery\conditions;
|
||||
|
||||
/**
|
||||
* GreaterThanOrEqual checks if value is greater or equal to the data searched.
|
||||
*
|
||||
* @author Antonio Ramirez <hola@2amigos.us>
|
||||
* @link http://www.ramirezcobos.com/
|
||||
* @link http://www.2amigos.us/
|
||||
* @package dosamigos\arrayquery\conditions
|
||||
*/
|
||||
class GreaterThanOrEqual extends Condition
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns [[LessThanOrEqual]] condition
|
||||
* @return LessThanOrEqual
|
||||
*/
|
||||
public function reverse()
|
||||
{
|
||||
return new LessThanOrEqual($this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function matches($data)
|
||||
{
|
||||
$gt = new GreaterThan($this->value);
|
||||
$e = new Equal($this->value);
|
||||
|
||||
return $gt->matches($data) || $e->matches($data);
|
||||
}
|
||||
|
||||
}
|
39
vendor/2amigos/yii2-arrayquery-component/src/conditions/LessThan.php
vendored
Normal file
39
vendor/2amigos/yii2-arrayquery-component/src/conditions/LessThan.php
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2013-2017 2amigOS! Consulting Group LLC
|
||||
* @link http://2amigos.us
|
||||
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
|
||||
*/
|
||||
namespace dosamigos\arrayquery\conditions;
|
||||
|
||||
|
||||
/**
|
||||
* LessThan checks if value is less than to the data searched.
|
||||
*
|
||||
* @author Antonio Ramirez <hola@2amigos.us>
|
||||
* @link http://www.ramirezcobos.com/
|
||||
* @link http://www.2amigos.us/
|
||||
* @package dosamigos\arrayquery\conditions
|
||||
*/
|
||||
class LessThan extends Condition
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns [[GreaterThan]] condition
|
||||
* @return GreaterThan
|
||||
*/
|
||||
public function reverse()
|
||||
{
|
||||
return new GreaterThan($this->value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function matches($data)
|
||||
{
|
||||
return ($this->checkType($data, $this->value) && $data < $this->value);
|
||||
}
|
||||
|
||||
}
|
41
vendor/2amigos/yii2-arrayquery-component/src/conditions/LessThanOrEqual.php
vendored
Normal file
41
vendor/2amigos/yii2-arrayquery-component/src/conditions/LessThanOrEqual.php
vendored
Normal file
|
@ -0,0 +1,41 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2013-2017 2amigOS! Consulting Group LLC
|
||||
* @link http://2amigos.us
|
||||
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
|
||||
*/
|
||||
namespace dosamigos\arrayquery\conditions;
|
||||
|
||||
|
||||
/**
|
||||
* LessThanOrEqual checks if value is less than or equal to the data searched.
|
||||
*
|
||||
* @author Antonio Ramirez <hola@2amigos.us>
|
||||
* @link http://www.ramirezcobos.com/
|
||||
* @link http://www.2amigos.us/
|
||||
* @package dosamigos\arrayquery\conditions
|
||||
*/
|
||||
class LessThanOrEqual extends Condition
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns [[GreaterThanOrEqual]] condition
|
||||
* @return GreaterThanOrEqual
|
||||
*/
|
||||
public function reverse()
|
||||
{
|
||||
return new GreaterThanOrEqual($this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function matches($data)
|
||||
{
|
||||
$gt = new LessThan($this->value);
|
||||
$e = new Equal($this->value);
|
||||
|
||||
return $gt->matches($data) || $e->matches($data);
|
||||
}
|
||||
|
||||
}
|
28
vendor/2amigos/yii2-arrayquery-component/src/conditions/Like.php
vendored
Normal file
28
vendor/2amigos/yii2-arrayquery-component/src/conditions/Like.php
vendored
Normal file
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2013-2017 2amigOS! Consulting Group LLC
|
||||
* @link http://2amigos.us
|
||||
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
|
||||
*/
|
||||
namespace dosamigos\arrayquery\conditions;
|
||||
|
||||
|
||||
/**
|
||||
* Like checks if value is matches any words in theå data searched.
|
||||
*
|
||||
* @author Antonio Ramirez <hola@2amigos.us>
|
||||
* @link http://www.ramirezcobos.com/
|
||||
* @link http://www.2amigos.us/
|
||||
* @package dosamigos\arrayquery\conditions
|
||||
*/
|
||||
class Like extends Condition
|
||||
{
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function matches($data)
|
||||
{
|
||||
return is_string($data) && mb_stripos($data, $this->value) !== false;
|
||||
}
|
||||
}
|
27
vendor/2amigos/yii2-arrayquery-component/src/conditions/NotLike.php
vendored
Normal file
27
vendor/2amigos/yii2-arrayquery-component/src/conditions/NotLike.php
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
/**
|
||||
* @copyright Copyright (c) 2013-2017 2amigOS! Consulting Group LLC
|
||||
* @link http://2amigos.us
|
||||
* @license http://www.opensource.org/licenses/bsd-license.php New BSD License
|
||||
*/
|
||||
namespace dosamigos\arrayquery\conditions;
|
||||
|
||||
|
||||
/**
|
||||
* NotLike checks if value is not within the data searched.
|
||||
*
|
||||
* @author Antonio Ramirez <hola@2amigos.us>
|
||||
* @link http://www.ramirezcobos.com/
|
||||
* @link http://www.2amigos.us/
|
||||
* @package dosamigos\arrayquery\conditions
|
||||
*/
|
||||
class NotLike extends Like
|
||||
{
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function matches($data)
|
||||
{
|
||||
return !parent::matches($data);
|
||||
}
|
||||
}
|
34
vendor/almasaeed2010/adminlte/.github/ISSUE_TEMPLATE.md
vendored
Normal file
34
vendor/almasaeed2010/adminlte/.github/ISSUE_TEMPLATE.md
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
<!--
|
||||
Before opening a new issue, please search through the existing issues to
|
||||
see if your topic has already been addressed. Note that you may need to
|
||||
remove the "is:open" filter from the search bar to include closed issues.
|
||||
|
||||
Check the appropriate type for your issue below by placing an x between the
|
||||
brackets.
|
||||
|
||||
Please note that issues which do not fall under any of the below categories
|
||||
will be closed.
|
||||
--->
|
||||
### Issue type:
|
||||
- [ ] Feature request <!-- Requesting the implementation of a new feature -->
|
||||
- [ ] Bug report <!-- Reporting unexpected or erroneous behavior -->
|
||||
- [ ] Documentation <!-- Proposing a modification to the documentation -->
|
||||
|
||||
<!--
|
||||
Please describe the environment.
|
||||
-->
|
||||
### Environment:
|
||||
* AdminLTE Version: <!-- Example: 2.4 -->
|
||||
* Operating System: <!-- Example: OSX/Android -->
|
||||
* Browser (Version): <!-- Example: Chrome (Latest) -->
|
||||
|
||||
<!--
|
||||
BUG REPORTS must include:
|
||||
* Steps or URL needed to reproduce the bug/issue
|
||||
* Any relevant error messages (screenshots may also help)
|
||||
* A snippet of your markup (where applicable)
|
||||
|
||||
FEATURE REQUESTS must include:
|
||||
* A detailed description of the proposed functionality
|
||||
-->
|
||||
### Description:
|
11
vendor/almasaeed2010/adminlte/.gitignore
vendored
Normal file
11
vendor/almasaeed2010/adminlte/.gitignore
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
*.DS_Store
|
||||
*.log
|
||||
*.zip
|
||||
.idea
|
||||
.sass-cache/
|
||||
/nbproject/
|
||||
/nbproject/private/
|
||||
/node_modules/
|
||||
ad.js
|
||||
TODO
|
||||
test.html
|
2
vendor/almasaeed2010/adminlte/.npmignore
vendored
Normal file
2
vendor/almasaeed2010/adminlte/.npmignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
documentation/
|
||||
composer.json
|
311
vendor/almasaeed2010/adminlte/Gruntfile.js
vendored
Normal file
311
vendor/almasaeed2010/adminlte/Gruntfile.js
vendored
Normal file
|
@ -0,0 +1,311 @@
|
|||
// AdminLTE Gruntfile
|
||||
module.exports = function (grunt) { // jshint ignore:line
|
||||
'use strict';
|
||||
|
||||
grunt.initConfig({
|
||||
pkg : grunt.file.readJSON('package.json'),
|
||||
watch : {
|
||||
less : {
|
||||
// Compiles less files upon saving
|
||||
files: ['build/less/*.less'],
|
||||
tasks: ['less:development', 'less:production', 'replace', 'notify:less']
|
||||
},
|
||||
js : {
|
||||
// Compile js files upon saving
|
||||
files: ['build/js/*.js'],
|
||||
tasks: ['js', 'notify:js']
|
||||
},
|
||||
skins: {
|
||||
// Compile any skin less files upon saving
|
||||
files: ['build/less/skins/*.less'],
|
||||
tasks: ['less:skins', 'less:minifiedSkins', 'notify:less']
|
||||
}
|
||||
},
|
||||
// Notify end of tasks
|
||||
notify: {
|
||||
less: {
|
||||
options: {
|
||||
title : 'AdminLTE',
|
||||
message: 'LESS finished running'
|
||||
}
|
||||
},
|
||||
js : {
|
||||
options: {
|
||||
title : 'AdminLTE',
|
||||
message: 'JS bundler finished running'
|
||||
}
|
||||
}
|
||||
},
|
||||
// 'less'-task configuration
|
||||
// This task will compile all less files upon saving to create both AdminLTE.css and AdminLTE.min.css
|
||||
less : {
|
||||
// Development not compressed
|
||||
development : {
|
||||
files: {
|
||||
// compilation.css : source.less
|
||||
'dist/css/AdminLTE.css' : 'build/less/AdminLTE.less',
|
||||
// AdminLTE without plugins
|
||||
'dist/css/alt/AdminLTE-without-plugins.css' : 'build/less/AdminLTE-without-plugins.less',
|
||||
// Separate plugins
|
||||
'dist/css/alt/AdminLTE-select2.css' : 'build/less/select2.less',
|
||||
'dist/css/alt/AdminLTE-fullcalendar.css' : 'build/less/fullcalendar.less',
|
||||
'dist/css/alt/AdminLTE-bootstrap-social.css': 'build/less/bootstrap-social.less'
|
||||
}
|
||||
},
|
||||
// Production compressed version
|
||||
production : {
|
||||
options: {
|
||||
compress: true
|
||||
},
|
||||
files : {
|
||||
// compilation.css : source.less
|
||||
'dist/css/AdminLTE.min.css' : 'build/less/AdminLTE.less',
|
||||
// AdminLTE without plugins
|
||||
'dist/css/alt/AdminLTE-without-plugins.min.css' : 'build/less/AdminLTE-without-plugins.less',
|
||||
// Separate plugins
|
||||
'dist/css/alt/AdminLTE-select2.min.css' : 'build/less/select2.less',
|
||||
'dist/css/alt/AdminLTE-fullcalendar.min.css' : 'build/less/fullcalendar.less',
|
||||
'dist/css/alt/AdminLTE-bootstrap-social.min.css': 'build/less/bootstrap-social.less'
|
||||
}
|
||||
},
|
||||
// Non minified skin files
|
||||
skins : {
|
||||
files: {
|
||||
'dist/css/skins/skin-blue.css' : 'build/less/skins/skin-blue.less',
|
||||
'dist/css/skins/skin-black.css' : 'build/less/skins/skin-black.less',
|
||||
'dist/css/skins/skin-yellow.css' : 'build/less/skins/skin-yellow.less',
|
||||
'dist/css/skins/skin-green.css' : 'build/less/skins/skin-green.less',
|
||||
'dist/css/skins/skin-red.css' : 'build/less/skins/skin-red.less',
|
||||
'dist/css/skins/skin-purple.css' : 'build/less/skins/skin-purple.less',
|
||||
'dist/css/skins/skin-blue-light.css' : 'build/less/skins/skin-blue-light.less',
|
||||
'dist/css/skins/skin-black-light.css' : 'build/less/skins/skin-black-light.less',
|
||||
'dist/css/skins/skin-yellow-light.css': 'build/less/skins/skin-yellow-light.less',
|
||||
'dist/css/skins/skin-green-light.css' : 'build/less/skins/skin-green-light.less',
|
||||
'dist/css/skins/skin-red-light.css' : 'build/less/skins/skin-red-light.less',
|
||||
'dist/css/skins/skin-purple-light.css': 'build/less/skins/skin-purple-light.less',
|
||||
'dist/css/skins/_all-skins.css' : 'build/less/skins/_all-skins.less'
|
||||
}
|
||||
},
|
||||
// Skins minified
|
||||
minifiedSkins: {
|
||||
options: {
|
||||
compress: true
|
||||
},
|
||||
files : {
|
||||
'dist/css/skins/skin-blue.min.css' : 'build/less/skins/skin-blue.less',
|
||||
'dist/css/skins/skin-black.min.css' : 'build/less/skins/skin-black.less',
|
||||
'dist/css/skins/skin-yellow.min.css' : 'build/less/skins/skin-yellow.less',
|
||||
'dist/css/skins/skin-green.min.css' : 'build/less/skins/skin-green.less',
|
||||
'dist/css/skins/skin-red.min.css' : 'build/less/skins/skin-red.less',
|
||||
'dist/css/skins/skin-purple.min.css' : 'build/less/skins/skin-purple.less',
|
||||
'dist/css/skins/skin-blue-light.min.css' : 'build/less/skins/skin-blue-light.less',
|
||||
'dist/css/skins/skin-black-light.min.css' : 'build/less/skins/skin-black-light.less',
|
||||
'dist/css/skins/skin-yellow-light.min.css': 'build/less/skins/skin-yellow-light.less',
|
||||
'dist/css/skins/skin-green-light.min.css' : 'build/less/skins/skin-green-light.less',
|
||||
'dist/css/skins/skin-red-light.min.css' : 'build/less/skins/skin-red-light.less',
|
||||
'dist/css/skins/skin-purple-light.min.css': 'build/less/skins/skin-purple-light.less',
|
||||
'dist/css/skins/_all-skins.min.css' : 'build/less/skins/_all-skins.less'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Uglify task info. Compress the js files.
|
||||
uglify: {
|
||||
options : {
|
||||
mangle : true,
|
||||
preserveComments: 'some'
|
||||
},
|
||||
production: {
|
||||
files: {
|
||||
'dist/js/adminlte.min.js': ['dist/js/adminlte.js']
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Concatenate JS Files
|
||||
concat: {
|
||||
options: {
|
||||
separator: '\n\n',
|
||||
banner : '/*! AdminLTE app.js\n'
|
||||
+ '* ================\n'
|
||||
+ '* Main JS application file for AdminLTE v2. This file\n'
|
||||
+ '* should be included in all pages. It controls some layout\n'
|
||||
+ '* options and implements exclusive AdminLTE plugins.\n'
|
||||
+ '*\n'
|
||||
+ '* @Author Almsaeed Studio\n'
|
||||
+ '* @Support <https://www.almsaeedstudio.com>\n'
|
||||
+ '* @Email <abdullah@almsaeedstudio.com>\n'
|
||||
+ '* @version <%= pkg.version %>\n'
|
||||
+ '* @repository <%= pkg.repository.url %>\n'
|
||||
+ '* @license MIT <http://opensource.org/licenses/MIT>\n'
|
||||
+ '*/\n\n'
|
||||
+ '// Make sure jQuery has been loaded\n'
|
||||
+ 'if (typeof jQuery === \'undefined\') {\n'
|
||||
+ 'throw new Error(\'AdminLTE requires jQuery\')\n'
|
||||
+ '}\n\n'
|
||||
},
|
||||
dist : {
|
||||
src : [
|
||||
'build/js/BoxRefresh.js',
|
||||
'build/js/BoxWidget.js',
|
||||
'build/js/ControlSidebar.js',
|
||||
'build/js/DirectChat.js',
|
||||
'build/js/Layout.js',
|
||||
'build/js/PushMenu.js',
|
||||
'build/js/TodoList.js',
|
||||
'build/js/Tree.js'
|
||||
],
|
||||
dest: 'dist/js/adminlte.js'
|
||||
}
|
||||
},
|
||||
|
||||
// Replace image paths in AdminLTE without plugins
|
||||
replace: {
|
||||
withoutPlugins : {
|
||||
src : ['dist/css/alt/AdminLTE-without-plugins.css'],
|
||||
dest : 'dist/css/alt/AdminLTE-without-plugins.css',
|
||||
replacements: [
|
||||
{
|
||||
from: '../img',
|
||||
to : '../../img'
|
||||
}
|
||||
]
|
||||
},
|
||||
withoutPluginsMin: {
|
||||
src : ['dist/css/alt/AdminLTE-without-plugins.min.css'],
|
||||
dest : 'dist/css/alt/AdminLTE-without-plugins.min.css',
|
||||
replacements: [
|
||||
{
|
||||
from: '../img',
|
||||
to : '../../img'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
// Build the documentation files
|
||||
includes: {
|
||||
build: {
|
||||
src : ['*.html'], // Source files
|
||||
dest : 'documentation/', // Destination directory
|
||||
flatten: true,
|
||||
cwd : 'documentation/build',
|
||||
options: {
|
||||
silent : true,
|
||||
includePath: 'documentation/build/include'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Optimize images
|
||||
image: {
|
||||
dynamic: {
|
||||
files: [
|
||||
{
|
||||
expand: true,
|
||||
cwd : 'build/img/',
|
||||
src : ['**/*.{png,jpg,gif,svg,jpeg}'],
|
||||
dest : 'dist/img/'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
// Validate JS code
|
||||
jshint: {
|
||||
options: {
|
||||
jshintrc: 'build/js/.jshintrc'
|
||||
},
|
||||
grunt : {
|
||||
options: {
|
||||
jshintrc: 'build/grunt/.jshintrc'
|
||||
},
|
||||
src : 'Gruntfile.js'
|
||||
},
|
||||
core : {
|
||||
src: 'build/js/*.js'
|
||||
},
|
||||
demo : {
|
||||
src: 'dist/js/demo.js'
|
||||
},
|
||||
pages : {
|
||||
src: 'dist/js/pages/*.js'
|
||||
}
|
||||
},
|
||||
|
||||
jscs: {
|
||||
options: {
|
||||
config: 'build/js/.jscsrc'
|
||||
},
|
||||
core : {
|
||||
src: '<%= jshint.core.src %>'
|
||||
},
|
||||
pages : {
|
||||
src: '<%= jshint.pages.src %>'
|
||||
}
|
||||
},
|
||||
|
||||
// Validate CSS files
|
||||
csslint: {
|
||||
options: {
|
||||
csslintrc: 'build/less/.csslintrc'
|
||||
},
|
||||
dist : [
|
||||
'dist/css/AdminLTE.css'
|
||||
]
|
||||
},
|
||||
|
||||
// Validate Bootstrap HTML
|
||||
bootlint: {
|
||||
options: {
|
||||
relaxerror: ['W005']
|
||||
},
|
||||
files : ['pages/**/*.html', '*.html']
|
||||
},
|
||||
|
||||
// Delete images in build directory
|
||||
// After compressing the images in the build/img dir, there is no need
|
||||
// for them
|
||||
clean: {
|
||||
build: ['build/img/*']
|
||||
}
|
||||
});
|
||||
|
||||
// Load all grunt tasks
|
||||
|
||||
// LESS Compiler
|
||||
grunt.loadNpmTasks('grunt-contrib-less');
|
||||
// Watch File Changes
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
// Compress JS Files
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
// Include Files Within HTML
|
||||
grunt.loadNpmTasks('grunt-includes');
|
||||
// Optimize images
|
||||
grunt.loadNpmTasks('grunt-image');
|
||||
// Validate JS code
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadNpmTasks('grunt-jscs');
|
||||
// Delete not needed files
|
||||
grunt.loadNpmTasks('grunt-contrib-clean');
|
||||
// Lint CSS
|
||||
grunt.loadNpmTasks('grunt-contrib-csslint');
|
||||
// Lint Bootstrap
|
||||
grunt.loadNpmTasks('grunt-bootlint');
|
||||
// Concatenate JS files
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
// Notify
|
||||
grunt.loadNpmTasks('grunt-notify');
|
||||
// Replace
|
||||
grunt.loadNpmTasks('grunt-text-replace');
|
||||
|
||||
// Linting task
|
||||
grunt.registerTask('lint', ['jshint', 'csslint', 'bootlint']);
|
||||
// JS task
|
||||
grunt.registerTask('js', ['concat', 'uglify']);
|
||||
// CSS Task
|
||||
grunt.registerTask('css', ['less:development', 'less:production', 'replace']);
|
||||
|
||||
// The default task (running 'grunt' in console) is 'watch'
|
||||
grunt.registerTask('default', ['watch']);
|
||||
};
|
20
vendor/almasaeed2010/adminlte/LICENSE
vendored
Normal file
20
vendor/almasaeed2010/adminlte/LICENSE
vendored
Normal file
|
@ -0,0 +1,20 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014-2017 Abdullah Almsaeed
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
57
vendor/almasaeed2010/adminlte/README.md
vendored
Normal file
57
vendor/almasaeed2010/adminlte/README.md
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
Introduction
|
||||
============
|
||||
|
||||

|
||||
[](https://www.npmjs.com/package/admin-lte)
|
||||
[](https://packagist.org/packages/almasaeed2010/adminlte)
|
||||
[](https://cdnjs.com/libraries/admin-lte)
|
||||
|
||||
**AdminLTE** -- is a fully responsive admin template. Based on **[Bootstrap 3](https://github.com/twbs/bootstrap)** framework. Highly customizable and easy to use. Fits many screen resolutions from small mobile devices to large desktops. Check out the live preview now and see for yourself.
|
||||
|
||||
**Download & Preview on [AdminLTE.IO](https://adminlte.io)**
|
||||
|
||||
### Looking for Premium Templates?
|
||||
**AdminLTE.IO just opened a new premium templates website. Hand picked to ensure the best quality and the most affordable prices. Visit https://themequarry.com for more information.**
|
||||
|
||||
## Documentation & Installation Guide
|
||||
Visit the [online documentation](https://adminlte.io/docs) for the most
|
||||
updated guide.
|
||||
|
||||

|
||||
|
||||
### Contribution
|
||||
Contribution are always **welcome and recommended**! Here is how:
|
||||
|
||||
- Fork the repository ([here is the guide](https://help.github.com/articles/fork-a-repo/)).
|
||||
- Clone to your machine ```git clone https://github.com/YOUR_USERNAME/AdminLTE.git```
|
||||
- Make your changes
|
||||
- Create a pull request
|
||||
|
||||
#### Contribution Requirements:
|
||||
|
||||
- When you contribute, you agree to give a non-exclusive license to AdminLTE.IO to use that contribution in any context as we (AdminLTE.IO) see appropriate.
|
||||
- If you use content provided by another party, it must be appropriately licensed using an [open source](http://opensource.org/licenses) license.
|
||||
- Contributions are only accepted through Github pull requests.
|
||||
- Finally, contributed code must work in all supported browsers (see above for browser support).
|
||||
|
||||
### License
|
||||
AdminLTE is an open source project by [AdminLTE.IO](https://adminlte.io) that is licensed under [MIT](http://opensource.org/licenses/MIT). AdminLTE.IO
|
||||
reserves the right to change the license of future releases. Wondering what you can or can't do? View the [license guide](https://adminlte.io/docs/license).
|
||||
|
||||
### Legacy Releases
|
||||
AdminLTE 1.x can be easily upgraded to 2.x using [this guide](https://adminlte.io/themes/AdminLTE/documentation/index.html#upgrade), but if you intend to keep using AdminLTE 1.x, you can download the latest release from the [releases](https://github.com/almasaeed2010/AdminLTE/releases) section above.
|
||||
|
||||
### Change log
|
||||
**For the most recent change log, visit the [releases page](https://github.com/almasaeed2010/AdminLTE/releases) or the [changelog file](https://github.com/almasaeed2010/AdminLTE/blob/master/changelog.md).** We will add detailed release notes to each new release.
|
||||
|
||||
### Image Credits
|
||||
- [Pixeden](http://www.pixeden.com/psd-web-elements/flat-responsive-showcase-psd)
|
||||
- [Graphicsfuel](http://www.graphicsfuel.com/2013/02/13-high-resolution-blur-backgrounds/)
|
||||
- [Pickaface](http://pickaface.net/)
|
||||
- [Unsplash](https://unsplash.com/)
|
||||
- [Uifaces](http://uifaces.com/)
|
||||
|
||||
### Donations
|
||||
Donations are **greatly appreciated!**
|
||||
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=629XCUSXBHCBC "Donate")
|
65
vendor/almasaeed2010/adminlte/bower.json
vendored
Normal file
65
vendor/almasaeed2010/adminlte/bower.json
vendored
Normal file
|
@ -0,0 +1,65 @@
|
|||
{
|
||||
"name": "admin-lte",
|
||||
"homepage": "https://adminlte.io",
|
||||
"authors": [
|
||||
"Abdullah Almsaeed <abdullah@almsaeedstudio.com>"
|
||||
],
|
||||
"description": "Admin dashboard and control panel template",
|
||||
"main": [
|
||||
"index2.html",
|
||||
"dist/css/AdminLTE.css",
|
||||
"dist/js/adminlte.js",
|
||||
"build/less/AdminLTE.less"
|
||||
],
|
||||
"keywords": [
|
||||
"css",
|
||||
"js",
|
||||
"html",
|
||||
"template",
|
||||
"admin",
|
||||
"bootstrap",
|
||||
"theme",
|
||||
"backend",
|
||||
"responsive"
|
||||
],
|
||||
"license": "MIT",
|
||||
"ignore": [
|
||||
"/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"composer.json",
|
||||
"documentation"
|
||||
],
|
||||
"dependencies": {
|
||||
"bootstrap-slider": "*",
|
||||
"chart.js": "1.0.*",
|
||||
"ckeditor": "^4.7.0",
|
||||
"bootstrap-colorpicker": "^2.5.1",
|
||||
"bootstrap": "^3.3.7",
|
||||
"jquery": "^3.2.1",
|
||||
"datatables.net": "^1.10.15",
|
||||
"datatables.net-bs": "^2.1.1",
|
||||
"bootstrap-datepicker": "^1.7.0",
|
||||
"bootstrap-daterangepicker": "^2.1.25",
|
||||
"moment": "^2.18.1",
|
||||
"fastclick": "^1.0.6",
|
||||
"Flot": "flot#^0.8.3",
|
||||
"fullcalendar": "^3.4.0",
|
||||
"inputmask": "jquery.inputmask#^3.3.7",
|
||||
"ion.rangeSlider": "ionrangeslider#^2.2.0",
|
||||
"jvectormap": "^1.2.2",
|
||||
"jquery-knob": "^1.2.13",
|
||||
"morris.js": "^0.5.1",
|
||||
"PACE": "pace#^1.0.2",
|
||||
"select2": "^4.0.3",
|
||||
"jquery-slimscroll": "slimscroll#^1.3.8",
|
||||
"bootstrap-timepicker": "^0.5.2",
|
||||
"jquery-sparkline": "^2.1.3",
|
||||
"font-awesome": "^4.7.0",
|
||||
"Ionicons": "ionicons#^2.0.1",
|
||||
"jquery-ui": "1.11.4"
|
||||
},
|
||||
"resolutions": {
|
||||
"jquery": "^3.2.1"
|
||||
}
|
||||
}
|
18
vendor/almasaeed2010/adminlte/bower_components/Flot/.bower.json
vendored
Normal file
18
vendor/almasaeed2010/adminlte/bower_components/Flot/.bower.json
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "Flot",
|
||||
"version": "0.8.3",
|
||||
"main": "jquery.flot.js",
|
||||
"dependencies": {
|
||||
"jquery": ">= 1.2.6"
|
||||
},
|
||||
"homepage": "https://github.com/flot/flot",
|
||||
"_release": "0.8.3",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v0.8.3",
|
||||
"commit": "453b017cc5acfd75e252b93e8635f57f4196d45d"
|
||||
},
|
||||
"_source": "https://github.com/flot/flot.git",
|
||||
"_target": "^0.8.3",
|
||||
"_originalSource": "flot"
|
||||
}
|
3
vendor/almasaeed2010/adminlte/bower_components/Flot/.gitignore
vendored
Normal file
3
vendor/almasaeed2010/adminlte/bower_components/Flot/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
*.min.js
|
||||
!excanvas.min.js
|
||||
node_modules/
|
3
vendor/almasaeed2010/adminlte/bower_components/Flot/.travis.yml
vendored
Normal file
3
vendor/almasaeed2010/adminlte/bower_components/Flot/.travis.yml
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- 0.8
|
1498
vendor/almasaeed2010/adminlte/bower_components/Flot/API.md
vendored
Normal file
1498
vendor/almasaeed2010/adminlte/bower_components/Flot/API.md
vendored
Normal file
File diff suppressed because it is too large
Load Diff
98
vendor/almasaeed2010/adminlte/bower_components/Flot/CONTRIBUTING.md
vendored
Normal file
98
vendor/almasaeed2010/adminlte/bower_components/Flot/CONTRIBUTING.md
vendored
Normal file
|
@ -0,0 +1,98 @@
|
|||
## Contributing to Flot ##
|
||||
|
||||
We welcome all contributions, but following these guidelines results in less
|
||||
work for us, and a faster and better response.
|
||||
|
||||
### Issues ###
|
||||
|
||||
Issues are not a way to ask general questions about Flot. If you see unexpected
|
||||
behavior but are not 100% certain that it is a bug, please try posting to the
|
||||
[forum](http://groups.google.com/group/flot-graphs) first, and confirm that
|
||||
what you see is really a Flot problem before creating a new issue for it. When
|
||||
reporting a bug, please include a working demonstration of the problem, if
|
||||
possible, or at least a clear description of the options you're using and the
|
||||
environment (browser and version, jQuery version, other libraries) that you're
|
||||
running under.
|
||||
|
||||
If you have suggestions for new features, or changes to existing ones, we'd
|
||||
love to hear them! Please submit each suggestion as a separate new issue.
|
||||
|
||||
If you would like to work on an existing issue, please make sure it is not
|
||||
already assigned to someone else. If an issue is assigned to someone, that
|
||||
person has already started working on it. So, pick unassigned issues to prevent
|
||||
duplicated effort.
|
||||
|
||||
### Pull Requests ###
|
||||
|
||||
To make merging as easy as possible, please keep these rules in mind:
|
||||
|
||||
1. Submit new features or architectural changes to the *<version>-work*
|
||||
branch for the next major release. Submit bug fixes to the master branch.
|
||||
|
||||
2. Divide larger changes into a series of small, logical commits with
|
||||
descriptive messages.
|
||||
|
||||
3. Rebase, if necessary, before submitting your pull request, to reduce the
|
||||
work we need to do to merge it.
|
||||
|
||||
4. Format your code according to the style guidelines below.
|
||||
|
||||
### Flot Style Guidelines ###
|
||||
|
||||
Flot follows the [jQuery Core Style Guidelines](http://docs.jquery.com/JQuery_Core_Style_Guidelines),
|
||||
with the following updates and exceptions:
|
||||
|
||||
#### Spacing ####
|
||||
|
||||
Use four-space indents, no tabs. Do not add horizontal space around parameter
|
||||
lists, loop definitions, or array/object indices. For example:
|
||||
|
||||
```js
|
||||
for ( var i = 0; i < data.length; i++ ) { // This block is wrong!
|
||||
if ( data[ i ] > 1 ) {
|
||||
data[ i ] = 2;
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < data.length; i++) { // This block is correct!
|
||||
if (data[i] > 1) {
|
||||
data[i] = 2;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Comments ####
|
||||
|
||||
Use [jsDoc](http://usejsdoc.org) comments for all file and function headers.
|
||||
Use // for all inline and block comments, regardless of length.
|
||||
|
||||
All // comment blocks should have an empty line above *and* below them. For
|
||||
example:
|
||||
|
||||
```js
|
||||
var a = 5;
|
||||
|
||||
// We're going to loop here
|
||||
// TODO: Make this loop faster, better, stronger!
|
||||
|
||||
for (var x = 0; x < 10; x++) {}
|
||||
```
|
||||
|
||||
#### Wrapping ####
|
||||
|
||||
Block comments should be wrapped at 80 characters.
|
||||
|
||||
Code should attempt to wrap at 80 characters, but may run longer if wrapping
|
||||
would hurt readability more than having to scroll horizontally. This is a
|
||||
judgement call made on a situational basis.
|
||||
|
||||
Statements containing complex logic should not be wrapped arbitrarily if they
|
||||
do not exceed 80 characters. For example:
|
||||
|
||||
```js
|
||||
if (a == 1 && // This block is wrong!
|
||||
b == 2 &&
|
||||
c == 3) {}
|
||||
|
||||
if (a == 1 && b == 2 && c == 3) {} // This block is correct!
|
||||
```
|
75
vendor/almasaeed2010/adminlte/bower_components/Flot/FAQ.md
vendored
Normal file
75
vendor/almasaeed2010/adminlte/bower_components/Flot/FAQ.md
vendored
Normal file
|
@ -0,0 +1,75 @@
|
|||
## Frequently asked questions ##
|
||||
|
||||
#### How much data can Flot cope with? ####
|
||||
|
||||
Flot will happily draw everything you send to it so the answer
|
||||
depends on the browser. The excanvas emulation used for IE (built with
|
||||
VML) makes IE by far the slowest browser so be sure to test with that
|
||||
if IE users are in your target group (for large plots in IE, you can
|
||||
also check out Flashcanvas which may be faster).
|
||||
|
||||
1000 points is not a problem, but as soon as you start having more
|
||||
points than the pixel width, you should probably start thinking about
|
||||
downsampling/aggregation as this is near the resolution limit of the
|
||||
chart anyway. If you downsample server-side, you also save bandwidth.
|
||||
|
||||
|
||||
#### Flot isn't working when I'm using JSON data as source! ####
|
||||
|
||||
Actually, Flot loves JSON data, you just got the format wrong.
|
||||
Double check that you're not inputting strings instead of numbers,
|
||||
like [["0", "-2.13"], ["5", "4.3"]]. This is most common mistake, and
|
||||
the error might not show up immediately because Javascript can do some
|
||||
conversion automatically.
|
||||
|
||||
|
||||
#### Can I export the graph? ####
|
||||
|
||||
You can grab the image rendered by the canvas element used by Flot
|
||||
as a PNG or JPEG (remember to set a background). Note that it won't
|
||||
include anything not drawn in the canvas (such as the legend). And it
|
||||
doesn't work with excanvas which uses VML, but you could try
|
||||
Flashcanvas.
|
||||
|
||||
|
||||
#### The bars are all tiny in time mode? ####
|
||||
|
||||
It's not really possible to determine the bar width automatically.
|
||||
So you have to set the width with the barWidth option which is NOT in
|
||||
pixels, but in the units of the x axis (or the y axis for horizontal
|
||||
bars). For time mode that's milliseconds so the default value of 1
|
||||
makes the bars 1 millisecond wide.
|
||||
|
||||
|
||||
#### Can I use Flot with libraries like Mootools or Prototype? ####
|
||||
|
||||
Yes, Flot supports it out of the box and it's easy! Just use jQuery
|
||||
instead of $, e.g. call jQuery.plot instead of $.plot and use
|
||||
jQuery(something) instead of $(something). As a convenience, you can
|
||||
put in a DOM element for the graph placeholder where the examples and
|
||||
the API documentation are using jQuery objects.
|
||||
|
||||
Depending on how you include jQuery, you may have to add one line of
|
||||
code to prevent jQuery from overwriting functions from the other
|
||||
libraries, see the documentation in jQuery ("Using jQuery with other
|
||||
libraries") for details.
|
||||
|
||||
|
||||
#### Flot doesn't work with [insert name of Javascript UI framework]! ####
|
||||
|
||||
Flot is using standard HTML to make charts. If this is not working,
|
||||
it's probably because the framework you're using is doing something
|
||||
weird with the DOM or with the CSS that is interfering with Flot.
|
||||
|
||||
A common problem is that there's display:none on a container until the
|
||||
user does something. Many tab widgets work this way, and there's
|
||||
nothing wrong with it - you just can't call Flot inside a display:none
|
||||
container as explained in the README so you need to hold off the Flot
|
||||
call until the container is actually displayed (or use
|
||||
visibility:hidden instead of display:none or move the container
|
||||
off-screen).
|
||||
|
||||
If you find there's a specific thing we can do to Flot to help, feel
|
||||
free to submit a bug report. Otherwise, you're welcome to ask for help
|
||||
on the forum/mailing list, but please don't submit a bug report to
|
||||
Flot.
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user