diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..6537ca4 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false + +[*.{yml,yaml}] +indent_size = 2 diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..c3ed2a9 --- /dev/null +++ b/.env.example @@ -0,0 +1,49 @@ +APP_NAME=Laravel +APP_ENV=local +APP_KEY= +APP_DEBUG=true +APP_URL=http://localhost + +LOG_CHANNEL=stack +LOG_LEVEL=debug + +DB_CONNECTION=mysql +DB_HOST=127.0.0.1 +DB_PORT=3306 +DB_DATABASE=laravel +DB_USERNAME=root +DB_PASSWORD= + +BROADCAST_DRIVER=log +CACHE_DRIVER=file +QUEUE_CONNECTION=sync +SESSION_DRIVER=file +SESSION_LIFETIME=120 + +MEMCACHED_HOST=127.0.0.1 + +REDIS_HOST=127.0.0.1 +REDIS_PASSWORD=null +REDIS_PORT=6379 + +MAIL_MAILER=smtp +MAIL_HOST=mailhog +MAIL_PORT=1025 +MAIL_USERNAME=null +MAIL_PASSWORD=null +MAIL_ENCRYPTION=null +MAIL_FROM_ADDRESS=null +MAIL_FROM_NAME="${APP_NAME}" + +AWS_ACCESS_KEY_ID= +AWS_SECRET_ACCESS_KEY= +AWS_DEFAULT_REGION=us-east-1 +AWS_BUCKET= + +PUSHER_APP_ID= +PUSHER_APP_KEY= +PUSHER_APP_SECRET= +PUSHER_APP_CLUSTER=mt1 + +MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}" +MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}" diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..967315d --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +* text=auto +*.css linguist-vendored +*.scss linguist-vendored +*.js linguist-vendored +CHANGELOG.md export-ignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c4be83d --- /dev/null +++ b/.gitignore @@ -0,0 +1,14 @@ +/node_modules +/public/hot +/public/storage +/storage/*.key +/vendor +/.idea +.env +.env.backup +.phpunit.result.cache +docker-compose.override.yml +Homestead.json +Homestead.yaml +npm-debug.log +yarn-error.log diff --git a/.styleci.yml b/.styleci.yml new file mode 100644 index 0000000..9231873 --- /dev/null +++ b/.styleci.yml @@ -0,0 +1,13 @@ +php: + preset: laravel + disabled: + - no_unused_imports + finder: + not-name: + - index.php + - server.php +js: + finder: + not-name: + - webpack.mix.js +css: true diff --git a/@php b/@php new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md index 6464bd2..e1dcd2e 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,62 @@ -# user_center +

+

+Build Status +Total Downloads +Latest Stable Version +License +

