drupal-exporter 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.gitignore +39 -0
 - data/.rspec +3 -0
 - data/.travis.yml +8 -0
 - data/CHANGELOG.md +4 -0
 - data/Gemfile +7 -0
 - data/Gemfile.lock +72 -0
 - data/LICENSE +22 -0
 - data/README.md +251 -0
 - data/Rakefile +9 -0
 - data/bin/drupal-exporter +37 -0
 - data/drupal_exporter.gemspec +34 -0
 - data/drupal_settings/boolean_columns.yml +2 -0
 - data/drupal_settings/drupal_content_types.json +47 -0
 - data/drupal_settings/drupal_settings.yml +23 -0
 - data/lib/cli.rb +13 -0
 - data/lib/configuration.rb +46 -0
 - data/lib/converters/content_types_structure_creator.rb +60 -0
 - data/lib/converters/contentful_model_to_json.rb +109 -0
 - data/lib/drupal/content_type.rb +151 -0
 - data/lib/drupal/export.rb +69 -0
 - data/lib/drupal/file_managed.rb +42 -0
 - data/lib/drupal/tag.rb +52 -0
 - data/lib/drupal/user.rb +46 -0
 - data/lib/drupal/vocabulary.rb +42 -0
 - data/lib/migrator.rb +28 -0
 - data/lib/version.rb +3 -0
 - data/spec/fixtures/database_rows/content_type_article.json +14 -0
 - data/spec/fixtures/database_rows/image.json +10 -0
 - data/spec/fixtures/database_rows/node_content_type_article.json +15 -0
 - data/spec/fixtures/database_rows/node_content_type_blog.json +15 -0
 - data/spec/fixtures/database_rows/tag.json +8 -0
 - data/spec/fixtures/database_rows/user.json +18 -0
 - data/spec/fixtures/database_rows/vocabulary.json +9 -0
 - data/spec/fixtures/drupal/assets/file/file_4.json +6 -0
 - data/spec/fixtures/drupal/entries/article/article_5.json +24 -0
 - data/spec/fixtures/drupal/entries/tag/tag_1.json +9 -0
 - data/spec/fixtures/drupal/entries/user/user_1.json +6 -0
 - data/spec/fixtures/drupal/entries/vocabulary/vocabulary_3.json +6 -0
 - data/spec/fixtures/json_responses/article.json +24 -0
 - data/spec/fixtures/json_responses/image.json +6 -0
 - data/spec/fixtures/json_responses/tag.json +9 -0
 - data/spec/fixtures/json_responses/vocabulary.json +6 -0
 - data/spec/fixtures/settings/boolean_columns.yml +2 -0
 - data/spec/fixtures/settings/drupal_content_types.json +47 -0
 - data/spec/fixtures/settings/drupal_settings.yml +17 -0
 - data/spec/lib/configuration_spec.rb +18 -0
 - data/spec/lib/drupal/content_type_spec.rb +123 -0
 - data/spec/lib/drupal/export_spec.rb +33 -0
 - data/spec/lib/drupal/file_managed_spec.rb +52 -0
 - data/spec/lib/drupal/tag_spec.rb +60 -0
 - data/spec/lib/drupal/user_spec.rb +49 -0
 - data/spec/lib/drupal/vocabulary_spec.rb +51 -0
 - data/spec/spec_helper.rb +11 -0
 - data/spec/support/db_rows_json.rb +15 -0
 - data/spec/support/shared_configuration.rb +20 -0
 - metadata +297 -0
 
| 
         @@ -0,0 +1,34 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            lib = File.expand_path('../lib', __FILE__)
         
     | 
| 
      
 2 
     | 
    
         
            +
            $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require File.expand_path('../lib/version', __FILE__)
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            Gem::Specification.new do |spec|
         
     | 
| 
      
 7 
     | 
    
         
            +
              spec.name          = 'drupal-exporter'
         
     | 
| 
      
 8 
     | 
    
         
            +
              spec.version       = Version::VERSION
         
     | 
| 
      
 9 
     | 
    
         
            +
              spec.authors       = ['Contentful GmbH (Andreas Tiefenthaler)']
         
     | 
| 
      
 10 
     | 
    
         
            +
              spec.email         = ['rubygems@contentful.com']
         
     | 
| 
      
 11 
     | 
    
         
            +
              spec.description   = 'Drupal exporter that prepares content to be imported'
         
     | 
| 
      
 12 
     | 
    
         
            +
              spec.summary       = 'Exporter for Drupal 7'
         
     | 
| 
      
 13 
     | 
    
         
            +
              spec.homepage      = 'https://github.com/contentful/drupal-exporter.rb'
         
     | 
| 
      
 14 
     | 
    
         
            +
              spec.license       = 'MIT'
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              spec.files         = `git ls-files -z`.split("\x0")
         
     | 
