PageRenderTime 49ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/plugins/SegmentEditor/API.php

https://github.com/CodeYellowBV/piwik
PHP | 334 lines | 318 code | 3 blank | 13 comment | 0 complexity | d2a88f58ac350ab92559f7277b9848e1 MD5 | raw file
Possible License(s): LGPL-3.0, JSON, MIT, GPL-3.0, LGPL-2.1, GPL-2.0, AGPL-1.0, BSD-2-Clause, BSD-3-Clause
  1. <?php
  2. /**
  3. * Piwik - free/libre analytics platform
  4. *
  5. * @link http://piwik.org
  6. * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
  7. *
  8. */
  9. namespace Piwik\Plugins\SegmentEditor;
  10. use Exception;
  11. use Piwik\Common;
  12. use Piwik\Date;
  13. use Piwik\Db;
  14. use Piwik\Piwik;
  15. use Piwik\Config;
  16. use Piwik\Plugins\UsersManager\UsersManager;
  17. use Piwik\Segment;
  18. /**
  19. * The SegmentEditor API lets you add, update, delete custom Segments, and list saved segments.a
  20. *
  21. * @method static \Piwik\Plugins\SegmentEditor\API getInstance()
  22. */
  23. class API extends \Piwik\Plugin\API
  24. {
  25. protected function checkSegmentValue($definition, $idSite)
  26. {
  27. // unsanitize so we don't record the HTML entitied segment
  28. $definition = Common::unsanitizeInputValue($definition);
  29. $definition = str_replace("#", '%23', $definition); // hash delimiter
  30. $definition = str_replace("'", '%27', $definition); // not encoded in JS
  31. $definition = str_replace("&", '%26', $definition);
  32. try {
  33. $segment = new Segment($definition, $idSite);
  34. $segment->getHash();
  35. } catch (Exception $e) {
  36. throw new Exception("The specified segment is invalid: " . $e->getMessage());
  37. }
  38. return $definition;
  39. }
  40. protected function checkSegmentName($name)
  41. {
  42. if (empty($name)) {
  43. throw new Exception("Invalid name for this custom segment.");
  44. }
  45. }
  46. protected function checkEnabledAllUsers($enabledAllUsers)
  47. {
  48. $enabledAllUsers = (int)$enabledAllUsers;
  49. if ($enabledAllUsers
  50. && !Piwik::hasUserSuperUserAccess()
  51. ) {
  52. throw new Exception("enabledAllUsers=1 requires Super User access");
  53. }
  54. return $enabledAllUsers;
  55. }
  56. protected function checkIdSite($idSite)
  57. {
  58. if (empty($idSite)) {
  59. if (!Piwik::hasUserSuperUserAccess()) {
  60. throw new Exception($this->getMessageCannotEditSegmentCreatedBySuperUser());
  61. }
  62. } else {
  63. if (!is_numeric($idSite)) {
  64. throw new Exception("idSite should be a numeric value");
  65. }
  66. Piwik::checkUserHasViewAccess($idSite);
  67. }
  68. $idSite = (int)$idSite;
  69. return $idSite;
  70. }
  71. protected function checkAutoArchive($autoArchive, $idSite)
  72. {
  73. $autoArchive = (int)$autoArchive;
  74. if ($autoArchive) {
  75. $exception = new Exception("To prevent abuse, autoArchive=1 requires Super User or ControllerAdmin access.");
  76. if (empty($idSite)) {
  77. if (!Piwik::hasUserSuperUserAccess()) {
  78. throw $exception;
  79. }
  80. } else {
  81. if (!Piwik::isUserHasAdminAccess($idSite)) {
  82. throw $exception;
  83. }
  84. }
  85. }
  86. return $autoArchive;
  87. }
  88. protected function getSegmentOrFail($idSegment)
  89. {
  90. $segment = $this->get($idSegment);
  91. if (empty($segment)) {
  92. throw new Exception("Requested segment not found");
  93. }
  94. return $segment;
  95. }
  96. protected function checkUserIsNotAnonymous()
  97. {
  98. if (Piwik::isUserIsAnonymous()) {
  99. throw new Exception("To create, edit or delete Custom Segments, please sign in first.");
  100. }
  101. }
  102. protected function checkUserCanAddNewSegment($idSite)
  103. {
  104. if(!$this->isUserCanAddNewSegment($idSite)) {
  105. throw new Exception(Piwik::translate('SegmentEditor_YouDontHaveAccessToCreateSegments'));
  106. }
  107. }
  108. public function isUserCanAddNewSegment($idSite)
  109. {
  110. if(Piwik::isUserIsAnonymous()) {
  111. return false;
  112. }
  113. $requiredAccess = Config::getInstance()->General['adding_segment_requires_access'];
  114. $authorized =
  115. ($requiredAccess == 'view' && Piwik::isUserHasViewAccess($idSite)) ||
  116. ($requiredAccess == 'admin' && Piwik::isUserHasAdminAccess($idSite)) ||
  117. ($requiredAccess == 'superuser' && Piwik::hasUserSuperUserAccess())
  118. ;
  119. return $authorized;
  120. }
  121. protected function checkUserCanEditOrDeleteSegment($segment)
  122. {
  123. if(Piwik::hasUserSuperUserAccess()) {
  124. return;
  125. }
  126. $this->checkUserIsNotAnonymous();
  127. if($segment['login'] != Piwik::getCurrentUserLogin()) {
  128. throw new Exception($this->getMessageCannotEditSegmentCreatedBySuperUser());
  129. }
  130. }
  131. /**
  132. * Deletes a stored segment.
  133. *
  134. * @param $idSegment
  135. * @return bool
  136. */
  137. public function delete($idSegment)
  138. {
  139. $segment = $this->getSegmentOrFail($idSegment);
  140. $this->checkUserCanEditOrDeleteSegment($segment);
  141. /**
  142. * Triggered before a segment is deleted or made invisible.
  143. *
  144. * This event can be used by plugins to throw an exception
  145. * or do something else.
  146. *
  147. * @param int $idSegment The ID of the segment being deleted.
  148. */
  149. Piwik::postEvent('SegmentEditor.deactivate', array($idSegment));
  150. $db = Db::get();
  151. $db->delete(Common::prefixTable('segment'), 'idsegment = ' . $idSegment);
  152. return true;
  153. }
  154. /**
  155. * Modifies an existing stored segment.
  156. *
  157. * @param int $idSegment The ID of the stored segment to modify.
  158. * @param string $name The new name of the segment.
  159. * @param string $definition The new definition of the segment.
  160. * @param bool $idSite If supplied, associates the stored segment with as single site.
  161. * @param bool $autoArchive Whether to automatically archive data with the segment or not.
  162. * @param bool $enabledAllUsers Whether the stored segment is viewable by all users or just the one that created it.
  163. *
  164. * @return bool
  165. */
  166. public function update($idSegment, $name, $definition, $idSite = false, $autoArchive = false, $enabledAllUsers = false)
  167. {
  168. $segment = $this->getSegmentOrFail($idSegment);
  169. $this->checkUserCanEditOrDeleteSegment($segment);
  170. $idSite = $this->checkIdSite($idSite);
  171. $this->checkSegmentName($name);
  172. $definition = $this->checkSegmentValue($definition, $idSite);
  173. $enabledAllUsers = $this->checkEnabledAllUsers($enabledAllUsers);
  174. $autoArchive = $this->checkAutoArchive($autoArchive, $idSite);
  175. $bind = array(
  176. 'name' => $name,
  177. 'definition' => $definition,
  178. 'enable_all_users' => $enabledAllUsers,
  179. 'enable_only_idsite' => $idSite,
  180. 'auto_archive' => $autoArchive,
  181. 'ts_last_edit' => Date::now()->getDatetime(),
  182. );
  183. /**
  184. * Triggered before a segment is modified.
  185. *
  186. * This event can be used by plugins to throw an exception
  187. * or do something else.
  188. *
  189. * @param int $idSegment The ID of the segment which visibility is reduced.
  190. */
  191. Piwik::postEvent('SegmentEditor.update', array($idSegment, $bind));
  192. $db = Db::get();
  193. $db->update(Common::prefixTable("segment"),
  194. $bind,
  195. "idsegment = $idSegment"
  196. );
  197. return true;
  198. }
  199. /**
  200. * Adds a new stored segment.
  201. *
  202. * @param string $name The new name of the segment.
  203. * @param string $definition The new definition of the segment.
  204. * @param bool $idSite If supplied, associates the stored segment with as single site.
  205. * @param bool $autoArchive Whether to automatically archive data with the segment or not.
  206. * @param bool $enabledAllUsers Whether the stored segment is viewable by all users or just the one that created it.
  207. *
  208. * @return int The newly created segment Id
  209. */
  210. public function add($name, $definition, $idSite = false, $autoArchive = false, $enabledAllUsers = false)
  211. {
  212. $this->checkUserCanAddNewSegment($idSite);
  213. $idSite = $this->checkIdSite($idSite);
  214. $this->checkSegmentName($name);
  215. $definition = $this->checkSegmentValue($definition, $idSite);
  216. $enabledAllUsers = $this->checkEnabledAllUsers($enabledAllUsers);
  217. $autoArchive = $this->checkAutoArchive($autoArchive, $idSite);
  218. $db = Db::get();
  219. $bind = array(
  220. 'name' => $name,
  221. 'definition' => $definition,
  222. 'login' => Piwik::getCurrentUserLogin(),
  223. 'enable_all_users' => $enabledAllUsers,
  224. 'enable_only_idsite' => $idSite,
  225. 'auto_archive' => $autoArchive,
  226. 'ts_created' => Date::now()->getDatetime(),
  227. 'deleted' => 0,
  228. );
  229. $db->insert(Common::prefixTable("segment"), $bind);
  230. return $db->lastInsertId();
  231. }
  232. /**
  233. * Returns a stored segment by ID
  234. *
  235. * @param $idSegment
  236. * @throws Exception
  237. * @return bool
  238. */
  239. public function get($idSegment)
  240. {
  241. Piwik::checkUserHasSomeViewAccess();
  242. if (!is_numeric($idSegment)) {
  243. throw new Exception("idSegment should be numeric.");
  244. }
  245. $segment = Db::get()->fetchRow("SELECT * " .
  246. " FROM " . Common::prefixTable("segment") .
  247. " WHERE idsegment = ?", $idSegment);
  248. if (empty($segment)) {
  249. return false;
  250. }
  251. try {
  252. if (!$segment['enable_all_users']) {
  253. Piwik::checkUserHasSuperUserAccessOrIsTheUser($segment['login']);
  254. }
  255. } catch (Exception $e) {
  256. throw new Exception($this->getMessageCannotEditSegmentCreatedBySuperUser());
  257. }
  258. if ($segment['deleted']) {
  259. throw new Exception("This segment is marked as deleted. ");
  260. }
  261. return $segment;
  262. }
  263. /**
  264. * Returns all stored segments.
  265. *
  266. * @param bool|int $idSite Whether to return stored segments for a specific idSite, or all of them. If supplied, must be a valid site ID.
  267. * @return array
  268. */
  269. public function getAll($idSite = false)
  270. {
  271. if (!empty($idSite)) {
  272. Piwik::checkUserHasViewAccess($idSite);
  273. } else {
  274. Piwik::checkUserHasSomeViewAccess();
  275. }
  276. $userLogin = Piwik::getCurrentUserLogin();
  277. $model = new Model();
  278. if (empty($idSite)) {
  279. $segments = $model->getAllSegments($userLogin);
  280. } else {
  281. $segments = $model->getAllSegmentsForSite($idSite, $userLogin);
  282. }
  283. return $segments;
  284. }
  285. /**
  286. * @return string
  287. */
  288. private function getMessageCannotEditSegmentCreatedBySuperUser()
  289. {
  290. $message = "You can only edit and delete custom segments that you have created yourself. This segment was created and 'shared with you' by the Super User. " .
  291. "To modify this segment, you can first create a new one by clicking on 'Add new segment'. Then you can customize the segment's definition.";
  292. return $message;
  293. }
  294. }