text:
//
//  MGPopController.m
//  MGPopControllerDemo
//
//  Created by 宋海梁 on 16/8/4.
//  Copyright © 2016年 宋海梁. All rights reserved.
//

#import "MGPopController.h"
#import <Masonry/Masonry.h>

@implementation MGPopAction

- (instancetype)initWithImage:(UIImage *)image title:(NSString *)title action:(dispatch_block_t)action {

    self = [super init];
    if (self) {
        _image = image;
        _action = action;
        _title = title;

        _autoDismiss = YES;
        _titleColor = [UIColor colorWithRed:0 green:0.48 blue:1.0 alpha:1.0];
        _titleFont = [UIFont systemFontOfSize:17.0];
        _disabledTitleColor = [UIColor lightGrayColor];
        _enable = YES;
    }

    return self;
}

+ (instancetype)actionWithImage:(UIImage *)image action:(dispatch_block_t)action {

    return [[MGPopAction alloc] initWithImage:image title:nil action:action];
}

+ (instancetype)actionWithTitle:(NSString *)title action:(dispatch_block_t)action {

    return [[MGPopAction alloc] initWithImage:nil title:title action:action];
}

@end

@interface MGPopController () {

    NSString *_title;
    NSString *_message;
    UIImage *_image;
}

@property (nonatomic, strong) UIView *containerView;
@property (nonatomic, strong) UIImageView *topImageView;
@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UILabel *messageLabel;
@property (nonatomic, strong) UIButton *closeButton;
@property (nonatomic, strong) UIView *actionContainerView;
@property (nonatomic, strong) UIView *textFieldContainerView;

@property (nonatomic, strong) NSMutableArray *actions;

@end

@implementation MGPopController

#pragma mark - Init

- (instancetype)initWithTitle:(NSString *)title message:(NSString *)message image:(UIImage *)image {

    self = [super init];
    if (self) {
        _title = title;
        _message = message;
        _image = image;

        [self setupDefault];
    }

    return self;
}

- (void)setupDefault {

    _actions = [NSMutableArray array];

    _backgroundColor = [UIColor whiteColor];
    _titleFont = [UIFont systemFontOfSize:36.0];
    _titleColor = [UIColor darkGrayColor];
    _messageFont = [UIFont systemFontOfSize:18.0];
    _messageColor = [UIColor lightGrayColor];
    _closeButtonTintColor = [UIColor lightGrayColor];
    _cornerRadius = 10.0;
    _horizontalOffset = 50;

    _showActionSeparator = NO;
    _actionPaddingLeftRight = 10;
    _actionSpacing = 10;
    _actionPaddingBottom = 15;
    _showCloseButton = YES;
}

#pragma mark - Life Circle

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    [self setupUI];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)dealloc {
    NSLog(@"dealloc -- %@",NSStringFromClass([self class]));
}

#pragma mark - UI

- (void)setupUI {

    self.view.backgroundColor = [UIColor colorWithWhite:0 alpha:0.4];

    [self.view addSubview:self.containerView];
    [self.containerView addSubview:self.topImageView];
    [self.containerView addSubview:self.titleLabel];
    [self.containerView addSubview:self.messageLabel];
    [self.containerView addSubview:self.closeButton];
    [self.containerView addSubview:self.actionContainerView];
    [self.containerView addSubview:self.textFieldContainerView];

    [self makeConstrains];

    self.titleLabel.text = _title;
    self.messageLabel.text = _message;
    self.topImageView.image = _image;
    self.closeButton.hidden = !self.showCloseButton;
}

- (void)makeConstrains {

    [self.containerView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.leading.offset(_horizontalOffset);
        make.trailing.offset(-_horizontalOffset);
        make.centerY.equalTo(self.view).offset(self.verticalOffset);
    }];

    [self.topImageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.offset(17);
        make.centerX.equalTo(self.containerView);
    }];

    [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_equalTo(self.topImageView.mas_bottom).offset(9);
        make.centerX.equalTo(self.containerView);
    }];

    [self.messageLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.leading.offset(10);
        make.trailing.offset(-10);
        make.top.mas_equalTo(self.titleLabel.mas_bottom).offset(10);
    }];

    [self.textFieldContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.leading.trailing.offset(0);
        make.top.mas_equalTo(self.messageLabel.mas_bottom).offset(15);
    }];

    [self.actionContainerView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.leading.offset(self.actionPaddingLeftRight);
        make.trailing.offset(-self.actionPaddingLeftRight);
        make.top.mas_equalTo(self.textFieldContainerView.mas_bottom).offset(0);
        make.bottom.equalTo(self.containerView).offset(-self.actionPaddingBottom);
    }];

    [self.closeButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.offset(0);
        make.trailing.offset(0);
        make.width.height.equalTo(@44);
    }];

    //Actions
    [self.actions enumerateObjectsUsingBlock:^(MGPopAction *action, NSUInteger idx, BOOL * _Nonnull stop) {
        UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
        btn.tag = idx;
        [btn addTarget:self action:@selector(actionButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
        if (action.image) {
            [btn setImage:action.image forState:UIControlStateNormal];
        }
        else if (action.title.length) {
            [btn setTitle:action.title forState:UIControlStateNormal];
            [btn setTitleColor:action.titleColor forState:UIControlStateNormal];
            [btn setTitleColor:action.disabledTitleColor forState:UIControlStateDisabled];
            btn.titleLabel.font = action.titleFont;
        }
        btn.enabled = action.enable;

        [self.actionContainerView addSubview:btn];
    }];

    NSInteger count = self.actions.count;
    __block UIButton *preBtn;
    [self.actionContainerView.subviews enumerateObjectsUsingBlock:^(UIButton * _Nonnull btn, NSUInteger idx, BOOL * _Nonnull stop) {
       [btn mas_makeConstraints:^(MASConstraintMaker *make) {
           make.top.bottom.offset(0);
           make.height.equalTo(@44);
           if (preBtn) {
               make.left.equalTo(preBtn.mas_right).offset(self.actionSpacing);
               make.width.equalTo(preBtn.mas_width);
           }
           else {
               make.leading.offset(0);
           }
           if (idx == count-1) { //最后一个
               make.trailing.offset(0);
           }
       }];

        preBtn = btn;
    }];

    //分割线separator
    if (self.showActionSeparator) {
        //Top separator
        UIView *topSeparator = [[UIView alloc] init];
        topSeparator.backgroundColor = [UIColor colorWithRed:227/255.0 green:225/255.0 blue:228/255.0 alpha:1.0];
        [self.actionContainerView addSubview:topSeparator];
        [topSeparator mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.leading.trailing.offset(0);
            make.height.equalTo(@0.5);
        }];

        //vertical separator
        NSInteger separatorNum = self.actions.count-1;
        for (NSInteger i=0; i<separatorNum; i++) {
            UIView *separator = [[UIView alloc] init];
            separator.backgroundColor = [UIColor colorWithRed:227/255.0 green:225/255.0 blue:228/255.0 alpha:1.0];
            [self.actionContainerView addSubview:separator];
            [separator mas_makeConstraints:^(MASConstraintMaker *make) {
                make.top.bottom.offset(0);
                make.width.equalTo(@0.5);
                make.centerX.equalTo(self.actionContainerView).multipliedBy((i*2+2)/((CGFloat)self.actions.count));
            }];
        }
    }

    //TextFields
    [self.textFields enumerateObjectsUsingBlock:^(UITextField * _Nonnull textField, NSUInteger idx, BOOL * _Nonnull stop) {
        [self.textFieldContainerView addSubview:textField];
    }];

    __block UITextField *preTextField;
    [self.textFieldContainerView.subviews enumerateObjectsUsingBlock:^(UITextField * textField, NSUInteger idx, BOOL * _Nonnull stop) {
        [textField mas_makeConstraints:^(MASConstraintMaker *make) {
            make.leading.offset(16);
            make.trailing.offset(-16);
            if (preTextField) {
                make.top.equalTo(preTextField.mas_bottom).offset(8);
            }
            else {
                make.top.offset(0);
            }
            if (idx == self.textFields.count-1) { //最后一个
                make.bottom.offset(-8);
            }
        }];
        preTextField = textField;
    }];

}

