Please help - multiple members.html pages hiding products

Discussion in 'Customization & add-ons' started by ronniead, Jun 3, 2008.

  1. ronniead

    ronniead Member

    Joined:
    Dec 20, 2007
    Messages:
    118
    Hey Everyone,

    I have a few very different websites, and they all hook up to amember for membership processing.

    The problem is that when they arrive at the members.php page, they see ALL the products. This sux. I only want them to see products for the product_group of which they are PENDING / NOT-PAID for.

    The main problem occurs when people start signing up, but don't complete the payment. When they return, they are tagged in amember as "NOT-PAID" users, so they need to login. Then they get sent straight to the members.html page where see ALL the products and confuses them.

    I would love a solution to this problem! Perhaps something like the following would work:

    I would have a few members.html pages:

    1. members1.html :will have links for price_group1
    2. members2.html: will have links for price_group2
    3. members3.html: will have links for price_group3

    Then on members1.html I would hard code products like this: http://www.yoursite.com/amember/member.php?product_id=PRODUCT_ID&paysys_id=PAYSYS_ID&action=renew

    etc...

    Then I'm assuming it would be on the signup.php page, I would need to add something like:

    • If user=NOT-PAID for PRODUCT_ID=1 then load members1.html
    • ifelse user=NOT-PAID for PRODUCT_ID=2 then load members2.html
    • ifelse user=NOT-PAID for PRODUCT_ID=3 then load members3.html

    Is that possible? Any other solutions?

    Thanks guys,

    Ronnie
  2. jimjwright

    jimjwright New Member

    Joined:
    Sep 12, 2007
    Messages:
    162
    Hello,

    This is how I understand it to work. Purchasing a product is a two-step process.

    Step 1. Create membership account in Amember.
    Step 2. Redirected to payment processor to complete payment transaction.

    The user creates an Amember account on the first page of signup. They do this by providing a username/password email address. When they click continue/submit they are taking to the payment processor for the purchased product. At this point Amember will have done the following:

    1. Add a member record to amember_members table.
    2. Add a payment record to amember_payments table.

    The payment record is marked as not completed. It will be marked as completed when payment transaction is completed. If user aborts and does not complete the purchase, the member record and the unfinished payment record will still exist in amember tables.

    If you know the members id, you should be able to get this information, then you can query the amember_payment table for that member_id and unfinished payments. The unfinished payment record contains the product_id that the user had started to purchase. So you basically have all the information you need to customize the products displayed if you can do the customization work yourself.

    Basically you would have to modify member.php and templates/member.html. Member.php already sets a variable $_amember_id to member id value at the beginning of main() so that is the most pertinent information to do what you want to do.

    To summarize:

    1. Get member_id
    2. Query payment table using member_id for unfinished payments that match member_id
    3. Obtain product_id from unfinished payment.
    4. Modify member.html to only display this product.

    Optional

    If you grouped product(s) by price group.

    4. Obtain price_group_id for a product from product_id
    5. Query product table for all products that match price_group_id
    6. Modify member.html to only display the products found in step 5.

    Straightforward if you don't mind hacking member.php/member.html.

    Jimmy
  3. ronniead

    ronniead Member

    Joined:
    Dec 20, 2007
    Messages:
    118
    skills

    Hi Jimmy,

    Really appreciate the answer, and so happy that it a solution appears possible in theory. I don't really have the skills to do that kind of stuff...I'm more of a script-kiddie type of guy. How much for a solution? :)

    I prefer your optional suggestion using price_group_id.

    I found this sample code which kinda seems in the right direction....but again, I just don't have the skill set.


    http://www.smarty.net/foreach

    Database lookup
    Code:
    <?php
      $search_condition = "where name like '$foo%' ";
      $sql = 'select contact_id, name, nick from contacts '.$search_condition.' order by name';
      $smarty->assign('results', $db->getAssoc($sql) );
    ?> 
    Here's the smarty code which would limit what prodcts would be shown...
    Code:
    {foreach key=cid item=con from=$results}
        <a href="contact.php?contact_id={$cid}">{$con.name} - {$con.nick}</a><br />
    {/foreach}
    
  4. jimjwright

    jimjwright New Member

    Joined:
    Sep 12, 2007
    Messages:
    162
    I only have version 3.0.9. If you are on that version then I could hack, I mean customize :) member.php to do what you what. I won't charge you its pretty simple.

    Let me know, I couldn't do it until tomorrow night (Thursday night in US) and you would be responsible for testing/verifying the mod.

    Jimmy
  5. ronniead

    ronniead Member

    Joined:
    Dec 20, 2007
    Messages:
    118
    whoah

    Hi Jimmy,

    If you could do it, that would be amazing!

    Once you've done it (and it works), give me your paypal email, and I'll send you some cash no questions asked.

    You say that you'll need to change member.php, but wouldn't member.html also need to be modified?

    You rock...

    Ronnie
  6. jimjwright

    jimjwright New Member

    Joined:
    Sep 12, 2007
    Messages:
    162
    Okay this code works for me. Again I'm using 3.0.9 code base. Before modifying member.php save the original member.php.

    I added the following function right before MAIN or line 262 in original member.php

    PHP:
    function get_product_groups($member_id)
    {
      global 
    $db;

      
    $price_group_ids = array('');
      foreach (
    $db->get_user_payments($member_id0) as $p)
      {
        
    $p $db->get_product($p['product_id']);
        
    $price_group_ids[] = $p['price_group'];
      }
      
    $price_group_ids array_unique($price_group_ids);
      return 
    $price_group_ids;
    }

    ///////////////////////// MAIN /////////////////////////////////////////

    Then I changed the following code snippet starting at line 380 of original member.php

    PHP:
    $products_to_renew $products;
    $products_active = array();
    $dat date('Y-m-d');
    foreach (
    $db->get_user_payments(intval($_amember_id), 1) as $p)
        if ((
    $p['begin_date'] >= $dat) && ($p['expire_date'] <= $dat))
            
    $products_active[] = $p['product_id'];
    foreach (
    $products_to_renew as $k=>$v){
        if (!
    in_array($v['scope'], $member_scope_allowed))
            unset(
    $products_to_renew[$k]);
        if (
    $_GET['price_group']){
            if (!
    in_array($_GET['price_group'], split(',',$v['price_group'])) )
                unset(
    $products_to_renew[$k]);
        } elseif (
    $v['price_group'] < 0){
            unset(
    $products_to_renew[$k]);
        } elseif (!
    check_renewal_allowed($v$products_active)){
            unset(
    $products_to_renew[$k]);
        }
        if (
    $err check_product_requirements(array($v['product_id']), 
                
    get_product_requirements_for_member($_amember_id))){
            unset(
    $products_to_renew[$k]);
        }
    }
    $t->assign('products_to_renew'$products_to_renew);
    To the following code snippet:

    PHP:
    $products_to_renew $products;
    $products_active = array();
    $dat date('Y-m-d');
    foreach (
    $db->get_user_payments(intval($_amember_id), 1) as $p)
        if ((
    $p['begin_date'] >= $dat) && ($p['expire_date'] <= $dat))
            
    $products_active[] = $p['product_id'];
    $product_group_ids get_product_groups($_amember_id);   // NEW LINE !!!
    foreach ($products_to_renew as $k=>$v){
        if (!
    in_array($v['scope'], $member_scope_allowed))
            unset(
    $products_to_renew[$k]);
        if (
    $_GET['price_group']){
            if (!
    in_array($_GET['price_group'], split(',',$v['price_group'])) )
                unset(
    $products_to_renew[$k]);
        } elseif (
    $v['price_group'] < 0){
            unset(
    $products_to_renew[$k]);
        } elseif (!
    check_renewal_allowed($v$products_active)){
            unset(
    $products_to_renew[$k]);
        }
        if (
    $err check_product_requirements(array($v['product_id']),
                
    get_product_requirements_for_member($_amember_id))){
            unset(
    $products_to_renew[$k]);
        }
        if (!
    in_array($v['price_group'], $product_group_ids))  // NEW LINE !!!
          
    unset($products_to_renew[$k]); // NEW LINE !!!
    }
    $t->assign('products_to_renew'$products_to_renew);

    This code snippet had 3 new lines added to it that I tried to indicate with comment // NEW LINE !!!

    You should not need to change member.html.

    member.html uses $products_to_renew to display products. What this code did was find all products either completed or not completed. Then it matched the product to a price_group_id and filtered out products that don't match all of your price_group_id(s) out of $products_to_renew. Hope this was what you were after.

    Anyway this worked for me, if it doesn't work for you then what can I say it was free and you should revert back to the original member.php code.

    Jimmy
  7. jimjwright

    jimjwright New Member

    Joined:
    Sep 12, 2007
    Messages:
    162
    By the way the following lines of code in member.php make no sense to me. The if conditions seem backwards.

    PHP:
    $dat date('Y-m-d');
    foreach (
    $db->get_user_payments(intval($_amember_id), 1) as $p)
        if ((
    $p['begin_date'] >= $dat) && ($p['expire_date'] <= $dat))
            
    $products_active[] = $p['product_id'];
    I would think it would be the following:

    PHP:
    $dat date('Y-m-d');
    foreach (
    $db->get_user_payments(intval($_amember_id), 1) as $p)
        if ((
    $p['begin_date'] <=$dat) && ($p['expire_date'] >=$dat))
            
    $products_active[] = $p['product_id'];
    But maybe I just think backwards :)

    Jimmy
  8. ronniead

    ronniead Member

    Joined:
    Dec 20, 2007
    Messages:
    118
    nice...

    Hey Jimmy,

    I'm totally impressed. I hope you won't get upset, but I also asked Alex for advice on this (he told me once it wasn't possible, and i persisted for a solution).

    His solution seems like a radically different solution to yours, but I'd like your advice...because I'm not sure if Alex understood what I was aksing for....

    Here's his response:

    But that looks like it won't atually select different products based on price_group, so I asked him how can I ensure that only the relevant products are displayed, and he advised the following, which does not make any sense to me:

    Code:
    {foreach from=$products_to_renew item=p}
        {if $smarty.session._amember_user.price_group==1}
        <input type="checkbox" id="product{$p.product_id}" name="product_id[]"
    value="{$p.product_id|escape}"
            {if in_array($p.product_id,
    (array)$smarty.request.product_id)}checked="checked"{/if}
            />
            <label for="product{$p.product_id}"><b>{$p.title} ({if $p.price > 0 }{$config.currency|default:"$"}{$p.price}{else}free{/if})</b><br />
            <span class="small">{$p.description}</span></label><br /><br />
        {if $p.price <= 0.0 }
        {assign var="paysys_id_not_required" value="1"}
        {/if}        
    {/if}
        {/foreach}
    
    I just can't see how that would work.....
  9. jimjwright

    jimjwright New Member

    Joined:
    Sep 12, 2007
    Messages:
    162
    I don't know if its radically different, just a different way to do it. I have not done anything with custom fields but I believe what his solution does is the following:

    1) It adds a price_group field to the user record. I'm not sure when this is done since I'm not familiar using custom fields.

    2) Then in member.html you can filter out products based on price_group. I believe he left that piece out of his code snippet as an exercise for you. In other words you would have to filter them out of member.html inside that code snippet. I was filtering them out in member.php before member.html was rendered on the screen.

    My solution just uses the payment records to find all products the user either purchased or tried to purchase. It then uses the product_id of each product to find the price_group (which I call product set). Then I filter out products that don't match the price_group or product set for the specific user.

    Both solutions do the same thing, I believe his solution binds the user to a price group immediately whereas my solution is more dynamic after the fact. Since Alex knows this stuff inside and out his solution is probably the way to go. In general I believe Alex only wants most users to modify the template files (i.e. html files) versus the PHP files if your not a programmer. So I believe his solutions to most users are geared towards tweaking the html or template files which I would agree with since it is easier to upgrade to a newer version. I'm a programmer so I would rather tweak PHP code than HTML/CSS/SMARTY.

    Anyway I'm not familiar with custom fields :( so I won't be of much help.

    Good luck.

    Jimmy
  10. ronniead

    ronniead Member

    Joined:
    Dec 20, 2007
    Messages:
    118
    thanks

    Hi Jimmy,

    I've asked Alex how to filter poducts in the member.html - I'll post the soluton here if I can get it working. If not, I'll use your suggestion. In the meantime, give me your paypal email, and I'll send you some dollars.

    Thanks again for your help. REALLY appreciate it.

    Ron
  11. ronniead

    ronniead Member

    Joined:
    Dec 20, 2007
    Messages:
    118
    So here is what Alex suggested, but it's not working for me. I added the field: "product_group" and it when looking at a users record, it does add the correct product_group, but it doesn't seem to effect the members.html page....well at least not with the code Alex suggested....

    In member.html template you need to change this block:

    Code:
    {if $config.member_select_multiple_products}
        {foreach from=$products_to_renew item=p} 
        <input type="checkbox" id="product{$p.product_id}" name="product_id[]" value="{$p.product_id|escape}"
            {if in_array($p.product_id, (array)$smarty.request.product_id)}checked="checked"{/if}
            />
            <label for="product{$p.product_id}"><b>{$p.title} ({if $p.price > 0 }{$config.currency|default:"$"}{$p.price}{else}free{/if})</b><br />
            <span class="small">{$p.description}</span></label><br /><br />
        {if $p.price <= 0.0 }
        {assign var="paysys_id_not_required" value="1"}
        {/if}        
        {/foreach}
    {else}
    <select name="product_id" size="1">
        <option value="0">#_TPL_MEMBER_SELECT#</option>
    {foreach from=$products_to_renew item=p}
        <option value="{$p.product_id}"
        {if $p.product_id == $smarty.request.product_id}selected="selected"{/if}>{$p.title} 
        ({if $p.price > 0 }{$config.currency|default:"$"}{$p.price}{else}free{/if}) 
        </option>
        {if $p.price <= 0.0 }
        {assign var="paysys_id_not_required" value="1"}
        {/if}        
    {/foreach}
    </select>
    {/if}
    
    Change it to:

    Code:
    
    {if $config.member_select_multiple_products}
        {foreach from=$products_to_renew item=p} 
        {if $p.price_group == $smarty.session._amember_user.price_group}
        <input type="checkbox" id="product{$p.product_id}" name="product_id[]" value="{$p.product_id|escape}"
            {if in_array($p.product_id, (array)$smarty.request.product_id)}checked="checked"{/if}
            />
            <label for="product{$p.product_id}"><b>{$p.title} ({if $p.price > 0 }{$config.currency|default:"$"}{$p.price}{else}free{/if})</b><br />
            <span class="small">{$p.description}</span></label><br /><br />
        {if $p.price <= 0.0 }
        {assign var="paysys_id_not_required" value="1"}
        {/if}        
        {/if}
        {/foreach}
    {else}
    <select name="product_id" size="1">
        <option value="0">#_TPL_MEMBER_SELECT#</option>
    {foreach from=$products_to_renew item=p}
        {if $p.price_group == $smarty.session._amember_user.price_group}
    
        <option value="{$p.product_id}"
        {if $p.product_id == $smarty.request.product_id}selected="selected"{/if}>{$p.title} 
        ({if $p.price > 0 }{$config.currency|default:"$"}{$p.price}{else}free{/if}) 
        </option>
        {if $p.price <= 0.0 }
        {assign var="paysys_id_not_required" value="1"}
        {/if}        
        {/if}
    {/foreach}
    </select>
    {/if}
    
    Any ideas as to what might be the problem?
  12. jimjwright

    jimjwright New Member

    Joined:
    Sep 12, 2007
    Messages:
    162
    Hello,

    I don't know if typo or not but you said you added custom field "product_group"

    His code is as follows:

    PHP:
    {if $p.price_group == $smarty.session._amember_user.price_group}
    He wrote the code assuming you added custom field "price_group". If you really added the custom field as "product_group" then you will have to change his code to as follows:

    PHP:
    {if $p.price_group == $smarty.session._amember_user.product_group}
    Jimmy
  13. jimjwright

    jimjwright New Member

    Joined:
    Sep 12, 2007
    Messages:
    162
    Hello,

    Just curious, with the custom field product_group are you exposing the user to the product_group? In other words is the field being added to the signup form? I would think you wouldn't since the user would not know what this meant which to me would imply your providing a default value? How do you rectify the binding when you want to assign different users to different product groups? I thought this was the crux of your original problem that you wanted to limit a certain set of users to a certain set of products. In other words I thought you had

    User group A ==> Product Set ABC
    User group B ==> Product Set XYZ

    How do you distinguish a user as being in group A vesus group B via the signup form? Is the product_group being passed as a variable via the signup url and auto-filling the product_group? I guess there is something that I don't quite understand about custom fields in how you assign a dynamic value at run-time (signup) without the user providing the product_group via inputing the value into a field. In other words (I know I get verbose) if the field is not exposed in form how do you assign a dynamic value to a custom field at run-time or can it only be a pre-defined static value?

    Jimmy
  14. ronniead

    ronniead Member

    Joined:
    Dec 20, 2007
    Messages:
    118
    Hi there,

    The product_group field which I added somehow magically gets populated with the correct product_group. I was also scepitcal at first, but it does work....don't ask me how it works!

    maybe because it has the same name, the variable just automatically gets assigned to it....?

    But, still, it doesn't seem to work as I wish with the members.html code alex provided.....
  15. ronniead

    ronniead Member

    Joined:
    Dec 20, 2007
    Messages:
    118
    oops

    Okay, so Alex advised me that the field I need to add is not "product_group" but rather "price_group"

    I'l try it out later today and update...
  16. jimjwright

    jimjwright New Member

    Joined:
    Sep 12, 2007
    Messages:
    162
    Hello,

    Okay I figured it out I assume you have to call your signup page as follows:

    PHP:
    /amember/signup.php?price_group=xyz
    The value passed for price_group via the url is filled into the price_group field of the member record. In other words the names must match up. So yeah if you change your custom field to price_group it should work. Its pretty slick actually, but I still like my way better :)

    Jimmy
  17. ronniead

    ronniead Member

    Joined:
    Dec 20, 2007
    Messages:
    118
    oops

    I made a mistake....the field I created was indeed called price_group...

    but alas it's still not working! strange....

    At the moment, I think I like your idea as well, because it seems like it works (although I have yet to try it)!! But, I'd like to try and do this via member.html page if possible, as I believe it'll make upgrading a little more transparent for me.

    oh...yes...you're correct. My signup page code is indeed:

    Code:
     /amember/signup.php?price_group=xyz  
    Alex said he'll have a look more in depth what's going on....
  18. ronniead

    ronniead Member

    Joined:
    Dec 20, 2007
    Messages:
    118
    Arghh I got it working. I changed the field type from a "common" to SQL, and that fixed it. I was going to try and do that before, but I was scared to change the table structure....but alas it worked!

    jim - thanks so much for helping through this. i wanted to PM you something, but not sure how to do it...
  19. jimjwright

    jimjwright New Member

    Joined:
    Sep 12, 2007
    Messages:
    162
    Hello,

    Congrats !!! I learned something about custom fields and how they work. I think the important lesson learned that other people can benefit from your experience is the following:

    PHP:
    /amember/signup.php?field_name=value
    If you create a custom field named "field_name" that the above mechanism will pre-populate the field_name with the specified "value" into the member record when its created.

    Maybe others already knew this but I didn't.

    The most obvious reason for doing this is your example of trying to categorize members into various groups so that you can control the products available to them. It can be thought of as a "selection criteria" for a "class of users".

    It took a while to get the solution but ultimately it turned out to be very simple with very little modifications.

    Jimmy
  20. jimjwright

    jimjwright New Member

    Joined:
    Sep 12, 2007
    Messages:
    162
    Hello,

    To finally beat this horse to death Alex provided the following snippet

    PHP:
    if $p.price_group == $smarty.session._amember_user.price_group
    I believe this code assumes you created the field as type "sql".

    If you created the field as type "common" then I think you would have to modify his snippet as follows:

    PHP:
    if $p.price_group == $smarty.session._amember_user.data.price_group
    All the common fields are packed into a "data" section of the table. It can be thought of as "chaotic dynamic data". Just kidding :) If you have never looked at your database records you will find that most of the interesting stuff is stored under the "data" field for the payment, product, and user records.

    At least that is how I understand it to work.

    Jimmy

Share This Page