| 
      
 17 
     | 
    
         
            +
              spec.executables    << 'drupal-exporter'
         
     | 
| 
      
 18 
     | 
    
         
            +
              spec.test_files    = spec.files.grep(%r{^(test|spec|features)/})
         
     | 
| 
      
 19 
     | 
    
         
            +
              spec.require_paths = ['lib']
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
              spec.add_dependency 'http', '~> 0.6'
         
     | 
| 
      
 22 
     | 
    
         
            +
              spec.add_dependency 'multi_json', '~> 1'
         
     | 
| 
      
 23 
     | 
    
         
            +
              spec.add_dependency 'sequel','~> 4.15'
         
     | 
| 
      
 24 
     | 
    
         
            +
              spec.add_dependency 'mysql2','~> 0.3'
         
     | 
| 
      
 25 
     | 
    
         
            +
              spec.add_dependency 'activesupport','~> 4.1'
         
     | 
| 
      
 26 
     | 
    
         
            +
              spec.add_dependency 'pg', '~> 0.17.0'
         
     | 
| 
      
 27 
     | 
    
         
            +
              spec.add_dependency 'escort','~> 0.4.0'
         
     | 
| 
      
 28 
     | 
    
         
            +
              spec.add_dependency 'i18n', '~> 0.6'
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              spec.add_development_dependency 'rspec', '~> 3'
         
     | 
| 
      
 31 
     | 
    
         
            +
              spec.add_development_dependency 'rspec-its', '~> 1.1.0'
         
     | 
| 
      
 32 
     | 
    
         
            +
              spec.add_development_dependency 'bundler', '~> 1.6'
         
     | 
| 
      
 33 
     | 
    
         
            +
              spec.add_development_dependency 'rake'
         
     | 
| 
      
 34 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,47 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            // machine_name_of_content_type : {
         
     | 
| 
      
 2 
     | 
    
         
            +
            //  contentful_api_field : column_machine_name
         
     | 
| 
      
 3 
     | 
    
         
            +
            // }
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            {
         
     | 
| 
      
 6 
     | 
    
         
            +
              "article": {
         
     | 
| 
      
 7 
     | 
    
         
            +
                "body": "body",
         
     | 
| 
      
 8 
     | 
    
         
            +
                "image": "field_image"
         
     | 
| 
      
 9 
     | 
    
         
            +
              },
         
     | 
| 
      
 10 
     | 
    
         
            +
              "page": {
         
     | 
| 
      
 11 
     | 
    
         
            +
                "body": "body"
         
     | 
| 
      
 12 
     | 
    
         
            +
              },
         
     | 
| 
      
 13 
     | 
    
         
            +
              "blog": {
         
     | 
| 
      
 14 
     | 
    
         
            +
                "body": "body"
         
     | 
| 
      
 15 
     | 
    
         
            +
              },
         
     | 
| 
      
 16 
     | 
    
         
            +
              "content_type": {
         
     | 
| 
      
 17 
     | 
    
         
            +
                "body": "body",
         
     | 
| 
      
 18 
     | 
    
         
            +
                "age": "field_age",
         
     | 
| 
      
 19 
     | 
    
         
            +
                "if_content_type": "field_if_content_type",
         
     | 
| 
      
 20 
     | 
    
         
            +
                "decimal": "field_decimal"
         
     | 
| 
      
 21 
     | 
    
         
            +
              },
         
     | 
| 
      
 22 
     | 
    
         
            +
              "second_content_type": {
         
     | 
| 
      
 23 
     | 
    
         
            +
                "body": "body",
         
     | 
| 
      
 24 
     | 
    
         
            +
                "firma": "field_firma"
         
     | 
| 
      
 25 
     | 
    
         
            +
              },
         
     | 
| 
      
 26 
     | 
    
         
            +
              "content_all_types": {
         
     | 
| 
      
 27 
     | 
    
         
            +
                "body": "body",
         
     | 
| 
      
 28 
     | 
    
         
            +
                "file": "field_file",
         
     | 
| 
      
 29 
     | 
    
         
            +
                "image_sec": "field_sec_image",
         
     | 
| 
      
 30 
     | 
    
         
            +
                "integer": "field_integer",
         
     | 
| 
      
 31 
     | 
    
         
            +
                "boolean": "field_boolean",
         
     | 
| 
      
 32 
     | 
    
         
            +
                "decimal": "field_sec_decimal",
         
     | 
| 
      
 33 
     | 
    
         
            +
                "list_float": "field_list_float",
         
     | 
| 
      
 34 
     | 
    
         
            +
                "list_integer": "field_list_integer",
         
     | 
| 
      
 35 
     | 
    
         
            +
                "list_text": "field_list_text",
         
     | 
| 
      
 36 
     | 
    
         
            +
                "long_text": "field_long_text",
         
     | 
| 
      
 37 
     | 
    
         
            +
                "text_summary": "field_text_summary",
         
     | 
| 
      
 38 
     | 
    
         
            +
                "term_tagging": {
         
     | 
| 
      
 39 
     | 
    
         
            +
                  "table": "field_term_tagging"
         
     | 
| 
      
 40 
     | 
    
         
            +
                },
         
     | 
| 
      
 41 
     | 
    
         
            +
                "text": "field_text"
         
     | 
| 
      
 42 
     | 
    
         
            +
              },
         
     | 
| 
      
 43 
     | 
    
         
            +
              "assety": {
         
     | 
| 
      
 44 
     | 
    
         
            +
                "body": "body",
         
     | 
| 
      
 45 
     | 
    
         
            +
                "assets": "field_asset"
         
     | 
| 
      
 46 
     | 
    
         
            +
              }
         
     | 
| 
      
 47 
     | 
    
         
            +
            }
         
     | 
