Duplicate category programmatically - magento

I'm on Magento 1.4.1.1. How can I duplicate category programmatically using its id number?

<?php set_time_limit(0); ?>
<?php ob_end_flush(); ?>
<?php ob_implicit_flush(); ?>
<?php require_once 'app/Mage.php'; ?>
<?php Mage::app(); ?>
<?php define('STARTTIME', microtime(true)); ?>
<?php $availSortBy = array() ?>
<?php foreach (Mage::getSingleton('catalog/config')->getAttributeUsedForSortByArray() as $key => $value){$availSortBy[] = $key;} ?>
<?php define('AVAILSORTBY', implode(",",$availSortBy)); ?>
<?php var_dump(AVAILSORTBY) ?>
<?php
function buildTree($category,$return=array()){
if($category->getChildrenCount() !== "0"){
$return[$category->getId()] = array();
foreach($category->getChildrenCategories() as $child){
$return[$category->getId()][$child->getId()] = buildTree($child);
}
}else{
$return = $category->getId();
}
return $return;
}
function processTree($tree,$parentId){
$first=false;
foreach ($tree as $catId => $data) {
if($first){
$newParentId = $parentId;
$first = false;
}else{
// EXCLUDE COLLECTION
$newParentId = createCategory($catId,$parentId);
// INCLUDE COLLECTION
// $newParentId = createCategory($catId,$parentId,true);
}
if(is_array($data)){
processTree($data,$newParentId);
}
}
}
function createCategory($oldCategoryId,$parent_id,$includeCollection=false){
try{
// LOAD MODELS
$oldCategory = Mage::getModel('catalog/category')->load($oldCategoryId);
// SET VALUES
$newData = $oldCategory->getData();
foreach (array('entity_id','parent_id','created_at','updated_at','path','children_count') as $unset) {
unset($newData[$unset]);
}
foreach (array('available_sort_by'=>AVAILSORTBY,'default_sort_by'=>'name','include_in_menu'=>'0','is_active'=>'1','name'=>'Unnamed Category') as $req=>$default) {
$newData[$req] = empty($newData[$req]) ? $default : $newData[$req];
}
$newId = Mage::getSingleton('catalog/category_api')->create($parent_id,$newData);
$newCategory = Mage::getModel('catalog/category')->load($newId);
// COLLECTION
if($includeCollection){
$collectionCount = 0;
foreach ($oldCategory->getProductCollection() as $_product) {
$collectionCount++;
Mage::getSingleton('catalog/category_api')->assignProduct($newCategory->getId(),$_product->getId());
}
$collectionString = "<p>".$collectionCount." Products Added</p>";
}else{
$collectionString = "";
}
// RUN TIME
$duration = number_format(((microtime(true)-STARTTIME)/60),4);
// OUTPUT
echo "<p>New Category: <strong>".$newCategory->getName()."</strong> (".$newCategory->getUrlPath().")</p>".$collectionString."<small>DURATION:".$duration." mins</small><hr>";
ob_flush();
return $newCategory->getId();
} catch(Exception $e) {
print_r($e);
}
return false;
}
?>
<?php if(!empty($_REQUEST['category-id']) && !empty($_REQUEST['target-parent-id'])):?>
<?php $oldCategory = Mage::getModel('catalog/category')->load($_REQUEST['category-id']); ?>
<?php if($oldCategory): ?>
<?php $catTree = buildTree($oldCategory); ?>
<?php processTree($catTree,$_REQUEST['target-parent-id']); ?>
<script>
var iFrequency = 500; // expressed in miliseconds
var interval = 0;
function startLoop() {
if(interval > 0) clearInterval(interval); // stop
interval = setInterval( "window.scrollTo(0,document.body.scrollHeight)", iFrequency );
}
startLoop();
</script>
<?php else: ?>
<h1>Invalid Category</h1>
<?php endif; ?>
<?php else: ?>
<h1>Missing Parameters</h1>
<?php endif; ?>
Check out the attached script. If you upload it to your root folder and access it, including the URL params:
category-id={ID OF THE CATEGORY YOU WOULD LIKE TO COPY}
target-parent-id={ID OF THE TARGET CATEGORY}
NOTE: I included (but commented out) an alternate function call that would include the product collection as well in the category but because we use a dynamic script at my company it wasn't necessary for me to include the collection data. You can uncomment line 39 and comment out line 37 to include the category product collection.