#pragma mark - Public Method

- (void)addAction:(MGPopAction *)action {

    [_actions addObject:action];
}

- (void)addTextFieldWithConfiguration:(void (^)(UITextField *textField))configuration {

    UITextField *textField = [[UITextField alloc] init];
    textField.borderStyle = UITextBorderStyleRoundedRect;
    textField.font = [UIFont systemFontOfSize:13.0f];

    NSMutableArray *arr = [NSMutableArray arrayWithArray:_textFields];
    [arr addObject:textField];
    _textFields = arr;

    if (configuration) {
        configuration(textField);
    }
}

- (void)show {

    UIViewController *currentController = [self currentController];
    [currentController addChildViewController:self];
    [currentController.view addSubview:self.view];
    [self.view mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.insets(UIEdgeInsetsZero);
    }];

    CABasicAnimation *animation=[CABasicAnimation animationWithKeyPath:@"transform.scale"];
    animation.fromValue = @(0.8);
    animation.toValue = @(1);
    animation.duration = 0.15;
    animation.autoreverses = NO;
    animation.repeatCount = 1;
    animation.removedOnCompletion = YES;
    animation.fillMode = kCAFillModeForwards;

    [self.containerView.layer addAnimation:animation forKey:@"animation"];
}

- (void)dismiss {
    __weak typeof(self) weakSelf = self;
    [UIView animateWithDuration:0.15 animations:^{

        self.containerView.layer.transform = CATransform3DMakeScale(0.5, 0.5, 1);
        self.containerView.alpha = 0;

    } completion:^(BOOL finished) {
        [weakSelf.view removeFromSuperview];
        [weakSelf removeFromParentViewController];
    }];
}

#pragma mark - getter、setter

- (void)setBackgroundColor:(UIColor *)backgroundColor {
    _backgroundColor = backgroundColor;
    self.containerView.backgroundColor = backgroundColor;
}

- (void)setTitleFont:(UIFont *)titleFont {
    _titleFont = titleFont;
    self.titleLabel.font = _titleFont;
}

- (void)setTitleColor:(UIColor *)titleColor {
    _titleColor = titleColor;
    self.titleLabel.textColor = _titleColor;
}

- (void)setMessageFont:(UIFont *)messageFont {
    _messageFont = messageFont;
    self.messageLabel.font = _messageFont;
}

- (void)setMessageColor:(UIColor *)messageColor {
    _messageColor = messageColor;
    self.messageLabel.textColor = _messageColor;
}

- (void)setCloseButtonTintColor:(UIColor *)closeButtonTintColor {
    _closeButtonTintColor = closeButtonTintColor;
    self.closeButton.tintColor = _closeButtonTintColor;
}

- (void)setCornerRadius:(NSInteger)cornerRadius {
    _cornerRadius = cornerRadius;
    self.containerView.layer.cornerRadius = _cornerRadius;
}

#pragma mark - Private Method

- (void)closeButtonTouched:(UIButton *)sender {

    [self dismiss];
}

- (void)actionButtonTouched:(UIButton *)sender {

    if (self.actions.count > sender.tag) {
        MGPopAction *action = [self.actions objectAtIndex:sender.tag];
        if (action.action) {
            action.action();
        }
        if (action.autoDismiss) {
            [self dismiss];
        }
    }
}

- (UIViewController *)currentController {
    UIViewController *result = nil;
    UIWindow *window = [[UIApplication sharedApplication] keyWindow];

    if (window.windowLevel != UIWindowLevelNormal) {
        NSArray *windows = [[UIApplication sharedApplication] windows];

        for (UIWindow *temWin in windows) {
            if (temWin.windowLevel == UIWindowLevelNormal) {
                window = temWin;
                break;
            }
        }
    }

    UIView *frontView = [[window subviews] objectAtIndex:0];
    id nestResponder = [frontView nextResponder];
    if ([nestResponder isKindOfClass:[UIViewController class]]) {
        result = nestResponder;
    } else {
        result = window.rootViewController;
    }
    return result;
}

/*
 // Only override drawRect: if you perform custom drawing.
 // An empty implementation adversely affects performance during animation.
 - (void)drawRect:(CGRect)rect {
 // Drawing code
 }
 */

#pragma mark - Property

- (UIView *)containerView {

    if (!_containerView) {
        _containerView = [[UIView alloc] init];
        _containerView.layer.cornerRadius = _cornerRadius;
        _containerView.backgroundColor = _backgroundColor;
    }

    return _containerView;
}

- (UIImageView *)topImageView {

    if (!_topImageView) {
        _topImageView = [[UIImageView alloc] init];
        _topImageView.contentMode = UIViewContentModeScaleAspectFill;
    }

    return _topImageView;
}

