From 68f6fbd1c7562c6028d7c8c292716517ed3b2c13 Mon Sep 17 00:00:00 2001 From: aviggngyv Date: Wed, 23 Oct 2019 11:19:11 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BA=86=E5=BE=88=E5=A4=9A?= =?UTF-8?q?=E4=B8=9C=E8=A5=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 3 + composer.json | 3 +- core/includes/common.inc | 25 +- core/includes/theme.inc | 10 + core/lib/Hunter/App/Application.php | 15 + .../Hunter/App/Strategy/HunterStrategy.php | 59 +-- core/lib/Hunter/Cache/FastCache.php | 52 ++ core/lib/Hunter/Database/Schema.php | 36 +- core/lib/Hunter/Discovery/PluginDiscovery.php | 2 +- core/lib/Hunter/FormApi/Seven.php | 443 ++++++++++++++++++ module/test/src/Controller/TestController.php | 2 +- sites/config.php | 9 +- theme/front/.htaccess | 4 + theme/{hunter => front}/index.html | 0 14 files changed, 625 insertions(+), 38 deletions(-) create mode 100644 .gitattributes create mode 100644 core/lib/Hunter/Cache/FastCache.php create mode 100644 core/lib/Hunter/FormApi/Seven.php create mode 100644 theme/front/.htaccess rename theme/{hunter => front}/index.html (100%) diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..b748c52 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +*.js linguist-language=php +*.css linguist-language=php +*.html linguist-language=php diff --git a/composer.json b/composer.json index 4424e81..8b513f1 100644 --- a/composer.json +++ b/composer.json @@ -21,12 +21,13 @@ "schnittstabil/csrf-tokenservice": "^3.1", "lootils/uuid": "^1.0", "overclokk/cookie": "^1.0", + "phpfastcache/phpfastcache": "^7.1", "fzaninotto/faker": "^1.6", "creitive/breadcrumbs": "^3.1", "voku/anti-xss": "^2.0", "gregwar/captcha": "1.*", "katzgrau/klogger": "^1.2", - "doctrine/annotations": "dev-master", + "doctrine/annotations": "^1.8", "overtrue/pinyin": "~3.0" }, "extra": { diff --git a/core/includes/common.inc b/core/includes/common.inc index 209a0a1..7e96cdf 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -15,6 +15,7 @@ use Zend\Diactoros\ServerRequestFactory; use Zend\Diactoros\Response\RedirectResponse; use Hunter\Core\FormApi\Layui; use Hunter\Core\FormApi\Bootstrap; +use Hunter\Core\FormApi\Seven; use voku\helper\AntiXSS; use Overclokk\Cookie\Cookie; use Gregwar\Image\Image; @@ -241,10 +242,9 @@ function hunter_convert_to_utf8($data) { * 转换文件名. */ function hunter_rename($text, $ext = false, $type = 'date', $format = 'YmdHis') { - $string = new StringConverter(); $houzhui = substr(strrchr($text, '.'), 1); $basename = basename($text,".".$houzhui); - $newname = $string->createMachineName($basename); + $newname = machine_name($basename); if($type == 'date'){ $newname .= '_'.date($format, time()); } @@ -298,7 +298,7 @@ function hunter_map_assoc($array, $function = NULL) { */ function hunter_form_render($type, &$fields, $module = NULL, $parms = NULL, $wrap = TRUE, $parentform = NULL) { global $app; - $form_id = 'exampleForm-'.rand(1,100); + $form_id = 'hpForm-'.rand(1,100); if(isset($fields['form_id'])){ $form_id = $fields['form_id']; unset($fields['form_id']); @@ -329,9 +329,11 @@ function hunter_form_render($type, &$fields, $module = NULL, $parms = NULL, $wra } if($wrap){ - if($type == 'layui'){ + if($type == 'layui') { $form = Layui::create()->start($form_redirect, $form_id, $class, $show_type, $enctype); - }else{ + }elseif($type == 'seven') { + $form = Seven::create()->start($form_redirect, $form_id, $class, $show_type, $enctype); + }else { $form = Bootstrap::create()->start($form_redirect, $form_id, $class, $show_type, $enctype); } }else { @@ -428,6 +430,10 @@ function hunter_form_render($type, &$fields, $module = NULL, $parms = NULL, $wra if(isset($field['#disabled']) && $field['#disabled']){ $field['#attributes']['disabled'] = 'true'; } + if(isset($field['#multiple']) && $field['#multiple']){ + $field['#attributes']['multiple'] = 'multiple'; + $field['#name'] = $name.'[]'; + } element_set_attributes($field, array('id', 'name', 'size')); $form->select($name, $field); break; @@ -641,6 +647,15 @@ function module_exists($module) { return $app->getModuleHandle()->moduleExists($module); } +/** + * create machine name. + */ +function machine_name($text) { + $string = new StringConverter(); + $machine_name = $string->createMachineName($text); + return $machine_name; +} + if (!function_exists('e')) { /** * Escape HTML entities in a string. diff --git a/core/includes/theme.inc b/core/includes/theme.inc index 86b226b..a659d8f 100644 --- a/core/includes/theme.inc +++ b/core/includes/theme.inc @@ -23,6 +23,16 @@ function theme($target = 'default') { * @param $parameters 变量 */ function view($name, array $parameters = array(), $target = 'default') { + global $default_admin_theme, $default_front_theme; + + if($default_admin_theme !== 'admin' && strpos($name, 'admin') !==false) { + $name = str_replace("admin", $default_admin_theme, $name); + } + + if($default_front_theme !== 'front' && strpos($name, 'front') !==false) { + $name = str_replace("front", $default_front_theme, $name); + } + return theme($target)->setTemplate($name)->setParameters($parameters)->render($name, $parameters); } diff --git a/core/lib/Hunter/App/Application.php b/core/lib/Hunter/App/Application.php index ee82011..a3fabd2 100644 --- a/core/lib/Hunter/App/Application.php +++ b/core/lib/Hunter/App/Application.php @@ -396,6 +396,21 @@ protected function buildRouters($container) { } } + if(module_exists('views')) { + $all_views = views_get_all(); + static $view_paths = array(); + foreach ($all_views as $view) { + if(isset($view['view_path']) && $view['view_path'] && !isset($this->routeTitles[$view['view_path']]) && !isset($view_paths[$view['view_path']])){ + $view_paths[$view['view_path']] = $view['view_name']; + $route = $routers->map(['GET','POST'], $view['view_path'], '\Hunter\views\Controller\ViewsUIController::api_get_view'); + } + + if(is_object($route) && isset($view['view_permissions']) && !empty($view['view_permissions'])){ + $this->routePermission[$view['view_path']] = $view['view_permissions']; + } + } + } + $this->routers = $routers; $this->container->add('routePermission', $this->routePermission); $this->container->add('routeOptions', $this->routeOptions); diff --git a/core/lib/Hunter/App/Strategy/HunterStrategy.php b/core/lib/Hunter/App/Strategy/HunterStrategy.php index 275f917..ae52ddd 100644 --- a/core/lib/Hunter/App/Strategy/HunterStrategy.php +++ b/core/lib/Hunter/App/Strategy/HunterStrategy.php @@ -13,6 +13,8 @@ use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Zend\Diactoros\Response\RedirectResponse; +use Hunter\Core\Utility\StringConverter; +use Hunter\Core\Cache\FastCache; class HunterStrategy extends ApplicationStrategy implements StrategyInterface { /** @@ -20,41 +22,40 @@ class HunterStrategy extends ApplicationStrategy implements StrategyInterface { */ public function getCallable(Route $route, array $vars) { return function (ServerRequestInterface $request, ResponseInterface $response, callable $next) use ($route, $vars) { - global $default_theme, $hunter_static, $app; - $generate_html = false; + global $default_theme, $hunter_static, $app, $hunter_debug, $static_time; + timer_start(); $path = $route->getPath(); $routeNames = $route->getContainer()->get('routeNames'); $routeOptions = $route->getContainer()->get('routeOptions'); - //if enabled html static, and file exists, then load it + $routePermission = $route->getContainer()->get('routePermission'); + if($hunter_static && isset($routeNames[$path]) && !isset($routeOptions[$path]['no_cache']) && substr($path, 0, 6) != '/admin' && substr($path, 0, 5) != '/api/') { - $generate_file = 'sites/html/'.$default_theme.'/'.str_replace('.', '/', $routeNames[$path]); - if($vars){ - $generate_file .= '_'.implode('_',array_values($vars)); - } - if(is_file($generate_file.'.html')){ - require_once($generate_file.'.html'); - die; - }else { - $generate_html = true; - } - } + $FastCache = FastCache::getInstance(); + $string = new StringConverter(); + $serverParams = $request->getServerParams(); + $key = $string->createMachineName(ltrim($serverParams['REQUEST_URI'], '/'))."_cache"; - if(isset($routeOptions[$path]['init'])){ - foreach ($app->getModuleHandle()->getImplementations('init') as $module) { - $app->getModuleHandle()->invoke($module, 'init', array($request)); - } - } + if (!$FastCache->isCached($key)) { + $routeTitles = $route->getContainer()->get('routeTitles'); - $routeTitles = $route->getContainer()->get('routeTitles'); + if(isset($routeTitles[$path]) && function_exists('theme')){ + theme()->getEnvironment()->addGlobal('page_title', $routeTitles[$path]); + } + $vars['vars'] = $vars; + $body = $route->getContainer()->call($route->getCallable(), $vars); - if(isset($routeTitles[$path]) && function_exists('theme')){ - theme()->getEnvironment()->addGlobal('page_title', $routeTitles[$path]); - } - $vars['vars'] = $vars; - $body = $route->getContainer()->call($route->getCallable(), $vars); + $FastCache->set($key, $body, $static_time); + } else { + $body = $FastCache->get($key); + } + }else { + $routeTitles = $route->getContainer()->get('routeTitles'); - if($generate_html){ - $this->htmlMake($body, $generate_file); + if(isset($routeTitles[$path]) && function_exists('theme')){ + theme()->getEnvironment()->addGlobal('page_title', $routeTitles[$path]); + } + $vars['vars'] = $vars; + $body = $route->getContainer()->call($route->getCallable(), $vars); } if(is_array($body) || (is_object($body) && get_class($body) == 'stdClass')){ @@ -63,6 +64,10 @@ public function getCallable(Route $route, array $vars) { } if(is_string($body) || is_bool($body)){ + if($hunter_debug && (!isset($routePermission[$path]) || isset($routePermission[$path]) && $routePermission[$path] != 'pjax') && !isset($routeOptions[$path]['no_cache']) && substr($path, 0, 6) != '/admin' && substr($path, 0, 5) != '/api/') { + $body .= '
页面加载时间: '.timer_read(). ' ms
'; + } + if ($response->getBody()->isWritable()) { $response->getBody()->write($body); } diff --git a/core/lib/Hunter/Cache/FastCache.php b/core/lib/Hunter/Cache/FastCache.php new file mode 100644 index 0000000..a3f4a66 --- /dev/null +++ b/core/lib/Hunter/Cache/FastCache.php @@ -0,0 +1,52 @@ +conn = CacheManager::getInstance('files', new Config(["path" => $cache_dir, "itemDetailedDate" => false])); + } + + public static function getInstance(){ + if(!self::$instance){ + self::$instance = new FastCache(); + } + return self::$instance; + } + + public function getConnection(){ + return $this->conn; + } + + public function isCached($key){ + $CachedString = $this->conn->getItem($key); + return $CachedString->isHit(); + } + + public function set($key, $data, $expire = 60){ + $CachedString = $this->conn->getItem($key); + $CachedString->set($data)->expiresAfter($expire); + $this->conn->save($CachedString); + } + + public function get($key){ + return $this->conn->getItem($key)->get(); + } + + private function __clone(){ + } + +} diff --git a/core/lib/Hunter/Database/Schema.php b/core/lib/Hunter/Database/Schema.php index 09b8c44..f9f271a 100644 --- a/core/lib/Hunter/Database/Schema.php +++ b/core/lib/Hunter/Database/Schema.php @@ -185,7 +185,37 @@ public function addField($table, $field, $spec) { if (is_string($spec)) { $this->connection->query($spec); } - //todo spec is array + + $fixnull = FALSE; + if (!empty($spec['not null']) && !isset($spec['default']) && !$is_primary_key) { + $fixnull = TRUE; + $spec['not null'] = FALSE; + } + $query = 'ALTER TABLE {' . $table . '} ADD '; + $query .= $this->createFieldSql($field, $this->processField($spec)); + $this->connection->query($query); + if (isset($spec['initial_from_field'])) { + if (isset($spec['initial'])) { + $expression = 'COALESCE(' . $spec['initial_from_field'] . ', :default_initial_value)'; + $arguments = [':default_initial_value' => $spec['initial']]; + } + else { + $expression = $spec['initial_from_field']; + $arguments = []; + } + $this->connection->update($table) + ->expression($field, $expression, $arguments) + ->execute(); + } + elseif (isset($spec['initial'])) { + $this->connection->update($table) + ->fields([$field => $spec['initial']]) + ->execute(); + } + if ($fixnull) { + $spec['not null'] = TRUE; + $this->changeField($table, $field, $field, $spec); + } } /** @@ -212,7 +242,9 @@ public function changeField($table, $field, $field_new, $spec) { if (is_string($spec)) { $this->connection->query($spec); } - //todo spec is array + + $sql = 'ALTER TABLE {' . $table . '} CHANGE `' . $field . '` ' . $this->createFieldSql($field_new, $this->processField($spec)); + $this->connection->query($sql); } /** diff --git a/core/lib/Hunter/Discovery/PluginDiscovery.php b/core/lib/Hunter/Discovery/PluginDiscovery.php index 24b6a62..9217b0c 100644 --- a/core/lib/Hunter/Discovery/PluginDiscovery.php +++ b/core/lib/Hunter/Discovery/PluginDiscovery.php @@ -4,7 +4,7 @@ use ReflectionClass; use Hunter\Core\Utility\Unicode; -use Doctrine\Annotations\AnnotationReader; +use Doctrine\Common\Annotations\AnnotationReader; /** * Provides discovery for plugin within a given set of directories. diff --git a/core/lib/Hunter/FormApi/Seven.php b/core/lib/Hunter/FormApi/Seven.php new file mode 100644 index 0000000..a15c541 --- /dev/null +++ b/core/lib/Hunter/FormApi/Seven.php @@ -0,0 +1,443 @@ +form_show_type = $show_type; + switch ($enctype) + { + case true: + $this->form = '
'; + break; + default : + $this->form = ''; + break; + } + return $this; + } + + /** + * generate a file input + * + * @param $name + * @param $field + * @return $this + */ + public function file($name, $field) { + if(isset($field['#prefix'])){ + $this->form .= $field['#prefix']; + } + if(isset($field['#multiple'])){ + $this->form .= ' +
+ +
+
'.t('选择文件').' + +
+
+
+
'; + }else{ + $this->form .= ' +
+ +
+ +
'; + + if(!isset($field['#disabled']) || (isset($field['#disabled']) && !$field['#disabled'])){ + if($field['#type'] == 'file'){ + $this->form .= ''; + }else { + $this->form .= ''; + } + } + + $this->form .= '
'; + $this->form .= '
'; + if(isset($field['#default_value']) && !empty($field['#default_value'])) { + $this->form .= '
'; + } + $this->form .= '
'; + + if(isset($field['#description'])){ + $this->form .= ''.$field['#description'].''; + } + + $this->form .= '
'; + } + + if(isset($field['#suffix'])){ + $this->form .= $field['#suffix']; + } + + return $this; + } + + /** + * generate a hidden input + * + * @param $name + * @param $value + * @return $this + */ + public function hidden($name, $value) { + $this->form .= ''; + + return $this; + } + + /** + * generate a new input + * + * @param string $type + * @param array $field + * @return $this + */ + public function input($name, $field) { + if(isset($field['#prefix'])){ + $this->form .= $field['#prefix']; + } + $this->form .= '
'; + if(isset($field['#description'])){ + $this->form .= ''.$field['#description'].''; + } + + $this->form .= '
'; + + if(isset($field['#suffix'])){ + $this->form .= $field['#suffix']; + } + return $this; + } + + /** + * generate a textarea + * + * @param string $name + * @param array field + * @return $this + */ + public function textarea($name, $field) { + if(isset($field['#prefix'])){ + $this->form .= $field['#prefix']; + } + if(isset($field['#default_value'])){ + $this->form .= '
'; + }else { + $this->form .= '
'; + } + + if(isset($field['#description'])){ + $this->form .= ''.$field['#description'].''; + } + $this->form .= '
'; + + if(isset($field['#suffix'])){ + $this->form .= $field['#suffix']; + } + return $this; + } + + /** + * generate a image + * + * @return $this + */ + public function img($name, $field) { + if(isset($field['#prefix'])){ + $this->form .= $field['#prefix']; + } + $this->form .= ' +
+ +
+ +
+
'; + + if(isset($field['#suffix'])){ + $this->form .= $field['#suffix']; + } + return $this; + } + + /** + * generate a captcha + * + * @return $this + */ + public function captcha($name, $field) { + if(isset($field['#prefix'])){ + $this->form .= $field['#prefix']; + } + $this->form .= ' +
+ +
+ +
+
+ +
+
'; + + if(isset($field['#suffix'])){ + $this->form .= $field['#suffix']; + } + return $this; + } + + /** + * generate a fieldset + * + * @return $this + */ + public function fieldset($name, $field) { + if(isset($field['#prefix'])){ + $this->form .= $field['#prefix']; + } + $this->form .= ' +
+ '.$field['#title'].' +
'; + + if(isset($field['#suffix'])){ + $this->form .= $field['#suffix']; + } + return $this; + } + + /** + * generate a image + * + * @param string $src + * @param array $field + * @return $this + */ + public function markup($name, $field) { + if(isset($field['#prefix'])){ + $this->form .= $field['#prefix']; + } + if(isset($field['#title'])){ + if(isset($field['#hidden']) && $field['#hidden']){ + $this->form .= ' +