+ +## About Laravel + +Laravel is a web application framework with expressive, elegant syntax. We believe development must be an enjoyable and creative experience to be truly fulfilling. Laravel takes the pain out of development by easing common tasks used in many web projects, such as: + +- [Simple, fast routing engine](https://laravel.com/docs/routing). +- [Powerful dependency injection container](https://laravel.com/docs/container). +- Multiple back-ends for [session](https://laravel.com/docs/session) and [cache](https://laravel.com/docs/cache) storage. +- Expressive, intuitive [database ORM](https://laravel.com/docs/eloquent). +- Database agnostic [schema migrations](https://laravel.com/docs/migrations). +- [Robust background job processing](https://laravel.com/docs/queues). +- [Real-time event broadcasting](https://laravel.com/docs/broadcasting). + +Laravel is accessible, powerful, and provides tools required for large, robust applications. + +## Learning Laravel + +Laravel has the most extensive and thorough [documentation](https://laravel.com/docs) and video tutorial library of all modern web application frameworks, making it a breeze to get started with the framework. + +If you don't feel like reading, [Laracasts](https://laracasts.com) can help. Laracasts contains over 1500 video tutorials on a range of topics including Laravel, modern PHP, unit testing, and JavaScript. Boost your skills by digging into our comprehensive video library. + +## Laravel Sponsors + +We would like to extend our thanks to the following sponsors for funding Laravel development. If you are interested in becoming a sponsor, please visit the Laravel [Patreon page](https://patreon.com/taylorotwell). + +### Premium Partners + +- **[Vehikl](https://vehikl.com/)** +- **[Tighten Co.](https://tighten.co)** +- **[Kirschbaum Development Group](https://kirschbaumdevelopment.com)** +- **[64 Robots](https://64robots.com)** +- **[Cubet Techno Labs](https://cubettech.com)** +- **[Cyber-Duck](https://cyber-duck.co.uk)** +- **[Many](https://www.many.co.uk)** +- **[Webdock, Fast VPS Hosting](https://www.webdock.io/en)** +- **[DevSquad](https://devsquad.com)** +- **[Curotec](https://www.curotec.com/)** +- **[OP.GG](https://op.gg)** + +## Contributing + +Thank you for considering contributing to the Laravel framework! The contribution guide can be found in the [Laravel documentation](https://laravel.com/docs/contributions). + +## Code of Conduct + +In order to ensure that the Laravel community is welcoming to all, please review and abide by the [Code of Conduct](https://laravel.com/docs/contributions#code-of-conduct). + +## Security Vulnerabilities + +If you discover a security vulnerability within Laravel, please send an e-mail to Taylor Otwell via [taylor@laravel.com](mailto:taylor@laravel.com). All security vulnerabilities will be promptly addressed. + +## License + +The Laravel framework is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT). diff --git a/app/Console/Commands/ApiControllerGenerator.php b/app/Console/Commands/ApiControllerGenerator.php new file mode 100644 index 0000000..b0d81c4 --- /dev/null +++ b/app/Console/Commands/ApiControllerGenerator.php @@ -0,0 +1,181 @@ +resolveStubPath('/stubs/controller.model.api.stub'); + } + + /** + * Resolve the fully-qualified path to the stub. + * + * @param string $stub + * @return string + */ + protected function resolveStubPath($stub) + { + return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) + ? $customPath + : __DIR__.$stub; + } + + /** + * Get the default namespace for the class. + * + * @param string $rootNamespace + * @return string + */ + protected function getDefaultNamespace($rootNamespace) + { + return $rootNamespace.'\Http\Controllers\Api'; + } + + /** + * Build the class with the given name. + * + * Remove the base controller import if we are already in base namespace. + * + * @param string $name + * @return string + */ + protected function buildClass($name) + { + $modelClass = $this->parseModel(Str::replaceLast('Controller', 'T', class_basename($name))); + + if (! class_exists($modelClass)) { + if ($this->confirm("A {$modelClass} model does not exist. Do you want to generate it?", true)) { + $this->call('make:apiModel', ['name' => $modelClass]); + } + } + + $resourceClass = $this->qualifyResource(Str::replaceLast('Controller', '', class_basename($name))); + if (! class_exists($resourceClass)) { + if ($this->confirm("A {$resourceClass} resource does not exist. Do you want to generate it?", true)) { + $this->call('make:apiResource', ['name' => $resourceClass]); + } + } + $resourceCollectionClass = $resourceClass . 'Collection'; + if (! class_exists($resourceCollectionClass)) { + if ($this->confirm("A {$resourceCollectionClass} resource collection does not exist. Do you want to generate it?", true)) { + $this->call('make:resource', ['name' => $resourceCollectionClass]); + } + } + + $table_name = env('DB_PREFIX') . Str::snake(str_replace([$this->getNamespace($name).'\\', 'Controller'], ['','T'], $name)); + $columns = DB::select("select COLUMN_NAME,DATA_TYPE,IS_NULLABLE,COLUMN_DEFAULT from information_schema.COLUMNS where table_name = '$table_name'"); + $attributes = ''; + $rules = ''; + foreach ($columns as $column){ + if(!in_array($column->COLUMN_NAME, ['id', 'created_at', 'updated_at'])){ + $attributes .= ' $this->model->'. $column->COLUMN_NAME .' = $this->params[\''. $column->COLUMN_NAME .'\']'; + $rule = " '{$column->COLUMN_NAME}' => '"; + if ($column->IS_NULLABLE == 'NO' && $column->COLUMN_DEFAULT === null) { + $rule .= 'required|'; + } + if(in_array($column->DATA_TYPE, ['int','integer', 'tinyint','smallint','mediumint','bigint','decimal'])){ + $rule .= 'numeric|'; + $attributes .= ' ?? 0'; + } + if(in_array($column->DATA_TYPE, ['varchar','char'])){ + $rule .= 'string|'; + $attributes .= ' ?? \'\''; + } + $attributes .= ';'. PHP_EOL; + if (Str::endsWith($rule,'|')) { + $rules .= Str::replaceLast('|', '', $rule) .'\',' . PHP_EOL; + } + } + + } + + $replace = [ + '{{ namespacedModel }}' => $modelClass, + '{{ model }}' => class_basename($modelClass), + '{{ namespacedResource }}' => $resourceClass, + '{{ resource }}' => class_basename($resourceClass), + '{{ namespacedResourceCollection }}' => $resourceCollectionClass, + '{{ resourceCollection }}' => class_basename($resourceCollectionClass), + '{{ attrList }}' => Str::replaceLast(PHP_EOL, '', $attributes), + '{{ ruleList }}' => Str::replaceLast(PHP_EOL, '', $rules), + ]; + + return str_replace( + array_keys($replace), array_values($replace), parent::buildClass($name) + ); + } + + protected function qualifyResource(string $name) + { + $rootNamespace = $this->rootNamespace(); + + return $rootNamespace. 'Http' . DIRECTORY_SEPARATOR .'Resources'. DIRECTORY_SEPARATOR . $name; + } + + /** + * Get the fully-qualified model class name. + * + * @param string $model + * @return string + * + * @throws \InvalidArgumentException + */ + protected function parseModel($model) + { + if (preg_match('([^A-Za-z0-9_/\\\\])', $model)) { + throw new InvalidArgumentException('Model name contains invalid characters.'); + } + + return $this->qualifyModel($model); + } + + /** + * Get the console command options. + * + * @return array + */ + protected function getOptions() + { + return [ + ['api', null, InputOption::VALUE_NONE, 'Exclude the create and edit methods from the controller.'], + ['force', null, InputOption::VALUE_NONE, 'Create the class even if the controller already exists'], + ['invokable', 'i', InputOption::VALUE_NONE, 'Generate a single method, invokable controller class.'], + ['model', 'm', InputOption::VALUE_OPTIONAL, 'Generate a resource controller for the given model.'], + ['parent', 'p', InputOption::VALUE_OPTIONAL, 'Generate a nested resource controller class.'], + ['resource', 'r', InputOption::VALUE_NONE, 'Generate a resource controller class.'], + ]; + } +} diff --git a/app/Console/Commands/ApiModelGenerator.php b/app/Console/Commands/ApiModelGenerator.php new file mode 100644 index 0000000..71a9aca --- /dev/null +++ b/app/Console/Commands/ApiModelGenerator.php @@ -0,0 +1,186 @@ +option('force')) { + return false; + } + + if ($this->option('all')) { + $this->input->setOption('controller', true); + $this->input->setOption('resource', true); + } + + if ($this->option('resource')) { + $this->createResource(); + } + + if ($this->option('controller')) { + $this->createController(); + } + } + + /** + * Build the class with the given name. + * + * @param string $name + * @return string + * + * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException + */ + protected function buildClass($name) + { + $db_name = DB::connection()->getDatabaseName(); + $table_name = env('DB_PREFIX') . Str::snake(str_replace($this->getNamespace($name).'\\', '', $name)); + + $properties = $attributes = ''; + $columns = DB::select("SELECT COLUMN_NAME,DATA_TYPE,COLUMN_COMMENT,IS_NULLABLE,COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '{$db_name}' AND TABLE_NAME = '{$table_name}'"); + foreach ($columns as $column){ + $properties .= ' * @property $'. $column->COLUMN_NAME . ' ' . $column->DATA_TYPE . PHP_EOL; + if(in_array($column->COLUMN_NAME, ['id', 'created_at', 'updated_at'])) continue; + $attributes .= " '{$column->COLUMN_NAME}' => ['name' => '{$column->COLUMN_NAME}', 'title' => '". ($column->COLUMN_COMMENT ? explode(':', $column->COLUMN_COMMENT)[0] : $column->COLUMN_NAME) ."', 'type' => '{$column->DATA_TYPE}', 'is_must' => '". intval($column->IS_NULLABLE == 'NO' && $column->COLUMN_DEFAULT === null) ."'], " . PHP_EOL; + } + + $replace = [ + '{{ table }}' => $table_name, + '{{ propertiesList }}' => Str::replaceLast(PHP_EOL, '', $properties), + '{{ attrList }}' => Str::replaceLast(PHP_EOL, '', $attributes) + ]; + + return str_replace( + array_keys($replace), array_values($replace), parent::buildClass($name) + ); + } + + protected function generatorProperty(&$stub, $name) + { + $db_name = DB::connection()->getDatabaseName(); + $table_name = env('DB_PREFIX') . Str::snake(str_replace($this->getNamespace($name).'\\', '', $name)); + + $properties = $attributes = ''; + $columns = DB::select("SELECT COLUMN_NAME,DATA_TYPE,COLUMN_COMMENT,IS_NULLABLE,COLUMN_DEFAULT FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '{$db_name}' AND TABLE_NAME = '{$table_name}'"); + foreach ($columns as $column){ + $properties .= ' * @property $'. $column->COLUMN_NAME . ' ' . $column->DATA_TYPE . PHP_EOL; + if(in_array($column->COLUMN_NAME, ['id', 'created_at', 'updated_at'])) continue; + $attributes .= " '{$column->COLUMN_NAME}' => ['name' => '{$column->COLUMN_NAME}', 'title' => '". ($column->COLUMN_COMMENT ? explode(':', $column->COLUMN_COMMENT)[0] : $column->COLUMN_NAME) ."', 'type' => '{$column->DATA_TYPE}', 'is_must' => '". intval($column->IS_NULLABLE == 'NO' && $column->COLUMN_DEFAULT === null) ."'], " . PHP_EOL; + } + + $stub = str_replace(['{{ table }}', '{{ propertiesList }}', '{{ attrList }}'], [$table_name, Str::replaceLast(PHP_EOL, '', $properties), Str::replaceLast(PHP_EOL, '', $attributes)], $stub); + return $this; + } + + /** + * Create a seeder file for the model. + * + * @return void + */ + protected function createResource() + { + $resource = Str::replaceLast('T', '', Str::studly(class_basename($this->argument('name')))); + + $this->call('make:apiResource', [ + 'name' => "{$resource}", + ]); + + $this->call('make:resource', [ + 'name' => "{$resource}Collection", + ]); + } + + /** + * Create a controller for the model. + * + * @return void + */ + protected function createController() + { + $controller = Str::replaceLast('T', '', Str::studly(class_basename($this->argument('name')))); + + $modelName = $this->qualifyClass($this->getNameInput()); + + $this->call('make:apiController', array_filter([ + 'name' => "App\\Http\\Controllers\\Api\\{$controller}Controller", + '--model' => $modelName, + '--api' => true, + ])); + } + + /** + * Get the stub file for the generator. + * + * @return string + */ + protected function getStub() + { + return $this->resolveStubPath('/stubs/model.stub'); + } + + /** + * Resolve the fully-qualified path to the stub. + * + * @param string $stub + * @return string + */ + protected function resolveStubPath($stub) + { + return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) + ? $customPath + : __DIR__.$stub; + } + + /** + * Get the default namespace for the class. + * + * @param string $rootNamespace + * @return string + */ + protected function getDefaultNamespace($rootNamespace) + { + return is_dir(app_path('Models')) ? $rootNamespace.'\\Models' : $rootNamespace; + } + + /** + * Get the console command options. + * + * @return array + */ + protected function getOptions() + { + return [ + ['all', 'a', InputOption::VALUE_NONE, 'Generate a resource and controller for the model'], + ['controller', 'c', InputOption::VALUE_NONE, 'Create a new controller for the model'], + ['force', 'f', InputOption::VALUE_NONE, 'Create the class even if the model already exists'], + ['resource', 'r', InputOption::VALUE_NONE, 'Indicates if the generated controller should be a resource controller'], + ]; + } +} diff --git a/app/Console/Commands/ApiResourceGenerator.php b/app/Console/Commands/ApiResourceGenerator.php new file mode 100644 index 0000000..b2923eb --- /dev/null +++ b/app/Console/Commands/ApiResourceGenerator.php @@ -0,0 +1,127 @@ +collection()) { + $this->type = 'Resource collection'; + } + + parent::handle(); + } + + protected function buildClass($name) + { + $db_name = DB::connection()->getDatabaseName(); + $table_name = env('DB_PREFIX') . Str::snake(str_replace($this->getNamespace($name).'\\', '', $name) . 'T'); + + $properties = ''; + $columns = DB::select("SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '{$db_name}' AND TABLE_NAME = '{$table_name}'"); + foreach ($columns as $column){ + $properties .= ' \''. $column->COLUMN_NAME . '\' => $this->' . $column->COLUMN_NAME . ',' . PHP_EOL; + } + + $replace = [ + '{{ propertiesList }}' => Str::replaceLast(PHP_EOL, '', $properties), + ]; + + return str_replace( + array_keys($replace), array_values($replace), parent::buildClass($name) + ); + + return str_replace( + array_keys($replace), array_values($replace), parent::buildClass($name) + ); + } + + /** + * Get the stub file for the generator. + * + * @return string + */ + protected function getStub() + { + return $this->resolveStubPath('/stubs/resource.stub'); + } + + /** + * Determine if the command is generating a resource collection. + * + * @return bool + */ + protected function collection() + { + return $this->option('collection') || + Str::endsWith($this->argument('name'), 'Collection'); + } + + /** + * Resolve the fully-qualified path to the stub. + * + * @param string $stub + * @return string + */ + protected function resolveStubPath($stub) + { + return file_exists($customPath = $this->laravel->basePath(trim($stub, '/'))) + ? $customPath + : __DIR__.$stub; + } + + /** + * Get the default namespace for the class. + * + * @param string $rootNamespace + * @return string + */ + protected function getDefaultNamespace($rootNamespace) + { + return $rootNamespace.'\Http\Resources'; + } + + /** + * Get the console command options. + * + * @return array + */ + protected function getOptions() + { + return [ + ['collection', 'c', InputOption::VALUE_NONE, 'Create a resource collection'], + ]; + } +} diff --git a/app/Console/Commands/CarModelUpdate.php b/app/Console/Commands/CarModelUpdate.php new file mode 100644 index 0000000..63ab97f --- /dev/null +++ b/app/Console/Commands/CarModelUpdate.php @@ -0,0 +1,216 @@ +tuhu(); + $end_time = time(); + $total_time = $end_time - $begin_time; + $h = floor($total_time/3600); + $m = floor(($total_time - $h * 3600)/60); + $s = $total_time - $h * 3600 - $m * 60; + echo '花费时间: '.$h.'小时'.$m.'分钟'.$s.'秒
'; + } + + private function tuhu(){ + $disk = Storage::disk('oss'); + $brand_infos = json_decode($this->getHtml('https://item.tuhu.cn/Car/GetCarBrands2', 'https://by.tuhu.cn/'), true); + foreach ($brand_infos as $letter => $brands_info) { + if($letter == 'hot'){ + continue; + } + foreach ($brands_info as $brand_info) { + $name = trim(explode('-', $brand_info['Brand'])[1]); + $brand = CarBrandT::where('name',$name)->where('letter',$letter)->first(); + if (!$brand) { + $brand = new CarBrandT(); + $brand->logo = ''; + } + if(!Str::startsWith($brand->logo, 'http://images.banmacar.com')){ + file_put_contents(storage_path(). 'logo.png',file_get_contents('https://img1.tuhu.org'. $brand_info['Url'])); + $filename = $disk->putFile("png/".date('Ymd'), storage_path(). 'logo.png'); + $brand->logo = str_replace('http://bmoc-files.oss-cn-hangzhou.aliyuncs.com', 'http://images.banmacar.com', $disk->getUrl($filename)); + } + $brand->name = $name; + $brand->letter = $letter; + $brand->save(); + $sub_brand_array = []; + $sub_brand_infos = json_decode($this->getHtml('https://item.tuhu.cn/Car/SelOneBrand?Brand='. urlencode($brand_info['Brand']), 'https://by.tuhu.cn/'),true); + foreach ($sub_brand_infos['OneBrand'] as $sub_brand_info) { + if(!isset($sub_brand_array[$sub_brand_info['BrandType']])){ + $sub_brand = CarSubBrandT::where('car_brand_id',$brand->id) + ->where('name',$sub_brand_info['BrandType'])->first(); + if (!$sub_brand) { + $sub_brand = new CarSubBrandT(); + $sub_brand->car_brand_id = $brand->id; + } + $sub_brand->name = $sub_brand_info['BrandType']; + $sub_brand->save(); + echo '----'. $sub_brand_info['BrandType']. '
' . PHP_EOL; + $sub_brand_array[$sub_brand_info['BrandType']] = $sub_brand->id; + } + $series = CarSeriesT::where('car_sub_brand_id',$sub_brand_array[$sub_brand_info['BrandType']]) + ->where('name',$sub_brand_info['CarName'])->first(); + if (!$series) { + $series = new CarSeriesT(); + $series->car_sub_brand_id = $sub_brand_array[$sub_brand_info['BrandType']]; + } + $series->name = $sub_brand_info['CarName']; + $series->save(); + echo '--------'. $sub_brand_info['CarName']. '
' . PHP_EOL; + $displacement_infos = json_decode($this->getHtml('https://item.tuhu.cn/Car/SelectVehicle?VehicleID='. urlencode($sub_brand_info['ProductID']), 'https://by.tuhu.cn/'),true); + foreach ($displacement_infos['PaiLiang'] as $displacement_info) { + $years = json_decode($this->getHtml('https://item.tuhu.cn/Car/SelectVehicle?VehicleID='. urlencode($sub_brand_info['ProductID']) . '&PaiLiang='. urlencode($displacement_info['Value']), 'https://by.tuhu.cn/'),true); + if(!isset($years['Nian'])){ + sleep(3); + $years = json_decode($this->getHtml('https://item.tuhu.cn/Car/SelectVehicle?VehicleID='. urlencode($sub_brand_info['ProductID']) . '&PaiLiang='. urlencode($displacement_info['Value']), 'https://by.tuhu.cn/'),true); + }else if(count($years['Nian']) <= 0){ + continue; + } + $model_years = ''; + foreach ($years['Nian'] as $year) { + $model_years .= $year['Value'] . ','; + } + $model_years = substr($model_years,0,-1); + foreach ($years['Nian'] as $year) { + $model_infos = json_decode($this->getHtml('https://item.tuhu.cn/Car/SelectVehicleSalesName?VehicleID='. urlencode($sub_brand_info['ProductID']) . '&PaiLiang='. urlencode($displacement_info['Value']) . '&Nian='. urlencode($year['Value']), 'https://by.tuhu.cn/'),true); + if(!isset($model_infos['SalesName'])){ + sleep(3); + $model_infos = json_decode($this->getHtml('https://item.tuhu.cn/Car/SelectVehicleSalesName?VehicleID='. urlencode($sub_brand_info['ProductID']) . '&PaiLiang='. urlencode($displacement_info['Value']) . '&Nian='. urlencode($year['Value']), 'https://by.tuhu.cn/'),true); + } + foreach ($model_infos['SalesName'] as $model_info) { + $model = CarModelT::where('car_series_id',$series->id) + ->where('name',$model_info['Name'])->first(); + if (!$model) { + $model = new CarModelT(); + $model->car_series_id = $series->id; + } + $model->year = $year['Value']; + $model->tuhu_code = $model_info['TID']; + $model->modelYears = $model_years; + $model->displacement = $displacement_info['Value']; + $model->name = $model_info['Name']; + $model->save(); + echo '------------'. $model_info['Name']. '
' . PHP_EOL; + } + } + } + } + } + } + echo 'over'; + } + + private function autohome(){ + $brand_html_str = mb_convert_encoding(substr($this->getHtml($this->url . '?' . http_build_query($this->param), 'https://car.autohome.com.cn/'), 18, -2),'utf-8','gbk'); + $brand_content_html = new \simple_html_dom(); + $brand_content_html->load($brand_html_str); + foreach ($brand_content_html->find('.cartree-letter') as $letter_html) { + $letter = $letter_html->plaintext; + $brand_html = $letter_html->next_sibling()->find('h3'); + foreach ($brand_html as $brand_h3) { + $brand_a = $brand_h3->find('a', 0); + $name = $brand_a->plaintext; + $name = substr($name,0,stripos($name,'(')); + $brand = CarBrandT::where('name',$name)->where('letter',$letter)->first(); + preg_match('/\-(\d+)/',$brand_a->href,$match); + if (!$brand) { + $brand = new CarBrandT(); + $brand->uuid = MyLib::uuid(); + echo $name. '
' . PHP_EOL; + } + $brand->name = $name; + $brand->autohome_id = $match[1]; + $brand->letter = $letter; + $series_html_str = mb_convert_encoding(substr($this->getHtml($brand_a->href, 'https://car.autohome.com.cn/'), 18, -2),'utf-8','gbk'); + $series_content_html = new \simple_html_dom(); + $series_content_html->load($series_html_str); + foreach ($brand_content_html->find('.carbradn-cont .list-dl') as $sub_brand_html) { + $sub_brand_a = $sub_brand_html->find('dt a', 0); + $sub_brand = CarSubBrandT::where('car_brand_id',$brand->id)->where('name',$name)->first(); + if (!$sub_brand) { + $sub_brand = new CarSubBrandT(); + $sub_brand->uuid = MyLib::uuid(); + $sub_brand->car_brand_id = $brand->id; + echo $name. '
' . PHP_EOL; + } + $sub_brand->name = $sub_brand_a->plaintext; + $sub_brand->save(); + foreach ($sub_brand_html->find('.list-dl-text a') as $series_a) { + $sub_brand_a = $sub_brand_html->find('dt a', 0); + $sub_brand = CarSubBrandT::where('car_brand_id',$brand->id)->where('name',$name)->first(); + if (!$sub_brand) { + $sub_brand = new CarSubBrandT(); + $sub_brand->uuid = MyLib::uuid(); + $sub_brand->car_brand_id = $brand->id; + echo $name. '
' . PHP_EOL; + } + $sub_brand->name = $sub_brand_a->plaintext; + $sub_brand->save(); + } + } + $brand->logo = $series_content_html->find('.carbradn-pic img',0)->src; + $brand->save(); + } + } + } + + private function getHtml($url,$last_url) + { + // 构造包头,模拟浏览器请求 + $header = array ( + 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36', + ); + $ch = curl_init(); + curl_setopt($ch,CURLOPT_URL, $url); + curl_setopt($ch,CURLOPT_HTTPHEADER, $header); + curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1); + $content = curl_exec($ch); + if ($content == FALSE) { + echo "error:" . curl_error($ch); + } + curl_close($ch); + return $content; + } +} diff --git a/app/Console/Commands/Test.php b/app/Console/Commands/Test.php new file mode 100644 index 0000000..3841e76 --- /dev/null +++ b/app/Console/Commands/Test.php @@ -0,0 +1,46 @@ +keyBy('Field')->toArray()); + exit(); + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php new file mode 100644 index 0000000..69914e9 --- /dev/null +++ b/app/Console/Kernel.php @@ -0,0 +1,41 @@ +command('inspire')->hourly(); + } + + /** + * Register the commands for the application. + * + * @return void + */ + protected function commands() + { + $this->load(__DIR__.'/Commands'); + + require base_path('routes/console.php'); + } +} diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php new file mode 100644 index 0000000..f9644ad --- /dev/null +++ b/app/Exceptions/Handler.php @@ -0,0 +1,40 @@ +reportable(function (Throwable $e) { + // + }); + } +} diff --git a/app/Http/Controllers/Api/AuthController.php b/app/Http/Controllers/Api/AuthController.php new file mode 100644 index 0000000..088ebdc --- /dev/null +++ b/app/Http/Controllers/Api/AuthController.php @@ -0,0 +1,418 @@ + [ + 'rules' => [ + 'username' => 'required', + 'password' => 'required', + ], + 'messages' => [ + 'username.required' => '用户名不能为空', + 'password.required' => '密码不能为空' + ], + ], + 'modifyPassword' => [ + 'rules' => [ + 'id' => 'bail|min:1', + 'oldPassword' => 'required', + 'newPassword' => 'required', + ], + 'custom' => 'exists,App\Models\EmployeeT,id' + ], + 'resetPassword' => [ + 'rules' => [ + 'id' => 'bail|min:1', + ], + 'custom' => 'exists,App\Models\EmployeeT,id' + ], + 'EmployeeAuth' => [ + 'rules' => [ + 'id' => 'bail|min:1', + 'rules' => 'required' + ], + 'custom' => 'exists,App\Models\EmployeeT,id' + ], + 'EmployeeGroupAuth' => [ + 'rules' => [ + 'id' => 'bail|min:1', + 'rules' => 'required' + ], + 'custom' => 'exists,App\Models\EmployeeGroupT,id' + ], + 'store' => [ + 'rules' => [ + 'title' => 'required|max:20', + 'name' => 'bail|required|unique:App\Models\AuthRuleT|max:20', + 'method' => 'required|in:GET,POST,PUT,PATCH,DELETE', + 'group' => 'required', + 'module' => 'required', + ], + 'custom' => [ + 'unique,App\Models\AuthRuleT,name' + ] + ], + 'show' => [ + 'rules' => [ + 'id' => 'bail|min:1', + ], + 'custom' => 'exists,App\Models\AuthRuleT,id' + ], + 'update' => [ + 'rules' => [ + 'id' => 'bail|min:1', + 'title' => 'required|max:20', + 'name' => 'bail|required|max:20', + 'method' => 'required|in:GET,POST,PUT,PATCH,DELETE', + 'group' => 'required', + 'module' => 'required', + ], + 'custom' => [ + 'exists,App\Models\AuthRuleT,id', + 'unique,App\Models\AuthRuleT,name,id' + ] + ], + 'destroy' => [ + 'rules' => [ + 'id' => 'bail|min:1', + ], + 'custom' => [ + 'exists,App\Models\AuthRuleT,id', + ] + ] + ]; + + + public function __construct(Request $request) + { + $this->model = new AuthRuleT(); + parent::__construct($request); + } + + /** + * @title 登录 + * @description 登录授权,返回jwt凭据 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + * @time 2021/1/28 + */ + public function login() + { + if (!$token = auth('api')->attempt([ + 'username' => $this->params['username'], + 'password' => $this->params['password'], + ])) { + return $this->error(401, '登录失败,用户名或密码错误'); + } + + return $this->success([ + 'access_token' => $token, + 'token_type' => 'bearer', + 'expires_in' => auth('api')->factory()->getTTL() * 60 + ]); + } + + /** + * @title 注销登录 + * @description 注销登录,全局退出并通知其他系统退出 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + * @time 2021/1/28 + */ + public function logout() + { + auth('api')->logout(); + return $this->success(); + } + + /** + * @title 刷新token + * @description 刷新token,如果开启黑名单,以前的token便会失效 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + * @time 2021/1/28 + */ + public function refresh() + { + try { + $token = auth('api')->refresh(); + return $this->success([ + 'access_token' => $token, + 'token_type' => 'bearer', + 'expires_in' => auth('api')->factory()->getTTL() * 60 + ]); + } catch (\Exception $e){ + return $this->error(403, '令牌已过期'); + } + } + + /** + * @title 修改密码 + * @description 本人或管理员修改密码 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + * @time 2021/2/2 + */ + public function modifyPassword($id){ + $user = auth('api')->user(); + if($user['id'] != $id && $user['id'] != 1){ + return $this->error(403, '权限不足'); + } + $employee = EmployeeT::find($id); + if(!password_verify($this->params['oldPassword'], $employee['password'])){ + return $this->error(403, '原密码错误'); + }; + $employee->password = password_hash($this->params['newPassword'], PASSWORD_DEFAULT); + if($employee->save()){ + return $this->success('','密码修改成功'); + } else { + return $this->error(500, '配置信息保存失败'); + } + } + + /** + * @title 重置密码 + * @description 管理员重置密码 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + * @time 2021/2/2 + */ + public function resetPassword($id) + { + if(auth('api')->user()['id'] != 1){ + return $this->error(403, '权限不足'); + } + EmployeeT::where('id',$id)->update(['password' => password_hash('123456', PASSWORD_DEFAULT)]); + auth('api')->tokenById('id'); + return $this->success('','密码重置成功'); + } + + /** + * @title 用户授权 + * @description 单用户授权 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + * @time 2021/2/2 + */ + public function EmployeeAuth($id) + { + $user = EmployeeT::find($id); + $authList = $user->getAuthList(); + $rules = array_diff($this->params['rules'], array_intersect($this->params['rules'], $authList)); + $user->rules = implode(',', $rules); + if($user->save()){ + return $this->success('','权限添加成功,用户需重新登录获取权限'); + } else { + return $this->error(500, '配置信息保存失败'); + } + } + + /** + * @title 用户组授权 + * @description 用户组授权 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + * @time 2021/2/3 + */ + public function EmployeeGroupAuth($id) + { + $group = EmployeeGroupT::find($id); + $rules = array_diff($this->params['rules'], array_intersect($this->params['rules'], explode(',',$group->rules))); + $group->rules = implode(',', $rules); + if($group->save()){ + return $this->success('','权限添加成功,用户需重新登录获取权限'); + } else { + return $this->error(500, '配置信息保存失败'); + } + } + + /** + * @title 节点列表 + * @description 权限节点列表 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + * @time 2021/1/28 + */ + public function index() + { + $query = AuthRuleT::query(); + if(isset($this->params['name']) && $this->params['name'] != ''){ + $query->where('name', $this->params['name']); + } + if(isset($this->params['title']) && $this->params['title'] != ''){ + $query->where('title', 'like', '%'. $this->params['title'] .'%'); + } + + if(isset($this->params['status']) && $this->params['status'] >= 0){ + $query->where('status', $this->params['status']); + } else { + $query->where('status', 1); + } + + $data = $query->paginate(); + + return $this->success(new AuthRuleCollection($data)); + } + + /** + * @title 节点新增 + * @description 手动创建节点 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + * @time 2021/1/28 + */ + public function store() + { + $rule = new AuthRuleT(); + $rule->title = $this->params['title']; + $rule->name = $this->params['name']; + $rule->method = $this->params['method'] ?? ''; + $rule->desc = $this->params['desc'] ?? ''; + $rule->module = $this->params['module']; + $rule->group = $this->params['group']; + $rule->condition = $this->params['condition'] ?? ''; + $rule->status = $this->params['status'] ?? 1; + if($rule->save()){ + return $this->success(new AuthRule($rule)); + } else { + return $this->error(500, '配置信息保存失败'); + } + } + + /** + * @title 节点详情 + * @description 节点详情 + * @param $id + * @return mixed + * @author zcstatham + * @time 2021/1/28 + */ + public function show($id) + { + $rule = AuthRuleT::find($id); + return $this->success(new AuthRule($rule)); + } + + /** + * @title 节点更新 + * @description 节点更新 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + * @time 2021/1/28 + */ + public function update($id) + { + $rule = AuthRuleT::find($id); + $rule->title = $this->params['title']; + $rule->name = $this->params['name']; + $rule->method = $this->params['method'] ?? $rule->method; + $rule->desc = $this->params['desc'] ?? $rule->desc; + $rule->module = $this->params['module']; + $rule->group = $this->params['group']; + $rule->condition = $this->params['condition'] ?? $rule->condition; + $rule->status = $this->params['status'] ?? $rule->status; + if($rule->save()){ + return $this->success(new AuthRule($rule)); + } else { + return $this->error(500, '配置信息保存失败'); + } + } + + /** + * @title 节点扫描 + * @description 扫描控制器目录,更新或创建权限节点 + * @return \Illuminate\Http\JsonResponse + * @throws \ReflectionException + * @author zcstatham + * @time 2021/1/28 + */ + public function scanNode(){ + $path = app_path('Http/Controllers'); + $dirs = scandir($path); + $list = []; + foreach ($dirs as $dir) { + if ($dir != '.' && $dir != '..' && is_dir($path . DIRECTORY_SEPARATOR . $dir)) { + $classes = MyLib::scanFile($path . DIRECTORY_SEPARATOR . $dir); + foreach ($classes as $class) { + if($class == 'BaseController'){ + continue; + } + $classname = "App\\Http\\Controllers\\" . $dir . "\\" . $class; + if (class_exists($classname)) { + $reflection = new \ReflectionClass($classname); + $group_doc = MyLib::Parser($reflection->getDocComment()); + $methods = $reflection->getMethods(\ReflectionMethod::IS_FINAL | \ReflectionMethod::IS_PUBLIC); + $group_doc['name'] = $class; + foreach ($methods as $key => $method) { + if (!in_array($method->name, ['__construct'])) { + $title_doc = MyLib::Parser($method->getDocComment()); + $title_doc['param'] = $title_doc['param'] ?? []; + unset($title_doc['param']['Request']); + if (isset($title_doc['title']) && $title_doc['title']) { + $route = app('router')->getRoutes()->getByAction($classname .'@'. $method->name); + $list[] = array( + 'title' => trim($title_doc['title']), + 'name' => $route->uri(), + 'desc' => trim($title_doc['description']), + 'group' => trim($group_doc['title']), + 'method' => $route->methods()[0], + 'module' => $dir, + ); + } + } + } + } + } + } + } + + if(AuthRuleT::upsert($list, ['name', 'module'], ['title', 'desc', 'group'])){ + return $this->success(); + } else { + return $this->error(500,'权限节点更新失败'); + } + } + + /** + * @title 节点删除 + * @description 软删除 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + * @time 2021/1/28 + */ + public function destroy($id) + { + $rule = AuthRuleT::find($id); + $rule->status = 0; + if($rule->save()){ + return $this->success(); + } else { + return $this->error(500, '配置信息保存失败'); + } + } +} diff --git a/app/Http/Controllers/Api/BaseController.php b/app/Http/Controllers/Api/BaseController.php new file mode 100644 index 0000000..e83b6da --- /dev/null +++ b/app/Http/Controllers/Api/BaseController.php @@ -0,0 +1,51 @@ +request = $request; + $this->params = $request->input(); + $this->initialize(); + } + + protected function initialize() { + $this->request->attributes->add([ + 'rules' => $this->rules[explode('@', $this->request->route()->getActionName())[1]] ?? [], + 'attributes' => $this->model->attrs, + ]); + $this->middleware('param_verify'); + } + + protected function success($data = [], $msg = '请求成功', $code = 200) + { + + if($data instanceof ResourceCollection){ + $response = ['code' => $code, 'msg' => $msg] + $data->toArray($this->request); + } else { + $response = ['code' => $code, 'msg' => $msg, 'data' => $data,]; + } + return response()->json($response, $code); + } + + protected function error($code = 400, $msg = '请求失败', $data = []) + { + return response()->json([ + 'code' => $code, + 'msg' => $msg, + 'data' => $data, + ], $code); + } +} diff --git a/app/Http/Controllers/Api/CarBrandController.php b/app/Http/Controllers/Api/CarBrandController.php new file mode 100644 index 0000000..b4df548 --- /dev/null +++ b/app/Http/Controllers/Api/CarBrandController.php @@ -0,0 +1,104 @@ + [ + 'rules' => [ + 'name' => 'required', + ] + ], + 'update' => [ + 'rules' => [ + 'id' => 'bail|min:1', + 'name' => 'required', + ], + 'custom' => [ + 'exists,App\Models\CarBrandT,id', + ] + ], + ]; + + public function __construct(Request $request) + { + $this->model = new CarBrandT(); + parent::__construct($request); + } + + /** + * @title 车辆品牌列表 + * @description 车辆品牌列表 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function index() + { + $query = $this->model->query(); + + if(isset($this->params['name']) && $this->params['name'] != ''){ + $query->where('name', $this->params['name']); + } + + if(isset($this->params['car_brand_id']) && $this->params['car_brand_id'] > 0){ + $query->where('car_brand_id', $this->params['car_brand_id']); + } + + if(isset($this->params['is_page']) && $this->params['is_page'] == 1){ + return $this->success(new CarBrandCollection($query->paginate())); + } else { + return $this->success($query->get()); + } + } + + /** + * @title 车辆品牌保存 + * @description 车辆品牌保存 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function store() + { + $this->model->name = $this->params['name']; + $this->model->logo = $this->params['logo']; + $this->model->letter = $this->params['letter']; + if($this->model->save()){ + return $this->success(new CarBrand($this->model)); + } else { + return $this->error(500, '车辆品牌信息保存失败'); + } + } + + /** + * @title 车辆品牌更新 + * @description 车辆品牌更新 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function update($id) + { + $this->model = $this->model->where('id', $id)->first(); + $this->model->name = $this->params['name']; + $this->model->logo = $this->params['logo']; + $this->model->letter = $this->params['letter']; + if($this->model->save()){ + return $this->success(new CarBrand($this->model)); + } else { + return $this->error(500, '车辆品牌信息保存失败'); + } + } +} diff --git a/app/Http/Controllers/Api/CarInfoController.php b/app/Http/Controllers/Api/CarInfoController.php new file mode 100644 index 0000000..75b4d35 --- /dev/null +++ b/app/Http/Controllers/Api/CarInfoController.php @@ -0,0 +1,178 @@ + [ + 'rules' => [ + 'car_no' => 'required', + 'frame_no' => 'required', + ] + ], + 'show' => [ + 'rules' => [ + 'id' => 'bail|min:1', + ], + 'custom' => 'exists,App\Models\CarInfoT,id' + ], + 'update' => [ + 'rules' => [ + 'id' => 'bail|min:1', + 'car_no' => 'required', + 'frame_no' => 'required', + ], + 'custom' => [ + 'exists,App\Models\CarInfoT,id', + ] + ], + 'destroy' => [ + 'rules' => [ + 'id' => 'bail|min:1', + ], + 'custom' => [ + 'exists,App\Models\CarInfoT,id', + ] + ] + ]; + + public function __construct(Request $request) + { + $this->model = new CarInfoT(); + parent::__construct($request); + } + + /** + * @title 基础列表 + * @description 基础列表 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function index() + { + $query = $this->model->query(); + + if(isset($this->params['name']) && $this->params['name'] != ''){ + $query->where('name', $this->params['name']); + } + + $data = $query->paginate(); + + return $this->success(new CarInfoCollection($data)); + } + + /** + * @title 基础保存 + * @description 基础保存 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function store() + { + $this->model->car_no = $this->params['car_no']; + $this->model->frame_no = $this->params['frame_no']; + $this->model->engine_no = $this->params['engine_no']; + $this->model->factory_model = $this->params['factory_model']; + $this->model->car_used_type = $this->params['car_used_type']; + $this->model->car_man = $this->params['car_man']; + $this->model->purchase_price = $this->params['purchase_price']; + $this->model->register_date = $this->params['register_date']; + $this->model->seat_count = $this->params['seat_count']; + $this->model->insurance_times = $this->params['insurance_times']; + $this->model->insurance_serial_times = $this->params['insurance_serial_times']; + $this->model->repair_times = $this->params['repair_times']; + $this->model->insurance_repair_times = $this->params['insurance_repair_times']; + $this->model->last_insurance_company = $this->params['last_insurance_company']; + $this->model->last_insurance_type = $this->params['last_insurance_type']; + $this->model->last_insurance_rate = $this->params['last_insurance_rate']; + $this->model->last_insurance_salesman = $this->params['last_insurance_salesman']; + $this->model->last_insurance_date = $this->params['last_insurance_date']; + $this->model->force_expire_date = $this->params['force_expire_date']; + $this->model->business_expire_date = $this->params['business_expire_date']; + $this->model->status = $this->params['status']; + if($this->model->save()){ + return $this->success(new CarInfo($this->model)); + } else { + return $this->error(500, '基础信息保存失败'); + } + } + + /** + * @title 基础详情 + * @description 基础详情 + * @param $id + * @return mixed + * @author zcstatham + */ + public function show($id) + { + return $this->success(new CarInfo($this->model->where('id', $id)->first())); + } + + /** + * @title 基础更新 + * @description 基础更新 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function update($id) + { + $this->model = $this->model->where('id', $id)->first(); + $this->model->car_no = $this->params['car_no']; + $this->model->frame_no = $this->params['frame_no']; + $this->model->engine_no = $this->params['engine_no']; + $this->model->factory_model = $this->params['factory_model']; + $this->model->car_used_type = $this->params['car_used_type']; + $this->model->car_man = $this->params['car_man']; + $this->model->purchase_price = $this->params['purchase_price']; + $this->model->register_date = $this->params['register_date']; + $this->model->seat_count = $this->params['seat_count']; + $this->model->insurance_times = $this->params['insurance_times']; + $this->model->insurance_serial_times = $this->params['insurance_serial_times']; + $this->model->repair_times = $this->params['repair_times']; + $this->model->insurance_repair_times = $this->params['insurance_repair_times']; + $this->model->last_insurance_company = $this->params['last_insurance_company']; + $this->model->last_insurance_type = $this->params['last_insurance_type']; + $this->model->last_insurance_rate = $this->params['last_insurance_rate']; + $this->model->last_insurance_salesman = $this->params['last_insurance_salesman']; + $this->model->last_insurance_date = $this->params['last_insurance_date']; + $this->model->force_expire_date = $this->params['force_expire_date']; + $this->model->business_expire_date = $this->params['business_expire_date']; + $this->model->status = $this->params['status']; + if($this->model->save()){ + return $this->success(new CarInfo($this->model)); + } else { + return $this->error(500, '基础信息保存失败'); + } + } + + /** + * @title 基础删除 + * @description 基础删除 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function destroy($id) + { + if($this->model->destroy($id)){ + return $this->success(); + } else { + return $this->error(500, '基础信息保存失败'); + } + } +} diff --git a/app/Http/Controllers/Api/CarModelController.php b/app/Http/Controllers/Api/CarModelController.php new file mode 100644 index 0000000..06953a8 --- /dev/null +++ b/app/Http/Controllers/Api/CarModelController.php @@ -0,0 +1,158 @@ + [ + 'rules' => [ + 'car_series_id' => 'required', + 'name' => 'required', + 'year' => 'required', + ] + ], + 'show' => [ + 'rules' => [ + 'id' => 'bail|min:1', + ], + 'custom' => 'exists,App\Models\CarModelT,id' + ], + 'update' => [ + 'rules' => [ + 'id' => 'bail|min:1', + 'car_series_id' => 'required', + 'name' => 'required', + 'year' => 'required', + ], + 'custom' => [ + 'exists,App\Models\CarModelT,id', + ] + ], + ]; + + public function __construct(Request $request) + { + $this->model = new CarModelT(); + parent::__construct($request); + } + + /** + * @title 基础列表 + * @description 基础列表 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function index() + { + $query = $this->model->query(); + + if(isset($this->params['name']) && $this->params['name'] != ''){ + $query->where('name', $this->params['name']); + } + + if(isset($this->params['is_page']) && $this->params['is_page'] == 1){ + $data = $query->paginate(); + } else { + $data = $query->get(); + } + + return $this->success(new CarModelCollection($data)); + } + + /** + * @title 基础保存 + * @description 基础保存 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function store() + { + $this->model->car_series_id = $this->params['car_series_id']; + $this->model->name = $this->params['name']; + $this->model->year = $this->params['year']; + $this->model->modelYears = $this->params['modelYears']; + $this->model->vehicle_type = $this->params['vehicle_type']; + $this->model->vehicle_size = $this->params['vehicle_size']; + $this->model->engine_model = $this->params['engine_model']; + $this->model->emission_standard = $this->params['emission_standard']; + $this->model->displacement = $this->params['displacement']; + $this->model->induction = $this->params['induction']; + $this->model->fuel_type = $this->params['fuel_type']; + $this->model->transmission_type = $this->params['transmission_type']; + $this->model->transmission_description = $this->params['transmission_description']; + $this->model->gear_number = $this->params['gear_number']; + $this->model->front_tyre = $this->params['front_tyre']; + $this->model->rear_tyre = $this->params['rear_tyre']; + $this->model->doors = $this->params['doors']; + $this->model->seats = $this->params['seats']; + $this->model->tuhu_code = $this->params['tuhu_code']; + $this->model->guidance_price = $this->params['guidance_price']; + if($this->model->save()){ + return $this->success(new CarModel($this->model)); + } else { + return $this->error(500, '基础信息保存失败'); + } + } + + /** + * @title 基础详情 + * @description 基础详情 + * @param $id + * @return mixed + * @author zcstatham + */ + public function show($id) + { + return $this->success(new CarModel($this->model->where('id', $id)->first())); + } + + /** + * @title 基础更新 + * @description 基础更新 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function update($id) + { + $this->model = $this->model->where('id', $id)->first(); + $this->model->car_series_id = $this->params['car_series_id']; + $this->model->name = $this->params['name']; + $this->model->year = $this->params['year']; + $this->model->modelYears = $this->params['modelYears']; + $this->model->vehicle_type = $this->params['vehicle_type']; + $this->model->vehicle_size = $this->params['vehicle_size']; + $this->model->engine_model = $this->params['engine_model']; + $this->model->emission_standard = $this->params['emission_standard']; + $this->model->displacement = $this->params['displacement']; + $this->model->induction = $this->params['induction']; + $this->model->fuel_type = $this->params['fuel_type']; + $this->model->transmission_type = $this->params['transmission_type']; + $this->model->transmission_description = $this->params['transmission_description']; + $this->model->gear_number = $this->params['gear_number']; + $this->model->front_tyre = $this->params['front_tyre']; + $this->model->rear_tyre = $this->params['rear_tyre']; + $this->model->doors = $this->params['doors']; + $this->model->seats = $this->params['seats']; + $this->model->tuhu_code = $this->params['tuhu_code']; + $this->model->guidance_price = $this->params['guidance_price']; + if($this->model->save()){ + return $this->success(new CarModel($this->model)); + } else { + return $this->error(500, '基础信息保存失败'); + } + } +} diff --git a/app/Http/Controllers/Api/CarSeriesController.php b/app/Http/Controllers/Api/CarSeriesController.php new file mode 100644 index 0000000..70551ec --- /dev/null +++ b/app/Http/Controllers/Api/CarSeriesController.php @@ -0,0 +1,192 @@ + [ + 'rules' => [ + 'car_sub_brand_id' => 'required|numeric', + 'name' => 'required|string', + 'series' => 'string', + 'level' => 'string', + 'externalPanelPrice' => 'numeric', + 'internalPanelPrice' => 'numeric', + 'externalPaintPrice' => 'numeric', + 'internalPaintPrice' => 'numeric', + 'externalUnderPrice' => 'numeric', + 'internalUnderPrice' => 'numeric', + 'externalPolishPrice' => 'numeric', + 'internalPolishPrice' => 'numeric', + 'externalRepairPrice' => 'numeric', + 'internalRepairPrice' => 'numeric', + 'externalOutreachPrice' => 'numeric', + ] + ], + 'show' => [ + 'rules' => [ + 'id' => 'bail|min:1', + ], + 'custom' => 'exists,App\Models\CarSeriesT,id' + ], + 'update' => [ + 'rules' => [ + 'id' => 'bail|min:1', + 'car_sub_brand_id' => 'required|numeric', + 'name' => 'required|string', + 'series' => 'string', + 'level' => 'string', + 'externalPanelPrice' => 'numeric', + 'internalPanelPrice' => 'numeric', + 'externalPaintPrice' => 'numeric', + 'internalPaintPrice' => 'numeric', + 'externalUnderPrice' => 'numeric', + 'internalUnderPrice' => 'numeric', + 'externalPolishPrice' => 'numeric', + 'internalPolishPrice' => 'numeric', + 'externalRepairPrice' => 'numeric', + 'internalRepairPrice' => 'numeric', + 'externalOutreachPrice' => 'numeric', + ], + 'custom' => [ + 'exists,App\Models\CarSeriesT,id', + ] + ], + 'destroy' => [ + 'rules' => [ + 'id' => 'bail|min:1', + ], + 'custom' => [ + 'exists,App\Models\CarSeriesT,id', + ] + ] + ]; + + public function __construct(Request $request) + { + $this->model = new CarSeriesT(); + parent::__construct($request); + } + + /** + * @title 基础列表 + * @description 基础列表 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function index() + { + $query = $this->model->query(); + + if(isset($this->params['name']) && $this->params['name'] > 0){ + $query->where('name', $this->params['name']); + } + + $data = $query->paginate(); + + return $this->success(new CarSeriesCollection($data)); + } + + /** + * @title 基础保存 + * @description 基础保存 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function store() + { + $this->model->car_sub_brand_id = $this->params['car_sub_brand_id'] ?? 0; + $this->model->name = $this->params['name'] ?? ''; + $this->model->series = $this->params['series'] ?? ''; + $this->model->level = $this->params['level'] ?? ''; + $this->model->externalPanelPrice = $this->params['externalPanelPrice'] ?? 0; + $this->model->internalPanelPrice = $this->params['internalPanelPrice'] ?? 0; + $this->model->externalPaintPrice = $this->params['externalPaintPrice'] ?? 0; + $this->model->internalPaintPrice = $this->params['internalPaintPrice'] ?? 0; + $this->model->externalUnderPrice = $this->params['externalUnderPrice'] ?? 0; + $this->model->internalUnderPrice = $this->params['internalUnderPrice'] ?? 0; + $this->model->externalPolishPrice = $this->params['externalPolishPrice'] ?? 0; + $this->model->internalPolishPrice = $this->params['internalPolishPrice'] ?? 0; + $this->model->externalRepairPrice = $this->params['externalRepairPrice'] ?? 0; + $this->model->internalRepairPrice = $this->params['internalRepairPrice'] ?? 0; + $this->model->externalOutreachPrice = $this->params['externalOutreachPrice'] ?? 0; + if($this->model->save()){ + return $this->success(new CarSeries($this->model)); + } else { + return $this->error(500, '基础信息保存失败'); + } + } + + /** + * @title 基础详情 + * @description 基础详情 + * @param $id + * @return mixed + * @author zcstatham + */ + public function show($id) + { + return $this->success(new CarSeries($this->model->where('id', $id)->first())); + } + + /** + * @title 基础更新 + * @description 基础更新 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function update($id) + { + $this->model = $this->model->where('id', $id)->first(); + $this->model->car_sub_brand_id = $this->params['car_sub_brand_id'] ?? 0; + $this->model->name = $this->params['name'] ?? ''; + $this->model->series = $this->params['series'] ?? ''; + $this->model->level = $this->params['level'] ?? ''; + $this->model->externalPanelPrice = $this->params['externalPanelPrice'] ?? 0; + $this->model->internalPanelPrice = $this->params['internalPanelPrice'] ?? 0; + $this->model->externalPaintPrice = $this->params['externalPaintPrice'] ?? 0; + $this->model->internalPaintPrice = $this->params['internalPaintPrice'] ?? 0; + $this->model->externalUnderPrice = $this->params['externalUnderPrice'] ?? 0; + $this->model->internalUnderPrice = $this->params['internalUnderPrice'] ?? 0; + $this->model->externalPolishPrice = $this->params['externalPolishPrice'] ?? 0; + $this->model->internalPolishPrice = $this->params['internalPolishPrice'] ?? 0; + $this->model->externalRepairPrice = $this->params['externalRepairPrice'] ?? 0; + $this->model->internalRepairPrice = $this->params['internalRepairPrice'] ?? 0; + $this->model->externalOutreachPrice = $this->params['externalOutreachPrice'] ?? 0; + if($this->model->save()){ + return $this->success(new CarSeries($this->model)); + } else { + return $this->error(500, '基础信息保存失败'); + } + } + + /** + * @title 基础删除 + * @description 基础删除 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function destroy($id) + { + if($this->model->destroy($id)){ + return $this->success(); + } else { + return $this->error(500, '基础信息保存失败'); + } + } +} diff --git a/app/Http/Controllers/Api/CarSubBrandController.php b/app/Http/Controllers/Api/CarSubBrandController.php new file mode 100644 index 0000000..a8a78ba --- /dev/null +++ b/app/Http/Controllers/Api/CarSubBrandController.php @@ -0,0 +1,132 @@ + [ + 'rules' => [ + 'car_brand_id' => 'required', + 'name' => 'required', + ] + ], + 'update' => [ + 'rules' => [ + 'id' => 'bail|min:1', + 'car_brand_id' => 'required', + 'name' => 'required', + ], + 'custom' => [ + 'exists,App\Models\CarSubBrandT,id', + ] + ], + ]; + + public function __construct(Request $request) + { + $this->model = new CarSubBrandT(); + parent::__construct($request); + } + + /** + * @title 厂家列表 + * @description 厂家列表 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function index() + { + $query = $this->model->query(); + + if(isset($this->params['name']) && $this->params['name'] != ''){ + $query->where('name', $this->params['name']); + } + + if(isset($this->params['car_brand_id']) && $this->params['car_brand_id'] > 0){ + $query->where('car_brand_id', $this->params['car_brand_id']); + } + + if(isset($this->params['is_page']) && $this->params['is_page'] == 1){ + return $this->success(new CarSubBrandCollection($query->paginate())); + } else { + return $this->success($query->get()); + } + } + + /** + * @title 厂家保存 + * @description 厂家保存 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function store() + { + $this->model->car_brand_id = $this->params['car_brand_id']; + $this->model->name = $this->params['name']; + if($this->model->save()){ + return $this->success(new CarSubBrand($this->model)); + } else { + return $this->error(500, '厂家信息保存失败'); + } + } + + /** + * @title 厂家详情 + * @description 厂家详情 + * @param $id + * @return mixed + * @author zcstatham + */ + public function show($id) + { + return $this->success(new CarSubBrand($this->model->where('id', $id)->first())); + } + + /** + * @title 厂家更新 + * @description 厂家更新 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function update($id) + { + $this->model = $this->model->where('id', $id)->first(); + $this->model->car_brand_id = $this->params['car_brand_id']; + $this->model->name = $this->params['name']; + if($this->model->save()){ + return $this->success(new CarSubBrand($this->model)); + } else { + return $this->error(500, '厂家信息保存失败'); + } + } + + /** + * @title 厂家删除 + * @description 厂家删除 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function destroy($id) + { + if($this->model->destroy($id)){ + return $this->success(); + } else { + return $this->error(500, '厂家信息保存失败'); + } + } +} diff --git a/app/Http/Controllers/Api/CommonController.php b/app/Http/Controllers/Api/CommonController.php new file mode 100644 index 0000000..700f9a9 --- /dev/null +++ b/app/Http/Controllers/Api/CommonController.php @@ -0,0 +1,34 @@ + [ + 'rules' => [ + 'file' => 'required', + 'file_type' => 'required' + ] + ] + ]; + + public function upload(Request $request) { + $file = $request->file('file'); + $fileType = $request->input('file_type','files'); + $disk = Storage::disk('oss'); + $filename = $disk->putFile($fileType."/".date('Ymd'), $file); + $url = str_replace('http://bmoc-files.oss-cn-hangzhou.aliyuncs.com', 'http://images.banmacar.com', $disk->getUrl($filename)); + return $this->success(['url' => $url]); + } +} diff --git a/app/Http/Controllers/Api/CompanyController.php b/app/Http/Controllers/Api/CompanyController.php new file mode 100644 index 0000000..6f81268 --- /dev/null +++ b/app/Http/Controllers/Api/CompanyController.php @@ -0,0 +1,155 @@ + [ + 'rules' => [ + 'title' => 'bail|required|unique:App\Models\CompanyT|max:20', + 'name' => 'bail|required|unique:App\Models\CompanyT|max:20', + 'pid' => 'required', + ] + ], + 'show' => [ + 'rules' => [ + 'id' => 'bail|inter|min:1', + ], + 'custom' => 'exists,App\Models\CompanyT,id' + ], + 'update' => [ + 'rules' => [ + 'id' => 'bail|inter|min:1', + 'title' => 'required|max:20', + 'name' => 'bail|required|max:20', + 'pid' => 'required', + ], + 'custom' => [ + 'exists,App\Models\CompanyT,id', + 'unique,App\Models\CompanyT,title,id', + 'unique,App\Models\CompanyT,name,id' + ] + ], + 'destroy' => [ + 'rules' => [ + 'id' => 'bail|inter|min:1', + ], + 'custom' => [ + 'exists,App\Models\CompanyT,id', + ] + ] + ]; + + public function __construct(Request $request) + { + $this->model = new CompanyT(); + parent::__construct($request); + } + + /** + * @title 公司列表 + * @description 公司列表 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + * @time 2021/1/28 + */ + public function index() + { + $query = CompanyT::query(); + if(isset($this->params['name']) && $this->params['name'] != ''){ + $query->where('name', $this->params['name']); + } + if(isset($this->params['title']) && $this->params['title'] != ''){ + $query->where('title', 'like', '%'. $this->params['title'] .'%'); + } + + $data = $query->paginate(); + + return $this->success(new CompanyCollection($data)); + } + + /** + * @title 公司新增 + * @description 公司新增 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + * @time 2021/1/28 + */ + public function store() + { + $company = new CompanyT(); + $company->title = $this->params['title']; + $company->name = $this->params['name']; + $company->pid = $this->params['pid']; + if($company->save()){ + return $this->success(new Company($company)); + } else { + return $this->error(500, '配置信息保存失败'); + } + } + + /** + * @title 公司详情 + * @description 公司详情 + * @param $id + * @return mixed + * @author zcstatham + * @time 2021/1/28 + */ + public function show($id) + { + return $this->success(new Company($this->model->where('id', $id)->first())); + } + + /** + * @title 公司更新 + * @description 公司更新 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + * @time 2021/1/28 + */ + public function update($id) + { + $company = $this->model->where('id', $id)->first(); + $company->title = $this->params['title']; + $company->name = $this->params['name']; + $company->pid = $this->params['pid']; + if($company->save()){ + return $this->success(new Company($company)); + } else { + return $this->error(500, '配置信息保存失败'); + } + } + + /** + * @title 公司删除 + * @description 公司删除 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + * @time 2021/1/28 + */ + public function destroy($id) + { + if(CompanyT::destroy($id)){ + return $this->success(); + } else { + return $this->error(500, '配置信息保存失败'); + } + } +} diff --git a/app/Http/Controllers/Api/DictionaryController.php b/app/Http/Controllers/Api/DictionaryController.php new file mode 100644 index 0000000..83394c4 --- /dev/null +++ b/app/Http/Controllers/Api/DictionaryController.php @@ -0,0 +1,160 @@ + [ + 'rules' => [ + 'name' => 'required', + 'title' => 'required', + ], + 'custom' => 'unique,App\Models\DictionaryT,pid,name' + + ], + 'show' => [ + 'rules' => [ + 'id' => 'bail|min:1', + ], + 'custom' => 'exists,App\Models\DictionaryT,id' + ], + 'update' => [ + 'rules' => [ + 'id' => 'bail|min:1', + 'name' => 'required', + 'title' => 'required', + ], + 'custom' => [ + 'exists,App\Models\DictionaryT,id', + 'custom' => 'unique,App\Models\DictionaryT,pid,name,id' + ] + ], + 'destroy' => [ + 'rules' => [ + 'id' => 'bail|min:1', + ], + 'custom' => [ + 'exists,App\Models\DictionaryT,id', + ] + ] + ]; + + public function __construct(Request $request) + { + $this->model = new DictionaryT(); + parent::__construct($request); + } + + /** + * @title 字典列表 + * @description 字典列表 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function index() + { + $query = $this->model->query(); + + if(isset($this->params['name']) && $this->params['name'] != ''){ + $query->where('name', $this->params['name']); + } + + if(isset($this->params['title']) && $this->params['title'] > 0){ + $query->where('title', $this->params['title']); + } + + if(isset($this->params['status']) && $this->params['status'] >= 0){ + $query->where('status', $this->params['status']); + } else { + $query->where('status', 1); + } + + $data = $query->paginate(); + + return $this->success(new DictionaryCollection($data)); + } + + /** + * @title 字典保存 + * @description 字典保存 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function store() + { + $this->model->pid = $this->params['pid'] ?? 0; + $this->model->name = $this->params['name']; + $this->model->title = $this->params['title']; + $this->model->status = $this->params['status'] ?? '1'; + if($this->model->save()){ + return $this->success(new Dictionary($this->model)); + } else { + return $this->error(500, '字典信息保存失败'); + } + } + + /** + * @title 字典详情 + * @description 字典详情 + * @param $id + * @return mixed + * @author zcstatham + */ + public function show($id) + { + return $this->success(new Dictionary($this->model->where('id', $id)->first())); + } + + /** + * @title 字典更新 + * @description 字典更新 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function update($id) + { + $this->model = $this->model->where('id', $id)->first(); + $this->model->pid = $this->params['pid'] ?? $this->model->pid; + $this->model->name = $this->params['name']; + $this->model->title = $this->params['title']; + $this->model->status = $this->params['status'] ?? $this->model->status; + if($this->model->save()){ + return $this->success(new Dictionary($this->model)); + } else { + return $this->error(500, '字典信息保存失败'); + } + } + + /** + * @title 字典删除 + * @description 字典删除 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function destroy($id) + { + $this->model = $this->model->where('id', $id)->first(); + $this->model->status = 0; + if($this->model->save()){ + return $this->success(); + } else { + return $this->error(500, '字典信息保存失败'); + } + } +} diff --git a/app/Http/Controllers/Api/EmployeeBankController.php b/app/Http/Controllers/Api/EmployeeBankController.php new file mode 100644 index 0000000..61d57d1 --- /dev/null +++ b/app/Http/Controllers/Api/EmployeeBankController.php @@ -0,0 +1,165 @@ + [ + 'rules' => [ + 'employee_id' => 'required', + 'super_bank_name' => 'required', + 'bank_name' => 'required', + 'bank_code' => 'required', + 'bank_num' => 'required', + 'bank_man' => 'required', + 'maximum' => 'max:10000000', + ], + 'custom' => 'unique,App\Models\EmployeeBankT,bank_num' + ], + 'show' => [ + 'rules' => [ + 'id' => 'bail|min:1', + ], + 'custom' => 'exists,App\Models\EmployeeBankT,id' + ], + 'update' => [ + 'rules' => [ + 'id' => 'bail|min:1', + 'employee_id' => 'required', + 'super_bank_name' => 'required', + 'bank_name' => 'required', + 'bank_code' => 'required', + 'bank_num' => 'required', + 'bank_man' => 'required', + 'maximum' => 'max:10000000', + ], + 'custom' => [ + 'exists,App\Models\EmployeeBankT,id', + 'unique,App\Models\EmployeeBankT,bank_num,id' + ] + ], + 'destroy' => [ + 'rules' => [ + 'id' => 'bail|min:1', + ], + 'custom' => [ + 'exists,App\Models\EmployeeBankT,id', + ] + ] + ]; + + public function __construct(Request $request) + { + $this->model = new EmployeeBankT(); + parent::__construct($request); + } + + /** + * @title 银行卡列表 + * @description 银行卡列表 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function index() + { + $query = $this->model->query(); + + if(isset($this->params['name']) && $this->params['name'] != ''){ + $query->where('name', $this->params['name']); + } + + $data = $query->paginate(); + + return $this->success(new EmployeeBankCollection($data)); + } + + /** + * @title 银行卡保存 + * @description 银行卡保存 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function store() + { + $this->model->employee_id = $this->params['employee_id']; + $this->model->super_bank_name = $this->params['super_bank_name']; + $this->model->bank_name = $this->params['bank_name']; + $this->model->bank_code = $this->params['bank_code']; + $this->model->bank_num = $this->params['bank_num']; + $this->model->bank_man = $this->params['bank_man']; + $this->model->maximum = $this->params['maximum']; + $this->model->priority = $this->params['priority']; + if($this->model->save()){ + return $this->success(new EmployeeBank($this->model)); + } else { + return $this->error(500, '银行卡信息保存失败'); + } + } + + /** + * @title 银行卡详情 + * @description 银行卡详情 + * @param $id + * @return mixed + * @author zcstatham + */ + public function show($id) + { + return $this->success(new EmployeeBank($this->model->where('id', $id)->first())); + } + + /** + * @title 银行卡更新 + * @description 银行卡更新 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function update($id) + { + $this->model = $this->model->where('id', $id)->first(); + $this->model->employee_id = $this->params['employee_id']; + $this->model->super_bank_name = $this->params['super_bank_name']; + $this->model->bank_name = $this->params['bank_name']; + $this->model->bank_code = $this->params['bank_code']; + $this->model->bank_num = $this->params['bank_num']; + $this->model->bank_man = $this->params['bank_man']; + $this->model->maximum = $this->params['maximum']; + $this->model->priority = $this->params['priority']; + if($this->model->save()){ + return $this->success(new EmployeeBank($this->model)); + } else { + return $this->error(500, '银行卡信息保存失败'); + } + } + + /** + * @title 银行卡删除 + * @description 银行卡删除 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function destroy($id) + { + if($this->model->destroy($id)){ + return $this->success(); + } else { + return $this->error(500, '银行卡信息保存失败'); + } + } +} diff --git a/app/Http/Controllers/Api/EmployeeController.php b/app/Http/Controllers/Api/EmployeeController.php new file mode 100644 index 0000000..ff4dee4 --- /dev/null +++ b/app/Http/Controllers/Api/EmployeeController.php @@ -0,0 +1,170 @@ + [ + 'rules' => [ + 'username' => 'required', + 'nickname' => 'required', + ] + ], + 'show' => [ + 'rules' => [ + 'id' => 'bail|integer|min:1', + ], + 'custom' => 'exists,App\Models\EmployeeT,id' + ], + 'update' => [ + 'rules' => [ + 'id' => 'bail|integer|min:1', + 'username' => 'required', + 'nickname' => 'required', + ], + 'custom' => [ + 'exists,App\Models\EmployeeT,id', + ] + ], + 'destroy' => [ + 'rules' => [ + 'id' => 'bail|integer|min:1', + ], + 'custom' => [ + 'exists,App\Models\EmployeeT,id', + ] + ] + ]; + + public function __construct(Request $request) + { + $this->model = new EmployeeT(); + parent::__construct($request); + } + + /** + * @title 员工列表 + * @description 员工列表 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function index() + { + $query = $this->model->query(); + + if(isset($this->params['name']) && $this->params['name'] != ''){ + $query->where('name', $this->params['name']); + } + + if(isset($this->params['status']) && $this->params['status'] >= 0){ + $query->where('status', $this->params['status']); + } else { + $query->where('status', 3); + } + + $data = $query->paginate(); + + return $this->success(new EmployeeCollection($data)); + } + + /** + * @title 员工保存 + * @description 员工保存 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function store() + { + $this->model->username = $this->params['username']; + $this->model->nickname = $this->params['nickname']; + $this->model->password = password_hash($this->params['password']??'123456', PASSWORD_DEFAULT ); + $this->model->company_id = $this->params['company_id']; + $this->model->group_id = $this->params['group_id']; + $this->model->phone = $this->params['phone']; + $this->model->monthly_working_days = $this->params['monthly_working_days']; + $this->model->entry_date = $this->params['entry_date']; + $this->model->official_date = $this->params['official_date']; + $this->model->resign_date = $this->params['resign_date']; + $this->model->probation_salary = $this->params['probation_salary']; + $this->model->official_salary = $this->params['official_salary']; + $this->model->is_outer = $this->params['is_outer']; + $this->model->status = $this->params['status']; + if($this->model->save()){ + return $this->success(new Employee($this->model)); + } else { + return $this->error(500, '员工信息保存失败'); + } + } + + /** + * @title 员工详情 + * @description 员工详情 + * @param $id + * @return mixed + * @author zcstatham + */ + public function show($id) + { + return $this->success(new Employee($this->model->where('id', $id)->first())); + } + + /** + * @title 员工更新 + * @description 员工更新 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function update($id) + { + $this->model = $this->model->where('id', $id)->first(); + $this->model->username = $this->params['username']; + $this->model->nickname = $this->params['nickname']; + $this->model->company_id = $this->params['company_id']; + $this->model->group_id = $this->params['group_id']; + $this->model->phone = $this->params['phone']; + $this->model->monthly_working_days = $this->params['monthly_working_days']; + $this->model->entry_date = $this->params['entry_date']; + $this->model->official_date = $this->params['official_date']; + $this->model->resign_date = $this->params['resign_date']; + $this->model->probation_salary = $this->params['probation_salary']; + $this->model->official_salary = $this->params['official_salary']; + $this->model->is_outer = $this->params['is_outer']; + $this->model->status = $this->params['status']; + if($this->model->save()){ + return $this->success(new Employee($this->model)); + } else { + return $this->error(500, '员工信息保存失败'); + } + } + + /** + * @title 员工删除 + * @description 员工删除 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function destroy($id) + { + if($this->model->destroy($id)){ + return $this->success(); + } else { + return $this->error(500, '员工信息保存失败'); + } + } +} diff --git a/app/Http/Controllers/Api/EmployeeGroupController.php b/app/Http/Controllers/Api/EmployeeGroupController.php new file mode 100644 index 0000000..1fe6a19 --- /dev/null +++ b/app/Http/Controllers/Api/EmployeeGroupController.php @@ -0,0 +1,143 @@ + [ + 'rules' => [ + 'title' => 'required', + 'pid' => 'required', + ] + ], + 'show' => [ + 'rules' => [ + 'id' => 'bail|min:1', + ], + 'custom' => 'exists,App\Models\EmployeeGroupT,id' + ], + 'update' => [ + 'rules' => [ + 'id' => 'bail|min:1', + 'pid' => 'required', + 'title' => 'required', + ], + 'custom' => [ + 'exists,App\Models\EmployeeGroupT,id', + ] + ], + 'destroy' => [ + 'rules' => [ + 'id' => 'bail|min:1', + ], + 'custom' => [ + 'exists,App\Models\EmployeeGroupT,id', + ] + ] + ]; + + public function __construct(Request $request) + { + $this->model = new EmployeeGroupT(); + parent::__construct($request); + } + + /** + * @title 岗位列表 + * @description 岗位列表 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function index() + { + $data = $this->model->getTree($this->params['status'] ?? null, $this->params['pid'] ?? 0); + + return $this->success($data); + } + + /** + * @title 岗位保存 + * @description 岗位保存 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function store() + { + $this->model->pid = $this->params['pid']; + $this->model->title = $this->params['title']; + $this->model->level = $this->params['level']; + $this->model->description = $this->params['description'] ?? ''; + $this->model->base_salary = $this->params['base_salary'] ?? 0; + $this->model->status = $this->params['status'] ?? 2; + if($this->model->save()){ + return $this->success(new EmployeeGroup($this->model)); + } else { + return $this->error(500, '岗位信息保存失败'); + } + } + + /** + * @title 岗位详情 + * @description 岗位详情 + * @param $id + * @return mixed + * @author zcstatham + */ + public function show($id) + { + return $this->success(new EmployeeGroup($this->model->where('id', $id)->first())); + } + + /** + * @title 岗位更新 + * @description 岗位更新 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function update($id) + { + $this->model = $this->model->where('id', $id)->first(); + $this->model->pid = $this->params['pid']; + $this->model->title = $this->params['title']; + $this->model->level = $this->params['level'] ?? $this->model->level; + $this->model->description = $this->params['description'] ?? $this->model->description; + $this->model->base_salary = $this->params['base_salary'] ?? $this->model->base_salary; + $this->model->status = $this->params['status'] ?? $this->model->status; + if($this->model->save()){ + return $this->success(new EmployeeGroup($this->model)); + } else { + return $this->error(500, '岗位信息保存失败'); + } + } + + /** + * @title 岗位删除 + * @description 岗位删除 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function destroy($id) + { + if($this->model->where('id', $id)->update(['status' => 0])){ + return $this->success(); + } else { + return $this->error(500, '岗位信息保存失败'); + } + } +} diff --git a/app/Http/Controllers/Api/EmployeeRewardPunishmentController.php b/app/Http/Controllers/Api/EmployeeRewardPunishmentController.php new file mode 100644 index 0000000..43d4584 --- /dev/null +++ b/app/Http/Controllers/Api/EmployeeRewardPunishmentController.php @@ -0,0 +1,157 @@ + [ + 'rules' => [ + 'employee_id' => 'required', + 'type' => 'required', + 'date' => 'required|date', + 'price' => 'required', + ], + 'custom' => [ + 'unique,App\Models\EmployeeRewardPunishmentT,date,type' + ] + ], + 'show' => [ + 'rules' => [ + 'id' => 'bail|min:1', + ], + 'custom' => 'exists,App\Models\EmployeeRewardPunishmentT,id' + ], + 'update' => [ + 'rules' => [ + 'id' => 'bail|min:1', + 'employee_id' => 'required', + 'type' => 'required', + 'date' => 'required|date', + 'price' => 'required', + ], + 'custom' => [ + 'exists,App\Models\EmployeeRewardPunishmentT,id', + 'unique,App\Models\EmployeeRewardPunishmentT,date,type,id' + ] + ], + 'destroy' => [ + 'rules' => [ + 'id' => 'bail|min:1', + ], + 'custom' => [ + 'exists,App\Models\EmployeeRewardPunishmentT,id', + ] + ] + ]; + + public function __construct(Request $request) + { + $this->model = new EmployeeRewardPunishmentT(); + parent::__construct($request); + } + + /** + * @title 奖惩列表 + * @description 奖惩列表 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function index() + { + $query = $this->model->query(); + + if(isset($this->params['name']) && $this->params['name'] != ''){ + $query->where('name', $this->params['name']); + } + + $data = $query->paginate(); + + return $this->success(new EmployeeRewardPunishmentCollection($data)); + } + + /** + * @title 奖惩保存 + * @description 奖惩保存 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function store() + { + $this->model->employee_id = $this->params['employee_id']; + $this->model->type = $this->params['type']; + $this->model->price = $this->params['type'] > 600 ? abs($this->params['price']) : -abs($this->params['price']); + $this->model->remark = $this->params['remark'] ?? ''; + $this->model->date = $this->params['date'] ?? ''; + $this->model->status = $this->params['status'] ?? 1; + if($this->model->save()){ + return $this->success(new EmployeeRewardPunishment($this->model)); + } else { + return $this->error(500, '奖惩信息保存失败'); + } + } + + /** + * @title 奖惩详情 + * @description 奖惩详情 + * @param $id + * @return mixed + * @author zcstatham + */ + public function show($id) + { + return $this->success(new EmployeeRewardPunishment($this->model->where('id', $id)->first())); + } + + /** + * @title 奖惩更新 + * @description 奖惩更新 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function update($id) + { + $this->model = $this->model->where('id', $id)->first(); + $this->model->employee_id = $this->params['employee_id']; + $this->model->type = $this->params['type']; + $this->model->price = $this->params['type'] > 600 ? abs($this->params['price']) : -abs($this->params['price']); + $this->model->remark = $this->params['remark'] ?? $this->model->remark; + if($this->model->save()){ + return $this->success(new EmployeeRewardPunishment($this->model)); + } else { + return $this->error(500, '奖惩信息保存失败'); + } + } + + /** + * @title 奖惩删除 + * @description 奖惩删除 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function destroy($id) + { + $this->model = $this->model::find($id); + $this->model->status = 0; + if($this->model->save()){ + return $this->success(); + } else { + return $this->error(500, '奖惩信息保存失败'); + } + } +} diff --git a/app/Http/Controllers/Api/EmployeeSocialItemsController.php b/app/Http/Controllers/Api/EmployeeSocialItemsController.php new file mode 100644 index 0000000..28586b3 --- /dev/null +++ b/app/Http/Controllers/Api/EmployeeSocialItemsController.php @@ -0,0 +1,157 @@ + [ + 'rules' => [ + 'employee_id' => 'required', + 'social_type' => 'required', + 'base_price' => 'required', + 'personal_rate' => 'required', + 'unit_rate' => 'required', + ] + ], + 'show' => [ + 'rules' => [ + 'id' => 'bail|min:1', + ], + 'custom' => 'exists,App\Models\EmployeeSocialItemsT,id' + ], + 'update' => [ + 'rules' => [ + 'id' => 'bail|min:1', + 'employee_id' => 'required', + 'social_type' => 'required', + 'base_price' => 'required', + 'personal_rate' => 'required', + 'unit_rate' => 'required', + ], + 'custom' => [ + 'exists,App\Models\EmployeeSocialItemsT,id', + ] + ], + 'destroy' => [ + 'rules' => [ + 'id' => 'bail|min:1', + ], + 'custom' => [ + 'exists,App\Models\EmployeeSocialItemsT,id', + ] + ] + ]; + + public function __construct(Request $request) + { + $this->model = new EmployeeSocialItemsT(); + parent::__construct($request); + } + + /** + * @title 社保列表 + * @description 社保列表 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function index() + { + $query = $this->model->query(); + + if(isset($this->params['name']) && $this->params['name'] != ''){ + $query->where('name', $this->params['name']); + } + + $data = $query->paginate(); + + return $this->success(new EmployeeSocialItemsCollection($data)); + } + + /** + * @title 社保保存 + * @description 社保保存 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function store() + { + $this->model->employee_id = $this->params['employee_id']; + $this->model->social_type = $this->params['social_type']; + $this->model->base_price = $this->params['base_price']; + $this->model->personal_rate = $this->params['personal_rate']; + $this->model->unit_rate = $this->params['unit_rate']; + $this->model->personal_price = $this->params['personal_price'] ?: route($this->params['base_price'] * $this->params['personal_rate'] / 100); + $this->model->unit_price = $this->params['unit_price'] ?: route($this->params['base_price'] * $this->params['unit_rate'] / 100); + if($this->model->save()){ + return $this->success(new EmployeeSocialItems($this->model)); + } else { + return $this->error(500, '社保信息保存失败'); + } + } + + /** + * @title 社保详情 + * @description 社保详情 + * @param $id + * @return mixed + * @author zcstatham + */ + public function show($id) + { + return $this->success(new EmployeeSocialItems($this->model->where('id', $id)->first())); + } + + /** + * @title 社保更新 + * @description 社保更新 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function update($id) + { + $this->model = $this->model->where('id', $id)->first(); + $this->model->employee_id = $this->params['employee_id']; + $this->model->social_type = $this->params['social_type']; + $this->model->base_price = $this->params['base_price']; + $this->model->personal_rate = $this->params['personal_rate']; + $this->model->unit_rate = $this->params['unit_rate']; + $this->model->personal_price = $this->params['personal_price'] ?: route($this->params['base_price'] * $this->params['personal_price'] / 100); + $this->model->unit_price = $this->params['unit_price'] ?: route($this->params['base_price'] * $this->params['unit_rate'] / 100); + if($this->model->save()){ + return $this->success(new EmployeeSocialItems($this->model)); + } else { + return $this->error(500, '社保信息保存失败'); + } + } + + /** + * @title 社保删除 + * @description 社保删除 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + */ + public function destroy($id) + { + if($this->model->destroy($id)){ + return $this->success(); + } else { + return $this->error(500, '社保信息保存失败'); + } + } +} diff --git a/app/Http/Controllers/Api/SystemSettingController.php b/app/Http/Controllers/Api/SystemSettingController.php new file mode 100644 index 0000000..d17b3f6 --- /dev/null +++ b/app/Http/Controllers/Api/SystemSettingController.php @@ -0,0 +1,194 @@ + [ + 'rules' => [ + 'title' => 'required|max:20', + 'name' => 'bail|required|unique:App\Models\SystemSettingT|max:20', + 'data_type' => 'required', + 'prop' => 'required', + 'content' => 'required', + 'sort' => 'integer', + 'status' => 'integer', + ], + 'messages' => [], + ], + 'show' => [ + 'rules' => [ + 'id' => 'bail|inter|min:1', + ], + 'messages' => [], + 'custom' => 'exists,App\Models\SystemSettingT,id' + ], + 'update' => [ + 'rules' => [ + 'id' => 'bail|inter|min:1', + 'title' => 'required|max:20', + 'name' => 'bail|required|max:20', + 'data_type' => 'required', + 'prop' => 'required', + 'content' => 'required', + 'sort' => 'integer', + 'status' => 'integer', + ], + 'messages' => [], + 'custom' => [ + 'exists,App\Models\SystemSettingT,id', + 'unique,App\Models\SystemSettingT,name,id' + ] + ], + 'destroy' => [ + 'rules' => [ + 'id' => 'bail|inter|min:1', + ], + 'messages' => [], + 'custom' => [ + 'exists,App\Models\SystemSettingT,id', + ] + ] + ]; + + public function __construct(Request $request) + { + $this->model = new SystemSettingT(); + parent::__construct($request); + } + + /** + * @title 配置列表 + * @description 配置列表 + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + * @time 2021/1/28 + */ + public function index() + { + $query = SystemSettingT::query(); + if(isset($this->params['prop']) && $this->params['prop'] != ''){ + $query->where('prop', $this->params['prop']); + } + if(isset($this->params['group']) && $this->params['group'] != ''){ + $query->where('group', $this->params['group']); + } + if(isset($this->params['name']) && $this->params['name'] != ''){ + $query->where('name', $this->params['name']); + } + if(isset($this->params['status']) && $this->params['status'] >= 0){ + $query->where('status', $this->params['status']); + } else { + $query->where('status', 1); + } + if(isset($this->params['title']) && $this->params['title'] != ''){ + $query->where('title', 'like', '%'. $this->params['title'] .'%'); + } + + $data = $query->paginate(); + + return $this->success(new SystemSettingCollection($data)); + } + + /** + * @title 配置新增 + * @description 配置新增 + * @param Request $request + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + * @time 2021/1/28 + */ + public function store(Request $request) + { + $setting = new SystemSettingT(); + $setting->name = $this->params['name']; + $setting->title = $this->params['title']; + $setting->data_type = $this->params['data_type']; + $setting->prop = $this->params['prop']; + $setting->group = $this->params['group'] ?? ''; + $setting->content = $this->params['content']; + $setting->remark = $this->params['remark'] ?? ''; + $setting->sort = $this->params['sort'] ?? 1; + $setting->status = $this->params['status'] ?? 1; + if($setting->save()){ + return $this->success($setting); + } else { + return $this->error(500, '配置信息保存失败'); + } + } + + /** + * @title 配置详情 + * @description 配置详情 + * @param $id + * @return mixed + * @author zcstatham + * @time 2021/1/28 + */ + public function show($id) + { + $setting = SystemSettingT::find($id); + return $this->success(new SystemSetting($setting)); + } + + /** + * @title 配置更新 + * @description 配置更新 + * @param Request $request + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + * @time 2021/1/28 + */ + public function update(Request $request, $id) + { + $setting = SystemSettingT::find($id); + $setting->name = $this->params['name']; + $setting->title = $this->params['title']; + $setting->data_type = $this->params['data_type']; + $setting->prop = $this->params['prop']; + $setting->group = $this->params['group'] ?? $setting->group; + $setting->content = $this->params['content']; + $setting->remark = $this->params['remark'] ?? $setting->remark; + $setting->sort = $this->params['sort'] ?? $setting->sort; + $setting->status = $this->params['status'] ?? $setting->status; + if($setting->save()){ + return $this->success(new SystemSetting($setting)); + } else { + return $this->error(500, '配置信息保存失败'); + } + } + + /** + * @title 配置删除 + * @description 软删除 + * @param $id + * @return \Illuminate\Http\JsonResponse + * @author zcstatham + * @time 2021/1/28 + */ + public function destroy($id) + { + $setting = SystemSettingT::find($id); + $setting->status = 0; + if($setting->save()){ + return $this->success(); + } else { + return $this->error(500, '配置信息保存失败'); + } + } +} diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php new file mode 100644 index 0000000..a0a2a8a --- /dev/null +++ b/app/Http/Controllers/Controller.php @@ -0,0 +1,13 @@ + [ + \App\Http\Middleware\EncryptCookies::class, + \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, + \Illuminate\Session\Middleware\StartSession::class, + // \Illuminate\Session\Middleware\AuthenticateSession::class, + \Illuminate\View\Middleware\ShareErrorsFromSession::class, + \App\Http\Middleware\VerifyCsrfToken::class, + \Illuminate\Routing\Middleware\SubstituteBindings::class, + ], + + 'api' => [ + 'throttle:api', + \Illuminate\Routing\Middleware\SubstituteBindings::class, + ], + ]; + + /** + * The application's route middleware. + * + * These middleware may be assigned to groups or used individually. + * + * @var array + */ + protected $routeMiddleware = [ + 'auth' => \App\Http\Middleware\Authenticate::class, + 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, + 'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class, + 'can' => \Illuminate\Auth\Middleware\Authorize::class, + 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, + 'password.confirm' => \Illuminate\Auth\Middleware\RequirePassword::class, + 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, + 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, + 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, + 'param_verify' => \App\Http\Middleware\ParamVerify::class, + ]; +} diff --git a/app/Http/Middleware/Authenticate.php b/app/Http/Middleware/Authenticate.php new file mode 100644 index 0000000..69cbf2c --- /dev/null +++ b/app/Http/Middleware/Authenticate.php @@ -0,0 +1,22 @@ +expectsJson()) { +// return route('login'); +// } + } +} diff --git a/app/Http/Middleware/EncryptCookies.php b/app/Http/Middleware/EncryptCookies.php new file mode 100644 index 0000000..033136a --- /dev/null +++ b/app/Http/Middleware/EncryptCookies.php @@ -0,0 +1,17 @@ +get('rules'); + $attributes = $request->get('attributes'); + array_walk($attributes, function(&$value){ + if(is_array($value)) $value = $value['title']; + }); + if(count($rules) > 0) { + $validator = Validator::make($request->input(), $rules['rules'], $rules['messages'] ?? [], $attributes); + if (isset($rules['custom']) && $rules['custom']) { + $param = $request->input(); + if($request->route('id')){ + $param['id'] = $request->route('id'); + } + $validator->after(function ($validator) use ($rules, &$param, &$attributes) { + $data = true; + if(is_array($rules['custom'])){ + foreach ($rules['custom'] as $callback){ + $data = $this->validate(explode(',', $callback), $param, $attributes); + if($data !== true){ + break; + } + } + } else { + $data = $this->validate(explode(',', $rules['custom']), $param, $attributes); + } + if (is_array($data)) { + $validator->errors()->add($data['field'], $data['message']); + } + }); + } + + if ($validator->fails()) { + return response()->json(['code' => 422, 'msg' => $validator->errors()->first(), 'data' => $validator->errors()->all()], 400); + } + } + return $next($request); + } + + private function validate($rule, $param, $attributes) + { + switch ($rule[0]) { + case 'exists': + $model = new $rule[1](); + if ($model->where($rule[2], $param[$rule[2]])->count() > 0) { + return true; + } else { + return ['field' => 'id', 'message' => '当前信息不存在']; + } + break; + case 'unique': + $model = new $rule[1](); + $msg = $attributes[$rule[2]]; + $model = $model->where($rule[2], $param[$rule[2]]); + if((count($rule)) >= 4){ + foreach ($rule as $key => $item){ + if($item == 'id'){ + $model = $model->where('id', '<>', $param['id']); + } else if($key > 2){ + $msg .= '--'. $attributes[$item]; + $model = $model->where($item, $param[$item]); + } + } + } + if ($model->count() > 0) { + return ['field' => 'id', 'message' => $msg .' 字段已存在']; + } else { + return true; + } + break; + case 'ip_check': + $model = new $rule[1](); + $ip_addrs = explode(',', $model->where('name', $rule[2])->value('content')); + if (in_array(MyLib::GetClientIP(), $ip_addrs)) { + return true; + } else { + return ['field' => 'ip', 'message' => '禁止外网访问']; + } + break; + } + } + + private function calc($operator, $value1, $value2) + { + switch ($operator){ + case 'eq': + return $value1 == $value2; + case 'neq': + return $value1 != $value2; + case 'gt': + return $value1 > $value2; + case 'egt': + return $value1 >= $value2; + case 'lt': + return $value1 < $value2; + case 'elt': + return $value1 <= $value2; + case 'heq': + return $value1 === $value2; + case 'nheq': + return $value1 !== $value2; + } + } +} diff --git a/app/Http/Middleware/PreventRequestsDuringMaintenance.php b/app/Http/Middleware/PreventRequestsDuringMaintenance.php new file mode 100644 index 0000000..e4956d0 --- /dev/null +++ b/app/Http/Middleware/PreventRequestsDuringMaintenance.php @@ -0,0 +1,17 @@ +check()) { + return redirect(RouteServiceProvider::HOME); + } + } + + return $next($request); + } +} diff --git a/app/Http/Middleware/TrimStrings.php b/app/Http/Middleware/TrimStrings.php new file mode 100644 index 0000000..5a50e7b --- /dev/null +++ b/app/Http/Middleware/TrimStrings.php @@ -0,0 +1,18 @@ +allSubdomainsOfApplicationUrl(), + ]; + } +} diff --git a/app/Http/Middleware/TrustProxies.php b/app/Http/Middleware/TrustProxies.php new file mode 100644 index 0000000..a3b6aef --- /dev/null +++ b/app/Http/Middleware/TrustProxies.php @@ -0,0 +1,23 @@ + '删除', 1 => '启用', 2 => '关闭']; + return [ + 'id' => $this->id, + 'name' => $this->name, + 'method' => $this->method, + 'title' => $this->title, + 'group' => $this->group, + 'module' => $this->module, + 'condition' => $this->condition, + 'status' => $this->status, + 'status_txt' => $status_txts[$this->status] + ]; + } +} diff --git a/app/Http/Resources/AuthRuleCollection.php b/app/Http/Resources/AuthRuleCollection.php new file mode 100644 index 0000000..2824b54 --- /dev/null +++ b/app/Http/Resources/AuthRuleCollection.php @@ -0,0 +1,19 @@ + $this->collection, + 'links' => [ + 'path' => $this->path(), + "first"=> $this->url(1), + "last"=> $this->url($this->lastPage()), + "prev"=> $this->previousPageUrl(), + "next"=> $this->nextPageUrl() + + ], + 'meta' => [ + "current_page"=> $this->currentPage(), + "last_page"=> $this->lastPage(), + 'per_page' => $this->perPage(), + "total"=> $this->total() + ], + ]; + } +} diff --git a/app/Http/Resources/CarBrand.php b/app/Http/Resources/CarBrand.php new file mode 100644 index 0000000..dd4a792 --- /dev/null +++ b/app/Http/Resources/CarBrand.php @@ -0,0 +1,24 @@ + $this->id, + 'name' => $this->name, + 'logo' => $this->logo, + 'letter' => $this->letter, + ]; + } +} diff --git a/app/Http/Resources/CarBrandCollection.php b/app/Http/Resources/CarBrandCollection.php new file mode 100644 index 0000000..02ad737 --- /dev/null +++ b/app/Http/Resources/CarBrandCollection.php @@ -0,0 +1,17 @@ + $this->id, + 'car_no' => $this->car_no, + 'frame_no' => $this->frame_no, + 'engine_no' => $this->engine_no, + 'factory_model' => $this->factory_model, + 'car_used_type' => $this->car_used_type, + 'car_man' => $this->car_man, + 'purchase_price' => $this->purchase_price, + 'register_date' => $this->register_date, + 'seat_count' => $this->seat_count, + 'insurance_times' => $this->insurance_times, + 'insurance_serial_times' => $this->insurance_serial_times, + 'repair_times' => $this->repair_times, + 'insurance_repair_times' => $this->insurance_repair_times, + 'last_insurance_company' => $this->last_insurance_company, + 'last_insurance_type' => $this->last_insurance_type, + 'last_insurance_rate' => $this->last_insurance_rate, + 'last_insurance_salesman' => $this->last_insurance_salesman, + 'last_insurance_date' => $this->last_insurance_date, + 'force_expire_date' => $this->force_expire_date, + 'business_expire_date' => $this->business_expire_date, + 'status' => $this->status, + 'created_at' => $this->created_at, + 'updated_at' => $this->updated_at, + ]; + } +} diff --git a/app/Http/Resources/CarInfoCollection.php b/app/Http/Resources/CarInfoCollection.php new file mode 100644 index 0000000..a465e3c --- /dev/null +++ b/app/Http/Resources/CarInfoCollection.php @@ -0,0 +1,17 @@ + $this->id, + 'car_series_id' => $this->car_series_id, + 'name' => $this->name, + 'year' => $this->year, + 'modelYears' => $this->modelYears, + 'vehicle_type' => $this->vehicle_type, + 'vehicle_size' => $this->vehicle_size, + 'engine_model' => $this->engine_model, + 'emission_standard' => $this->emission_standard, + 'displacement' => $this->displacement, + 'induction' => $this->induction, + 'fuel_type' => $this->fuel_type, + 'transmission_type' => $this->transmission_type, + 'transmission_description' => $this->transmission_description, + 'gear_number' => $this->gear_number, + 'front_tyre' => $this->front_tyre, + 'rear_tyre' => $this->rear_tyre, + 'doors' => $this->doors, + 'seats' => $this->seats, + 'tuhu_code' => $this->tuhu_code, + 'guidance_price' => $this->guidance_price, + 'created_at' => $this->created_at, + 'updated_at' => $this->updated_at, + ]; + } +} diff --git a/app/Http/Resources/CarModelCollection.php b/app/Http/Resources/CarModelCollection.php new file mode 100644 index 0000000..6e0167c --- /dev/null +++ b/app/Http/Resources/CarModelCollection.php @@ -0,0 +1,17 @@ + $this->id, + 'car_sub_brand_id' => $this->car_sub_brand_id, + 'name' => $this->name, + 'series' => $this->series, + 'level' => $this->level, + 'externalPanelPrice' => $this->externalPanelPrice, + 'internalPanelPrice' => $this->internalPanelPrice, + 'externalPaintPrice' => $this->externalPaintPrice, + 'internalPaintPrice' => $this->internalPaintPrice, + 'externalUnderPrice' => $this->externalUnderPrice, + 'internalUnderPrice' => $this->internalUnderPrice, + 'externalPolishPrice' => $this->externalPolishPrice, + 'internalPolishPrice' => $this->internalPolishPrice, + 'externalRepairPrice' => $this->externalRepairPrice, + 'internalRepairPrice' => $this->internalRepairPrice, + 'externalOutreachPrice' => $this->externalOutreachPrice, + ]; + } +} diff --git a/app/Http/Resources/CarSeriesCollection.php b/app/Http/Resources/CarSeriesCollection.php new file mode 100644 index 0000000..08acc0c --- /dev/null +++ b/app/Http/Resources/CarSeriesCollection.php @@ -0,0 +1,17 @@ + $this->id, + 'car_brand_id' => $this->car_brand_id, + 'name' => $this->name, + ]; + } +} diff --git a/app/Http/Resources/CarSubBrandCollection.php b/app/Http/Resources/CarSubBrandCollection.php new file mode 100644 index 0000000..34e6518 --- /dev/null +++ b/app/Http/Resources/CarSubBrandCollection.php @@ -0,0 +1,17 @@ + $this->id, + 'name' => $this->name, + 'title' => $this->title, + 'pid' => $this->pid, + ]; + } +} diff --git a/app/Http/Resources/CompanyCollection.php b/app/Http/Resources/CompanyCollection.php new file mode 100644 index 0000000..b10f3be --- /dev/null +++ b/app/Http/Resources/CompanyCollection.php @@ -0,0 +1,18 @@ + $this->id, + 'pid' => $this->pid, + 'name' => $this->name, + 'title' => $this->title, + 'status' => $this->status, + ]; + } +} diff --git a/app/Http/Resources/DictionaryCollection.php b/app/Http/Resources/DictionaryCollection.php new file mode 100644 index 0000000..a77d6f1 --- /dev/null +++ b/app/Http/Resources/DictionaryCollection.php @@ -0,0 +1,18 @@ + $this->id, + 'username' => $this->username, + 'nickname' => $this->nickname, + 'company_id' => $this->company_id, + 'group_id' => $this->group_id, + 'phone' => $this->phone, + 'monthly_working_days' => $this->monthly_working_days, + 'entry_date' => $this->entry_date, + 'official_date' => $this->official_date, + 'resign_date' => $this->resign_date, + 'probation_salary' => $this->probation_salary, + 'official_salary' => $this->official_salary, + 'is_outer' => $this->is_outer, + 'status' => $this->status, + ]; + } +} diff --git a/app/Http/Resources/EmployeeBank.php b/app/Http/Resources/EmployeeBank.php new file mode 100644 index 0000000..350b867 --- /dev/null +++ b/app/Http/Resources/EmployeeBank.php @@ -0,0 +1,29 @@ + $this->id, + 'employee_id' => $this->employee_id, + 'super_bank_name' => $this->super_bank_name, + 'bank_name' => $this->bank_name, + 'bank_code' => $this->bank_code, + 'bank_num' => $this->bank_num, + 'bank_man' => $this->bank_man, + 'maximum' => $this->maximum, + 'priority' => $this->priority, + ]; + } +} diff --git a/app/Http/Resources/EmployeeBankCollection.php b/app/Http/Resources/EmployeeBankCollection.php new file mode 100644 index 0000000..2bb8db7 --- /dev/null +++ b/app/Http/Resources/EmployeeBankCollection.php @@ -0,0 +1,17 @@ + $this->id, + 'pid' => $this->pid, + 'title' => $this->title, + 'level' => $this->level, + 'description' => $this->description, + 'base_salary' => $this->base_salary, + 'status' => $this->status, + 'rules' => $this->rules, + ]; + } +} diff --git a/app/Http/Resources/EmployeeGroupCollection.php b/app/Http/Resources/EmployeeGroupCollection.php new file mode 100644 index 0000000..5acb561 --- /dev/null +++ b/app/Http/Resources/EmployeeGroupCollection.php @@ -0,0 +1,17 @@ + $this->id, + 'employee_id' => $this->employee_id, + 'type' => $this->type, + 'date' => $this->date, + 'type_txt' => DictionaryT::getDictValue('REWARD_TYPE', $this->type), + 'price' => $this->price, + 'remark' => $this->remark, + 'status' => $this->status, + 'status_txt' => DictionaryT::getDictValue('REWARD_STATUS', $this->status), + 'created_at' => $this->created_at->toDateTimeString(), + 'updated_at' => $this->updated_at->toDateTimeString(), + ]; + } +} diff --git a/app/Http/Resources/EmployeeRewardPunishmentCollection.php b/app/Http/Resources/EmployeeRewardPunishmentCollection.php new file mode 100644 index 0000000..c2fafb8 --- /dev/null +++ b/app/Http/Resources/EmployeeRewardPunishmentCollection.php @@ -0,0 +1,17 @@ + $this->id, + 'employee_id' => $this->employee_id, + 'social_type' => $this->social_type, + 'base_price' => $this->base_price, + 'personal_rate' => $this->personal_rate, + 'unit_rate' => $this->unit_rate, + 'personal_price' => $this->personal_price, + 'unit_price' => $this->unit_price, + 'created_at' => $this->created_at, + 'updated_at' => $this->updated_at, + ]; + } +} diff --git a/app/Http/Resources/EmployeeSocialItemsCollection.php b/app/Http/Resources/EmployeeSocialItemsCollection.php new file mode 100644 index 0000000..4e5e91c --- /dev/null +++ b/app/Http/Resources/EmployeeSocialItemsCollection.php @@ -0,0 +1,17 @@ + '删除', 1 => '启用', 2 => '关闭']; + return [ + 'id' => $this->id, + 'name' => $this->name, + 'data_type' => $this->data_type, + 'title' => $this->title, + 'group' => $this->group, + 'prop' => $this->prop, + 'content' => $this->content, + 'remark' => $this->remark, + 'sort' => $this->sort, + 'status' => $this->status, + 'status_txt' => $status_txts[$this->status], + 'created_at' => $this->created_at->toDateTimeString(), + 'updated_at' => $this->updated_at->toDateTimeString() + ]; + } +} diff --git a/app/Http/Resources/SystemSettingCollection.php b/app/Http/Resources/SystemSettingCollection.php new file mode 100644 index 0000000..3ff7636 --- /dev/null +++ b/app/Http/Resources/SystemSettingCollection.php @@ -0,0 +1,18 @@ +params; + } + // Get the comment + if (preg_match('#^/\*\*(.*)\*/#s', $doc, $comment) === false) + return $this->params; + $comment = trim($comment[1]); + // Get all the lines and strip the * from the first character + if (preg_match_all('#^\s*\*(.*)#m', $comment, $lines) === false) + return $this->params; + $this->parseLines($lines[1]); + return $this->params; + } + + private function parseLines($lines) { + $desc = []; + foreach ($lines as $line) { + $parsedLine = $this->parseLine($line); // Parse the line + if ($parsedLine === false && !isset ($this->params['description'])) { + if (isset ($desc)) { + // Store the first line in the short description + $this->params['description'] = implode(PHP_EOL, $desc); + } + $desc = array(); + } elseif ($parsedLine !== false) { + $desc[] = $parsedLine; // Store the line in the long description + } + } + $desc = implode(' ', $desc); + if (!empty ($desc)) + $this->params['long_description'] = $desc; + } + + private function parseLine($line) { + // trim the whitespace from the line + $line = trim($line); + if (empty ($line)) + return false; // Empty line + if (strpos($line, '@') === 0) { + if (strpos($line, ' ') > 0) { + // Get the parameter name + $param = substr($line, 1, strpos($line, ' ') - 1); + $value = substr($line, strlen($param) + 2); // Get the value + } else { + $param = substr($line, 1); + $value = ''; + } + if($value == 'Request $request') + return false; + // Parse the line and return false if the parameter is valid + if ($this->setParam($param, $value)) + return false; + } + return $line; + } + + private function setParam($param, $value) { + if ($param == 'param' || $param == 'header') + $value = $this->formatParam($value); + if ($param == 'class') + list ($param, $value) = $this->formatClass($value); + if ($param == 'return' || $param == 'param' || $param == 'header') { + $this->params[$param][] = $value; + } else if (empty ($this->params[$param])) { + $this->params[$param] = $value; + } else { + $this->params[$param] = $this->params[$param] . $value; + } + return true; + } + + private function formatClass($value) { + $r = preg_split("[\(|\)]", $value); + if (is_array($r)) { + $param = $r[0]; + parse_str($r[1], $value); + foreach ($value as $key => $val) { + $val = explode(',', $val); + if (count($val) > 1) + $value[$key] = $val; + } + } else { + $param = 'Unknown'; + } + return array($param, $value); + } + + private function formatParam($string) { + $string = $string . " "; + if (preg_match_all('/(\w+):(.*?)[\s\n]/s', $string, $match)) { + $param = []; + foreach ($match[1] as $key => $value) { + $param[$match[1][$key]] = $this->getParamType($match[2][$key]); + } + return $param; + } else if (preg_match('/(\w+) (\$.*?)[\s\n]/s', $string, $match)) { + return $match[2]; + } else { + return trim($string); + } + } + + private function getParamType($type) + { + $typeMaps = [ + 'string' => '字符串', + 'int' => '整型', + 'float' => '浮点型', + 'boolean' => '布尔型', + 'date' => '日期', + 'array' => '数组', + 'fixed' => '固定值', + 'enum' => '枚举类型', + 'object' => '对象', + ]; + return array_key_exists($type, $typeMaps) ? $typeMaps[$type] : $type; + } +} diff --git a/app/Libs/MyLib.php b/app/Libs/MyLib.php new file mode 100644 index 0000000..a1d2f98 --- /dev/null +++ b/app/Libs/MyLib.php @@ -0,0 +1,73 @@ +parse($text); + } + + public static function GetClientIP() + { + global $HTTP_SERVER_VARS; + if (isset($HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"])) { + $ip = $HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"]; + } elseif ($HTTP_SERVER_VARS["HTTP_CLIENT_IP"]) { + $ip = $HTTP_SERVER_VARS["HTTP_CLIENT_IP"]; + } elseif ($HTTP_SERVER_VARS["REMOTE_ADDR"]) { + $ip = $HTTP_SERVER_VARS["REMOTE_ADDR"]; + } elseif (getenv("HTTP_X_FORWARDED_FOR")) { + $ip = getenv("HTTP_X_FORWARDED_FOR"); + } elseif (getenv("HTTP_CLIENT_IP")) { + $ip = getenv("HTTP_CLIENT_IP"); + } elseif (getenv("REMOTE_ADDR")) { + $ip = getenv("REMOTE_ADDR"); + } else { + $ip = "0.0.0.0"; + } + return $ip ; + } + + public static function GetServerIP() + { + $ip = '0.0.0.0'; + if (isset($_SERVER)) { + if (isset($_SERVER['SERVER_ADDR'])) { + $ip = $_SERVER['SERVER_ADDR']; + } elseif (isset($_SERVER['LOCAL_ADDR'])) { + $ip = $_SERVER['LOCAL_ADDR']; + } elseif (isset($_SERVER['SERVER_NAME'])) { + return gethostbyname($_SERVER['SERVER_NAME']); + } + } else { + $ip = getenv('SERVER_ADDR'); + } + return $ip; + } +} diff --git a/app/Libs/simple_html_dom.php b/app/Libs/simple_html_dom.php new file mode 100644 index 0000000..caa5fb4 --- /dev/null +++ b/app/Libs/simple_html_dom.php @@ -0,0 +1,2353 @@ + $maxLen) { + $dom->clear(); + return false; + } + + return $dom->load($contents, $lowercase, $stripRN); +} + +function str_get_html( + $str, + $lowercase = true, + $forceTagsClosed = true, + $target_charset = DEFAULT_TARGET_CHARSET, + $stripRN = true, + $defaultBRText = DEFAULT_BR_TEXT, + $defaultSpanText = DEFAULT_SPAN_TEXT) +{ + $dom = new simple_html_dom( + null, + $lowercase, + $forceTagsClosed, + $target_charset, + $stripRN, + $defaultBRText, + $defaultSpanText + ); + + if (empty($str) || strlen($str) > MAX_FILE_SIZE) { + $dom->clear(); + return false; + } + + return $dom->load($str, $lowercase, $stripRN); +} + +function dump_html_tree($node, $show_attr = true, $deep = 0) +{ + $node->dump($node); +} + +class simple_html_dom_node +{ + public $nodetype = HDOM_TYPE_TEXT; + public $tag = 'text'; + public $attr = array(); + public $children = array(); + public $nodes = array(); + public $parent = null; + public $_ = array(); + public $tag_start = 0; + private $dom = null; + + function __construct($dom) + { + $this->dom = $dom; + $dom->nodes[] = $this; + } + + function __destruct() + { + $this->clear(); + } + + function __toString() + { + return $this->outertext(); + } + + function clear() + { + $this->dom = null; + $this->nodes = null; + $this->parent = null; + $this->children = null; + } + + function dump($show_attr = true, $depth = 0) + { + echo str_repeat("\t", $depth) . $this->tag; + + if ($show_attr && count($this->attr) > 0) { + echo '('; + foreach ($this->attr as $k => $v) { + echo "[$k]=>\"$v\", "; + } + echo ')'; + } + + echo "\n"; + + if ($this->nodes) { + foreach ($this->nodes as $node) { + $node->dump($show_attr, $depth + 1); + } + } + } + + function dump_node($echo = true) + { + $string = $this->tag; + + if (count($this->attr) > 0) { + $string .= '('; + foreach ($this->attr as $k => $v) { + $string .= "[$k]=>\"$v\", "; + } + $string .= ')'; + } + + if (count($this->_) > 0) { + $string .= ' $_ ('; + foreach ($this->_ as $k => $v) { + if (is_array($v)) { + $string .= "[$k]=>("; + foreach ($v as $k2 => $v2) { + $string .= "[$k2]=>\"$v2\", "; + } + $string .= ')'; + } else { + $string .= "[$k]=>\"$v\", "; + } + } + $string .= ')'; + } + + if (isset($this->text)) { + $string .= " text: ({$this->text})"; + } + + $string .= ' HDOM_INNER_INFO: '; + + if (isset($node->_[HDOM_INFO_INNER])) { + $string .= "'" . $node->_[HDOM_INFO_INNER] . "'"; + } else { + $string .= ' NULL '; + } + + $string .= ' children: ' . count($this->children); + $string .= ' nodes: ' . count($this->nodes); + $string .= ' tag_start: ' . $this->tag_start; + $string .= "\n"; + + if ($echo) { + echo $string; + return; + } else { + return $string; + } + } + + function parent($parent = null) + { + // I am SURE that this doesn't work properly. + // It fails to unset the current node from it's current parents nodes or + // children list first. + if ($parent !== null) { + $this->parent = $parent; + $this->parent->nodes[] = $this; + $this->parent->children[] = $this; + } + + return $this->parent; + } + + function has_child() + { + return !empty($this->children); + } + + function children($idx = -1) + { + if ($idx === -1) { + return $this->children; + } + + if (isset($this->children[$idx])) { + return $this->children[$idx]; + } + + return null; + } + + function first_child() + { + if (count($this->children) > 0) { + return $this->children[0]; + } + return null; + } + + function last_child() + { + if (count($this->children) > 0) { + return end($this->children); + } + return null; + } + + function next_sibling() + { + if ($this->parent === null) { + return null; + } + + $idx = array_search($this, $this->parent->children, true); + + if ($idx !== false && isset($this->parent->children[$idx + 1])) { + return $this->parent->children[$idx + 1]; + } + + return null; + } + + function prev_sibling() + { + if ($this->parent === null) { + return null; + } + + $idx = array_search($this, $this->parent->children, true); + + if ($idx !== false && $idx > 0) { + return $this->parent->children[$idx - 1]; + } + + return null; + } + + function find_ancestor_tag($tag) + { + global $debug_object; + if (is_object($debug_object)) { $debug_object->debug_log_entry(1); } + + if ($this->parent === null) { + return null; + } + + $ancestor = $this->parent; + + while (!is_null($ancestor)) { + if (is_object($debug_object)) { + $debug_object->debug_log(2, 'Current tag is: ' . $ancestor->tag); + } + + if ($ancestor->tag === $tag) { + break; + } + + $ancestor = $ancestor->parent; + } + + return $ancestor; + } + + function innertext() + { + if (isset($this->_[HDOM_INFO_INNER])) { + return $this->_[HDOM_INFO_INNER]; + } + + if (isset($this->_[HDOM_INFO_TEXT])) { + return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); + } + + $ret = ''; + + foreach ($this->nodes as $n) { + $ret .= $n->outertext(); + } + + return $ret; + } + + function outertext() + { + global $debug_object; + + if (is_object($debug_object)) { + $text = ''; + + if ($this->tag === 'text') { + if (!empty($this->text)) { + $text = ' with text: ' . $this->text; + } + } + + $debug_object->debug_log(1, 'Innertext of tag: ' . $this->tag . $text); + } + + if ($this->tag === 'root') { + return $this->innertext(); + } + + // todo: What is the use of this callback? Remove? + if ($this->dom && $this->dom->callback !== null) { + call_user_func_array($this->dom->callback, array($this)); + } + + if (isset($this->_[HDOM_INFO_OUTER])) { + return $this->_[HDOM_INFO_OUTER]; + } + + if (isset($this->_[HDOM_INFO_TEXT])) { + return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); + } + + $ret = ''; + + if ($this->dom && $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]) { + $ret = $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]->makeup(); + } + + if (isset($this->_[HDOM_INFO_INNER])) { + // todo:
should either never have HDOM_INFO_INNER or always + if ($this->tag !== 'br') { + $ret .= $this->_[HDOM_INFO_INNER]; + } + } elseif ($this->nodes) { + foreach ($this->nodes as $n) { + $ret .= $this->convert_text($n->outertext()); + } + } + + if (isset($this->_[HDOM_INFO_END]) && $this->_[HDOM_INFO_END] != 0) { + $ret .= 'tag . '>'; + } + + return $ret; + } + + function text() + { + if (isset($this->_[HDOM_INFO_INNER])) { + return $this->_[HDOM_INFO_INNER]; + } + + switch ($this->nodetype) { + case HDOM_TYPE_TEXT: return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); + case HDOM_TYPE_COMMENT: return ''; + case HDOM_TYPE_UNKNOWN: return ''; + } + + if (strcasecmp($this->tag, 'script') === 0) { return ''; } + if (strcasecmp($this->tag, 'style') === 0) { return ''; } + + $ret = ''; + + // In rare cases, (always node type 1 or HDOM_TYPE_ELEMENT - observed + // for some span tags, and some p tags) $this->nodes is set to NULL. + // NOTE: This indicates that there is a problem where it's set to NULL + // without a clear happening. + // WHY is this happening? + if (!is_null($this->nodes)) { + foreach ($this->nodes as $n) { + // Start paragraph after a blank line + if ($n->tag === 'p') { + $ret = trim($ret) . "\n\n"; + } + + $ret .= $this->convert_text($n->text()); + + // If this node is a span... add a space at the end of it so + // multiple spans don't run into each other. This is plaintext + // after all. + if ($n->tag === 'span') { + $ret .= $this->dom->default_span_text; + } + } + } + return $ret; + } + + function xmltext() + { + $ret = $this->innertext(); + $ret = str_ireplace('', '', $ret); + return $ret; + } + + function makeup() + { + // text, comment, unknown + if (isset($this->_[HDOM_INFO_TEXT])) { + return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); + } + + $ret = '<' . $this->tag; + $i = -1; + + foreach ($this->attr as $key => $val) { + ++$i; + + // skip removed attribute + if ($val === null || $val === false) { continue; } + + $ret .= $this->_[HDOM_INFO_SPACE][$i][0]; + + //no value attr: nowrap, checked selected... + if ($val === true) { + $ret .= $key; + } else { + switch ($this->_[HDOM_INFO_QUOTE][$i]) + { + case HDOM_QUOTE_DOUBLE: $quote = '"'; break; + case HDOM_QUOTE_SINGLE: $quote = '\''; break; + default: $quote = ''; + } + + $ret .= $key + . $this->_[HDOM_INFO_SPACE][$i][1] + . '=' + . $this->_[HDOM_INFO_SPACE][$i][2] + . $quote + . $val + . $quote; + } + } + + $ret = $this->dom->restore_noise($ret); + return $ret . $this->_[HDOM_INFO_ENDSPACE] . '>'; + } + + function find($selector, $idx = null, $lowercase = false) + { + $selectors = $this->parse_selector($selector); + if (($count = count($selectors)) === 0) { return array(); } + $found_keys = array(); + + // find each selector + for ($c = 0; $c < $count; ++$c) { + // The change on the below line was documented on the sourceforge + // code tracker id 2788009 + // used to be: if (($levle=count($selectors[0]))===0) return array(); + if (($levle = count($selectors[$c])) === 0) { return array(); } + if (!isset($this->_[HDOM_INFO_BEGIN])) { return array(); } + + $head = array($this->_[HDOM_INFO_BEGIN] => 1); + $cmd = ' '; // Combinator + + // handle descendant selectors, no recursive! + for ($l = 0; $l < $levle; ++$l) { + $ret = array(); + + foreach ($head as $k => $v) { + $n = ($k === -1) ? $this->dom->root : $this->dom->nodes[$k]; + //PaperG - Pass this optional parameter on to the seek function. + $n->seek($selectors[$c][$l], $ret, $cmd, $lowercase); + } + + $head = $ret; + $cmd = $selectors[$c][$l][4]; // Next Combinator + } + + foreach ($head as $k => $v) { + if (!isset($found_keys[$k])) { + $found_keys[$k] = 1; + } + } + } + + // sort keys + ksort($found_keys); + + $found = array(); + foreach ($found_keys as $k => $v) { + $found[] = $this->dom->nodes[$k]; + } + + // return nth-element or array + if (is_null($idx)) { return $found; } + elseif ($idx < 0) { $idx = count($found) + $idx; } + return (isset($found[$idx])) ? $found[$idx] : null; + } + + protected function seek($selector, &$ret, $parent_cmd, $lowercase = false) + { + global $debug_object; + if (is_object($debug_object)) { $debug_object->debug_log_entry(1); } + + list($tag, $id, $class, $attributes, $cmb) = $selector; + $nodes = array(); + + if ($parent_cmd === ' ') { // Descendant Combinator + // Find parent closing tag if the current element doesn't have a closing + // tag (i.e. void element) + $end = (!empty($this->_[HDOM_INFO_END])) ? $this->_[HDOM_INFO_END] : 0; + if ($end == 0) { + $parent = $this->parent; + while (!isset($parent->_[HDOM_INFO_END]) && $parent !== null) { + $end -= 1; + $parent = $parent->parent; + } + $end += $parent->_[HDOM_INFO_END]; + } + + // Get list of target nodes + $nodes_start = $this->_[HDOM_INFO_BEGIN] + 1; + $nodes_count = $end - $nodes_start; + $nodes = array_slice($this->dom->nodes, $nodes_start, $nodes_count, true); + } elseif ($parent_cmd === '>') { // Child Combinator + $nodes = $this->children; + } elseif ($parent_cmd === '+' + && $this->parent + && in_array($this, $this->parent->children)) { // Next-Sibling Combinator + $index = array_search($this, $this->parent->children, true) + 1; + if ($index < count($this->parent->children)) + $nodes[] = $this->parent->children[$index]; + } elseif ($parent_cmd === '~' + && $this->parent + && in_array($this, $this->parent->children)) { // Subsequent Sibling Combinator + $index = array_search($this, $this->parent->children, true); + $nodes = array_slice($this->parent->children, $index); + } + + // Go throgh each element starting at this element until the end tag + // Note: If this element is a void tag, any previous void element is + // skipped. + foreach($nodes as $node) { + $pass = true; + + // Skip root nodes + if(!$node->parent) { + $pass = false; + } + + // Handle 'text' selector + if($pass && $tag === 'text' && $node->tag === 'text') { + $ret[array_search($node, $this->dom->nodes, true)] = 1; + unset($node); + continue; + } + + // Skip if node isn't a child node (i.e. text nodes) + if($pass && !in_array($node, $node->parent->children, true)) { + $pass = false; + } + + // Skip if tag doesn't match + if ($pass && $tag !== '' && $tag !== $node->tag && $tag !== '*') { + $pass = false; + } + + // Skip if ID doesn't exist + if ($pass && $id !== '' && !isset($node->attr['id'])) { + $pass = false; + } + + // Check if ID matches + if ($pass && $id !== '' && isset($node->attr['id'])) { + // Note: Only consider the first ID (as browsers do) + $node_id = explode(' ', trim($node->attr['id']))[0]; + + if($id !== $node_id) { $pass = false; } + } + + // Check if all class(es) exist + if ($pass && $class !== '' && is_array($class) && !empty($class)) { + if (isset($node->attr['class'])) { + $node_classes = explode(' ', $node->attr['class']); + + if ($lowercase) { + $node_classes = array_map('strtolower', $node_classes); + } + + foreach($class as $c) { + if(!in_array($c, $node_classes)) { + $pass = false; + break; + } + } + } else { + $pass = false; + } + } + + // Check attributes + if ($pass + && $attributes !== '' + && is_array($attributes) + && !empty($attributes)) { + foreach($attributes as $a) { + list ( + $att_name, + $att_expr, + $att_val, + $att_inv, + $att_case_sensitivity + ) = $a; + + // Handle indexing attributes (i.e. "[2]") + /** + * Note: This is not supported by the CSS Standard but adds + * the ability to select items compatible to XPath (i.e. + * the 3rd element within it's parent). + * + * Note: This doesn't conflict with the CSS Standard which + * doesn't work on numeric attributes anyway. + */ + if (is_numeric($att_name) + && $att_expr === '' + && $att_val === '') { + $count = 0; + + // Find index of current element in parent + foreach ($node->parent->children as $c) { + if ($c->tag === $node->tag) ++$count; + if ($c === $node) break; + } + + // If this is the correct node, continue with next + // attribute + if ($count === (int)$att_name) continue; + } + + // Check attribute availability + if ($att_inv) { // Attribute should NOT be set + if (isset($node->attr[$att_name])) { + $pass = false; + break; + } + } else { // Attribute should be set + // todo: "plaintext" is not a valid CSS selector! + if ($att_name !== 'plaintext' + && !isset($node->attr[$att_name])) { + $pass = false; + break; + } + } + + // Continue with next attribute if expression isn't defined + if ($att_expr === '') continue; + + // If they have told us that this is a "plaintext" + // search then we want the plaintext of the node - right? + // todo "plaintext" is not a valid CSS selector! + if ($att_name === 'plaintext') { + $nodeKeyValue = $node->text(); + } else { + $nodeKeyValue = $node->attr[$att_name]; + } + + if (is_object($debug_object)) { + $debug_object->debug_log(2, + 'testing node: ' + . $node->tag + . ' for attribute: ' + . $att_name + . $att_expr + . $att_val + . ' where nodes value is: ' + . $nodeKeyValue + ); + } + + // If lowercase is set, do a case insensitive test of + // the value of the selector. + if ($lowercase) { + $check = $this->match( + $att_expr, + strtolower($att_val), + strtolower($nodeKeyValue), + $att_case_sensitivity + ); + } else { + $check = $this->match( + $att_expr, + $att_val, + $nodeKeyValue, + $att_case_sensitivity + ); + } + + if (is_object($debug_object)) { + $debug_object->debug_log(2, + 'after match: ' + . ($check ? 'true' : 'false') + ); + } + + if (!$check) { + $pass = false; + break; + } + } + } + + // Found a match. Add to list and clear node + if ($pass) $ret[$node->_[HDOM_INFO_BEGIN]] = 1; + unset($node); + } + // It's passed by reference so this is actually what this function returns. + if (is_object($debug_object)) { + $debug_object->debug_log(1, 'EXIT - ret: ', $ret); + } + } + + protected function match($exp, $pattern, $value, $case_sensitivity) + { + global $debug_object; + if (is_object($debug_object)) {$debug_object->debug_log_entry(1);} + + if ($case_sensitivity === 'i') { + $pattern = strtolower($pattern); + $value = strtolower($value); + } + + switch ($exp) { + case '=': + return ($value === $pattern); + case '!=': + return ($value !== $pattern); + case '^=': + return preg_match('/^' . preg_quote($pattern, '/') . '/', $value); + case '$=': + return preg_match('/' . preg_quote($pattern, '/') . '$/', $value); + case '*=': + return preg_match('/' . preg_quote($pattern, '/') . '/', $value); + case '|=': + /** + * [att|=val] + * + * Represents an element with the att attribute, its value + * either being exactly "val" or beginning with "val" + * immediately followed by "-" (U+002D). + */ + return strpos($value, $pattern) === 0; + case '~=': + /** + * [att~=val] + * + * Represents an element with the att attribute whose value is a + * whitespace-separated list of words, one of which is exactly + * "val". If "val" contains whitespace, it will never represent + * anything (since the words are separated by spaces). Also if + * "val" is the empty string, it will never represent anything. + */ + return in_array($pattern, explode(' ', trim($value)), true); + } + return false; + } + + protected function parse_selector($selector_string) + { + global $debug_object; + if (is_object($debug_object)) { $debug_object->debug_log_entry(1); } + + /** + * Pattern of CSS selectors, modified from mootools (https://mootools.net/) + * + * Paperg: Add the colon to the attribute, so that it properly finds + * like google does. + * + * Note: if you try to look at this attribute, you MUST use getAttribute + * since $dom->x:y will fail the php syntax check. + * + * Notice the \[ starting the attribute? and the @? following? This + * implies that an attribute can begin with an @ sign that is not + * captured. This implies that an html attribute specifier may start + * with an @ sign that is NOT captured by the expression. Farther study + * is required to determine of this should be documented or removed. + * + * Matches selectors in this order: + * + * [0] - full match + * + * [1] - tag name + * ([\w:\*-]*) + * Matches the tag name consisting of zero or more words, colons, + * asterisks and hyphens. + * + * [2] - id name + * (?:\#([\w-]+)) + * Optionally matches a id name, consisting of an "#" followed by + * the id name (one or more words and hyphens). + * + * [3] - class names (including dots) + * (?:\.([\w\.-]+))? + * Optionally matches a list of classs, consisting of an "." + * followed by the class name (one or more words and hyphens) + * where multiple classes can be chained (i.e. ".foo.bar.baz") + * + * [4] - attributes + * ((?:\[@?(?:!?[\w:-]+)(?:(?:[!*^$|~]?=)[\"']?(?:.*?)[\"']?)?(?:\s*?(?:[iIsS])?)?\])+)? + * Optionally matches the attributes list + * + * [5] - separator + * ([\/, >+~]+) + * Matches the selector list separator + */ + // phpcs:ignore Generic.Files.LineLength + $pattern = "/([\w:\*-]*)(?:\#([\w-]+))?(?:|\.([\w\.-]+))?((?:\[@?(?:!?[\w:-]+)(?:(?:[!*^$|~]?=)[\"']?(?:.*?)[\"']?)?(?:\s*?(?:[iIsS])?)?\])+)?([\/, >+~]+)/is"; + + preg_match_all( + $pattern, + trim($selector_string) . ' ', // Add final ' ' as pseudo separator + $matches, + PREG_SET_ORDER + ); + + if (is_object($debug_object)) { + $debug_object->debug_log(2, 'Matches Array: ', $matches); + } + + $selectors = array(); + $result = array(); + + foreach ($matches as $m) { + $m[0] = trim($m[0]); + + // Skip NoOps + if ($m[0] === '' || $m[0] === '/' || $m[0] === '//') { continue; } + + // Convert to lowercase + if ($this->dom->lowercase) { + $m[1] = strtolower($m[1]); + } + + // Extract classes + if ($m[3] !== '') { $m[3] = explode('.', $m[3]); } + + /* Extract attributes (pattern based on the pattern above!) + + * [0] - full match + * [1] - attribute name + * [2] - attribute expression + * [3] - attribute value + * [4] - case sensitivity + * + * Note: Attributes can be negated with a "!" prefix to their name + */ + if($m[4] !== '') { + preg_match_all( + "/\[@?(!?[\w:-]+)(?:([!*^$|~]?=)[\"']?(.*?)[\"']?)?(?:\s+?([iIsS])?)?\]/is", + trim($m[4]), + $attributes, + PREG_SET_ORDER + ); + + // Replace element by array + $m[4] = array(); + + foreach($attributes as $att) { + // Skip empty matches + if(trim($att[0]) === '') { continue; } + + $inverted = (isset($att[1][0]) && $att[1][0] === '!'); + $m[4][] = array( + $inverted ? substr($att[1], 1) : $att[1], // Name + (isset($att[2])) ? $att[2] : '', // Expression + (isset($att[3])) ? $att[3] : '', // Value + $inverted, // Inverted Flag + (isset($att[4])) ? strtolower($att[4]) : '', // Case-Sensitivity + ); + } + } + + // Sanitize Separator + if ($m[5] !== '' && trim($m[5]) === '') { // Descendant Separator + $m[5] = ' '; + } else { // Other Separator + $m[5] = trim($m[5]); + } + + // Clear Separator if it's a Selector List + if ($is_list = ($m[5] === ',')) { $m[5] = ''; } + + // Remove full match before adding to results + array_shift($m); + $result[] = $m; + + if ($is_list) { // Selector List + $selectors[] = $result; + $result = array(); + } + } + + if (count($result) > 0) { $selectors[] = $result; } + return $selectors; + } + + function __get($name) + { + if (isset($this->attr[$name])) { + return $this->convert_text($this->attr[$name]); + } + switch ($name) { + case 'outertext': return $this->outertext(); + case 'innertext': return $this->innertext(); + case 'plaintext': return $this->text(); + case 'xmltext': return $this->xmltext(); + default: return array_key_exists($name, $this->attr); + } + } + + function __set($name, $value) + { + global $debug_object; + if (is_object($debug_object)) { $debug_object->debug_log_entry(1); } + + switch ($name) { + case 'outertext': return $this->_[HDOM_INFO_OUTER] = $value; + case 'innertext': + if (isset($this->_[HDOM_INFO_TEXT])) { + return $this->_[HDOM_INFO_TEXT] = $value; + } + return $this->_[HDOM_INFO_INNER] = $value; + } + + if (!isset($this->attr[$name])) { + $this->_[HDOM_INFO_SPACE][] = array(' ', '', ''); + $this->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE; + } + + $this->attr[$name] = $value; + } + + function __isset($name) + { + switch ($name) { + case 'outertext': return true; + case 'innertext': return true; + case 'plaintext': return true; + } + //no value attr: nowrap, checked selected... + return (array_key_exists($name, $this->attr)) ? true : isset($this->attr[$name]); + } + + function __unset($name) + { + if (isset($this->attr[$name])) { unset($this->attr[$name]); } + } + + function convert_text($text) + { + global $debug_object; + if (is_object($debug_object)) { $debug_object->debug_log_entry(1); } + + $converted_text = $text; + + $sourceCharset = ''; + $targetCharset = ''; + + if ($this->dom) { + $sourceCharset = strtoupper($this->dom->_charset); + $targetCharset = strtoupper($this->dom->_target_charset); + } + + if (is_object($debug_object)) { + $debug_object->debug_log(3, + 'source charset: ' + . $sourceCharset + . ' target charaset: ' + . $targetCharset + ); + } + + if (!empty($sourceCharset) + && !empty($targetCharset) + && (strcasecmp($sourceCharset, $targetCharset) != 0)) { + // Check if the reported encoding could have been incorrect and the text is actually already UTF-8 + if ((strcasecmp($targetCharset, 'UTF-8') == 0) + && ($this->is_utf8($text))) { + $converted_text = $text; + } else { + $converted_text = iconv($sourceCharset, $targetCharset, $text); + } + } + + // Lets make sure that we don't have that silly BOM issue with any of the utf-8 text we output. + if ($targetCharset === 'UTF-8') { + if (substr($converted_text, 0, 3) === "\xef\xbb\xbf") { + $converted_text = substr($converted_text, 3); + } + + if (substr($converted_text, -3) === "\xef\xbb\xbf") { + $converted_text = substr($converted_text, 0, -3); + } + } + + return $converted_text; + } + + static function is_utf8($str) + { + $c = 0; $b = 0; + $bits = 0; + $len = strlen($str); + for($i = 0; $i < $len; $i++) { + $c = ord($str[$i]); + if($c > 128) { + if(($c >= 254)) { return false; } + elseif($c >= 252) { $bits = 6; } + elseif($c >= 248) { $bits = 5; } + elseif($c >= 240) { $bits = 4; } + elseif($c >= 224) { $bits = 3; } + elseif($c >= 192) { $bits = 2; } + else { return false; } + if(($i + $bits) > $len) { return false; } + while($bits > 1) { + $i++; + $b = ord($str[$i]); + if($b < 128 || $b > 191) { return false; } + $bits--; + } + } + } + return true; + } + + function get_display_size() + { + global $debug_object; + + $width = -1; + $height = -1; + + if ($this->tag !== 'img') { + return false; + } + + // See if there is aheight or width attribute in the tag itself. + if (isset($this->attr['width'])) { + $width = $this->attr['width']; + } + + if (isset($this->attr['height'])) { + $height = $this->attr['height']; + } + + // Now look for an inline style. + if (isset($this->attr['style'])) { + // Thanks to user gnarf from stackoverflow for this regular expression. + $attributes = array(); + + preg_match_all( + '/([\w-]+)\s*:\s*([^;]+)\s*;?/', + $this->attr['style'], + $matches, + PREG_SET_ORDER + ); + + foreach ($matches as $match) { + $attributes[$match[1]] = $match[2]; + } + + // If there is a width in the style attributes: + if (isset($attributes['width']) && $width == -1) { + // check that the last two characters are px (pixels) + if (strtolower(substr($attributes['width'], -2)) === 'px') { + $proposed_width = substr($attributes['width'], 0, -2); + // Now make sure that it's an integer and not something stupid. + if (filter_var($proposed_width, FILTER_VALIDATE_INT)) { + $width = $proposed_width; + } + } + } + + // If there is a width in the style attributes: + if (isset($attributes['height']) && $height == -1) { + // check that the last two characters are px (pixels) + if (strtolower(substr($attributes['height'], -2)) == 'px') { + $proposed_height = substr($attributes['height'], 0, -2); + // Now make sure that it's an integer and not something stupid. + if (filter_var($proposed_height, FILTER_VALIDATE_INT)) { + $height = $proposed_height; + } + } + } + + } + + // Future enhancement: + // Look in the tag to see if there is a class or id specified that has + // a height or width attribute to it. + + // Far future enhancement + // Look at all the parent tags of this image to see if they specify a + // class or id that has an img selector that specifies a height or width + // Note that in this case, the class or id will have the img subselector + // for it to apply to the image. + + // ridiculously far future development + // If the class or id is specified in a SEPARATE css file thats not on + // the page, go get it and do what we were just doing for the ones on + // the page. + + $result = array( + 'height' => $height, + 'width' => $width + ); + + return $result; + } + + function save($filepath = '') + { + $ret = $this->outertext(); + + if ($filepath !== '') { + file_put_contents($filepath, $ret, LOCK_EX); + } + + return $ret; + } + + function addClass($class) + { + if (is_string($class)) { + $class = explode(' ', $class); + } + + if (is_array($class)) { + foreach($class as $c) { + if (isset($this->class)) { + if ($this->hasClass($c)) { + continue; + } else { + $this->class .= ' ' . $c; + } + } else { + $this->class = $c; + } + } + } else { + if (is_object($debug_object)) { + $debug_object->debug_log(2, 'Invalid type: ', gettype($class)); + } + } + } + + function hasClass($class) + { + if (is_string($class)) { + if (isset($this->class)) { + return in_array($class, explode(' ', $this->class), true); + } + } else { + if (is_object($debug_object)) { + $debug_object->debug_log(2, 'Invalid type: ', gettype($class)); + } + } + + return false; + } + + function removeClass($class = null) + { + if (!isset($this->class)) { + return; + } + + if (is_null($class)) { + $this->removeAttribute('class'); + return; + } + + if (is_string($class)) { + $class = explode(' ', $class); + } + + if (is_array($class)) { + $class = array_diff(explode(' ', $this->class), $class); + if (empty($class)) { + $this->removeAttribute('class'); + } else { + $this->class = implode(' ', $class); + } + } + } + + function getAllAttributes() + { + return $this->attr; + } + + function getAttribute($name) + { + return $this->__get($name); + } + + function setAttribute($name, $value) + { + $this->__set($name, $value); + } + + function hasAttribute($name) + { + return $this->__isset($name); + } + + function removeAttribute($name) + { + $this->__set($name, null); + } + + function remove() + { + if ($this->parent) { + $this->parent->removeChild($this); + } + } + + function removeChild($node) + { + $nidx = array_search($node, $this->nodes, true); + $cidx = array_search($node, $this->children, true); + $didx = array_search($node, $this->dom->nodes, true); + + if ($nidx !== false && $cidx !== false && $didx !== false) { + + foreach($node->children as $child) { + $node->removeChild($child); + } + + foreach($node->nodes as $entity) { + $enidx = array_search($entity, $node->nodes, true); + $edidx = array_search($entity, $node->dom->nodes, true); + + if ($enidx !== false && $edidx !== false) { + unset($node->nodes[$enidx]); + unset($node->dom->nodes[$edidx]); + } + } + + unset($this->nodes[$nidx]); + unset($this->children[$cidx]); + unset($this->dom->nodes[$didx]); + + $node->clear(); + + } + } + + function getElementById($id) + { + return $this->find("#$id", 0); + } + + function getElementsById($id, $idx = null) + { + return $this->find("#$id", $idx); + } + + function getElementByTagName($name) + { + return $this->find($name, 0); + } + + function getElementsByTagName($name, $idx = null) + { + return $this->find($name, $idx); + } + + function parentNode() + { + return $this->parent(); + } + + function childNodes($idx = -1) + { + return $this->children($idx); + } + + function firstChild() + { + return $this->first_child(); + } + + function lastChild() + { + return $this->last_child(); + } + + function nextSibling() + { + return $this->next_sibling(); + } + + function previousSibling() + { + return $this->prev_sibling(); + } + + function hasChildNodes() + { + return $this->has_child(); + } + + function nodeName() + { + return $this->tag; + } + + function appendChild($node) + { + $node->parent($this); + return $node; + } + +} + +class simple_html_dom +{ + public $root = null; + public $nodes = array(); + public $callback = null; + public $lowercase = false; + public $original_size; + public $size; + + protected $pos; + protected $doc; + protected $char; + + protected $cursor; + protected $parent; + protected $noise = array(); + protected $token_blank = " \t\r\n"; + protected $token_equal = ' =/>'; + protected $token_slash = " />\r\n\t"; + protected $token_attr = ' >'; + + public $_charset = ''; + public $_target_charset = ''; + + protected $default_br_text = ''; + + public $default_span_text = ''; + + protected $self_closing_tags = array( + 'area' => 1, + 'base' => 1, + 'br' => 1, + 'col' => 1, + 'embed' => 1, + 'hr' => 1, + 'img' => 1, + 'input' => 1, + 'link' => 1, + 'meta' => 1, + 'param' => 1, + 'source' => 1, + 'track' => 1, + 'wbr' => 1 + ); + protected $block_tags = array( + 'body' => 1, + 'div' => 1, + 'form' => 1, + 'root' => 1, + 'span' => 1, + 'table' => 1 + ); + protected $optional_closing_tags = array( + // Not optional, see + // https://www.w3.org/TR/html/textlevel-semantics.html#the-b-element + 'b' => array('b' => 1), + 'dd' => array('dd' => 1, 'dt' => 1), + // Not optional, see + // https://www.w3.org/TR/html/grouping-content.html#the-dl-element + 'dl' => array('dd' => 1, 'dt' => 1), + 'dt' => array('dd' => 1, 'dt' => 1), + 'li' => array('li' => 1), + 'optgroup' => array('optgroup' => 1, 'option' => 1), + 'option' => array('optgroup' => 1, 'option' => 1), + 'p' => array('p' => 1), + 'rp' => array('rp' => 1, 'rt' => 1), + 'rt' => array('rp' => 1, 'rt' => 1), + 'td' => array('td' => 1, 'th' => 1), + 'th' => array('td' => 1, 'th' => 1), + 'tr' => array('td' => 1, 'th' => 1, 'tr' => 1), + ); + + function __construct( + $str = null, + $lowercase = true, + $forceTagsClosed = true, + $target_charset = DEFAULT_TARGET_CHARSET, + $stripRN = true, + $defaultBRText = DEFAULT_BR_TEXT, + $defaultSpanText = DEFAULT_SPAN_TEXT, + $options = 0) + { + if ($str) { + if (preg_match('/^http:\/\//i', $str) || is_file($str)) { + $this->load_file($str); + } else { + $this->load( + $str, + $lowercase, + $stripRN, + $defaultBRText, + $defaultSpanText, + $options + ); + } + } + // Forcing tags to be closed implies that we don't trust the html, but + // it can lead to parsing errors if we SHOULD trust the html. + if (!$forceTagsClosed) { + $this->optional_closing_array = array(); + } + + $this->_target_charset = $target_charset; + } + + function __destruct() + { + $this->clear(); + } + + function load( + $str, + $lowercase = true, + $stripRN = true, + $defaultBRText = DEFAULT_BR_TEXT, + $defaultSpanText = DEFAULT_SPAN_TEXT, + $options = 0) + { + global $debug_object; + + // prepare + $this->prepare($str, $lowercase, $defaultBRText, $defaultSpanText); + + // Per sourceforge http://sourceforge.net/tracker/?func=detail&aid=2949097&group_id=218559&atid=1044037 + // Script tags removal now preceeds style tag removal. + // strip out