Adding A Client-Customizable Reports Page In A Symfony Application

Recently I decided to port ManyLeagues.com, a sports league management site, to Symfony2. One nice feature in ManyLeagues is the Report View, in which the client can easily see information concerning registration, payments, disciplinary actions, etc.

reports page

manyleagues.com reports page

The page uses jQueryUI tabs each of which should be shown or hidden based on the user’s role.

There are various administrative roles, such as regular admin, site admin, finance admin, referee assignor and super admin. A regular admin is mostly concerned with handling registration, receiving money, and so on. A finance admin would be responsible for maintaining the Paypal API credentials, setting refund policies and paying ManyLeagues. A super admin can do anything.

Not all reports are shown to all admins. For example, only someone with the role of finance admin or above should be shown the Paypal report tab. Furthermore, the reports in the system should be easy to add to, as new requests arrive regularly. A config file is the perfect location.

show_reports: []
reports:
  personRegistration: 
    name: Person Registration
    access: admin
  teamRegistration: 
    name: Team Registration
    access: admin
  referees: 
    name: Referees
    access: admin
  paypal: 
    name: Paypal
    access: finance_admin
    requirement: paypal

The client config gets loaded from the database upon user login, since there are several leagues using the site, which overwrites some of the information from the config file. The key show_reports is used to determine which reports a client has on. The requirement key refers to another config setting, in this case a boolean key called paypal. If true, the site allows users to pay via Paypal. If false, there is no reason to show the Paypal report tab to anyone.

The super admin can edit which reports are shown. In the controller:

public function reportsConfigAction()
{
  $reports = $this->get('config')->get('reports');
  $choices = [];

  foreach ($reports as $report_key => $report)
  {
      $choices[$report_key] = $report['name'];
  }

  $default_data = ['show_reports' => $this->get('config')->get('show_reports')];

  $form = $this->createFormBuilder($default_data)
    ->add('show_reports', 'choice', [
      'choices' => $choices, 
      'multiple' => TRUE, 
      'expanded' => TRUE, 
      'label' => 'Reports to Show:'
    ])
    ->add('submit', 'submit')
    ->setAction($this->generateUrl('site_update'))
    ->setMethod('POST')
    ->getForm();

  return $this->render('TheBundle:Site:reports_config.html.twig', [
      'form' => $form->createView()
  ]);
}

Upon form submission, the config will now have something like

  show_reports["personRegistration","referees","paypal"]

When an admin user accesses the reports view, here is the controller action:

  $access_granted = [];
  if ($this->get('security.context')->isGranted('ROLE_ADMIN'))
  {
      $access_granted[] = 'admin';
  }
  if ($this->get('security.context')->isGranted('ROLE_FINANCIAL_ADMIN'))
  {
      $access_granted[] = 'finance_admin';
  }
  $special = ['paypal' => $this->get('config')->get('paypal')];

  return $this->render('TheBundle:Report:reports.html.twig', [
      'access_granted' => $access_granted,
      'reports' => $this->get('config')->get('reports'),
      'show_reports' => $this->get('config')->get('show_reports'),
      'special' => $special
  ]);

Here is the relevant part of the template:

{% for report_key, report in reports %}
  {% if report_key in show_reports and report.access in access_granted %}
    {% if 'requirement' not in report|keys or special[report.requirement] %}
      <li><a href="#data_tab" data-name="{{ report_key }}">{{ report.name }}</a></li>
    {% endif %}
  {% endif %}
{% endfor %}

This is an overview only, but hopefully enough to give you a good idea how to implement this for your site.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>