| 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            #PATH to all data
         
     | 
| 
      
 2 
     | 
    
         
            +
            data_dir: PATH_WHERE_ALL_DATA_WILL_BE_SAVED
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            ########## EXPORT DATA ##########
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            #Connecting to a database
         
     | 
| 
      
 7 
     | 
    
         
            +
            adapter: mysql2
         
     | 
| 
      
 8 
     | 
    
         
            +
            host: localhost
         
     | 
| 
      
 9 
     | 
    
         
            +
            database: drupal_database_name
         
     | 
| 
      
 10 
     | 
    
         
            +
            user: username
         
     | 
| 
      
 11 
     | 
    
         
            +
            password: password
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
            # DRUPAL
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            drupal_content_types_json: drupal_settings/drupal_content_types.json
         
     | 
| 
      
 16 
     | 
    
         
            +
            drupal_boolean_columns: drupal_settings/boolean_columns.yml
         
     | 
| 
      
 17 
     | 
    
         
            +
            drupal_base_url: http://example_hostname.com
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            # CONVERT CONTENTFUL MODEL TO CONTENTFUL IMPORT STRUCTURE
         
     | 
| 
      
 20 
     | 
    
         
            +
            content_model_json: PATH_TO_CONTENTFUL_MODEL_JSON_FILE
         
     | 
| 
      
 21 
     | 
    
         
            +
            converted_model_dir: PATH_WHERE_CONVERTED_CONTENT_MODEL_WILL_BE_SAVED
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
            contentful_structure_dir: PATH_TO_CONTENTFUL_STRUCUTRE_JSON_FILE
         
     | 
    
        data/lib/cli.rb
    ADDED
    
    
| 
         @@ -0,0 +1,46 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'sequel'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'active_support/core_ext/hash'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Contentful
         
     | 
| 
      
 5 
     | 
    
         
            +
              class Configuration
         
     | 
| 
      
 6 
     | 
    
         
            +
                attr_reader :space_id,
         
     | 
| 
      
 7 
     | 
    
         
            +
                            :config,
         
     | 
| 
      
 8 
     | 
    
         
            +
                            :data_dir,
         
     | 
| 
      
 9 
     | 
    
         
            +
                            :collections_dir,
         
     | 
| 
      
 10 
     | 
    
         
            +
                            :entries_dir,
         
     | 
| 
      
 11 
     | 
    
         
            +
                            :assets_dir,
         
     | 
| 
      
 12 
     | 
    
         
            +
                            :db,
         
     | 
| 
      
 13 
     | 
    
         
            +
                            :drupal_content_types,
         
     | 
| 
      
 14 
     | 
    
         
            +
                            :drupal_base_url
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                def initialize(settings)
         
     | 
| 
      
 17 
     | 
    
         
            +
                  @config = settings
         
     | 
| 
      
 18 
     | 
    
         
            +
                  validate_required_parameters
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @data_dir = config['data_dir']
         
     | 
| 
      
 20 
     | 
    
         
            +
                  @collections_dir = "#{data_dir}/collections"
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @entries_dir = "#{data_dir}/entries"
         
     | 
| 
      
 22 
     | 
    
         
            +
                  @assets_dir = "#{data_dir}/assets"
         
     | 
| 
      
 23 
     | 
    
         
            +
                  @space_id = config['space_id']
         
     | 
| 
      
 24 
     | 
    
         
            +
                  @drupal_content_types = JSON.parse(File.read(config['drupal_content_types_json']), symbolize_names: true).with_indifferent_access
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @drupal_base_url = config['drupal_base_url']
         
     | 
| 
      
 26 
     | 
    
         
            +
                  @db = adapter_setup
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                def validate_required_parameters
         
     | 
| 
      
 30 
     | 
    
         
            +
                  fail ArgumentError, 'Set PATH to data_dir, the destination for all generated files. Check README' if config['data_dir'].nil?
         
     | 
