GithubHelp home page GithubHelp logo

devgeniem / wp-geniem-importer Goto Github PK

View Code? Open in Web Editor NEW
14.0 30.0 2.0 146 KB

An object-oriented WordPress importer.

License: GNU General Public License v3.0

PHP 100.00%
wordpress wordpress-plugin wordpress-development wordpress-importer importer php polylang advanced-custom-fields acf

wp-geniem-importer's Introduction

geniem-github-banner

Enterprise WordPress Importer

Enterprise Importer is a WordPress importer plugin enabling importing WordPress data from external sources through an object-oriented functional API.

Installation

Install the plugin with Composer by first adding the private repository and then requiring the package:

composer config repositories.devgeniem/wp-geniem-importer git [email protected]:devgeniem/wp-geniem-importer.git
composer require devgeniem/wp-geniem-importer

Then activate the plugin from the WordPress dashboard or with the WP-CLI.

wp plugin activate wp-geniem-importer

Importing post objects

The plugin provides a functional API for importing various data types. You can think of the importer as an integration layer between your custom data source and the WordPress database. Your job is to format the data to meet the importer object specification. If you are lucky and your external data source can provide the data in the importer data format, your job is as simple as decoding the data into a PHP object and then passing it through the API.

An import is a two step process. First you must set the data for the importer \Geniem\Importer\Post object instance and then you call its save method to store the object data into the WordPress database.

An example of importing a single post can be found here.

\Geniem\Importer\Post - Methods

__construct() public

To start a new import process call the Post class constructor and pass a unique id for it. This creates a new instance of the class and identifies it. If this is an update, the WP post matching the id is fetched and the post object data is loaded as default values for the import. To ensure the time values are updating they are unset from the post object at this point.

Parameters
  • $gi_id (string) (Required) An id uniquely identifies the object in the external data source.
Example usage
$post = new \Geniem\Importer\Post( 'my_id_1234' );

set_data() public

The first step in the import process is to set the data for the importer. This funtion takes a full importer object as a parameter, validates all fields and sets the data into the corresponding class properties. To check if the data is valid after setting it, you can call the get_errors() which will return an array of occurred errors.

Parameters
  • $raw_post (object) (Required) An object containing needed \Geniem\Importer\Post class properties.
    • post (object) (Required) The basic WP post object data as a stdClass object.
    • attachments (array) (Optional) An array of attachment objects containing:
      • id (string) (Required) An unique id identifying the object in the external data source.
      • src (string) (Required) The source from which to upload the image into WordPress.
        • The plugin currently supports only image files!
      • alt (string) (Optional) The alt text for the image. This is saved into postmeta.
      • caption (string) (Optional) The file caption text.
      • descrpition (string) (Optional) The file description text.
    • meta (object) (Optional) An object where all the keys correspond to meta keys and values correspond to meta values.
    • taxonomies (array) (Optional) An array of taxonomy objects containing:
      • slug (string) (Required) The taxonomy term slug.
      • name (string) (Required) The taxonomy term display name.
      • taxonomy (string) (Required) The taxonomy name, for example category.
    • acf (array) (Optional) An array of Advanced Custom Fields data objects containing:
      • type (string) (Required) The ACF field type (types).
      • key (string) (Required) The ACF field key. This must be the unique key defined for the field.
      • value (mixed) (Required) The data value matching the field type specifications.
    • i18n (object) (Optional) Custom localization information is stored in the property. It must contain an object with the following properties:
      • locale (string) (Required) The language code string, for example fi.
      • master (string|object) (Required) A gi_id value to be used to fetch a default language post or an array containing a query_key value. This is used to link the post as a translation.

Example usage

$post->set_data( $my_raw_post_data );
Example data in JSON format
{
  "post": {
    "post_title": "The title",
    "post_content": "This is a new post and it is awesome!",
    "post_excerpt": "This is a new post..."
  },
  "meta": {
    "my_meta_key": "My meta value.",
    "my_meta_key2": 1234
  },
  "attachments": [
    {
      "mime_type": "image/jpg",
      "id": "123456",
      "alt": "Alt text is stored in postmeta.",
      "caption": "This is the post excerpt.",
      "description": "This is the post content.",
      "src": "http://upload-from-here.com/123456.jpg",
    }
  ],
  "taxonomies": [
    {
      "slug": "my-term",
      "taxonomy": "post_tag"
    }
  ],
}

