/**
  * Insert a file into a folder by it's local path.
  *
  * @param string           $localFilePath    The local file path of the file to insert.
  * @param AssetFolderModel $folder           The assetFolderModel where the file should be uploaded to.
  * @param string           $filename         The name of the file to insert.
  * @param bool             $preventConflicts If set to true, will ensure that a conflict is not encountered by
  *                                           checking the file name prior insertion.
  *
  * @return AssetOperationResponseModel
  */
 public function insertFileByPath($localFilePath, AssetFolderModel $folder, $filename, $preventConflicts = false)
 {
     // Fire an 'onBeforeUploadAsset' event
     $event = new Event($this, array('path' => $localFilePath, 'folder' => $folder, 'filename' => $filename));
     craft()->assets->onBeforeUploadAsset($event);
     if ($event->performAction) {
         // We hate Javascript and PHP in our image files.
         if (IOHelper::getFileKind(IOHelper::getExtension($localFilePath)) == 'image' && ImageHelper::isImageManipulatable(IOHelper::getExtension($localFilePath)) && IOHelper::getExtension($localFilePath) != 'svg') {
             craft()->images->cleanImage($localFilePath);
         }
         $mobileUpload = false;
         if (IOHelper::getFileName($filename, false) == "image" && craft()->request->isMobileBrowser(true)) {
             $mobileUpload = true;
             $date = DateTimeHelper::currentUTCDateTime();
             $filename = "image_" . $date->format('Ymd_His') . "." . IOHelper::getExtension($filename);
         }
         if ($preventConflicts) {
             $newFileName = $this->getNameReplacementInFolder($folder, $filename);
             $response = $this->insertFileInFolder($folder, $localFilePath, $newFileName);
         } else {
             $response = $this->insertFileInFolder($folder, $localFilePath, $filename);
             // Naming conflict. create a new file and ask the user what to do with it
             if ($response->isConflict()) {
                 $newFileName = $this->getNameReplacementInFolder($folder, $filename);
                 $conflictResponse = $response;
                 $response = $this->insertFileInFolder($folder, $localFilePath, $newFileName);
             }
         }
         if ($response->isSuccess()) {
             $fileModel = new AssetFileModel();
             $title = $fileModel->generateAttributeLabel(IOHelper::getFileName($filename, false));
             // If there were double spaces, it's because the filename had a space followed by a
             // capital letter. We convert the space to a dash, but Yii thinks it's a new "word"
             // and adds another space.
             $fileModel->getContent()->title = str_replace('  ', ' ', $title);
             $filename = IOHelper::getFileName($response->getDataItem('filePath'));
             $fileModel->filename = IOHelper::getFileName($filename);
             $fileModel->sourceId = $this->model->id;
             $fileModel->folderId = $folder->id;
             $fileModel->kind = IOHelper::getFileKind(IOHelper::getExtension($filename));
             $fileModel->size = filesize($localFilePath);
             $fileModel->dateModified = IOHelper::getLastTimeModified($localFilePath);
             if ($fileModel->kind == 'image') {
                 list($width, $height) = ImageHelper::getImageSize($localFilePath);
                 $fileModel->width = $width;
                 $fileModel->height = $height;
             }
             if ($mobileUpload) {
                 $fileModel->getContent()->title = Craft::t('Mobile Upload');
             }
             craft()->assets->storeFile($fileModel);
             if (!$this->isSourceLocal() && $fileModel->kind == 'image') {
                 craft()->assetTransforms->storeLocalSource($localFilePath, craft()->path->getAssetsImageSourcePath() . $fileModel->id . '.' . IOHelper::getExtension($fileModel->filename));
             }
             // Check if we stored a conflict response originally - send that back then.
             if (isset($conflictResponse)) {
                 $response = $conflictResponse;
             }
             $response->setDataItem('fileId', $fileModel->id);
         }
     } else {
         $response = new AssetOperationResponseModel();
         $response->setError(Craft::t('The file upload was cancelled.'));
     }
     return $response;
 }
 /**
  * Saves the record for an asset.
  *
  * @param AssetFileModel $file
  *
  * @throws \Exception
  * @return bool
  */
 public function storeFile(AssetFileModel $file)
 {
     $isNewFile = !$file->id;
     if (!$isNewFile) {
         $fileRecord = AssetFileRecord::model()->findById($file->id);
         if (!$fileRecord) {
             throw new Exception(Craft::t("No asset exists with the ID “{id}”.", array('id' => $file->id)));
         }
     } else {
         $fileRecord = new AssetFileRecord();
     }
     $fileRecord->sourceId = $file->sourceId;
     $fileRecord->folderId = $file->folderId;
     $fileRecord->filename = $file->filename;
     $fileRecord->kind = $file->kind;
     $fileRecord->size = $file->size;
     $fileRecord->width = $file->width;
     $fileRecord->height = $file->height;
     $fileRecord->dateModified = $file->dateModified;
     $fileRecord->validate();
     $file->addErrors($fileRecord->getErrors());
     if ($file->hasErrors()) {
         return false;
     }
     if ($isNewFile && !$file->getContent()->title) {
         // Give it a default title based on the file name
         $file->getContent()->title = $file->generateAttributeLabel(IOHelper::getFileName($file->filename, false));
     }
     $transaction = craft()->db->getCurrentTransaction() === null ? craft()->db->beginTransaction() : null;
     try {
         // Fire an 'onBeforeSaveAsset' event
         $event = new Event($this, array('asset' => $file, 'isNewAsset' => $isNewFile));
         $this->onBeforeSaveAsset($event);
         // Is the event giving us the go-ahead?
         if ($event->performAction) {
             // Save the element
             $success = craft()->elements->saveElement($file, false);
             // If it didn't work, rollback the transaction in case something changed in onBeforeSaveAsset
             if (!$success) {
                 if ($transaction !== null) {
                     $transaction->rollback();
                 }
                 return false;
             }
             // Now that we have an element ID, save it on the other stuff
             if ($isNewFile) {
                 $fileRecord->id = $file->id;
             }
             // Save the file row
             $fileRecord->save(false);
         } else {
             $success = false;
         }
         // Commit the transaction regardless of whether we saved the asset, in case something changed
         // in onBeforeSaveAsset
         if ($transaction !== null) {
             $transaction->commit();
         }
     } catch (\Exception $e) {
         if ($transaction !== null) {
             $transaction->rollback();
         }
         throw $e;
     }
     if ($success) {
         // Fire an 'onSaveAsset' event
         $this->onSaveAsset(new Event($this, array('asset' => $file, 'isNewAsset' => $isNewFile)));
         if ($this->hasEventHandler('onSaveFileContent')) {
             // Fire an 'onSaveFileContent' event (deprecated)
             $this->onSaveFileContent(new Event($this, array('file' => $file)));
         }
     }
     return $success;
 }