| 
      
 31 
     | 
    
         
            +
                  fail ArgumentError, 'Set PATH to drupal_content_types_json. File with Drupal database structure. View README' if config['drupal_content_types_json'].nil?
         
     | 
| 
      
 32 
     | 
    
         
            +
                  define_adapter
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                def define_adapter
         
     | 
| 
      
 36 
     | 
    
         
            +
                  %w(adapter user host database).each do |param|
         
     | 
| 
      
 37 
     | 
    
         
            +
                    fail ArgumentError, "Set database connection parameters [adapter, host, database, user, password]. Missing the '#{param}' parameter! Password is optional. Check README!" unless config[param]
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                def adapter_setup
         
     | 
| 
      
 42 
     | 
    
         
            +
                  Sequel.connect(:adapter => config['adapter'], :user => config['user'], :host => config['host'], :database => config['database'], :password => config['password'])
         
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              end
         
     | 
| 
      
 46 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,60 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Contentful
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Converter
         
     | 
| 
      
 3 
     | 
    
         
            +
                class ContentTypesStructureCreator
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  attr_reader :config, :logger
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  def initialize(config)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    @config = config
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @logger = Logger.new(STDOUT)
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def create_content_type_json_file(content_type_name, values)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    collection = {
         
     | 
| 
      
 14 
     | 
    
         
            +
                        id: values[:id],
         
     | 
| 
      
 15 
     | 
    
         
            +
                        name: values[:name],
         
     | 
| 
      
 16 
     | 
    
         
            +
                        description: values[:description],
         
     | 
| 
      
 17 
     | 
    
         
            +
                        displayField: values[:displayField],
         
     | 
| 
      
 18 
     | 
    
         
            +
                        fields: create_fields(values[:fields])
         
     | 
| 
      
 19 
     | 
    
         
            +
                    }
         
     | 
| 
      
 20 
     | 
    
         
            +
                    write_json_to_file("#{config.collections_dir}/#{content_type_name}.json", collection)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    logger.info "Saving #{content_type_name}.json to #{config.collections_dir}"
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  def create_fields(fields)
         
     | 
| 
      
 25 
     | 
    
         
            +
                    fields.each_with_object([]) do |(field, value), results|
         
     | 
| 
      
 26 
     | 
    
         
            +
                      results << {
         
     | 
| 
      
 27 
     | 
    
         
            +
                          name: create_field(field, value).capitalize,
         
     | 
| 
      
 28 
     | 
    
         
            +
                          id: create_field(field, value),
         
     | 
| 
      
 29 
     | 
    
         
            +
                          type: create_type_field(value),
         
     | 
| 
      
 30 
     | 
    
         
            +
                          link_type: create_link_type_field(value),
         
     | 
| 
      
 31 
     | 
    
         
            +
                          link: create_link_field(value)
         
     | 
| 
      
 32 
     | 
    
         
            +
                      }.compact
         
     | 
| 
      
 33 
     | 
    
         
            +
                    end
         
     | 
| 
      
 34 
     | 
    
         
            +
                  end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  def create_field(field, value)
         
     | 
| 
      
 37 
     | 
    
         
            +
                    value.is_a?(Hash) ? value[:id] : field
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  def create_link_type_field(value)
         
     | 
| 
      
 41 
     | 
    
         
            +
                    value.is_a?(Hash) ? value[:link_type] : nil
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  def create_type_field(value)
         
     | 
| 
      
 45 
     | 
    
         
            +
                    value.is_a?(Hash) ? value[:type] : value
         
     | 
| 
      
 46 
     | 
    
         
            +
                  end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                  def create_link_field(value)
         
     | 
| 
      
 49 
     | 
    
         
            +
                    value.is_a?(Hash) ? value[:link] : nil
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                  def write_json_to_file(path, data)
         
     | 
| 
      
 53 
     | 
    
         
            +
                    File.open(path, 'w') do |file|
         
     | 
| 
      
 54 
     | 
    
         
            +
                      file.write(JSON.pretty_generate(data))
         
     | 
| 
      
 55 
     | 
    
         
            +
                    end
         
     | 
| 
      
 56 
     | 
    
         
            +
                  end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                end
         
     | 
| 
      
 59 
     | 
    
         
            +
              end
         
     | 
| 
      
 60 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,109 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require_relative 'content_types_structure_creator'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Contentful
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Converter
         
     | 
| 
      
 5 
     | 
    
         
            +
                class ContentfulModelToJson
         
     | 
| 
      
 6 
     | 
    
         
            +
                  attr_reader :config, :logger, :converted_model_dir, :content_types
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  FIELD_TYPE = %w( Link Array )
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def initialize(settings)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    @config = settings
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @logger = Logger.new(STDOUT)
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def create_content_type_json
         
     | 
