Hoping this isn't true, but is Concrete5 a bit of a nightmare if you want to use your own markup?

Permalink 1 user found helpful
I'm trying to convert a couple of frameworks (Twitter Bootstrap and Zurb's Foundation) over to Concrete5 but am having a lot of issues finding and controlling the markup in some areas - form implementation doesn't seem all that consistent or easy to control?

As an example, I'm trying to sort the login single page and for the most part, everything is sweet.

But while validation and success message markup is contained on the page for most items, for some reason the success message markup for the reset form is pulled from somewhere else.

Does anyone know where I can control that markup?

Also, if anyone has experience with the core_commerce plugin - total nightmare!

Any help would be much appreciated.

Cheers

Ben

 
12345j replied on at Permalink Reply
12345j
hey.
concrete5 is a mvc based framework. That means that a lot of the code you are looking for is in a controller file- located in root/concrete/controllers. That should give you the error messages you want. Btw, the next version of c5 has bootstrap framework built into it, so it should be a good starting point.
cmscss replied on at Permalink Reply
Thanks for that mate,

I've looked through those files but don't see any markup sorry - just the error messages themselves.

With regard to MVC, I've used other CMS that claim MVC as well and I've found them a bit easier to work out - in fact, they don't generate any markup so you never have to override anything.

But in c5's case, does MVC mean there's standard form and fields markup defined somewhere that could be changed which would updated it everywhere?

e.g. The core_commerce billing form:
- The email address has the required span inside the label
- The other fields have their required spans outside their labels

But I can't find the markup for these other fields as they're called differently from the email field - e.g.
<!-- email -->
<label for="oEmail"><?php echo t('Email Address')?> <span class="ccm-required">*</span></label><?php echo $form->text('oEmail', $o->getOrderEmail())?>
<!-- first name -->
<?php $ak = CoreCommerceOrderAttributeKey::getByHandle('billing_first_name');
echo $form_attribute->display($ak, $ak->isOrderAttributeKeyRequired());?>


I've spent time training with the c5 guys which has helped but if you're not a programmer, it's quite difficult figuring out how this stuff fits together sorry.

Any help would be much appreciated.
cmscss replied on at Permalink Reply
So have found: /concrete/helpers/form/attribute.php and can kinda see why the "required" spans are outside the labels.

