src/AppBundle/Controller/BaseController.php line 251

Open in your IDE?
  1. <?php
  2. namespace AppBundle\Controller;
  3. use AppBundle\Common\ArrayToolkit;
  4. use AppBundle\Common\Exception\ResourceNotFoundException;
  5. use AppBundle\Common\LoginToolkit;
  6. use Biz\ResourceManage\Service\ResourceManageService;
  7. use Biz\ResourceManage\Type\BaseType;
  8. use Biz\User\CurrentUser;
  9. use Bodoudou\SDK\BodoudouApi;
  10. use Common\PrepareOrgTrait;
  11. use Common\Validator;
  12. use CorporateTrainingBundle\Biz\ManagePermission\Service\ManagePermissionOrgService;
  13. use CorporateTrainingBundle\Biz\ResourceScope\Service\ResourceAccessScopeService;
  14. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  15. use Symfony\Component\Form\Extension\Core\Type\FormType;
  16. use Symfony\Component\HttpFoundation\JsonResponse;
  17. use Symfony\Component\HttpFoundation\Request;
  18. use Symfony\Component\HttpFoundation\Response;
  19. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  20. use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
  21. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  22. use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
  23. use Symfony\Component\Security\Http\SecurityEvents;
  24. use Topxia\Service\Common\ServiceKernel;
  25. class BaseController extends AbstractController
  26. {
  27.     use PrepareOrgTrait;
  28.     /**
  29.      * @return CurrentUser
  30.      */
  31.     protected function getCurrentUser()
  32.     {
  33.         return $this->getUser();
  34.     }
  35.     protected function getBiz()
  36.     {
  37.         return $this->container->get('biz');
  38.     }
  39.     /**
  40.      * @return CurrentUser
  41.      */
  42.     public function getUser()
  43.     {
  44.         $biz $this->getBiz();
  45.         return $biz['user'];
  46.     }
  47.     /**
  48.      * switch current user.
  49.      *
  50.      * @return CurrentUser
  51.      */
  52.     protected function switchUser(Request $requestCurrentUser $user)
  53.     {
  54.         $user['currentIp'] = $request->getClientIp();
  55.         $token = new UsernamePasswordToken($usernull'main'$user['roles']);
  56.         $this->container->get('security.token_storage')->setToken($token);
  57.         $biz $this->getBiz();
  58.         $biz['user'] = $user;
  59.         $this->container->get('event_dispatcher')->dispatch(
  60.             new InteractiveLoginEvent($request$token),
  61.             SecurityEvents::INTERACTIVE_LOGIN
  62.         );
  63.         return $user;
  64.     }
  65.     protected function authenticateUser(array $user)
  66.     {
  67.         if (!$user['pwdInit'] && !LoginToolkit::isEnforcementInitPwd()) {
  68.             $this->getUserService()->changePwdInit($user['id']);
  69.             $user['pwdInit'] = 1;
  70.         }
  71.         $user['currentIp'] = $this->container->get('request_stack')->getCurrentRequest()->getClientIp();
  72.         $currentUser = new CurrentUser();
  73.         $currentUser->fromArray($user);
  74.         return $this->switchUser($this->get('request_stack')->getCurrentRequest(), $currentUser);
  75.     }
  76.     protected function fillOrgCode($conditions)
  77.     {
  78.         if (isset($conditions['orgCode']) && !$this->getCurrentUser()->hasManagePermissionWithOrgCode($conditions['orgCode'])) {
  79.             $conditions['likeOrgCode'] = '-1';
  80.             return $conditions;
  81.         }
  82.         if ($this->setting('magic.enable_org')) {
  83.             if (!isset($conditions['orgCode'])) {
  84.                 $orgCodes $this->getCurrentUser()->getManageOrgCodes();
  85.                 $conditions['likeOrgCode'] = empty($orgCodes) ? '-1' $orgCodes[0];
  86.             } else {
  87.                 $conditions['likeOrgCode'] = $conditions['orgCode'];
  88.                 unset($conditions['orgCode']);
  89.             }
  90.         } else {
  91.             if (isset($conditions['orgCode'])) {
  92.                 unset($conditions['orgCode']);
  93.             }
  94.         }
  95.         return $conditions;
  96.     }
  97.     protected function buildAccessScope($fields)
  98.     {
  99.         return $this->getResourceAccessService()->processAccessScope($fields);
  100.     }
  101.     protected function createViolationJsonResponse($message ''$code 0)
  102.     {
  103.         return $this->createJsonResponse([
  104.             'status' => false,
  105.             'code' => $code,
  106.             'message' => $this->getMessage($message),
  107.         ], Response::HTTP_BAD_REQUEST);
  108.     }
  109.     protected function getMessage($message$arguments = [], $domain null$locale null)
  110.     {
  111.         return ServiceKernel::instance()->trans($message$arguments$domain$locale);
  112.     }
  113.     /**
  114.      * 判断是否微信内置浏览器访问.
  115.      *
  116.      * @return bool
  117.      */
  118.     protected function isWxClient()
  119.     {
  120.         return $this->isMobileClient() && false !== strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger');
  121.     }
  122.     protected function qrcode($routerName$params)
  123.     {
  124.         $token $this->getTokenService()->makeToken('qrcode', [
  125.             'data' => [
  126.                 'url' => $this->generateUrl($routerName$paramsUrlGeneratorInterface::ABSOLUTE_URL),
  127.             ],
  128.             'duration' => 3600 24 365,
  129.         ]);
  130.         $url $this->generateUrl('common_parse_qrcode', ['token' => $token['token']], UrlGeneratorInterface::ABSOLUTE_URL);
  131.         return $this->generateUrl('common_qrcode', ['text' => $url], UrlGeneratorInterface::ABSOLUTE_URL);
  132.     }
  133.     /**
  134.      * 是否移动端访问访问.
  135.      *
  136.      * @return bool
  137.      */
  138.     protected function isMobileClient()
  139.     {
  140.         // 如果有HTTP_X_WAP_PROFILE则一定是移动设备
  141.         if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) {
  142.             return true;
  143.         }
  144.         // 判断手机发送的客户端标志,兼容性有待提高
  145.         if (isset($_SERVER['HTTP_USER_AGENT'])) {
  146.             $clientkeywords = [
  147.                 'nokia',
  148.                 'sony',
  149.                 'ericsson',
  150.                 'mot',
  151.                 'samsung',
  152.                 'htc',
  153.                 'sgh',
  154.                 'lg',
  155.                 'sharp',
  156.                 'sie-',
  157.                 'philips',
  158.                 'panasonic',
  159.                 'alcatel',
  160.                 'lenovo',
  161.                 'iphone',
  162.                 'ipod',
  163.                 'blackberry',
  164.                 'meizu',
  165.                 'android',
  166.                 'netfront',
  167.                 'symbian',
  168.                 'ucweb',
  169.                 'windowsce',
  170.                 'palm',
  171.                 'operamini',
  172.                 'operamobi',
  173.                 'openwave',
  174.                 'nexusone',
  175.                 'cldc',
  176.                 'midp',
  177.                 'wap',
  178.                 'mobile',
  179.                 'ipad',
  180.             ];
  181.             // 从HTTP_USER_AGENT中查找手机浏览器的关键字
  182.             if (preg_match('/('.implode('|'$clientkeywords).')/i'strtolower($_SERVER['HTTP_USER_AGENT']))) {
  183.                 return true;
  184.             }
  185.         }
  186.         // 如果via信息含有wap则一定是移动设备,部分服务商会屏蔽该信息
  187.         if (isset($_SERVER['HTTP_VIA'])) {
  188.             // 找不到为flase,否则为true
  189.             return (bool) stristr($_SERVER['HTTP_VIA'], 'wap');
  190.         }
  191.         // 协议法,因为有可能不准确,放到最后判断
  192.         if (isset($_SERVER['HTTP_ACCEPT'])) {
  193.             // 如果只支持wml并且不支持html那一定是移动设备
  194.             // 如果支持wml和html但是wml在html之前则是移动设备
  195.             if ((false !== strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml'))
  196.                 && (false === strpos($_SERVER['HTTP_ACCEPT'], 'text/html')
  197.                     || (strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') < strpos($_SERVER['HTTP_ACCEPT'], 'text/html'))
  198.                 )) {
  199.                 return true;
  200.             }
  201.         }
  202.         return false;
  203.     }
  204.     protected function purifyHtml($html$trusted false)
  205.     {
  206.         $biz $this->getBiz();
  207.         $htmlHelper $biz['html_helper'];
  208.         return $htmlHelper->purify($html$trusted);
  209.     }
  210.     protected function trans($id, array $parameters = [], $domain null$locale null)
  211.     {
  212.         return $this->container->get('translator')->trans($id$parameters$domain$locale);
  213.     }
  214.     protected function isPluginInstalled($pluginName)
  215.     {
  216.         return $this->get('kernel')->getPluginConfigurationManager()->isPluginInstalled($pluginName);
  217.     }
  218.     protected function getTargetPath(Request $request)
  219.     {
  220.         if ($request->query->get('goto')) {
  221.             $targetPath $request->query->get('goto');
  222.         } elseif ($request->getSession()->has('_target_path')) {
  223.             $targetPath $request->getSession()->get('_target_path');
  224.         } else {
  225.             $targetPath $request->headers->get('Referer');
  226.         }
  227.         if (false !== strpos($targetPath'/register')) {
  228.             return $this->generateUrl('homepage');
  229.         }
  230.         if ($targetPath == $this->generateUrl('login', [], UrlGeneratorInterface::ABSOLUTE_URL)) {
  231.             return $this->generateUrl('homepage');
  232.         }
  233.         $url explode('?'$targetPath);
  234.         if ($url[0] == $this->generateUrl('partner_logout', [], UrlGeneratorInterface::ABSOLUTE_URL)) {
  235.             return $this->generateUrl('homepage');
  236.         }
  237.         if ($url[0] == $this->generateUrl('password_reset_update', [], UrlGeneratorInterface::ABSOLUTE_URL)) {
  238.             $targetPath $this->generateUrl('homepage', [], UrlGeneratorInterface::ABSOLUTE_URL);
  239.         }
  240.         if (strpos($url[0], $request->getPathInfo()) > -1) {
  241.             $targetPath $this->generateUrl('homepage', [], UrlGeneratorInterface::ABSOLUTE_URL);
  242.         }
  243.         if (false !== strpos($url[0], 'callback')
  244.             || false !== strpos($url[0], '/login/bind')
  245.             || false !== strpos($url[0], 'crontab')
  246.         ) {
  247.             $targetPath $this->generateUrl('homepage', [], UrlGeneratorInterface::ABSOLUTE_URL);
  248.         }
  249.         if (empty($targetPath)) {
  250.             $targetPath $this->generateUrl('homepage', [], UrlGeneratorInterface::ABSOLUTE_URL);
  251.         }
  252.         return $this->filterRedirectUrl($targetPath);
  253.     }
  254.     protected function setFlashMessage($level$message)
  255.     {
  256.         $this->get('session')->getFlashBag()->add($level$message);
  257.     }
  258.     protected function agentInWhiteList($userAgent)
  259.     {
  260.         $whiteList = ['iPhone''iPad''Android''HTC'];
  261.         return ArrayToolkit::some(
  262.             $whiteList,
  263.             function ($agent) use ($userAgent) {
  264.                 return strpos($userAgent$agent) > -1;
  265.             }
  266.         );
  267.     }
  268.     protected function createNamedFormBuilder($name$data null, array $options = [])
  269.     {
  270.         return $this->container->get('form.factory')->createNamedBuilder($nameFormType::class, $data$options);
  271.     }
  272.     protected function createJsonResponse($data null$status 200$headers = [])
  273.     {
  274.         return new JsonResponse($data$status$headers);
  275.     }
  276.     protected function createJsonpResponse($data null$callback 'callback'$status 200$headers = [])
  277.     {
  278.         $response $this->createJsonResponse($data$status$headers);
  279.         return $response->setCallback($callback);
  280.     }
  281.     // @todo 此方法是为了和旧的调用兼容,考虑清理掉
  282.     protected function createErrorResponse($request$name$message)
  283.     {
  284.         $error = ['error' => ['name' => $name'message' => $message]];
  285.         return new JsonResponse($error'200');
  286.     }
  287.     /**
  288.      * JSONM
  289.      * https://github.com/lifesinger/lifesinger.github.com/issues/118.
  290.      */
  291.     protected function createJsonmResponse($data)
  292.     {
  293.         $response = new JsonResponse($data);
  294.         $response->setCallback('define');
  295.         return $response;
  296.     }
  297.     /**
  298.      * 创建消息提示响应.
  299.      *
  300.      * @param string $type     消息类型:info, warning, error
  301.      * @param string $message  消息内容
  302.      * @param string $title    消息抬头
  303.      * @param int    $duration 消息显示持续的时间
  304.      * @param string $goto     消息跳转的页面
  305.      *
  306.      * @return Response
  307.      */
  308.     protected function createMessageResponse($type$message$title ''$duration 0$goto null)
  309.     {
  310.         if (!in_array($type, ['info''warning''error'])) {
  311.             throw new \RuntimeException('type error');
  312.         }
  313.         return $this->render(
  314.             'default/message.html.twig',
  315.             [
  316.                 'type' => $type,
  317.                 'message' => $message,
  318.                 'title' => $title,
  319.                 'duration' => $duration,
  320.                 'goto' => $this->filterRedirectUrl($goto),
  321.             ]
  322.         );
  323.     }
  324.     protected function createResourceNotFoundException($resourceType$resourceId$message '')
  325.     {
  326.         return new ResourceNotFoundException($resourceType$resourceId$message);
  327.     }
  328.     protected function createAccessDeniedException(string $message 'Access Denied.', ?\Throwable $previous null): AccessDeniedException
  329.     {
  330.         return new AccessDeniedException($message$previous);
  331.     }
  332.     /**
  333.      * 安全的重定向.
  334.      *
  335.      * 如果url不属于非本站域名下的,则重定向到本周首页。
  336.      *
  337.      * @param $url    string 重定向url
  338.      * @param $status int 重定向时的HTTP状态码
  339.      *
  340.      * @return \Symfony\Component\HttpFoundation\RedirectResponse
  341.      */
  342.     public function redirectSafely($url$status 302)
  343.     {
  344.         $url $this->filterRedirectUrl($url);
  345.         return $this->redirect($url$status);
  346.     }
  347.     /**
  348.      * 过滤URL.
  349.      *
  350.      * 如果url不属于非本站域名下的,则返回本站首页地址。
  351.      *
  352.      * @param $url string 待过滤的$url
  353.      *
  354.      * @return string
  355.      */
  356.     public function filterRedirectUrl($url)
  357.     {
  358.         $host $this->get('request_stack')->getCurrentRequest()->getHost();
  359.         $safeHosts = [$host];
  360.         $parsedUrl parse_url($url);
  361.         $isUnsafeHost = isset($parsedUrl['host']) && !in_array($parsedUrl['host'], $safeHosts);
  362.         if (empty($url) || $isUnsafeHost) {
  363.             $url $this->generateUrl('homepage', [], UrlGeneratorInterface::ABSOLUTE_URL);
  364.         }
  365.         return $url;
  366.     }
  367.     /**
  368.      * @param $conditions
  369.      *
  370.      * @return array
  371.      *               // 带有仅自己管理 组建查询的orgIds过滤
  372.      */
  373.     protected function prepareManageTypeOrgIds($conditions)
  374.     {
  375.         if (!isset($conditions['orgIds'])) {
  376.             $orgIds $this->getCurrentUser()->getManageOrgIdsRecursively();
  377.         } else {
  378.             $orgIds explode(','$conditions['orgIds']);
  379.         }
  380.         if (!isset($conditions['orgIds']) || (in_array(0explode(','$conditions['orgIds'])) && '' != $conditions['orgIds'])) {
  381.             $orgIds array_merge([0], $orgIds);
  382.         }
  383.         return $orgIds;
  384.     }
  385.     /**
  386.      * @param $resourceType
  387.      * @param $orgIds
  388.      *
  389.      * @return array
  390.      *               //带仅定管理员查询组件查询参数构造
  391.      */
  392.     protected function prepareManageResourceIds($resourceType$orgIds): array
  393.     {
  394.         $userIds = [];
  395.         if (in_array(0$orgIds)) {
  396.             if ($this->getUser()->isSuperAdmin()) {
  397.                 $userIds $this->getResourceManageClass($resourceType)->searchManageUserIds();
  398.             }
  399.             $userIds[] = $this->getUser()->getId();
  400.         }
  401.         $targetList = [
  402.             'org' => array_values(array_unique($orgIds)),
  403.             'user' => array_values(array_unique($userIds)),
  404.         ];
  405.         if (empty($targetList['org']) && empty($targetList['user'])) {
  406.             return [];
  407.         }
  408.         return $this->getResourceManageClass($resourceType)->searchManageResourceIds($targetList);
  409.     }
  410.     /**
  411.      * @param $fields
  412.      *
  413.      * @return mixed
  414.      *               // 处理资源带有指定管理员权限组件的创建数据
  415.      */
  416.     protected function processResourceManagePermission($fields)
  417.     {
  418.         $resourceManage = [
  419.             'manageType' => 'user',
  420.             'manageTargetIds' => [$this->getCurrentUser()->getId()],
  421.         ];
  422.         if (empty($fields['manageType']) || empty($fields['manageUserIds'])) {
  423.             $fields['resourceManage'] = $resourceManage;
  424.             return $fields;
  425.         }
  426.         if ('org' == $fields['manageType']) {
  427.             $manageOrg = !empty($fields['orgCode']) ? $this->getOrgService()->getOrgByOrgCode($fields['orgCode']) : ($this->getCurrentUser()->getManageOrgIds() ? ['id' => $this->getCurrentUser()->getManageOrgIds()[0]] : []);
  428.             $orgId = empty($manageOrg['id']) ? $this->getCurrentUser()->getCurrentOrgId() : $manageOrg['id'];
  429.             $org $this->getOrgService()->getOrg($orgId);
  430.             if ('org' == $fields['manageType'] && !$this->getCurrentUser()->hasManagePermissionWithOrgCode($org['orgCode'])) {
  431.                 throw $this->createAccessDeniedException($this->trans('所属部门不在你的管理范围内'));
  432.             }
  433.             $resourceManage['manageType'] = 'org';
  434.             $resourceManage['manageTargetIds'] = [$orgId];
  435.         } else {
  436.             $resourceManage['manageTargetIds'] = explode(','$fields['manageUserIds']);
  437.         }
  438.         $fields['resourceManage'] = $resourceManage;
  439.         unset($fields['orgId']);
  440.         unset($fields['orgCode']);
  441.         unset($fields['manageUserIds']);
  442.         return $fields;
  443.     }
  444.     protected function prepareListKeyWordTypeConditions($conditions$resourceType)
  445.     {
  446.         if (!empty($conditions['keyword']) && 'nameLike' == $conditions['keywordType']) {
  447.             $conditions[$conditions['keywordType']] = $conditions['keyword'];
  448.         }
  449.         if (!empty($conditions['keyword']) && 'createdUserId' == $conditions['keywordType']) {
  450.             $users $this->getUserService()->searchUsers(['truename' => $conditions['keyword']], [], 02000, ['id']);
  451.             $conditions['createdUserIds'] = empty($users) ? [-1] : array_column($users'id');
  452.         }
  453.         if (!empty($conditions['keyword']) && 'manageUser' == $conditions['keywordType']) {
  454.             $users $this->getUserService()->searchUsers(['truename' => $conditions['keyword']], [], 02000, ['id''truename']);
  455.             $resourceRecords $this->getResourceManageService()->searchRecords(['manageType' => 'user''resourceType' => $resourceType'targetIds' => empty($users) ? [-1] : array_column($users'id')], [], 0PHP_INT_MAX, ['resourceId']);
  456.             $resourceIds = isset($conditions['ids']) ? array_intersect($conditions['ids'], array_column($resourceRecords'resourceId')) : array_column($resourceRecords'resourceId');
  457.             $conditions['ids'] = empty($resourceIds) ? [-1] : $resourceIds;
  458.         }
  459.         unset($conditions['keywordType']);
  460.         unset($conditions['keyword']);
  461.         return $conditions;
  462.     }
  463.     protected function filterLockedAndDeletedUsers($conditions)
  464.     {
  465.         $conditions['userIds'] = isset($conditions['userIds']) ? $conditions['userIds'] : [];
  466.         $users $this->getUserService()->findDeletedAndLockedUsers();
  467.         $excludeUserIds ArrayToolkit::column($users'id');
  468.         if (empty($excludeUserIds)) {
  469.             return $conditions;
  470.         }
  471.         if (!empty($conditions['userIds'])) {
  472.             $conditions['userIds'] = array_diff($conditions['userIds'], $excludeUserIds);
  473.         }
  474.         return $conditions;
  475.     }
  476.     protected function getResourceManageClass($type): BaseType
  477.     {
  478.         return $this->getBiz()->offsetGet('resource_manage.'.$type);
  479.     }
  480.     /**
  481.      * @return ResourceManageService
  482.      */
  483.     protected function getResourceManageService()
  484.     {
  485.         return $this->createService('ResourceManage:ResourceManageService');
  486.     }
  487.     protected function createSuccessJsonResponse($data = [])
  488.     {
  489.         $data array_merge(['success' => 1], $data);
  490.         return $this->createJsonResponse($data);
  491.     }
  492.     protected function createFailJsonResponse($data = [])
  493.     {
  494.         $data array_merge(['success' => 0], $data);
  495.         return $this->createJsonResponse($data);
  496.     }
  497.     protected function getWebExtension()
  498.     {
  499.         return $this->get('web.twig.extension');
  500.     }
  501.     protected function createService($alias)
  502.     {
  503.         $biz $this->getBiz();
  504.         return $biz->service($alias);
  505.     }
  506.     protected function setting($name$default null)
  507.     {
  508.         return $this->get('web.twig.extension')->getSetting($name$default);
  509.     }
  510.     /**
  511.      * @return ManagePermissionOrgService
  512.      */
  513.     protected function getManagePermissionService()
  514.     {
  515.         return $this->getBiz()->service('CorporateTrainingBundle:ManagePermission:ManagePermissionOrgService');
  516.     }
  517.     /**
  518.      * @return \Biz\User\Service\UserService
  519.      */
  520.     protected function getUserService()
  521.     {
  522.         return $this->getBiz()->service('User:UserService');
  523.     }
  524.     protected function getTokenService()
  525.     {
  526.         return $this->getBiz()->service('User:TokenService');
  527.     }
  528.     /**
  529.      * @return \Biz\System\Service\LogService
  530.      */
  531.     protected function getLogService()
  532.     {
  533.         return $this->getBiz()->service('System:LogService');
  534.     }
  535.     /**
  536.      * @return \Biz\Org\Service\OrgService
  537.      */
  538.     protected function getOrgService()
  539.     {
  540.         return $this->getBiz()->service('Org:OrgService');
  541.     }
  542.     /**
  543.      * @return ResourceAccessScopeService
  544.      */
  545.     protected function getResourceAccessService()
  546.     {
  547.         return $this->createService('CorporateTrainingBundle:ResourceScope:ResourceAccessScopeService');
  548.     }
  549.     /**
  550.      * @return BodoudouApi
  551.      */
  552.     protected function getBodoudouApiService()
  553.     {
  554.         return $this->getBiz()['bodoudou.api'];
  555.     }
  556.     /**
  557.      * @return Validator
  558.      */
  559.     protected function getCommonValidator()
  560.     {
  561.         return $this->getBiz()['common.validator'];
  562.     }
  563. }