src/AppBundle/Controller/BaseController.php line 263

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