Example #1
0
 /**
  * Copy an object
  *
  * @param mixed &$source     MgdSchema object for reading the parameters
  * @param mixed &$parent      MgdSchema parent object
  * @param array $defaults
  * @return boolean Indicating success
  */
 public function copy_object(&$source, &$parent = null, $defaults = array())
 {
     // Resolve the source object
     self::resolve_object($source);
     // Duplicate the object
     $class_name = get_class($source);
     $target = new $class_name();
     $properties = $this->get_object_properties($source);
     // Copy the object properties
     foreach ($properties as $property) {
         // Skip certain fields
         if (preg_match('/^(_|metadata|guid|id)/', $property)) {
             continue;
         }
         $target->{$property} = $source->{$property};
     }
     // Override requested root object properties
     if (isset($this->target->guid) && $target->guid === $this->target->guid) {
         foreach ($this->root_object_values as $name => $value) {
             $target->{$name} = $value;
         }
     }
     // Override with defaults
     if ($defaults) {
         foreach ($defaults as $name => $value) {
             $target->{$name} = $value;
         }
     }
     $parent_property = $this->get_parent_property($source);
     // Copy the link to parent
     if ($parent) {
         self::resolve_object($parent);
         if (!$parent || !$parent->guid) {
             return false;
         }
         // @TODO: Is there a sure way to determine if the parent is
         // GUID or is it ID? If so, please change it here.
         if (is_string($source->{$parent_property})) {
             $parent_key = 'guid';
         } else {
             $parent_key = 'id';
         }
         $target->{$parent_property} = $parent->{$parent_key};
     } else {
         if (is_string($source->{$parent_property})) {
             $target->{$parent_property} = '';
         } else {
             $target->{$parent_property} = 0;
         }
     }
     $name_property = midcom_helper_reflector::get_name_property($target);
     $resolver = new midcom_helper_reflector_nameresolver($target);
     if (!empty($name_property) && !$resolver->name_is_safe_or_empty($name_property)) {
         debug_add('Source object ' . get_class($source) . " {$source->guid} has unsafe name, rewriting to safe form for the target", MIDCOM_LOG_WARN);
         $name_property = midcom_helper_reflector::get_name_property($target);
         if (empty($name_property)) {
             $this->errors[] = sprintf($this->_l10n->get('cannot fix unsafe name for source object %s, skipping'), get_class($source) . " {$source->guid}");
             return false;
         }
         $name_parts = explode('.', $target->{$name_property}, 2);
         if (isset($name_parts[1])) {
             $target->{$name_property} = midcom_helper_misc::generate_urlname_from_string($name_parts[0]) . ".{$name_parts[1]}";
             // Doublecheck safety and fall back if needed
             if (!$resolver->name_is_safe_or_empty()) {
                 $target->{$name_property} = midcom_helper_misc::generate_urlname_from_string($target->{$name_property});
             }
         } else {
             $target->{$name_property} = midcom_helper_misc::generate_urlname_from_string($target->{$name_property});
         }
         unset($name_parts, $name_property);
     }
     if ($this->allow_name_catenate && $name_property) {
         $name = $resolver->generate_unique_name();
         if ($name !== $target->{$name_property}) {
             $target->{$name_property} = $name;
         }
     }
     // This needs to be here, otherwise it will be overridden
     $target->allow_name_catenate = true;
     if (!$target->create()) {
         $this->errors[] = $this->_l10n->get('failed to create object: ' . mgd_errstr());
         return false;
     }
     // Store for later use - if ever needed
     $this->new_objects[] = $target;
     unset($name_property);
     // Copy parameters
     if (!$this->copy_parameters($source, $target) && $this->halt_on_errors) {
         $this->errors[] = $this->_l10n->get('failed to copy parameters');
         return false;
     }
     // Copy metadata
     if (!$this->copy_metadata($source, $target) && $this->halt_on_errors) {
         $this->errors[] = $this->_l10n->get('failed to copy metadata');
         return false;
     }
     // Copy attachments
     if (!$this->copy_attachments($source, $target) && $this->halt_on_errors) {
         $this->errors[] = $this->_l10n->get('failed to copy attachments');
         return false;
     }
     // Copy privileges
     if (!$this->copy_privileges($source, $target) && $this->halt_on_errors) {
         $this->errors[] = $this->_l10n->get('failed to copy privileges');
         return false;
     }
     return $target;
 }
