text:
type: post
layout: post
title: My Reading Workflow
eye_catch: https://storage.buzzsprout.com/variants/nbhDW1yUwySC4G5zppbj8W2r/8d66eb17bb7d02ca4856ab443a78f2148cafbb129f58a3c81282007c6fe24ff2?.jpg
tags:
- agile-chuck-wagon
- reading
- fiction
- nonfiction
comments: true
categories:
- professional
- podcast
status: publish
published: true
meta:
_edit_last: "1"
---

### Agile Chuck Wagon, season 8, episode 16

For the last episode of season 8, I did not record a retrospective due to the hiatus. Instead, I talked about my personal reading workflow. It's enabled me to read over a book a week.

Photo by [Thought Catalog](https://unsplash.com/@thoughtcatalog?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/s/photos/reading?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) (length: 7 min)


text:
(function () {"use strict";})();
/**
 * Created by apizzimenti on 6/23/16.
 */

/**
 * @author Anthony Pizzimenti
 *
 * @desc Ninboy Item class.
 *
 * @param game {object} Current game instance.
 * @param key {string} Cached Phaser texture key.
 * @param inventory {Inventory} Game's Inventory instance.
 *
 * @class {object} Ninboy
 * @extends Item
 * @constructor
 */

function Ninboy (game, key, inventory) {
    Item.call(this, game, key, inventory);
}

Ninboy.prototype = Object.create(Item.prototype);

redpajama_set_name: RedPajamaGithub


text:
<?php

/**
 * @file
 * Contains \Drupal\content_translation\ContentTranslationPermissions.
 */

namespace Drupal\content_translation;

use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Provides dynamic permissions for the content_translation module.
 */
class ContentTranslationPermissions implements ContainerInjectionInterface {

  use StringTranslationTrait;

  /**
   * The entity manager.
   *
   * @var \Drupal\Core\Entity\EntityManagerInterface
   */
  protected $entityManager;

  /**
   * The content translation manager.
   *
   * @var \Drupal\content_translation\ContentTranslationManagerInterface
   */
  protected $contentTranslationManager;

  /**
   * Constructs a ContentTranslationPermissions instance.
   *
   * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
   *   The entity manager.
   * @param \Drupal\content_translation\ContentTranslationManagerInterface $content_translation_manager
   *   The content translation manager.
   */
  public function __construct(EntityManagerInterface $entity_manager, ContentTranslationManagerInterface $content_translation_manager) {
    $this->entityManager = $entity_manager;
    $this->contentTranslationManager = $content_translation_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('entity.manager'),
      $container->get('content_translation.manager')
    );
  }

  /**
   * Returns an array of content translation permissions.
   *
   * @return array
   */
  public function contentPermissions() {
    $permission = [];
    // Create a translate permission for each enabled entity type and (optionally)
    // bundle.
    foreach ($this->entityManager->getDefinitions() as $entity_type_id => $entity_type) {
      if ($permission_granularity = $entity_type->getPermissionGranularity()) {
        $t_args = ['@entity_label' => $entity_type->getLowercaseLabel()];

        switch ($permission_granularity) {
          case 'bundle':
            foreach ($this->entityManager->getBundleInfo($entity_type_id) as $bundle => $bundle_info) {
              if ($this->contentTranslationManager->isEnabled($entity_type_id, $bundle)) {
                $t_args['%bundle_label'] = isset($bundle_info['label']) ? $bundle_info['label'] : $bundle;
                $permission["translate $bundle $entity_type_id"] = [
                  'title' => $this->t('Translate %bundle_label @entity_label', $t_args),
                ];
              }
            }
            break;

          case 'entity_type':
            if ($this->contentTranslationManager->isEnabled($entity_type_id)) {
              $permission["translate $entity_type_id"] = [
                'title' => $this->t('Translate @entity_label', $t_args),
              ];
            }
            break;
        }
      }
    }

    return $permission;
  }

}