$category_to_duplicate = Mage::getModel('catalog/category')->load($cat_id);
$category_new = Mage::getModel('catalog/category');
$category_new->setStoreId(0); // 0 = default/all store view.
$category_new->addData($category_to_duplicate->getData());
try {
$category->save();
echo "Success! Id: ".$category_new->getId();
}
catch (Exception $e){
echo $e->getMessage();
}

Related

Load images from database CodeIgniter

I would like to create a photo gallery, taking images from the database.
I'm using codeigniter.
Database
this is a static page located in views/pages/gallery.php
does anyone have any ideas?
What you want is to query the database table, get the relevant fields, and return that to a view. In MVC, it looks something like this:
Model:
class Portfolio_model extends CI_Model {
public function get_items() {
$this->db->select('name, description, image');
$this->db->order_by('date', 'DESC');
$q = $this->db->get('tablename'); // your tablename here
if ($q->num_rows() > 0) {
return $q->result();
} else {
return null;
}
}
}
Controller:
class Portfolio extends CI_Controller {
public function index() {
$this->load->helper('html');
$this->load->model('portfolio_model');
$data['items'] = $this->portfolio_model->get_items();
$this->load->view('portfolio', $data);
}
}
View:
if (!is_null($items)) {
foreach ($items as $item) {
echo $item->name . '<br>';
echo $item->description . '<br>';
echo 'Image src: ' . base_url() . $item->image . '<br>'; // might need slash after base_url, don't remember
echo img($item->image);
}
} else {
echo 'No items found!';
}
This worked for me :
Controller -
public function index(){
$this->load->model('galleryModel');
$data1['items'] = $this->galleryModel->get_items();
$this->load->view('gallery', $data1);
}
Model -
public function get_items() {
$this->db->select('*');
$this->db->from('gallery');
$query = $this->db->get();
if($query->num_rows() != 0){
return $query->result_array();
}else{
return false;
}
}
View -
<?php
foreach ($items as $item) {
$image_id = $item['image_id'];
$name = $item['name'];
$category = $item['category'];
$image = $item['image'];
?>
<div class="tile scale-anm <?php echo $category; ?>">
<img src="<?php echo $image; ?>" class="film-img-gallery" alt="" />
</div>
<?php } ?>

get all Categories and SubCatgories without loading model in foreach loop

