| 1 | <?php
|
| 2 | /**
|
| 3 | * ###############################################
|
| 4 | *
|
| 5 | * SWIFT Framework
|
| 6 | * _______________________________________________
|
| 7 | *
|
| 8 | * @author Varun Shoor
|
| 9 | *
|
| 10 | * @package SWIFT
|
| 11 | * @copyright Copyright (c) 2001-2012, Kayako
|
| 12 | * @license http://www.kayako.com/license
|
| 13 | * @link http://www.kayako.com
|
| 14 | *
|
| 15 | * ###############################################
|
| 16 | */
|
| 17 |
|
| 18 | /**
|
| 19 | * The TicketAttachment API Controller
|
| 20 | *
|
| 21 | * @author Varun Shoor
|
| 22 | */
|
| 23 | class Controller_TicketAttachment extends Controller_api implements SWIFT_REST_Interface
|
| 24 | {
|
| 25 | /**
|
| 26 | * Constructor
|
| 27 | *
|
| 28 | * @author Varun Shoor
|
| 29 | * @return bool "true" on Success, "false" otherwise
|
| 30 | */
|
| 31 | public function __construct()
|
| 32 | {
|
| 33 | parent::__construct();
|
| 34 |
|
| 35 | $this->Load->Library('XML:XML');
|
| 36 |
|
| 37 | return true;
|
| 38 | }
|
| 39 |
|
| 40 | /**
|
| 41 | * Destructor
|
| 42 | *
|
| 43 | * @author Varun Shoor
|
| 44 | * @return bool "true" on Success, "false" otherwise
|
| 45 | */
|
| 46 | public function __destruct()
|
| 47 | {
|
| 48 | parent::__destruct();
|
| 49 |
|
| 50 | return true;
|
| 51 | }
|
| 52 |
|
| 53 | /**
|
| 54 | * GetList
|
| 55 | *
|
| 56 | * @author Varun Shoor
|
| 57 | * @return bool "true" on Success, "false" otherwise
|
| 58 | * @throws SWIFT_Exception If the Class is not Loaded
|
| 59 | */
|
| 60 | public function GetList()
|
| 61 | {
|
| 62 | if (!$this->GetIsClassLoaded())
|
| 63 | {
|
| 64 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
| 65 |
|
| 66 | return false;
|
| 67 | }
|
| 68 |
|
| 69 | $this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_BADREQUEST, 'Not Implemented, Call /Tickets/TicketAttachment/ListAll instead.');
|
| 70 |
|
| 71 | return false;
|
| 72 | }
|
| 73 |
|
| 74 |
|
| 75 | /**
|
| 76 | * Get a list of attachments for the given ticket
|
| 77 | *
|
| 78 | * Example Output:
|
| 79 | *
|
| 80 | * <attachments>
|
| 81 | * <attachment>
|
| 82 | * <id>1</id>
|
| 83 | * <ticketid>1</ticketid>
|
| 84 | * <ticketpostid>1</ticketpostid>
|
| 85 | * <filename>icon_chart.gif</filename>
|
| 86 | * <filesize>541</filesize>
|
| 87 | * <filetype>image/gif</filetype>
|
| 88 | * <dateline>1296645496</dateline>
|
| 89 | * </attachment>
|
| 90 | * </attachments>
|
| 91 | *
|
| 92 | * @author Varun Shoor
|
| 93 | * @param int $_ticketID The Ticket ID
|
| 94 | * @param int $_attachmentID (OPTIONAL) To filter result set to a single attachment id
|
| 95 | * @return bool "true" on Success, "false" otherwise
|
| 96 | * @throws SWIFT_Exception If the Class is not Loaded
|
| 97 | */
|
| 98 | public function ListAll($_ticketID, $_attachmentID = false)
|
| 99 | {
|
| 100 | if (!$this->GetIsClassLoaded())
|
| 101 | {
|
| 102 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
| 103 |
|
| 104 | return false;
|
| 105 | }
|
| 106 |
|
| 107 | $_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);
|
| 108 | if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
|
| 109 | $this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_NOTFOUND, 'Ticket not Found');
|
| 110 |
|
| 111 | return false;
|
| 112 | }
|
| 113 |
|
| 114 | $_querySuffix = '';
|
| 115 | if (!empty($_attachmentID)) {
|
| 116 | $_querySuffix .= " AND attachmentid = '" . intval($_attachmentID) . "'";
|
| 117 | }
|
| 118 |
|
| 119 | $_attachmentContainer = array();
|
| 120 | $this->Database->Query("SELECT * FROM " . TABLE_PREFIX . "attachments WHERE linktype = '" . SWIFT_Attachment::LINKTYPE_TICKETPOST . "' AND ticketid = '" . intval($_ticketID) . "'" . $_querySuffix);
|
| 121 | while ($this->Database->NextRecord()) {
|
| 122 | $_attachmentContainer[$this->Database->Record['attachmentid']] = $this->Database->Record;
|
| 123 | }
|
| 124 |
|
| 125 | $this->XML->AddParentTag('attachments');
|
| 126 | foreach ($_attachmentContainer as $_attachmentID => $_attachment) {
|
| 127 | $this->XML->AddParentTag('attachment');
|
| 128 | $this->XML->AddTag('id', $_attachment['attachmentid']);
|
| 129 | $this->XML->AddTag('ticketid', $_attachment['ticketid']);
|
| 130 | $this->XML->AddTag('ticketpostid', $_attachment['linktypeid']);
|
| 131 | $this->XML->AddTag('filename', $_attachment['filename']);
|
| 132 | $this->XML->AddTag('filesize', $_attachment['filesize']);
|
| 133 | $this->XML->AddTag('filetype', $_attachment['filetype']);
|
| 134 | $this->XML->AddTag('dateline', $_attachment['dateline']);
|
| 135 | $this->XML->EndParentTag('attachment');
|
| 136 | }
|
| 137 | $this->XML->EndParentTag('attachments');
|
| 138 |
|
| 139 | $this->XML->EchoXML();
|
| 140 |
|
| 141 | return true;
|
| 142 | }
|
| 143 |
|
| 144 | /**
|
| 145 | * Retrieve the Attachment
|
| 146 | *
|
| 147 | * Example Output:
|
| 148 | *
|
| 149 | * <attachment>
|
| 150 | * <id>1</id>
|
| 151 | * <ticketid>1</ticketid>
|
| 152 | * <ticketpostid>1</ticketpostid>
|
| 153 | * <filename>icon_chart.gif</filename>
|
| 154 | * <filesize>541</filesize>
|
| 155 | * <filetype>image/gif</filetype>
|
| 156 | * <dateline>1296645496</dateline>
|
| 157 | * <contents><![CDATA[iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK==]]></contents>
|
| 158 | * </attachment>
|
| 159 | *
|
| 160 | *
|
| 161 | * @author Varun Shoor
|
| 162 | * @param int $_ticketID The Ticket ID
|
| 163 | * @param int $_attachmentID The Attachment ID
|
| 164 | * @return bool "true" on Success, "false" otherwise
|
| 165 | * @throws SWIFT_Exception If the Class is not Loaded
|
| 166 | */
|
| 167 | public function Get($_ticketID, $_attachmentID)
|
| 168 | {
|
| 169 | if (!$this->GetIsClassLoaded())
|
| 170 | {
|
| 171 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
| 172 |
|
| 173 | return false;
|
| 174 | }
|
| 175 |
|
| 176 | $_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);
|
| 177 | if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
|
| 178 | $this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_NOTFOUND, 'Ticket not Found');
|
| 179 |
|
| 180 | return false;
|
| 181 | }
|
| 182 |
|
| 183 | $_SWIFT_AttachmentObject = false;
|
| 184 |
|
| 185 | try {
|
| 186 | $_SWIFT_AttachmentObject = new SWIFT_Attachment($_attachmentID);
|
| 187 | } catch (SWIFT_Exception $_SWIFT_ExceptionObject) {
|
| 188 | $this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_NOTFOUND, 'Attachment not Found');
|
| 189 |
|
| 190 | return false;
|
| 191 | }
|
| 192 |
|
| 193 | $this->XML->AddParentTag('attachments');
|
| 194 | $this->XML->AddParentTag('attachment');
|
| 195 |
|
| 196 | $this->XML->AddTag('id', $_SWIFT_AttachmentObject->GetProperty('attachmentid'));
|
| 197 | $this->XML->AddTag('ticketid', $_SWIFT_AttachmentObject->GetProperty('ticketid'));
|
| 198 | $this->XML->AddTag('ticketpostid', $_SWIFT_AttachmentObject->GetProperty('linktypeid'));
|
| 199 | $this->XML->AddTag('filename', $_SWIFT_AttachmentObject->GetProperty('filename'));
|
| 200 | $this->XML->AddTag('filesize', $_SWIFT_AttachmentObject->GetProperty('filesize'));
|
| 201 | $this->XML->AddTag('filetype', $_SWIFT_AttachmentObject->GetProperty('filetype'));
|
| 202 | $this->XML->AddTag('dateline', $_SWIFT_AttachmentObject->GetProperty('dateline'));
|
| 203 |
|
| 204 | $this->XML->AddTag('contents', base64_encode($_SWIFT_AttachmentObject->Get()));
|
| 205 |
|
| 206 | $this->XML->EndParentTag('attachment');
|
| 207 | $this->XML->EndParentTag('attachments');
|
| 208 |
|
| 209 | $this->XML->EchoXML();
|
| 210 |
|
| 211 | return true;
|
| 212 | }
|
| 213 |
|
| 214 | /**
|
| 215 | * Create a new Ticket Attachment
|
| 216 | *
|
| 217 | * Required Fields:
|
| 218 | * ticketid
|
| 219 | * ticketpostid
|
| 220 | *
|
| 221 | * Example Output:
|
| 222 | *
|
| 223 | * <attachments>
|
| 224 | * <attachment>
|
| 225 | * <id>1</id>
|
| 226 | * <ticketid>1</ticketid>
|
| 227 | * <ticketpostid>1</ticketpostid>
|
| 228 | * <filename>icon_chart.gif</filename>
|
| 229 | * <filesize>541</filesize>
|
| 230 | * <filetype>image/gif</filetype>
|
| 231 | * <dateline>1296645496</dateline>
|
| 232 | * </attachment>
|
| 233 | * </attachments>
|
| 234 | *
|
| 235 | * @author Varun Shoor
|
| 236 | * @return bool "true" on Success, "false" otherwise
|
| 237 | * @throws SWIFT_Exception If the Class is not Loaded
|
| 238 | */
|
| 239 | public function Post()
|
| 240 | {
|
| 241 | if (!$this->GetIsClassLoaded())
|
| 242 | {
|
| 243 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
| 244 |
|
| 245 | return false;
|
| 246 | }
|
| 247 |
|
| 248 | $_ticketID = $_ticketPostID = 0;
|
| 249 | if (!isset($_POST['ticketid']) || empty($_POST['ticketid']) || trim($_POST['ticketid']) == '') {
|
| 250 | $this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_BADREQUEST, 'No Ticket ID Specified');
|
| 251 |
|
| 252 | return false;
|
| 253 | } else if (!isset($_POST['ticketpostid']) || empty($_POST['ticketpostid']) || trim($_POST['ticketpostid']) == '') {
|
| 254 | $this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_BADREQUEST, 'No Ticket Post ID Specified');
|
| 255 |
|
| 256 | return false;
|
| 257 | }
|
| 258 |
|
| 259 |
|
| 260 | $_ticketID = $_POST['ticketid'];
|
| 261 | $_ticketPostID = $_POST['ticketpostid'];
|
| 262 |
|
| 263 | $_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);
|
| 264 | if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
|
| 265 | $this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_NOTFOUND, 'Ticket not Found');
|
| 266 |
|
| 267 | return false;
|
| 268 | }
|
| 269 |
|
| 270 | $_SWIFT_TicketPostObject = false;
|
| 271 | try {
|
| 272 | $_SWIFT_TicketPostObject = new SWIFT_TicketPost(new SWIFT_DataID($_ticketPostID));
|
| 273 | } catch (SWIFT_Exception $_SWIFT_ExceptionObject) {
|
| 274 | }
|
| 275 |
|
| 276 | if (!$_SWIFT_TicketPostObject instanceof SWIFT_TicketPost || !$_SWIFT_TicketPostObject->GetIsClassLoaded() || $_SWIFT_TicketPostObject->GetProperty('ticketid') != $_SWIFT_TicketObject->GetTicketID()) {
|
| 277 | $this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_NOTFOUND, 'Ticket Post not found');
|
| 278 |
|
| 279 | return false;
|
| 280 | }
|
| 281 |
|
| 282 | if (!isset($_POST['filename']) || empty($_POST['filename']) || trim($_POST['filename']) == '') {
|
| 283 | $this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_BADREQUEST, 'No file name specified');
|
| 284 |
|
| 285 | return false;
|
| 286 | } else if (!isset($_POST['contents'])) {
|
| 287 | $this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_BADREQUEST, 'No contents specified');
|
| 288 |
|
| 289 | return false;
|
| 290 | }
|
| 291 |
|
| 292 | $_finalContents = base64_decode($_POST['contents']);
|
| 293 |
|
| 294 | /*
|
| 295 | * BUG FIX: Parminder Singh
|
| 296 | *
|
| 297 | * SWIFT-1716: invalid filetype is returned in xml response when attaching a file in a ticket post using Rest API->REST - TicketAttachment->POST /Tickets/TicketAttachment
|
| 298 | *
|
| 299 | */
|
| 300 | $_fileExtension = mb_strtolower(substr($_POST['filename'], (strrpos($_POST['filename'], '.') + 1)));
|
| 301 | $_MIMEListObject = new SWIFT_MIMEList();
|
| 302 | $_mimeDataContainer = $_MIMEListObject->Get($_fileExtension);
|
| 303 | $_contentType = 'application/octet-stream';
|
| 304 | if (isset($_mimeDataContainer[0]) && !empty($_mimeDataContainer[0])) {
|
| 305 | $_contentType = $_mimeDataContainer[0];
|
| 306 | }
|
| 307 |
|
| 308 | $_SWIFT_AttachmentStoreStringObject = new SWIFT_AttachmentStoreString($_POST['filename'], $_contentType, $_finalContents);
|
| 309 |
|
| 310 | unset($_finalContents);
|
| 311 |
|
| 312 | $_SWIFT_AttachmentObject = SWIFT_Attachment::Create(SWIFT_Attachment::LINKTYPE_TICKETPOST, $_ticketPostID, $_SWIFT_AttachmentStoreStringObject, $_ticketID);
|
| 313 | if (!$_SWIFT_AttachmentObject instanceof SWIFT_Attachment || !$_SWIFT_AttachmentObject->GetIsClassLoaded()) {
|
| 314 | $this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_BADREQUEST, 'Attachment Creation Failed');
|
| 315 |
|
| 316 | return false;
|
| 317 | }
|
| 318 |
|
| 319 | SWIFT_Ticket::RecalculateHasAttachmentProperty(array($_ticketID));
|
| 320 |
|
| 321 | $_SWIFT_TicketPostObject->UpdateHasAttachments(1);
|
| 322 |
|
| 323 | $this->ListAll($_ticketID, $_SWIFT_AttachmentObject->GetAttachmentID());
|
| 324 |
|
| 325 | return false;
|
| 326 | }
|
| 327 |
|
| 328 | /**
|
| 329 | * Delete a Ticket Attachment
|
| 330 | *
|
| 331 | * Example Output:
|
| 332 | * No output is sent, if server returns HTTP Code 200, then the deletion was successful
|
| 333 | *
|
| 334 | * @author Varun Shoor
|
| 335 | * @param int $_ticketID The Ticket ID
|
| 336 | * @param int $_attachmentID The Attachment ID
|
| 337 | * @return bool "true" on Success, "false" otherwise
|
| 338 | * @throws SWIFT_Exception If the Class is not Loaded
|
| 339 | */
|
| 340 | public function Delete($_ticketID, $_attachmentID)
|
| 341 | {
|
| 342 | $_SWIFT = SWIFT::GetInstance();
|
| 343 |
|
| 344 | if (!$this->GetIsClassLoaded())
|
| 345 | {
|
| 346 | throw new SWIFT_Exception(SWIFT_CLASSNOTLOADED);
|
| 347 |
|
| 348 | return false;
|
| 349 | }
|
| 350 |
|
| 351 | $_SWIFT_TicketObject = SWIFT_Ticket::GetObjectOnID($_ticketID);
|
| 352 | if (!$_SWIFT_TicketObject instanceof SWIFT_Ticket || !$_SWIFT_TicketObject->GetIsClassLoaded()) {
|
| 353 | $this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_NOTFOUND, 'Ticket not Found');
|
| 354 |
|
| 355 | return false;
|
| 356 | }
|
| 357 |
|
| 358 | $_SWIFT_AttachmentObject = false;
|
| 359 |
|
| 360 | try {
|
| 361 | $_SWIFT_AttachmentObject = new SWIFT_Attachment($_attachmentID);
|
| 362 | } catch (SWIFT_Exception $_SWIFT_ExceptionObject) {
|
| 363 | $this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_NOTFOUND, 'Attachment not Found');
|
| 364 |
|
| 365 | return false;
|
| 366 | }
|
| 367 |
|
| 368 | if ($_SWIFT_AttachmentObject->GetProperty('ticketid') != $_ticketID) {
|
| 369 | $this->RESTServer->DispatchStatus(SWIFT_RESTServer::HTTP_BADREQUEST, 'Attachment does not belong to the specified ticket');
|
| 370 |
|
| 371 | return false;
|
| 372 | }
|
| 373 |
|
| 374 | SWIFT_Attachment::DeleteList(array($_attachmentID));
|
| 375 |
|
| 376 | SWIFT_Ticket::RecalculateHasAttachmentProperty(array($_ticketID));
|
| 377 |
|
| 378 | return true;
|
| 379 | }
|
| 380 | }
|
| 381 | ?> |