text:
System.register(['aurelia-dependency-injection', 'aurelia-templating', '../common/widget-base', '../common/decorators', '../common/constants', '../common/options-builder', '../common/template-gatherer', '../pdf/pdf'], function (_export, _context) {
  "use strict";

  var inject, Container, customElement, WidgetBase, generateBindables, constants, OptionsBuilder, TemplateGatherer, PDF, _dec, _dec2, _dec3, _class, Grid;

  function _classCallCheck(instance, Constructor) {
    if (!(instance instanceof Constructor)) {
      throw new TypeError("Cannot call a class as a function");
    }
  }

  function isInitFromTable(element) {
    return element.children.length > 0 && element.children[0].nodeName === 'TABLE';
  }

  function isInitFromDiv(element) {
    return element.querySelectorAll('div').length > 0;
  }
  return {
    setters: [function (_aureliaDependencyInjection) {
      inject = _aureliaDependencyInjection.inject;
      Container = _aureliaDependencyInjection.Container;
    }, function (_aureliaTemplating) {
      customElement = _aureliaTemplating.customElement;
    }, function (_commonWidgetBase) {
      WidgetBase = _commonWidgetBase.WidgetBase;
    }, function (_commonDecorators) {
      generateBindables = _commonDecorators.generateBindables;
    }, function (_commonConstants) {
      constants = _commonConstants.constants;
    }, function (_commonOptionsBuilder) {
      OptionsBuilder = _commonOptionsBuilder.OptionsBuilder;
    }, function (_commonTemplateGatherer) {
      TemplateGatherer = _commonTemplateGatherer.TemplateGatherer;
    }, function (_pdfPdf) {
      PDF = _pdfPdf.PDF;
    }],
    execute: function () {
      _export('Grid', Grid = (_dec = customElement(constants.elementPrefix + 'grid'), _dec2 = generateBindables('kendoGrid'), _dec3 = inject(Element, WidgetBase, Container, OptionsBuilder, TemplateGatherer), _dec(_class = _dec2(_class = _dec3(_class = function () {
        function Grid(element, widgetBase, container, optionsBuilder, templateGatherer) {
          var _this = this;

          _classCallCheck(this, Grid);

          this.element = element;
          this.templateGatherer = templateGatherer;
          this.optionsBuilder = optionsBuilder;
          this.widgetBase = widgetBase.control('kendoGrid').useRootElement(this.element).beforeInitialize(function (options) {
            return _this._beforeInitialize(options);
          }).linkViewModel(this).useContainer(container);
        }

        Grid.prototype.subscribe = function subscribe(event, callback) {
          return this.widgetBase.subscribe(event, callback);
        };

        Grid.prototype.bind = function bind(ctx, overrideCtx) {
          this.widgetBase.useParentCtx(overrideCtx);
        };

        Grid.prototype.attached = function attached() {
          if (isInitFromDiv(this.element)) {
            this.widgetBase.useElement(this.element.querySelectorAll('div')[0]);
          } else if (isInitFromTable(this.element)) {
            this.widgetBase.useElement(this.element.children[0]);
          } else {
            var target = document.createElement('div');
            this.element.appendChild(target);
            this.widgetBase.useElement(target);
          }

          if (!this.kNoInit) {
            this.recreate();
          }
        };

        Grid.prototype.recreate = function recreate() {
          var templates = this.widgetBase.util.getChildrenVMs(this.element, constants.elementPrefix + 'template');
          this.templateGatherer.useTemplates(this, 'kendoGrid', templates);

          this.kWidget = this.widgetBase.recreate();
        };

        Grid.prototype._beforeInitialize = function _beforeInitialize(options) {
          var _this2 = this;

          var columns = this.widgetBase.util.getChildrenVMs(this.element, constants.elementPrefix + 'col');
          var gridToolbars = this.widgetBase.util.getChildrenVMs(this.element, constants.elementPrefix + 'grid-toolbar');

          if (columns && columns.length > 0) {
            options.columns = [];

            columns.forEach(function (column) {
              options.columns.push(_this2.optionsBuilder.getOptions(column, 'GridColumn'));
            });
          }

          if (gridToolbars && gridToolbars.length > 0) {
            var toolbar = gridToolbars[0];
            var o = this.optionsBuilder.getOptions(toolbar, 'GridToolbarItem');
            if (o.template) {
              options.toolbar = o.template;
            } else {
              options.toolbar = o;
            }
          }
        };

        Grid.prototype.destroy = function destroy() {
          this.widgetBase.destroy(this.kWidget);
        };

        Grid.prototype.detached = function detached() {
          this.destroy();
        };

        return Grid;
      }()) || _class) || _class) || _class));

      _export('Grid', Grid);
    }
  };
});
//# sourceMappingURL=../dist/dev/grid/grid.js.map


text:
package com.dogecoindark.dogecoindarkj.core;