| 
      
 16 
     | 
    
         
            +
                    contentful_structure = load_contentful_structure_file
         
     | 
| 
      
 17 
     | 
    
         
            +
                    logger.info 'Create JSON files with content types structure...'
         
     | 
| 
      
 18 
     | 
    
         
            +
                    contentful_structure.each do |content_type, values|
         
     | 
| 
      
 19 
     | 
    
         
            +
                      content_type_name = content_type_name(content_type)
         
     | 
| 
      
 20 
     | 
    
         
            +
                      create_directory(config.collections_dir)
         
     | 
| 
      
 21 
     | 
    
         
            +
                      ContentTypesStructureCreator.new(config).create_content_type_json_file(content_type_name, values)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    end
         
     | 
| 
      
 23 
     | 
    
         
            +
                    logger.info 'Done!'
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                  def convert_to_import_form
         
     | 
| 
      
 27 
     | 
    
         
            +
                    set_content_model_parameters
         
     | 
| 
      
 28 
     | 
    
         
            +
                    logger.info 'Converting Contentful model to Contentful import structure...'
         
     | 
| 
      
 29 
     | 
    
         
            +
                    File.open(converted_model_dir, 'w') { |file| file.write({}) }
         
     | 
| 
      
 30 
     | 
    
         
            +
                    content_type_file = JSON.parse(File.read(content_types))['items']
         
     | 
| 
      
 31 
     | 
    
         
            +
                    content_type_file.each do |content_type|
         
     | 
| 
      
 32 
     | 
    
         
            +
                      parsed_content_type = {
         
     | 
| 
      
 33 
     | 
    
         
            +
                          id: content_type['sys']['id'],
         
     | 
| 
      
 34 
     | 
    
         
            +
                          name: content_type['name'],
         
     | 
| 
      
 35 
     | 
    
         
            +
                          description: content_type['description'],
         
     | 
| 
      
 36 
     | 
    
         
            +
                          displayField: content_type['displayField'],
         
     | 
| 
      
 37 
     | 
    
         
            +
                          fields: create_content_type_fields(content_type)
         
     | 
| 
      
 38 
     | 
    
         
            +
                      }
         
     | 
| 
      
 39 
     | 
    
         
            +
                      import_form = JSON.parse(File.read(converted_model_dir))
         
     | 
| 
      
 40 
     | 
    
         
            +
                      File.open(converted_model_dir, 'w') do |file|
         
     | 
| 
      
 41 
     | 
    
         
            +
                        file.write(JSON.pretty_generate(import_form.merge!(content_type['name'] => parsed_content_type)))
         
     | 
| 
      
 42 
     | 
    
         
            +
                      end
         
     | 
| 
      
 43 
     | 
    
         
            +
                    end
         
     | 
| 
      
 44 
     | 
    
         
            +
                    logger.info "Done! Contentful import structure file saved in #{converted_model_dir}"
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
                  def create_content_type_fields(content_type)
         
     | 
| 
      
 48 
     | 
    
         
            +
                    content_type['fields'].each_with_object({}) do |(field, _value), results|
         
     | 
| 
      
 49 
     | 
    
         
            +
                      id = link_id(field)
         
     | 
| 
      
 50 
     | 
    
         
            +
                      results[id] = case field['type']
         
     | 
| 
      
 51 
     | 
    
         
            +
                                      when 'Link'
         
     | 
| 
      
 52 
     | 
    
         
            +
                                        {id: field['id'], type: field['linkType'], link: 'Link'}
         
     | 
| 
      
 53 
     | 
    
         
            +
                                      when 'Array'
         
     | 
| 
      
 54 
     | 
    
         
            +
                                        {id: field['id'], type: field['type'], link_type: field['items']['linkType'], link: field['items']['type']}
         
     | 
| 
      
 55 
     | 
    
         
            +
                                      else
         
     | 
| 
      
 56 
     | 
    
         
            +
                                        field['type']
         
     | 
| 
      
 57 
     | 
    
         
            +
                                    end
         
     | 
| 
      
 58 
     | 
    
         
            +
                    end
         
     | 
| 
      
 59 
     | 
    
         
            +
                  end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
                  def link_id(field)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    if FIELD_TYPE.include? field['type']
         
     | 
| 
      
 63 
     | 
    
         
            +
                      field['name'].capitalize
         
     | 
| 
      
 64 
     | 
    
         
            +
                    else
         
     | 
| 
      
 65 
     | 
    
         
            +
                      field['id']
         
     | 
| 
      
 66 
     | 
    
         
            +
                    end
         
     | 
| 
      
 67 
     | 
    
         
            +
                  end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                  def content_type_name(content_type)
         
     | 
| 
      
 70 
     | 
    
         
            +
                    I18n.transliterate(content_type).underscore.tr(' ', '_')
         
     | 