save() public

Run this function after setting the data for the importer object. This function saves all set data into WordPress database. Before any data is stored into the database the current Post object is validated and it throws an Geniem\Importer\Exception\PostException if any errors have occurred. After all data is saved into the database the instance is validated again and any save errors throw the same expection. If no errors occurred, the WordPress post id is returned.

Parameters
  • $force_save (boolean) (Optional) Set this to true skip validation and force saving. You can create custom validations through multiple hooks or by manually inspecting error with by getting them with the get_errors() function. Defaults to false.

Plugin settings

The \Geniem\Importer\Settings\ class is used to set and load all plugin settings. It uses the following settings that are overridable with corresponding constants.

Available settings

  • Setting key id_prefix, constant GI_ID_PREFIX, default value 'gi_id_'.
  • Setting key attachment_prefix, constant GI_ATTACHMENT_PREFIX, default value 'gi_attachment_'.
  • Setting key log_errors, constant GI_LOG_ERRORS, default value false.
  • Setting key transient_key, constant GI_TRANSIENT_KEY, default value 'gi_'.
  • Setting key transient_expiration, constant GI_TRANSIENT_EXPIRATION, default value HOUR_IN_SECOND.
  • Setting key tmp_folder, constant GI_TMP_FOLDER, default value '/tmp/'.
  • Setting key table_name, constant GI_TABLE_NAME, default value geniem_importer_log.
  • Setting key log_status_ok, constant GI_LOG_STATUS_OK, default value 'OK'.
  • Setting key log_status_fail, constant GI_LOG_STATUS_FAIL, default value 'FAIL'.

Accessing settings

Example usage:

$gi_id_prefix = \Geniem\Importer\Settings::get( 'id_prefix' );

Overriding settings

To override the transient expiration time set the following constant before the setting is used the first time.

define( 'GI_TRANSIENT_EXPIRATION', MONTH_IN_SECONDS );

Logging

The plugin creates a custom table into the WordPress database called wp_geniem_importer_log. This table holds log entries of all import actions and contains the following columns:

  • id Log entry id.
  • gi_id The importer object id.
  • post_id The WordPress post id of the importer object. Stored only if the save() is run successfully.
  • import_date_gmt A GMT timestamp of the import date in MySQL datetime format.
  • data The importer object data containing all properties including errors.
  • status The import status: OK|FAIL.

Rollback

The log provides a rollback feature. If an import fails the importer tries to roll back the previous successful import. If no previous imports with the OK status are found, the imported object is set into draft state to prevent front-end users from accessing posts with malformed data.

To disable the rollback feature set the GENIEM_IMPORTER_ROLLBACK_DISABLE constant with a value of true.

Changelog

CHANGELOG.md

Contributors

wp-geniem-importer's People

Contributors

godbone avatar liblastic avatar mikamiinalainen avatar zarubaru avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wp-geniem-importer's Issues

No support for groupable type fields (e.g. repeater) or a hierarchical structure in acf in general.

The importer doesn't yet have support for fields that contain sub fields. This makes it hard to save for instance repeater fields or group fields.

A proposed solution is to create a recursive method inside save_acf that gets called on each iteration of the acf_field array and calls itself again whenever there's a field that has a groupable type.

Group and repeater fields also have to be handled differently. The proposed way should probably be this: https://www.advancedcustomfields.com/resources/update_sub_field/

Translations create multuple posts for the main language if the post type is not translatable

If the importer data holds translation data for Polylang, the import process creates a multiple posts under the main language if the post type is not translatable. This will happen as many times as there are translations defined for the post.

The save process should discard translations for post types not set to be translated with Polylang and throw an error. This would prevent creation of multiple posts and would give the user information about translations not being active for the post type.

Allow object type for the i18n property

The documentation describes master linking with the following specifications:

Fix this by allowing the "i18n" value to be passed as either an associative array or an object.

To further improve type handling, a breaking change would be to create a class for the "i18n" and to add the class as the type of the "i18n" property.