import com.dogecoindark.dogecoindarkj.testing.FooWalletExtension;
import com.dogecoindark.dogecoindarkj.testing.TestWithWallet;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class WalletExtensionsTest extends TestWithWallet {

    @Before
    @Override
    public void setUp() throws Exception {
        super.setUp();
    }

    @After
    @Override
    public void tearDown() throws Exception {
        super.tearDown();
    }

    @Test(expected = java.lang.IllegalStateException.class)
    public void duplicateWalletExtensionTest() {
        wallet.addExtension(new FooWalletExtension("com.whatever.required", true));
        wallet.addExtension(new FooWalletExtension("com.whatever.required", true));
    }
}


text:
crm configure primitive RabbitMon ocf:rabbitmq:rabbit-monitor \
params servicemq="'service rabbitmq-server'" \
log_base="/var/log/rabbitmq" \
op monitor interval="10s" timeout="20s" \
op start interval="0" timeout="30" \
op stop interval="0" timeout="30" \

crm_resource --meta --resource RabbitMon --set-parameter migration-threshold -v 1
crm_resource --meta --resource RabbitMon --set-parameter failure-timeout -v 0
crm_resource --meta --resource RabbitMon --set-parameter resource-stickiness -v 100

crm configure order ClusterMon-after-RabbitMon inf: RabbitMon ClusterMon
crm configure order RabbitMon-after-ClusterIP inf: RabbitMon ClusterIP
crm configure colocation ClusterIP-RabbitMon-ClusterMon-col inf: RabbitMon ClusterIP ClusterMon


text:
unless Proc.method_defined? :lambda?
  require 'backports/tools/alias_method_chain'

  class Proc
    # Standard in Ruby 1.9. See official documentation[http://ruby-doc.org/core-1.9/classes/Proc.html]
    def lambda?
      !!__is_lambda__
    end

    attr_accessor :__is_lambda__
    private :__is_lambda__
    private :__is_lambda__=
  end

  class Method
    def to_proc_with_lambda_tracking
      proc = to_proc_without_lambda_tracking
      proc.send :__is_lambda__=, true
      proc
    end
    Backports.alias_method_chain self, :to_proc, :lambda_tracking
  end

  module Kernel
    def lambda_with_lambda_tracking(&block)
      l = lambda_without_lambda_tracking(&block)
      l.send :__is_lambda__=, true unless block.send(:__is_lambda__) == false
      l
    end

    def proc_with_lambda_tracking(&block)
      l = proc_without_lambda_tracking(&block)
      l.send :__is_lambda__=, block.send(:__is_lambda__) == true
      l
    end

    Backports.alias_method_chain self, :lambda, :lambda_tracking
    Backports.alias_method_chain self, :proc, :lambda_tracking
  end
end


text:
class CreatePictures < ActiveRecord::Migration
  def change
    create_table :pictures do |t|
      t.references :imageable, polymorphic: true, index: true
      t.timestamps null: false
    end
  end
end


text:
SET gp_create_table_random_default_distribution=off;
-- end_ignore
DROP TABLE IF EXISTS reindex_drop_ao_bitmap;

CREATE TABLE reindex_drop_ao_bitmap (a INT) WITH (appendonly=true);
insert into reindex_drop_ao_bitmap select generate_series(1,1000);
insert into reindex_drop_ao_bitmap select generate_series(1,1000);
create index idx_reindex_drop_ao_bitmap on reindex_drop_ao_bitmap USING bitmap(a);
SELECT 1 AS relfilenode_same_on_all_segs from gp_dist_random('pg_class')   WHERE relname = 'idx_reindex_drop_ao_bitmap' GROUP BY relfilenode having count(*) = (SELECT count(*) FROM     gp_segment_configuration WHERE role='p' AND content > -1);


text:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
#if UNITY_EDITOR
using UnityEditor;
#endif

public abstract class GameEvent : BaseRuleElement
{
	[HideInInspector]
	public Actor Actor;

	#region Reaction Handling
	private List<Reaction> triggeredReactions = new List<Reaction>();

	public void Register(Reaction newReaction)
	{
		if (!triggeredReactions.Contains(newReaction))
		{
			triggeredReactions.Add(newReaction);
		}
	}

	public void Unregister(Reaction oldReaction)
	{
		triggeredReactions.Remove(oldReaction);
	}
	#endregion