| 
      
 71 
     | 
    
         
            +
                  end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                  def create_directory(path)
         
     | 
| 
      
 74 
     | 
    
         
            +
                    FileUtils.mkdir_p(path) unless File.directory?(path)
         
     | 
| 
      
 75 
     | 
    
         
            +
                  end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                  # If contentful_structure JSON file exists, it will load the file. If not, it will automatically create an empty file.
         
     | 
| 
      
 78 
     | 
    
         
            +
                  # This file is required to convert contentful model to contentful import structure.
         
     | 
| 
      
 79 
     | 
    
         
            +
                  def load_contentful_structure_file
         
     | 
| 
      
 80 
     | 
    
         
            +
                    fail ArgumentError, 'Set PATH for contentful structure JSON file. View README' if config.config['contentful_structure_dir'].nil?
         
     | 
| 
      
 81 
     | 
    
         
            +
                    file_exists? ? load_existing_contentful_structure_file : create_empty_contentful_structure_file
         
     | 
| 
      
 82 
     | 
    
         
            +
                  end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                  def file_exists?
         
     | 
| 
      
 85 
     | 
    
         
            +
                    File.exists?(config.config['contentful_structure_dir'])
         
     | 
| 
      
 86 
     | 
    
         
            +
                  end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                  def create_empty_contentful_structure_file
         
     | 
| 
      
 89 
     | 
    
         
            +
                    File.open(config.config['contentful_structure_dir'], 'w') { |file| file.write({}) }
         
     | 
| 
      
 90 
     | 
    
         
            +
                    load_existing_contentful_structure_file
         
     | 
| 
      
 91 
     | 
    
         
            +
                  end
         
     | 
| 
      
 92 
     | 
    
         
            +
             
     | 
| 
      
 93 
     | 
    
         
            +
                  def load_existing_contentful_structure_file
         
     | 
| 
      
 94 
     | 
    
         
            +
                    JSON.parse(File.read(config.config['contentful_structure_dir']), symbolize_names: true).with_indifferent_access
         
     | 
| 
      
 95 
     | 
    
         
            +
                  end
         
     | 
| 
      
 96 
     | 
    
         
            +
             
     | 
| 
      
 97 
     | 
    
         
            +
                  def set_content_model_parameters
         
     | 
| 
      
 98 
     | 
    
         
            +
                    validate_content_model_files
         
     | 
| 
      
 99 
     | 
    
         
            +
                    @converted_model_dir = config.config['converted_model_dir']
         
     | 
| 
      
 100 
     | 
    
         
            +
                    @content_types = config.config['content_model_json']
         
     | 
| 
      
 101 
     | 
    
         
            +
                  end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
                  def validate_content_model_files
         
     | 
| 
      
 104 
     | 
    
         
            +
                    fail ArgumentError, 'Set PATH for content model JSON file. View README' if config.config['content_model_json'].nil?
         
     | 
| 
      
 105 
     | 
    
         
            +
                    fail ArgumentError, 'Set PATH where converted content model file will be saved. View README' if config.config['converted_model_dir'].nil?
         
     | 
| 
      
 106 
     | 
    
         
            +
                  end
         
     | 
| 
      
 107 
     | 
    
         
            +
                end
         
     | 
| 
      
 108 
     | 
    
         
            +
              end
         
     | 
| 
      
 109 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,151 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Contentful
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Exporter
         
     | 
| 
      
 3 
     | 
    
         
            +
                module Drupal
         
     | 
| 
      
 4 
     | 
    
         
            +
                  class ContentType
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                    attr_reader :exporter, :config, :type, :schema
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                    def initialize(exporter, config, type, schema)
         
     | 
| 
      
 9 
     | 
    
         
            +
                      @exporter = exporter
         
     | 
| 
      
 10 
     | 
    
         
            +
                      @config = config
         
     | 
| 
      
 11 
     | 
    
         
            +
                      @type = type
         
     | 
| 
      
 12 
     | 
    
         
            +
                      @schema = schema
         
     | 
| 
      
 13 
     | 
    
         
            +
                    end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                    def save_content_types_as_json
         
     | 
| 
      
 16 
     | 
    
         
            +
                      exporter.create_directory("#{config.entries_dir}/#{type}")
         
     | 
| 
      
 17 
     | 
    
         
            +
                      config.db[:node].where(type: type).each do |content_row|
         
     | 
| 
      
 18 
     | 
    
         
            +
                        extract_data(content_row)
         
     | 
| 
      
 19 
     | 
    
         
            +
                      end
         
     | 
| 
      
 20 
     | 
    
         
            +
                    end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    private
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                    def extract_data(content_row)
         
     | 
| 
      
 25 
     | 
    
         
            +
                      puts "Saving #{type} - id: #{content_row[:nid]}"
         
     | 
| 
      
 26 
     | 
    
         
            +
                      db_object = map_fields(content_row)
         
     | 
