| @ -0,0 +1,22 @@ | |||
| The MIT License (MIT) | |||
| Copyright (c) 2015 M.Karminski | |||
| Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| of this software and associated documentation files (the "Software"), to deal | |||
| in the Software without restriction, including without limitation the rights | |||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| copies of the Software, and to permit persons to whom the Software is | |||
| furnished to do so, subject to the following conditions: | |||
| The above copyright notice and this permission notice shall be included in all | |||
| copies or substantial portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| SOFTWARE. | |||
| @ -0,0 +1,19 @@ | |||
| related_modules.md | |||
| ------------------- | |||
| ``` | |||
| @version 151109:1 | |||
| @author karminski <code.karminski@outlook.com> | |||
| ``` | |||
| PHP Module | |||
| ------------ | |||
| - curl | |||
| - json | |||
| - PDO | |||
| - pdo_mysql | |||
| - phpredis | |||
| - https://github.com/phpredis/phpredis | |||
| - mongodb | |||
| - rdkafka | |||
| - yac | |||
| @ -1,2 +1,26 @@ | |||
| # gq-hello-container | |||
| Saltfish Raw PHP | |||
| ---------------- | |||
| ``` | |||
| @version 180426:1 | |||
| @author karminski <code.karminski@outlook.com> | |||
| ``` | |||
| Name | |||
| ---- | |||
| saltfish_raw_php | |||
| Table of Contents | |||
| ----------------- | |||
| * [Name](#name) | |||
| * [Desc](#desc) | |||
| sdgdfghdf | |||
| Desc | |||
| ---- | |||
| saltfish API generator base framework PHP version. | |||
| @ -0,0 +1,7 @@ | |||
| # SampleBuilder.cron | |||
| # @version: 160309:1 | |||
| # @author: karminski <code.karminski@outlook.com> | |||
| # | |||
| # SampleBuilder cronjob | |||
| 0 0 */1 * * root flock -xn /data/repo/saltfish_raw_php/lock/SampleBuilder.lock -c '/data/apps/php7/bin/php /data/repo/saltfish_raw_php/src/SampleBuilder.php --signal_file=/data/repo/saltfish_raw_php/lock/SampleBuilder.lock & >> /data/repo/saltfish_raw_php/logs/SampleBuilder.stdout.log' | |||
| @ -0,0 +1,71 @@ | |||
| // Jenkinsfile.beta | |||
| // @version 180820:1 | |||
| // @author zhangxuhong <zhangxuhong@xitu.io> | |||
| // | |||
| def appName = "suid-generator" | |||
| def label = "worker-${UUID.randomUUID().toString()}" | |||
| def registryHost = "harbor02.juejin.id/beta/" | |||
| def deployLocation = "beta.kube01.lobj.juejin.id" | |||
| podTemplate( | |||
| label: label, | |||
| containers: [ | |||
| containerTemplate( | |||
| name: 'git', | |||
| image: 'harbor02.juejin.id/infrastructure/git-1.8.3.1-centos:0.0.3', | |||
| command: 'cat', | |||
| ttyEnabled: true | |||
| ), | |||
| containerTemplate( | |||
| name: 'dind', | |||
| image: 'harbor02.juejin.id/infrastructure/docker-18.06.0-ce-dind:0.0.2', | |||
| command: 'cat', | |||
| ttyEnabled: true | |||
| ), | |||
| containerTemplate( | |||
| name: 'kubectl', | |||
| image: 'harbor02.juejin.id/infrastructure/kubectl-1.11.1-centos-with-cert-cluster01.lobj:latest', | |||
| command: 'cat', | |||
| ttyEnabled: true | |||
| ), | |||
| ], | |||
| volumes: [ | |||
| hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock'), | |||
| ], | |||
| cloud: deployLocation | |||
| ){ | |||
| node(label) { | |||
| // start deploy phrase | |||
| stage("[1/4] check out"){ | |||
| container('git'){ | |||
| checkout scm | |||
| sh "git rev-parse --short HEAD > commit-id" | |||
| tag = readFile('commit-id').replace("\n", "").replace("\r", "") | |||
| imageName = "${registryHost}${appName}:${tag}" | |||
| env.BUILDIMG=imageName | |||
| } | |||
| } | |||
| stage("[2/4] Build"){ | |||
| container('dind'){ | |||
| sh "docker version" | |||
| sh "docker build -t ${imageName} ./" | |||
| } | |||
| } | |||
| stage("[3/4] Push"){ | |||
| container('dind'){ | |||
| sh "/usr/local/bin/docker-login.sh" | |||
| sh "docker push ${imageName}" | |||
| } | |||
| } | |||
| stage("[4/4] Deploy"){ | |||
| container('kubectl'){ | |||
| sh "sed -i 's#__IMAGE__#$BUILDIMG#g' ./config/kubernetes/Deployment.yaml" | |||
| sh "cat ./config/kubernetes/Deployment.yaml" | |||
| sh "kubectl --kubeconfig=/root/.kube/config apply -f ./config/kubernetes/Service.yaml" | |||
| sh "kubectl --kubeconfig=/root/.kube/config apply -f ./config/kubernetes/Ingress.yaml" | |||
| sh "kubectl --kubeconfig=/root/.kube/config apply -f ./config/kubernetes/Deployment.yaml" | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,71 @@ | |||
| // Jenkinsfile.prod | |||
| // @version 180820:1 | |||
| // @author zhangxuhong <zhangxuhong@xitu.io> | |||
| // | |||
| def appName = "suid-generator" | |||
| def label = "worker-${UUID.randomUUID().toString()}" | |||
| def registryHost = "harbor02.juejin.id/prod/" | |||
| def deployLocation = "prod.kube01.lobj.juejin.id" | |||
| podTemplate( | |||
| label: label, | |||
| containers: [ | |||
| containerTemplate( | |||
| name: 'git', | |||
| image: 'harbor02.juejin.id/infrastructure/git-1.8.3.1-centos:0.0.3', | |||
| command: 'cat', | |||
| ttyEnabled: true | |||
| ), | |||
| containerTemplate( | |||
| name: 'dind', | |||
| image: 'harbor02.juejin.id/infrastructure/docker-18.06.0-ce-dind:0.0.2', | |||
| command: 'cat', | |||
| ttyEnabled: true | |||
| ), | |||
| containerTemplate( | |||
| name: 'kubectl', | |||
| image: 'harbor02.juejin.id/infrastructure/kubectl-1.11.1-centos-with-cert-cluster01.lobj:latest', | |||
| command: 'cat', | |||
| ttyEnabled: true | |||
| ), | |||
| ], | |||
| volumes: [ | |||
| hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock'), | |||
| ], | |||
| cloud: deployLocation | |||
| ){ | |||
| node(label) { | |||
| // start deploy phrase | |||
| stage("[1/4] check out"){ | |||
| container('git'){ | |||
| checkout scm | |||
| sh "git rev-parse --short HEAD > commit-id" | |||
| tag = readFile('commit-id').replace("\n", "").replace("\r", "") | |||
| imageName = "${registryHost}${appName}:${tag}" | |||
| env.BUILDIMG=imageName | |||
| } | |||
| } | |||
| stage("[2/4] Build"){ | |||
| container('dind'){ | |||
| sh "docker version" | |||
| sh "docker build -t ${imageName} ./" | |||
| } | |||
| } | |||
| stage("[3/4] Push"){ | |||
| container('dind'){ | |||
| sh "/usr/local/bin/docker-login.sh" | |||
| sh "docker push ${imageName}" | |||
| } | |||
| } | |||
| stage("[4/4] Deploy"){ | |||
| container('kubectl'){ | |||
| sh "sed -i 's#__IMAGE__#$BUILDIMG#g' ./config/kubernetes/Deployment.yaml" | |||
| sh "cat ./config/kubernetes/Deployment.yaml" | |||
| sh "kubectl --kubeconfig=/root/.kube/config apply -f ./config/kubernetes/Service.yaml" | |||
| sh "kubectl --kubeconfig=/root/.kube/config apply -f ./config/kubernetes/Ingress.yaml" | |||
| sh "kubectl --kubeconfig=/root/.kube/config apply -f ./config/kubernetes/Deployment.yaml" | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,82 @@ | |||
| // Jenkinsfile.test | |||
| // @version 180903:2 | |||
| // @author zhangxuhong <zhangxuhong@xitu.io> | |||
| // | |||
| def repoName = "gq-hello" | |||
| def nginxRepoName = "${repoName}-nginx" | |||
| def label = "worker-${UUID.randomUUID().toString()}" | |||
| def registryHost = "harbor02.juejin.id/test/" | |||
| def deployLocation = "test.kube01.lobj.juejin.id" | |||
| podTemplate( | |||
| label: label, | |||
| containers: [ | |||
| containerTemplate( | |||
| name: 'git', | |||
| image: 'harbor02.juejin.id/infrastructure/git-1.8.3.1-centos:0.0.3', | |||
| command: 'cat', | |||
| ttyEnabled: true | |||
| ), | |||
| containerTemplate( | |||
| name: 'dind', | |||
| image: 'harbor02.juejin.id/infrastructure/docker-18.06.0-ce-dind:0.0.2', | |||
| command: 'cat', | |||
| ttyEnabled: true | |||
| ), | |||
| containerTemplate( | |||
| name: 'kubectl', | |||
| image: 'harbor02.juejin.id/infrastructure/kubectl-1.11.1-centos-with-cert-cluster01.lobj:latest', | |||
| command: 'cat', | |||
| ttyEnabled: true | |||
| ), | |||
| ], | |||
| volumes: [ | |||
| hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock'), | |||
| ], | |||
| cloud: deployLocation | |||
| ){ | |||
| node(label) { | |||
| // start deploy phrase | |||
| stage("[1/4] check out"){ | |||
| container('git'){ | |||
| checkout scm | |||
| sh "git rev-parse --short HEAD > commit-id" | |||
| tag = readFile('commit-id').replace("\n", "").replace("\r", "") | |||
| imageName = "${registryHost}${repoName}:${tag}" | |||
| nginxImageName = "${registryHost}${nginxRepoName}:${tag}" | |||
| env.IMAGE_NAME = imageName | |||
| env.NGINX_IMAGE_NAME = nginxImageName | |||
| } | |||
| } | |||
| stage("[2/4] Build"){ | |||
| container('dind'){ | |||
| sh "docker version" | |||
| sh "docker build -f gq-hello.dockerfile -t ${imageName} ./" | |||
| sh "docker build -f gq-hello-nginx.dockerfile -t ${nginxImageName} ./" | |||
| } | |||
| } | |||
| stage("[3/4] Push"){ | |||
| container('dind'){ | |||
| sh "/usr/local/bin/docker-login.sh" | |||
| sh "docker push ${imageName}" | |||
| sh "docker push ${nginxImageName}" | |||
| } | |||
| } | |||
| stage("[4/4] Deploy"){ | |||
| container('kubectl'){ | |||
| // deploy nginx | |||
| sh "sed -i 's#__IMAGE__#$NGINX_IMAGE_NAME#g' ./config/kubernetes/gq-hello-nginx-deployment.yaml" | |||
| sh "cat ./config/kubernetes/gq-hello-nginx-deployment.yaml" | |||
| sh "kubectl --kubeconfig=/root/.kube/config apply -f ./config/kubernetes/gq-hello-nginx-service.yaml" | |||
| sh "kubectl --kubeconfig=/root/.kube/config apply -f ./config/kubernetes/gq-hello-nginx-ingress.yaml" | |||
| sh "kubectl --kubeconfig=/root/.kube/config apply -f ./config/kubernetes/gq-hello-nginx-deployment.yaml" | |||
| // deploy repo | |||
| sh "sed -i 's#__IMAGE__#$IMAGE_NAME#g' ./config/kubernetes/gq-hello-deployment.yaml" | |||
| sh "cat ./config/kubernetes/gq-hello-deployment.yaml" | |||
| sh "kubectl --kubeconfig=/root/.kube/config apply -f ./config/kubernetes/gq-hello-service.yaml" | |||
| sh "kubectl --kubeconfig=/root/.kube/config apply -f ./config/kubernetes/gq-hello-deployment.yaml" | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,39 @@ | |||
| # gq-hello-deployment.yaml | |||
| # | |||
| # @version 180806:2 | |||
| # @author zhangxuhong <zhangxuhong@xitu.io> | |||
| kind: Deployment | |||
| apiVersion: apps/v1 | |||
| metadata: | |||
| name: gq-hello | |||
| labels: | |||
| name: gq-hello | |||
| role: backend | |||
| pl: php | |||
| application: php | |||
| version: 7.2.9 | |||
| division: infrastructure | |||
| spec: | |||
| replicas: 3 | |||
| selector: | |||
| matchLabels: | |||
| name: gq-hello | |||
| strategy: | |||
| type: RollingUpdate | |||
| rollingUpdate: | |||
| maxUnavailable: 25% | |||
| maxSurge: 25% | |||
| template: | |||
| metadata: | |||
| labels: | |||
| name: gq-hello | |||
| spec: | |||
| containers: | |||
| - name: gq-hello | |||
| image: __IMAGE__ | |||
| imagePullPolicy: Always | |||
| ports: | |||
| - name: gq-hello | |||
| containerPort: 9000 | |||
| protocol: TCP | |||
| @ -0,0 +1,39 @@ | |||
| # gq-hello-nginx-deployment.yaml | |||
| # | |||
| # @version 180806:2 | |||
| # @author zhangxuhong <zhangxuhong@xitu.io> | |||
| kind: Deployment | |||
| apiVersion: apps/v1 | |||
| metadata: | |||
| name: gq-hello-nginx | |||
| labels: | |||
| name: gq-hello-nginx | |||
| role: backend | |||
| pl: c | |||
| application: nginx | |||
| version: 1.14.0 | |||
| division: infrastructure | |||
| spec: | |||
| replicas: 3 | |||
| selector: | |||
| matchLabels: | |||
| name: gq-hello-nginx | |||
| strategy: | |||
| type: RollingUpdate | |||
| rollingUpdate: | |||
| maxUnavailable: 25% | |||
| maxSurge: 25% | |||
| template: | |||
| metadata: | |||
| labels: | |||
| name: gq-hello-nginx | |||
| spec: | |||
| containers: | |||
| - name: gq-hello-nginx | |||
| image: __IMAGE__ | |||
| imagePullPolicy: Always | |||
| ports: | |||
| - name: gq-hello-nginx | |||
| containerPort: 80 | |||
| protocol: TCP | |||
| @ -0,0 +1,26 @@ | |||
| # gq-hello-nginx-ingress.yaml | |||
| # | |||
| # @version: 180627:1 | |||
| # @author: zhangxuhong <zhangxuhong@xitu.io> | |||
| # | |||
| apiVersion: extensions/v1beta1 | |||
| kind: Ingress | |||
| metadata: | |||
| name: gq-hello-nginx | |||
| labels: | |||
| name: gq-hello-nginx | |||
| role: backend | |||
| pl: c | |||
| application: nginx | |||
| version: 1.14.0 | |||
| division: infrastructure | |||
| spec: | |||
| rules: | |||
| - host: gq-hello.juejin.im | |||
| http: | |||
| paths: | |||
| - path: / | |||
| backend: | |||
| serviceName: gq-hello-nginx | |||
| servicePort: 80 | |||
| @ -0,0 +1,24 @@ | |||
| # gq-hello-nginx-service.yaml | |||
| # | |||
| # @version 180719:1 | |||
| # @author zhangxuhong <zhangxuhong@xitu.io> | |||
| kind: Service | |||
| apiVersion: v1 | |||
| metadata: | |||
| name: gq-hello-nginx | |||
| labels: | |||
| name: gq-hello-nginx | |||
| role: backend | |||
| pl: c | |||
| application: nginx | |||
| version: 1.14.0 | |||
| division: infrastructure | |||
| spec: | |||
| ports: | |||
| - port: 80 | |||
| targetPort: gq-hello-nginx | |||
| protocol: TCP | |||
| name: gq-hello-nginx | |||
| selector: | |||
| name: gq-hello-nginx | |||
| @ -0,0 +1,24 @@ | |||
| # gq-hello-service.yaml | |||
| # | |||
| # @version 180719:1 | |||
| # @author zhangxuhong <zhangxuhong@xitu.io> | |||
| kind: Service | |||
| apiVersion: v1 | |||
| metadata: | |||
| name: gq-hello | |||
| labels: | |||
| name: gq-hello | |||
| role: backend | |||
| pl: c | |||
| application: nginx | |||
| version: 1.14.0 | |||
| division: infrastructure | |||
| spec: | |||
| ports: | |||
| - port: 9000 | |||
| targetPort: gq-hello | |||
| protocol: TCP | |||
| name: gq-hello | |||
| selector: | |||
| name: gq-hello | |||
| @ -0,0 +1,71 @@ | |||
| # gq-hello.public.conf | |||
| # gq-hello nginx public config. | |||
| # This api is a [public] api. | |||
| # @version 170624:8 | |||
| # server config | |||
| server { | |||
| listen 80; | |||
| server_name gq-hello.juejin.im; | |||
| # origin sessings | |||
| include /data/apps/nginx/conf/origin/gold.xitu.io_and_juejin.im.conf; | |||
| default_type 'text/plain'; # or browser will download page | |||
| root /data/repo/gq-hello/src/; | |||
| access_log /dev/stdout; | |||
| error_log /dev/stderr; | |||
| client_body_temp_path /data/tmp/nginx/client_body_temp/ 1 2; | |||
| proxy_temp_path /data/tmp/nginx/proxy_temp/ 1 2; | |||
| fastcgi_temp_path /data/tmp/nginx/fastcgi_temp/ 1 2; | |||
| rewrite "^(.*)/v1/sample$" $1/SampleApi.php?$query_string last; | |||
| rewrite "^(.*)/status$" $1/status.php last; | |||
| # global location settings | |||
| location / { | |||
| return 200; | |||
| } | |||
| location = /ENV { | |||
| allow 127.0.0.1; | |||
| deny all; | |||
| } | |||
| location ~* ^/DOCUMENTS{ | |||
| return 404; | |||
| } | |||
| location ~* ^/logs{ | |||
| return 404; | |||
| } | |||
| location ~* ^/src{ | |||
| return 404; | |||
| } | |||
| location ~* ^/config{ | |||
| return 404; | |||
| } | |||
| location = /favicon.ico { | |||
| allow all; | |||
| log_not_found off; | |||
| access_log off; | |||
| } | |||
| location ~ /\. { | |||
| deny all; | |||
| access_log off; | |||
| log_not_found off; | |||
| } | |||
| location ~ \.php$ { | |||
| if ( $fastcgi_script_name ~ \..*\/.*php ) { | |||
| return 403; | |||
| } | |||
| include fastcgi.conf; | |||
| #这里如果是本地测试,要使用docker的ip,还不能解析名称,要使用容器ip,使用hostname -I | |||
| #进入容器要使用docker exec -i -t {dockerId} /bin/sh | |||
| #查看dockerId使用命令docker ps | |||
| fastcgi_pass gq-hello:9000; | |||
| fastcgi_index index.php; | |||
| } | |||
| } | |||
| @ -0,0 +1,21 @@ | |||
| # gq-hello-nginx.dockerfile | |||
| # Dockerfile for demo gq-hello-nginx | |||
| # This docker file base on harbor02.juejin.id/lib/php:7.2.9-fpm-alpine3.8 | |||
| # @version 180719:2 | |||
| # @author zhangxuhong <zhangxuhong@xitu.io> | |||
| # | |||
| # base info | |||
| FROM harbor02.juejin.id/infrastructure/nginx-1.14.0-centos:latest | |||
| MAINTAINER zhangxuhong <zhangxuhong@xitu.io> | |||
| USER root | |||
| # copy config to /data/apps/nginx/conf/vhost/ | |||
| COPY ./config/nginx/ /data/apps/nginx/conf/vhost/ | |||
| # define health check | |||
| HEALTHCHECK --interval=5s --timeout=3s CMD curl -fs http://127.0.0.1:80/status?src=docker_health_check -H"Host:gq-hello.juejin.im" || exit 1 | |||
| # run php-fpm | |||
| EXPOSE 80 | |||
| ENTRYPOINT ["/data/apps/nginx/sbin/nginx", "-g", "daemon off;"] | |||
| @ -0,0 +1,25 @@ | |||
| # gq-hello.dockerfile | |||
| # Dockerfile for demo gq-hello | |||
| # This docker file base on harbor02.juejin.id/lib/php:7.2.9-fpm-alpine3.8 | |||
| # @version 180719:2 | |||
| # @author zhangxuhong <zhangxuhong@xitu.io> | |||
| # | |||
| # base info | |||
| FROM harbor02.juejin.id/infrastructure/php-7.2.9-fpm-alpine3.8:latest | |||
| MAINTAINER zhangxuhong <zhangxuhong@xitu.io> | |||
| USER root | |||
| # init | |||
| # RUN apk add --update --no-cache --virtual .build-deps \ | |||
| # copy repo to /data/repo | |||
| COPY . /data/repo/gq-hello/ | |||
| # define health check | |||
| HEALTHCHECK --interval=5s --timeout=3s CMD netstat -an | grep 9000 > /dev/null; if [ 0 != $? ]; then exit 1; fi; | |||
| # run php-fpm | |||
| EXPOSE 9000 | |||
| ENTRYPOINT ["php-fpm"] | |||
| @ -0,0 +1 @@ | |||
| 1 | |||
| @ -0,0 +1,18 @@ | |||
| <?php | |||
| /** | |||
| * SampleApi.php | |||
| * Api entrance | |||
| * @version 151024:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| */ | |||
| define('PROCESS_NAME', 'index'); | |||
| define('DEBUG', true); | |||
| // controller | |||
| require(dirname(__FILE__).'/protected/controller/BaseController.php'); | |||
| require(dirname(__FILE__).'/protected/controller/SampleController.php'); | |||
| $SampleController = new SampleController; | |||
| $SampleController->run(); | |||
| @ -0,0 +1,50 @@ | |||
| <?php | |||
| /** | |||
| * Main config file. | |||
| * @version 161017:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| */ | |||
| /** | |||
| * set default ini | |||
| */ | |||
| ini_set("date.timezone", "Asia/Harbin"); | |||
| /** | |||
| * product config here | |||
| */ | |||
| $product = array( | |||
| 'global' => array( | |||
| 'global_id' => 'salt_fish_raw_php', | |||
| 'folder' => '/data/repo/salt_fish_raw_php/', | |||
| ), | |||
| 'log' => array( | |||
| 'open' => true, | |||
| 'address' => '/data/repo/salt_fish_raw_php/logs/', // the '/' at end of line is necessary | |||
| 'split' => 'day', // options: month, day, hour, minute | |||
| ), | |||
| 'storage' => array( | |||
| 'sample' => array( | |||
| 'host' => '192.168.0.1', | |||
| 'port' => 3306, | |||
| 'name' => 'sample', | |||
| 'charset' => 'utf8', | |||
| 'user' => 'sample', | |||
| 'pass' => 'sample', | |||
| ), | |||
| ), | |||
| 'cache' => array( | |||
| 'sample_cache' => array( | |||
| 'host' => '192.168.0.1', | |||
| 'port' => 6379, | |||
| 'pass' => null, | |||
| 'database' => 2, | |||
| 'timeout' => 0, | |||
| ), | |||
| ), | |||
| 'mongodb' => array( | |||
| 'sample' => "mongodb://sample:password@192.168.0.1:27017/sample", | |||
| ), | |||
| ); | |||
| @ -0,0 +1,122 @@ | |||
| <?php | |||
| /** | |||
| * BaseController.php | |||
| * Base controller. | |||
| * @version 160823:8 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs | |||
| * 160823:8 REMOVE initFeedback method. | |||
| * 160129:7 ADD checkShutDownSignal(). | |||
| * 151123:6 REFACTORY. | |||
| * 151024:5 REFACTORY. | |||
| * 150824:4 ADD isProcessNumberOverLimit(). | |||
| * 150811:3 CHANGE input method. | |||
| * 150609:2 ADD debugSwitch(). | |||
| * 150520:1 INIT baseController. | |||
| */ | |||
| namespace SaltFish; | |||
| /** | |||
| * abstract class BaseController | |||
| */ | |||
| abstract class BaseController{ | |||
| public $_log; | |||
| public $_feedback; | |||
| /** | |||
| * [__construct description] | |||
| */ | |||
| public function __construct(){ | |||
| $this->debugSwitch(); | |||
| $this->initRequirements(); | |||
| $this->initLog(); | |||
| } | |||
| /** | |||
| * [debugSwitch description] | |||
| * This function set debug info. | |||
| * @param null | |||
| * @return null | |||
| */ | |||
| public function debugSwitch(){ | |||
| if(!defined(DEBUG)){ | |||
| define(DEBUG, false); | |||
| } | |||
| if(DEBUG){ | |||
| ini_set('display_errors', 1); | |||
| error_reporting(E_ALL); | |||
| } | |||
| } | |||
| /** | |||
| * [initRequirements description] | |||
| * This function load main config and all necessary files. | |||
| * @param null | |||
| * @return null | |||
| */ | |||
| public function initRequirements(){ | |||
| // init config | |||
| require(dirname(__FILE__).'/../lib/base/AutoRequire.php'); | |||
| require(dirname(__FILE__).'/../lib/base/Config.php'); | |||
| $conf = require(dirname(__FILE__).'/../config/main.config.php'); | |||
| Config::importMainConfig($conf); | |||
| // load all necessary files | |||
| $class_name = get_class($this); | |||
| $config = AutoRequire::headerArray("{$class_name}.requirements"); | |||
| AutoRequire::classes($config); | |||
| } | |||
| /** | |||
| * [initLog description] | |||
| * This function init log address and echo settings. | |||
| * @param null | |||
| * @return null | |||
| */ | |||
| public function initLog(){ | |||
| $logConfig = Config::get('log'); | |||
| Log::setLogAddress($logConfig['address'], PROCESS_NAME, $logConfig['split']); | |||
| if(DEBUG){ | |||
| Log::setEchoSwitch(Log::ECHO_THE_LOG); | |||
| } | |||
| } | |||
| /** | |||
| * [fetchInput description] | |||
| * @param [type] &$inputException [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function fetchInput(&$inputException){ | |||
| $inputIsOk = Input::getInputByParams( | |||
| $this->input_method, $this->input_param, $this->input, $inputException | |||
| ); | |||
| // check callback | |||
| if(!empty($input['callback'])){ | |||
| $this->output_format = Feedback::FORMAT_JSONP; | |||
| } | |||
| // gen feeedback | |||
| if(!$inputIsOk) return false; | |||
| return true; | |||
| } | |||
| /** | |||
| * [checkShutDownSignal description] | |||
| * @param [type] $signal [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function checkShutDownSignal($signal, $shutdownMessage = 'signal file removed'){ | |||
| if(file_exists($signal)) return; | |||
| Log::message('checkShutDownSignal', 'DETECTED', 'EXIT', $shutdownMessage); | |||
| exit("signal file removed, process shut down.\n"); | |||
| } | |||
| /** | |||
| * [run description] | |||
| * @return [type] [description] | |||
| */ | |||
| public abstract function run(); | |||
| } | |||
| @ -0,0 +1,110 @@ | |||
| <?php | |||
| /** | |||
| * SampleController.php | |||
| * SampleController controller. | |||
| * @version 160901:1 | |||
| * @author karminski karminski@outlook.com> | |||
| * | |||
| * @changes | |||
| * 160901:1 INIT version. | |||
| */ | |||
| /** | |||
| * class SampleController extends BaseController | |||
| */ | |||
| class SampleController extends SaltFish\BaseController{ | |||
| private $_h; | |||
| public $input = array(); // user input data | |||
| public $default_input_method = ''; | |||
| public $output_format = ''; | |||
| public $input_param = array(); | |||
| /** | |||
| * [__construct description] | |||
| */ | |||
| public function __construct(){ | |||
| parent::__construct(); | |||
| } | |||
| /** | |||
| * public function setInputRules | |||
| */ | |||
| public function setInputRules(){ | |||
| $this->default_input_method = SaltFish\Input::METHOD_GET; | |||
| $this->output_format = SaltFish\Feedback::FORMAT_JSON; | |||
| $this->input_param = array( | |||
| array( | |||
| 'param' => 'uid', | |||
| 'condition' => array( | |||
| 'method' => null, | |||
| 'type' => SaltFish\Input::TYPE_INT, | |||
| 'limit' => array(), | |||
| 'default' => 0, | |||
| 'necessary' => true, | |||
| ), | |||
| ), | |||
| ); | |||
| SaltFish\Feedback::setOutputFormat($this->output_format); | |||
| SaltFish\Feedback::setCallback(null); | |||
| } | |||
| /** | |||
| * [initDatabase description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function initDatabase(){ | |||
| $this->SampleCache = new SampleCache; | |||
| $this->SampleMongoDBStorage = new SampleMongoDBStorage; | |||
| $this->SampleMySQLStorage = new SampleMySQLStorage; | |||
| } | |||
| /** | |||
| * [run description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function run(){ | |||
| // init | |||
| $Log = $this->_log; | |||
| // get user input | |||
| $exception = array(); | |||
| $this->setInputRules(); | |||
| if(!SaltFish\Input::get($this->default_input_method, $this->input_param, $this->input, $exception)){ | |||
| $feed = SaltFish\Feedback::getFeed(FeedbackInfo::S_WRONG_INPUT, $exception, array()); | |||
| BaseView::renderJson($feed); | |||
| return false; | |||
| } | |||
| // init request, result | |||
| $SampleRequest = new SampleRequest($this->input); | |||
| $SampleResult = new SampleResult; | |||
| // check access token | |||
| // if(SaltFish\AccessibilityCheck::isIllegalToken($SampleRequest)){ | |||
| // $feed = SaltFish\Feedback::getFeed(FeedbackInfo::S_WRONG_INPUT, FeedbackInfo::M_ILLEGAL_TOKEN, array()); | |||
| // BaseView::renderJson($feed); | |||
| // return false; | |||
| // } | |||
| // init database | |||
| $this->initDatabase(); | |||
| // sample 1 : get data from cache | |||
| if(!$this->SampleCache->get($SampleRequest, $SampleResult)){ | |||
| $feed = SaltFish\Feedback::getFeed(FeedbackInfo::S_NO_RESULT, FeedbackInfo::M_NO_RESULT, array()); | |||
| BaseView::renderJson($feed); | |||
| return false; | |||
| } | |||
| // ok, feedback | |||
| $feedData = array(); | |||
| $SampleResult->exportForFeedback($feedData); | |||
| $feed = SaltFish\Feedback::getFeed(FeedbackInfo::S_OK, FeedbackInfo::M_OK, $feedData); | |||
| BaseView::renderJson($feed); | |||
| return true; | |||
| } | |||
| } | |||
| @ -0,0 +1,48 @@ | |||
| <?php | |||
| /** | |||
| * SampleController.requirements.h.php | |||
| * @version 150831:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| */ | |||
| return array( | |||
| 'config' => array( | |||
| 'main.config' | |||
| ), | |||
| 'lib' => array( | |||
| 'base/Log', | |||
| 'base/Feedback', | |||
| 'base/Input', | |||
| 'base/AccessibilityCheck', | |||
| 'network/Curl', | |||
| 'encrypt/Encrypt', | |||
| 'cache/RedisFactory', | |||
| 'cache/RedisProxy', | |||
| 'storage/File', | |||
| 'storage/FluentPDO', | |||
| 'storage/MysqlFactory', | |||
| 'storage/MysqlProxy', | |||
| 'storage/MongoDBFactory', | |||
| ), | |||
| 'controller' => array( | |||
| ), | |||
| 'model' => array( | |||
| 'FeedbackInfo', | |||
| 'Request', | |||
| 'Result', | |||
| 'ApiProxy', | |||
| 'SampleCache', | |||
| 'SampleMongoDBStorage', | |||
| 'SampleMySQLStorage', | |||
| 'SampleApiProxy', | |||
| 'SampleRequest', | |||
| 'SampleResult', | |||
| ), | |||
| 'views' => array( | |||
| 'BaseView', | |||
| ), | |||
| ); | |||
| @ -0,0 +1,13 @@ | |||
| <?php | |||
| /** | |||
| * public_key.h.php | |||
| * @version 151024:2 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| */ | |||
| return array( | |||
| "default" => "PV0XRWUebytdO8c9QhET", | |||
| "tester" => "kvYgJ19P3DW4mRcfNO0u", | |||
| "example" => "GBk3UAbh5SefRZsnwj2T", | |||
| ); | |||
| @ -0,0 +1,256 @@ | |||
| <?php | |||
| /** | |||
| * TrieTree.php | |||
| * Algorithm Trie-tree php implementation. | |||
| * @version 150609:4 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changes | |||
| * 150609:4 fix reference issue, ADD importTree() retval. | |||
| * 150528:3 add subContain(). | |||
| */ | |||
| /** | |||
| * class TrieTree | |||
| */ | |||
| class TrieTree{ | |||
| // const | |||
| const SHORT_SEARCH = true; | |||
| const NOT_SHORT_SEARCH = false; | |||
| // properties | |||
| public $tree = array(); | |||
| /** | |||
| * [flushTree description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function flushTree(){ | |||
| $this->tree = array(); | |||
| } | |||
| /** | |||
| * [importTree description] | |||
| * @param [type] $tree [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function importTree(&$tree){ | |||
| $this->tree = $tree; | |||
| if(empty($this->tree)) return false; | |||
| return true; | |||
| } | |||
| /** | |||
| * [exportTree description] | |||
| * @param [type] $tree [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function exportTree(){ | |||
| return $this->tree; | |||
| } | |||
| /** | |||
| * [insertAll description] | |||
| * @param [type] $data [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function insertAll($data){ | |||
| foreach($data as $line){ | |||
| $this->insert($line['word'], explode(",", $line['type'])); | |||
| } | |||
| } | |||
| /** | |||
| * [insert description] | |||
| * @param [type] $utf8_str [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function insert($utf8_str = "", $type = array()){ | |||
| // unset empty type | |||
| foreach($type as $serial => $line){ | |||
| if(empty($line)){ | |||
| unset($type[$serial]); | |||
| } | |||
| } | |||
| // insert tree | |||
| $chars = String::utf8Split(trim($utf8_str)); | |||
| $chars[] = null; // null for end of thread | |||
| $count = count($chars); | |||
| $T = &$this->tree; | |||
| $last = $count-1; | |||
| for($i = 0;$i < $count;$i++){ | |||
| $c = $chars[$i]; | |||
| if(!array_key_exists($c, $T)){ | |||
| $T[$c] = array(); // insert new char | |||
| } | |||
| // fill type | |||
| if($i === $last){ | |||
| $T['__type'] = $type; | |||
| } | |||
| $T = &$T[$c]; | |||
| } | |||
| } | |||
| /** | |||
| * [remove description] | |||
| * @param [type] $utf8_str [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function remove($utf8_str){ | |||
| $chars = String::utf8Split($utf8_str); | |||
| $chars[] = null; | |||
| if($this->_find($chars)){ // match the head char | |||
| $chars[] = null; | |||
| $count = count($chars); | |||
| $T = &$this->tree; | |||
| for($i = 0;$i < $count;$i++){ | |||
| $c = $chars[$i]; | |||
| if(count($T[$c]) == 1){ // only this thread | |||
| unset($T[$c]); | |||
| return; | |||
| } | |||
| $T = &$T[$c]; | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * [_find description] | |||
| * @param [type] &$chars [description] | |||
| * @return [type] [description] | |||
| */ | |||
| private function _find(&$chars){ | |||
| $string = ""; | |||
| $count = count($chars); | |||
| $T = &$this->tree; | |||
| for($i = 0;$i < $count;$i++){ | |||
| $c = $chars[$i]; | |||
| if(empty($c)){ | |||
| return explode(",", $this->recrusiveStr($T, $string)); | |||
| } | |||
| $T = &$T[$c]; | |||
| $string .= $c; | |||
| } | |||
| return $string; | |||
| } | |||
| /** | |||
| * [recrusiveStr description] | |||
| * @param [type] $tree [description] | |||
| * @param [type] $results [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function recrusiveStr($tree, $results){ | |||
| if(empty($tree)) return false; | |||
| $r = ""; | |||
| foreach($tree as $key => $subTree){ | |||
| $results .= $key; | |||
| if(empty($subTree)) return $results.","; | |||
| $r .= $this->recrusiveStr($subTree, $results); | |||
| } | |||
| return $r; | |||
| } | |||
| /** | |||
| * [find description] | |||
| * @param [type] $utf8_str [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function find($utf8_str){ | |||
| $chars = String::utf8Split($utf8_str); | |||
| $chars[] = null; | |||
| return $this->_find($chars); | |||
| } | |||
| /** | |||
| * [subContain description] | |||
| * @param [type] &$chars [description] | |||
| * @param [type] $len [description] | |||
| * @param [type] &$Tree [description] | |||
| * @param [type] &$hit_tmp [description] | |||
| * @param [type] &$hit_words [description] | |||
| * @param [type] $short_search [description] | |||
| * @return [type] [description] | |||
| */ | |||
| private static function subContain(&$chars, $len, &$Tree, &$hit_tmp, &$hit_words, $short_search){ | |||
| for($i = 0; $i<$len; $i++){ | |||
| $c = $chars[$i]; | |||
| if(array_key_exists($c, $Tree)){ | |||
| $T = &$Tree[$c]; | |||
| for($j = $i + 1;$j < $len;$j++){ | |||
| $c = $chars[$j]; | |||
| $hit_tmp[] = $chars[$j-1]; | |||
| // if end match | |||
| if(array_key_exists(null, $T)){ | |||
| $hitWord = implode("", $hit_tmp); | |||
| if(!empty($hit_words[$hitWord])){ | |||
| $hit_words[$hitWord]['hits'] ++; | |||
| }else{ | |||
| $hit_words[$hitWord] = array( | |||
| 'hits' => 1, | |||
| 'type' => $T['__type'], | |||
| ); | |||
| } | |||
| if($short_search){ | |||
| $hit_tmp = array(); | |||
| return true; | |||
| } | |||
| } | |||
| // if wildcard | |||
| if(array_key_exists(" ", $T)){ | |||
| $T = &$T[" "]; | |||
| $hit_tmp[] = " "; | |||
| self::subContain($chars, $len, $T, $hit_tmp, $hit_words, true); | |||
| $hit_tmp = array(); | |||
| continue; | |||
| } | |||
| // if miss match | |||
| if(!array_key_exists($c, $T)){ | |||
| array_pop($hit_tmp); | |||
| break; | |||
| } | |||
| $T = &$T[$c]; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * [contain description] | |||
| * @param [type] $utf8_str [description] | |||
| * @param integer $do_count [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function contain($utf8_str, &$hit_words = array(), $short_search = false){ | |||
| $chars = String::utf8Split($utf8_str); | |||
| $chars[] = null; | |||
| $len = count($chars); | |||
| $Tree = &$this->tree; | |||
| $count = 0; | |||
| $totalLoop = 0; | |||
| $hit_tmp = array(); | |||
| self::subContain($chars, $len, $Tree, $hit_tmp, $hit_words, $short_search); | |||
| if(!empty($hit_words)){ | |||
| return true; | |||
| }else{ | |||
| return false; | |||
| } | |||
| } | |||
| /** | |||
| * [containAll description] | |||
| * @param [type] $str_array [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function containAll($str_array){ | |||
| foreach($str_array as $str){ | |||
| if($this->contain($str)){ | |||
| return true; | |||
| } | |||
| } | |||
| return false; | |||
| } | |||
| } | |||
| @ -0,0 +1,132 @@ | |||
| <?php | |||
| /** | |||
| * AccessibilityCheck.php | |||
| * Accessibility check model. | |||
| * @version 160908:4 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs | |||
| * 160908:4 ADD generatePayload(). | |||
| * 160823:3 CHANGE string serialize method. | |||
| * 151024:2 REFACTORY | |||
| * 151020:1 INIT version. | |||
| */ | |||
| namespace SaltFish; | |||
| /** | |||
| * class AccessibilityCheck | |||
| */ | |||
| class AccessibilityCheck{ | |||
| const PUBLIC_KEY_FILE = 'public_key'; | |||
| const DEFAULT_PUBLIC_KEY = 'default'; | |||
| const DEFAULT_EXPIRE = 3; // minutes | |||
| private static $instance; | |||
| private $publicKey = ""; | |||
| /** | |||
| * [__construct description] | |||
| */ | |||
| private function __construct(){ | |||
| $this->loadHeaderFile(); | |||
| } | |||
| /** | |||
| * [getInstance description] | |||
| * @param null | |||
| * @return Log $instance | |||
| */ | |||
| public static function getInstance(){ | |||
| if(empty(self::$instance)){ | |||
| self::$instance = new AccessibilityCheck; | |||
| } | |||
| return self::$instance; | |||
| } | |||
| /** | |||
| * [loadHeaderFile description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function loadHeaderFile(){ | |||
| $this->publicKey = AutoRequire::headerArray(self::PUBLIC_KEY_FILE); | |||
| return true; | |||
| } | |||
| /** | |||
| * [getPublicKey description] | |||
| * @param [type] $src [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function getPublicKey($src){ | |||
| $instance = self::getInstance(); | |||
| if(empty($instance->publicKey[$src])) return $instance->publicKey[self::DEFAULT_PUBLIC_KEY]; | |||
| return $instance->publicKey[$src]; | |||
| } | |||
| /** | |||
| * [generatePayload description] | |||
| * @param [type] $data [description] | |||
| * @param [type] $public_key [description] | |||
| * @param integer $expire [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function generatePayload($data, $public_key, $expire = self::DEFAULT_EXPIRE){ | |||
| ksort($data); | |||
| $str = ""; | |||
| $str .= json_encode($data); | |||
| $str .= $public_key; | |||
| $payloads = array(); | |||
| if(empty($expire)){ | |||
| return array( | |||
| 0 => $str, | |||
| ); | |||
| } | |||
| $start = -floor($expire * 0.5); | |||
| for($i=$start;$i<=-$start;$i++){ | |||
| if($i!==0){ | |||
| $payloads[] = $str.strtotime(date("Y-m-d H:i:00", strtotime("{$i} minute"))); | |||
| }else{ | |||
| $payloads[] = $str.strtotime(date("Y-m-d H:i:00")); | |||
| } | |||
| } | |||
| return $payloads; | |||
| } | |||
| /** | |||
| * [generateToken description] | |||
| * @param [type] $data [description] | |||
| * @param [type] $public_key [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function generateToken($data, $public_key){ | |||
| ksort($data); | |||
| $str = ""; | |||
| $str .= json_encode($data); | |||
| $str .= $public_key; | |||
| $str .= strtotime(date("Y-m-d H:i:00")); | |||
| return Encrypt::hash($str); | |||
| } | |||
| /** | |||
| * [isIllegalToken description] | |||
| * @param Request $Request [description] | |||
| * @return boolean [description] | |||
| */ | |||
| public static function isIllegalToken(\Request $Request){ | |||
| $instance = self::getInstance(); | |||
| $data = array(); | |||
| $token = ""; | |||
| $src = ""; | |||
| $Request->exportForAccessibilityCheck($data); | |||
| $token = $Request->getToken(); | |||
| $src = $Request->getSrc(); | |||
| $payloads = self::generatePayload($data, self::getPublicKey($src)); | |||
| foreach($payloads as $payload){ | |||
| if(Encrypt::matchMd5($payload, $token)) return false; | |||
| } | |||
| return true; | |||
| } | |||
| } | |||
| @ -0,0 +1,67 @@ | |||
| <?php | |||
| /** | |||
| * AutoRequire.php | |||
| * auto require lib. | |||
| * @version 151123:3 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs | |||
| * 151123:3 CHNAGE function name. | |||
| * 150609:2 FIX _header_array(), _header_json() require file name issue. | |||
| * 150520:1 INIT commit. | |||
| */ | |||
| namespace SaltFish; | |||
| /** | |||
| * CLASS AutoRequire | |||
| */ | |||
| class AutoRequire{ | |||
| /** | |||
| * [basedir description] | |||
| * @param null | |||
| * @return string basedir | |||
| */ | |||
| private static function basedir(){ | |||
| return dirname(__FILE__).'/../../'; | |||
| } | |||
| /** | |||
| * [classes description] | |||
| * @param array $classes, required class type and name | |||
| * @return null | |||
| */ | |||
| public static function classes( | |||
| $classes = array('type' => array('name_1', 'name_2')) | |||
| ){ | |||
| $basedir = self::basedir(); | |||
| foreach($classes as $type => $names){ | |||
| if(empty($names)) continue; | |||
| foreach($names as $name){ | |||
| require("{$basedir}{$type}/{$name}.php"); | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * [headerArray description] | |||
| * @param string $name, config name | |||
| * @return array h, in file array | |||
| */ | |||
| public static function headerArray($name = ''){ | |||
| $basedir = self::basedir(); | |||
| return require("{$basedir}h/{$name}.h.php"); | |||
| } | |||
| /** | |||
| * [headerJson description] | |||
| * @param string $name, config name | |||
| * @return array h, in file array | |||
| */ | |||
| public static function headerJson($name = ''){ | |||
| $basedir = self::basedir(); | |||
| return json_decode(require("{$basedir}h/{$name}.h.json"), true); | |||
| } | |||
| } | |||
| @ -0,0 +1,72 @@ | |||
| <?php | |||
| /** | |||
| * Config.php | |||
| * For config fetch. | |||
| * @version 151123:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changes | |||
| * 151123:1 INIT commit. | |||
| */ | |||
| namespace SaltFish; | |||
| /** | |||
| * CLASS Config | |||
| */ | |||
| class Config{ | |||
| private static $instance; | |||
| private $main; | |||
| private $h; | |||
| private function __construct(){ | |||
| } | |||
| /** | |||
| * [importMainConfig description] | |||
| * @param array $main, main config array | |||
| * @return null | |||
| */ | |||
| public static function importMainConfig(&$main){ | |||
| $instance = self::getInstance(); | |||
| $instance->main = &$main; | |||
| } | |||
| /** | |||
| * [get description] | |||
| * @param string $field_name, main config field name | |||
| * @return array config | |||
| */ | |||
| public static function get($field_name = ''){ | |||
| $instance = self::getInstance(); | |||
| return $instance->main[$field_name]; | |||
| } | |||
| /** | |||
| * [getHeader description] | |||
| * @param string $name, header file name | |||
| * @return array h, header array | |||
| */ | |||
| public static function getHeader($name = ''){ | |||
| $instance = self::getInstance(); | |||
| if(empty($instance->h[$name])){ | |||
| $instance->h[$name] = AutoRequire::headerArray($name); | |||
| } | |||
| return $instance->h[$name]; | |||
| } | |||
| /** | |||
| * [getInstance description] | |||
| * @param null | |||
| * @return Config $instance | |||
| */ | |||
| public static function getInstance(){ | |||
| if(empty(self::$instance)){ | |||
| self::$instance = new Config; | |||
| } | |||
| return self::$instance; | |||
| } | |||
| } | |||
| @ -0,0 +1,150 @@ | |||
| <?php | |||
| /** | |||
| * Feedback.php | |||
| * Feedback message. | |||
| * @version 160823:10 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs | |||
| * 160823:10 CHANGE to singleton. | |||
| * 151024:9 REFACTORY. | |||
| * 150811:8 ADD raw result format. | |||
| * 150520:7 old version. | |||
| * | |||
| */ | |||
| namespace SaltFish; | |||
| /** | |||
| * class Feedback | |||
| */ | |||
| class Feedback{ | |||
| // const | |||
| const SIGNAL = 's'; | |||
| const MESSAGE = 'm'; | |||
| const DATA = 'd'; | |||
| const M_OK = 'ok'; | |||
| const FORMAT_RAW = 'raw'; | |||
| const FORMAT_JSON = 'json'; | |||
| const FORMAT_JSONP = 'jsonp'; | |||
| const FORMAT_SERIALIZE = 'serialize'; | |||
| private static $instance; | |||
| public $output_format = self::FORMAT_JSON; | |||
| public $callback = ''; | |||
| public static $result_tmpl = array( | |||
| self::SIGNAL => false, | |||
| self::MESSAGE => self::M_OK, | |||
| self::DATA => array(), | |||
| ); | |||
| /** | |||
| * [__construct description] | |||
| */ | |||
| private function __construct(){ | |||
| return; | |||
| } | |||
| /** | |||
| * [getInstance description] | |||
| * @param null | |||
| * @return Log $instance | |||
| */ | |||
| public static function getInstance(){ | |||
| if(empty(self::$instance)){ | |||
| self::$instance = new Feedback; | |||
| } | |||
| return self::$instance; | |||
| } | |||
| /** | |||
| * [setOutputFormat description] | |||
| * @param [type] $output_format [description] | |||
| */ | |||
| public static function setOutputFormat($output_format = self::FORMAT_JSON){ | |||
| $instance = self::getInstance(); | |||
| $instance->output_format = $output_format; | |||
| return; | |||
| } | |||
| /** | |||
| * [setCallback description] | |||
| * @param string $callback [description] | |||
| */ | |||
| public static function setCallback($callback = ''){ | |||
| $instance = self::getInstance(); | |||
| $instance->callback = $callback; | |||
| return; | |||
| } | |||
| /** | |||
| * [resultTransfer description] | |||
| * You can define your return format status field in here | |||
| * @param [type] $result [description] | |||
| * @return [type] [description] | |||
| */ | |||
| private static function resultTransfer($result){ | |||
| if(is_numeric($result)) return $result; | |||
| if(!empty($result)){ | |||
| return true; | |||
| }else{ | |||
| return false; | |||
| } | |||
| } | |||
| /** | |||
| * [returnFromat description] | |||
| * this method leave format param for extension on future | |||
| * @param [type] $data [description] | |||
| * @param [type] $format [description] | |||
| * @param string $callback [description] | |||
| * @return [type] [description] | |||
| */ | |||
| private static function returnFromat( | |||
| &$data, $format = self::FORMAT_JSON, $callback = '' | |||
| ){ | |||
| if($format === self::FORMAT_JSON){ | |||
| return json_encode($data); | |||
| }elseif($format === self::FORMAT_JSONP||!empty($callback)){ | |||
| $data = json_encode($data); | |||
| $callback = urlencode($callback); | |||
| return "{$callback}($data)"; | |||
| }elseif($format === self::FORMAT_SERIALIZE){ | |||
| return serialize($data); | |||
| }elseif($format === self::FORMAT_RAW){ | |||
| return $data; | |||
| } | |||
| } | |||
| /** | |||
| * [getFeed description] | |||
| * @param boolean $result [description] | |||
| * @param array $message [description] | |||
| * @param array $data [description] | |||
| * @param [type] $format [description] | |||
| * @param string $callback [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function getFeed( | |||
| $result = false, | |||
| $message = array(), | |||
| $data = array() | |||
| ){ | |||
| $instance = self::getInstance(); | |||
| $result = self::resultTransfer($result); | |||
| $r = self::$result_tmpl; | |||
| $r[self::SIGNAL] = $result; | |||
| if(!empty($message)){ | |||
| $r[self::MESSAGE] = $message; | |||
| } | |||
| if(!empty($data)){ | |||
| $r[self::DATA] = &$data; | |||
| } | |||
| return self::returnFromat($r, $instance->output_format, $instance->callback); | |||
| } | |||
| } | |||
| @ -0,0 +1,155 @@ | |||
| <?php | |||
| /** | |||
| * Input.php | |||
| * Base input class. | |||
| * @version 160204:11 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| */ | |||
| namespace SaltFish; | |||
| /** | |||
| * class Input | |||
| */ | |||
| class Input{ | |||
| // input method | |||
| const METHOD_GET = 'get'; | |||
| const METHOD_POST = 'post'; | |||
| const METHOD_ARGV = 'argv'; | |||
| const METHOD_HTTP = 'http'; | |||
| // input types | |||
| const TYPE_INT = 'int'; | |||
| const TYPE_STRING = 'string'; | |||
| const TYPE_ENUM = 'enum'; | |||
| const TYPE_ARRAY = 'array'; | |||
| const TYPE_BOOLEAN = 'array'; | |||
| /** | |||
| * [getInputByMethod description] | |||
| * get and fill default value when input empty. | |||
| * @param [type] $method [description] | |||
| * @param [type] $param [description] | |||
| * @param [type] $default [description] | |||
| * @return mixed, input data | |||
| */ | |||
| private static function getInputByMethod($method, $param, $default){ | |||
| if($method === self::METHOD_GET){ | |||
| return empty($_GET[$param]) ? $default : $_GET[$param]; | |||
| }elseif($method === self::METHOD_POST){ | |||
| return empty($_POST[$param]) ? $default : $_POST[$param]; | |||
| }elseif($method === self::METHOD_HTTP){ | |||
| $post = empty($_POST[$param]) ? null : $_POST[$param]; | |||
| if(empty($post)){ | |||
| return empty($_GET[$param]) ? $default : $_GET[$param]; | |||
| } | |||
| return $post; | |||
| }elseif($method === self::METHOD_ARGV){ | |||
| $argvInput = getopt(false, array("{$param}:")); | |||
| return empty($argvInput[$param]) ? $default : $argvInput[$param]; | |||
| } | |||
| } | |||
| /** | |||
| * [isMissing description] | |||
| * @param [type] &$data [description] | |||
| * @param [type] $necessary [description] | |||
| * @return boolean [description] | |||
| */ | |||
| private static function isMissing(&$data, $necessary){ | |||
| if($necessary && !isset($data)) return true; | |||
| return false; | |||
| } | |||
| /** | |||
| * [isIllegal description] | |||
| * @param [type] &$data [description] | |||
| * @param [type] &$condition [description] | |||
| * @return boolean [description] | |||
| */ | |||
| private static function isIllegal(&$data, &$condition){ | |||
| $type = $condition['type']; | |||
| if($type === self::TYPE_INT){ | |||
| $data = (int)$data; | |||
| if(!empty($condition['limit'])){ | |||
| if(isset($condition['limit']['min'])){ | |||
| if($data < $condition['limit']['min']) return true; | |||
| } | |||
| if(isset($condition['limit']['max'])){ | |||
| if($data > $condition['limit']['max']) return true; | |||
| } | |||
| } | |||
| }elseif($type === self::TYPE_STRING){ | |||
| if(!empty($condition['limit'])){ | |||
| $len = strlen($data); | |||
| if(isset($condition['limit']['min'])){ | |||
| if($len < $condition['limit']['min']) return true; | |||
| } | |||
| if(isset($condition['limit']['max'])){ | |||
| if($len > $condition['limit']['max']) return true; | |||
| } | |||
| } | |||
| }elseif($type === self::TYPE_ENUM){ | |||
| if(!empty($condition['options'])){ | |||
| $enums = array(); | |||
| foreach($condition['options'] as $avaliable_value){ | |||
| $enums[$avaliable_value] = true; | |||
| } | |||
| if(empty($enums[$data])) return true; | |||
| } | |||
| }elseif($type === self::TYPE_ARRAY){ | |||
| $subCondition = $condition; | |||
| $subCondition['type'] = $condition['sub_type']; | |||
| if(self::isIllegal($line, $subCondition)) return true; | |||
| }elseif($type === self::TYPE_BOOLEAN){ | |||
| if(!isset($ata)) return true; | |||
| } | |||
| return false; | |||
| } | |||
| /** | |||
| * [get description] | |||
| * @param [type] $default_input_method [description] | |||
| * @param array &$input_param [description] | |||
| * @param array &$result [description] | |||
| * @param array &$exception [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function get( | |||
| $default_input_method = self::METHOD_HTTP, | |||
| &$input_param = array(), | |||
| &$result = array(), | |||
| &$exception = array() | |||
| ){ | |||
| $isMissing = false; | |||
| $isIllegal = false; | |||
| $exception = array( | |||
| 'missing' => array(), | |||
| 'illegal' => array(), | |||
| ); | |||
| foreach($input_param as $line){ | |||
| $param = &$line['param']; | |||
| $condition = &$line['condition']; | |||
| // check method | |||
| $method = empty($condition['method']) ? $default_input_method : $condition['method']; | |||
| // get and fill default value when input empty. | |||
| $result[$param] = self::getInputByMethod($method, $param, $condition['default']); | |||
| // check necessary | |||
| if(self::isMissing($result[$param], $condition['necessary'])){ | |||
| $isMissing = true; | |||
| $exception['missing'] = $param; | |||
| } | |||
| // check illegal | |||
| if(self::isIllegal($result[$param], $condition)){ | |||
| $isIllegal = true; | |||
| $exception['illegal'] = $param; | |||
| } | |||
| } | |||
| if($isMissing||$isIllegal) return false; | |||
| return true; | |||
| } | |||
| } | |||
| @ -0,0 +1,198 @@ | |||
| <?php | |||
| /** | |||
| * Log.php | |||
| * Log something. | |||
| * @version 151231:8 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs 151231:8 ADD writeRaw(). | |||
| * 151123:7 ADD getInstance(). | |||
| * 151024:6 RENAME. | |||
| * 150831:5 ADD process name. | |||
| * 150826:4 ADD uniqid | |||
| * 150609:3 ADD echoSwitch(). | |||
| * 140626:2 INIT base log. | |||
| * | |||
| * @example | |||
| * | |||
| * exec: | |||
| * Log::error("somefunction()", "failed to exec", "jump", array('return' => false)); | |||
| * then will write to log: | |||
| * 0000-00-00 00:00:00 <-ERROR-> [somefunction()] [failed to exec] [jump] return: false \n | |||
| */ | |||
| namespace SaltFish; | |||
| /** | |||
| * class Log | |||
| */ | |||
| class Log{ | |||
| const SIGNAL_OK = ' O K '; | |||
| const SIGNAL_BAD = ' BAD '; | |||
| const SIGNAL_MESSAGE = 'MESSAGE'; | |||
| const SIGNAL_WARING = 'WARING!'; | |||
| const SIGNAL_ERROR = '-ERROR-'; | |||
| const SIGNAL_FATAL = '-FATAL-'; | |||
| const ECHO_THE_LOG = true; | |||
| const DO_NOT_ECHO_THE_LOG = false; | |||
| private static $instance; | |||
| private $logAddress = ''; | |||
| private $echoSwitch = false; | |||
| private function __construct(){ | |||
| } | |||
| /** | |||
| * [getInstance description] | |||
| * @param null | |||
| * @return Log $instance | |||
| */ | |||
| public static function getInstance(){ | |||
| if(empty(self::$instance)){ | |||
| self::$instance = new Log; | |||
| } | |||
| return self::$instance; | |||
| } | |||
| /** | |||
| * [setLogAddress description] | |||
| * @param string $addr | |||
| * @param string $logName | |||
| * @param string $split, log split method | |||
| */ | |||
| public static function setLogAddress($addr = '', $logName = '', $split = ''){ | |||
| $instance = self::getInstance(); | |||
| if($split === 'year'){ | |||
| $suffix = date("Y"); | |||
| }elseif($split === 'month'){ | |||
| $suffix = date("Ym"); | |||
| }elseif($split === 'day'){ | |||
| $suffix = date("Ymd"); | |||
| }elseif($split === 'hour'){ | |||
| $suffix = date("YmdH"); | |||
| }elseif($split === 'minute'){ | |||
| $suffix = date("YmdHi"); | |||
| }elseif($split === 'second'){ | |||
| $suffix = date("YmdHis"); | |||
| }else{ | |||
| $suffix = ''; | |||
| } | |||
| $instance->logAddress = $addr.$logName.".".$suffix.".".uniqid().".log"; | |||
| } | |||
| /** | |||
| * [setEchoSwitch description] | |||
| * @param boolean $switch, set true to print log | |||
| */ | |||
| public static function setEchoSwitch($switch = false){ | |||
| $instance = self::getInstance(); | |||
| $instance->echoSwitch = $switch; | |||
| } | |||
| /** | |||
| * [writeLog description] | |||
| * @param [type] $signal [description] | |||
| * @param string $action [description] | |||
| * @param string $ret_info [description] | |||
| * @param string $process [description] | |||
| * @param array $dump [description] | |||
| * @return [type] [description] | |||
| */ | |||
| private static function writeLog($signal, $action = '', $ret_info = '', $process = '', $dump = array()){ | |||
| $instance = self::getInstance(); | |||
| $timestamp = date("Y-m-d H:i:s"); | |||
| $dump = serialize($dump); | |||
| error_log("{$timestamp} <{$signal}>\t[{$action}]\t[{$ret_info}][{$process}] {$dump} \n", 3, $instance->logAddress); | |||
| if($instance->echoSwitch){ | |||
| echo("{$timestamp} <{$signal}>\t[{$action}]\t[{$ret_info}][{$process}] {$dump} \n"); | |||
| } | |||
| } | |||
| /** | |||
| * [writeRaw description] | |||
| * @param [type] &$line [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function writeRaw(&$line){ | |||
| $instance = self::getInstance(); | |||
| error_log($line+"\n", 3, $instance->logAddress); | |||
| } | |||
| /** | |||
| * [ok description] | |||
| * @param string $action [description] | |||
| * @param string $ret_info [description] | |||
| * @param string $process [description] | |||
| * @param array $dump [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function ok($action = '', $ret_info = '', $process = '', $dump = array()){ | |||
| self::writeLog(self::SIGNAL_OK , $action, $ret_info, $process, $dump); | |||
| } | |||
| /** | |||
| * [bad description] | |||
| * @param string $action [description] | |||
| * @param string $ret_info [description] | |||
| * @param string $process [description] | |||
| * @param array $dump [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function bad($action = '', $ret_info = '', $process = '', $dump = array()){ | |||
| self::writeLog(self::SIGNAL_BAD , $action, $ret_info, $process, $dump); | |||
| } | |||
| /** | |||
| * [message description] | |||
| * @param string $action [description] | |||
| * @param string $ret_info [description] | |||
| * @param string $process [description] | |||
| * @param array $dump [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function message($action = '', $ret_info = '', $process = '', $dump = array()){ | |||
| self::writeLog(self::SIGNAL_MESSAGE , $action, $ret_info, $process, $dump); | |||
| } | |||
| /** | |||
| * [waring description] | |||
| * @param string $action [description] | |||
| * @param string $ret_info [description] | |||
| * @param string $process [description] | |||
| * @param array $dump [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function waring($action = '', $ret_info = '', $process = '', $dump = array()){ | |||
| self::writeLog(self::SIGNAL_WARING , $action, $ret_info, $process, $dump); | |||
| } | |||
| /** | |||
| * [error description] | |||
| * @param string $action [description] | |||
| * @param string $ret_info [description] | |||
| * @param string $process [description] | |||
| * @param array $dump [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function error($action = '', $ret_info = '', $process = '', $dump = array()){ | |||
| self::writeLog(self::SIGNAL_ERROR , $action, $ret_info, $process, $dump); | |||
| } | |||
| /** | |||
| * [fatal description] | |||
| * @param string $action [description] | |||
| * @param string $ret_info [description] | |||
| * @param string $process [description] | |||
| * @param array $dump [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function fatal($action = '', $ret_info = '', $process = '', $dump = array()){ | |||
| self::writeLog(self::SIGNAL_FATAL , $action, $ret_info, $process, $dump); | |||
| exit(); | |||
| } | |||
| } | |||
| @ -0,0 +1,130 @@ | |||
| <?php | |||
| /** | |||
| * ObjectArray.php | |||
| * ObjectArray class, operate Object as array, implement by SPL. | |||
| * @version 151201:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs | |||
| * 151201:1 INIT version. | |||
| */ | |||
| namespace SaltFish; | |||
| /** | |||
| * abstract class ObjectArray implements ArrayAccess, Iterator | |||
| */ | |||
| abstract class ObjectArray implements ArrayAccess, Iterator{ | |||
| private $valid = false; | |||
| private $data; | |||
| /** | |||
| * [__construct description] | |||
| * @param array &$data [description] | |||
| */ | |||
| public function __construct(&$data = array()){ | |||
| $this->import($data); | |||
| } | |||
| /** | |||
| * [import description] | |||
| * @param array &$data [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function import(&$data = array()){ | |||
| $this->data = $data; | |||
| } | |||
| /** | |||
| * [exportRaw description] | |||
| * @param [type] &$data [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function exportRaw(&$data){ | |||
| $data = $this->data; | |||
| } | |||
| /** | |||
| * [offsetSet description] | |||
| * @param [type] $offset [description] | |||
| * @param [type] $value [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function offsetSet($offset, $value){ | |||
| if(is_null($offset)){ | |||
| $this->data[] = $value; | |||
| }else{ | |||
| $this->data[$offset] = $value; | |||
| } | |||
| } | |||
| /** | |||
| * [offsetExists description] | |||
| * @param [type] $offset [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function offsetExists($offset){ | |||
| return isset($this->data[$offset]); | |||
| } | |||
| /** | |||
| * [offsetUnset description] | |||
| * @param [type] $offset [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function offsetUnset($offset){ | |||
| unset($this->data[$offset]); | |||
| } | |||
| /** | |||
| * [offsetGet description] | |||
| * @param [type] $offset [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function offsetGet($offset){ | |||
| return isset($this->data[$offset]) ? $this->data[$offset] : null; | |||
| } | |||
| /** | |||
| * [rewind description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function rewind(){ | |||
| $this->valid = (false !== reset($this->data)); | |||
| } | |||
| /** | |||
| * [current description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function current(){ | |||
| return current($this->data); | |||
| } | |||
| /** | |||
| * [key description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function key(){ | |||
| return key($this->data); | |||
| } | |||
| /** | |||
| * [next description] | |||
| * @return function [description] | |||
| */ | |||
| public function next(){ | |||
| $this->valid = (false !== next($this->data)); | |||
| } | |||
| /** | |||
| * [valid description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function valid(){ | |||
| return $this->valid; | |||
| } | |||
| } | |||
| @ -0,0 +1,59 @@ | |||
| <?php | |||
| /** | |||
| * RedisFactory.php | |||
| * Redis connection factory. | |||
| * @version 151025:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs | |||
| * 151025:1 INIT version. | |||
| */ | |||
| namespace SaltFish; | |||
| /** | |||
| * class RedisFactory | |||
| */ | |||
| class RedisFactory{ | |||
| private static $instance; | |||
| public $h; | |||
| public $pool = array(); | |||
| /** | |||
| * [__construct description] | |||
| * @param array &$h, redis all config | |||
| */ | |||
| private function __construct(){ | |||
| $this->h = Config::get('cache'); | |||
| return; | |||
| } | |||
| /** | |||
| * [getInstance description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function getInstance(){ | |||
| if(empty(self::$instance)){ | |||
| self::$instance = new RedisFactory; | |||
| } | |||
| return self::$instance; | |||
| } | |||
| /** | |||
| * [spawn description] | |||
| * @param string $name, redis instance name | |||
| * @return RedisProxy RedisProxy | |||
| */ | |||
| public static function &spawn($name){ | |||
| $instance = self::getInstance(); | |||
| // if alerady spawn return pool result | |||
| if(!empty($instance->pool[$name])) return $instance->pool[$name]; | |||
| // spawn | |||
| $instance->pool[$name] = new RedisProxy($instance->h[$name]); | |||
| return $instance->pool[$name]; | |||
| } | |||
| } | |||
| @ -0,0 +1,104 @@ | |||
| <?php | |||
| /** | |||
| * RedisProxy.php | |||
| * Redis Proxy for redis connection. | |||
| * @version 150105:2 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs | |||
| * 141109:1 INIT version. | |||
| * | |||
| */ | |||
| namespace SaltFish; | |||
| /** | |||
| * CLASS RedisProxy | |||
| */ | |||
| class RedisProxy{ | |||
| public $RedisInstance; | |||
| public $connectInfo; | |||
| /** | |||
| * [__construct description] | |||
| * @param array &$connectInfo, e.g. array(host=>'', port=>3306, pass=>'', database=>0). | |||
| * @return boolean connect result. | |||
| */ | |||
| public function __construct(&$connectInfo){ | |||
| $this->connectInfo = $connectInfo; | |||
| $this->RedisInstance = new \Redis; | |||
| return; | |||
| } | |||
| /** | |||
| * [__destruct description] | |||
| */ | |||
| public function __destruct(){ | |||
| return $this->disconnect(); | |||
| } | |||
| /** | |||
| * [__call description] | |||
| * @param string $name, called function name | |||
| * @param array $args, input args | |||
| * @return mixed function call return | |||
| */ | |||
| public function __call($name, $args){ | |||
| // check connection | |||
| if(!$this->connect()) return false; | |||
| // call instance | |||
| $argnum = count($args); | |||
| if($argnum === 1){ | |||
| return $this->RedisInstance->$name($args[0]); | |||
| }elseif($argnum === 2){ | |||
| return $this->RedisInstance->$name($args[0], $args[1]); | |||
| }elseif($argnum === 3){ | |||
| return $this->RedisInstance->$name($args[0], $args[1], $args[2]); | |||
| }elseif($argnum === 4){ | |||
| return $this->RedisInstance->$name($args[0], $args[1], $args[2], $args[3]); | |||
| } | |||
| return false; | |||
| } | |||
| /** | |||
| * [getName description] | |||
| * @return string name | |||
| */ | |||
| public function getName(){ | |||
| return $this->connectInfo['name']; | |||
| } | |||
| /** | |||
| * [connect description] | |||
| * @return boolean success | |||
| */ | |||
| public function connect(){ | |||
| $info = &$this->connectInfo; | |||
| if(!$this->RedisInstance->IsConnected()){ | |||
| if(!$this->RedisInstance->connect( | |||
| $info['host'], $info['port'], $info['timeout'] | |||
| )) return false; | |||
| // auth and select database | |||
| if(!empty($info['pass'])){ | |||
| if(!$this->RedisInstance->auth($info['pass'])) return false; | |||
| } | |||
| return $this->RedisInstance->select($info['database']); | |||
| } | |||
| return true; | |||
| } | |||
| /** | |||
| * [disconnect description] | |||
| * @return boolean result | |||
| */ | |||
| public function disconnect(){ | |||
| if($this->RedisInstance->IsConnected()){ | |||
| return $this->RedisInstance->close(); | |||
| } | |||
| return true; | |||
| } | |||
| } | |||
| @ -0,0 +1,159 @@ | |||
| <?php | |||
| /** | |||
| * Encrypt.php | |||
| * This class inlcude some encrypt & decrypt method. | |||
| * @version 161017:6 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs | |||
| * 161017:6 ADD matchMd5() method. | |||
| * 160907:5 ADD const. | |||
| * 160901:4 ADD getRamdomString() method. | |||
| * 160823:3 MAKE iv readable. | |||
| * 160130:2 ADD opensslRandomPseudoBytes(); | |||
| * 141118:1 ADD hash(), match(), pbkdf2() method. | |||
| * | |||
| */ | |||
| namespace SaltFish; | |||
| /** | |||
| * CLASS Encrypt | |||
| */ | |||
| class Encrypt{ | |||
| // consts | |||
| const HASH_ALGORITHM = "SHA512"; | |||
| const IV_LEN = 16; | |||
| const HASH_COUNT = 1024; | |||
| const OUTPUT_KEY_LEN = 64; | |||
| const MD5_LEN = 32; | |||
| const MD5_KEY_LEN = 48; | |||
| const IV_SOURCE = MCRYPT_DEV_URANDOM; | |||
| const MCRYPT_MODE = MCRYPT_MODE_CFB; | |||
| const MCRYPT_SIZE = MCRYPT_CAST_256; | |||
| /** | |||
| * [getRamdomString description] | |||
| * @param [type] $len [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function getRamdomString($len){ | |||
| $size = mcrypt_get_iv_size(self::MCRYPT_SIZE, self::MCRYPT_MODE); | |||
| return substr(bin2hex(mcrypt_create_iv($size, self::IV_SOURCE)), 0, $len); | |||
| } | |||
| /** | |||
| * [hash description] | |||
| * @param [type] $_i [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function hash($_i, $iv = ""){ | |||
| if(empty($iv)){ | |||
| $iv = self::getRamdomString(self::IV_LEN); | |||
| } | |||
| $hash = self::pbkdf2(self::HASH_ALGORITHM, $_i, $iv, self::HASH_COUNT, self::OUTPUT_KEY_LEN); | |||
| return $hash.$iv; | |||
| } | |||
| /** | |||
| * [match description] | |||
| * @param [type] $_i [description] | |||
| * @param [type] $_hash [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function match($_i, $_hash){ | |||
| $hash = substr($_hash, 0, self::OUTPUT_KEY_LEN-self::IV_LEN); | |||
| $iv = substr($_hash, self::OUTPUT_KEY_LEN-self::IV_LEN); | |||
| $newHash = self::pbkdf2(self::HASH_ALGORITHM, $_i, $iv, self::HASH_COUNT, self::OUTPUT_KEY_LEN); | |||
| if($hash === $newHash){ | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| /** | |||
| * [matchMd5 description] | |||
| * @param [type] $_i [description] | |||
| * @param [type] $_hash [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function matchMd5($_i, $_hash){ | |||
| $hash = substr($_hash, 0, self::MD5_KEY_LEN-self::IV_LEN); | |||
| $iv = substr($_hash, self::MD5_KEY_LEN-self::IV_LEN); | |||
| $newHash = md5($_i.$iv); | |||
| if($hash === $newHash){ | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| /** | |||
| * PBKDF2 key derivation function as defined by RSA's PKCS #5: https://www.ietf.org/rfc/rfc2898.txt | |||
| * $algorithm - The hash algorithm to use. Recommended: SHA256 | |||
| * $password - The password. | |||
| * $salt - A salt that is unique to the password. | |||
| * $count - Iteration count. Higher is better, but slower. Recommended: At least 1000. | |||
| * $key_length - The length of the derived key in bytes. | |||
| * $raw_output - If true, the key is returned in raw binary format. Hex encoded otherwise. | |||
| * Returns: A $key_length-byte key derived from the password and salt. | |||
| * | |||
| * Test vectors can be found here: https://www.ietf.org/rfc/rfc6070.txt | |||
| * | |||
| * This implementation of PBKDF2 was originally created by https://defuse.ca | |||
| * With improvements by http://www.variations-of-shadow.com | |||
| */ | |||
| private static function pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output = false){ | |||
| $key_length = $key_length - self::IV_LEN; // iv len is usually 16 | |||
| $algorithm = strtolower($algorithm); | |||
| if(!in_array($algorithm, hash_algos(), true)) | |||
| trigger_error('PBKDF2 ERROR: Invalid hash algorithm.', E_USER_ERROR); | |||
| if($count <= 0 || $key_length <= 0) | |||
| trigger_error('PBKDF2 ERROR: Invalid parameters.', E_USER_ERROR); | |||
| if(function_exists("hash_pbkdf2")){ | |||
| // The output length is in NIBBLES (4-bits) if $raw_output is false! | |||
| if (!$raw_output) { | |||
| // $key_length = $key_length * 2; | |||
| } | |||
| return hash_pbkdf2($algorithm, $password, $salt, $count, $key_length, $raw_output); | |||
| } | |||
| $hash_length = strlen(hash($algorithm, "", true)); | |||
| $block_count = ceil($key_length / $hash_length); | |||
| $output = ""; | |||
| for($i = 1; $i <= $block_count; $i++) { | |||
| // $i encoded as 4 bytes, big endian. | |||
| $last = $salt . pack("N", $i); | |||
| // first iteration | |||
| $last = $xorsum = hash_hmac($algorithm, $last, $password, true); | |||
| // perform the other $count - 1 iterations | |||
| for ($j = 1; $j < $count; $j++) { | |||
| $xorsum ^= ($last = hash_hmac($algorithm, $last, $password, true)); | |||
| } | |||
| $output .= $xorsum; | |||
| } | |||
| if($raw_output){ | |||
| return substr($output, 0, $key_length); | |||
| }else{ | |||
| return bin2hex(substr($output, 0, $key_length)); | |||
| } | |||
| } | |||
| /** | |||
| * [opensslRandomPseudoBytes description] | |||
| * @param [type] $length [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function opensslRandomPseudoBytes($length, $raw_output = false) { | |||
| $length_n = (int) $length; // shell injection is no fun | |||
| if(!$raw_output) $length_n = $length_n/2; | |||
| $handle = popen("/usr/bin/openssl rand $length_n", "r"); | |||
| $data = stream_get_contents($handle); | |||
| pclose($handle); | |||
| if($raw_output) return $data; | |||
| return bin2hex($data); | |||
| } | |||
| } | |||
| @ -0,0 +1,7 @@ | |||
| <?php | |||
| require("Encrypt.php"); | |||
| $r = SaltFish\Encrypt::opensslRandomPseudoBytes(16); | |||
| var_dump($r); | |||
| @ -0,0 +1,97 @@ | |||
| <?php | |||
| /** | |||
| * Curl.php | |||
| * @version 150625:6 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changes | |||
| * 150625:6 add forward option. | |||
| * 150608:5 remove singleCurl() method. | |||
| * 140809:4 FIX urlencode option value. | |||
| * 140719:3 ADD urlencode option. | |||
| * 140719:2 ADD httpRequest() method. | |||
| * 130927:1 ADD singleCurl(), httpRequestPost() method. | |||
| */ | |||
| namespace SaltFish; | |||
| /** | |||
| * CLASS Curl | |||
| */ | |||
| class Curl{ | |||
| /** | |||
| * [httpRequestPost description] | |||
| * @param [type] $args [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function httpRequest($args){ | |||
| // start | |||
| $ch = curl_init(); | |||
| curl_setopt($ch, CURLOPT_HEADER, 0); | |||
| curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | |||
| curl_setopt($ch, CURLOPT_URL, $args['url']); | |||
| // set UA | |||
| if(!empty($args['useragent'])){ | |||
| curl_setopt($ch, CURLOPT_USERAGENT, $args['useragent']); | |||
| } | |||
| // set time out | |||
| if(!empty($args['timeout'])){ | |||
| curl_setopt($ch, CURLOPT_TIMEOUT, $args['timeout']); | |||
| } | |||
| // set data | |||
| if(!empty($args['data'])){ | |||
| if(!empty($args['urlencode'])){ | |||
| $urlencode = true; | |||
| }else{ | |||
| $urlencode = false; | |||
| } | |||
| curl_setopt($ch, CURLOPT_POSTFIELDS, self::formData($args['data'], $urlencode)); | |||
| } | |||
| // set header | |||
| if(!empty($args['host'])){ | |||
| curl_setopt($ch, CURLOPT_HTTPHEADER, array( | |||
| 'Host: '.$args['host'], | |||
| )); | |||
| } | |||
| if(!empty($args['header'])){ | |||
| curl_setopt($ch, CURLOPT_HTTPHEADER, $args['header']); | |||
| } | |||
| //set Cookie | |||
| if(!empty($args['cookie'])){ | |||
| curl_setopt($ch, CURLOPT_COOKIE, $args['cookie']); | |||
| } | |||
| // set proxy | |||
| if(!empty($args['proxy'])){ | |||
| curl_setopt($ch, CURLOPT_PROXY, $args['proxy']); | |||
| } | |||
| // set gzip | |||
| if(!empty($args['gzip'])){ | |||
| curl_setopt($ch, CURLOPT_ENCODING , "gzip"); | |||
| } | |||
| if(!empty($args['forward'])){ | |||
| curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); | |||
| } | |||
| $result = curl_exec($ch); | |||
| $info = curl_getinfo($ch); | |||
| // var_dump($info); | |||
| unset($ch); | |||
| return $result; | |||
| } | |||
| /** | |||
| * [formData description] | |||
| * @param [type] $data [description] | |||
| * @return [type] [description] | |||
| */ | |||
| private static function formData($data, $urlencode = false){ | |||
| if($urlencode){ | |||
| return http_build_query($data); | |||
| } | |||
| $str = ""; | |||
| foreach($data as $k => $v){ | |||
| $str .= "&{$k}={$v}"; | |||
| } | |||
| return $str; | |||
| } | |||
| } | |||
| @ -0,0 +1,28 @@ | |||
| <?php | |||
| /** | |||
| * Ip.php | |||
| * @version 150608:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changes | |||
| * 150608:1 Add getClientIp(). | |||
| */ | |||
| /** | |||
| * class Ip | |||
| */ | |||
| class Ip{ | |||
| /** | |||
| * [getClientIp description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function getClientIp(){ | |||
| return array( | |||
| 'HTTP_X_FORWARDED_FOR' => empty($_SERVER['HTTP_X_FORWARDED_FOR']) ? array() : explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']), | |||
| 'HTTP_CLIENT_IP' => empty($_SERVER["HTTP_CLIENT_IP"])? "" : $_SERVER["HTTP_CLIENT_IP"], | |||
| 'REMOTE_ADDR' => empty($_SERVER["REMOTE_ADDR"])? "" : $_SERVER["REMOTE_ADDR"], | |||
| ); | |||
| } | |||
| } | |||
| @ -0,0 +1,230 @@ | |||
| <?php | |||
| /*if(!class_exists('MultiCurlManager')) | |||
| include 'MultiCurlManager.php'; | |||
| if(!class_exists('MultiCurlSequence')) | |||
| include 'MultiCurlSequence.php'; | |||
| if(!class_exists('MultiCurlException')) | |||
| include 'MultiCurlException.php';*/ | |||
| /** | |||
| * MultiCurl multicurl http client | |||
| * | |||
| * @author Jaisen Mathai <jaisen@jmathai.com> | |||
| */ | |||
| class MultiCurl | |||
| { | |||
| const timeout = 3; | |||
| private static $inst = null; | |||
| /* @TODO make this private and add a method to set it to 0 */ | |||
| public static $singleton = 0; | |||
| private $mc; | |||
| private $running; | |||
| private $execStatus; | |||
| private $sleepIncrement = 1.1; | |||
| private $requests = array(); | |||
| private $responses = array(); | |||
| private $properties = array(); | |||
| private static $timers = array(); | |||
| public function __construct() | |||
| { | |||
| if(self::$singleton === 0) | |||
| { | |||
| throw new MultiCurlException('This class cannot be instantiated by the new keyword. You must instantiate it using: $obj = MultiCurl::getInstance();'); | |||
| } | |||
| $this->mc = curl_multi_init(); | |||
| $this->properties = array( | |||
| 'code' => CURLINFO_HTTP_CODE, | |||
| 'time' => CURLINFO_TOTAL_TIME, | |||
| 'length'=> CURLINFO_CONTENT_LENGTH_DOWNLOAD, | |||
| 'type' => CURLINFO_CONTENT_TYPE, | |||
| 'url' => CURLINFO_EFFECTIVE_URL | |||
| ); | |||
| } | |||
| public function addUrl($url, $options = array()) | |||
| { | |||
| $ch = curl_init($url); | |||
| curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); | |||
| foreach($options as $option=>$value) | |||
| { | |||
| curl_setopt($ch, $option, $value); | |||
| } | |||
| return $this->addCurl($ch); | |||
| } | |||
| public function addCurl($ch) | |||
| { | |||
| if(gettype($ch) !== 'resource') | |||
| { | |||
| throw new MultiCurlInvalidParameterException('Parameter must be a valid curl handle'); | |||
| } | |||
| $key = $this->getKey($ch); | |||
| $this->requests[$key] = $ch; | |||
| // uncomment this when you need header info | |||
| // curl_setopt($ch, CURLOPT_HEADERFUNCTION, array($this, 'headerCallback')); | |||
| $code = curl_multi_add_handle($this->mc, $ch); | |||
| // uncomment this when you need timer; | |||
| // $this->startTimer($key); | |||
| // (1) | |||
| if($code === CURLM_OK || $code === CURLM_CALL_MULTI_PERFORM) | |||
| { | |||
| do | |||
| { | |||
| $this->execStatus = curl_multi_exec($this->mc, $this->running); | |||
| } while ($this->execStatus === CURLM_CALL_MULTI_PERFORM); | |||
| return new MultiCurlManager($key); | |||
| } | |||
| else | |||
| { | |||
| return $code; | |||
| } | |||
| } | |||
| public function getResult($key = null) | |||
| { | |||
| if($key != null) | |||
| { | |||
| if(isset($this->responses[$key]['code'])) | |||
| { | |||
| return $this->responses[$key]; | |||
| } | |||
| $innerSleepInt = $outerSleepInt = 1; | |||
| while($this->running && ($this->execStatus == CURLM_OK || $this->execStatus == CURLM_CALL_MULTI_PERFORM)) | |||
| { | |||
| usleep(intval($outerSleepInt)); | |||
| $outerSleepInt = intval(max(1, ($outerSleepInt*$this->sleepIncrement))); | |||
| $ms=curl_multi_select($this->mc, 0); | |||
| // bug in PHP 5.3.18+ where curl_multi_select can return -1 | |||
| // https://bugs.php.net/bug.php?id=63411 | |||
| if($ms === -1) | |||
| usleep(100000); | |||
| // see pull request https://github.com/jmathai/php-multi-curl/pull/17 | |||
| // details here http://curl.haxx.se/libcurl/c/libcurl-errors.html | |||
| if($ms >= CURLM_CALL_MULTI_PERFORM) | |||
| { | |||
| do{ | |||
| $this->execStatus = curl_multi_exec($this->mc, $this->running); | |||
| usleep(intval($innerSleepInt)); | |||
| $innerSleepInt = intval(max(1, ($innerSleepInt*$this->sleepIncrement))); | |||
| }while($this->execStatus==CURLM_CALL_MULTI_PERFORM); | |||
| $innerSleepInt = 1; | |||
| } | |||
| $this->storeResponses(); | |||
| if(isset($this->responses[$key]['data'])) | |||
| { | |||
| return $this->responses[$key]; | |||
| } | |||
| } | |||
| return null; | |||
| } | |||
| return false; | |||
| } | |||
| public static function getSequence() | |||
| { | |||
| return new MultiCurlSequence(self::$timers); | |||
| } | |||
| public static function getTimers() | |||
| { | |||
| return self::$timers; | |||
| } | |||
| public function inject($key, $value) | |||
| { | |||
| $this->$key = $value; | |||
| } | |||
| private function getKey($ch) | |||
| { | |||
| return (string)$ch; | |||
| } | |||
| private function headerCallback($ch, $header) | |||
| { | |||
| $_header = trim($header); | |||
| $colonPos= strpos($_header, ':'); | |||
| if($colonPos > 0) | |||
| { | |||
| $key = substr($_header, 0, $colonPos); | |||
| $val = preg_replace('/^\W+/','',substr($_header, $colonPos)); | |||
| $this->responses[$this->getKey($ch)]['headers'][$key] = $val; | |||
| } | |||
| return strlen($header); | |||
| } | |||
| private function storeResponses() | |||
| { | |||
| while($done = curl_multi_info_read($this->mc)) | |||
| { | |||
| $this->storeResponse($done); | |||
| } | |||
| } | |||
| private function storeResponse($done, $isAsynchronous = true) | |||
| { | |||
| $key = $this->getKey($done['handle']); | |||
| // uncomment this line when you need timer. | |||
| // $this->stopTimer($key, $done); | |||
| if($isAsynchronous) | |||
| $this->responses[$key]['data'] = curl_multi_getcontent($done['handle']); | |||
| else | |||
| $this->responses[$key]['data'] = curl_exec($done['handle']); | |||
| $this->responses[$key]['response'] = $this->responses[$key]['data']; | |||
| foreach($this->properties as $name => $const) | |||
| { | |||
| $this->responses[$key][$name] = curl_getinfo($done['handle'], $const); | |||
| } | |||
| if($isAsynchronous) | |||
| curl_multi_remove_handle($this->mc, $done['handle']); | |||
| curl_close($done['handle']); | |||
| } | |||
| private function startTimer($key) | |||
| { | |||
| self::$timers[$key]['start'] = microtime(true); | |||
| } | |||
| private function stopTimer($key, $done) | |||
| { | |||
| self::$timers[$key]['end'] = microtime(true); | |||
| self::$timers[$key]['api'] = curl_getinfo($done['handle'], CURLINFO_EFFECTIVE_URL); | |||
| self::$timers[$key]['time'] = curl_getinfo($done['handle'], CURLINFO_TOTAL_TIME); | |||
| self::$timers[$key]['code'] = curl_getinfo($done['handle'], CURLINFO_HTTP_CODE); | |||
| } | |||
| public static function getInstance($new_instance = false) | |||
| { | |||
| if($new_instance){ | |||
| self::$inst == null; | |||
| self::$singleton = 1; | |||
| self::$inst = new MultiCurl(); | |||
| } | |||
| if(self::$inst == null){ | |||
| self::$singleton = 1; | |||
| self::$inst = new MultiCurl(); | |||
| } | |||
| return self::$inst; | |||
| } | |||
| } | |||
| /* | |||
| * Credits: | |||
| * - (1) Alistair pointed out that curl_multi_add_handle can return CURLM_CALL_MULTI_PERFORM on success. | |||
| */ | |||
| @ -0,0 +1,3 @@ | |||
| <?php | |||
| class MultiCurlException extends \Exception {} | |||
| class MultiCurlInvalidParameterException extends MultiCurlException {} | |||
| @ -0,0 +1,29 @@ | |||
| <?php | |||
| /** | |||
| * MultiCurlManager manages multicurl handles | |||
| * | |||
| * @author Jaisen Mathai <jaisen@jmathai.com> | |||
| */ | |||
| class MultiCurlManager | |||
| { | |||
| private $key; | |||
| private $epiCurl; | |||
| public function __construct($key) | |||
| { | |||
| $this->key = $key; | |||
| $this->epiCurl = MultiCurl::getInstance(); | |||
| } | |||
| public function __get($name) | |||
| { | |||
| $responses = $this->epiCurl->getResult($this->key); | |||
| return isset($responses[$name]) ? $responses[$name] : null; | |||
| } | |||
| public function __isset($name) | |||
| { | |||
| $val = self::__get($name); | |||
| return empty($val); | |||
| } | |||
| } | |||
| @ -0,0 +1,71 @@ | |||
| <?php | |||
| /** | |||
| * MultiCurlSequence displays sequence of http calls | |||
| * | |||
| * @author Jaisen Mathai <jaisen@jmathai.com> | |||
| */ | |||
| class MultiCurlSequence | |||
| { | |||
| private $width = 100; | |||
| private $timers; | |||
| private $min; | |||
| private $max; | |||
| private $range; | |||
| private $step; | |||
| public function __construct($timers) | |||
| { | |||
| $this->timers = $timers; | |||
| $min = PHP_INT_MAX; | |||
| $max = 0; | |||
| foreach($this->timers as $timer) | |||
| { | |||
| if(!isset($timer['start'])) | |||
| $timer['start'] = PHP_INT_MAX; | |||
| if(!isset($timer['end'])) | |||
| $timer['end'] = 0; | |||
| $min = min($timer['start'], $min); | |||
| $max = max($timer['end'], $max); | |||
| } | |||
| $this->min = $min; | |||
| $this->max = $max; | |||
| $this->range = $max-$min; | |||
| $this->step = floatval($this->range/$this->width); | |||
| } | |||
| public function renderAscii() | |||
| { | |||
| $tpl = ''; | |||
| foreach($this->timers as $timer) | |||
| $tpl .= $this->tplAscii($timer); | |||
| return $tpl; | |||
| } | |||
| private function tplAscii($timer) | |||
| { | |||
| $lpad = $rpad = 0; | |||
| $lspace = $chars = $rspace = ''; | |||
| if($timer['start'] > $this->min) | |||
| $lpad = intval(($timer['start'] - $this->min) / $this->step); | |||
| if($timer['end'] < $this->max) | |||
| $rpad = intval(($this->max - $timer['end']) / $this->step); | |||
| $mpad = $this->width - $lpad - $rpad; | |||
| if($lpad > 0) | |||
| $lspace = str_repeat(' ', $lpad); | |||
| if($mpad > 0) | |||
| $chars = str_repeat('=', $mpad); | |||
| if($rpad > 0) | |||
| $rspace = str_repeat(' ', $rpad); | |||
| $tpl = <<<TPL | |||
| ({$timer['api']} :: code={$timer['code']}, start={$timer['start']}, end={$timer['end']}, total={$timer['time']}) | |||
| [{$lspace}{$chars}{$rspace}] | |||
| TPL; | |||
| return $tpl; | |||
| } | |||
| } | |||
| @ -0,0 +1,59 @@ | |||
| <?php | |||
| /** | |||
| * AMQPFactory.php | |||
| * AMQP connection factory. | |||
| * @version 160127:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs | |||
| * 160127:1 INIT version. | |||
| */ | |||
| namespace SaltFish; | |||
| /** | |||
| * class AMQPFactory | |||
| */ | |||
| class AMQPFactory{ | |||
| private static $instance; | |||
| public $h; | |||
| public $pool = array(); | |||
| /** | |||
| * [__construct description] | |||
| * @param array &$h, redis all config | |||
| */ | |||
| private function __construct(){ | |||
| $this->h = Config::get('queue'); | |||
| return; | |||
| } | |||
| /** | |||
| * [getInstance description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function getInstance(){ | |||
| if(empty(self::$instance)){ | |||
| self::$instance = new AMQPFactory; | |||
| } | |||
| return self::$instance; | |||
| } | |||
| /** | |||
| * [spawn description] | |||
| * @param string $name, redis instance name | |||
| * @return RedisProxy RedisProxy | |||
| */ | |||
| public static function &spawn($name){ | |||
| $instance = self::getInstance(); | |||
| // if alerady spawn return pool result | |||
| if(!empty($instance->pool[$name])) return $instance->pool[$name]; | |||
| // spawn | |||
| $instance->pool[$name] = new AMQPProxy($instance->h[$name]); | |||
| return $instance->pool[$name]; | |||
| } | |||
| } | |||
| @ -0,0 +1,106 @@ | |||
| <?php | |||
| /** | |||
| * AMQPProxy.php | |||
| * AMQP Proxy for rabbitMQ connection. | |||
| * @version 160127:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs | |||
| * 160127:1 INIT version. | |||
| * | |||
| */ | |||
| namespace SaltFish; | |||
| /** | |||
| * CLASS AMQPProxy | |||
| */ | |||
| class AMQPProxy{ | |||
| public $AMQPInstance; | |||
| public $connectInfo; | |||
| public $connection; | |||
| public $exchange; | |||
| public $channel; | |||
| public $queue; | |||
| /** | |||
| * [__construct description] | |||
| * @param array &$connectInfo. | |||
| * @return boolean connect result. | |||
| */ | |||
| public function __construct(&$connectInfo){ | |||
| $this->connectInfo = $connectInfo; | |||
| return; | |||
| } | |||
| /** | |||
| * [__destruct description] | |||
| */ | |||
| public function __destruct(){ | |||
| return $this->disconnect(); | |||
| } | |||
| /** | |||
| * [consume description] | |||
| * @param [type] $callback_func [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function consume($callback_func){ | |||
| $this->connect(); | |||
| $this->queue->consume($callback_func); | |||
| } | |||
| /** | |||
| * [getName description] | |||
| * @return string name | |||
| */ | |||
| public function getName(){ | |||
| return $this->connectInfo['name']; | |||
| } | |||
| /** | |||
| * [connect description] | |||
| * @return boolean success | |||
| */ | |||
| public function connect(){ | |||
| if(empty($this->connection)){ | |||
| // connect | |||
| $info = &$this->connectInfo; | |||
| $this->connection = new \AMQPConnection(); | |||
| $this->connection->setHost($info['host']); | |||
| $this->connection->setLogin($info['user']); | |||
| $this->connection->setPassword($info['password']); | |||
| $this->connection->connect(); | |||
| // set channel | |||
| $this->channel = new \AMQPChannel($this->connection); | |||
| // set exchange | |||
| $this->exchange = new \AMQPExchange($this->channel); | |||
| // spawn queue | |||
| $this->queue = new \AMQPQueue($this->channel); | |||
| $this->queue->setName($info['routing_key']); | |||
| $this->queue->setFlags($info['flags']); | |||
| $this->queue->declareQueue(); | |||
| if(empty($this->queue)) return false; | |||
| } | |||
| return true; | |||
| } | |||
| /** | |||
| * [disconnect description] | |||
| * @return boolean result | |||
| */ | |||
| public function disconnect(){ | |||
| if(!is_object($this->queue)) return false; | |||
| $this->queue->cancel(); | |||
| if(!is_object($this->connection)) return false; | |||
| $connection->disconnect(); | |||
| return true; | |||
| } | |||
| } | |||
| @ -0,0 +1,291 @@ | |||
| <?php | |||
| /** Base query builder | |||
| */ | |||
| abstract class BaseQuery implements IteratorAggregate { | |||
| /** @var FluentPDO */ | |||
| private $fpdo; | |||
| /** @var array of definition clauses */ | |||
| protected $clauses = array(); | |||
| /** @var PDOStatement */ | |||
| private $result; | |||
| /** @var float */ | |||
| private $time; | |||
| /** @var bool */ | |||
| private $object = false; | |||
| protected $statements = array(), $parameters = array(); | |||
| protected function __construct(FluentPDO $fpdo, $clauses) { | |||
| $this->fpdo = $fpdo; | |||
| $this->clauses = $clauses; | |||
| $this->initClauses(); | |||
| } | |||
| private function initClauses() { | |||
| foreach ($this->clauses as $clause => $value) { | |||
| if ($value) { | |||
| $this->statements[$clause] = array(); | |||
| $this->parameters[$clause] = array(); | |||
| } else { | |||
| $this->statements[$clause] = null; | |||
| $this->parameters[$clause] = null; | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * Add statement for all kind of clauses | |||
| * @param $clause | |||
| * @param $statement | |||
| * @param array $parameters | |||
| * @return $this|SelectQuery | |||
| */ | |||
| protected function addStatement($clause, $statement, $parameters = array()) { | |||
| if ($statement === null) { | |||
| return $this->resetClause($clause); | |||
| } | |||
| # $statement !== null | |||
| if ($this->clauses[$clause]) { | |||
| if (is_array($statement)) { | |||
| $this->statements[$clause] = array_merge($this->statements[$clause], $statement); | |||
| } else { | |||
| $this->statements[$clause][] = $statement; | |||
| } | |||
| $this->parameters[$clause] = array_merge($this->parameters[$clause], $parameters); | |||
| } else { | |||
| $this->statements[$clause] = $statement; | |||
| $this->parameters[$clause] = $parameters; | |||
| } | |||
| return $this; | |||
| } | |||
| /** | |||
| * Remove all prev defined statements | |||
| * @param $clause | |||
| * @return $this | |||
| */ | |||
| protected function resetClause($clause) { | |||
| $this->statements[$clause] = null; | |||
| $this->parameters[$clause] = array(); | |||
| if ($this->clauses[$clause]) { | |||
| $this->statements[$clause] = array(); | |||
| } | |||
| return $this; | |||
| } | |||
| /** Implements method from IteratorAggregate | |||
| * @return PDOStatement | |||
| */ | |||
| public function getIterator() { | |||
| return $this->execute(); | |||
| } | |||
| /** Execute query with earlier added parameters | |||
| * @return PDOStatement | |||
| */ | |||
| public function execute() { | |||
| $query = $this->buildQuery(); | |||
| $parameters = $this->buildParameters(); | |||
| $result = $this->fpdo->getPdo()->prepare($query); | |||
| // At this point, $result is a PDOStatement instance, or false. | |||
| // PDO::prepare() does not reliably return errors. Some database drivers | |||
| // do not support prepared statements, and PHP emulates them. Postgres | |||
| // does support prepared statements, but PHP does not call Postgres's | |||
| // prepare function until we call PDOStatement::execute() (below). | |||
| // If PDO::prepare() worked properly, this is where we would check | |||
| // for prepare errors, such as invalid SQL. | |||
| if ($this->object !== false) { | |||
| if (class_exists($this->object)) { | |||
| $result->setFetchMode(PDO::FETCH_CLASS, $this->object); | |||
| } else { | |||
| $result->setFetchMode(PDO::FETCH_OBJ); | |||
| } | |||
| } elseif ($this->fpdo->getPdo()->getAttribute(PDO::ATTR_DEFAULT_FETCH_MODE) == PDO::FETCH_BOTH) { | |||
| $result->setFetchMode(PDO::FETCH_ASSOC); | |||
| } | |||
| $time = microtime(true); | |||
| if ($result && $result->execute($parameters)) { | |||
| $this->time = microtime(true) - $time; | |||
| } else { | |||
| $result = false; | |||
| } | |||
| $this->result = $result; | |||
| $this->debugger(); | |||
| return $result; | |||
| } | |||
| private function debugger() { | |||
| if ($this->fpdo->debug) { | |||
| if (!is_callable($this->fpdo->debug)) { | |||
| $backtrace = ''; | |||
| $query = $this->getQuery(); | |||
| $parameters = $this->getParameters(); | |||
| $debug = ''; | |||
| if ($parameters) { | |||
| $debug = "# parameters: " . implode(", ", array_map(array($this, 'quote'), $parameters)) . "\n"; | |||
| } | |||
| $debug .= $query; | |||
| $pattern = '(^' . preg_quote(dirname(__FILE__)) . '(\\.php$|[/\\\\]))'; // can be static | |||
| foreach (debug_backtrace() as $backtrace) { | |||
| if (isset($backtrace["file"]) && !preg_match($pattern, $backtrace["file"])) { | |||
| // stop on first file outside FluentPDO source codes | |||
| break; | |||
| } | |||
| } | |||
| $time = sprintf('%0.3f', $this->time * 1000) . ' ms'; | |||
| $rows = ($this->result) ? $this->result->rowCount() : 0; | |||
| fwrite(STDERR, "# $backtrace[file]:$backtrace[line] ($time; rows = $rows)\n$debug\n\n"); | |||
| } else { | |||
| call_user_func($this->fpdo->debug, $this); | |||
| } | |||
| } | |||
| } | |||
| /** | |||
| * @return \PDO | |||
| */ | |||
| protected function getPDO() { | |||
| return $this->fpdo->getPdo(); | |||
| } | |||
| /** | |||
| * @return \FluentStructure | |||
| */ | |||
| protected function getStructure() { | |||
| return $this->fpdo->getStructure(); | |||
| } | |||
| /** Get PDOStatement result | |||
| * @return \PDOStatement | |||
| */ | |||
| public function getResult() { | |||
| return $this->result; | |||
| } | |||
| /** Get time of execution | |||
| * @return float | |||
| */ | |||
| public function getTime() { | |||
| return $this->time; | |||
| } | |||
| /** Get query parameters | |||
| * @return array | |||
| */ | |||
| public function getParameters() { | |||
| return $this->buildParameters(); | |||
| } | |||
| /** Get query string | |||
| * @param boolean $formated return formated query | |||
| * @return string | |||
| */ | |||
| public function getQuery($formated = true) { | |||
| $query = $this->buildQuery(); | |||
| if ($formated) $query = FluentUtils::formatQuery($query); | |||
| return $query; | |||
| } | |||
| /** | |||
| * Generate query | |||
| * @return string | |||
| * @throws Exception | |||
| */ | |||
| protected function buildQuery() { | |||
| $query = ''; | |||
| foreach ($this->clauses as $clause => $separator) { | |||
| if ($this->clauseNotEmpty($clause)) { | |||
| if (is_string($separator)) { | |||
| $query .= " $clause " . implode($separator, $this->statements[$clause]); | |||
| } elseif ($separator === null) { | |||
| $query .= " $clause " . $this->statements[$clause]; | |||
| } elseif (is_callable($separator)) { | |||
| $query .= call_user_func($separator); | |||
| } else { | |||
| throw new Exception("Clause '$clause' is incorrectly set to '$separator'."); | |||
| } | |||
| } | |||
| } | |||
| return trim($query); | |||
| } | |||
| private function clauseNotEmpty($clause) { | |||
| if ($this->clauses[$clause]) { | |||
| return (boolean) count($this->statements[$clause]); | |||
| } else { | |||
| return (boolean) $this->statements[$clause]; | |||
| } | |||
| } | |||
| private function buildParameters() { | |||
| $parameters = array(); | |||
| foreach ($this->parameters as $clauses) { | |||
| if (is_array($clauses)) { | |||
| foreach ($clauses as $value) { | |||
| if (is_array($value) && is_string(key($value)) && substr(key($value), 0, 1) == ':') { | |||
| // this is named params e.g. (':name' => 'Mark') | |||
| $parameters = array_merge($parameters, $value); | |||
| } else { | |||
| $parameters[] = $value; | |||
| } | |||
| } | |||
| } else { | |||
| if ($clauses) $parameters[] = $clauses; | |||
| } | |||
| } | |||
| return $parameters; | |||
| } | |||
| protected function quote($value) { | |||
| if (!isset($value)) { | |||
| return "NULL"; | |||
| } | |||
| if (is_array($value)) { // (a, b) IN ((1, 2), (3, 4)) | |||
| return "(" . implode(", ", array_map(array($this, 'quote'), $value)) . ")"; | |||
| } | |||
| $value = $this->formatValue($value); | |||
| if (is_float($value)) { | |||
| return sprintf("%F", $value); // otherwise depends on setlocale() | |||
| } | |||
| if ($value === false) { | |||
| return "0"; | |||
| } | |||
| if (is_int($value) || $value instanceof FluentLiteral) { // number or SQL code - for example "NOW()" | |||
| return (string) $value; | |||
| } | |||
| return $this->fpdo->getPdo()->quote($value); | |||
| } | |||
| private function formatValue($val) { | |||
| if ($val instanceof DateTime) { | |||
| return $val->format("Y-m-d H:i:s"); //! may be driver specific | |||
| } | |||
| return $val; | |||
| } | |||
| /** | |||
| * Select an item as object | |||
| * @param boolean|object $object If set to true, items are returned as stdClass, otherwise a class | |||
| * name can be passed and a new instance of this class is return. | |||
| * Can be set to false to return items as an associative array. | |||
| * @return BaseQuery | |||
| */ | |||
| public function asObject($object = true) { | |||
| $this->object = $object; | |||
| return $this; | |||
| } | |||
| } | |||
| @ -0,0 +1,230 @@ | |||
| <?php | |||
| /** CommonQuery add JOIN and WHERE clauses for (SELECT, UPDATE, DELETE) | |||
| */ | |||
| abstract class CommonQuery extends BaseQuery { | |||
| /** @var array of used tables (also include table from clause FROM) */ | |||
| protected $joins = array(); | |||
| /** @var boolean disable adding undefined joins to query? */ | |||
| protected $isSmartJoinEnabled = true; | |||
| public function enableSmartJoin() { | |||
| $this->isSmartJoinEnabled = true; | |||
| return $this; | |||
| } | |||
| public function disableSmartJoin() { | |||
| $this->isSmartJoinEnabled = false; | |||
| return $this; | |||
| } | |||
| public function isSmartJoinEnabled() { | |||
| return $this->isSmartJoinEnabled; | |||
| } | |||
| /** Add where condition, more calls appends with AND | |||
| * @param string $condition possibly containing ? or :name (PDO syntax) | |||
| * @param mixed $parameters array or a scalar value | |||
| * @return SelectQuery | |||
| */ | |||
| public function where($condition, $parameters = array()) { | |||
| if ($condition === null) { | |||
| return $this->resetClause('WHERE'); | |||
| } | |||
| if (!$condition) { | |||
| return $this; | |||
| } | |||
| if (is_array($condition)) { // where(array("column1" => 1, "column2 > ?" => 2)) | |||
| foreach ($condition as $key => $val) { | |||
| $this->where($key, $val); | |||
| } | |||
| return $this; | |||
| } | |||
| $args = func_get_args(); | |||
| if (count($args) == 1) { | |||
| return $this->addStatement('WHERE', $condition); | |||
| } | |||
| if (count($args) == 2 && preg_match('~^[a-z_:][a-z0-9_.:]*$~i', $condition)) { | |||
| # condition is column only | |||
| if (is_null($parameters)) { | |||
| return $this->addStatement('WHERE', "$condition is NULL"); | |||
| } elseif (is_array($args[1])) { | |||
| $in = $this->quote($args[1]); | |||
| return $this->addStatement('WHERE', "$condition IN $in"); | |||
| } | |||
| $condition = "$condition = ?"; | |||
| } | |||
| array_shift($args); | |||
| return $this->addStatement('WHERE', $condition, $args); | |||
| } | |||
| /** | |||
| * @param $clause | |||
| * @param array $parameters - first is $statement followed by $parameters | |||
| * @return $this|SelectQuery | |||
| */ | |||
| public function __call($clause, $parameters = array()) { | |||
| $clause = FluentUtils::toUpperWords($clause); | |||
| if ($clause == 'GROUP') $clause = 'GROUP BY'; | |||
| if ($clause == 'ORDER') $clause = 'ORDER BY'; | |||
| if ($clause == 'FOOT NOTE') $clause = "\n--"; | |||
| $statement = array_shift($parameters); | |||
| if (strpos($clause, 'JOIN') !== FALSE) { | |||
| return $this->addJoinStatements($clause, $statement, $parameters); | |||
| } | |||
| return $this->addStatement($clause, $statement, $parameters); | |||
| } | |||
| protected function getClauseJoin() { | |||
| return implode(' ', $this->statements['JOIN']); | |||
| } | |||
| /** | |||
| * Statement can contain more tables (e.g. "table1.table2:table3:") | |||
| * @param $clause | |||
| * @param $statement | |||
| * @param array $parameters | |||
| * @return $this|SelectQuery | |||
| */ | |||
| private function addJoinStatements($clause, $statement, $parameters = array()) { | |||
| if ($statement === null) { | |||
| $this->joins = array(); | |||
| return $this->resetClause('JOIN'); | |||
| } | |||
| if (array_search(substr($statement, 0, -1), $this->joins) !== FALSE) { | |||
| return $this; | |||
| } | |||
| # match "tables AS alias" | |||
| preg_match('~`?([a-z_][a-z0-9_\.:]*)`?(\s+AS)?(\s+`?([a-z_][a-z0-9_]*)`?)?~i', $statement, $matches); | |||
| $joinAlias = ''; | |||
| $joinTable = ''; | |||
| if ($matches) { | |||
| $joinTable = $matches[1]; | |||
| if (isset($matches[4]) && !in_array(strtoupper($matches[4]), array('ON', 'USING'))) { | |||
| $joinAlias = $matches[4]; | |||
| } | |||
| } | |||
| if (strpos(strtoupper($statement), ' ON ') || strpos(strtoupper($statement), ' USING')) { | |||
| if (!$joinAlias) $joinAlias = $joinTable; | |||
| if (in_array($joinAlias, $this->joins)) { | |||
| return $this; | |||
| } else { | |||
| $this->joins[] = $joinAlias; | |||
| $statement = " $clause $statement"; | |||
| return $this->addStatement('JOIN', $statement, $parameters); | |||
| } | |||
| } | |||
| # $joinTable is list of tables for join e.g.: table1.table2:table3.... | |||
| if (!in_array(substr($joinTable, -1), array('.', ':'))) { | |||
| $joinTable .= '.'; | |||
| } | |||
| preg_match_all('~([a-z_][a-z0-9_]*[\.:]?)~i', $joinTable, $matches); | |||
| if (isset($this->statements['FROM'])) { | |||
| $mainTable = $this->statements['FROM']; | |||
| } elseif (isset($this->statements['UPDATE'])) { | |||
| $mainTable = $this->statements['UPDATE']; | |||
| } | |||
| $lastItem = array_pop($matches[1]); | |||
| array_push($matches[1], $lastItem); | |||
| foreach ($matches[1] as $joinItem) { | |||
| if ($mainTable == substr($joinItem, 0, -1)) continue; | |||
| # use $joinAlias only for $lastItem | |||
| $alias = ''; | |||
| if ($joinItem == $lastItem) $alias = $joinAlias; | |||
| $newJoin = $this->createJoinStatement($clause, $mainTable, $joinItem, $alias); | |||
| if ($newJoin) $this->addStatement('JOIN', $newJoin, $parameters); | |||
| $mainTable = $joinItem; | |||
| } | |||
| return $this; | |||
| } | |||
| /** | |||
| * Create join string | |||
| * @param $clause | |||
| * @param $mainTable | |||
| * @param $joinTable | |||
| * @param string $joinAlias | |||
| * @return string | |||
| */ | |||
| private function createJoinStatement($clause, $mainTable, $joinTable, $joinAlias = '') { | |||
| if (in_array(substr($mainTable, -1), array(':', '.'))) { | |||
| $mainTable = substr($mainTable, 0, -1); | |||
| } | |||
| $referenceDirection = substr($joinTable, -1); | |||
| $joinTable = substr($joinTable, 0, -1); | |||
| $asJoinAlias = ''; | |||
| if ($joinAlias) { | |||
| $asJoinAlias = " AS $joinAlias"; | |||
| } else { | |||
| $joinAlias = $joinTable; | |||
| } | |||
| if (in_array($joinAlias, $this->joins)) { | |||
| # if join exists don't create same again | |||
| return ''; | |||
| } else { | |||
| $this->joins[] = $joinAlias; | |||
| } | |||
| if ($referenceDirection == ':') { | |||
| # back reference | |||
| $primaryKey = $this->getStructure()->getPrimaryKey($mainTable); | |||
| $foreignKey = $this->getStructure()->getForeignKey($mainTable); | |||
| return " $clause $joinTable$asJoinAlias ON $joinAlias.$foreignKey = $mainTable.$primaryKey"; | |||
| } else { | |||
| $primaryKey = $this->getStructure()->getPrimaryKey($joinTable); | |||
| $foreignKey = $this->getStructure()->getForeignKey($joinTable); | |||
| return " $clause $joinTable$asJoinAlias ON $joinAlias.$primaryKey = $mainTable.$foreignKey"; | |||
| } | |||
| } | |||
| /** | |||
| * @return string | |||
| */ | |||
| protected function buildQuery() { | |||
| # first create extra join from statements with columns with referenced tables | |||
| $statementsWithReferences = array('WHERE', 'SELECT', 'GROUP BY', 'ORDER BY'); | |||
| foreach ($statementsWithReferences as $clause) { | |||
| if (array_key_exists($clause, $this->statements)) { | |||
| $this->statements[$clause] = array_map(array($this, 'createUndefinedJoins'), $this->statements[$clause]); | |||
| } | |||
| } | |||
| return parent::buildQuery(); | |||
| } | |||
| /** Create undefined joins from statement with column with referenced tables | |||
| * @param string $statement | |||
| * @return string rewrited $statement (e.g. tab1.tab2:col => tab2.col) | |||
| */ | |||
| private function createUndefinedJoins($statement) { | |||
| if (!$this->isSmartJoinEnabled) { | |||
| return $statement; | |||
| } | |||
| preg_match_all('~\\b([a-z_][a-z0-9_.:]*[.:])[a-z_]*~i', $statement, $matches); | |||
| foreach ($matches[1] as $join) { | |||
| if (!in_array(substr($join, 0, -1), $this->joins)) { | |||
| $this->addJoinStatements('LEFT JOIN', $join); | |||
| } | |||
| } | |||
| # don't rewrite table from other databases | |||
| foreach ($this->joins as $join) { | |||
| if (strpos($join, '.') !== FALSE && strpos($statement, $join) === 0) { | |||
| return $statement; | |||
| } | |||
| } | |||
| # remove extra referenced tables (rewrite tab1.tab2:col => tab2.col) | |||
| $statement = preg_replace('~(?:\\b[a-z_][a-z0-9_.:]*[.:])?([a-z_][a-z0-9_]*)[.:]([a-z_*])~i', '\\1.\\2', $statement); | |||
| return $statement; | |||
| } | |||
| } | |||
| @ -0,0 +1,72 @@ | |||
| <?php | |||
| /** DELETE query builder | |||
| * | |||
| * @method DeleteQuery leftJoin(string $statement) add LEFT JOIN to query | |||
| * ($statement can be 'table' name only or 'table:' means back reference) | |||
| * @method DeleteQuery innerJoin(string $statement) add INNER JOIN to query | |||
| * ($statement can be 'table' name only or 'table:' means back reference) | |||
| * @method DeleteQuery from(string $table) add LIMIT to query | |||
| * @method DeleteQuery orderBy(string $column) add ORDER BY to query | |||
| * @method DeleteQuery limit(int $limit) add LIMIT to query | |||
| */ | |||
| class DeleteQuery extends CommonQuery { | |||
| private $ignore = false; | |||
| public function __construct(FluentPDO $fpdo, $table) { | |||
| $clauses = array( | |||
| 'DELETE FROM' => array($this, 'getClauseDeleteFrom'), | |||
| 'DELETE' => array($this, 'getClauseDelete'), | |||
| 'FROM' => null, | |||
| 'JOIN' => array($this, 'getClauseJoin'), | |||
| 'WHERE' => ' AND ', | |||
| 'ORDER BY' => ', ', | |||
| 'LIMIT' => null, | |||
| ); | |||
| parent::__construct($fpdo, $clauses); | |||
| $this->statements['DELETE FROM'] = $table; | |||
| $this->statements['DELETE'] = $table; | |||
| } | |||
| /** DELETE IGNORE - Delete operation fails silently | |||
| * @return \DeleteQuery | |||
| */ | |||
| public function ignore() { | |||
| $this->ignore = true; | |||
| return $this; | |||
| } | |||
| /** | |||
| * @return string | |||
| */ | |||
| protected function buildQuery() { | |||
| if ($this->statements['FROM']) { | |||
| unset($this->clauses['DELETE FROM']); | |||
| } else { | |||
| unset($this->clauses['DELETE']); | |||
| } | |||
| return parent::buildQuery(); | |||
| } | |||
| /** Execute DELETE query | |||
| * @return boolean | |||
| */ | |||
| public function execute() { | |||
| $result = parent::execute(); | |||
| if ($result) { | |||
| return $result->rowCount(); | |||
| } | |||
| return false; | |||
| } | |||
| protected function getClauseDelete() { | |||
| return 'DELETE' . ($this->ignore ? " IGNORE" : '') . ' ' . $this->statements['DELETE']; | |||
| } | |||
| protected function getClauseDeleteFrom() { | |||
| return 'DELETE' . ($this->ignore ? " IGNORE" : '') . ' FROM ' . $this->statements['DELETE FROM']; | |||
| } | |||
| } | |||
| @ -0,0 +1,303 @@ | |||
| <?php | |||
| /** | |||
| * File.class.php | |||
| * This class inlcude some file & folder operation method. | |||
| * WARING: This script can works on linux only. | |||
| * @version 151231:13 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelog | |||
| * 151231:13 ADD cat(). | |||
| * 151207:12 ADD openFile(), closeFile(), readByLine(). | |||
| * 151207:11 ADD flush(), humanFilesize(). | |||
| * 140721:10 ADD trim to loadFile() method. | |||
| * 140721:9 FIX static method declare. | |||
| * 140719:7 ADD move(), loadFile() method. | |||
| * 131117:6 FIX txtEcho '>' method should be an atomic action | |||
| * 131012:5 FIX loadFolderFilename() read . or .. issue | |||
| * 130912:4 ADD txtReadByLineNum | |||
| * getLineNumByContent | |||
| * 130903:3 ADD txtTail | |||
| * 130902:2 ADD txtEcho | |||
| * txtHead | |||
| * auto_warp | |||
| * 130831:1 ADD loadFolderFilename | |||
| * txtWrite | |||
| * | |||
| */ | |||
| namespace SaltFish; | |||
| /** | |||
| * class File | |||
| */ | |||
| class File{ | |||
| private static $instance; | |||
| public $fd; | |||
| public function __construct(){ | |||
| } | |||
| public function __destruct(){ | |||
| $this->closeFile(); | |||
| } | |||
| /** | |||
| * [getInstance description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function getInstance(){ | |||
| if(empty(self::$instance)){ | |||
| self::$instance = new File; | |||
| } | |||
| return self::$instance; | |||
| } | |||
| /** | |||
| * PUBLIC STATIC FUNCTION loadFolderFilename | |||
| * This method load all filenames which in target folder into an array. | |||
| * @param string $dir, dir path | |||
| * @return array $files, array which loaded filenames | |||
| */ | |||
| public static function loadFolderFilename($dir){ | |||
| if(empty($dir)) return false; | |||
| $files = array(); | |||
| if($handle = opendir($dir)){ | |||
| while(false !== ($file = readdir($handle))){ | |||
| if($file === '.' || $file === '..') continue; | |||
| $files[] = $file; | |||
| } | |||
| closedir($handle); | |||
| }else{ | |||
| return false; | |||
| } | |||
| return $files; | |||
| } | |||
| /** | |||
| * PUBLIC STATIC FUNCTION txtWrite | |||
| * This method use php BIF(build in function) 'error_log' to write files. | |||
| * @param string $str, what you want to write | |||
| * @param string $file, target file loaction | |||
| * @param string $auto_wrap, there's 'unix'. 'windows'('win'), 'mac', null(no-warp) offered. | |||
| * @return boolean status, write status. | |||
| */ | |||
| public static function txtWrite($str='', $file, $auto_wrap = ''){ | |||
| if(empty($file)) return false; | |||
| self::auto_warp($str, $auto_wrap); | |||
| return error_log($str, 3, $file); | |||
| } | |||
| /** | |||
| * [txtEcho description] | |||
| * @param [type] $str [description] | |||
| * @param string $mode [description] | |||
| * @param [type] $file [description] | |||
| * @param string $auto_wrap [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function txtEcho($str, $mode ='>', $file, $auto_wrap = ''){ | |||
| if(empty($file)) return false; | |||
| self::auto_warp($str, $auto_wrap); | |||
| $com = "echo '{$str}' "; | |||
| if($mode === '>'){ | |||
| $com .= ' > '; | |||
| $fileTmp = $file.".tmp"; | |||
| $com .= $fileTmp; | |||
| if(exec($com) !== "") return false; | |||
| return (exec("mv $fileTmp $file")===""?true:false); | |||
| }elseif($mode === '>>'){ | |||
| $com .= ' >> '; | |||
| $com .= $file; | |||
| return (exec($com)===""?true:false); | |||
| } | |||
| return false; | |||
| } | |||
| /** | |||
| * [txtHead description] | |||
| * @param [type] $file [description] | |||
| * @param integer $lines [description] | |||
| * @param string $bytes [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function txtHead($file, $lines = 1, $bytes = ''){ | |||
| if(empty($file)) return false; | |||
| $com = "head"; | |||
| if(!empty($lines)) $com .= " -n {$lines} "; | |||
| if(!empty($bytes)) $com .= " -c {$bytes} "; | |||
| $com .= $file; | |||
| return exec($com); | |||
| } | |||
| /** | |||
| * [txtTail description] | |||
| * @param [type] $file [description] | |||
| * @param integer $lines [description] | |||
| * @param string $bytes [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function txtTail($file, $lines = 1, $bytes = ''){ | |||
| if(empty($file)) return false; | |||
| $com = "tail"; | |||
| if(!empty($lines)) $com .= " -n {$lines} "; | |||
| if(!empty($bytes)) $com .= " -c {$bytes} "; | |||
| $com .= $file; | |||
| return exec($com); | |||
| } | |||
| /** | |||
| * [txtReadByLineNum description] | |||
| * @param [type] $line [description] | |||
| * @param [type] $file [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function txtReadByLineNum($line, $file){ | |||
| if(empty($line)||empty($file)) return false; | |||
| return exec("sed -n {$line}p {$file}"); | |||
| } | |||
| /** | |||
| * [getLineNumByContent description] | |||
| * @param [type] $content [description] | |||
| * @param [type] $file [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function getLineNumByContent($content, $file){ | |||
| if(empty($content)||empty($file)) return false; | |||
| $lines = exec(" awk '/{$content}/ {print NR}' $file"); | |||
| return explode("\n", $lines); | |||
| } | |||
| /** | |||
| * [move description] | |||
| * @param [type] $target [description] | |||
| * @param [type] $from [description] | |||
| * @param [type] $to [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function move($target, $from, $to){ | |||
| if(empty($from)||empty($to)) return false; | |||
| exec("mv {$from}{$target} {$to}",$out, $rc); | |||
| if($rc === 0) return true; | |||
| return false; | |||
| } | |||
| /** | |||
| * [flush description] | |||
| * @param [type] $target [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function flush($target){ | |||
| if(empty($target)) return false; | |||
| exec("echo '' > {$target}",$out, $rc); | |||
| if($rc === 0) return true; | |||
| return false; | |||
| } | |||
| /** | |||
| * [cat description] | |||
| * @param [type] $target [description] | |||
| * @param [type] $out [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function cat($target, &$out){ | |||
| if(empty($target)) return false; | |||
| exec("cat {$target}", $out, $rc); | |||
| if(empty($out)) return false; | |||
| return true; | |||
| } | |||
| /** | |||
| * [loadFile description] | |||
| * @param [type] $file_addr [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function loadFile($file_addr, &$content, &$content_len){ | |||
| $content = array(); | |||
| $content_len = 0; | |||
| $requestDataHandle = @fopen($file_addr, "r"); | |||
| if($requestDataHandle){ | |||
| while(!feof($requestDataHandle)){ | |||
| $content[] = trim(fgets($requestDataHandle)); | |||
| $content_len ++; | |||
| } | |||
| fclose($requestDataHandle); | |||
| }else{ | |||
| return false; | |||
| } | |||
| unset($requestDataHandle); | |||
| return true; | |||
| } | |||
| /** | |||
| * [openFile description] | |||
| * @param [type] $file [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function openFile($file){ | |||
| $fd = @fopen($file, "r"); | |||
| if(!$fd) return false; | |||
| $this->fd = $fd; | |||
| return true; | |||
| } | |||
| /** | |||
| * [closeFile description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function closeFile(){ | |||
| if(!empty($this->df)) fclose($this->fd); | |||
| } | |||
| /** | |||
| * [readByLine description] | |||
| * @param string $file [description] | |||
| * @param [type] &$line [description] | |||
| * @param integer $buffer_size [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function readByLine(&$line, $buffer_size = 4096){ | |||
| if(!empty($this->fd) && !feof($this->fd)){ | |||
| $line = fgets($this->fd, $buffer_size); | |||
| return true; | |||
| }else{ | |||
| return false; | |||
| } | |||
| } | |||
| /** | |||
| * [humanFilesize description] | |||
| * @param [type] $bytes [description] | |||
| * @param integer $decimals [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function humanFilesize($bytes, $decimals=2){ | |||
| $sz = 'BKMGTP'; | |||
| $factor = floor((strlen($bytes) - 1) / 3); | |||
| return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$sz[$factor]; | |||
| } | |||
| /** | |||
| * [auto_warp description] | |||
| * @param [type] $str [description] | |||
| * @param string $mode [description] | |||
| * @return [type] [description] | |||
| */ | |||
| private static function auto_warp(&$str, $mode =''){ | |||
| if(!empty($mode)){ | |||
| if($mode === 'unix'){ | |||
| $str .= "\n"; | |||
| }elseif($mode === 'win' || $mode === 'windows'){ | |||
| $str .= "\r\n"; | |||
| }elseif($mode === 'mac'){ | |||
| $str .= "\r"; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,23 @@ | |||
| <?php | |||
| /** SQL literal value | |||
| */ | |||
| class FluentLiteral { | |||
| protected $value = ''; | |||
| /** Create literal value | |||
| * @param string $value | |||
| */ | |||
| function __construct($value) { | |||
| $this->value = $value; | |||
| } | |||
| /** Get literal value | |||
| * @return string | |||
| */ | |||
| function __toString() { | |||
| return $this->value; | |||
| } | |||
| } | |||
| @ -0,0 +1,133 @@ | |||
| <?php | |||
| /** | |||
| * FluentPDO is simple and smart SQL query builder for PDO | |||
| * | |||
| * For more information @see readme.md | |||
| * | |||
| * @link http://github.com/lichtner/fluentpdo | |||
| * @author Marek Lichtner, marek@licht.sk | |||
| * @copyright 2012 Marek Lichtner | |||
| * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 | |||
| * @license http://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) | |||
| */ | |||
| include_once 'FluentStructure.php'; | |||
| include_once 'FluentUtils.php'; | |||
| include_once 'FluentLiteral.php'; | |||
| include_once 'BaseQuery.php'; | |||
| include_once 'CommonQuery.php'; | |||
| include_once 'SelectQuery.php'; | |||
| include_once 'InsertQuery.php'; | |||
| include_once 'ReplaceQuery.php'; | |||
| include_once 'UpdateQuery.php'; | |||
| include_once 'DeleteQuery.php'; | |||
| class FluentPDO { | |||
| private $pdo, $structure; | |||
| /** @var boolean|callback */ | |||
| public $debug; | |||
| function __construct(PDO $pdo, FluentStructure $structure = null) { | |||
| $this->pdo = $pdo; | |||
| if (!$structure) { | |||
| $structure = new FluentStructure; | |||
| } | |||
| $this->structure = $structure; | |||
| } | |||
| /** Create SELECT query from $table | |||
| * @param string $table db table name | |||
| * @param integer $primaryKey return one row by primary key | |||
| * @return \SelectQuery | |||
| */ | |||
| public function from($table, $primaryKey = null) { | |||
| $query = new SelectQuery($this, $table); | |||
| if ($primaryKey) { | |||
| $tableTable = $query->getFromTable(); | |||
| $tableAlias = $query->getFromAlias(); | |||
| $primaryKeyName = $this->structure->getPrimaryKey($tableTable); | |||
| $query = $query->where("$tableAlias.$primaryKeyName", $primaryKey); | |||
| } | |||
| return $query; | |||
| } | |||
| /** Create INSERT INTO query | |||
| * | |||
| * @param string $table | |||
| * @param array $values you can add one or multi rows array @see docs | |||
| * @return \InsertQuery | |||
| */ | |||
| public function insertInto($table, $values = array()) { | |||
| $query = new InsertQuery($this, $table, $values); | |||
| return $query; | |||
| } | |||
| /** Create REPLACE INTO query | |||
| * | |||
| * @param string $table | |||
| * @param array $values you can add one or multi rows array @see docs | |||
| * @return \InsertQuery | |||
| */ | |||
| public function replaceInto($table, $values = array()) { | |||
| $query = new ReplaceQuery($this, $table, $values); | |||
| return $query; | |||
| } | |||
| /** Create UPDATE query | |||
| * | |||
| * @param string $table | |||
| * @param array|string $set | |||
| * @param string $primaryKey | |||
| * | |||
| * @return \UpdateQuery | |||
| */ | |||
| public function update($table, $set = array(), $primaryKey = null) { | |||
| $query = new UpdateQuery($this, $table); | |||
| $query->set($set); | |||
| if ($primaryKey) { | |||
| $primaryKeyName = $this->getStructure()->getPrimaryKey($table); | |||
| $query = $query->where($primaryKeyName, $primaryKey); | |||
| } | |||
| return $query; | |||
| } | |||
| /** Create DELETE query | |||
| * | |||
| * @param string $table | |||
| * @param string $primaryKey delete only row by primary key | |||
| * @return \DeleteQuery | |||
| */ | |||
| public function delete($table, $primaryKey = null) { | |||
| $query = new DeleteQuery($this, $table); | |||
| if ($primaryKey) { | |||
| $primaryKeyName = $this->getStructure()->getPrimaryKey($table); | |||
| $query = $query->where($primaryKeyName, $primaryKey); | |||
| } | |||
| return $query; | |||
| } | |||
| /** Create DELETE FROM query | |||
| * | |||
| * @param string $table | |||
| * @param string $primaryKey | |||
| * @return \DeleteQuery | |||
| */ | |||
| public function deleteFrom($table, $primaryKey = null) { | |||
| $args = func_get_args(); | |||
| return call_user_func_array(array($this, 'delete'), $args); | |||
| } | |||
| /** @return \PDO | |||
| */ | |||
| public function getPdo() { | |||
| return $this->pdo; | |||
| } | |||
| /** @return \FluentStructure | |||
| */ | |||
| public function getStructure() { | |||
| return $this->structure; | |||
| } | |||
| } | |||
| @ -0,0 +1,29 @@ | |||
| <?php | |||
| class FluentStructure { | |||
| private $primaryKey, $foreignKey; | |||
| function __construct($primaryKey = 'id', $foreignKey = '%s_id') { | |||
| if ($foreignKey === null) { | |||
| $foreignKey = $primaryKey; | |||
| } | |||
| $this->primaryKey = $primaryKey; | |||
| $this->foreignKey = $foreignKey; | |||
| } | |||
| public function getPrimaryKey($table) { | |||
| return $this->key($this->primaryKey, $table); | |||
| } | |||
| public function getForeignKey($table) { | |||
| return $this->key($this->foreignKey, $table); | |||
| } | |||
| private function key($key, $table) { | |||
| if (is_callable($key)) { | |||
| return $key($table); | |||
| } | |||
| return sprintf($key, $table); | |||
| } | |||
| } | |||
| @ -0,0 +1,26 @@ | |||
| <?php | |||
| class FluentUtils { | |||
| /** Convert "camelCaseWord" to "CAMEL CASE WORD" | |||
| * @param string $string | |||
| * @return string | |||
| */ | |||
| public static function toUpperWords($string) { | |||
| return trim(strtoupper(preg_replace('#(.)([A-Z]+)#', '$1 $2', $string))); | |||
| } | |||
| public static function formatQuery($query) { | |||
| $query = preg_replace( | |||
| '/WHERE|FROM|GROUP BY|HAVING|ORDER BY|LIMIT|OFFSET|UNION|ON DUPLICATE KEY UPDATE|VALUES/', | |||
| "\n$0", $query | |||
| ); | |||
| $query = preg_replace( | |||
| '/INNER|LEFT|RIGHT|CASE|WHEN|END|ELSE|AND/', | |||
| "\n $0", $query | |||
| ); | |||
| # remove trailing spaces | |||
| $query = preg_replace("/\s+\n/", "\n", $query); | |||
| return $query; | |||
| } | |||
| } | |||
| @ -0,0 +1,124 @@ | |||
| <?php | |||
| /** INSERT query builder | |||
| */ | |||
| class InsertQuery extends BaseQuery { | |||
| private $columns = array(); | |||
| private $firstValue = array(); | |||
| private $ignore = false; | |||
| public function __construct(FluentPDO $fpdo, $table, $values) { | |||
| $clauses = array( | |||
| 'INSERT INTO' => array($this, 'getClauseInsertInto'), | |||
| 'VALUES' => array($this, 'getClauseValues'), | |||
| 'ON DUPLICATE KEY UPDATE' => array($this, 'getClauseOnDuplicateKeyUpdate'), | |||
| ); | |||
| parent::__construct($fpdo, $clauses); | |||
| $this->statements['INSERT INTO'] = $table; | |||
| $this->values($values); | |||
| } | |||
| /** Execute insert query | |||
| * @return integer last inserted id or false | |||
| */ | |||
| public function execute() { | |||
| $result = parent::execute(); | |||
| if ($result) { | |||
| return $this->getPDO()->lastInsertId(); | |||
| } | |||
| return false; | |||
| } | |||
| /** Add ON DUPLICATE KEY UPDATE | |||
| * @param array $values | |||
| * @return \InsertQuery | |||
| */ | |||
| public function onDuplicateKeyUpdate($values) { | |||
| $this->statements['ON DUPLICATE KEY UPDATE'] = array_merge( | |||
| $this->statements['ON DUPLICATE KEY UPDATE'], $values | |||
| ); | |||
| return $this; | |||
| } | |||
| /** | |||
| * Add VALUES | |||
| * @param $values | |||
| * @return \InsertQuery | |||
| * @throws Exception | |||
| */ | |||
| public function values($values) { | |||
| if (!is_array($values)) { | |||
| throw new Exception('Param VALUES for INSERT query must be array'); | |||
| } | |||
| $first = current($values); | |||
| if (is_string(key($values))) { | |||
| # is one row array | |||
| $this->addOneValue($values); | |||
| } elseif (is_array($first) && is_string(key($first))) { | |||
| # this is multi values | |||
| foreach ($values as $oneValue) { | |||
| $this->addOneValue($oneValue); | |||
| } | |||
| } | |||
| return $this; | |||
| } | |||
| /** INSERT IGNORE - insert operation fails silently | |||
| * @return \InsertQuery | |||
| */ | |||
| public function ignore() { | |||
| $this->ignore = true; | |||
| return $this; | |||
| } | |||
| protected function getClauseInsertInto() { | |||
| return 'INSERT' . ($this->ignore ? " IGNORE" : '') . ' INTO ' . $this->statements['INSERT INTO']; | |||
| } | |||
| protected function getClauseValues() { | |||
| $valuesArray = array(); | |||
| foreach ($this->statements['VALUES'] as $rows) { | |||
| $quoted = array_map(array($this, 'quote'), $rows); | |||
| $valuesArray[] = '(' . implode(', ', $quoted) . ')'; | |||
| } | |||
| $columns = "`".implode('`, `', $this->columns)."`"; | |||
| $values = implode(', ', $valuesArray); | |||
| return " ($columns) VALUES $values"; | |||
| } | |||
| protected function getClauseOnDuplicateKeyUpdate() { | |||
| $result = array(); | |||
| foreach ($this->statements['ON DUPLICATE KEY UPDATE'] as $key => $value) { | |||
| $result[] = "$key = " . $this->quote($value); | |||
| } | |||
| return ' ON DUPLICATE KEY UPDATE ' . implode(', ', $result); | |||
| } | |||
| private function addOneValue($oneValue) { | |||
| # check if all $keys are strings | |||
| foreach ($oneValue as $key => $value) { | |||
| if (!is_string($key)) { | |||
| throw new Exception('INSERT query: All keys of value array have to be strings.'); | |||
| } | |||
| } | |||
| if (!$this->firstValue) { | |||
| $this->firstValue = $oneValue; | |||
| } | |||
| if (!$this->columns) { | |||
| $this->columns = array_keys($oneValue); | |||
| } | |||
| if ($this->columns != array_keys($oneValue)) { | |||
| throw new Exception('INSERT query: All VALUES have to same keys (columns).'); | |||
| } | |||
| $this->statements['VALUES'][] = $oneValue; | |||
| } | |||
| } | |||
| @ -0,0 +1,57 @@ | |||
| <?php | |||
| /** | |||
| * MongoDBFactory.php | |||
| * MongoDB connection factory. | |||
| * @version 160106:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs | |||
| * 160106:1 INIT version. | |||
| */ | |||
| namespace SaltFish; | |||
| /** | |||
| * class MongoDBFactory | |||
| */ | |||
| class MongoDBFactory{ | |||
| private static $instance; | |||
| public $h; | |||
| public $pool = array(); | |||
| /** | |||
| * [__construct description] | |||
| */ | |||
| private function __construct(){ | |||
| $this->h = Config::get('mongodb'); | |||
| return; | |||
| } | |||
| /** | |||
| * [getInstance description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function getInstance(){ | |||
| if(empty(self::$instance)){ | |||
| self::$instance = new MongoDBFactory; | |||
| } | |||
| return self::$instance; | |||
| } | |||
| /** | |||
| * [spawn description] | |||
| * @param string $name, mysql instance name | |||
| * @return MysqlProxy MysqlProxy | |||
| */ | |||
| public static function &spawn($name){ | |||
| $instance = self::getInstance(); | |||
| // if alerady spawn return pool result | |||
| if(!empty($instance->pool[$name])) return $instance->pool[$name]; | |||
| // spawn | |||
| $instance->pool[$name] = new \MongoDB\Driver\Manager($instance->h[$name]); | |||
| return $instance->pool[$name]; | |||
| } | |||
| } | |||
| @ -0,0 +1,57 @@ | |||
| <?php | |||
| /** | |||
| * MysqlFactory.php | |||
| * Mysql connection factory. | |||
| * @version 151110:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs | |||
| * 151110:1 INIT version. | |||
| */ | |||
| namespace SaltFish; | |||
| /** | |||
| * class MysqlFactory | |||
| */ | |||
| class MysqlFactory{ | |||
| private static $instance; | |||
| public $h; | |||
| public $pool = array(); | |||
| /** | |||
| * [__construct description] | |||
| */ | |||
| private function __construct(){ | |||
| $this->h = Config::get('storage'); | |||
| return; | |||
| } | |||
| /** | |||
| * [getInstance description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function getInstance(){ | |||
| if(empty(self::$instance)){ | |||
| self::$instance = new MysqlFactory; | |||
| } | |||
| return self::$instance; | |||
| } | |||
| /** | |||
| * [spawn description] | |||
| * @param string $name, mysql instance name | |||
| * @return MysqlProxy MysqlProxy | |||
| */ | |||
| public static function &spawn($name){ | |||
| $instance = self::getInstance(); | |||
| // if alerady spawn return pool result | |||
| if(!empty($instance->pool[$name])) return $instance->pool[$name]; | |||
| // spawn | |||
| $instance->pool[$name] = new MysqlProxy($instance->h[$name]); | |||
| return $instance->pool[$name]; | |||
| } | |||
| } | |||
| @ -0,0 +1,123 @@ | |||
| <?php | |||
| /** | |||
| * MysqlProxy.php | |||
| * Mysql Proxy for mysql connection. | |||
| * @version 151110:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs | |||
| * 141109:1 INIT version. | |||
| * | |||
| */ | |||
| namespace SaltFish; | |||
| /** | |||
| * CLASS MysqlProxy | |||
| */ | |||
| class MysqlProxy{ | |||
| public $MysqlInstance; | |||
| public $connectInfo; | |||
| public $DBH; // PDO DBH | |||
| /** | |||
| * [__construct description] | |||
| * @param array &$connectInfo, e.g. array(host=>'', port=>3306, pass=>'', database=>0). | |||
| * @return boolean connect result. | |||
| */ | |||
| public function __construct(&$connectInfo){ | |||
| $this->connectInfo = $connectInfo; | |||
| return; | |||
| } | |||
| /** | |||
| * [__destruct description] | |||
| */ | |||
| public function __destruct(){ | |||
| return $this->disconnect(); | |||
| } | |||
| /** | |||
| * [__call description] | |||
| * @param string $name, called function name | |||
| * @param array $args, input args | |||
| * @return mixed function call return | |||
| */ | |||
| public function __call($name, $args){ | |||
| // check connection | |||
| if(!$this->connect()) return false; | |||
| // call instance | |||
| $argnum = count($args); | |||
| if($argnum === 1){ | |||
| return $this->MysqlInstance->$name($args[0]); | |||
| }elseif($argnum === 2){ | |||
| return $this->MysqlInstance->$name($args[0], $args[1]); | |||
| }elseif($argnum === 3){ | |||
| return $this->MysqlInstance->$name($args[0], $args[1], $args[2]); | |||
| }elseif($argnum === 4){ | |||
| return $this->MysqlInstance->$name($args[0], $args[1], $args[2], $args[3]); | |||
| } | |||
| return false; | |||
| } | |||
| /** | |||
| * [getName description] | |||
| * @return string name | |||
| */ | |||
| public function getName(){ | |||
| return $this->connectInfo['name']; | |||
| } | |||
| /** | |||
| * [connect description] | |||
| * @return boolean success | |||
| */ | |||
| public function connect(){ | |||
| if(empty($this->DBH)){ | |||
| $info = &$this->connectInfo; | |||
| $opt = array( | |||
| \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, | |||
| \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC | |||
| ); | |||
| echo "============1\n"; | |||
| print_r($info); | |||
| $this->DBH = new \PDO( | |||
| "mysql:host={$info['host']};port={$info['port']};dbname={$info['name']};charset={$info['charset']}", | |||
| $info['user'], | |||
| $info['pass'], | |||
| $opt | |||
| ); | |||
| if(empty($this->DBH)) return false; | |||
| $this->MysqlInstance = new \FluentPDO($this->DBH); | |||
| if(empty($this->MysqlInstance)) return false; | |||
| if(!empty($info['debug'])){ | |||
| $this->MysqlInstance->debug = function(){ | |||
| echo "query: " . $BaseQuery->getQuery(false) . "\n"; | |||
| echo "parameters: " . implode(', ', $BaseQuery->getParameters()) . "\n"; | |||
| echo "rowCount: " . $BaseQuery->getResult()->rowCount() . "\n"; | |||
| // time is impossible to test (each time is other) | |||
| // echo $FluentQuery->getTime() . "\n"; | |||
| }; | |||
| } | |||
| } | |||
| return true; | |||
| } | |||
| /** | |||
| * [disconnect description] | |||
| * @return boolean result | |||
| */ | |||
| public function disconnect(){ | |||
| if(!empty($this->DBH)){ | |||
| $this->DBH = null; | |||
| } | |||
| return true; | |||
| } | |||
| } | |||
| @ -0,0 +1,124 @@ | |||
| <?php | |||
| /** REPLACE query builder | |||
| */ | |||
| class ReplaceQuery extends BaseQuery { | |||
| private $columns = array(); | |||
| private $firstValue = array(); | |||
| private $ignore = false; | |||
| public function __construct(FluentPDO $fpdo, $table, $values) { | |||
| $clauses = array( | |||
| 'REPLACE INTO' => array($this, 'getClauseReplaceInto'), | |||
| 'VALUES' => array($this, 'getClauseValues'), | |||
| 'ON DUPLICATE KEY UPDATE' => array($this, 'getClauseOnDuplicateKeyUpdate'), | |||
| ); | |||
| parent::__construct($fpdo, $clauses); | |||
| $this->statements['REPLACE INTO'] = $table; | |||
| $this->values($values); | |||
| } | |||
| /** Execute insert query | |||
| * @return integer last inserted id or false | |||
| */ | |||
| public function execute() { | |||
| $result = parent::execute(); | |||
| if ($result) { | |||
| return $this->getPDO()->lastInsertId(); | |||
| } | |||
| return false; | |||
| } | |||
| /** Add ON DUPLICATE KEY UPDATE | |||
| * @param array $values | |||
| * @return \ReplaceQuery | |||
| */ | |||
| public function onDuplicateKeyUpdate($values) { | |||
| $this->statements['ON DUPLICATE KEY UPDATE'] = array_merge( | |||
| $this->statements['ON DUPLICATE KEY UPDATE'], $values | |||
| ); | |||
| return $this; | |||
| } | |||
| /** | |||
| * Add VALUES | |||
| * @param $values | |||
| * @return \ReplaceQuery | |||
| * @throws Exception | |||
| */ | |||
| public function values($values) { | |||
| if (!is_array($values)) { | |||
| throw new Exception('Param VALUES for REPLACE query must be array'); | |||
| } | |||
| $first = current($values); | |||
| if (is_string(key($values))) { | |||
| # is one row array | |||
| $this->addOneValue($values); | |||
| } elseif (is_array($first) && is_string(key($first))) { | |||
| # this is multi values | |||
| foreach ($values as $oneValue) { | |||
| $this->addOneValue($oneValue); | |||
| } | |||
| } | |||
| return $this; | |||
| } | |||
| /** REPLACE IGNORE - insert operation fails silently | |||
| * @return \ReplaceQuery | |||
| */ | |||
| public function ignore() { | |||
| $this->ignore = true; | |||
| return $this; | |||
| } | |||
| protected function getClauseReplaceInto() { | |||
| return 'REPLACE' . ($this->ignore ? " IGNORE" : '') . ' INTO ' . $this->statements['REPLACE INTO']; | |||
| } | |||
| protected function getClauseValues() { | |||
| $valuesArray = array(); | |||
| foreach ($this->statements['VALUES'] as $rows) { | |||
| $quoted = array_map(array($this, 'quote'), $rows); | |||
| $valuesArray[] = '(' . implode(', ', $quoted) . ')'; | |||
| } | |||
| $columns = "`".implode('`, `', $this->columns)."`"; | |||
| $values = implode(', ', $valuesArray); | |||
| return " ($columns) VALUES $values"; | |||
| } | |||
| protected function getClauseOnDuplicateKeyUpdate() { | |||
| $result = array(); | |||
| foreach ($this->statements['ON DUPLICATE KEY UPDATE'] as $key => $value) { | |||
| $result[] = "$key = " . $this->quote($value); | |||
| } | |||
| return ' ON DUPLICATE KEY UPDATE ' . implode(', ', $result); | |||
| } | |||
| private function addOneValue($oneValue) { | |||
| # check if all $keys are strings | |||
| foreach ($oneValue as $key => $value) { | |||
| if (!is_string($key)) { | |||
| throw new Exception('REPLACE query: All keys of value array have to be strings.'); | |||
| } | |||
| } | |||
| if (!$this->firstValue) { | |||
| $this->firstValue = $oneValue; | |||
| } | |||
| if (!$this->columns) { | |||
| $this->columns = array_keys($oneValue); | |||
| } | |||
| if ($this->columns != array_keys($oneValue)) { | |||
| throw new Exception('REPLACE query: All VALUES have to same keys (columns).'); | |||
| } | |||
| $this->statements['VALUES'][] = $oneValue; | |||
| } | |||
| } | |||
| @ -0,0 +1,133 @@ | |||
| <?php | |||
| /** | |||
| * SELECT query builder | |||
| * | |||
| * @method SelectQuery select(string $column) add one or more columns in SELECT to query | |||
| * @method SelectQuery leftJoin(string $statement) add LEFT JOIN to query | |||
| * ($statement can be 'table' name only or 'table:' means back reference) | |||
| * @method SelectQuery innerJoin(string $statement) add INNER JOIN to query | |||
| * ($statement can be 'table' name only or 'table:' means back reference) | |||
| * @method SelectQuery groupBy(string $column) add GROUP BY to query | |||
| * @method SelectQuery having(string $column) add HAVING query | |||
| * @method SelectQuery orderBy(string $column) add ORDER BY to query | |||
| * @method SelectQuery limit(int $limit) add LIMIT to query | |||
| * @method SelectQuery offset(int $offset) add OFFSET to query | |||
| */ | |||
| class SelectQuery extends CommonQuery { | |||
| private $fromTable, $fromAlias; | |||
| function __construct(FluentPDO $fpdo, $from) { | |||
| $clauses = array( | |||
| 'SELECT' => ', ', | |||
| 'FROM' => null, | |||
| 'JOIN' => array($this, 'getClauseJoin'), | |||
| 'WHERE' => ' AND ', | |||
| 'GROUP BY' => ',', | |||
| 'HAVING' => ' AND ', | |||
| 'ORDER BY' => ', ', | |||
| 'LIMIT' => null, | |||
| 'OFFSET' => null, | |||
| "\n--" => "\n--", | |||
| ); | |||
| parent::__construct($fpdo, $clauses); | |||
| # initialize statements | |||
| $fromParts = explode(' ', $from); | |||
| $this->fromTable = reset($fromParts); | |||
| $this->fromAlias = end($fromParts); | |||
| $this->statements['FROM'] = $from; | |||
| $this->statements['SELECT'][] = $this->fromAlias . '.*'; | |||
| $this->joins[] = $this->fromAlias; | |||
| } | |||
| /** Return table name from FROM clause | |||
| * @internal | |||
| */ | |||
| public function getFromTable() { | |||
| return $this->fromTable; | |||
| } | |||
| /** Return table alias from FROM clause | |||
| * @internal | |||
| */ | |||
| public function getFromAlias() { | |||
| return $this->fromAlias; | |||
| } | |||
| /** Returns a single column | |||
| * @param int $columnNumber | |||
| * @return string | |||
| */ | |||
| public function fetchColumn($columnNumber = 0) { | |||
| if ($s = $this->execute()) { | |||
| return $s->fetchColumn($columnNumber); | |||
| } | |||
| return false; | |||
| } | |||
| /** Fetch first row or column | |||
| * @param string $column column name or empty string for the whole row | |||
| * @return mixed string, array or false if there is no row | |||
| */ | |||
| public function fetch($column = '') { | |||
| $return = $this->execute(); | |||
| if ($return === false) { | |||
| return false; | |||
| } | |||
| $return = $return->fetch(); | |||
| if ($return && $column != '') { | |||
| if (is_object($return)) { | |||
| return $return->{$column}; | |||
| } else { | |||
| return $return[$column]; | |||
| } | |||
| } | |||
| return $return; | |||
| } | |||
| /** | |||
| * Fetch pairs | |||
| * @param $key | |||
| * @param $value | |||
| * @param $object | |||
| * @return array of fetched rows as pairs | |||
| */ | |||
| public function fetchPairs($key, $value, $object = false) { | |||
| if ($s = $this->select(null)->select("$key, $value")->asObject($object)->execute()) { | |||
| return $s->fetchAll(PDO::FETCH_KEY_PAIR); | |||
| } | |||
| return false; | |||
| } | |||
| /** Fetch all row | |||
| * @param string $index specify index column | |||
| * @param string $selectOnly select columns which could be fetched | |||
| * @return array of fetched rows | |||
| */ | |||
| public function fetchAll($index = '', $selectOnly = '') { | |||
| if ($selectOnly) { | |||
| $this->select(null)->select($index . ', ' . $selectOnly); | |||
| } | |||
| if ($index) { | |||
| $data = array(); | |||
| foreach ($this as $row) { | |||
| if (is_object($row)) { | |||
| $data[$row->{$index}] = $row; | |||
| } else { | |||
| $data[$row[$index]] = $row; | |||
| } | |||
| } | |||
| return $data; | |||
| } else { | |||
| if ($s = $this->execute()) { | |||
| return $s->fetchAll(); | |||
| } | |||
| return false; | |||
| } | |||
| } | |||
| } | |||
| @ -0,0 +1,91 @@ | |||
| <?php | |||
| /** UPDATE query builder | |||
| * | |||
| * @method UpdateQuery leftJoin(string $statement) add LEFT JOIN to query | |||
| * ($statement can be 'table' name only or 'table:' means back reference) | |||
| * @method UpdateQuery innerJoin(string $statement) add INNER JOIN to query | |||
| * ($statement can be 'table' name only or 'table:' means back reference) | |||
| * @method UpdateQuery orderBy(string $column) add ORDER BY to query | |||
| * @method UpdateQuery limit(int $limit) add LIMIT to query | |||
| */ | |||
| class UpdateQuery extends CommonQuery { | |||
| public function __construct(FluentPDO $fpdo, $table) { | |||
| $clauses = array( | |||
| 'UPDATE' => array($this, 'getClauseUpdate'), | |||
| 'JOIN' => array($this, 'getClauseJoin'), | |||
| 'SET' => array($this, 'getClauseSet'), | |||
| 'WHERE' => ' AND ', | |||
| 'ORDER BY' => ', ', | |||
| 'LIMIT' => null, | |||
| ); | |||
| parent::__construct($fpdo, $clauses); | |||
| $this->statements['UPDATE'] = $table; | |||
| $tableParts = explode(' ', $table); | |||
| $this->joins[] = end($tableParts); | |||
| } | |||
| /** | |||
| * @param string|array $fieldOrArray | |||
| * @param null $value | |||
| * @return $this | |||
| * @throws Exception | |||
| */ | |||
| public function set($fieldOrArray, $value = false) { | |||
| if (!$fieldOrArray) { | |||
| return $this; | |||
| } | |||
| if (is_string($fieldOrArray) && $value !== false) { | |||
| $this->statements['SET'][$fieldOrArray] = $value; | |||
| } else { | |||
| if (!is_array($fieldOrArray)) { | |||
| throw new Exception('You must pass a value, or provide the SET list as an associative array. column => value'); | |||
| } else { | |||
| foreach ($fieldOrArray as $field => $value) { | |||
| $this->statements['SET'][$field] = $value; | |||
| } | |||
| } | |||
| } | |||
| return $this; | |||
| } | |||
| /** Execute update query | |||
| * @param boolean $getResultAsPdoStatement true to return the pdo statement instead of row count | |||
| * @return int|boolean|PDOStatement | |||
| */ | |||
| public function execute($getResultAsPdoStatement = false) { | |||
| $result = parent::execute(); | |||
| if ($getResultAsPdoStatement) { | |||
| return $result; | |||
| } | |||
| if ($result) { | |||
| return $result->rowCount(); | |||
| } | |||
| return false; | |||
| } | |||
| protected function getClauseUpdate() { | |||
| return 'UPDATE ' . $this->statements['UPDATE']; | |||
| } | |||
| protected function getClauseSet() { | |||
| $setArray = array(); | |||
| foreach ($this->statements['SET'] as $field => $value) { | |||
| if ($value instanceof FluentLiteral) { | |||
| $setArray[] = "`{$field}` = " . $value; | |||
| } else { | |||
| $setArray[] = "`{$field}` = ?"; | |||
| $this->parameters['SET'][$field] = $value; | |||
| } | |||
| } | |||
| return ' SET ' . implode(', ', $setArray); | |||
| } | |||
| } | |||
| @ -0,0 +1,52 @@ | |||
| <?php | |||
| /** | |||
| * String.php | |||
| * utils of string. | |||
| * @version 150609:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| */ | |||
| /** | |||
| * class String | |||
| */ | |||
| class String{ | |||
| /** | |||
| * [utf8Split description] | |||
| * @param [type] $utf8_str [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function utf8Split(&$utf8_str){ | |||
| $s = $utf8_str; | |||
| $len = strlen($s); | |||
| if($len == 0) return array(); | |||
| $chars = array(); | |||
| for($i = 0;$i < $len;$i++){ | |||
| $c = $s[$i]; | |||
| $n = ord($c); | |||
| if(($n >> 7) == 0){ // 0xxx xxxx, asci, single | |||
| $chars[] = $c; | |||
| } | |||
| else if(($n >> 4) == 15){ // 1111 xxxx, first in four char | |||
| if($i < $len - 3){ | |||
| $chars[] = $c.$s[$i + 1].$s[$i + 2].$s[$i + 3]; | |||
| $i += 3; | |||
| } | |||
| } | |||
| else if(($n >> 5) == 7){ // 111x xxxx, first in three char | |||
| if($i < $len - 2){ | |||
| $chars[] = $c.$s[$i + 1].$s[$i + 2]; | |||
| $i += 2; | |||
| } | |||
| } | |||
| else if(($n >> 6) == 3){ // 11xx xxxx, first in two char | |||
| if($i < $len - 1){ | |||
| $chars[] = $c.$s[$i + 1]; | |||
| $i++; | |||
| } | |||
| } | |||
| } | |||
| return $chars; | |||
| } | |||
| } | |||
| @ -0,0 +1,32 @@ | |||
| <?php | |||
| /** | |||
| * Process.php | |||
| * This class inlcude some process operation method. | |||
| * WARING: This script can works on linux only. | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * @version 131012 | |||
| * | |||
| * @changelog | |||
| * 131012 init version. | |||
| * | |||
| * | |||
| */ | |||
| /** | |||
| * class Process | |||
| */ | |||
| class Process{ | |||
| /** | |||
| * [getProcessNumbers description] | |||
| * @param [type] $process_name [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function getProcessNumbers($process_name){ | |||
| if(empty($process_name)) return 0; | |||
| $com = "ps aux | grep {$process_name} | wc -l"; | |||
| return (int)exec($com)-1; // -1 for grep | |||
| } | |||
| } | |||
| @ -0,0 +1,60 @@ | |||
| <?php | |||
| /** | |||
| * Sxml.php | |||
| * utils of sxml. | |||
| * @version 150810:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| */ | |||
| /** | |||
| * class Sxml | |||
| */ | |||
| class Sxml{ | |||
| const SXML_ATOM_TMPL = '<%s:%s>'; | |||
| /** | |||
| * [encryptSxml description] | |||
| * @param [type] &$data [description] | |||
| * @param string &$retval [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function encrypt(&$data, &$retval = ""){ | |||
| foreach($data as $key => $value){ | |||
| $retval .= sprintf(self::SXML_ATOM_TMPL, $key, $value); | |||
| } | |||
| return; | |||
| } | |||
| /** | |||
| * [decryptSxml description] | |||
| * @param [type] $line [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function decrypt(&$line, &$retval = array()){ | |||
| $stage1 = explode("><", $line); | |||
| $stage1Len = count($stage1); | |||
| // single field | |||
| if($stage1Len===1){ | |||
| return false; | |||
| } | |||
| // multifield ok | |||
| foreach($stage1 as $serial => $subLine){ | |||
| if($serial === 0){ | |||
| $subLine = str_replace("<", "", $subLine); | |||
| } | |||
| if($serial === ($stage1Len-1)){ | |||
| $subLine = str_replace(">", "", $subLine); | |||
| } | |||
| $stage2 = explode(":", $subLine); | |||
| $key = $stage2[0]; | |||
| unset($stage2[0]); | |||
| $value = implode(":", $stage2); // avoide ":" in data | |||
| $retval[$key] = $value; | |||
| } | |||
| return true; | |||
| } | |||
| } | |||
| @ -0,0 +1,39 @@ | |||
| <?php | |||
| /** | |||
| * ApiProxy.php | |||
| * ApiProxy model. | |||
| * @version 161101:2 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs | |||
| * 160905:1 INIT version. | |||
| */ | |||
| /** | |||
| * abstract class ApiProxy | |||
| */ | |||
| abstract class ApiProxy{ | |||
| /** | |||
| * [generateToken description] | |||
| * @param [type] $data [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function generateToken($data, $public_key){ | |||
| return SaltFish\AccessibilityCheck::generateToken($data, $public_key); | |||
| } | |||
| /** | |||
| * [generateTokenWithSha256 description] | |||
| * @param [type] $data [description] | |||
| * @param [type] $public_key [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function generateTokenWithSha256($data, $public_key){ | |||
| return SaltFish\AccessibilityCheck::generateTokenWithSha256($data, $public_key); | |||
| } | |||
| } | |||
| @ -0,0 +1,29 @@ | |||
| <?php | |||
| /** | |||
| * FeedbackInfo.php | |||
| * FeedbackInfo model. | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * @version 160819:1 | |||
| */ | |||
| /** | |||
| * class FeedbackInfo | |||
| */ | |||
| class FeedbackInfo{ | |||
| // signals | |||
| const S_UNKNOWN_ERROR = 0; | |||
| const S_OK = 1; | |||
| const S_NO_RESULT = 2; | |||
| const S_PERMISSION_DENIED = 3; | |||
| const S_WRONG_INPUT = 4; | |||
| const S_WRONG_EXEC_RESULT = 5; | |||
| // messages | |||
| const M_OK = 'ok'; | |||
| const M_ILLEGAL_SESSION = 'illegal session'; | |||
| const M_ACCESS_DENIED = 'access denied'; | |||
| const M_NO_RESULT = 'no result'; | |||
| const M_ILLEGAL_TOKEN = 'illegal token'; | |||
| const M_CACHE_FAILED = 'cache failed'; | |||
| const M_STORAGE_FAILED = 'storage failed'; | |||
| } | |||
| @ -0,0 +1,60 @@ | |||
| <?php | |||
| /** | |||
| * Request.php | |||
| * Request base model. | |||
| * @version 160825:4 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs | |||
| * 160825:4 ADD getSrc() method. | |||
| * 151104:3 CHANGE field token to verify | |||
| * 151027:2 REMOVE exportForAccessibilityCheck(). | |||
| * 151020:1 INIT version. | |||
| */ | |||
| /** | |||
| * abstract class Request | |||
| */ | |||
| abstract class Request{ | |||
| public $token; | |||
| public $src; | |||
| /** | |||
| * [__construct description] | |||
| * @param [type] &$input [description] | |||
| */ | |||
| public function __construct(&$input){ | |||
| return $this->setRequest($input); | |||
| } | |||
| /** | |||
| * [setRequest description] | |||
| * @param [type] &$input [description] | |||
| */ | |||
| public abstract function setRequest(&$input); | |||
| /** | |||
| * [getVerify description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function getToken(){ | |||
| return $this->token; | |||
| } | |||
| /** | |||
| * [getSrc description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function getSrc(){ | |||
| if(empty($this->src)) return ''; | |||
| return $this->src; | |||
| } | |||
| /** | |||
| * exportForAccessibilityCheck() | |||
| * @return [type] | |||
| */ | |||
| public abstract function exportForAccessibilityCheck(&$data); | |||
| } | |||
| @ -0,0 +1,18 @@ | |||
| <?php | |||
| /** | |||
| * Result.php | |||
| * Result base model. | |||
| * @version 151027:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs | |||
| * 151027:1 INIT version. | |||
| */ | |||
| /** | |||
| * abstract class Result | |||
| */ | |||
| abstract class Result{ | |||
| } | |||
| @ -0,0 +1,50 @@ | |||
| <?php | |||
| /** | |||
| * SampleApiProxy.php | |||
| * Sample api proxy. | |||
| * @version 161011:2 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| */ | |||
| /** | |||
| * class LeancloudRestApiProxy | |||
| */ | |||
| class SampleApiProxy extends ApiProxy{ | |||
| const API_SRC = 'sample_repo'; | |||
| const API_PUBLIC_KEY = 'UPbGdCjQyrYgX8tn34Zl'; | |||
| const REQUEST_TIMEOUT = 5; // seconds | |||
| const API_HOST = 'sample-api.juejin.im'; | |||
| public static $GET_SAMPLE_API = array( | |||
| ENV_PRODUCT => 'http://192.168.0.1:8000/v1/get?id=%s&token=%s&src=%s', | |||
| ENV_BETA => 'http://192.168.0.2:8000/v1/get?id=%s&token=%s&src=%s', | |||
| ENV_TEST => 'http://192.168.0.3:8000/v1/get?id=%s&token=%s&src=%s', | |||
| ); | |||
| /** | |||
| * [get description] | |||
| * @param SampleRequest $SampleRequest [description] | |||
| * @param SampleResult $SampleResult [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function get(SampleRequest $SampleRequest, SampleResult $SampleResult){ | |||
| $requestData = array( | |||
| 'ids' => array() | |||
| ); | |||
| $SampleRequest->exportAllIds($requestData['ids']); | |||
| $requestData['token'] = self::generateToken($requestData, self::API_PUBLIC_KEY); | |||
| $requestData['src'] = self::API_SRC; | |||
| $query = array( | |||
| 'url' => sprintf(self::$GET_SAMPLE_API[SERVER_ENV], implode("|", $requestData['entryIds']), $requestData['token'], $requestData['src']), | |||
| 'host' => self::API_HOST, | |||
| 'timeout' => self::REQUEST_TIMEOUT, | |||
| 'urlencode' => false, | |||
| ); | |||
| $result = SaltFish\Curl::httpRequest($query); | |||
| return $SampleResult->setByApiProxy($result); | |||
| } | |||
| } | |||
| @ -0,0 +1,63 @@ | |||
| <?php | |||
| /** | |||
| * SampleCache.php | |||
| * Sample cache | |||
| * @version 170821:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| */ | |||
| /** | |||
| * class SampleCache | |||
| */ | |||
| class SampleCache{ | |||
| const INSTANCE_NAME = 'sample_cache'; | |||
| const KEY_NAME_PREFIX = 'sc:'; | |||
| public $Redis; | |||
| /** | |||
| * [__construct description] | |||
| */ | |||
| public function __construct(){ | |||
| $this->Redis = SaltFish\RedisFactory::spawn(self::INSTANCE_NAME); | |||
| } | |||
| /** | |||
| * [__destruct description] | |||
| */ | |||
| public function __destruct(){ | |||
| $this->Redis = null; | |||
| } | |||
| /** | |||
| * [set description] | |||
| * @param SampleRequest $SampleRequest [description] | |||
| */ | |||
| public function set(SampleRequest $SampleRequest){ | |||
| $requestKey = ""; | |||
| $requestData = ""; | |||
| $SampleRequest->exportForSampleCacheSet($requestKey, $requestData); | |||
| return $this->Redis->set(self::KEY_NAME_PREFIX.$requestKey, $requestData); | |||
| } | |||
| /** | |||
| * [get description] | |||
| * @param SampleRequest $SampleRequest [description] | |||
| * @param SampleResult $SampleResult [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function get(SampleRequest $SampleRequest, SampleResult $SampleResult){ | |||
| $requestKey = ""; | |||
| // $resultData = ""; | |||
| $resultData = '{"name":"test"}'; | |||
| // if(!$SampleRequest->exportForSampleCacheGet($requestKey)) return false; | |||
| // $resultData = $this->Redis->get(self::KEY_NAME_PREFIX.$requestKey); | |||
| if(!$SampleResult->importResultFromCache($resultData)) return false; | |||
| return true; | |||
| } | |||
| } | |||
| @ -0,0 +1,89 @@ | |||
| <?php | |||
| /** | |||
| * SampleMongoDBStorage.php | |||
| * Sample MongoDB storage model. | |||
| * @version 170410:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| */ | |||
| /** | |||
| * class SampleMongoDBStorage | |||
| */ | |||
| class SampleMongoDBStorage{ | |||
| const CONNECTION_INFO = 'SampleMongoDBStorage'; | |||
| const STORAGE_ADDRESS = 'SampleMongoDBStorage.Sample'; | |||
| public $MongoDB; | |||
| /** | |||
| * [__construct description] | |||
| * @param [type] $redis [description] | |||
| */ | |||
| public function __construct(){ | |||
| $this->MongoDB = SaltFish\MongoDBFactory::spawn(self::CONNECTION_INFO); | |||
| } | |||
| /** | |||
| * [get description] | |||
| * @param SampleRequest $SampleRequest [description] | |||
| * @param SampleResult $SampleResult [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function get(SampleRequest $SampleRequest, SampleResult $SampleResult){ | |||
| $req = array(); | |||
| if(!$SampleRequest->exportForSampleMongoDBStorageGet($req)) return false; | |||
| if($SampleRequest->isAfterRequest()){ | |||
| $filter = array( | |||
| "createdAt" => array( | |||
| '$gt' => $req['after'], | |||
| ), | |||
| ); | |||
| }else{ | |||
| $filter = array( | |||
| "createdAt" => array( | |||
| '$lt' => $req['before'], | |||
| ), | |||
| ); | |||
| } | |||
| $options = array( | |||
| 'sort' => array("createdAt" => 1), | |||
| 'limit' => SampleRequest::PAGE_LIMIT, | |||
| ); | |||
| $query = new MongoDB\Driver\Query($filter, $options); | |||
| try{ | |||
| $r = $this->MongoDB->executeQuery(self::STORAGE_ADDRESS, $query); | |||
| } | |||
| catch(MongoDB\Driver\Exception\BulkWriteException $e){ | |||
| return false; | |||
| } | |||
| if(!is_object($r)) return false; | |||
| foreach($r as $doc){ | |||
| if(empty($doc)) continue; | |||
| if(!$SampleResult->importFromSampleMongoDBStorageGet($doc)) return false; | |||
| } | |||
| return true; | |||
| } | |||
| /** | |||
| * [set description] | |||
| * @param SampleRequest $SampleRequest [description] | |||
| */ | |||
| public function set(SampleRequest $SampleRequest){ | |||
| $data = array(); | |||
| if(!$EntryStorageRequest->exportForSampleMongoDBStorageSet($data)) return false; | |||
| $bulk = new MongoDB\Driver\BulkWrite(); | |||
| $result_obj = (array) ($bulk->insert($data)); | |||
| try{ | |||
| $r = $this->MongoDBManager->executeBulkWrite(self::STORAGE_ADDRESS, $bulk); | |||
| }catch(MongoDB\Driver\Exception\BulkWriteException $e){ | |||
| return false; | |||
| } | |||
| if (! is_object($r)){ | |||
| return false; | |||
| } | |||
| return true; | |||
| } | |||
| } | |||
| @ -0,0 +1,46 @@ | |||
| <?php | |||
| /** | |||
| * SampleMySQLStorage.php | |||
| * Sample MySQL storage model | |||
| * @version 160819:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| */ | |||
| /** | |||
| * class SampleMySQLStorage | |||
| */ | |||
| class SampleMySQLStorage{ | |||
| const CONNECTION_INFO = 'SampleMySQLStorage'; | |||
| const TABLE_NAME = 'sample'; | |||
| public $MySQL; | |||
| /** | |||
| * [__construct description] | |||
| * @param [type] $redis [description] | |||
| */ | |||
| public function __construct(){ | |||
| $this->MySQL = SaltFish\MysqlFactory::spawn(self::CONNECTION_INFO); | |||
| } | |||
| /** | |||
| * [set description] | |||
| * @param SampleRequest $SampleRequest [description] | |||
| */ | |||
| public function set(SampleRequest $SampleRequest){ | |||
| $data = array(); | |||
| $SampleRequest->exportForSampleMySQLStorageSet($data); | |||
| $q = $this->MySQL->insertInto( | |||
| self::TABLE_NAME, | |||
| $data | |||
| ); | |||
| $r = $q->execute(); | |||
| return empty($r) ? false : true; | |||
| } | |||
| } | |||
| @ -0,0 +1,117 @@ | |||
| <?php | |||
| /** | |||
| * SampleRequest.php | |||
| * SampleRequest model. | |||
| * @version 170424:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs | |||
| * 170424:1 INIT version. | |||
| */ | |||
| /** | |||
| * class SampleRequest | |||
| */ | |||
| class SampleRequest extends Request{ | |||
| public $uid; | |||
| public $before; | |||
| public $after; | |||
| public $page; | |||
| public $src; | |||
| public $token; | |||
| /** | |||
| * [setRequest description] | |||
| * @param [type] &$input [description] | |||
| */ | |||
| public function setRequest(&$input){ | |||
| if(!empty($input['after'])){ | |||
| $this->after = $input['after']; | |||
| }elseif(!empty($input['before'])){ | |||
| $this->before = $input['before']; | |||
| }else{ | |||
| return false; | |||
| } | |||
| $this->uid = $input['uid']; | |||
| $this->page = $input['page']; | |||
| $this->token = $input['token']; | |||
| $this->src = $input['src']; | |||
| return true; | |||
| } | |||
| /** | |||
| * [exportForAccessibilityCheck description] | |||
| * @param [type] &$data [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function exportForAccessibilityCheck(&$data){ | |||
| $data = [ | |||
| 'uid' => $this->uid, | |||
| ]; | |||
| return true; | |||
| } | |||
| /** | |||
| * [isAfterRequest description] | |||
| * @return boolean [description] | |||
| */ | |||
| public function isAfterRequest(){ | |||
| if(!empty($this->after)) return true; | |||
| return false; | |||
| } | |||
| /** | |||
| * [exportForSampleCacheSet description] | |||
| * @param [type] &$requestKey [description] | |||
| * @param [type] &$requestData [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function exportForSampleCacheSet(&$requestKey, &$requestData){ | |||
| $requestKey = "uid"; | |||
| $requestData = $this->uid; | |||
| return true; | |||
| } | |||
| /** | |||
| * [exportForSampleCacheGet description] | |||
| * @param [type] &$requestKey [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function exportForSampleCacheGet(&$requestKey){ | |||
| $requestKey = $this->uid; | |||
| return true; | |||
| } | |||
| /** | |||
| * [exportForSampleMongoDBStorageGet description] | |||
| * @param [type] $req [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function exportForSampleMongoDBStorageGet(&$req){ | |||
| $req['uid'] = $this->uid; | |||
| return true; | |||
| } | |||
| /** | |||
| * [exportForSampleMongoDBStorageSet description] | |||
| * @param [type] &$data [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function exportForSampleMongoDBStorageSet(&$data){ | |||
| $data['uid'] = $this->uid; | |||
| return true; | |||
| } | |||
| /** | |||
| * [exportForSampleMySQLStorageSet description] | |||
| * @param [type] &$data [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function exportForSampleMySQLStorageSet(&$data){ | |||
| $data['uid'] = $this->uid; | |||
| return true; | |||
| } | |||
| } | |||
| @ -0,0 +1,64 @@ | |||
| <?php | |||
| /** | |||
| * SampleResult.php | |||
| * SampleResult model. | |||
| * @version 170424:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs | |||
| * 170424:1 INIT version. | |||
| */ | |||
| /** | |||
| * class SampleResult | |||
| */ | |||
| class SampleResult extends Result{ | |||
| public $data; | |||
| public $doc; | |||
| public $r; | |||
| /** | |||
| * [importResultFromCache description] | |||
| * @param [type] &$resultData [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function importResultFromCache(&$resultData){ | |||
| if(empty($resultData)) return false; | |||
| $this->data = json_decode($resultData, true); | |||
| return true; | |||
| } | |||
| /** | |||
| * [importFromSampleMongoDBStorageGet description] | |||
| * @param [type] &$doc [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function importFromSampleMongoDBStorageGet(&$doc){ | |||
| if(empty($doc['uid'])) return false; | |||
| $this->doc = $doc; | |||
| return true; | |||
| } | |||
| /** | |||
| * [importFromSampleMySQLStorageGet description] | |||
| * @param [type] &$r [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function importFromSampleMySQLStorageGet(&$r){ | |||
| if(empty($r)) return false; | |||
| $this->r = $r; | |||
| return true; | |||
| } | |||
| /** | |||
| * [exportForFeedback description] | |||
| * @param [type] &$feedData [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function exportForFeedback(&$feedData){ | |||
| $feedData = $this->data; | |||
| return true; | |||
| } | |||
| } | |||
| @ -0,0 +1,92 @@ | |||
| <?php | |||
| /** | |||
| * BaseRender.php | |||
| * Base render. | |||
| * @version 160104:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs | |||
| * 160104:1 INIT commit | |||
| */ | |||
| namespace SaltFish; | |||
| /** | |||
| * class BaseRender | |||
| */ | |||
| class BaseRender{ | |||
| /** | |||
| * [fillBlank description] | |||
| * @param [type] $data [description] | |||
| * @param integer $max_length [description] | |||
| * @return [type] [description] | |||
| */ | |||
| private static function fillBlank($data = "", $max_length = 0, $separator = false){ | |||
| $len = strlen($data); | |||
| $fillNum = $max_length - $len; | |||
| for($i=0;$i<$fillNum;$i++){ | |||
| if(!$separator){ | |||
| $data .= ' '; | |||
| }else{ | |||
| $data .= '-'; | |||
| } | |||
| } | |||
| if($separator){ | |||
| return "+-{$data}-"; | |||
| }else{ | |||
| return "| {$data} "; | |||
| } | |||
| } | |||
| /** | |||
| * [generateGrid description] | |||
| * @param [type] $data [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function grid(&$r){ | |||
| $header = ""; | |||
| $sepLine = ""; | |||
| $content = array(); | |||
| $maxLenStat = array(); | |||
| // stat max len | |||
| $firstLine = true; | |||
| foreach($r as $lineNum => $line){ | |||
| foreach($line as $key => $value){ | |||
| $len = 0; | |||
| $len = strlen($value); | |||
| if($firstLine){ | |||
| $keyLen = strlen($key); | |||
| $keyLen > $len ? $len = $keyLen : true; | |||
| } | |||
| if(empty($maxLenStat[$key])){ | |||
| $maxLenStat[$key] = $len; | |||
| continue; | |||
| } | |||
| if($maxLenStat[$key]<$len) $maxLenStat[$key] = $len; | |||
| } | |||
| $firstLine = false; | |||
| } | |||
| // form grid | |||
| $headerGenSwitch = true; | |||
| foreach($r as $lineNum => $line){ | |||
| $content[$lineNum] = ""; | |||
| foreach($line as $key => $value){ | |||
| if($headerGenSwitch){ | |||
| $header .= self::fillBlank($key, $maxLenStat[$key]); | |||
| $sepLine .= self::fillBlank('', $maxLenStat[$key], true); | |||
| } | |||
| $content[$lineNum] .= self::fillBlank($value, $maxLenStat[$key]); | |||
| } | |||
| $content[$lineNum] .= " |\n"; | |||
| $headerGenSwitch = false; | |||
| } | |||
| $header .= " |\n"; | |||
| $sepLine .= "-+\n"; | |||
| $content = implode('', $content); | |||
| return("{$sepLine}{$header}{$sepLine}{$content}{$sepLine}"); | |||
| } | |||
| } | |||
| @ -0,0 +1,120 @@ | |||
| <?php | |||
| /** | |||
| * BaseView.php | |||
| * Views of Base. | |||
| * @version 150811:2 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| * @changelogs 150811:1 ADD renderRaw() | |||
| * 150511:1 INIT commit | |||
| */ | |||
| /** | |||
| * class BaseView | |||
| */ | |||
| class BaseView{ | |||
| /** | |||
| * [renderJson description] | |||
| * @param [type] $r [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function renderJson($r){ | |||
| header('Content-type: application/json; charset=utf-8'); | |||
| print($r); | |||
| flush(); | |||
| } | |||
| /** | |||
| * [renderRaw description] | |||
| * @param [type] $r [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function renderRaw($r){ | |||
| var_dump($r); | |||
| flush(); | |||
| } | |||
| /** | |||
| * [genBlank description] | |||
| * @param [type] $data [description] | |||
| * @param integer $max_length [description] | |||
| * @return [type] [description] | |||
| */ | |||
| private static function genBlank($data = "", $max_length = 0, $separator = false){ | |||
| $len = strlen($data); | |||
| $fillNum = $max_length - $len; | |||
| for($i=0;$i<$fillNum;$i++){ | |||
| if(!$separator){ | |||
| $data .= ' '; | |||
| }else{ | |||
| $data .= '-'; | |||
| } | |||
| } | |||
| if($separator){ | |||
| return "+-{$data}-"; | |||
| }else{ | |||
| return "| {$data} "; | |||
| } | |||
| } | |||
| /** | |||
| * [generateGrid description] | |||
| * @param [type] $data [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function generateGrid(&$r){ | |||
| $header = ""; | |||
| $sepLine = ""; | |||
| $content = array(); | |||
| $maxLenStat = array(); | |||
| // stat max len | |||
| $firstLine = true; | |||
| foreach($r as $lineNum => $line){ | |||
| foreach($line as $key => $value){ | |||
| $len = 0; | |||
| $len = strlen($value); | |||
| if($firstLine){ | |||
| $keyLen = strlen($key); | |||
| $keyLen > $len ? $len = $keyLen : true; | |||
| } | |||
| if(empty($maxLenStat[$key])){ | |||
| $maxLenStat[$key] = $len; | |||
| continue; | |||
| } | |||
| if($maxLenStat[$key]<$len) $maxLenStat[$key] = $len; | |||
| } | |||
| $firstLine = false; | |||
| } | |||
| // form grid | |||
| $headerGenSwitch = true; | |||
| foreach($r as $lineNum => $line){ | |||
| $content[$lineNum] = ""; | |||
| foreach($line as $key => $value){ | |||
| if($headerGenSwitch){ | |||
| $header .= self::genBlank($key, $maxLenStat[$key]); | |||
| $sepLine .= self::genBlank('', $maxLenStat[$key], true); | |||
| } | |||
| $content[$lineNum] .= self::genBlank($value, $maxLenStat[$key]); | |||
| } | |||
| $content[$lineNum] .= " |\n"; | |||
| $headerGenSwitch = false; | |||
| } | |||
| $header .= " |\n"; | |||
| $sepLine .= "-+\n"; | |||
| $content = implode('', $content); | |||
| return("{$sepLine}{$header}{$sepLine}{$content}{$sepLine}"); | |||
| } | |||
| /** | |||
| * [renderDumpGrid description] | |||
| * @param [type] $r [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public static function renderDumpGrid(&$r){ | |||
| echo self::generateGrid($r); | |||
| flush(); | |||
| } | |||
| } | |||
| ?> | |||
| @ -0,0 +1,10 @@ | |||
| <?php | |||
| /** | |||
| * status.php | |||
| * Api entrance | |||
| * @version 151024:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| */ | |||
| echo("ok"); | |||
| @ -0,0 +1,29 @@ | |||
| <?php | |||
| /** | |||
| * ObjectArray.test.php | |||
| * Test Base controller. | |||
| * @version 150629:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| */ | |||
| require(dirname(__FILE__).'/../protected/lib/base/ObjectArray.php'); | |||
| class DefaultRequest extends ObjectArray{ | |||
| } | |||
| $input = array( | |||
| 'id' => 12, | |||
| 'type' => 'a', | |||
| 'callback' => 'json_callback_21453534534', | |||
| 'src' => 'pc_452345', | |||
| ); | |||
| $DefaultRequest = new DefaultRequest($input); | |||
| $DefaultRequest['tar'] = 'zxvf'; | |||
| var_dump(json_encode($DefaultRequest)); | |||
| @ -0,0 +1,69 @@ | |||
| <?php | |||
| /** | |||
| * TestBase.php | |||
| * Test Base controller. | |||
| * @version 150629:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| */ | |||
| /** | |||
| * abstract class TestBase | |||
| */ | |||
| abstract class TestBase{ | |||
| public $_log; | |||
| /** | |||
| * [__construct description] | |||
| */ | |||
| public function __construct($requirements){ | |||
| // require | |||
| $this->InitRequirements($requirements); | |||
| // check mode | |||
| if(ONLINE_MODE){ | |||
| $debug = false; | |||
| }else{ | |||
| $debug = true; | |||
| } | |||
| // load files | |||
| $this->initLog($debug); | |||
| $this->debugSwitch(true); | |||
| } | |||
| /** | |||
| * [debugSwitch description] | |||
| * @param boolean $switch [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function debugSwitch($switch = false){ | |||
| if($switch){ | |||
| ini_set('display_errors', 1); | |||
| error_reporting(E_ALL); | |||
| } | |||
| return; | |||
| } | |||
| /** | |||
| * [InitRequirements description] | |||
| */ | |||
| public function InitRequirements($requirements){ | |||
| $class_name = get_class($this); | |||
| require(dirname(__FILE__).'/../protected/lib/base/AutoRequire.php'); | |||
| AutoRequire::_class($requirements); | |||
| return; | |||
| } | |||
| /** | |||
| * [initLog description] | |||
| * @param [type] $debug [description] | |||
| * @return [type] [description] | |||
| */ | |||
| public function initLog($debug){ | |||
| $this->_log = new Log(); | |||
| $this->_log->setLogAddress(LOG_FILE, LOG_SPLIT); | |||
| $this->_log->setEchoSwitch($debug); | |||
| return; | |||
| } | |||
| } | |||
| @ -0,0 +1,21 @@ | |||
| --TEST-- | |||
| SaltFish\Config test | |||
| @version 160103:1 | |||
| --FILE-- | |||
| <?php | |||
| require(dirname(__FILE__).'/../../src/protected/lib/base/AutoRequire.php'); | |||
| require(dirname(__FILE__).'/../../src/protected/lib/base/Config.php'); | |||
| $main = array( | |||
| 'database' => 1, | |||
| ); | |||
| SaltFish\Config::importMainConfig($main); | |||
| $db = SaltFish\Config::get('database'); | |||
| var_dump($db); | |||
| ?> | |||
| --EXPECT-- | |||
| int(1) | |||
| @ -0,0 +1,17 @@ | |||
| <?php | |||
| require("Encrypt.class.php"); | |||
| $pass = "123456ffffffffffffff"; | |||
| $hash = Encrypt::hash($pass); | |||
| var_dump($hash); | |||
| $r = Encrypt::match($pass, $hash); | |||
| var_dump($r); | |||
| if($r){ | |||
| print("MATCH\n"); | |||
| }else{ | |||
| print("NOT MATCH\n"); | |||
| } | |||
| @ -0,0 +1,91 @@ | |||
| <?php | |||
| /** | |||
| * Input.test.php | |||
| * Test Base controller. | |||
| * @version 150629:1 | |||
| * @author karminski <code.karminski@outlook.com> | |||
| * | |||
| */ | |||
| require(dirname(__FILE__).'/../protected/lib/base/Input.php'); | |||
| $input_param = array( | |||
| array( | |||
| 'param' => 'id', | |||
| 'condition' => array( | |||
| 'method' => null, | |||
| 'type' => Input::TYPE_INT, | |||
| 'limit' => array('min' => 0, 'max' => 100000000), | |||
| 'default' => 0, | |||
| 'necessary' => true, | |||
| ), | |||
| ), | |||
| array( | |||
| 'param' => 'type', | |||
| 'condition' => array( | |||
| 'method' => null, | |||
| 'type' => Input::TYPE_ENUM, | |||
| 'options' => array("a", "b", "c", 0), | |||
| 'default' => 0, | |||
| 'necessary' => true, | |||
| ), | |||
| ), | |||
| array( | |||
| 'param' => 'data', | |||
| 'condition' => array( | |||
| 'method' => null, | |||
| 'type' => Input::TYPE_STRING, | |||
| 'sub_type' => Input::TYPE_STRING, | |||
| 'limit' => array('fixed' => 32), | |||
| 'default' => null, | |||
| 'necessary' => true, | |||
| ), | |||
| ), | |||
| array( | |||
| 'param' => 'token', | |||
| 'condition' => array( | |||
| 'method' => null, | |||
| 'type' => Input::TYPE_STRING, | |||
| 'limit' => array('fixed' => 32), | |||
| 'default' => '', | |||
| 'necessary' => true, | |||
| ), | |||
| ), | |||
| array( | |||
| 'param' => 'callback', | |||
| 'condition' => array( | |||
| 'method' => null, | |||
| 'type' => Input::TYPE_STRING, | |||
| 'limit' => array('min' => 1, 'max' => 40), | |||
| 'default' => '', | |||
| 'necessary' => false, | |||
| ), | |||
| ), | |||
| array( | |||
| 'param' => 'src', | |||
| 'condition' => array( | |||
| 'method' => null, | |||
| 'type' => Input::TYPE_STRING, | |||
| 'limit' => array('min' => 1, 'max' => 40), | |||
| 'default' => '', | |||
| 'necessary' => false, | |||
| ), | |||
| ), | |||
| ); | |||
| $_GET = array( | |||
| 'id' => 12, | |||
| 'type' => 'a', | |||
| 'callback' => 'json_callback_21453534534', | |||
| 'src' => 'pc_452345', | |||
| ); | |||
| $r = array(); | |||
| $exp = array(); | |||
| Input::get(Input::METHOD_GET, $input_param, $r, $exp); | |||
| var_dump($r); | |||
| var_dump($exp); | |||