	//#region Condition Handling
	//private List<GameEventCondition> conditions = new List<GameEventCondition>();
	//public void AddCondition(GameEventCondition condition)
	//{
	//	if (!conditions.Contains(condition))
	//		conditions.Add(condition);
	//}
	//public void RemoveCondition(GameEventCondition condition)
	//{
	//	conditions.Remove(condition);
	//}
	//public bool ConditionsMet()
	//{
	//	foreach (GameEventCondition c in conditions)
	//	{
	//		if (!c.IsTrue)
	//			return false;
	//	}
	//	return true;
	//}
	//#endregion

	public override RuleData GetRuleInformation()
	{
		return new EventData()
		{
			id = Id,
			actorId = Actor.Id,
			type = this.GetType(),
			label = this.GetType().ToString(),
			OnShowGui = ShowGui
		};
	}

	public abstract GameEvent UpdateEvent();

	/// <summary>
	/// Trigger the event
	/// </summary>
	/// <param name="data">fill in event data</param>
	/// <returns>true once all reactions were executed, false if conditions aren't met</returns>
	public bool Trigger(GameEventData data)
	{
		//if (!ConditionsMet()) return false;

		for (int i = 0; i < triggeredReactions.Count; i++ )
		{
			if (triggeredReactions[i] != null)
			{
#if UNITY_EDITOR
				EditorGUIUtility.PingObject(Actor.gameObject);
				EditorGUIUtility.PingObject(gameObject);
#endif
				triggeredReactions[i].Execute(data);
			}
		}

		return true;
	}
}


text:
import ServerBase from './ServerBase';
import fs from 'fs';
import spdy from 'spdy';

class H2 extends ServerBase {

  createServer() {
    // Read in the certs
    const opts = this.server.options;
    opts.key = fs.readFileSync( opts.key );
    opts.cert = fs.readFileSync( opts.cert );

    return spdy.createServer(opts, this.app);
  }

}

export default H2;


text:
#ifndef FFI_COMMON_H
#define FFI_COMMON_H

#ifdef __cplusplus
extern "C" {
#endif

#include <fficonfig.h>
#include <malloc.h>

/* Check for the existence of memcpy. */
#if STDC_HEADERS
# include <string.h>
#else
# ifndef HAVE_MEMCPY
#  define memcpy(d, s, n) bcopy ((s), (d), (n))
# endif
#endif

#if defined(FFI_DEBUG)
#include <stdio.h>
#endif

#ifdef FFI_DEBUG
/*@exits@*/ void ffi_assert(/*@temp@*/ char *expr, /*@temp@*/ char *file, int line);
void ffi_stop_here(void);
void ffi_type_test(/*@temp@*/ /*@out@*/ ffi_type *a, /*@temp@*/ char *file, int line);

#define FFI_ASSERT(x) ((x) ? (void)0 : ffi_assert(#x, __FILE__,__LINE__))
#define FFI_ASSERT_AT(x, f, l) ((x) ? 0 : ffi_assert(#x, (f), (l)))
#define FFI_ASSERT_VALID_TYPE(x) ffi_type_test (x, __FILE__, __LINE__)
#else
#define FFI_ASSERT(x)
#define FFI_ASSERT_AT(x, f, l)
#define FFI_ASSERT_VALID_TYPE(x)
#endif

#define ALIGN(v, a)  (((((size_t) (v))-1) | ((a)-1))+1)

/* Perform machine dependent cif processing */
ffi_status ffi_prep_cif_machdep(ffi_cif *cif);

/* Extended cif, used in callback from assembly routine */
typedef struct
{
  /*@dependent@*/ ffi_cif *cif;
  /*@dependent@*/ void *rvalue;
  /*@dependent@*/ void **avalue;
} extended_cif;

/* Terse sized type definitions.  */
/* Fix for PyPy: these names are fine, but are bound to conflict with
 * some other name from somewhere else :-(  Added a 'ffi_' prefix. */
typedef unsigned int ffi_UINT8  __attribute__((__mode__(__QI__)));
typedef signed int   ffi_SINT8  __attribute__((__mode__(__QI__)));
typedef unsigned int ffi_UINT16 __attribute__((__mode__(__HI__)));
typedef signed int   ffi_SINT16 __attribute__((__mode__(__HI__)));
typedef unsigned int ffi_UINT32 __attribute__((__mode__(__SI__)));
typedef signed int   ffi_SINT32 __attribute__((__mode__(__SI__)));
typedef unsigned int ffi_UINT64 __attribute__((__mode__(__DI__)));
typedef signed int   ffi_SINT64 __attribute__((__mode__(__DI__)));

typedef float ffi_FLOAT32;

#ifdef __cplusplus
}
#endif

