public function init() { craft()->on('assets.onSaveAsset', function (Event $event) { $asset = $event->params['asset']; if (craft()->imageResizer->getSettings()->enabled) { // Only process if it's a new asset being saved. if ($event->params['isNewAsset']) { // Is this a manipulatable image? if (ImageHelper::isImageManipulatable(IOHelper::getExtension($asset->filename))) { craft()->imageResizer->resize($asset); } } } }); }
/** * Upload a logo for the admin panel. * * @return null */ public function actionUploadSiteImage() { $this->requireAjaxRequest(); $this->requireAdmin(); $type = craft()->request->getRequiredPost('type'); if (!in_array($type, $this->_allowedTypes)) { $this->returnErrorJson(Craft::t('That is not an accepted site image type.')); } // Upload the file and drop it in the temporary folder $file = UploadedFile::getInstanceByName('image-upload'); try { // Make sure a file was uploaded if ($file) { $fileName = AssetsHelper::cleanAssetName($file->getName()); if (!ImageHelper::isImageManipulatable($file->getExtensionName())) { throw new Exception(Craft::t('The uploaded file is not an image.')); } $folderPath = craft()->path->getTempUploadsPath(); IOHelper::ensureFolderExists($folderPath); IOHelper::clearFolder($folderPath, true); move_uploaded_file($file->getTempName(), $folderPath . $fileName); // Test if we will be able to perform image actions on this image if (!craft()->images->checkMemoryForImage($folderPath . $fileName)) { IOHelper::deleteFile($folderPath . $fileName); $this->returnErrorJson(Craft::t('The uploaded image is too large')); } list($width, $height) = ImageHelper::getImageSize($folderPath . $fileName); if (IOHelper::getExtension($fileName) != 'svg') { craft()->images->cleanImage($folderPath . $fileName); } else { craft()->images->loadImage($folderPath . $fileName)->saveAs($folderPath . $fileName); } $constraint = 500; // If the file is in the format badscript.php.gif perhaps. if ($width && $height) { // Never scale up the images, so make the scaling factor always <= 1 $factor = min($constraint / $width, $constraint / $height, 1); $html = craft()->templates->render('_components/tools/cropper_modal', array('imageUrl' => UrlHelper::getResourceUrl('tempuploads/' . $fileName), 'width' => round($width * $factor), 'height' => round($height * $factor), 'factor' => $factor, 'constraint' => $constraint, 'fileName' => $fileName)); $this->returnJson(array('html' => $html)); } } } catch (Exception $exception) { $this->returnErrorJson($exception->getMessage()); } $this->returnErrorJson(Craft::t('There was an error uploading your photo')); }
/** * 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) { // We hate Javascript and PHP in our image files. if (IOHelper::getFileKind(IOHelper::getExtension($localFilePath)) == 'image' && ImageHelper::isImageManipulatable(IOHelper::getExtension($localFilePath))) { craft()->images->cleanImage($localFilePath); } if ($preventConflicts) { $newFileName = $this->getNameReplacement($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->getNameReplacement($folder, $fileName); $conflictResponse = $response; $response = $this->insertFileInFolder($folder, $localFilePath, $newFileName); } } if ($response->isSuccess()) { $filename = IOHelper::getFileName($response->getDataItem('filePath')); $fileModel = new AssetFileModel(); $fileModel->sourceId = $this->model->id; $fileModel->folderId = $folder->id; $fileModel->filename = IOHelper::getFileName($filename); $fileModel->kind = IOHelper::getFileKind(IOHelper::getExtension($filename)); $fileModel->size = filesize($localFilePath); $fileModel->dateModified = IOHelper::getLastTimeModified($localFilePath); if ($fileModel->kind == 'image') { list($width, $height) = getimagesize($localFilePath); $fileModel->width = $width; $fileModel->height = $height; } 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); } return $response; }
/** * Get image width. * * @param string|null $transform The optional transform handle for which to get thumbnail. * * @return bool|float|mixed */ public function getWidth($transform = null) { if ($transform && !ImageHelper::isImageManipulatable($this->getExtension())) { return $this->_getDimension('width', null); } return $this->_getDimension('width', $transform); }
/** * Create a transform for the file by the transform index. * * @param AssetFileModel $file * @param AssetTransformIndexModel $index * * @throws Exception if the AssetTransformIndexModel cannot be determined to have a transform * @return null */ private function _createTransformForFile(AssetFileModel $file, AssetTransformIndexModel $index) { if (!ImageHelper::isImageManipulatable(IOHelper::getExtension($file->filename))) { return; } if (empty($index->transform)) { $transform = $this->normalizeTransform(mb_substr($index->location, 1)); if (empty($transform)) { throw new Exception(Craft::t("Unable to recognize the transform for this transform index!")); } } else { $transform = $index->transform; } if (!isset($index->detectedFormat)) { $index->detectedFormat = !empty($index->format) ? $index->format : $this->detectAutoTransformFormat($file); } $sourceType = craft()->assetSources->populateSourceType($file->getSource()); $imageSource = $file->getTransformSource(); $quality = $transform->quality ? $transform->quality : craft()->config->get('defaultImageQuality'); $image = craft()->images->loadImage($imageSource, $transform->width, $transform->height); $image->setQuality($quality); switch ($transform->mode) { case 'fit': $image->scaleToFit($transform->width, $transform->height); break; case 'stretch': $image->resize($transform->width, $transform->height); break; default: $image->scaleAndCrop($transform->width, $transform->height, true, $transform->position); break; } $createdTransform = AssetsHelper::getTempFilePath($index->detectedFormat); $image->saveAs($createdTransform); clearstatcache(true, $createdTransform); $sourceType->putImageTransform($file, $index, $createdTransform); IOHelper::deleteFile($createdTransform); if (craft()->assetSources->populateSourceType($file->getSource())->isRemote()) { $this->queueSourceForDeletingIfNecessary($imageSource); } return; }
/** * Get URL for a file. * * @param AssetFileModel $file * @param string $transform * * @return string */ public function getUrlForFile(AssetFileModel $file, $transform = null) { if (!$transform || !ImageHelper::isImageManipulatable(IOHelper::getExtension($file->filename))) { $sourceType = craft()->assetSources->getSourceTypeById($file->sourceId); return AssetsHelper::generateUrl($sourceType, $file); } // Get the transform index model $index = craft()->assetTransforms->getTransformIndex($file, $transform); // Does the file actually exist? if ($index->fileExists) { return craft()->assetTransforms->getUrlForTransformByTransformIndex($index); } else { if (craft()->config->get('generateTransformsBeforePageLoad')) { // Mark the transform as in progress $index->inProgress = true; craft()->assetTransforms->storeTransformIndexData($index); // Generate the transform craft()->assetTransforms->generateTransform($index); // Update the index $index->fileExists = true; craft()->assetTransforms->storeTransformIndexData($index); // Return the transform URL return craft()->assetTransforms->getUrlForTransformByTransformIndex($index); } else { // Queue up a new Generate Pending Transforms task, if there isn't one already if (!craft()->tasks->areTasksPending('GeneratePendingTransforms')) { craft()->tasks->createTask('GeneratePendingTransforms'); } // Return the temporary transform URL return UrlHelper::getResourceUrl('transforms/' . $index->id); } } }
/** * 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; }
/** * Upload a user photo. * * @return null */ public function actionUploadUserPhoto() { $this->requireAjaxRequest(); craft()->userSession->requireLogin(); $userId = craft()->request->getRequiredPost('userId'); if ($userId != craft()->userSession->getUser()->id) { craft()->userSession->requirePermission('editUsers'); } // Upload the file and drop it in the temporary folder $file = UploadedFile::getInstanceByName('image-upload'); try { // Make sure a file was uploaded if ($file) { $fileName = AssetsHelper::cleanAssetName($file->getName()); if (!ImageHelper::isImageManipulatable($file->getExtensionName())) { throw new Exception(Craft::t('The uploaded file is not an image.')); } $user = craft()->users->getUserById($userId); $userName = AssetsHelper::cleanAssetName($user->username, false); $folderPath = craft()->path->getTempUploadsPath() . 'userphotos/' . $userName . '/'; IOHelper::clearFolder($folderPath); IOHelper::ensureFolderExists($folderPath); move_uploaded_file($file->getTempName(), $folderPath . $fileName); // Test if we will be able to perform image actions on this image if (!craft()->images->checkMemoryForImage($folderPath . $fileName)) { IOHelper::deleteFile($folderPath . $fileName); $this->returnErrorJson(Craft::t('The uploaded image is too large')); } craft()->images->loadImage($folderPath . $fileName)->scaleToFit(500, 500, false)->saveAs($folderPath . $fileName); list($width, $height) = ImageHelper::getImageSize($folderPath . $fileName); // If the file is in the format badscript.php.gif perhaps. if ($width && $height) { $html = craft()->templates->render('_components/tools/cropper_modal', array('imageUrl' => UrlHelper::getResourceUrl('userphotos/temp/' . $userName . '/' . $fileName), 'width' => $width, 'height' => $height, 'fileName' => $fileName)); $this->returnJson(array('html' => $html)); } } } catch (Exception $exception) { $this->returnErrorJson($exception->getMessage()); } $this->returnErrorJson(Craft::t('There was an error uploading your photo.')); }
/** * Provides an endpoint for saving a user account. * * This action accounts for the following scenarios: * * - An admin registering a new user account. * - An admin editing an existing user account. * - A normal user with user-administration permissions registering a new user account. * - A normal user with user-administration permissions editing an existing user account. * - A guest registering a new user account ("public registration"). * * This action behaves the same regardless of whether it was requested from the Control Panel or the front-end site. * * @throws HttpException|Exception * @return null */ public function actionSaveUser() { $this->requirePostRequest(); $currentUser = craft()->userSession->getUser(); $requireEmailVerification = craft()->systemSettings->getSetting('users', 'requireEmailVerification'); // Get the user being edited // --------------------------------------------------------------------- $userId = craft()->request->getPost('userId'); $isNewUser = !$userId; $thisIsPublicRegistration = false; // Are we editing an existing user? if ($userId) { $user = craft()->users->getUserById($userId); if (!$user) { throw new Exception(Craft::t('No user exists with the ID “{id}”.', array('id' => $userId))); } if (!$user->isCurrent()) { // Make sure they have permission to edit other users craft()->userSession->requirePermission('editUsers'); } } else { if (craft()->getEdition() == Craft::Client) { // Make sure they're logged in craft()->userSession->requireAdmin(); // Make sure there's no Client user yet if (craft()->users->getClient()) { throw new Exception(Craft::t('A client account already exists.')); } $user = new UserModel(); $user->client = true; } else { // Make sure this is Craft Pro, since that's required for having multiple user accounts craft()->requireEdition(Craft::Pro); // Is someone logged in? if ($currentUser) { // Make sure they have permission to register users craft()->userSession->requirePermission('registerUsers'); } else { // Make sure public registration is allowed if (!craft()->systemSettings->getSetting('users', 'allowPublicRegistration')) { throw new HttpException(403); } $thisIsPublicRegistration = true; } $user = new UserModel(); } } $isCurrentUser = $user->isCurrent(); if ($isCurrentUser) { // Remember the old username in case it changes $oldUsername = $user->username; } // Handle secure properties (email and password) // --------------------------------------------------------------------- $verifyNewEmail = false; // Are they allowed to set the email address? if ($isNewUser || $isCurrentUser || $currentUser->can('changeUserEmails')) { $newEmail = craft()->request->getPost('email'); // Did it just change? if ($newEmail && $newEmail == $user->email) { $newEmail = null; } if ($newEmail) { // Does that email need to be verified? if ($requireEmailVerification && (!$currentUser || !$currentUser->admin || craft()->request->getPost('sendVerificationEmail'))) { // Save it as an unverified email for now $user->unverifiedEmail = $newEmail; $verifyNewEmail = true; // If this is a new user, set it as their main email address too if ($isNewUser) { $user->email = $newEmail; } } else { // We trust them $user->email = $newEmail; } } } // Are they allowed to set a new password? if ($thisIsPublicRegistration) { $user->newPassword = craft()->request->getPost('password', ''); } else { if ($isCurrentUser) { // If there was a newPassword input but it was empty, pretend it didn't exist $user->newPassword = craft()->request->getPost('newPassword') ?: null; } } // If editing an existing user and either of these properties are being changed, // require the user's current password for additional security if (!$isNewUser && (!empty($newEmail) || $user->newPassword)) { if (!$this->_verifyExistingPassword()) { Craft::log('Tried to change the email or password for userId: ' . $user->id . ', but the current password does not match what the user supplied.', LogLevel::Warning); $user->addError('currentPassword', Craft::t('Incorrect current password.')); } } // Handle the rest of the user properties // --------------------------------------------------------------------- // Is the site set to use email addresses as usernames? if (craft()->config->get('useEmailAsUsername')) { $user->username = $user->email; } else { $user->username = craft()->request->getPost('username', $user->username ? $user->username : $user->email); } $user->firstName = craft()->request->getPost('firstName', $user->firstName); $user->lastName = craft()->request->getPost('lastName', $user->lastName); $user->preferredLocale = craft()->request->getPost('preferredLocale', $user->preferredLocale); $user->weekStartDay = craft()->request->getPost('weekStartDay', $user->weekStartDay); // If email verification is required, then new users will be saved in a pending state, // even if an admin is doing this and opted to not send the verification email if ($isNewUser && $requireEmailVerification) { $user->pending = true; } // There are some things only admins can change if ($currentUser && $currentUser->admin) { $user->passwordResetRequired = (bool) craft()->request->getPost('passwordResetRequired', $user->passwordResetRequired); $user->admin = (bool) craft()->request->getPost('admin', $user->admin); } // If this is Craft Pro, grab any profile content from post if (craft()->getEdition() == Craft::Pro) { $user->setContentFromPost('fields'); } // Validate and save! // --------------------------------------------------------------------- $imageValidates = true; $userPhoto = UploadedFile::getInstanceByName('userPhoto'); if ($userPhoto && !ImageHelper::isImageManipulatable($userPhoto->getExtensionName())) { $imageValidates = false; $user->addError('userPhoto', Craft::t("The user photo provided is not an image.")); } if ($imageValidates && craft()->users->saveUser($user)) { // Is this the current user, and did their username just change? if ($isCurrentUser && $user->username !== $oldUsername) { // Update the username cookie craft()->userSession->processUsernameCookie($user->username); } // Save the user's photo, if it was submitted $this->_processUserPhoto($user); // If this is public registration, assign the user to the default user group if ($thisIsPublicRegistration) { // Assign them to the default user group craft()->userGroups->assignUserToDefaultGroup($user); } else { // Assign user groups and permissions if the current user is allowed to do that $this->_processUserGroupsPermissions($user); } // Do we need to send a verification email out? if ($verifyNewEmail) { // Temporarily set the unverified email on the UserModel so the verification email goes to the // right place $originalEmail = $user->email; $user->email = $user->unverifiedEmail; try { if ($isNewUser) { // Send the activation email craft()->users->sendActivationEmail($user); } else { // Send the standard verification email craft()->users->sendNewEmailVerifyEmail($user); } } catch (\phpmailerException $e) { craft()->userSession->setError(Craft::t('User saved, but couldn’t send verification email. Check your email settings.')); } // Put the original email back into place $user->email = $originalEmail; } if (isset($_POST['redirect']) && mb_strpos($_POST['redirect'], '{userId}') !== false) { craft()->deprecator->log('UsersController::saveUser():userId_redirect', 'The {userId} token within the ‘redirect’ param on users/saveUser requests has been deprecated. Use {id} instead.'); $_POST['redirect'] = str_replace('{userId}', '{id}', $_POST['redirect']); } // Is this public registration, and was the user going to be activated automatically? $publicActivation = $thisIsPublicRegistration && $user->status == UserStatus::Active; if ($publicActivation) { // Maybe automatically log them in $this->_maybeLoginUserAfterAccountActivation($user); } if (craft()->request->isAjaxRequest()) { $return['success'] = true; $return['id'] = $user->id; $this->returnJson($return); } else { craft()->userSession->setNotice(Craft::t('User saved.')); // Is this public registration, and is the user going to be activated automatically? if ($publicActivation) { $this->_redirectUserAfterAccountActivation($user); } else { $this->redirectToPostedUrl($user); } } } else { if (craft()->request->isAjaxRequest()) { $this->returnJson(array('errors' => $user->getErrors())); } else { craft()->userSession->setError(Craft::t('Couldn’t save user.')); // Send the account back to the template craft()->urlManager->setRouteVariables(array('account' => $user)); } } }
/** * Generate a local path for the external url based on the source location and the specified options * * @return string */ private function generateLocalFilePath($prepareDir = true) { $generatedPath = $this->localExternalImagePath; $parts = parse_url($this->url); $generatedPath .= $parts['host'] . DIRECTORY_SEPARATOR; $pathParts = explode('/', $parts['path']); $numPathParts = count($pathParts); $extension = substr(strrchr($pathParts[$numPathParts - 1], "."), 1); if (!ImageHelper::isImageManipulatable($extension)) { return false; } for ($i = 0; $i < $numPathParts - 1; $i++) { if (trim($pathParts[$i]) != '') { $generatedPath .= $pathParts[$i] . DIRECTORY_SEPARATOR; } } $generatedPath .= $this->getOptionsDir() . DIRECTORY_SEPARATOR; if ($prepareDir) { $this->prepareDir($generatedPath); } return $generatedPath . $pathParts[$numPathParts - 1]; }
public function init() { craft()->on('assets.onBeforeUploadAsset', function (Event $event) { $path = $event->params['path']; $folder = $event->params['folder']; $filename = $event->params['filename']; // User for overrides on element action $width = null; $height = null; // If we've triggered this from our cropping action, don't resize too if (craft()->httpSession->get('ImageResizer_CropElementAction')) { craft()->httpSession->remove('ImageResizer_CropElementAction'); return true; } // If this has been trigged from the element actions, bypass everything below if (!craft()->httpSession->get('ImageResizer_ResizeElementAction')) { // We can have settings globally, or per asset source. Check! $sourceEnabled = craft()->imageResizer->getSettingForAssetSource($folder->source->id, 'enabled'); // Should we be modifying images in this source? if (!$sourceEnabled) { return true; } } else { // If we are from a element action - delete this so it doesn't persist craft()->httpSession->remove('ImageResizer_ResizeElementAction'); // We also might ne overriding width/height $width = craft()->httpSession->get('ImageResizer_ResizeElementActionWidth'); $height = craft()->httpSession->get('ImageResizer_ResizeElementActionHeight'); craft()->httpSession->remove('ImageResizer_ResizeElementActionWidth'); craft()->httpSession->remove('ImageResizer_ResizeElementActionHeight'); } // Is this a manipulatable image? if (ImageHelper::isImageManipulatable(IOHelper::getExtension($filename))) { craft()->imageResizer_resize->resize($folder->source->id, $path, $width, $height); } }); }