WhispeakAuthPlugin.php 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. <?php
  2. /* For licensing terms, see /license.txt */
  3. use Chamilo\CoreBundle\Entity\ExtraField;
  4. use Chamilo\CoreBundle\Entity\ExtraFieldValues;
  5. use Chamilo\UserBundle\Entity\User;
  6. /**
  7. * Class WhispeakAuthPlugin.
  8. */
  9. class WhispeakAuthPlugin extends Plugin
  10. {
  11. const SETTING_ENABLE = 'enable';
  12. const SETTING_API_URL = 'api_url';
  13. const SETTING_TOKEN = 'token';
  14. const SETTING_INSTRUCTION = 'instruction';
  15. const EXTRAFIELD_AUTH_UID = 'whispeak_auth_uid';
  16. /**
  17. * StudentFollowUpPlugin constructor.
  18. */
  19. protected function __construct()
  20. {
  21. parent::__construct(
  22. '0.1',
  23. 'Angel Fernando Quiroz',
  24. [
  25. self::SETTING_ENABLE => 'boolean',
  26. self::SETTING_API_URL => 'text',
  27. self::SETTING_TOKEN => 'text',
  28. self::SETTING_INSTRUCTION => 'html',
  29. ]
  30. );
  31. }
  32. /**
  33. * @return WhispeakAuthPlugin
  34. */
  35. public static function create()
  36. {
  37. static $result = null;
  38. return $result ? $result : $result = new self();
  39. }
  40. public function install()
  41. {
  42. UserManager::create_extra_field(
  43. self::EXTRAFIELD_AUTH_UID,
  44. \ExtraField::FIELD_TYPE_TEXT,
  45. $this->get_lang('Whispeak uid'),
  46. ''
  47. );
  48. }
  49. public function uninstall()
  50. {
  51. $extraField = self::getAuthUidExtraField();
  52. if (empty($extraField)) {
  53. return;
  54. }
  55. $em = Database::getManager();
  56. $em->createQuery('DELETE FROM ChamiloCoreBundle:ExtraFieldValues efv WHERE efv.field = :field')
  57. ->execute(['field' => $extraField]);
  58. $em->remove($extraField);
  59. $em->flush();
  60. }
  61. /**
  62. * @return ExtraField
  63. */
  64. public static function getAuthUidExtraField()
  65. {
  66. $em = Database::getManager();
  67. $efRepo = $em->getRepository('ChamiloCoreBundle:ExtraField');
  68. /** @var ExtraField $extraField */
  69. $extraField = $efRepo->findOneBy(
  70. [
  71. 'variable' => self::EXTRAFIELD_AUTH_UID,
  72. 'extraFieldType' => ExtraField::USER_FIELD_TYPE,
  73. ]
  74. );
  75. return $extraField;
  76. }
  77. /**
  78. * @param int $userId
  79. *
  80. * @return ExtraFieldValues
  81. */
  82. public static function getAuthUidValue($userId)
  83. {
  84. $extraField = self::getAuthUidExtraField();
  85. $em = Database::getManager();
  86. $efvRepo = $em->getRepository('ChamiloCoreBundle:ExtraFieldValues');
  87. /** @var ExtraFieldValues $value */
  88. $value = $efvRepo->findOneBy(['field' => $extraField, 'itemId' => $userId]);
  89. return $value;
  90. }
  91. /**
  92. * @param int $userId
  93. *
  94. * @return bool
  95. */
  96. public static function checkUserIsEnrolled($userId)
  97. {
  98. $value = self::getAuthUidValue($userId);
  99. if (empty($value)) {
  100. return false;
  101. }
  102. return !empty($value->getValue());
  103. }
  104. /**
  105. * @return string
  106. */
  107. public static function getEnrollmentUrl()
  108. {
  109. return api_get_path(WEB_PLUGIN_PATH).'whispeakauth/enrollment.php';
  110. }
  111. /**
  112. * @param User $user
  113. * @param string $filePath
  114. *
  115. * @return array
  116. */
  117. public function requestEnrollment(User $user, $filePath)
  118. {
  119. $metadata = [
  120. 'motherTongue' => $user->getLanguage(),
  121. 'spokenTongue' => $user->getLanguage(),
  122. 'audioType' => 'pcm',
  123. ];
  124. return $this->sendRequest(
  125. 'enrollment',
  126. $metadata,
  127. $user,
  128. $filePath
  129. );
  130. }
  131. /**
  132. * @param User $user
  133. * @param string $uid
  134. *
  135. * @throws \Doctrine\ORM\OptimisticLockException
  136. */
  137. public function saveEnrollment(User $user, $uid)
  138. {
  139. $em = Database::getManager();
  140. $value = self::getAuthUidValue($user->getId());
  141. if (empty($value)) {
  142. $ef = self::getAuthUidExtraField();
  143. $now = new DateTime('now', new DateTimeZone('UTC'));
  144. $value = new ExtraFieldValues();
  145. $value
  146. ->setField($ef)
  147. ->setItemId($user->getId())
  148. ->setUpdatedAt($now);
  149. }
  150. $value->setValue($uid);
  151. $em->persist($value);
  152. $em->flush();
  153. }
  154. public function requestAuthentify(User $user, $filePath)
  155. {
  156. $value = self::getAuthUidValue($user->getId());
  157. if (empty($value)) {
  158. return null;
  159. }
  160. $metadata = [
  161. 'uid' => $value->getValue(),
  162. 'audioType' => 'pcm',
  163. ];
  164. return $this->sendRequest(
  165. 'authentify',
  166. $metadata,
  167. $user,
  168. $filePath
  169. );
  170. }
  171. /**
  172. * @return string
  173. */
  174. public function getAuthentifySampleText()
  175. {
  176. $phrases = [];
  177. for ($i = 1; $i <= 6; $i++) {
  178. $phrases[] = $this->get_lang("AuthentifySampleText$i");
  179. }
  180. $rand = array_rand($phrases, 1);
  181. return $phrases[$rand];
  182. }
  183. /**
  184. * @return bool
  185. */
  186. public function toolIsEnabled()
  187. {
  188. return 'true' === $this->get(self::SETTING_ENABLE);
  189. }
  190. /**
  191. * Access not allowed when tool is not enabled.
  192. *
  193. * @param bool $printHeaders Optional. Print headers.
  194. */
  195. public function protectTool($printHeaders = true)
  196. {
  197. if ($this->toolIsEnabled()) {
  198. return;
  199. }
  200. api_not_allowed($printHeaders);
  201. }
  202. /**
  203. * @return string
  204. */
  205. private function getApiUrl()
  206. {
  207. $url = $this->get(self::SETTING_API_URL);
  208. return trim($url, " \t\n\r \v/");
  209. }
  210. /**
  211. * @param string $endPoint
  212. * @param array $metadata
  213. * @param User $user
  214. * @param string $filePath
  215. *
  216. * @return array
  217. */
  218. private function sendRequest($endPoint, array $metadata, User $user, $filePath)
  219. {
  220. $moderator = $user->getCreatorId() ?: $user->getId();
  221. $apiUrl = $this->getApiUrl()."/$endPoint";
  222. $headers = [
  223. //"Content-Type: application/x-www-form-urlencoded",
  224. "Authorization: Bearer ".$this->get(self::SETTING_TOKEN),
  225. ];
  226. $post = [
  227. 'metadata' => json_encode($metadata),
  228. 'moderator' => "moderator_$moderator",
  229. 'client' => base64_encode($user->getUserId()),
  230. 'voice' => new CURLFile($filePath),
  231. ];
  232. $ch = curl_init();
  233. curl_setopt($ch, CURLOPT_URL, $apiUrl);
  234. curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  235. curl_setopt($ch, CURLOPT_POST, true);
  236. curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
  237. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  238. $result = curl_exec($ch);
  239. curl_close($ch);
  240. $result = json_decode($result, true);
  241. if (!empty($result['error'])) {
  242. return null;
  243. }
  244. return json_decode($result, true);
  245. }
  246. }