#endif


text:
/* jshint expr:true */

process.env.NODE_ENV = 'test';

var app = require('./../app');
var Comment = require('./../models/comment');
var expect = require('chai').expect;
var request = require('supertest');
var mongoose = require('mongoose');
var clearDB = require('mocha-mongoose')(app.get('db'), {noClear: true});

describe('comment resource', function() {

  before(function(done) {
    if (mongoose.connection.db) {
      return done();
    }
    mongoose.connect(app.get('db'), done);
  });

  before(function(done) {
    clearDB(done);
  });

  describe('GET /:domain/:resource/comments', function() {
    it('list all comments related to a :reference in a :domain', function(done) {
      Comment.create(
        {domain: 'example.com', reference: 42, author: 'gabriele.lana@example.com', text: '42'},
        function(err, comment) {
          expect(err).to.be.null;
          request(app).get('/example.com/42/comments')
            .expect('Content-Type', /json/)
            .expect(200, JSON.stringify([comment]))
            .end(done);
        }
      );
    });

    it('fails with 403 when request comes from wrong domain', function(done) {
      request(app).get('/example.com/42/comments')
        .set('Host', 'evil.com')
        .expect(403)
        .end(done);
    });
  });

  describe('POST /:domain/:resource/comments', function() {
    it('adds a comment to a :reference in a :domain', function(done) {
      request(app).post('/example.com/42/comments')
        .send({text: 'some text', author: 'gabriele.lana@example.com'})
        .expect(201)
        .expect('Content-Type', /json/)
        .expect('Location', /\/example.com\/42\/comments\/[0-9a-f]+/)
        .end(function(err, res) {
          if (err) {
            throw err;
          }
          Comment.findOne({_id: JSON.parse(res.text).id}, function(err, comment) {
            expect(err).to.be.null;
            expect(comment).to.be.an.instanceof(Comment);
            done();
          });
        });
    });

    it('fails with 400 when text is missing', function(done) {
      request(app).post('/example.com/42/comments')
        .send({author: 'gabriele.lana@example.com'})
        .expect(400)
        .end(done);
    });

    it('fails with 403 when request comes from wrong domain', function(done) {
      request(app).post('/example.com/42/comments')
        .send({text: 'some text', author: 'gabriele.lana@example.com'})
        .set('Host', 'evil.com')
        .expect(403)
        .end(done);
    });
  });
});


text:
package org.appng.cli.commands.subject;

import org.appng.api.BusinessException;
import org.appng.api.model.Subject;
import org.appng.cli.CliEnvironment;
import org.appng.cli.ExecutableCliCommand;

import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;

/**
 * Deletes a subject.

 *
 *

 * Usage: appng delete-subject [options]
 *   Options:
 *   * -n
 *        The subject name.
 *

 *
 * @author Matthias Herlitzius
 */
@Parameters(commandDescription = "Deletes a subject.")
public class DeleteSubject implements ExecutableCliCommand {

	@Parameter(names = "-n", required = true, description = "The subject name.")
	private String subjectName;

	public DeleteSubject() {
	}

	public DeleteSubject(String subjectName) {
		this.subjectName = subjectName;
	}

	public void execute(CliEnvironment cle) throws BusinessException {

		Subject subject = cle.getCoreService().getSubjectByName(subjectName, false);

		if (null != subject) {
			cle.getCoreService().deleteSubject(subject);
		} else {
			throw new BusinessException("Subject not found: " + subjectName);
		}

	}

}


text:
<?php

/**
 * @deprecated after 1.5.0.1
 */
class Mage_Catalog_Model_Mysql4_Convert
{
    protected $_productsBySku;
    protected $_productEntity;
    protected $_skuAttribute;

    public function getConnection()
    {
        return Mage::getSingleton('core/resource')->getConnection('catalog_write');
    }

    public function getSelect()
    {
        return $this->getConnection()->select();
    }

    public function getTable($table)
    {
        return Mage::getSingleton('core/resource')->getTableName($table);
    }