Example #2
0
 /**
  * DM2 creation callback, binds to the current content topic.
  */
 private function _create_article($title)
 {
     $this->_article = new midcom_db_article();
     $author = $this->_find_email_person($this->_request_data['from']);
     if (!$author) {
         debug_add("Author '{$this->_request_data['from']}' not found", MIDCOM_LOG_WARN);
         if ($this->_config->get('api_email_abort_authornotfound') !== false) {
             throw new midcom_error("Author '{$this->_request_data['from']}' not found");
         }
         $this->_article->author = midcom_connection::get_user();
     } else {
         // TODO: This code needs a bit of rethinking
         $author_user = midcom::get('auth')->get_user($author->guid);
         if (!$this->_content_topic->can_do('midgard:create', $author_user)) {
             throw new midcom_error('Author doesn\'t have posting privileges');
         }
         $this->_article->author = $author->id;
     }
     //Default to first user in DB if author is not set
     if (!$this->_article->author) {
         $qb = midcom_db_person::new_query_builder();
         $qb->add_constraint('username', '<>', '');
         $qb->set_limit(1);
         $results = $qb->execute();
         unset($qb);
         if (empty($results)) {
             //No users found
             throw new midcom_error('Cannot set any author for the article');
         }
         $this->_article->author = $results[0]->id;
     }
     $resolver = new midcom_helper_reflector_nameresolver($this->_article);
     $this->_article->topic = $this->_content_topic->id;
     $this->_article->title = $title;
     $this->_article->allow_name_catenate = true;
     $this->_article->name = $resolver->generate_unique_name('title');
     if (empty($this->_article->name)) {
         debug_add('Could not generate unique name for the new article from title, using timestamp', MIDCOM_LOG_INFO);
         $this->_article->name = time();
         $resolver = new midcom_helper_reflector_nameresolver($this->_article);
         if (!$resolver->name_is_unique()) {
             throw new midcom_error('Failed to create unique name for the new article, aborting.');
         }
     }
     if (!$this->_article->create()) {
         debug_print_r('Failed to create article:', $this->_article);
         throw new midcom_error('Failed to create a new article. Last Midgard error was: ' . midcom_connection::get_error_string());
     }
     $this->_article->parameter('midcom.helper.datamanager2', 'schema_name', $this->_config->get('api_email_schema'));
     return true;
 }
Example #3
0
 /**
  * Make sure our name is nice and clean
  *
  * @see http://trac.midgard-project.org/ticket/809
  */
 public function _on_validate()
 {
     $schema = $this->storage->_schema->fields[$this->name];
     $copy = $this->_copy_object($this->storage->object);
     $property = $schema['storage']['location'];
     $resolver = new midcom_helper_reflector_nameresolver($copy);
     if (empty($this->value)) {
         if (isset($this->_datamanager->types[$this->title_field]) && $this->_datamanager->types[$this->title_field]->value) {
             $copy->{$property} = midcom_helper_misc::generate_urlname_from_string($this->_datamanager->types[$this->title_field]->value);
             $this->value = $resolver->generate_unique_name();
         }
     }
     $copy->{$property} = $this->value;
     if (!$resolver->name_is_safe($property)) {
         $this->validation_error = sprintf($this->_l10n->get('type urlname: name is not "URL-safe", try "%s"'), midcom_helper_misc::generate_urlname_from_string($this->value));
         return false;
     }
     if (!$this->allow_unclean && !$resolver->name_is_clean($property)) {
         $this->validation_error = sprintf($this->_l10n->get('type urlname: name is not "clean", try "%s"'), midcom_helper_misc::generate_urlname_from_string($this->value));
         return false;
     }
     if (!$resolver->name_is_unique()) {
         $new_name = $resolver->generate_unique_name();
         if ($this->allow_catenate) {
             // If allowed to, silently use the generated name
             $this->value = $new_name;
             $this->_orig_value = $new_name;
             $copy->{$property} = $this->value;
         } else {
             $this->validation_error = sprintf($this->_l10n->get('type urlname: name is already taken, try "%s"'), $new_name);
             return false;
         }
     }
     return true;
 }
