public static function check($document) { self::$doc = $document; // Don't do anything if this is a new document or a user document if (!$document->getVersion() || $document->getModule() === 'users') { return; } if (self::fields_removed() >= 4 || self::i18n_fields_removed() >= 3) { self::signal(); } }
/** * Executes edit action. */ public function executeEdit() { // populate objects for form display depending on what we are doing (creating, editing) $this->setEditFormInformation(); // All modules will use the same template $this->setTemplate('../../documents/templates/edit'); $document = $this->document; $module_name = $this->getModuleName(); $this->document_name = $document->get('name'); // Culture (lang) is automatically defined in Hydrate, // redefined in the model. if ($this->getRequest()->getMethod() == sfRequest::POST) { $lang = $this->getRequestParameter('lang'); $user_id = $this->getUser()->getId(); $is_minor = $this->getRequestParameter('rev_is_minor', false); $message = $this->getRequestParameter('rev_comment'); $document->setCulture($lang); $old_lon = $document->get('lon'); $old_lat = $document->get('lat'); $this->setDataFields($document); // upload potential GPX file to server and set WKT field // or upload a new version of an image $request = $this->getRequest(); if ($request->hasFiles()) { c2cTools::log('request has files'); if ($request->getFileName('image_new_version') && $module_name == 'images') { c2cTools::log('new image uploaded'); $base_path = sfConfig::get('sf_upload_dir') . DIRECTORY_SEPARATOR; $temp_dir = $base_path . sfConfig::get('app_images_temp_directory_name'); $upload_dir = $base_path . sfConfig::get('app_images_directory_name'); $filename = $request->getFiles(); $unique_filename = c2cTools::generateUniqueName(); $file_ext = Images::detectExtension($filename['image_new_version']['tmp_name']); // upload file in a temporary folder $new_location = $temp_dir . DIRECTORY_SEPARATOR . $unique_filename . $file_ext; sfLoader::loadHelpers(array('General')); $redir_route = '@document_by_id_lang_slug?module=' . $module_name . '&id=' . $this->document->get('id') . '&lang=' . $this->document->getCulture() . '&slug=' . get_slug($this->document); if (!$request->moveFile('image_new_version', $new_location)) { return $this->setErrorAndRedirect('Failed moving uploaded file', $redir_route); } if ($file_ext == '.svg') { if (!SVG::rasterize($temp_dir . DIRECTORY_SEPARATOR, $unique_filename, $file_ext)) { return $this->setErrorAndRedirect('Failed rasterizing svg file', $redir_route); } $document->set('has_svg', true); } else { $document->set('has_svg', false); } // generate thumbnails (ie. resized images: "BI"/"SI") Images::generateThumbnails($unique_filename, $file_ext, $temp_dir); // move to uploaded images directory if (!Images::moveAll($unique_filename . $file_ext, $temp_dir, $upload_dir)) { return $this->setErrorAndRedirect('image dir unavailable', $redir_route); } // update filename and image properties $document->set('filename', $unique_filename . $file_ext); $size = getimagesize($upload_dir . DIRECTORY_SEPARATOR . $unique_filename . $file_ext); if ($size) { $document->set('width', $size[0]); $document->set('height', $size[1]); } $document->set('file_size', filesize($upload_dir . DIRECTORY_SEPARATOR . $unique_filename . $file_ext)); // populate with new exif data, if any... $document->populateWithExifDataFrom($upload_dir . DIRECTORY_SEPARATOR . $unique_filename . $file_ext); } if ($request->getFileName('gps_data') && in_array($module_name, array('routes', 'outings'))) { // it is necessary to preserve both tests nested. if ($wkt = $this->getWktFromFileUpload($request)) { c2cTools::log('wkt extracted'); $document->set('geom_wkt', $wkt); // NB: these fields exist in both objects for which a file upload is possible (outings, routes) $_a = ParseGeo::getCumulatedHeightDiffFromWkt($wkt); if (!$document->get('height_diff_up')) { $document->set('height_diff_up', $_a['up']); c2cTools::log('height diff up set from wkt : ' . $_a['up']); } if (!$document->get('height_diff_down')) { $document->set('height_diff_down', $_a['down']); c2cTools::log('height diff down set from wkt : ' . $_a['down']); } $message = '[geodata] ' . (!$message ? "Edit with geometry upload" : $message); } else { $this->getRequest()->setError('gps_data', 'invalid gpx file'); return false; } } } if (count($this->document->getModified()) == 0 && count($this->document->getCurrentI18nObject()->getModified()) == 0) { // no change of the document was detected // => redirects to the document without saving anything $this->redirectToView(); return; } // we prevent here concurrent edition : // fake data so that second test always fails on summit creation (and when document is an archive) : $rev_when_edition_begun = 1; $current_rev = 0; // test if id exists (summit update) before checking concurrent edition // and if this is not an archive (editing an old document to reverse wrong changes) // (because only useful for document update) : if (($id = $this->getRequestParameter('id')) && !$this->getRequestParameter('editing_archive')) { $rev_when_edition_begun = $this->getRequestParameter('revision'); $current_rev = $document->getVersion(); } c2cTools::log("Document {$id} in {$lang} : rev when edition begun : {$rev_when_edition_begun} - current rev : {$current_rev}"); if ($rev_when_edition_begun < $current_rev) { c2cTools::log("Document {$id} in {$lang} has been concurrently saved. {$rev_when_edition_begun} < {$current_rev}"); // document has been saved by someone else during edition // we present datas entered in the same form $this->document = $document; // and we launch a preview with the document in its true current state: $this->concurrent_edition = true; // if the current_document variable is available in the edit template, we display the preview of it. } else { $message = !$message ? "Edit in {$lang}" : $message; // if document has a geometry, compute and create associations with ranges, depts, countries. // nb: association is performed upon document creation with initial geometry // OR when the centroid (lon, lat) has moved during an update. $needs_geom_association = isset($wkt) || $document->get('lon') != $old_lon && $document->get('lon') != null || $document->get('lat') != $old_lat && $document->get('lat') != null; // geom centroid has moved $document->doSaveWithMetadata($user_id, $is_minor, $message); $this->success = true; // means that child class can redirect to document view after other operations if needed (eg: associations). $this->document = $document; $id = $document->get('id'); if ($needs_geom_association) { c2cTools::log('executeEdit: needs_geom_association'); // we create new associations : // (and delete old associations before creating the new ones) // (and do not create outings-maps associations) $nb_created = gisQuery::createGeoAssociations($id, true, $module_name != 'outings'); c2cTools::log("created {$nb_created} geo associations"); // if summit or site coordinates have moved (hence $needs_geom_association = true), // refresh geo-associations of associated routes (from summits) and outings (from routes or sites) $this->refreshGeoAssociations($id); } // we clear views, histories, diffs of this doc + filter and list, in every language (content+interface): $this->clearCache($module_name, $id); // we clear views of the associated docs in every language (content+interface): // find all associated docs // 'users' module is excuded because a change of a user page have no visibility in associated docs, then it is not necessary to clear the cache of all associated outings if ($module_name != 'users') { $associated_docs = Association::findAllAssociatedDocs($id, array('id', 'module')); $ids = array(); foreach ($associated_docs as $doc) { $doc_id = $doc['id']; $doc_module = $doc['module']; // clear their view cache $this->clearCache($doc_module, $doc_id, false, 'view'); if ($module_name == 'outings' && in_array($doc_module, array('routes', 'sites')) || $module_name == 'routes' && in_array($doc_module, array('summits', 'parkings'))) { $ids[] = $doc_id; } } if ($module_name == 'outings') { $associated_docs = Association::findAllAssociatedDocs($ids, array('id', 'module'), array('sr', 'hr', 'pr', 'rr', 'pt', 'ht')); $ids = array(); foreach ($associated_docs as $doc) { $doc_id = $doc['id']; $doc_module = $doc['module']; // clear their view cache $this->clearCache($doc_module, $doc_id, false, 'view'); if (in_array($doc_module, array('summits', 'parkings', 'sites'))) { $ids[] = $doc_id; } } if (count($ids)) { $associated_docs = Association::findMainAssociatedDocs($ids, array('id', 'module'), array('ss', 'pp', 'tt')); foreach ($associated_docs as $doc) { // clear their view cache $this->clearCache($doc['module'], $doc['id'], false, 'view'); } } } elseif ($module_name == 'routes') { $associated_docs = Association::findMainAssociatedDocs($ids, array('id', 'module'), array('ss', 'pp')); foreach ($associated_docs as $doc) { // clear their view cache $this->clearCache($doc['module'], $doc['id'], false, 'view'); } } } // saves new document id in a "pseudo id" cookie to retrieve it if user resubmits original form if ($this->new_document && $this->pseudo_id) { $this->getResponse()->setCookie($this->pseudo_id, $id); } } // Go through simple heuristics to check for potential vandalism Vandalism::check($this->document); } else { // We display edit form. Retrieve nb comments $this->nb_comments = $this->new_document ? 0 : PunbbComm::retrieveNbComments($document->get('id') . '_' . $document->getCulture()); } // module specific actions $this->endEdit(); }