    public function getProductEntity($field=null)
    {
        if (!$this->_productEntity) {
            $this->_productEntity = Mage::getResourceModel('catalog/product')
                ->loadAllAttributes();
        }
        return is_null($field) ? $this->_productEntity : $this->_productEntity->getData($field);
    }

    public function getSkuAttribute($field='attribute_id')
    {
        if (!$this->_skuAttribute) {
            $this->_skuAttribute = $this->getProductEntity()->getAttribute('sku');
        }
        return $this->_skuAttribute->getData($field);
    }

    public function getProductIdBySku($sku)
    {
        if (!$this->_productsBySku) {
            $select = $this->getSelect()
                ->from($this->getTable('catalog/product'), array('entity_id', 'sku'));
            $products = $this->getConnection()->fetchAll($select);

            $this->_productsBySku = array();
            foreach ($products as $p) {
                $this->_productsBySku[$p['sku']] = $p['entity_id'];
            }
        }
        return isset($this->_productsBySku[$sku]) ? $this->_productsBySku[$sku] : false;
    }

    public function addProductToStore($productId, $storeId)
    {
        $write = $this->getConnection();
        $table = $this->getTable('catalog/product_store');
        try {
            if (!$write->fetchOne("select * from $table where product_id=".(int)$productId." and store_id=".(int)$storeId)) {
               $write->query("insert into $table (product_id, store_id) values (".(int)$productId.",".(int)$storeId.")");
            }
        } catch (Exception $e) {
            throw $e;
        }
        return $this;
    }

    public function exportAttributes()
    {
        $attributeFields = array(
            'attribute_code',
            'frontend_label', 'frontend_input', 'frontend_class', 'frontend_model',
            'backend_type', 'backend_table', 'backend_model',
            'source_model', 'attribute_model',
            'is_visible', 'is_user_defined', 'is_global', 'is_required', 'is_unique',
            'is_visible_on_front', 'is_searchable', 'is_filterable', 'is_comparable',
            'default_value', 'apply_to', 'use_in_super_product',
        );

        $select = $this->getSelect()
            ->from(array('et'=>$this->getTable('eav/entity_type')), 'entity_type_code')
            ->join(array('a'=>$this->getTable('eav/attribute')), 'a.entity_type_id=et.entity_type_id', $attributeFields)
            ->where('et.entity_type_code in (?)', array('catalog_product', 'catalog_category'))
            ->order('if(not a.is_user_defined, 1, 2)')->order('attribute_code');

        $attributes = $this->getConnection()->fetchAll($select);

        return $attributes;
    }

    public function exportAttributeSets()
    {
        $select = $this->getSelect()
            ->from(array('et'=>$this->getTable('eav/entity_type')), 'entity_type_code')
            ->join(array('s'=>$this->getTable('eav/attribute_set')), 's.entity_type_id=et.entity_type_id', 'attribute_set_name')
            ->join(array('g'=>$this->getTable('eav/attribute_group')), 'g.attribute_set_id=s.attribute_set_id', 'attribute_group_name')
            ->join(array('ea'=>$this->getTable('eav/entity_attribute')), 'ea.attribute_group_id=g.attribute_group_id', array())
            ->join(array('a'=>$this->getTable('eav/attribute')), 'a.attribute_id=ea.attribute_id', 'attribute_code')
            ->where('et.entity_type_code in (?)', array('catalog_product', 'catalog_category'))
            ->order('et.entity_type_code')->order('s.sort_order')->order('g.sort_order');

        $sets = $this->getConnection()->fetchAll($select);

        return $sets;
    }

    public function exportAttributeOptions()
    {
        $select = $this->getSelect()
            ->from(array('et'=>$this->getTable('eav/entity_type')), 'entity_type_code')
            ->join(array('a'=>$this->getTable('eav/attribute')), 'a.entity_type_id=et.entity_type_id', 'attribute_code')
            ->join(array('ao'=>$this->getTable('eav/attribute_option')), 'ao.attribute_id=a.attribute_id', array())
            ->where('et.entity_type_code in (?)', array('catalog_product', 'catalog_category'))
            ->order('a.attribute_code')->order('ao.sort_order');

        $stores = Mage::getConfig()->getNode('stores')->children();
        foreach ($stores as $storeName=>$storeConfig) {
            $select->joinLeft(
                array($storeName=>$this->getTable('eav/attribute_option_value')),
                "$storeName.option_id=ao.option_id and $storeName.store_id=".$storeConfig->descend('system/store/id'),
                array($storeName=>"$storeName.value")
            );
        }

        $options = $this->getConnection()->fetchAll($select);

        return $options;
    }

