/** * DOCUMENT ME */ public function go() { $dir_iterator = new RecursiveDirectoryIterator($this->dir); $iterator = new RecursiveIteratorIterator($dir_iterator, RecursiveIteratorIterator::SELF_FIRST); $count = 0; $mimeTypes = aMediaTools::getOption('mime_types'); // It comes back as a mapping of extensions to types, get the types $extensions = array_keys($mimeTypes); $mimeTypes = array_values($mimeTypes); foreach ($iterator as $sfile) { if ($sfile->isFile()) { $file = $sfile->getPathname(); if (preg_match('/(^|\\/)\\./', $file)) { # Silently ignore all dot folders to avoid trouble with svn and friends $this->giveFeedback("info", "Ignoring dotfile", $file); continue; } $pathinfo = pathinfo($file); // basename and filename seem backwards to me, but that's how it is in the PHP docs and // sure enough that's how it behaves if ($pathinfo['basename'] === 'Thumbs.db') { continue; } $vfp = new aValidatorFilePersistent(array('mime_types' => $mimeTypes, 'validated_file_class' => 'aValidatedFile', 'required' => false), array('mime_types' => 'The following file types are accepted: ' . implode(', ', $extensions))); $guid = aGuid::generate(); try { $vf = $vfp->clean(array('newfile' => array('tmp_name' => $file, 'name' => $pathinfo['basename']), 'persistid' => $guid)); } catch (Exception $e) { $this->giveFeedback("warning", "Not supported or corrupt", $file); continue; } $item = new aMediaItem(); // Split it up to make tags out of the portion of the path that isn't dir (i.e. the folder structure they used) $dir = $this->dir; $dir = preg_replace('/\\/$/', '', $dir) . '/'; $relevant = preg_replace('/^' . preg_quote($dir, '/') . '/', '', $file); // TODO: not Microsoft-friendly, might matter in some setting $components = preg_split('/\\//', $relevant); $tags = array_slice($components, 0, count($components) - 1); foreach ($tags as &$tag) { // We don't strictly need to be this harsh, but it's safe and definitely // takes care of some things we definitely can't allow, like periods // (which cause mod_rewrite problems with pretty Symfony URLs). // TODO: clean it up in a nicer way without being UTF8-clueless // (aTools::slugify is UTF8-safe) $tag = aTools::slugify($tag); } $item->title = aMediaTools::filenameToTitle($pathinfo['basename']); $item->setTags($tags); if (!strlen($item->title)) { $this->giveFeedback("error", "Files must have a basename", $file); continue; } // The preSaveImage / save / saveImage dance is necessary because // the sluggable behavior doesn't kick in until save and the image file // needs a slug based filename. if (!$item->preSaveFile($vf)) { $this->giveFeedback("error", "Save failed", $file); continue; } $item->save(); if (!$item->saveFile($vf)) { $this->giveFeedback("error", "Save failed", $file); $item->delete(); continue; } unlink($file); $count++; $this->giveFeedback("completed", $count, $file); } } $this->giveFeedback("total", $count); }
/** * DOCUMENT ME * @param sfWebRequest $request */ public function executeUpload(sfWebRequest $request) { // Belongs at the beginning, not the end $this->forward404Unless(aMediaTools::userHasUploadPrivilege()); $this->embedAllowed = aMediaTools::getEmbedAllowed(); $this->uploadAllowed = aMediaTools::getUploadAllowed(); // This has been simplified. We no longer do real validation in the first pass, // we just make sure there is at least one file. Then the validation of the annotation // pass can take over to minimize duplicate code $this->form = new aMediaUploadMultipleForm(); $this->mustUploadSomething = false; $this->postMaxSizeExceeded = false; if (isset($_FILES['a_media_items']['error']['item-0']['file']['newfile']) && $_FILES['a_media_items']['error']['item-0']['file']['newfile']) { // upload_max_size exceeded $this->getUser()->setFlash('aMedia.postMaxSizeExceeded', true); $this->postMaxSizeExceeded = true; } // An empty POST is an anomaly indicating that we hit the php.ini max_post_size or similar if ($request->isMethod('post') && !count($request->getPostParameters())) { $this->getUser()->setFlash('aMedia.postMaxSizeExceeded', true); $this->postMaxSizeExceeded = true; } if (!$this->postMaxSizeExceeded && $request->isMethod('post')) { $count = 0; $request->setParameter('first_pass', true); // Saving embedded forms is weird. We can get the form objects // via getEmbeddedForms(), but those objects were never really // bound, so getValue will fail on them. We have to look at the // values array of the parent form instead. The widgets and // validators of the embedded forms are rolled into it. // See: // http://thatsquality.com/articles/can-the-symfony-forms-framework-be-domesticated-a-simple-todo-list $items = $request->getParameter("a_media_items"); $files = $request->getFiles("a_media_items"); for ($i = 0; $i < aMediaTools::getOption('batch_max'); $i++) { $values = $this->form->getValues(); // This is how we check for the presence of a file upload without a full form validation $good = false; if (isset($files["item-{$i}"]['file'])) { $file = $files["item-{$i}"]['file']; if (isset($file['newfile']['tmp_name']) && strlen($file['newfile']['tmp_name'])) { // Humanize the original filename $title = aMediaTools::filenameToTitle($file['newfile']['name']); $items["item-{$i}"]['title'] = $title; $count++; $good = true; } } if (!$good) { // So the editImagesForm validator won't complain about these unset($items["item-{$i}"]); } } $request->setParameter("a_media_items", $items); if ($count) { // We're not doing stupid iframe tricks anymore, so we can just forward $this->forward('aMedia', 'editMultiple'); } else { $this->getUser()->setFlash('aMedia.mustUploadSomething', true); $this->mustUploadSomething = true; } } // For errors we set some flash attributes and return to the index page // We use forward() because resume redirects - if we redirect twice // we'll lose the flash attributes telling us about the errors $this->forward('aMedia', 'resume'); }