But I don't full understand all the if statements so am not sure how to change it.
if (is_object($this->obj)) {
         $value = $this->obj->getAttributeValueObject($obj);
      }
      $html = '';
      if ($includeLabel || $required) {
         $html .= '<div>';
      }
      if ($includeLabel) {
         $html .= $obj->render('label', false, true);
      }
      if ($required) {
         $html .= ' <span class="ccm-required">*</span>';
      }
      if ($includeLabel || $required) {
         $html .= '</div>';

Which brings me to a question. It's beginning to look as if there's a bunch of markup split across literally 100s of files that c5 outputs. It seems next to impossible to switch frameworks, say to one with in-line form validation - you would have to maintain a separate set of all the files you're overriding - is that correct?

What's the best way to manage this?
12345j replied on at Permalink Reply
12345j
what are you trying to do here?
cmscss replied on at Permalink Reply
Thanks mate, I'm trying to control how form elements are rendered so I can use Bootstrap's forms and inline validation.

And I'm also trying to do the same thing using Zurb's Foundation framework.
12345j replied on at Permalink Reply
12345j
well look at where they are being outputted in the view files then- I'm not sure I understand what you're having issues with.
In terms of the form, the form helpers located in root/concrete/helpers/form.php and the form folder are used widely, though straight up inputs are also used, but changing the form input should have a wide effect.
cmscss replied on at Permalink Reply
OK, but in the view template (/elements/checkout/billing.php), the fields are rendered like this:
<?php 
  $ak = CoreCommerceOrderAttributeKey::getByHandle('billing_first_name');
  echo $form_attribute->display($ak, $ak->isOrderAttributeKeyRequired());
?>


So, no way of controlling the markup (that I can see anyway).

Or when you say "view templates", is there a directory containing view templates that offer more straight forward control over how markup is rendered?
12345j replied on at Permalink Reply
12345j
yeah, form.php in the helpers dir. What mark up do you want to be outputted for say the email form plugin? If you can give me an example of the current code and the desired code I'll be able to provide specifics that you could apply to other stuff.
cmscss replied on at Permalink Reply
Thanks mate,

The form I'm trying to style is the core_commerce billing address form - the email address field looks great, it's the others which render like this:

<div>
<label for="akID[27][value]">First Name</label> 
<span class="ccm-required">*</span>
</div>
<input type="text" class="ccm-input-text" value="Ben" name="akID[27][value]" id="akID[27][value]">


And what I would like is this ("required" span inside the label):
<div>
<label for="akID[27][value]">First Name <span class="ccm-required">*</span></label>
</div>
<input type="text" class="ccm-input-text" value="Ben" name="akID[27][value]" id="akID[27][value]">


In the billing.php template, the first name field is called like this:
<?php 
  $ak = CoreCommerceOrderAttributeKey::getByHandle('billing_first_name');
  echo $form_attribute->display($ak, $ak->isOrderAttributeKeyRequired());
?>


And in /concrete/helpers/form/attribute.php the there is a group of if statements that control the required span and looks like this:
if (!is_object($obj)) {
         return false;
      }
      if (is_object($this->obj)) {
         $value = $this->obj->getAttributeValueObject($obj);
      }
      $html = '';
      if ($includeLabel || $required) {
         $html .= '<div>';
      }
      if ($includeLabel) {
         $html .= $obj->render('label', false, true);
      }
      if ($required) {
         $html .= ' <span class="ccm-required">*</span>';


I've ruined the validation somehow (even if I remove my sing_pages override files and use c5's defaults) so didn't really want to mess with this file and break things further - so haven't touched this file as yet.

Hopefully that makes sense.
12345j replied on at Permalink Reply
12345j
yeah, to be honest the code that generates it is pretty complex and stung out along lots of files. To be honest, what I would do is to modify the part that generates the label based on input values- something like
public function display($key, $required = false, $includeLabel = true) {
      if (is_object($key)) {
         $obj = $key;
      } else {
         $oclass = get_class($this->obj);
         switch($oclass) {
            case 'UserInfo':
               $class = 'UserAttributeKey';
               break;
            default:
               $class = $oclass . 'AttributeKey';
               break;
         }
         $obj = call_user_func(array($class, 'getByHandle'), $key);
      }
mkly replied on at Permalink Reply
mkly
What he is saying is that each "Attribute" controls it's form markup. For the core ones(not core commerce) you have
/concrete/helpers/form/attribute.php display($key, $required = false, $includeLabel = true)

If you leave $includeLabel as true and/or set $required to true it will include a <div> and the required "*" will be wrapped in a <span class="ccm-required">
This then calls for example in the case of the text attribute
/concrete/models/attribute/types/text/controller.php form()

Which adds it's own markup and adds any javascript it may need to the header.

So the short answer is, no, it's not particular easy to control the markup of your form AFAIK. Sorry for the bad news, hopefully this was at least a little a bit helpful.
cmscss replied on at Permalink Reply
Actually, I've spent a lot of time fighting with c5 over form markup so it's kind of a relief to understand what's going on.

Just a couple of questions:

Instead of calling those attributes, could I just create my own forms with my own manual form fields or is there a lot of clever and useful stuff going on with the built-in attributes?

Also, another thing I'm constantly overriding is CSS (lots of !important declarations).

I tried copying the css file containg the declarations I was overriding from: /packages/core_commerce/css - To: c5_install/css.

I then deleted all the css form that file in an attempt to get c5 to not output any css but it still output the css form the original file - is there a way to force c5 to not output any css in these instances?

Hope that make sense?
mkly replied on at Permalink Reply
mkly
The only real clever thing going on is the name="akID[32]" stuff. This is used when you submit the form and have the attributes save themselves.

There is some documentation about this here
http://www.concrete5.org/documentation/developers/forms/concrete5-w...

I have used a method where I get the AttibuteKey Id and just manually build the form and then in the controller I can save those in the controller.

For example if you were doing this with UserAttributes(I'm not as well versed with core commerce) you could do.

Loader::model('attribute/categories/user');
$form = Loader::helper('form');
// you could just use the ID outright but I feel that
// getting it by handle is safer in case its deleted
// and recreated later
$ak = UserAttributeKey::getByHandle('my_attribute_key');
$form->label('akID[' . $ak->getAttributeKeyID() . ']', $ak->getAttributeKeyName());
// You could then either do this(below) using the built
// in form method or if you already know what form
// element you need(text, textarea etc) you can just
// use the form helper like for the label instead.
$at = $ak->getAttributeType();
$at->form();


In your controller you pass this form to you can then use $ak->saveAttibuteFrom() to save the data for each of the attributes which will grab akID[32] from the POST data or whatever the attribute key id is to save it for you. You still need to validate it first though.

Oh I should add that you can also do the label manually and just add the data in the html label tag.
jordanlev replied on at Permalink Reply
jordanlev
Looks like there's a lot of helpful responses already, but I think you might find this useful as well:
http://www.concrete5.org/community/forums/themes/customizing-login-...

As for the eCommerce addon -- yeah it's a total mess. Since version 2, though, the product and product_list blocks include a "plain" custom template that is a bit easier to style (the markup itself is still a mess, but it outputs divs and classes so you can style it with CSS, as opposed to being one monolithic table).

With eCommerce, I usually tell my clients "I can implement this functionality and it is very inexpensive, but will require some compromises on the design". Another option I found out about recently here on the forums is Ecwid, which plugs into any CMS or website:http://www.ecwid.com/
programmieraffe replied on at Permalink Reply
programmieraffe
Thanks for sharing the Ecwid-Link, looks very promising for basic ecommerce solutions! :)
cmscss replied on at Permalink Reply
Thanks heaps for the replies guys - it's all fairly confusing to be honest but I'm going to give it a go anyway.

To start with, if I copy: /concrete/helpers/forms/attribute.php TO: /helpers/forms/attribute.php

And make no modifications, my billing form displays the following error:
Fatal error: Cannot redeclare class FormAttributeHelper in /path/to/c5/install/helpers/form/attribute.php on line 3


Line 3 of attribute.php is:
class FormAttributeHelper {


If I search for "FormAttributeHelper" in attribute.php I can't see it declared anywhere else - does that mean it's already declared in another file somewhere?
jordanlev replied on at Permalink Reply
jordanlev
Overriding helper classes works a little differently than everything else in C5 (not sure why) -- you have to put "Site" in front of the helper class name. So In your copied file (/helpers/forms/attribute.php), change the class name from FormAttributeHelper to SiteFormAttributeHelper

-Jordan
cmscss replied on at Permalink Reply
Thanks mate, that works great - I now understand the "How To" I just read.

But when I try the same thing for a helper file inside core commerce here:http://www.concrete5.org/index.php?cID=239917...

I don't get an error, but c5 doesn't seem to use the file for output as the original button classes (the thing I'm changing) still get output - do you know how to do that as well?
jordanlev replied on at Permalink Reply
jordanlev
Not sure. Might be one of those things that doesn't work when it's in a package (there's a few inconsistencies in the override system when it comes to packages). If you don't get an answer here I'd try posting it to the eCommerce support forum.
fastcrash replied on at Permalink Reply
fastcrash
i just experience this too when add require user attribut,

it's seems your label cannot beside your input field if it require, because div break new line
<div><label for="akID[15][value]">Real Name</label> <span class="ccm-required">*</span></div>


so i only got is id form
<form method="post" action="<?php echo $this->action('save')?>" id="profile-edit-form" enctype="multipart/form-data" class="form1">
and set css:
#profile-edit-form label{float:left}
#profile-edit-form input{float:right}


ah, and i remove div tag from attribut.php

if you don't wanna it, just go as default. label and below label your input field.
Cahueya replied on at Permalink Reply
I am too trying to customize the look of eCommerce for a project now and I am stuck with the display of /checkout/billing

I want to have the fields responsive, the theme us based on bootstrap2.3, so I planned to use these classes.

Now I've removed all table tags and wrapped the fields in the relevant classes for "form_horizontal" and just found that the address attribute itself is already wrapped in form field tags but I need to get rid of those...

Very obvious problem but I cannot find the code where it is created - so how is the address attribute wrapped into divs and where can I change that? Appreciate any hints :)


Thank you!
JohntheFish replied on at Permalink Reply
JohntheFish
eCommerce includes alternative templates for the product and product list blocks that do not have tables and make a much better starting point for themeing.
Cahueya replied on at Permalink Reply
Hi John, thanks for your reply.

The product list and product block are no problem to style, I am struggling with the whole checkout process which is very scattered around many files...

Thanks anyway!
JohntheFish replied on at Permalink Reply
JohntheFish
Yes, good point. On one site I resorted to adding some jQuery to the footer that detects these pages and hacks what they look like afterwards. It began as a quick hack 4 years ago, but has actually since proved to be quite and I have never needed to change it or go back and do it in php, I suspect because eCommerce has had very little updating in those areas.