    public function exportProductLinks()
    {
        $skuTable = $this->getTable('catalog/product').'_'.$this->getSkuAttribute('backend_type');
        $skuCond = ' and sku.store_id=0 and sku.attribute_id='.$this->getSkuAttribute('attribute_id');

        $select = $this->getSelect()
            ->from(array('lt'=>$this->getTable('catalog/product_link_type')), array('link_type'=>'code'))
            ->join(array('l'=>$this->getTable('catalog/product_link')), 'l.link_type_id=lt.link_type_id', array())
            ->join(array('sku'=>$skuTable), 'sku.entity_id=l.product_id'.$skuCond, array('sku'=>'value'))
            ->join(array('linked'=>$skuTable), 'linked.entity_id=l.product_id'.$skuCond, array('linked'=>'value'))
            ->order('sku')->order('link_type');
        $links = $this->getConnection()->fetchAll($select);

        return $links;
    }

    public function exportProductsInCategories()
    {
        $skuTable = $this->getTable('catalog/product').'_'.$this->getSkuAttribute('backend_type');
        $skuCond = ' and sku.store_id=0 and sku.attribute_id='.$this->getSkuAttribute('attribute_id');

        $select = $this->getSelect()
            ->from(array('cp'=>$this->getTable('catalog/category_product')), array('category_id', 'position'))
            ->join(array('sku'=>$skuTable), 'sku.entity_id=cp.product_id'.$skuCond, array('sku'=>'value'))
            ->order('category_id')->order('position')->order('sku');

        $prodCats = $this->getConnection()->fetchAll($select);

        return $prodCats;
    }

    public function exportProductsInStores()
    {
        $skuTable = $this->getTable('catalog/product').'_'.$this->getSkuAttribute('backend_type');
        $skuCond = ' and sku.store_id=0 and sku.attribute_id='.$this->getSkuAttribute('attribute_id');

        $select = $this->getSelect()
            ->from(array('ps'=>$this->getTable('catalog/product_store')), array())
            ->join(array('s'=>$this->getTable('core/store')), 's.store_id=ps.store_id', array('store'=>'code'))
            ->join(array('sku'=>$skuTable), 'sku.entity_id=ps.product_id'.$skuCond, array('sku'=>'value'))
            ->order('store')->order('sku');

        $prodStores = $this->getConnection()->fetchAll($select);

        return $prodStores;
    }

    public function exportCategories()
    {
        $collection = Mage::getResourceModel('catalog/category_collection')
            ->addAttributeToSelect('*')
            ->load();

        $categories = array();
        foreach ($collection as $object) {
            $row = $object->getData();
            $categories[] = $row;
        }

        return $categories;
    }

    public function exportProducts()
    {
        $attrSets = Mage::getResourceModel('eav/entity_attribute_set_collection')->load();
        $attrSetName = array();
        foreach ($attrSets as $attrSet) {
            $attrSetName[$attrSet->getId()] = $attrSet->getAttributeSetName();
        }

        $select = $this->getSelect()
            ->from(array('ao'=>$this->getTable('eav/attribute_option')), array('attribute_id', 'option_id'))
            ->join(array('aov'=>$this->getTable('eav/attribute_option_value')), 'aov.option_id=ao.option_id', array('value_id', 'value'))
            ->where('aov.store_id=0');

        $collection = Mage::getResourceModel('catalog/product_collection')
            ->addAttributeToSelect('*')
            ->load();

        $products = array();
        foreach ($collection as $object) {
            $r = $object->getData();

            unset($r['entity_id'], $r['entity_type_id']);
            $r['attribute_set_id'] = $attrSetName[$r['attribute_set_id']];

            $products[] = $r;
        }

        return $products;
    }

    public function exportImageGallery()
    {
        return array();
    }

    public function getProductAttributeOption($attribute, $value)
    {
        #$attribute = Mage::get
    }

    public function importProducts(array $data)
    {
        /*
        $entity = Mage::getResourceModel('catalog/product')
           ->loadAllAttributes();

        $options =

        foreach ($data as $row) {
            if (empty($row['sku'])) {
                continue;
            }
            $sku = $row['sku'];
        }
        */
    }
}