Example #4
0
 /**
  * Helper method to call in the _xxx_pre_checks, handles the API
  * level checks and automatic operations as specified in ticket #809
  *
  * @see http://trac.midgard-project.org/ticket/809
  * Quoting the ticket API-level section:
  * <pre>
  *      1. Checks will be done in the pre-flight check phase (ie just after _on_creating/_on_updating)
  *      2. If name is not unique false is returned for pre-flight check, preventing create/update
  *          2.2 UNLESS a property in the object ('allow_name_catenate') is set to true in which case unique one is generated by catenating an incrementing number to the name.
  *      3. if name is empty unique name is generated from title property (unless title is empty too)
  *      4. if name is not URL-safe false is returned
  * </pre>
  *
  * @param midcom_core_dbaobject $object The DBA object we're working on
  * @return boolean indicating whether from our point of view everything is ok
  *
  * @see midcom_helper_reflector_nameresolver::name_is_safe_or_empty()
  * @see midcom_helper_reflector_nameresolver::name_is_unique_or_empty()
  * @see midcom_helper_reflector_nameresolver::generate_unique_name()
  */
 private static function _pre_check_name(midcom_core_dbaobject $object)
 {
     // Make sure name is empty of unique if the object has such property
     $name_property = midcom_helper_reflector::get_name_property($object);
     if (empty($name_property)) {
         // This object has no name property, return early
         return true;
     }
     $resolver = new midcom_helper_reflector_nameresolver($object);
     /**
      * If name is empty, try to generate new, unique one
      *
      * @see http://trac.midgard-project.org/ticket/809
      */
     if (empty($object->{$name_property})) {
         // name is empty, try to generate
         $new_name = $resolver->generate_unique_name();
         if (!empty($new_name)) {
             $object->{$name_property} = $new_name;
         }
         unset($new_name);
     }
     /**
      * Enforce URL-safe (or empty) names
      *
      * @see http://trac.midgard-project.org/ticket/809
      */
     if (!$resolver->name_is_safe_or_empty()) {
         midcom_connection::set_error(MGD_ERR_INVALID_NAME);
         return false;
     }
     /**
      * Enforce unique (or empty) names
      *
      * @see http://trac.midgard-project.org/ticket/809
      */
     if (!$resolver->name_is_unique_or_empty()) {
         if ($object->allow_name_catenate) {
             // Transparent catenation allowed, let's try again.
             $new_name = $resolver->generate_unique_name();
             if (!empty($new_name)) {
                 $object->{$name_property} = $new_name;
                 return true;
             } else {
                 debug_add('allow_name_catenate was set but midcom_helper_reflector_nameresolver::generate_unique_name() returned empty value, falling through', MIDCOM_LOG_WARN);
             }
         }
         midcom_connection::set_error(MGD_ERR_OBJECT_NAME_EXISTS);
         return false;
     }
     // All checks ok, we're fine.
     return true;
 }
Example #5
0
 /**
  * Make sure we have unique filename
  *
  * @todo Isn't there a reflector method that already does this (for filenames)?
  */
 private function _generate_unique_name($filename)
 {
     $attachment = new midcom_db_attachment();
     $attachment->name = $filename;
     $attachment->parentguid = $this->storage->object->guid;
     $resolver = new midcom_helper_reflector_nameresolver($attachment);
     if (!$resolver->name_is_unique()) {
         debug_add("Name '{$attachment->name}' is not unique, trying to generate", MIDCOM_LOG_INFO);
         $ext = '';
         if (preg_match('/^(.*)(\\..*?)$/', $filename, $ext_matches)) {
             $ext = $ext_matches[2];
         }
         $filename = $resolver->generate_unique_name('name', $ext);
     }
     return $filename;
 }