| 
      
 27 
     | 
    
         
            +
                      exporter.write_json_to_file("#{config.entries_dir}/#{type}/#{db_object[:id]}.json", db_object)
         
     | 
| 
      
 28 
     | 
    
         
            +
                    end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                    def map_fields(row, result = {})
         
     | 
| 
      
 31 
     | 
    
         
            +
                      result.merge!(set_default_data(row))
         
     | 
| 
      
 32 
     | 
    
         
            +
                      result.merge!(find_related_data(row))
         
     | 
| 
      
 33 
     | 
    
         
            +
                      result
         
     | 
| 
      
 34 
     | 
    
         
            +
                    end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                    def id(content_id)
         
     | 
| 
      
 37 
     | 
    
         
            +
                      "#{type}_#{content_id}"
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                    def author(user_id)
         
     | 
| 
      
 41 
     | 
    
         
            +
                      {type: 'Author', id: "user_#{user_id}"}
         
     | 
| 
      
 42 
     | 
    
         
            +
                    end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                    def tags(entity_row_id)
         
     | 
| 
      
 45 
     | 
    
         
            +
                      entity_tags(entity_row_id).each_with_object([]) do |tag, tags|
         
     | 
| 
      
 46 
     | 
    
         
            +
                        linked_tag = {type: 'EntryTag', id: "tag_#{tag[:field_tags_tid]}"}
         
     | 
| 
      
 47 
     | 
    
         
            +
                        tags << linked_tag
         
     | 
| 
      
 48 
     | 
    
         
            +
                      end
         
     | 
| 
      
 49 
     | 
    
         
            +
                    end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                    def entity_tags(entity_id)
         
     | 
| 
      
 52 
     | 
    
         
            +
                      config.db[:field_data_field_tags].where(entity_id: entity_id)
         
     | 
| 
      
 53 
     | 
    
         
            +
                    end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                    def set_default_data(row, result = {})
         
     | 
| 
      
 56 
     | 
    
         
            +
                      result[:id] = id(row[:nid])
         
     | 
| 
      
 57 
     | 
    
         
            +
                      result[:title] = row[:title]
         
     | 
| 
      
 58 
     | 
    
         
            +
                      result[:author] = author(row[:uid])
         
     | 
| 
      
 59 
     | 
    
         
            +
                      result[:tags] = tags(row[:nid]) unless tags(row[:nid]).empty?
         
     | 
| 
      
 60 
     | 
    
         
            +
                      result[:created_at] = created_at(row[:created])
         
     | 
| 
      
 61 
     | 
    
         
            +
                      result
         
     | 
| 
      
 62 
     | 
    
         
            +
                    end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                    def find_related_data(row, result = {})
         
     | 
| 
      
 65 
     | 
    
         
            +
                      schema.each do |key, column_name|
         
     | 
| 
      
 66 
     | 
    
         
            +
                        result[key] = column_name.is_a?(String) ? fetch_data_from_related_table(row[:nid], column_name) : fetch_custom_tags(row[:nid], column_name)
         
     | 
| 
      
 67 
     | 
    
         
            +
                      end
         
     | 
| 
      
 68 
     | 
    
         
            +
                      result
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                    def fetch_data_from_related_table(entity_id, table_name)
         
     | 
| 
      
 72 
     | 
    
         
            +
                      related_row = get_related_row(entity_id, table_name)
         
     | 
| 
      
 73 
     | 
    
         
            +
                      fetch_data_from_related_row(related_row, table_name)
         
     | 
| 
      
 74 
     | 
    
         
            +
                    end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                    def fetch_data_from_related_row(related_row, table_name)
         
     | 
| 
      
 77 
     | 
    
         
            +
                      respond_to_file?(related_row, table_name) ? get_file_id(related_row, table_name) : related_value(related_row, table_name)
         
     | 
| 
      
 78 
     | 
    
         
            +
                    end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                    def respond_to_file?(related_row, table_name)
         
     | 
| 
      
 81 
     | 
    
         
            +
                      file_id = "#{table_name}_fid".to_sym
         
     | 
| 
      
 82 
     | 
    
         
            +
                      (related_row.present? && related_row.first[file_id]) ? true : false
         
     | 
| 
      
 83 
     | 
    
         
            +
                    end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                    def get_file_id(related_row, table_name)
         
     | 
| 
      
 86 
     | 
    
         
            +
                      file_key = "#{table_name}_fid".to_sym
         
     | 
| 
      
 87 
     | 
    
         
            +
                      file_id = related_row.first[file_key]
         
     | 
| 
      
 88 
     | 
    
         
            +
                      file_asset_id = file_id(file_id)
         
     | 
| 
      
 89 
     | 
    
         
            +
                      link_asset_to_content_type(file_asset_id)
         
     | 