Taxonomies are handled as arrays instead of objects

Readme states that $raw_post->taxonomies shoud be An array of taxonomy objects.

In set_taxonomies function the $raw_post->taxonomies is casted as array. Note that it's the array of objects that are casted instead of the objects.

In validate_taxonomies function there is first check ! is_array( $taxonomies which it now always true. The error message "Error in the taxonomies. Taxonomies must be passed in an associative array." implies that each object should be checked but instead of object it should be an associative array.

After that there is foearch loop with check if $term['taxonomy'] is a registered taxonomy. Here the code fails if you have set the $raw_post->taxonomies as an array of taxonomy objects. Array of associative arrays works. That's not optimal though since the WP_Term need to be casted to array before it can be used.

So should $raw_post->taxonomies contain objects or associative arrays?

No support for taxonomy term translations

Currently there's no support for multilingual taxonomy term linking. Instead of creating terms in the same language with the post that is currently being imported, the code adds / modifies terms with the primary language only.

This means that terms of multilingual taxonomies all get added to the primary language, even though they are in another language. For example, "uutiset, news, nyheter".

Post's attachment image not saved in Post->save_meta()

In Post class, function save_attachments creates $this->attachment_ids array with keys prefixed with attachment prefix.
L821

                $this->attachment_ids[ $attachment_prefix . $attachment_id ] =
                    Api::set_prop( $attachment, 'post_id', $attachment_post_id );

In same class, function save_meta() tries to access saved attachment ids with only the attachment id as a key: L961

                    $attachment_post_id = $this->attachment_ids[ $value ] ?? '';

resulting missing $attachment_post_id and failed import. Adding prefix also to L961 seems to fix the issue:

                    $attachment_prefix = Settings::get('attachment_prefix')
                    $attachment_post_id = $this->attachment_ids[  $attachment_prefix  . $value ] ?? '';

Fix master linking for localized posts

The documentation describes master linking with the following specifications:

  • i18n (object) (Optional) Custom localization information is stored in the property. It must contain an object with the following properties:
    • locale (string) (Required) The language code string, for example fi.
    • master (string|object) (Required) A gi_id value to be used to fetch a default language post or an array containing a query_key value. This is used to link the post as a translation.

It seems that the current version only supports the array type as the "master" property. The validation does not allow passing a value other than an array with a "query_key" key. See:
https://github.com/devgeniem/wp-geniem-importer/blob/master/src/Post.php#L593

Fix this by allowing a direct id value to be set as the value of "master".

Translated taxonomy terms are added before post language is set

On importer's save the taxonomy terms given to the post object are saved before the localisation is done. This is why translated terms are not saved correctly to the post's data. The methods' run order needs to be changed in the save method, so that localisation comes first.

Localized posts with different languages have a number added to their permalink if the title is the same.

When localized versions of posts with the same title are created with Polylang manually in WP, the localized permalink structure handles it so that there's no -2 etc added to the end of the permalink.

With the importer, the post is saved before the translation connection and in that moment it is in the same language as the primary version of the post. The translation is created only afterwards and at that moment, there's already a -2 in the permalink of the translated post.

This would be an issue for example when importing events or movies that have the same name -> title in each language used on the web site.

No support for image translations when adding images to imported posts.

Issue is the same as with taxonomy terms. There is no way to handle image translations in a way that the correct localized version would be added as an attachment to the localized version of the post.

Instead currently the only option is to use the image added to the primary language version of the post or manually import the same image for the localized post with a different name so that it gets added as an attachment with the correct language. The latter way doesn't create a polylang translation connection between the images.

Taxonomy terms are fetched with "get_term_by" during taxonomy import -> localisation is not supported.

We have to change the method to get_terms which has support for language through polylang. Here's a quick example:

$lang     = ! empty( $this->i18n['locale'] ) ? $this->i18n['locale'] : \pll_default_language();

$found_terms = \get_terms( [
    'slug'       => $slug,
    'taxonomy'   => $taxonomy,
    'lang'       => $lang,
    'hide_empty' => false,
    'fields'     => 'ids',
] );

the existence of pll should also be checked in the code.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.