Example #6
0
 /**
  * Imports an item as an event
  */
 private function import_event($item)
 {
     // Check that we're trying to import item suitable to be an event
     if (!isset($item['xcal']) && !isset($item['gd']['when@'])) {
         // Not an event
         return false;
     }
     // Get start and end times
     $start = null;
     $end = null;
     if (isset($item['xcal']['dtstart'])) {
         // xCal RSS feed, for example Upcoming or Last.fm
         $start = strtotime($item['xcal']['dtstart']);
     } elseif (isset($item['gd']['when@starttime'])) {
         // gData Atom feed, for example Dopplr
         $start = strtotime($item['gd']['when@starttime']);
     }
     if (isset($item['xcal']['dtend'])) {
         $end = strtotime($item['xcal']['dtend']);
     } elseif (isset($item['gd']['when@starttime'])) {
         $end = strtotime($item['gd']['when@endtime']);
     }
     if (!$start || !$end) {
         return false;
     }
     if (!$this->_datamanager) {
         $schemadb = midcom_helper_datamanager2_schema::load_database($this->_node_config->get('schemadb'));
         $this->_datamanager = new midcom_helper_datamanager2_datamanager($schemadb);
     }
     // TODO: Move to real geocoded stuff
     $location_parts = array();
     if (isset($item['xcal']['x-calconnect-venue_adr_x-calconnect-venue-name'])) {
         $location_parts[] = $item['xcal']['x-calconnect-venue_adr_x-calconnect-venue-name'];
     }
     if (isset($item['xcal']['x-calconnect-venue_adr_x-calconnect-street'])) {
         $location_parts[] = $item['xcal']['x-calconnect-venue_adr_x-calconnect-street'];
     }
     if (isset($item['xcal']['x-calconnect-venue_adr_x-calconnect-city'])) {
         $location_parts[] = $item['xcal']['x-calconnect-venue_adr_x-calconnect-city'];
     }
     if (isset($item['gd']['where@valuestring'])) {
         $wherevalues = explode(' ', $item['gd']['where@valuestring']);
         foreach ($wherevalues as $val) {
             $location_parts[] = $val;
         }
     }
     $qb = net_nemein_calendar_event_dba::new_query_builder();
     $qb->add_constraint('node', '=', $this->_feed->node);
     $qb->add_constraint('extra', '=', md5($item['guid']));
     $events = $qb->execute();
     if (count($events) > 0) {
         // This item has been imported already earlier. Update
         $event = $events[0];
         $event->_activitystream_verb = 'http://community-equity.org/schema/1.0/clone';
         $event->_rcs_message = sprintf(midcom::get('i18n')->get_string('%s was imported from %s', 'net.nemein.rss'), $event->title, $this->_feed->title);
         $event->allow_name_catenate = true;
         if (empty($event->name)) {
             $resolver = new midcom_helper_reflector_nameresolver($event);
             // To prevent validation errors in case the auto-catenate is not allowed in the urlname datatype
             $event->name = $resolver->generate_unique_name();
         }
     } else {
         $node = new midcom_db_topic($this->_feed->node);
         $node_lang_code = $node->get_parameter('net.nemein.calendar', 'language');
         // This is a new item
         $event = new net_nemein_calendar_event_dba();
         $event->start = $start;
         $event->end = $end;
         $event->extra = md5($item['guid']);
         $event->node = $this->_feed->node;
         if ($node->get_parameter('net.nemein.calendar', 'symlink_topic') != '') {
             try {
                 $symlink_topic = new midcom_db_topic($node->get_parameter('net.nemein.calendar', 'symlink_topic'));
                 $event->node = $symlink_topic->id;
             } catch (midcom_error $e) {
                 $e->log();
             }
         }
         if ($node_lang_code != '') {
             $lang_id = midcom::get('i18n')->code_to_id($node_lang_code);
             $event->lang = $lang_id;
         }
         $event->allow_name_catenate = true;
         $event->title = (string) $item['title'];
         $event->_activitystream_verb = 'http://community-equity.org/schema/1.0/clone';
         $event->_rcs_message = sprintf(midcom::get('i18n')->get_string('%s was imported from %s', 'net.nemein.rss'), $event->title, $this->_feed->title);
         $resolver = new midcom_helper_reflector_nameresolver($event);
         $event->name = $resolver->generate_unique_name();
         if (!$event->create()) {
             return false;
         }
     }
     $this->_datamanager->autoset_storage($event);
     $this->_datamanager->types['start']->value = new DateTime(strftime('%Y-%m-%d %H:%M:%S', $start));
     $this->_datamanager->types['end']->value = new DateTime(strftime('%Y-%m-%d %H:%M:%S', $end));
     if (is_a($this->_datamanager->types['location'], 'midcom_helper_datamanager2_type_position')) {
         // Position type, give all values we got, assume order "Street, City, Country"
         $location_parts = array_reverse($location_parts);
         if (count($location_parts) > 0) {
             $country = org_routamc_positioning_country_dba::get_by_name($location_parts[0]);
             if ($country && $country->code) {
                 $this->_datamanager->types['location']->location->county = $country->code;
             }
         }
         if (count($location_parts) > 1) {
             $city = org_routamc_positioning_city_dba::get_by_name($location_parts[1]);
             if ($city && $city->id) {
                 $this->_datamanager->types['location']->location->city = $city->id;
             }
         }
         if (count($location_parts) > 2) {
             $this->_datamanager->types['location']->location->street = $location_parts[2];
         }
         if (isset($item['gml'])) {
             $gml_parts = explode(' ', $item['gml']['where_point_pos']);
             if (count($gml_parts) == 2) {
                 $this->_datamanager->types['location']->location->latitude = (double) $gml_parts[0];
                 $this->_datamanager->types['location']->location->longitude = (double) $gml_parts[1];
             }
         }
     } else {
         // Just give the location string we got
         $this->_datamanager->types['location']->value = implode(', ', $location_parts);
     }
     foreach ($item as $key => $value) {
         if (isset($this->_datamanager->types[$key])) {
             $this->_datamanager->types[$key]->value = $value;
         }
     }
     if (!$this->_datamanager->save()) {
         return false;
     }
     // This should be unnecessary but left in place just to be sure
     if (strlen($this->_datamanager->storage->object->name) == 0) {
         // Generate something to avoid empty "/" links in case of failures
         $this->_datamanager->storage->object->name = time();
         $this->_datamanager->storage->object->update();
     }
     $this->parse_tags($event, $item, 'description');
     $this->parse_parameters($event, $item);
     return $event->guid;
 }