| 
      
 90 
     | 
    
         
            +
                    end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                    def file_id(file_id)
         
     | 
| 
      
 93 
     | 
    
         
            +
                      config.db[:file_managed].where(fid: file_id).first[:fid]
         
     | 
| 
      
 94 
     | 
    
         
            +
                    end
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                    def get_related_row(entity_id, table_name)
         
     | 
| 
      
 97 
     | 
    
         
            +
                      config.db[related_table_name(table_name)].where(entity_id: entity_id)
         
     | 
| 
      
 98 
     | 
    
         
            +
                    end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
                    def link_asset_to_content_type(file_asset_id)
         
     | 
| 
      
 101 
     | 
    
         
            +
                      {type: 'File', id: "file_#{file_asset_id}"}
         
     | 
| 
      
 102 
     | 
    
         
            +
                    end
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                    def related_value(related_rows, table_name)
         
     | 
| 
      
 105 
     | 
    
         
            +
                      value = related_rows.empty? ? nil : related_rows.first[field_name(table_name)]
         
     | 
| 
      
 106 
     | 
    
         
            +
                      convert_type_value(value, table_name)
         
     | 
| 
      
 107 
     | 
    
         
            +
                    end
         
     | 
| 
      
 108 
     | 
    
         
            +
             
     | 
| 
      
 109 
     | 
    
         
            +
                    def fetch_custom_tags(entity_id, table_name)
         
     | 
| 
      
 110 
     | 
    
         
            +
                      custom_tag_table = "field_data_#{table_name['table']}".to_sym
         
     | 
| 
      
 111 
     | 
    
         
            +
                      tag_id = "#{table_name['table']}_tid".to_sym
         
     | 
| 
      
 112 
     | 
    
         
            +
                      config.db[custom_tag_table].where(entity_id: entity_id).each_with_object([]) do |content_tag, tags|
         
     | 
| 
      
 113 
     | 
    
         
            +
                        lined_tags = {type: 'EntryTag', id: "tag_#{content_tag[tag_id]}"}
         
     | 
| 
      
 114 
     | 
    
         
            +
                        tags << lined_tags
         
     | 
| 
      
 115 
     | 
    
         
            +
                      end
         
     | 
| 
      
 116 
     | 
    
         
            +
                    end
         
     | 
| 
      
 117 
     | 
    
         
            +
             
     | 
| 
      
 118 
     | 
    
         
            +
                    def related_table_name(table_name)
         
     | 
| 
      
 119 
     | 
    
         
            +
                      "field_data_#{table_name}".to_sym
         
     | 
| 
      
 120 
     | 
    
         
            +
                    end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                    def field_name(table_name)
         
     | 
| 
      
 123 
     | 
    
         
            +
                      "#{table_name}_value".to_sym
         
     | 
| 
      
 124 
     | 
    
         
            +
                    end
         
     | 
| 
      
 125 
     | 
    
         
            +
             
     | 
| 
      
 126 
     | 
    
         
            +
                    def created_at(timestamp)
         
     | 
| 
      
 127 
     | 
    
         
            +
                      Time.at(timestamp).to_datetime
         
     | 
| 
      
 128 
     | 
    
         
            +
                    end
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
                    def convert_type_value(value, column_name)
         
     | 
| 
      
 131 
     | 
    
         
            +
                      if value.is_a?(BigDecimal)
         
     | 
| 
      
 132 
     | 
    
         
            +
                        value.to_f
         
     | 
| 
      
 133 
     | 
    
         
            +
                      elsif boolean_column?(column_name)
         
     | 
| 
      
 134 
     | 
    
         
            +
                        convert_boolean_value(value)
         
     | 
| 
      
 135 
     | 
    
         
            +
                      else
         
     | 
| 
      
 136 
     | 
    
         
            +
                        value
         
     | 
| 
      
 137 
     | 
    
         
            +
                      end
         
     | 
| 
      
 138 
     | 
    
         
            +
                    end
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
                    def boolean_column?(column_name)
         
     | 
| 
      
 141 
     | 
    
         
            +
                      exporter.boolean_columns && exporter.boolean_columns.flatten.include?(column_name) ? true : false
         
     | 
| 
      
 142 
     | 
    
         
            +
                    end
         
     | 
| 
      
 143 
     | 
    
         
            +
             
     | 
| 
      
 144 
     | 
    
         
            +
                    def convert_boolean_value(value)
         
     | 
| 
      
 145 
     | 
    
         
            +
                      value.nil? ? nil : (value == 1 ? true : false)
         
     | 
| 
      
 146 
     | 
    
         
            +
                    end
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                  end
         
     | 
| 
      
 149 
     | 
    
         
            +
                end
         
     | 
| 
      
 150 
     | 
    
         
            +
              end
         
     | 
| 
      
 151 
     | 
    
         
            +
            end
         
     |