I want to display all categories and their subcategories in primary nav menu.
When i hover on cateory, it should display its subcategories.
I want to implement this functionality without loading Mage::getModel('catalog/category') in foreach loop.
as you want to write code in phtml file use below code which create tree structure of category.
<ul>
<?php
$obj = new Mage_Catalog_Block_Navigation();
$storeCategories = $obj->getStoreCategories();
Mage::registry('current_category') ? $currentCategoryId = Mage::registry('current_category')->getId() : $currentCategoryId='';
foreach ($storeCategories as $_category):
?>
<li>
<strong><?php echo $_category->getName(); ?></strong>
<?php $categoryChildren = $_category->getChildren(); ?>
<?php if($categoryChildren->count()) : ?>
<ul>
<?php foreach($categoryChildren as $_categoryChild) : ?>
<?php $_categoryChildModel = Mage::getModel('catalog/category')->load($_categoryChild->getId());?>
<?php $categoryGrandchildren=$_categoryChild->getChildren(); ?>
<li>
<?php
$currentCategoryId===$_categoryChild->getId() ? $bold="style=\"font-weight:bold\"" : $bold='';
echo ' ' . '<a href="' . $_categoryChildModel->getUrl() . '"' . $bold . '>' . $_categoryChild->getName() . '(' . $_categoryChildModel->getProductCollection()->count() . ')</a>';
?>
</li>
<?php if($categoryGrandchildren->count()) : ?>
<?php foreach($categoryGrandchildren as $_categoryGrandchild) : ?>
<?php $_categoryGrandchildModel = Mage::getModel('catalog/category')->load($_categoryGrandchild->getId());?>
<li>
<?php
$currentCategoryId===$_categoryChild->getId() ? $bold="style=\"font-weight:bold\"" : $bold='';
echo '  ' . '<a href="' . $_categoryGrandchildModel->getUrl() . '"' . $bold . '>' . $_categoryGrandchild->getName() . '(' . $_categoryGrandchildModel->getProductCount() . ')</a>';
?>
</li>
<?php endforeach; ?>
<?php endif; ?>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</li>
<?php endforeach ?>
</ul>
and using css and HTML you can achieve your goal to display sub menu on hover of main menu.
Still let me if you need any other help.
Thanks
ok so I just did this and I figured I'd search to see if anyone was wondering how to achieve this. The trick to this is
Mage::getResourceSingleton('catalog/category')->getAttributeRawValue($categoryEntityId,array('name','level','url_key','path','is_active'),Mage::app()->getStore());
This does not load the category model lets take a look at what it is actually doing.
Go to app/code/core/Mage/Catalog/Model/Resource/Abstract
public function getAttributeRawValue($entityId, $attribute, $store)
{
if (!$entityId || empty($attribute)) {
return false;
}
if (!is_array($attribute)) {
$attribute = array($attribute);
}
$attributesData = array();
$staticAttributes = array();
$typedAttributes = array();
$staticTable = null;
$adapter = $this->_getReadAdapter();
foreach ($attribute as $_attribute) {
/* #var $attribute Mage_Catalog_Model_Entity_Attribute */
$_attribute = $this->getAttribute($_attribute);
if (!$_attribute) {
continue;
}
$attributeCode = $_attribute->getAttributeCode();
$attrTable = $_attribute->getBackend()->getTable();
$isStatic = $_attribute->getBackend()->isStatic();
if ($isStatic) {
$staticAttributes[] = $attributeCode;
$staticTable = $attrTable;
} else {
/**
* That structure needed to avoid farther sql joins for getting attribute's code by id
*/
$typedAttributes[$attrTable][$_attribute->getId()] = $attributeCode;
}
}
/**
* Collecting static attributes
*/
if ($staticAttributes) {
$select = $adapter->select()->from($staticTable, $staticAttributes)
->where($this->getEntityIdField() . ' = :entity_id');
$attributesData = $adapter->fetchRow($select, array('entity_id' => $entityId));
}
/**
* Collecting typed attributes, performing separate SQL query for each attribute type table
*/
if ($store instanceof Mage_Core_Model_Store) {
$store = $store->getId();
}
$store = (int)$store;
if ($typedAttributes) {
foreach ($typedAttributes as $table => $_attributes) {
$select = $adapter->select()
->from(array('default_value' => $table), array('attribute_id'))
->where('default_value.attribute_id IN (?)', array_keys($_attributes))
->where('default_value.entity_type_id = :entity_type_id')
->where('default_value.entity_id = :entity_id')
->where('default_value.store_id = ?', 0);
$bind = array(
'entity_type_id' => $this->getTypeId(),
'entity_id' => $entityId,
);
if ($store != $this->getDefaultStoreId()) {
$valueExpr = $adapter->getCheckSql('store_value.value IS NULL',
'default_value.value', 'store_value.value');
$joinCondition = array(
$adapter->quoteInto('store_value.attribute_id IN (?)', array_keys($_attributes)),
'store_value.entity_type_id = :entity_type_id',
'store_value.entity_id = :entity_id',
'store_value.store_id = :store_id',
);
$select->joinLeft(
array('store_value' => $table),
implode(' AND ', $joinCondition),
array('attr_value' => $valueExpr)
);
$bind['store_id'] = $store;
} else {
$select->columns(array('attr_value' => 'value'), 'default_value');
}
$result = $adapter->fetchPairs($select, $bind);
foreach ($result as $attrId => $value) {
$attrCode = $typedAttributes[$table][$attrId];
$attributesData[$attrCode] = $value;
}
}
}
if (sizeof($attributesData) == 1) {
$_data = each($attributesData);
$attributesData = $_data[1];
}
return $attributesData ? $attributesData : false;
}
As you can see no model loading happening just retrieving specific pieces of info. Also being part of the resource abstract means all catalog resource models (I haven't checked other resource models but, I wouldn't be too surprised to find this in others) have this available.
If you use this in an override of Mage_Catalog_Block_Navigation you can then call all of the info you need about any category without loading the model. To traverse the tree however, you have to do terrible things.
You can use 'path'(explode on /) to easily retrieve parents but you will need to get dirty in order to retrieve children categories so something like this to get Children.
$childrenQuery = "SELECT entity_id FROM catalog_category_entity WHERE path REGEXP '^.*\/" . $categoryId . "\/[[:digit:]]?[[:digit:]]?[[:digit:]]?[[:digit:]]?$'";
$resource = Mage::getSingleton('core/resource');
$readCxn = $resource->getConnection('core/read');
$children = $readCxn->fetchAll($childrenQuery);
if ($children[0]) {
return $children;
} else {
return;
}
The overall difficulty is that all model and resource model functions will expect an instance of a category object to make them all work with just the entity_id is definitely possible just a pain.
So I would not recommend doing this in general the only reason I did this is because the default magento root category in my case was not the actual functional root of categories (fun eh). If you are using a standard root category I would recommend using the Helper functions and retrieving the info from cache.
Either way from here all you have to do complete your functions in Mage_Catalog_Block_Navigation and assemble your menu in a template. And there you go; complete category menu without ever accessing a model->load.
Try This Code
<?php
require_once("app/Mage.php");
Mage::app();
function getChildCategories($category, $First = false) {
$sub = $First ? $category : $category->getChildren();
foreach ($sub as $child) {
$_categories[] = [ "name" => $child->getName(), "id" => $child->getId(), "children" => getChildCategories($child) ];
}
return $_categories;
};
function CategoriesTree($category, $First = false) {
$sub = $First ? $category : $category->getChildren();
echo "<pre>";
foreach ($sub as $child) {
echo $child->getName(); ;
CategoriesTree($child);
}
}
$_categories = Mage::helper('catalog/category')->getStoreCategories();
$categories = getChildCategories($_categories, true);
CategoriesTree($_categories, true);
?>