Example #7
0
<?php

/**
 * @package midcom.helper.reflector
 * @author The Midgard Project, http://www.midgard-project.org
 * @copyright The Midgard Project, http://www.midgard-project.org
 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
 */
// FIXME: make generic
$article = new midcom_db_article();
$article->topic = 5;
$article->title = 'Duplicate name test with (with allow_catenate)';
$article->name = 'gathering-09';
$article->allow_name_catenate = true;
$reflected_name_property = midcom_helper_reflector::get_name_property($article);
$resolver = new midcom_helper_reflector_nameresolver($article);
$reflected_name = $resolver->get_object_name();
echo "Reflector thinks name is '{$reflected_name}' (from property '{$reflected_name_property}')<br>\n";
if ($resolver->name_is_safe()) {
    echo "OK: '{$reflected_name}' is considered URL-safe<br>\n";
} else {
    echo "ERROR: '{$reflected_name}' is NOT considered URL-safe<br>\n";
}
if ($resolver->name_is_clean()) {
    echo "OK: '{$reflected_name}' is considered 'clean'<br>\n";
} else {
    echo "WARN: '{$reflected_name}' is NOT considered 'clean'<br>\n";
}
if ($resolver->name_is_unique()) {
    echo "OK: '{$reflected_name}' is unique (among siblings)<br>\n";
} else {