- (UILabel *)titleLabel {

    if (!_titleLabel) {
        _titleLabel = [[UILabel alloc] init];
        _titleLabel.numberOfLines = 1;
        _titleLabel.font = _titleFont;
        _titleLabel.textColor = _titleColor;
        _titleLabel.textAlignment = NSTextAlignmentCenter;
    }

    return _titleLabel;
}

- (UILabel *)messageLabel {

    if (!_messageLabel) {
        _messageLabel = [[UILabel alloc] init];
        _messageLabel.numberOfLines = 0;
        _messageLabel.font = _messageFont;
        _messageLabel.textColor = _messageColor;
        _messageLabel.textAlignment = NSTextAlignmentCenter;
    }

    return _messageLabel;
}

- (UIButton *)closeButton {

    if (!_closeButton) {
        _closeButton = [UIButton buttonWithType:UIButtonTypeCustom];
        _closeButton.tintColor = _closeButtonTintColor;
        [_closeButton setImage:[UIImage imageNamed:@"icon_close"] forState:UIControlStateNormal];
        [_closeButton addTarget:self action:@selector(closeButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
    }

    return _closeButton;
}

- (UIView *)actionContainerView {

    if (!_actionContainerView) {
        _actionContainerView = [[UIView alloc] init];
    }

    return _actionContainerView;
}

- (UIView *)textFieldContainerView {

    if (!_textFieldContainerView) {
        _textFieldContainerView = [[UIView alloc] init];
    }

    return _textFieldContainerView;
}

@end


text:
package com.googlecode.charts4j;

import com.googlecode.charts4j.collect.ImmutableList;
import com.googlecode.charts4j.collect.Lists;
import com.googlecode.charts4j.parameters.ChartType;

/**
 * Pie chart constructed with the {@link GCharts} static factory class.
 *
 * If the number of colors specified in the {@link Slice} objects is less than
 * the number of slices, then colors are interpolated. If no colors are
 * specified, pie segment colors are interpolated from dark orange to pale
 * yellow. If slices do not add up to 100, slices will be proportional to the
 * total of all slices.
 *
 * @author Julien Chastang (julien.c.chastang at gmail dot com)
 *
 * @see Slice
 * @see GCharts
 */
public class PieChart extends AbstractGraphChart {

    /** Is this a 3D pie chart. */
    private boolean                    threeD = false;

    /** An immutable list of slices for this pie.  */
    private final ImmutableList<Slice> slices;

    /** The pie chart orientation radians.  */
    private double orientation = Double.NaN;

    /**
     * Set the pie chart orientation in radians. Positive values will rotate the
     * chart clockwise.
     *
     * @param radians
     *            the orientation to set in radians
     */
    public void setOrientation(final double radians) {
        this.orientation = radians;
    }

    /**
     * Create a pie chart with the given slices. If slices do not add up to 100,
     * slices will be proportional to the total of all slices.
     *
     * @param slices
     *            list of data slices of the pie chart.
     *
     * @see Slice
     */
    PieChart(final ImmutableList<? extends Slice> slices) {
        super();
        this.slices = Lists.copyOf(slices);
    }

    /**
     * Is this a 3D chart.
     *
     * @return the threeD
     */
    public final boolean isThreeD() {
        return threeD;
    }

    /**
     * If you want the chart to be 3D, set to true.
     *
     * @param threeD
     *            boolean to determine if pie chart is rendered in 3D.
     */
    public final void setThreeD(final boolean threeD) {
        this.threeD = threeD;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void prepareData() {
        super.prepareData();
        final double[] d = new double[slices.size()];
        int i = 0;
        boolean hasLegend = false;
        double sum = 0;
        for (Slice slice : slices) {
            if (slice.getLegend() != null ){
                hasLegend |= true;
            }
            sum += slice.getPercentage();
        }

        for (Slice slice : slices) {
            d[i++] = (slice.getPercentage()/sum)*100;
            parameterManager.addPieChartAndGoogleOMeterLegend(slice.getLabel() != null ? slice.getLabel() : "");
            if (hasLegend)
                parameterManager.addLegend(slice.getLegend() != null ? slice.getLegend() : "");
            if (slice.getColor() != null) {
                parameterManager.addColor(slice.getColor());
            }
        }
        if (!Double.isNaN(orientation)) {
            parameterManager.addPieChartOrientation(orientation);
        }
        parameterManager.addData(Data.newData(d));
        parameterManager.setChartTypeParameter(threeD ? ChartType.THREE_D_PIE_CHART : ChartType.PIE_CHART);
    }
}

redpajama_set_name: RedPajamaGithub


text:
<?php

namespace Styleguide\Pages;

use Factories\Page as PageFactory;

class PromoGrid extends Page
{
    /**
     * {@inheritdoc}
     */
    public function getPageData()
    {
        return app(PageFactory::class)->create(1, true, [
            'page' => [
                'controller' => 'PromoListingController',
                'title' => 'Promo grid',
                'id' => 101110200,
                'content' => [
                    'main' => '

Page setup

Custom page field required grid_promo_group_id.

Enable individual item view custom page field promotion_view_boolean.

If using individual view, you need to create a CMS page titled "Promo view", with the url "view".

Promo group setup

Title

Link: optional, if not using individual view

Excerpt: optional, displays underneath title

Description: optional, displays underneath excerpt

Filename: optional, image can be any size as long as it\'s consistent

                    ',
                ],
            ],
            'data' => [
                'grid_promo_group_id' => 12345,
            ],
        ]);
    }
}


text:
module Middleman
  module Imageoptim
    class Manifest
      MANIFEST_FILENAME = 'imageoptim.manifest.yml'.freeze

      attr_reader :app

      def initialize(app)
        @app = app
      end

      def path
        File.join(build_dir, MANIFEST_FILENAME)
      end

      def build_dir
        if Gem::Version.new(Middleman::VERSION) >= Gem::Version.new('4.0.0')
          app.config[:build_dir]
        else
          app.build_dir
        end
      end

      def build_and_write(new_resources)
        write(dump(build(new_resources)))
      end

      def resource(key)
        resources[key.to_s]
      end

      private

      def resources
        @resources ||= load(path)
      end

      def dump(source)
        YAML.dump(source)
      end

      def load(path)
        YAML.load(File.read(path))
      end

      def build(resources)
        resources.inject({}) do |new_manifest, resource|
          new_manifest[resource.to_s] = File.mtime(resource)
          new_manifest
        end
      end

      def write(manifest)
        File.open(path, 'w') do |manifest_file|
          manifest_file.write(manifest)
        end
      end
    end
  end
end


text:
## [Planned] - Planned as: [3.1.0]
### Change

- Remove Sprockets 3.x support.
- Rewrite `{% asset srcset %}` so it takes raw proxy args.
- Remove support for Ruby < 2.4

## [Unreleased] - Planned as: [3.0.9]
### Added
- `magick:transparency`
- Add the ability to change formats w/ srcset.
- Allow raw compiles to
- Add default ImgOptim profile.
- `magick:background`

### Fixed
- Make sure `@optim` worked, and `optim=profile` works.
- Make ImageMagick slightly faster using `new` w/ combine_options w/ format.
- Make sure that multiple proxy calls return the right path.
- Make sure not to output Proxy keys into HTML.

## [3.0.8] - 2018-3-10
### Added
- Add support for adding Clojure style `/* @alternate */`
- `:jekyll_assets_sassc` compressor.
- `:jekyll_assets_uglify` compressor.
- `:jekyll_assets_scss` compressor.

### Hooks
- Added `asset` -> `after_compression`
  This is useful for when you wish to implement things after compressing,
  but before writing, or any other kind of pre-write transformations that might
  happen within Sprockets.

### Fixed
- Made sure to only enable Uglify.js when JavaScript is available.

### Changes
- Revamped SourceMap integrations.
- Improved Utils.javascript? to return a boolean.
- Made AutoPrefixer load early, because it breaks a lot of stuff if not.
- Improved Utils.activate to return a boolean.
- Moved SourceMaps to the Plugin folder.

### API Changes
- `SprocketsExportersFileExporterPatches` -> `SprocketsWriterPatches`
- Moved `Env.old_sprockets?`, and `Env.old?` to `Utils.old_sprockets?`
- [Alpha Feature]: Moved SourceMaps to the Plugin folder.

## [3.0.7] - 2018-1-29
### Added

- Added a link to the migration guide.
- Make sure our defaults run first, so they never override plugin defaults.
- Add support for SASSC compression.  This speeds us up a bit.
- Added total time taken to do work as a final log.

#### Hooks
- Added `asset` -> `before_read`
- Added `asset` -> `before_write`
- Added `asset` -> `after_write`
- Added `asset` -> `after_read`

### Changes

- Allow `+` in Content-Types.
- Fix hook, where assets wouldn't generate.
- Fixed a bug with loopy Proxies, thanks @benben
- Refactored the way we handle `env` -> `after_write`. Now with 100% more asset.
- Moved `Utils.with_timed_logging` to `Logger.with_timed_logging`
- Refactored `Logger` to give it far less complexity.
- Encapsulate and handle errors more cleanly.
- Fixed a bug with discovering SVG images.
- Start colorizing the log.

## [3.0.5, 3.0.6] - 2017-12-05
### Fixed

- Make sure we remove non-digested assets, so we can write them again.  We
  will subscribe to the always write method of handling non-digesting so that
  we don't run into any problems when working with non-digested assets.

## [3.0.4] - 2017-12-05
### Added

- `env` -> `before_write`, hook.

### Changed

- Use Regexp's for our HTML builders.
- Optimize our writes, speeding up our system slightly.  The reason this is
  slightly faster is because of the way Sprockets handles writing, if we do
  it all at once, it's much faster than doing it one at a time.

### Fixed

- Don't output a path when doing `@inline`

## [3.0.3] - 2017-11-29
### Added

- Allow lowercase DOCTYPE. #455
- Prevent network connections on XML.
- Add support for non-digest assets again (*sponsored-by* @anomaly) #458
- Show how to use WebComponents.

### Fixed

- Make sure loops aren't broken. #449
- Make sure we exclude some of our directories. #456.
- Only search for `<img>` inside of `.html`, `.md`
- Make proxies deterministic. #451
- Prevent Entity Decoding.

## [3.0.2] - 2017-11-27
### Fixed

- Added support for Favicon #448
- Enforce minimum Ruby version so people don't try to use older versions
  of Ruby even though we note the minimum version inside of the README.

## [3.0.1] - 2017-11-21
### Added

- `jekyll-assets.rb`

## [3.0.0] - 2017-11-21
### Changed

- Rewrite for Sprockets 4.x
- Rewrite Proxies so they are cleaner, and faster/cached.
- Rewrite the Hook System.

### Added

- Sprockets 4.x support.
- SourceMaps for SASS, JavaScript. (*sponsored-by* @cameronmcefee)
- HTML Builder Defaults
- HTML Builders


text:
namespace autofill {

TestAutofillClient::TestAutofillClient(
    std::unique_ptr<TestPersonalDataManager> pdm)
    : test_personal_data_manager_(
          pdm ? std::move(pdm) : std::make_unique<TestPersonalDataManager>()),
      form_origin_(GURL("https://example.test")),
      last_committed_url_(GURL("https://example.test")),
      log_manager_(LogManager::Create(&log_router_, base::NullCallback())) {
  mock_iban_manager_ = std::make_unique<testing::NiceMock<MockIBANManager>>(
      test_personal_data_manager_.get());
  base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
  if (command_line->HasSwitch("show-autofill-internals"))
    scoped_logging_subscription_.Observe(&log_router_);
}

TestAutofillClient::~TestAutofillClient() = default;

version_info::Channel TestAutofillClient::GetChannel() const {
  return channel_for_testing_;
}

TestPersonalDataManager* TestAutofillClient::GetPersonalDataManager() {
  return test_personal_data_manager_.get();
}

AutocompleteHistoryManager*
TestAutofillClient::GetAutocompleteHistoryManager() {
  return &mock_autocomplete_history_manager_;
}

IBANManager* TestAutofillClient::GetIBANManager() {
  return mock_iban_manager_.get();
}

MerchantPromoCodeManager* TestAutofillClient::GetMerchantPromoCodeManager() {
  return &mock_merchant_promo_code_manager_;
}

CreditCardCVCAuthenticator* TestAutofillClient::GetCVCAuthenticator() {
  if (!cvc_authenticator_)
    cvc_authenticator_ = std::make_unique<CreditCardCVCAuthenticator>(this);
  return cvc_authenticator_.get();
}

CreditCardOtpAuthenticator* TestAutofillClient::GetOtpAuthenticator() {
  if (!otp_authenticator_)
    otp_authenticator_ = std::make_unique<CreditCardOtpAuthenticator>(this);
  return otp_authenticator_.get();
}

PrefService* TestAutofillClient::GetPrefs() {
  return const_cast<PrefService*>(base::as_const(*this).GetPrefs());
}

const PrefService* TestAutofillClient::GetPrefs() const {
  return prefs_.get();
}

syncer::SyncService* TestAutofillClient::GetSyncService() {
  return test_sync_service_;
}

signin::IdentityManager* TestAutofillClient::GetIdentityManager() {
  return identity_test_env_.identity_manager();
}

FormDataImporter* TestAutofillClient::GetFormDataImporter() {
  return form_data_importer_.get();
}

payments::PaymentsClient* TestAutofillClient::GetPaymentsClient() {
  return payments_client_.get();
}

StrikeDatabase* TestAutofillClient::GetStrikeDatabase() {
  return test_strike_database_.get();
}

ukm::UkmRecorder* TestAutofillClient::GetUkmRecorder() {
  return &test_ukm_recorder_;
}

ukm::SourceId TestAutofillClient::GetUkmSourceId() {
  if (source_id_ == -1) {
    source_id_ = ukm::UkmRecorder::GetNewSourceID();
    test_ukm_recorder_.UpdateSourceURL(source_id_, form_origin_);
  }
  return source_id_;
}

AddressNormalizer* TestAutofillClient::GetAddressNormalizer() {
  return &test_address_normalizer_;
}

AutofillOfferManager* TestAutofillClient::GetAutofillOfferManager() {
  return autofill_offer_manager_.get();
}

const GURL& TestAutofillClient::GetLastCommittedURL() const {
  return last_committed_url_;
}

security_state::SecurityLevel
TestAutofillClient::GetSecurityLevelForUmaHistograms() {
  return security_level_;
}

translate::LanguageState* TestAutofillClient::GetLanguageState() {
  return &mock_translate_driver_.GetLanguageState();
}

translate::TranslateDriver* TestAutofillClient::GetTranslateDriver() {
  return &mock_translate_driver_;
}

std::string TestAutofillClient::GetVariationConfigCountryCode() const {
  return variation_config_country_code_;
}

#if !BUILDFLAG(IS_IOS)
std::unique_ptr<webauthn::InternalAuthenticator>
TestAutofillClient::CreateCreditCardInternalAuthenticator(
    AutofillDriver* driver) {
  return std::make_unique<TestInternalAuthenticator>();
}
#endif

void TestAutofillClient::ShowAutofillSettings(bool show_credit_card_settings) {}

void TestAutofillClient::ShowUnmaskPrompt(
    const CreditCard& card,
    UnmaskCardReason reason,
    base::WeakPtr<CardUnmaskDelegate> delegate) {}

void TestAutofillClient::OnUnmaskVerificationResult(PaymentsRpcResult result) {}

VirtualCardEnrollmentManager*
TestAutofillClient::GetVirtualCardEnrollmentManager() {
  return form_data_importer_->GetVirtualCardEnrollmentManager();
}

void TestAutofillClient::ShowVirtualCardEnrollDialog(
    const VirtualCardEnrollmentFields& virtual_card_enrollment_fields,
    base::OnceClosure accept_virtual_card_callback,
    base::OnceClosure decline_virtual_card_callback) {}

#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
std::vector<std::string>
TestAutofillClient::GetAllowedMerchantsForVirtualCards() {
  return allowed_merchants_;
}

std::vector<std::string>
TestAutofillClient::GetAllowedBinRangesForVirtualCards() {
  return allowed_bin_ranges_;
}

void TestAutofillClient::ShowLocalCardMigrationDialog(
    base::OnceClosure show_migration_dialog_closure) {
  std::move(show_migration_dialog_closure).Run();
}

void TestAutofillClient::ConfirmMigrateLocalCardToCloud(
    const LegalMessageLines& legal_message_lines,
    const std::string& user_email,
    const std::vector<MigratableCreditCard>& migratable_credit_cards,
    LocalCardMigrationCallback start_migrating_cards_callback) {
  // If |migration_card_selection_| hasn't been preset by tests, default to
  // selecting all migratable cards.
  if (migration_card_selection_.empty()) {
    for (MigratableCreditCard card : migratable_credit_cards)
      migration_card_selection_.push_back(card.credit_card().guid());
  }
  std::move(start_migrating_cards_callback).Run(migration_card_selection_);
}

void TestAutofillClient::ShowLocalCardMigrationResults(
    const bool has_server_error,
    const std::u16string& tip_message,
    const std::vector<MigratableCreditCard>& migratable_credit_cards,
    MigrationDeleteCardCallback delete_local_card_callback) {}
void TestAutofillClient::ShowWebauthnOfferDialog(
    WebauthnDialogCallback offer_dialog_callback) {}

void TestAutofillClient::ShowWebauthnVerifyPendingDialog(
    WebauthnDialogCallback verify_pending_dialog_callback) {}

void TestAutofillClient::UpdateWebauthnOfferDialogWithError() {}

bool TestAutofillClient::CloseWebauthnDialog() {
  return true;
}

void TestAutofillClient::ConfirmSaveUpiIdLocally(
    const std::string& upi_id,
    base::OnceCallback<void(bool accept)> callback) {}

void TestAutofillClient::OfferVirtualCardOptions(
    const std::vector<CreditCard*>& candidates,
    base::OnceCallback<void(const std::string&)> callback) {}

#else  // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS)
void TestAutofillClient::ConfirmAccountNameFixFlow(
    base::OnceCallback<void(const std::u16string&)> callback) {
  credit_card_name_fix_flow_bubble_was_shown_ = true;
  std::move(callback).Run(std::u16string(u"Gaia Name"));
}

void TestAutofillClient::ConfirmExpirationDateFixFlow(
    const CreditCard& card,
    base::OnceCallback<void(const std::u16string&, const std::u16string&)>
        callback) {
  credit_card_name_fix_flow_bubble_was_shown_ = true;
  std::move(callback).Run(
      std::u16string(u"03"),
      std::u16string(base::ASCIIToUTF16(test::NextYear().c_str())));
}
#endif

void TestAutofillClient::ConfirmSaveCreditCardLocally(
    const CreditCard& card,
    SaveCreditCardOptions options,
    LocalSaveCardPromptCallback callback) {
  confirm_save_credit_card_locally_called_ = true;
  offer_to_save_credit_card_bubble_was_shown_ = options.show_prompt;
  save_credit_card_options_ = options;
  std::move(callback).Run(AutofillClient::SaveCardOfferUserDecision::kAccepted);
}

void TestAutofillClient::ConfirmSaveCreditCardToCloud(
    const CreditCard& card,
    const LegalMessageLines& legal_message_lines,
    SaveCreditCardOptions options,
    UploadSaveCardPromptCallback callback) {
  offer_to_save_credit_card_bubble_was_shown_ = options.show_prompt;
  save_credit_card_options_ = options;
  std::move(callback).Run(AutofillClient::SaveCardOfferUserDecision::kAccepted,
                          {});
}

void TestAutofillClient::CreditCardUploadCompleted(bool card_saved) {}

void TestAutofillClient::ConfirmCreditCardFillAssist(
    const CreditCard& card,
    base::OnceClosure callback) {
  std::move(callback).Run();
}

void TestAutofillClient::ConfirmSaveAddressProfile(
    const AutofillProfile& profile,
    const AutofillProfile* original_profile,
    SaveAddressProfilePromptOptions options,
    AddressProfileSavePromptCallback callback) {}

bool TestAutofillClient::HasCreditCardScanFeature() {
  return false;
}

void TestAutofillClient::ScanCreditCard(CreditCardScanCallback callback) {}

bool TestAutofillClient::IsFastCheckoutSupported() {
  return false;
}

bool TestAutofillClient::IsFastCheckoutTriggerForm(const FormData& form,
                                                   const FormFieldData& field) {
  return false;
}

bool TestAutofillClient::ShowFastCheckout(
    base::WeakPtr<FastCheckoutDelegate> delegate) {
  return false;
}

void TestAutofillClient::HideFastCheckout() {}

bool TestAutofillClient::IsTouchToFillCreditCardSupported() {
  return false;
}

bool TestAutofillClient::ShowTouchToFillCreditCard(
    base::WeakPtr<TouchToFillDelegate> delegate) {
  return false;
}

void TestAutofillClient::HideTouchToFillCreditCard() {}

void TestAutofillClient::ShowAutofillPopup(
    const AutofillClient::PopupOpenArgs& open_args,
    base::WeakPtr<AutofillPopupDelegate> delegate) {}

void TestAutofillClient::UpdateAutofillPopupDataListValues(
    const std::vector<std::u16string>& values,
    const std::vector<std::u16string>& labels) {}

base::span<const Suggestion> TestAutofillClient::GetPopupSuggestions() const {
  return base::span<const Suggestion>();
}

void TestAutofillClient::PinPopupView() {}

AutofillClient::PopupOpenArgs TestAutofillClient::GetReopenPopupArgs() const {
  return {};
}

void TestAutofillClient::UpdatePopup(const std::vector<Suggestion>& suggestions,
                                     PopupType popup_type) {}

void TestAutofillClient::HideAutofillPopup(PopupHidingReason reason) {}

void TestAutofillClient::ShowVirtualCardErrorDialog(
    const AutofillErrorDialogContext& context) {
  virtual_card_error_dialog_shown_ = true;
  autofill_error_dialog_context_ = context;
}

bool TestAutofillClient::IsAutocompleteEnabled() {
  return true;
}

bool TestAutofillClient::IsPasswordManagerEnabled() {
  return true;
}

void TestAutofillClient::PropagateAutofillPredictions(
    AutofillDriver* driver,
    const std::vector<FormStructure*>& forms) {}

void TestAutofillClient::DidFillOrPreviewField(
    const std::u16string& autofilled_value,
    const std::u16string& profile_full_name) {}

bool TestAutofillClient::IsContextSecure() const {
  // Simplified secure context check for tests.
  return form_origin_.SchemeIs("https");
}

bool TestAutofillClient::ShouldShowSigninPromo() {
  return false;
}

bool TestAutofillClient::AreServerCardsSupported() const {
  return true;
}

void TestAutofillClient::ExecuteCommand(int id) {}

void TestAutofillClient::OpenPromoCodeOfferDetailsURL(const GURL& url) {}

LogManager* TestAutofillClient::GetLogManager() const {
  return log_manager_.get();
}

void TestAutofillClient::LoadRiskData(
    base::OnceCallback<void(const std::string&)> callback) {
  std::move(callback).Run("some risk data");
}

#if BUILDFLAG(IS_IOS)
bool TestAutofillClient::IsQueryIDRelevant(int query_id) {
  return true;
}
#endif

void TestAutofillClient::InitializeUKMSources() {
  test_ukm_recorder_.UpdateSourceURL(source_id_, form_origin_);
}

void TestAutofillClient::set_form_origin(const GURL& url) {
  form_origin_ = url;
  // Also reset source_id_.
  source_id_ = ukm::UkmRecorder::GetNewSourceID();
  test_ukm_recorder_.UpdateSourceURL(source_id_, form_origin_);
}

void TestAutofillClient::set_last_committed_url(const GURL& url) {
  last_committed_url_ = url;
}

ukm::TestUkmRecorder* TestAutofillClient::GetTestUkmRecorder() {
  return &test_ukm_recorder_;
}

}  // namespace autofill


text:
<?php

namespace Pixeloid\AppBundle\Admin;

use Sonata\AdminBundle\Admin\Admin;
use Sonata\AdminBundle\Datagrid\DatagridMapper;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Show\ShowMapper;

class DiningAdmin extends Admin
{
    /**
     * @param DatagridMapper $datagridMapper
     */
    protected function configureDatagridFilters(DatagridMapper $datagridMapper)
    {
        $datagridMapper
            ->add('id')
            ->add('price')
        ;
    }

    /**
     * @param ListMapper $listMapper
     */
    protected function configureListFields(ListMapper $listMapper)
    {
        $listMapper
            ->add('id')
            ->add('price')

            ->add('_action', 'actions', array(
                'actions' => array(
                    'show' => array(),
                    'edit' => array(),
                    'delete' => array(),
                )
            ))
        ;
    }

    /**
     * @param FormMapper $formMapper
     */
    protected function configureFormFields(FormMapper $formMapper)
    {
        $formMapper
         ->add('diningType', null)
         ->add('diningDates', \Sonata\CoreBundle\Form\Type\CollectionType::class, array('by_reference' => false),
                            array(
                                   'edit' => 'inline',
                                   'sortable' => 'position',
                                   'inline' => 'table',
                              ))

            ->add('price')
            ->add('hidden')
        ;
    }

    /**
     * @param ShowMapper $showMapper
     */
    protected function configureShowFields(ShowMapper $showMapper)
    {
        $showMapper
            ->add('id')
            ->add('price')
        ;
    }
}


text:
const investmentData = require('../../../../../test/unit/data/investment/investment-data.json')

const {
  transformProjectManagementForView,
  transformClientRelationshipManagementForView,
  transformTeamMembersForView,
} = require('../team')

describe('Investment project transformers', () => {
  describe('#transformProjectManagementForView', () => {
    it('should return null if there is no project manager or assurance adviser', () => {
      const data = Object.assign({}, investmentData)
      data.project_manager = null
      data.project_assurance_adviser = null

      const projectManagementData = transformProjectManagementForView(data)
      expect(projectManagementData).to.deep.equal(null)
    })

    it('should return formatted data for the project manager and assurance adviser if there are both', () => {
      const data = Object.assign({}, investmentData)
      const expectedProjectManagementData = [
        {
          role: 'Project Assurance Adviser',
          adviser: 'John Brown',
          team: 'Team B',
        },
        {
          role: 'Project Manager',
          adviser: 'Fred Smith',
          team: 'Team A',
        },
      ]

      const projectManagementData = transformProjectManagementForView(data)
      expect(projectManagementData).to.deep.equal(expectedProjectManagementData)
    })

    it('should return formatted data for project manager, and todo for assurance officer if no assurance officer', () => {
      const data = Object.assign({}, investmentData)
      data.project_assurance_adviser = null
      data.project_assurance_team = null

      const expectedProjectManagementData = [
        {
          role: 'Project Assurance Adviser',
          adviser: 'To do',
          team: null,
        },
        {
          role: 'Project Manager',
          adviser: 'Fred Smith',
          team: 'Team A',
        },
      ]

      const projectManagementData = transformProjectManagementForView(data)
      expect(projectManagementData).to.deep.equal(expectedProjectManagementData)
    })

    it('should return formatted data for assurance adviser and todo for project manager is there is no project manager', () => {
      const data = Object.assign({}, investmentData)
      data.project_manager = null
      data.project_manager_team = null

      const expectedProjectManagementData = [
        {
          role: 'Project Assurance Adviser',
          adviser: 'John Brown',
          team: 'Team B',
        },
        {
          role: 'Project Manager',
          adviser: 'To do',
          team: null,
        },
      ]

      const projectManagementData = transformProjectManagementForView(data)
      expect(projectManagementData).to.deep.equal(expectedProjectManagementData)
    })
  })

  describe('#transformClientRelationshipManagementForView', () => {
    it('should return just the client relationship manager details if there is no account manager', () => {
      const data = {
        client_relationship_manager: {
          id: '123',
          first_name: 'Fred',
          last_name: 'Smith',
          dit_team: {
            id: '3321',
            name: 'Team Fred',
          },
        },
        investor_company: {},
      }

      const expectedResult = [
        {
          adviser: 'Fred Smith',
          role: 'Client Relationship Manager',
          team: 'Team Fred',
        },
      ]

      const actualResult = transformClientRelationshipManagementForView(data)
      expect(actualResult).to.deep.equal(expectedResult)
    })

    it('should return account manager details if there is an account manager also', () => {
      const data = {
        client_relationship_manager: {
          id: '123',
          first_name: 'Fred',
          last_name: 'Smith',
          dit_team: {
            id: '3321',
            name: 'Team Fred',
          },
        },
        investor_company: {
          one_list_group_global_account_manager: {
            id: '321',
            first_name: 'John',
            last_name: 'Brown',
            dit_team: {
              name: 'Johns Team',
            },
          },
        },
      }

      const expectedResult = [
        {
          adviser: 'Fred Smith',
          role: 'Client Relationship Manager',
          team: 'Team Fred',
        },
        {
          adviser: 'John Brown',
          role: 'Global Account Manager',
          team: 'Johns Team',
        },
      ]

      const actualResult = transformClientRelationshipManagementForView(data)
      expect(actualResult).to.deep.equal(expectedResult)
    })
  })

  describe('#transformTeamMembersForView', () => {
    it('should return a formatted version of team member data', () => {
      const teamMembers = [
        {
          adviser: {
            id: '1234',
            first_name: 'Fred',
            last_name: 'Smith',
            name: 'Fred Smith',
            dit_team: {
              id: '444',
              name: 'Freds Team',
            },
          },
          role: 'Director',
        },
      ]

      const expected = [
        {
          adviser: 'Fred Smith',
          team: 'Freds Team',
          role: 'Director',
        },
      ]

      const actual = teamMembers.map(transformTeamMembersForView)
      expect(actual).to.deep.equal(expected)
    })
  })
})


text:
<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Migrate extends CI_Controller
{
	function install()
	{
		$this->load->library('migration');

		if ($this->migration->current() === FALSE)
		{
			show_error($this->migration->error_string());
		}
		else
		{
			echo '
Successfully install schema database '.$this->config->item('web_name').'

				  This App Version : '.$this->migration->current().'

First Account

Username: '.get_current_user().'

Password: '.get_current_user().'

				  ';
		}
	}
}


text:
layout: page
title: CV
permalink: /cv/
comments: false
author_footer: false
---

[Download as PDF](https://bitbucket.org/asholokhov/cv/downloads/CV.pdf)

## Contacts

*e-mail: moc.liamg@aa.vohkolohs*

*skype: 12991detnawtsom*

---

## Education
*September 2010 - July 2015*

[The Bonch-Bruevich State University of Telecommunications](http://www.sut.ru)

Graduated with excellence. [Graduate work (RU).](https://bitbucket.org/asholokhov/cv/downloads/diploma.pdf)

---

## Career History
***Sr. Software Engineer** at [DINO System](http://www.dins.ru/), October 2016 - Present*

- Working on **Data Aggregation Hub** project
- Design and development real time **Quality of Service**, **Live reports** and **Historical reports** solutions
- Microservices architecture, event sourcing, CQRS principles, streaming processing
- Functional programming in Scala with Typelevel stack (cats, cats-effects, fs2, doobie, circe, monocle)
- Taking part in UI development with Angular 5
- *Languages: Scala, Java, Typescript*
- *Tools: Typelevel, Akka, SBT, GRPC, Docker, Kubernetes, Kafka, Prometheus, Gitlab CI*

***Software Engineer** at [NetCracker](https://www.netcracker.com/), November 2015 - October 2016*

- Design and development internal streaming platform based on Apache Kafka
- Design and development of full text search component based on ElasticSearch with concurrent index building
- Microservices architecture (Docker containers, OpenShift deployment)
- Developing and supporting high availability platform components
- DevOps (CI/CD, improve deploy and QA processes)
- *Languages: Java, Bash scripts*
- *Tools: Maven, Docker, ElasticSearch, Kafka, Jenkins*

***Software Engineer** at [Seventest R&D Centre](http://seventest.ru/), November 2012 - November 2015*

- Developing and performance boosting of billing core for interconnect traffic
- Implementing service monitoring, revenue assurance and network testing solutions
- Complex web frontend for [PROFIT Revenue Assurance](http://seventest.ru/products/profit/) platform and SQM system
- Adding new features and bug fixes for fraud management solutions
- *Languages: C++, PHP, Bash scripts*
- *Tools: Web stack (HTML/CSS/JS/AJAX), Linux servers (Debian), CORBA, Qt, MySQL, PostgreSQL, Memcache*

***Lab Assistant** at [The Bonch-Bruevich SUT](http://www.sut.ru), January 2012 - July 2015*

- Developing internal [judge system](http://orange.spbgut.ru/) for the programming contests (like ACM ICPC)
- Teaching course of Algorithms and Data Structures
- Teaching course of Object Oriented Programming
- Software and internal network support

---

## Technical Skills

### Backend
- Scala, Java 8, C++
- Node.js, PHP
- Common design patterns, Concurrency
- Streaming processing, Event sourcing, CQRS, MVC, REST

### Frontend
- HTML, CSS, LESS, SASS, AJAX, WS
- JavaScript (ES6, Angular 5)
- Single Page Applications

### Storage
- MySQL, PostgreSQL, MongoDB, Oracle basics
- Memcache, Redis, ElasticSearch
- Kafka, ActiveMQ

### Others
- Unix-based operating systems
- Git, SVN
- Extended Algorithms and Data Structures
- Network protocols, TCP/IP stack, OSI model

### Languages
- Russian (native)
- English (upper intermediate)

---

## Personal qualities
*Teamwork skills, flexibility, discipline, willingness to learn and work,
interested in high load systems, multiplayer game developmen, fascinating about
new technologies and programming languages.*

---

## Honors and Activities
- **ACM ICPC**, NEERC Semifinal in 2013
- **ACM ICPC**, NEERC Quarter-final in 2011, 2012, 2013
- **KPI-Open contests**, Kiev in 2012, 2013
- **Programming contests**, Codeforces, university trainings since 2011
- **Figure Skater**, Master of Sport since 2008

---

## Personal projects

### Repin (2016)
- small and simple paste bin tool with CLI
- *Tools: Golang, REST API, nginx*

### Electronic diary (2016)
- Personal accounts for parents, teachers and administrators
- Notifications, direct messages
- Diary with marks, home works and lessons themes
- Different statistics
- *Tools: Java (Spring, Maven, MySQL, REST API), Dojo Toolkit*

### Crossword Builder (2013)
- Generating crosswords from random dictionaries
- Share crosswords with friends and store in personal account
- Ability to export crossword in PDF format
- *Tools: HTML/CSS/JS, PHP, MySQL*

### Test System for students (2010)
- Introduced in School 28 in Kirov city
- Test constructor with different types of questions for Unified State Exam
- Supported question types: simple, accordance, variants, crosswords
- Simple statistics, two modes: teacher and student
- *Tools: Delphi 7, MySQL*

[Read more details about my projects.](/projects)


text:
package org.unix4j.io;

import org.unix4j.line.Line;
import org.unix4j.processor.LineProcessor;

/**
 * Represents a line-by-line output device. This interface does not add any
 * functionality but refines the documentation for the generally defined methods
 * from {@link LineProcessor}.
 */
public interface Output extends LineProcessor {
	/**
	 * Writes a line to the output.
	 *
	 * @param line
	 *            the line to write to the output.
	 *
	 * @return true if this {@code Output} device is ready to process more
	 *         lines, and false otherwise; output devices usually return true
	 */
	@Override
	boolean processLine(Line line);

	/**
	 * Indicates that all output has been written. Usually triggers a flush
	 * operation or closes the underlying reader or stream.
	 */
	@Override
	void finish();
}


text:
<?php

App::uses('Controller', 'Controller');

/**
 * Application Controller
 *
 * Add your application-wide methods in the class below, your controllers
 * will inherit them.
 *
 * @package		app.Controller
 * @link		http://book.cakephp.org/2.0/en/controllers.html#the-app-controller
 */
class AppController extends Controller {

    public $helpers = array(
        'Session',
        'Html' => array('className' => 'BoostCake.BoostCakeHtml'),
        'Form' => array('className' => 'BoostCake.BoostCakeForm'),
        'Paginator' => array('className' => 'BoostCake.BoostCakePaginator'),
    );

	public $components = array(
        'DebugKit.Toolbar',
        'Session',
        'Auth' => array(
			'flash' => array(
				'element' => 'alert',
				'key' => 'auth',
				'params' => array(
					'plugin' => 'BoostCake',
					'class' => 'alert-error'
				)
			),
            'loginAction' => array(
                'controller' => 'users',
                'action' => 'login',
            ),
            'authError' => "Your username and password is incorrect, please try again.",
            'redirect' => array("controller" => "users", "action" => "profile"),
            'loginRedirect' => array(
                'controller' => 'users',
                'action' => 'index'
            ),
            'logoutRedirect' => array(
                'controller' => 'users',
                'action' => 'login'
            ),
            'authenticate' => array(
                'Form' => array(
                    'passwordHasher' => 'Blowfish',
                )
            ),
            'authorize' => array('Controller')
        )
    );

    public function beforeFilter() {
        // assign admin layout for admin users
        if ((isset($this->params['prefix']) && ($this->params['prefix'] == 'admin'))) {
            $this->layout = 'admin';
        }

        $this->Auth->allow('index', 'view');
        $this->set('loggedIn', $this->Auth->loggedIn());
        $this->set('role', $this->Auth->user('role'));
        $this->set('userId', $this->Auth->user('id'));
    }

    public function isAuthorized($user) {
        // Admin can access every action
        if (isset($user['role']) && $user['role'] === 'admin') {
            return true;
        }

        // Default deny
        return false;
    }
}