Fatal error: Call to a member function getLevel() on a non-object in list.phtml on line 44

Fatal error: Call to a member function getLevel() on a non-object in list.phtml on line 44
getting error at the time of seraching
<?php
$_productCollection=$this->getLoadedProductCollection();
$_helper = $this->helper('catalog/output');
$_collectionSize = $_productCollection->count();
?>
<?php
$currentCat = Mage::registry('current_category');
if($currentCat->getLevel()!=2){
if ( $currentCat->getParentId() == Mage::app()
->getStore()->getRootCategoryId() )
{
$loadCategory = $currentCat;
}
else
{
$loadCategory = Mage::getModel('catalog/category')->
load($currentCat- >getParentId());
}
$subCategories = explode(',', $loadCategory->getChildren());
echo '<ul class="subcategories">';
foreach ( $subCategories as $subCategoryId )
{
$cat = Mage::getModel('catalog/category')->load($subCategoryId);
if($cat->getIsActive())
{
echo '<li class="subicon"><a href="'.$cat->getURL().'">'
.$cat->getName().'</a></li>';
}
}
echo '</ul>';
}else{
$category = Mage::getSingleton('catalog/layer')->getCurrentCategory();
$categories = $category->getCollection()
->addAttributeToSelect(array('name', 'thumbnail'))
->addAttributeToFilter('is_active', 1)
->addIdFilter($category->getChildren())
?>
her is my code how this can be error free
It's likely that you're using this list.phtml when not on a category listing page.
You'd be best doing a check to ensure the value you're retrieving is in the right format first.
$currentCat = Mage::registry('current_category');
if (get_class($currentCat) == "Mage_Catalog_Model_Category"){
if ($currentCat->getLevel() !=2 ){
This then ensures you have a Category object before you try to call a method on it.

Codeigniter dropdown only retrieve last data from db

I use CI form with form_dropdown helper and tried to pull Mysql data into its options, from the below code, its only retrieve the last record from db into the option list?
please advise what is wrong with my code?
Model
public function getStates() {
$query = $this->db->get('states');
$return = array();
if($query->num_rows() > 0){
$return[''] = 'please select';
foreach($query->result_array() as $row){
$return[$row['state_id']] = $row['state_name'];
}
}
return $return;
}
Controller
$this->load->model('db_model');
$data['options'] = $this->db_model->getStates();
$this->load->view('create_new', $data);
View
$state = array(
'name' => 'state',
'id' => 'state',
//'value' => set_value('state', $state)
);
<?php echo form_label('State', $state['id']); ?>
<?php echo form_dropdown($state['name'], $options); ?>
<?php echo form_error($state['name']); ?>
<?php echo isset($errors[$state['name']])?$errors[$state['name']]:''; ?>
send full query result from the model to the view like this
Model
public function getStates() {
$query = $this->db->get('states');
return $query->result();
}
let the controller as it is and now you can populate states in dropdown like this:
View
<?php
foreach($options as $opt){
$options[$opt->state_id]=$opt->state_name;
}
echo form_dropdown($state['name'], $options);
?>
Try this:
function getStates() {
$return = array();
$query = $this->db->get('states')->result_array();
if( is_array( $query ) && count( $query ) > 0 ){
$return[''] = 'please select';
foreach($query as $row){
$return[$row['state_id']] = $row['state_name'];
}
}
return $return;
}

One page checkout process show two shipping method in magento 1.7.0.1

I have enbaled two shipping method.
1. tablerate
2. free shipping
I need show only single shipping method and also enable two shipping method. I have customize code in app\code\core\Mage\Checkout\Block\Onepage\Shipping\Method\Available.php
if (!empty($groups)) {
$ratesFilter = new Varien_Filter_Object_Grid();
$ratesFilter->addFilter(Mage::app()->getStore()->getPriceFilter(), 'price');
$custom = array();
$k=0;
foreach ($groups as $code => $groupItems) {
$custom['shippingmethod'][$k] = $code;
$k++;
}
$check = array('tablerate','freeshipping');
if(in_array($check,$custom)){
foreach ($groups as $code => $groupItems) {
if($code == 'tablerate')
$groups[$code] = $ratesFilter->filter($groupItems);
}
} else {
foreach ($groups as $code => $groupItems) {
$groups[$code] = $ratesFilter->filter($groupItems);
}
}
}
But its not give me price for shipping method. Is there any other solution for this?
You can customize this feature in the frontend templates. You will have to change app/design/frontend/_your_package_/_your_theme_/template/checkout/onepage/shipping_method/available.phtml
I guess you want to show only the free shipping if available. When freeshipping is not availabe, it should not be shown anyway.
Original code:
<dl class="sp-methods">
<?php $shippingCodePrice = array(); ?>
New code:
<dl class="sp-methods">
<?php
$showFreeShipping = false;
$_shippingRateGroupsReduced = array();
foreach ($_shippingRateGroups as $code => $_rates) {
if(strstr($code, 'freeshipping')) {
$showFreeShipping = true;
$_shippingRateGroupsReduced[$code] = $_shippingRateGroups[$code];
}
}
if($showFreeShipping) {
$_shippingRateGroups = $_shippingRateGroupsReduced;
}
?>
<?php $shippingCodePrice = array(); ?>

Resources